--- title: "Value Representation" description: "JSValue tagging and encoding" --- ## Overview Every value in ƿit is a 64-bit word called a JSValue. The runtime uses LSB (least significant bit) tagging to pack type information directly into the value, avoiding heap allocation for common types. ## Tag Encoding The lowest bits of a JSValue determine its type: | LSB Pattern | Type | Payload | |-------------|------|---------| | `xxxxxxx0` | Integer | 31-bit signed integer in upper bits | | `xxxxx001` | Pointer | 61-bit aligned heap pointer | | `xxxxx101` | Short float | 8-bit exponent + 52-bit mantissa | | `xxxxx011` | Special | 5-bit tag selects subtype | ### Integers If the least significant bit is 0, the value is an immediate 31-bit signed integer. The integer is stored in the upper bits, extracted via `v >> 1`. ``` [integer: 31 bits][0] ``` Range: -1073741824 to 1073741823. Numbers outside this range are stored as short floats or heap-allocated. ### Pointers If the lowest 3 bits are `001`, the value is a pointer to a heap object. The pointer is 8-byte aligned, so the low 3 bits are available for the tag. The actual address is extracted by clearing the low 3 bits. ``` [pointer: 61 bits][001] ``` All heap objects (arrays, records, blobs, text, functions, etc.) are referenced through pointer-tagged JSValues. ### Short Floats If the lowest 3 bits are `101`, the value encodes a floating-point number directly. The format uses an 8-bit exponent (bias 127) and 52-bit mantissa, similar to IEEE 754 but with reduced range. ``` [sign: 1][exponent: 8][mantissa: 52][101] ``` Range: approximately ±3.4 * 10^38. Numbers outside this range fall back to null. Zero is always positive zero. ### Specials If the lowest 2 bits are `11`, the next 3 bits select a special type: | 5-bit Tag | Value | |-----------|-------| | `00011` | Boolean (true/false in upper bits) | | `00111` | Null | | `01111` | Exception marker | | `10111` | Uninitialized | | `11011` | Immediate string | | `11111` | Catch offset | ## Immediate Strings Short ASCII strings (up to 7 characters) are packed directly into the JSValue without heap allocation: ``` [char6][char5][char4][char3][char2][char1][char0][length: 3][11011] ``` Each character occupies 8 bits. The length (0-7) is stored in bits 5-7. Only ASCII characters (0-127) qualify — any non-ASCII character forces heap allocation. ```javascript var s = "hello" // 5 chars, fits in immediate string var t = "" // immediate (length 0) var u = "longtext" // 8 chars, heap-allocated ``` ## Null Null is encoded as a special-tagged value with tag `00111`. There is no `undefined` in ƿit — only null. ```javascript var x = null // special tag null var y = 1 / 0 // also null (division by zero) var z = {}.missing // null (missing field) ``` ## Boolean True and false are encoded as specials with tag `00011`, distinguished by a bit in the upper payload. ## Summary The tagging scheme ensures that the most common values — small integers, booleans, null, and short strings — require zero heap allocation. This significantly reduces GC pressure and improves cache locality.