I think read will now read integers and symbols, but it's untested.

Everything compiles.
This commit is contained in:
Simon Brooke 2026-04-01 16:06:16 +01:00
parent cc8e96eda4
commit 9eb0d3c5a0
28 changed files with 594 additions and 293 deletions

View file

@ -29,24 +29,35 @@ struct pso_pointer make_pointer( uint32_t node, uint16_t page,
/**
* @brief returns the in-memory address of the object indicated by this
* pointer. TODO: Yhe reason I'm doing it this way is because I'm not
* pointer `p`.
*
* NOTE THAT: It's impossible, with our calling conventions, to pass an
* exception back from this function. Consequently, if anything goes wrong
* we return NULL. The caller *should* check for that and throw an exception.
*
* NOTE THAT: The return signature of these functions is pso2, because it is
* safe to cast any paged space object to a pso2, but safe to cast an object
* of a smaller size class to a larger one. If you know what size class you
* want, you should prefer `pointer_to_object_of_size_class()`, q.v.
*
* TODO: The reason I'm doing it this way is because I'm not
* certain reference counter updates work right it we work with 'the object'
* rather than 'the address of the object'. I really ought to have a
* conversation with someone who understands this bloody language.
*
* @param pointer a pso_pointer which references an object.
* @return struct pso2* the actual address in memory of that object.
* @param p a pso_pointer which references an object.
*
* @return the actual address in memory of that object, or NULL if `p` is
* invalid.
*/
struct pso2 *pointer_to_object( struct pso_pointer pointer ) {
struct pso2 *pointer_to_object( struct pso_pointer p ) {
struct pso2 *result = NULL;
if ( pointer.node == node_index ) {
if (pointer.page < get_pages_allocated() && pointer.offset < (PAGE_BYTES / 8)) {
if ( p.node == node_index ) {
if (p.page < get_pages_allocated() && p.offset < (PAGE_BYTES / 8)) {
// TODO: that's not really a safe test of whether this is a valid pointer.
union page *pg = pages[pointer.page];
result = ( struct pso2 * ) &pg->words[pointer.offset];
} else {
// TODO: throw bad pointer exception.
union page *pg = pages[p.page];
result = ( struct pso2 * ) &pg->words[p.offset];
}
}
// TODO: else if we have a copy of the object in cache, return that;
@ -54,3 +65,51 @@ struct pso2 *pointer_to_object( struct pso_pointer pointer ) {
return result;
}
/**
* @brief returns the memory address of the object indicated by this pointer
* `p`, if it is of this `size_class`.
*
* NOTE THAT: It's impossible, with our calling conventions, to pass an
* exception back from this function. Consequently, if anything goes wrong
* we return NULL. The caller *should* check for that and throw an exception.
*
* NOTE THAT: The return signature of these functions is pso2, because it is
* safe to cast any paged space object to a pso2, but safe to cast an object
* of a smaller size class to a larger one. You should check that the object
* returned has the size class you expect.
*
* @param p a pointer to an object;
* @param size_class a size class.
*
* @return the memory address of the object, provided it is a valid object and
* of the specified size class, else NULL.
*/
struct pso2 * pointer_to_object_of_size_class( struct pso_pointer p, uint8_t size_class) {
struct pso2 * result = pointer_to_object( p);
if (result->header.tag.bytes.size_class != size_class) {
result = NULL;
}
return result;
}
/**
* @brief returns the memory address of the object indicated by this pointer
* `p`, if it has this `tag_value`.
*
* NOTE THAT: It's impossible, with our calling conventions, to pass an
* exception back from this function. Consequently, if anything goes wrong
* we return NULL. The caller *should* check for that and throw an exception.
*/
struct pso2 * pointer_to_object_with_tag_value( struct pso_pointer p, uint32_t tag_value) {
struct pso2 * result = pointer_to_object( p);
if ((result->header.tag.value & 0xffffff) != tag_value) {
result = NULL;
}
return result;
}