---
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.
