You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CLAUDE.md
+10-6Lines changed: 10 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -35,16 +35,20 @@ Callee-saved registers hold global interpreter state:
35
35
|----------|------|
36
36
|`rbx`| Bytecode IP (into co_code[]) |
37
37
|`r12`| Current frame (PyFrame*) |
38
-
|`r13`| Value stack top |
38
+
|`r13`| Value stack top (payload array, u64[]) |
39
39
|`r14`| co_consts data ptr (&tuple.ob_item[0]) |
40
-
|`r15`|co_names data ptr (&tuple.ob_item[0]) |
40
+
|`r15`|Tag stack top (sidecar tag array, u8[]) |
41
41
|`ecx`| Opcode arg on handler entry |
42
42
43
+
co_names is accessed via `LOAD_CO_NAMES reg` / `LOAD_CO_NAMES_TAGS reg` macros (reads from `eval_co_names` / `eval_co_names_tags` globals), not a dedicated register.
44
+
43
45
**Critical rule:** Never hold live values in caller-saved regs (rax, rcx, rdx, rsi, rdi, r8-r11) across `call` or `DECREF`/`DECREF_REG`. Use push/pop or callee-saved regs instead. `DECREF_REG` calls `obj_dealloc` which clobbers all caller-saved regs.
44
46
45
-
## 128-bit Fat Values
47
+
## Value64 Representation
48
+
49
+
Values are split into 64-bit payloads stored in `u64[]` arrays and 8-bit tags stored in separate `u8[]` sidecar arrays. The value stack uses `r13` (payload top) and `r15` (tag top). Containers (list, tuple, dict) store `ob_item` (u64[]) and `ob_item_tags` (u8[]) separately. Frame locals use `localsplus` (u64[]) and `locals_tag_base` (u8[]).
46
50
47
-
All values are 128-bit (payload, tag) pairs in 16-byte slots. Tags: `TAG_NULL=0`, `TAG_SMALLINT=1`, `TAG_FLOAT=2`, `TAG_NONE=3`, `TAG_BOOL=4`, `TAG_PTR=0x105`. SmallInts store raw signed i64 in payload (full 64-bit range), zero heap alloc/refcount. `INCREF_VAL`/`DECREF_VAL` check `TAG_RC_BIT` (bit 8) to decide refcounting. Functions return `(rax=payload, edx=tag)`.
51
+
Tags (u8): `TAG_NULL=0`, `TAG_SMALLINT=1`, `TAG_FLOAT=2`, `TAG_NONE=3`, `TAG_BOOL=4`, `TAG_PTR=0x85`. Bit 7 (`TAG_RC_BIT=0x80`) means payload is a refcounted heap pointer. SmallInts store raw signed i64 in payload (full 64-bit range), zero heap alloc/refcount. `INCREF_VAL`/`DECREF_VAL` check `TAG_RC_BIT` to decide refcounting. Functions return `(rax=payload, edx=tag)`.
48
52
49
53
## Source Layout
50
54
@@ -64,7 +68,7 @@ All values are 128-bit (payload, tag) pairs in 16-byte slots. Tags: `TAG_NULL=0`
64
68
Defined in `include/*.inc`. All objects start with `PyObject` (ob_refcnt +0, ob_type +8).
0 commit comments