From: Volker Schlecht Subject: Re: lang/node, wip v8-wasm support for yarn berry To: Fabien Romano , ports@openbsd.org Date: Sun, 19 Jul 2026 17:15:17 +0200 Your wasm fix for v8 has already been merged into node 26.x and is in the queue for 24.x - I've committed your diff, because why wait for upstream :-) Thanks! On 7/12/26 5:10 PM, Fabien Romano wrote: > > On 7/11/26 13:09, Volker Schlecht wrote: >> >> On 7/10/26 10:43 AM, Fabien Romano wrote: >> [...] >>> https://chromium-review.googlesource.com/c/v8/v8/+/8063803 >> [...] >> >>> For now, I think we have to disable regexp JIT. >> Attached is the diff I'm currently testing. Did I get it right? >> I am inclined to commit this sooner rather than later, because it >> looks like this will fix the build issues we've been seeing for the >> chromiums. > > Sorry, I'm slow at testing all that stuff. > > Random build failure seems unrelated to stack feature WASM uses. > So the diff looks good for the reliability issue. > > I tried the upstream fix, and it works fine, as expected. > > The regexp JIT, someone could check arm64 before we disable all arch. > If it succeeds on arm64, we may disable all arch except this one. > I need to invest more time learning this topic; see the small report below. > > Then about how we disable JIT. Thinking twice, we should just switch default. > JIT still built in the engine so someone can do --no-regexp-interpret-all. > > The first patch I sent made those read-only, which may produce (seen with d8): > Flag processing error: Contradictory value for readonly flag --regexp-interpret-all > > The problem is I lost my last node build, oops. > So maybe nodes treat those differently. > > Also, after checking carefully, regexp_interpret_all alone is enough. > > bool IrRegExpData::ShouldProduceBytecode() { > return v8_flags.regexp_interpret_all || > (v8_flags.regexp_tier_up && !MarkedForTierUp()); > } > > bool RegExp::CanGenerateBytecode() { > return v8_flags.regexp_interpret_all || v8_flags.regexp_tier_up; > } > > My bad. There is another patch to test. > Actually, I'm not sure which option I prefer (READONLY or not). > Let me know what you think. > > To reproduce the crash : > > Node uses a hardcoded executable path; > You may have to install the node binary you want to test. > (Tests may use both system and build binaries.) > I'm saying just in case because I was struggling to reproduce ... > Until I reinstall node without the patch. (maybe unrelated, not sure) > > cd /usr/ports/lang/node > make retest TEST_TARGET="JOBS=1 JS_SUITES=parallel/test-worker-heap-snapshot NATIVE_SUITES= TEST_CI_ARGS='--repeat 100 -p verbose' jstest" > > Starting release test-worker-heap-snapshot... > Done running release test-worker-heap-snapshot: pass > Starting release test-worker-heap-snapshot... > Done running release test-worker-heap-snapshot: CRASH > Starting release test-worker-heap-snapshot... > Done running release test-worker-heap-snapshot: pass > > On amd64: > > cd `make show=WRKSRC` > doas -u _pbuild egdb out/Release/node node.core > > Core was generated by `node'. > Program terminated with signal SIGTRAP, Trace/breakpoint trap. > #0 0x00000092c52fcb37 in v8::internal::RegExpMacroAssemblerX64::CheckStackGuardState(unsigned long*, unsigned long, unsigned long, unsigned long) () > [Current thread is 1 (process 294920) > > (gdb) disassemble /r $pc-32,$pc > Dump of assembler code from 0x92c52fcb17 to 0x92c52fcb37: > 0x00000092c52fcb17 <_ZN2v88internal23RegExpMacroAssemblerX6420CheckStackGuardStateEPmmmm+167>: 4e ff 48 83 rex.WRX decq -0x7d(%rax) > 0x00000092c52fcb1b <_ZN2v88internal23RegExpMacroAssemblerX6420CheckStackGuardStateEPmmmm+171>: c4 (bad) > 0x00000092c52fcb1c <_ZN2v88internal23RegExpMacroAssemblerX6420CheckStackGuardStateEPmmmm+172>: 30 5b 41 xor %bl,0x41(%rbx) > 0x00000092c52fcb1f <_ZN2v88internal23RegExpMacroAssemblerX6420CheckStackGuardStateEPmmmm+175>: 5c pop %rsp > 0x00000092c52fcb20 <_ZN2v88internal23RegExpMacroAssemblerX6420CheckStackGuardStateEPmmmm+176>: 41 5d pop %r13 > 0x00000092c52fcb22 <_ZN2v88internal23RegExpMacroAssemblerX6420CheckStackGuardStateEPmmmm+178>: 41 5e pop %r14 > 0x00000092c52fcb24 <_ZN2v88internal23RegExpMacroAssemblerX6420CheckStackGuardStateEPmmmm+180>: 41 5f pop %r15 > 0x00000092c52fcb26 <_ZN2v88internal23RegExpMacroAssemblerX6420CheckStackGuardStateEPmmmm+182>: 41 5b pop %r11 > 0x00000092c52fcb28 <_ZN2v88internal23RegExpMacroAssemblerX6420CheckStackGuardStateEPmmmm+184>: 5d pop %rbp > 0x00000092c52fcb29 <_ZN2v88internal23RegExpMacroAssemblerX6420CheckStackGuardStateEPmmmm+185>: 4c 33 1c 24 xor (%rsp),%r11 > 0x00000092c52fcb2d <_ZN2v88internal23RegExpMacroAssemblerX6420CheckStackGuardStateEPmmmm+189>: 4c 3b 1d dc c7 41 01 cmp 0x141c7dc(%rip),%r11 # 0x92c6719310 <__retguard_658> > 0x00000092c52fcb34 <_ZN2v88internal23RegExpMacroAssemblerX6420CheckStackGuardStateEPmmmm+196>: 74 09 je 0x92c52fcb3f <_ZN2v88internal23RegExpMacroAssemblerX6420CheckStackGuardStateEPmmmm+207> > 0x00000092c52fcb36 <_ZN2v88internal23RegExpMacroAssemblerX6420CheckStackGuardStateEPmmmm+198>: cc int3 > End of assembler dump. > > The %rsp changes came from v8/src/regexp/regexp-macro-assembler.cc > All architecture behaves differently, but they share this return address change. > > int NativeRegExpMacroAssembler::CheckStackGuardState( > Isolate* isolate, int start_index, RegExp::CallOrigin call_origin, > Address* return_address, Tagged re_code, > Address* subject, const uint8_t** input_start, const uint8_t** input_end, > uintptr_t gap) { > ... > if (!code_handle->SafeEquals(re_code)) { // Return address no longer valid > // Overwrite the return address on the stack. > intptr_t delta = code_handle->address() - re_code.address(); > Address new_pc = old_pc + delta; > // TODO(v8:10026): avoid replacing a signed pointer. > PointerAuthentication::ReplacePC(return_address, new_pc, 0); > } > ... > } > > Arm64 uses a stub to call native functions, and this stub doesn't use retguard. > If I'm reading this correctly, it should be able to change the return address. > Because it will not change the C++ function but the stub one. > > This is complex and hard to reproduce, but I got this crash in a build. > That's why I think we have to disable this regexp JIT for now. > >>> ./devel/codex >>> ./lang/deno >>> ./lang/node >>> ./www/chromium >>> ./www/iridium >>> ./www/ungoogled-chromium > > I have no idea how long for the WASM fix to land upstream. > > I think the process should be producing patches for chromium first. > > There is a lang/v8 (150.0.7871.100) port for test purposes only. > I didn't try to apply other patches, which should fix tests. > I didn't review test results yet. > I left a previous test.log run on amd64 inside the port. > > cd lang/v8 && make makesum && make MAKE_JOBS=8 test > > If you are missing dependencies, this should be enough (more than needed). > cd www/chromium && make prepare > > === > === 26 tests failed > === >>>> 15940 base tests produced 14817 (92%) non-filtered tests >>>> 14817 tests ran > >>> ./x11/qt5/qtwebengine > > This one is the oldest and looks not affected by new patches. > >>> ./x11/qt6/qtwebengine > > USE_NOBTCFI=yes, v8_enable_cet_ibt=false > This one isn't affected by the WASM jump table fix. > Other patches may apply. > >>> >>> Did I miss one? >> Don't think so. lang/deno and devel/codex are chasing the latest v8 >> and are typically very close to the chromiums. I don't know about >> qtwebengine, but lang/node is much more conservative however. > > And maybe someday we will also have www/electron. > Problems are more about the ecosystem than Electron itself.