diff options
Diffstat (limited to 'doc/0/0-value.md')
| -rw-r--r-- | doc/0/0-value.md | 63 |
1 files changed, 28 insertions, 35 deletions
diff --git a/doc/0/0-value.md b/doc/0/0-value.md index 2067842..f30735e 100644 --- a/doc/0/0-value.md +++ b/doc/0/0-value.md @@ -97,7 +97,7 @@ payload, which would step on Forbidden Pattern #2, Negative Infinity. This region of 51-bit non-zero values is divided as follows, based on the three highest bits, providing a payload value of 48 bits for each. - 000 :: Pointer to list (code) + 000 :: Pointer to list 001 :: Pointer to heap @@ -123,25 +123,26 @@ highest bits, providing a payload value of 48 bits for each. (etc.) +Forbidden Pattern #3, Positive cqNaN, is avoided thanks to the fact that some +bits of a list pointer are always set; see below. + Zisp splits the native program heap provided by the platform into three regions -of virtual memory: The code heap of 32 GiB, addressed in 64-bit (8-byte) units; +of virtual memory: The list heap of 32 GiB, addressed in 64-bit (8-byte) units; the main heap of 32 GiB, also addressed in 64-bit units; and the 4 GiB heap for `istr` objects (interned strings) which is addressed in bytes. Each region can thus be addressed via 32-bit indices instead of larger direct pointers. ### List pointers -In Zisp, a list is a contiguous array of a fixed number of Values. These may -reside in the main heap or the code heap; this pointer type here is used to -represent lists in the code heap only. - -These code lists are allocated with little or no padding and no metadata on the -heap, to achieve optimal memory density and cache locality of code. Therefore, -we must encode the length of the list directly in the pointer itself. +In Zisp, a list is a contiguous array of a fixed number of Values. To improve +memory density and cache locality, especially for the interpreter, lists of up +to 255 elements are allocated in tight blocks with little or no padding and no +metadata headers on the heap. Their length is therefore encoded directly with +an 8-bit metadata field within the NaN-packed pointer. The exact layout of the 48-bit payload is as follows: -The low 32 bits are an index into the code heap, while the higher 16 bits are +The low 32 bits are an index into the list heap, while the higher 16 bits are divided into 8 high bits for the length, and 8 low bits for garbage collector or other internal metadata. @@ -149,18 +150,10 @@ The length bits cannot be zero. The empty list is represented by a different bit pattern to provide a minor benefit during garbage collection: Zero-length lists can't needlessly trigger the code branch that handles list pointers. -The 8-bit length field means we can only encode lists of up to 255 elements -using this Value type. However, this doesn't mean that source code cannot -contain longer lists: - -Lists of arbitrary length can be allocated as regular heap objects of the Array -type; the difference is hidden when using a generic list API. This means that -*some* parts of source code may actually end up on the main heap, though lists -of greater than 255 elements should be extremely rare, typically only used to -embed static data arrays in source code anyway. - -Forbidden Pattern #3, Positive cqNaN, is avoided thanks to the fact that the -high 8 bits of the payload, encoding the list length, cannot be zero. +Note that "list pointer" and "list heap" are slightly misleading terms, since +arbitrary-length lists can be allocated on the main heap as Array objects with +element type Value. In this case, they are represented by a main heap pointer, +and the generic list API hides the difference. ### Heap pointers @@ -260,14 +253,17 @@ almost purely in-place mutations of the original source code tree. 011 :: Short string as constant - 100 :: Pointer to opcodes in code list + 100 :: Pointer to opcodes in list heap - 101 :: Pointer to opcodes in heap list + 101 :: Pointer to opcodes in main heap 110 :: Local variable reference index 111 :: Lexical capture reference index +Forbidden Pattern #4, Positive Infinity, is avoided thanks to the fact that +pointers to lists always have non-zero length bits. + ### Constant Values The first four categories simply mirror those of the previous 51-bit range, but @@ -275,20 +271,17 @@ mark the Value as being a constant rather than code to evaluate. This way, we can inject constant data into the AST without needing to worry about it being confused for code to evaluate, and without needing the `(quote ...)` wrapper. -Forbidden Pattern #4, Positive Infinity, is avoided thanks to the fact that -pointers to lists always have non-zero length bits. - ### Opcode array pointers -These types are derived from the regular code list pointers (length <= 255) and -heap list pointers (length > 255) by flipping 2 bits. +These types are derived from the regular list pointers (length <= 255) and main +heap Value Array pointers (length > 255) by flipping 2 bits. -A heap list pointer of this kind would result from a list of longer than 255 -that represents actual code to execute. (Had it been a quoted list, it would -have become a "pointer to heap as constant" instead.) This will be exceedingly -rare, given that regular code expressions almost never have such length, but we -must support it; it may result, for instance, from heavy macro use or otherwise -machine-generated source code. +A main heap pointer of this kind can only result from a list of more than 255 +elements which represents actual code to execute. (Had it been a quoted list, +it would have become a "pointer to heap as constant" instead.) This will be +exceedingly rare, given that regular code expressions almost never have such +length, but we must support it; it may result, for instance, from heavy macro +use or otherwise machine-generated source code. Either way, what this means is that a list has been analyzed to ensure it's a well-formed code expression, and transformed into an optimized form: |
