ci: build and ABI-gate B2 in-place GC

This commit is contained in:
Dusk-92
2026-09-08 09:35:37 +02:00
parent 5997a91d51
commit fdf4f0a13b
+128
View File
@@ -0,0 +1,128 @@
name: Build WeirdPerformance 2.4-B2 in-place GC test
on:
push:
branches:
- test/wp24b2-gc-inplace-sweep
paths:
- 'experiments/wp24b-gc/**'
- '.github/workflows/wp24b2-inplace-gc.yml'
workflow_dispatch:
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: mlugg/setup-zig@v2
with:
version: '0.17.0-dev.1970+67f39b551'
- name: Build and ABI-validate x86 DLL
working-directory: experiments/wp24b-gc
run: |
set -euo pipefail
zig build --fetch
python3 - <<'PY'
from pathlib import Path
matches = list(Path("zig-pkg").glob("zhook-*/src/zhook.zig"))
if len(matches) != 1:
raise SystemExit(f"expected one pinned zhook source, found {len(matches)}")
p = matches[0]
text = p.read_text(encoding="utf-8")
old = "var patch: [MAX_STOLEN]u8 = .{0x90} ** MAX_STOLEN;"
new = "var patch: [MAX_STOLEN]u8 = @splat(0x90);"
if old not in text:
raise SystemExit("expected pinned zhook repeat initializer not found")
p.write_text(text.replace(old, new), encoding="utf-8")
PY
zig build -Doptimize=small
DLL=zig-out/bin/weirdperformance_gc24b2.dll
test -s "$DLL"
file "$DLL" | tee BINARY_INFO.txt
file "$DLL" | grep -Eq 'PE32.*Intel (80386|i386)'
strings "$DLL" | grep -q '2.4-B2-gc-inplace-safe-sweep'
if command -v llvm-objdump >/dev/null 2>&1; then
llvm-objdump -d --x86-asm-syntax=intel "$DLL" > ABI_DISASM.txt
else
objdump -d -M intel "$DLL" > ABI_DISASM.txt
fi
python3 - <<'PY'
import re
from pathlib import Path
asm = Path("ABI_DISASM.txt").read_text(encoding="utf-8", errors="replace").lower()
def require(pattern, label):
if not re.search(pattern, asm, re.S):
raise SystemExit(f"ABI validation failed: {label}")
# Detour callbacks: L must arrive in ECX on WoW 5875 x86.
m = re.search(r"mov\s+edx,\s*0x6f7340.{0,240}?push\s+0x([0-9a-f]+)", asm, re.S)
if not m:
raise SystemExit("ABI validation failed: collector callback address not found")
cb = m.group(1).lstrip("0") or "0"
pos = asm.find(cb + ":")
if pos < 0 or not re.search(r"mov\s+esi,\s*ecx", asm[pos:pos+800]):
raise SystemExit("ABI validation failed: collector callback does not consume L from ECX")
m = re.search(r"mov\s+edx,\s*0x6f6ef0.{0,240}?push\s+0x([0-9a-f]+)", asm, re.S)
if not m:
raise SystemExit("ABI validation failed: lua_close callback address not found")
cb = m.group(1).lstrip("0") or "0"
pos = asm.find(cb + ":")
if pos < 0 or not re.search(r"mov\s+esi,\s*ecx", asm[pos:pos+600]):
raise SystemExit("ABI validation failed: lua_close callback does not consume L from ECX")
# Native helper ABI observed directly in WoW 5875:
# lua_gc_remove_objects: ECX=L, EDX=&list, stack arg all=0.
require(
r"lea\s+edx,\s*\[edi\s*\+\s*0x14\].{0,200}?"
r"mov\s+eax,\s*0x6f7210.{0,160}?"
r"mov\s+ecx,\s*esi.{0,160}?"
r"push\s+0x0.{0,100}?call\s+eax",
"rootudata lua_gc_remove_objects ABI",
)
# B2 also calls lua_gc_remove_objects through a runtime link address;
# require at least one call site with ECX loaded from L and EDX nonzero.
require(
r"mov\s+eax,\s*0x6f7210.{0,220}?mov\s+ecx,\s*e[a-z]{2}.{0,180}?call\s+eax",
"chunk lua_gc_remove_objects fastcall callsite",
)
require(
r"mov\s+eax,\s*0x6f72f0.{0,160}?"
r"mov\s+ecx,\s*esi.{0,120}?"
r"xor\s+edx,\s*edx.{0,100}?call\s+eax",
"lua_gc_sweep_all_lists fastcall ABI",
)
for addr, label in (
("6f73e0", "lua_gc_full_collection"),
("6f7370", "lua_gc_shrink_memory"),
("6f7080", "luaCallUserDataGC"),
):
require(
rf"mov\s+eax,\s*0x{addr}.{{0,180}}?mov\s+ecx,\s*e[a-z]{{2}}.{{0,120}}?call\s+eax",
f"{label} ECX ABI",
)
print("ABI validation: PASS")
PY
sha256sum "$DLL" | tee SHA256SUMS.txt
- uses: actions/upload-artifact@v4
with:
name: WeirdPerformance-2.4-B2-GC-InPlace-Safe-Sweep
path: |
experiments/wp24b-gc/zig-out/bin/weirdperformance_gc24b2.dll
experiments/wp24b-gc/SHA256SUMS.txt
experiments/wp24b-gc/BINARY_INFO.txt
experiments/wp24b-gc/ABI_DISASM.txt
if-no-files-found: error