Skip to content

Commit d8bd368

Browse files
committed
Roll back unsafe x64 TSETB inline CAS
1 parent 71876a1 commit d8bd368

5 files changed

Lines changed: 22 additions & 80 deletions

File tree

dynasm/dasm_x86.lua

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,8 +1175,6 @@ local map_op = {
11751175

11761176
imul_2 = "rmqdw:0FAFrM|rIqdw:69rmI|rSqdw:6BrmS|riqdw:69rmi",
11771177
imul_3 = "rmIqdw:69rMI|rmSqdw:6BrMS|rmiqdw:69rMi",
1178-
cmpxchg_2 = "mrb:0FB0Rm|mrqdw:0FB1Rm", -- 486+
1179-
11801178
movzx_2 = "rm/db:0FB6rM|rm/qb:|rm/wb:0FB6rM|rm/dw:0FB7rM|rm/qw:",
11811179
movsx_2 = "rm/db:0FBErM|rm/qb:|rm/wb:0FBErM|rm/dw:0FBFrM|rm/qw:",
11821180

@@ -2392,4 +2390,3 @@ end
23922390
return _M
23932391

23942392
------------------------------------------------------------------------------
2395-

notes/perf-regression-audit-2026-07-01.md

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,12 @@ Read-only subagent audits confirmed the major reports:
1818
without retiring the slot. `m6_jit_recursive_call_unroll` covers this, and
1919
`t-vm-safepoint` now asserts this recorder path does not perform a scoped
2020
handshake or scoped slot retirement; public `jit.flush(1)` still does.
21-
- x64 interpreter table stores remain helper-heavy overall: `TSETS` goes
22-
straight to `vmeta_tsets`, and `TSETV`/`TSETR` array stores route through
23-
`lj_tab_storetv_forvm_array()` plus barrier checks. The first narrow
24-
exception is `TSETB` for stable current-generation array slots: it now emits
25-
an inline `lock; cmpxchg` through DynASM's x86 frontend and falls back to the
26-
helper for weak tables, moved/retiring arrays, CAS races, nil/metatable
27-
decisions, and forwarding sentinels.
21+
- x64 interpreter table stores remain helper-heavy: `TSETS` goes straight to
22+
`vmeta_tsets`, and `TSETV`/`TSETB`/`TSETR` array stores route through
23+
`lj_tab_storetv_forvm_array()` plus barrier checks. A narrow `TSETB`
24+
inline-CAS experiment was rolled back after a clean rebuild exposed a default
25+
`luajit -e 'print(1)'` crash; the remaining fast-path work must first prove
26+
the VM barrier/base/PC contract for direct inline stores.
2827
- x64 `BC_TNEW` has no inline bump allocation. The current safe prerequisite is
2928
still exact object layout/bitmap/accounting/root-publication support; first
3029
slice should be empty-table only and fall back to the current helper when any
@@ -42,10 +41,10 @@ Follow-up order:
4241
keeps stock sweep/finalizer semantics while removing the global root-list
4342
cache line from normal allocations; bitmap-only sweep and zero-atomic bump
4443
allocation remain separate follow-up work.
45-
2. Partially done: `BC_TSETB` has a guarded x64 inline CAS fast path for
46-
stable current-generation array slots. Remaining work is `TSETV`/`TSETR`,
47-
stable hash slots, and any collectable-value fast barrier path; new-key,
48-
metatable, weak, moved/retiring, and forwarded cases stay on helpers.
44+
2. Reintroduce guarded x64 interpreter store fast paths for existing stable
45+
array/hash slots only after the direct-store barrier bridge preserves the
46+
same `lua_State` base, saved-PC, weak-write, forwarding, and parent-barrier
47+
contracts as `lj_tab_storetv_forvm_array()`.
4948
3. Restore JIT no-helper ASTORE/HSTORE for stable primitive-value stores before
5049
collectable-value barrier fast paths.
5150
4. Add empty-table x64 `BC_TNEW` inline bump allocation behind strict arena,

plan/07_interpreter_vm.md

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -229,13 +229,11 @@ reports `386 passed`.
229229

230230
Current store-publication guard: `m5_x64_vm_store_publication` asserts the x64
231231
VM cannot reintroduce legacy inline `barrierback`/`lj_gc_barrieruv` paths,
232-
keeps `TSETV`/`TSETR` array stores on `lj_tab_storetv_forvm_array()`, keeps
233-
`TSETM` range stores on `lj_tab_storetvn_forvm_array()`, keeps `TSETS` on the
234-
C fallback instead of a direct hash-slot store, and keeps closed `CSET`/`USETx`
235-
paths on `lj_func_storeuv_*_pub()` release-copy helpers. `TSETB` has a narrow
236-
x64 inline `lock; cmpxchg` fast path for stable current-generation array slots
237-
and falls back to `lj_tab_storetv_forvm_array()` for weak tables, moved or
238-
retiring arrays, CAS races, nil/metatable decisions, and forwarding sentinels.
232+
keeps `TSETV`/`TSETB`/`TSETR` array stores on
233+
`lj_tab_storetv_forvm_array()`, keeps `TSETM` range stores on
234+
`lj_tab_storetvn_forvm_array()`, keeps `TSETS` on the C fallback instead of a
235+
direct hash-slot store, and keeps closed `CSET`/`USETx` paths on
236+
`lj_func_storeuv_*_pub()` release-copy helpers.
239237

240238
Current x64 bridge note: the base-library `setmetatable` fast path now
241239
publishes the table -> metatable edge through `lj_gc2_barrier_obj_pair()` before
@@ -247,9 +245,7 @@ original inline `wbarrier_tv` sketch in favor of a more conservative,
247245
C-auditable safety surface; x64 closed `USETx`/`CSET` stores release-copy through
248246
`lj_func_storeuv_*_pub()` helpers, and raw/open cell stores remain stack-local
249247
writes. The old x64 `vm_gc2_barriertab` helper
250-
label has no remaining VM branch users and is retired; the `TSETB` inline CAS
251-
uses DynASM's x86 `cmpxchg` frontend entry rather than literal byte emission;
252-
the JIT C-call
248+
label has no remaining VM branch users and is retired; the JIT C-call
253249
`lj_gc2_barrier_tab_g` path remains separate. The interpreter allocation slow
254250
path now also runs the GC2 hard-threshold assist from `lj_gc_step_fixtop()` once
255251
the current legacy VM threshold check branches there, with

plan/12_implementation_plan.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -137,12 +137,10 @@ escaped, and weak-table references. These lower through split hash/array/newref
137137
helpers that run the parent-aware value barrier and the P_WEAK weak-write
138138
bridge; M10 now also pins that traced helper-backed array stores enqueue the
139139
old parent, not the young value, for idle generational remembered-set draining.
140-
The x64 VM `TSETV`/`TSETR`/`TSETM` fast array/range stores use post-store
141-
publication helpers instead of pre-store black-table repair retry branches,
142-
preserving the `TSETM` table barrier while the stored value snapshot drives GC2
143-
and legacy repair. `TSETB` keeps those helper fallbacks, but stable
144-
current-generation array slots now take a guarded inline `lock; cmpxchg` path
145-
emitted through DynASM's x86 frontend.
140+
The x64 VM `TSETV`/`TSETB`/`TSETR`/`TSETM` fast array/range stores use
141+
post-store publication helpers instead of pre-store black-table repair retry
142+
branches, preserving the `TSETM` table barrier while the stored value snapshot
143+
drives GC2 and legacy repair.
146144
Active-MT recording no longer disables all new traces: secondary TGs can still
147145
record numeric/non-table root and side traces, plus fresh table allocations,
148146
under the recorder token. The current temporary table boundary is narrower and

src/vm_x64.dasc

Lines changed: 2 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -371,43 +371,6 @@
371371
|.macro x64_vm_tab_node_hmask_acq, dst, node
372372
| mov dst, dword [node+TABNODE_HMASK_OFS] // x64_vm_tab_node_hmask_acq: TSO acquire load.
373373
|.endmacro
374-
|.macro x64_vm_tab_array_cas_fast, fallback
375-
| mov r9, RC // Save TValue *slot for helper fallback.
376-
| mov RC, r8 // cmpxchg expected value must be in RAX.
377-
| test byte TAB:RB->marked, LJ_GC_WEAK
378-
| jnz >9
379-
| x64_vm_tab_array_acq r8, TAB:RB
380-
| cmp r8, TMPR
381-
| jne >9
382-
| lea ITYPE, [RB+TAB_COLO_SLOTS]
383-
| cmp TMPR, ITYPE
384-
| je >7
385-
| x64_vm_tab_array_flags_acq ITYPEd, TMPR
386-
| test ITYPEd, TABARRAY_FLAG_RETIRING
387-
| jnz >9
388-
|7:
389-
| mov ITYPE, [BASE+RA*8]
390-
| lock; cmpxchg aword [r9], ITYPE
391-
| jne >9
392-
| test byte TAB:RB->marked, LJ_GC_WEAK
393-
| jnz >9
394-
| x64_vm_tab_array_acq r8, TAB:RB
395-
| cmp r8, TMPR
396-
| jne >9
397-
| lea ITYPE, [RB+TAB_COLO_SLOTS]
398-
| cmp TMPR, ITYPE
399-
| je >7
400-
| x64_vm_tab_array_flags_acq ITYPEd, TMPR
401-
| test ITYPEd, TABARRAY_FLAG_RETIRING
402-
| jnz >9
403-
|7:
404-
| mov RC, r9
405-
| jmp >7
406-
|9:
407-
| mov RC, r9
408-
| jmp fallback
409-
|7:
410-
|.endmacro
411374
|.macro x64_vm_node_next_acq, dst, node
412375
| mov dst, node->next // x64_vm_node_next_acq: TSO acquire load.
413376
|.endmacro
@@ -4522,24 +4485,13 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
45224485
| shl RCd, 3
45234486
| add RC, TMPR
45244487
| mov r8, [RC]
4525-
| mov64 ITYPE, LJ_TFORWARD_BITS
4526-
| cmp r8, ITYPE
4488+
| mov64 r10, LJ_TFORWARD_BITS
4489+
| cmp r8, r10
45274490
| je ->vmeta_tsetb
45284491
| cmp r8, LJ_TNIL
45294492
| je >3 // Previous value is nil?
45304493
|1:
45314494
|2: // Set array slot.
4532-
| x64_vm_tab_array_cas_fast >6
4533-
| cmp TGMARK, 0
4534-
| jnz ->vm_gc2_barriertv_tab
4535-
| test byte TAB:RB->marked, LJ_GC_BLACK // isblack(table)
4536-
| jz >8
4537-
| jmp ->vm_gc2_barriertv_tab
4538-
|8:
4539-
| ins_next
4540-
|
4541-
|6:
4542-
| movzx r9d, PC_RC
45434495
|.if X64WIN
45444496
| mov ARG5d, r9d
45454497
| lea CARG4, [BASE+RA*8]

0 commit comments

Comments
 (0)