3.1 KiB
title, description
| title | description |
|---|---|
| Value Representation | 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.
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.
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.