Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: d8d35775495697d094af498ab4e726cdff9aa029
https://github.com/WebKit/WebKit/commit/d8d35775495697d094af498ab4e726cdff9aa029
Author: Yijia Huang <[email protected]>
Date: 2026-09-15 (Tue, 15 Sep 2026)
Changed paths:
M JSTests/wasm/debugger/tests/tests.py
M Source/JavaScriptCore/wasm/debugger/WasmBreakpointManager.cpp
M Source/JavaScriptCore/wasm/debugger/WasmBreakpointManager.h
M Source/JavaScriptCore/wasm/debugger/WasmDebugServerUtilities.cpp
M Source/JavaScriptCore/wasm/debugger/WasmDebugServerUtilities.h
M Source/JavaScriptCore/wasm/debugger/WasmExecutionHandler.cpp
Log Message:
-----------
[JSC] Decide on the pre-patch opcode, not the patched byte, in the WASM
debugger
https://bugs.webkit.org/show_bug.cgi?id=324169
rdar://187395184
Reviewed by Mark Lam.
A breakpoint patches byte 0 of an instruction to 0x00, which is `unreachable`.
Any code that later reads that byte to decide what the instruction is gets
`unreachable` back for as long as the site is installed, not the opcode that is
really there.
setStepIntoBreakpointForThrow() did exactly that. It read *handlerPC to decide
whether the exception handler starts with try_table, and only then applied the
metadata delta that moves the target to the catch body. With a site installed
on that same try_table byte the comparison failed, the delta was skipped, and a
step into the throw armed the try_table itself instead of the handler body, so
the step never reported. BreakpointManager::originalOpcodeAt() now answers the
question the caller is actually asking: the opcode before any patch, falling
back to *pc when no breakpoint owns that byte.
Breakpoint::originalBytecode and StopData::originalBytecode were uint8_t, which
is what let a raw byte and a decoded opcode be used interchangeably. Both are
now OpType, so the two are distinct types and patchBreakpoint()/restorePatch()
have to say which one they mean. stepAtBytecode() switches on that field, so it
also stops needing a cast.
Separately, the address-to-breakpoint map held a raw uint8_t* and looked the
breakpoint up again on every removal, with a RELEASE_ASSERT that the second
lookup succeeded. It now holds Ref<Breakpoint> directly. Several addresses map
to one Breakpoint - sibling instances of a module name the same shared byte -
so this is many-to-one, and siteCount is exactly how many map entries point at
it. Holding the Ref rather than the pc means an address can no longer name a
patch that has already been released, and removeSiteImpl() does one lookup
instead of two.
StepIntoThrowWithPatchedTryTableTestCase installs a site on the try_table
opcode and steps through the throw, which fails without originalOpcodeAt().
Also restates four comments from 324167 that described the change rather than
the constraint, so they read as standing facts about the protocol instead of a
history of the patch.
Tests:
JSTests/wasm/debugger/tests/tests.py: StepIntoThrowWithPatchedTryTableTestCase
Canonical link: https://commits.webkit.org/321168@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications