Object Layout
Objects
This page describes the different object types and their in-memory layout in the rapid runtime system. Unless noted otherwise, memory is laid out left-to-right starting with lower addresses. Binary values are presented most-significant bit (MSB) first (left, numbered "n-1" for an n-bit value) and least-significant bit (LSB) last (right, numbered "0").
Immediate Values and Object Pointers
Objects and values are always stored in 64 bits, they can either point to an object in memory or directly contain an immediate value.
Immediate Values
Immediate Value: +-----------------------------+ |63 ... (bit number) ... 0| +-----------------------------+ |xxxxxx ... xxxxxx1| +-----------------------------+
Immediate values (or immediates) are values, whose LSB is set to 1. The remaining 63 bits contain the "payload" of the value (x in the diagram above). Currently the following types are represented using immediates:
- Int (63-bit signed integer)
- Bits8, Bits16, and Bits32
Note
In future versions, more types/values could be represented as immediates, e.g. 0-ary constructors and potentially Integer s x where |x| < 2^62
Object Pointers
Objects are referred to by a pointer. All objects are aligned to 8-byte boundaries in memory and therefore have their 3 least-significant bits all set to 0
Object Pointer: +-----------------------------+ |63 ... (bit number) ... 0| +-----------------------------+ |xxxxxx ... xxxxxx000| +-----------------------------+
Generic in-memory layout of objects
Object Layout: increasing memory addresses ===> +-----------------+-------------------------+ | Header (64 bit) | Payload (variable size) | +-----------------+-------------------------+ ^ | Object Pointer points to start address
Generic Object Header
Object Header (64 bit): +-----------------------+--------------------+-------------+ | 32 highest bits | 24 extra bits | 8 low bits | +=======================+====================+=============+ | Size, tag, or similar | (generally unused) | Object type | +-----------------------+--------------------+-------------+
The following table describes how the different fields are currently used for all object types:
Type Name | "Object Type" Field Value | "Size or tag" Field Meaning | Payload |
---|---|---|---|
CLOSURE | 0x02 | not present, see Closures | 8 * n bytes: captured free variables |
INT [1] | 0x04 | (ignored) | (not used) |
DOUBLE [1] | 0x04 | (ignored) | 8 bytes double precision float value |
BITS64 [1] | 0x04 | (ignored) | 8 bytes (64 bits) unsigned Integer |
STRING | 0x08 | length of the string in bytes | n bytes: string encoded as UTF-8 |
IOREF | 0x10 | (ignored) | 8 bytes: 1 value |
BUFFER | 0x14 | size of the buffer in bytes | n bytes: buffer contents |
OPAQUE | 0x18 | size of the contents in bytes | n bytes: opaque content |
PTR | 0x1c | reserved, must be 1 | 8 bytes: the pointer |
IOARRAY | 0x20 | number of contained items | 8 * n bytes: n values |
BIGINT | 0x24 | number of limbs | 8 * n bytes: the limbs, stored in little-endian order |
CLOCK | 0x28 | 0: invalid, 1: valid | 16 bytes: seconds (64 bit uint), nanoseconds (64 bit uint) |
CONSTRUCTOR | 0x2c see "special" in payload | tag of the constructor | 8 * n bytes: n values Value n is stored in the 24 extra bits ("left" of the type) |
Footnotes
[1] | (1, 2, 3) All numeric types are treated the same (OBJ_TYPE == 0x04), followed by 64 bits of payload |
Closures
Closure Layout: +------------------------------------------+------------------------------------------+ | 64 bits | Captured free variables (variable size) | +==========================================+==========================================+ | Tagged pointer to function entry address | n * 8 bytes, pointers to captured vars | +------------------------------------------+------------------------------------------+ | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx010 | | +------------------------------------------+------------------------------------------+
In-place Forwarding Pointer
During garbage collection, the object header may be replaced with a special "in-place forwarding pointer" which consists of the target pointer shifted one bit to the right, and the highest bit set.
In-place forwarding pointer object layout (64 bit): +-----------------------+-----------------+-----------------------------------------+ | 63 highest bits | 1 lowest bit | variable unused space (8 bytes or more) | +=======================+=================+=========================================+ | target_ptr | 1 | never accessed (former payload) | +-----------------------+-----------------+-----------------------------------------+
No such header should remain after GC is completed. I.e. normal program execution will never encounter an object with such header.