Skip to content

[SUB-BISECT] bcd47e7f3fe7 config-only (OptionsList.h + wasm.json + generator)#192

Closed
Jarred-Sumner wants to merge 9 commits into
mainfrom
ipint-revert-config-only
Closed

[SUB-BISECT] bcd47e7f3fe7 config-only (OptionsList.h + wasm.json + generator)#192
Jarred-Sumner wants to merge 9 commits into
mainfrom
ipint-revert-config-only

Conversation

@Jarred-Sumner

@Jarred-Sumner Jarred-Sumner commented Apr 23, 2026

Copy link
Copy Markdown
Collaborator

Context

Windows-x64-only WebAssembly OOB crash in pglite (RuntimeError: Out of bounds memory access at invoke_vi) appeared after the WebKit upgrade in oven-sh/bun#29393. JSC_useWasmIPInt=0 hides it. Bisect history:

Build WebKit What Windows pglite
WebKit#47292 f8513c72 (#190) 7 IPInt commits reverted ❌ fails
WebKit#47370 1987e88f (#190) 7 + bcd47e7f3fe7 (wide-arith) reverted ✅ passes

bcd47e7f3fe7 is the culprit. But disassembly of LowLevelInterpreter.cpp.obj from both Windows preview builds shows all 728 ipint_* handlers are byte-identical after address normalization — only .balign 512 padding differs. So the IPInt asm cannot be the cause; the bug is in one of the commit's other 13 files.

This branch

Starts from working 1987e88f, re-applies only the config slice of bcd47e7f3fe7:

  • OptionsList.h — appends useWasmWideArithmetic bool. Grows OptionsStorage by ≥1 byte, which shifts every JSC::Config field after options: shellTimeoutCheckCallback, wasmDebuggerOnStop, wasmDebuggerOnResume, memoryDebuggerStopTheWorld, jsDebuggerStopTheWorld (BUN-specific), llint.exceptionInstructions[], llint.gateMap[].
  • wasm.json — 4 wide-arith entries (extendedOp 19–22)
  • generateWasmOpsHeader.py — adds FOR_EACH_WASM_WIDE_ARITHMETIC_OP to Ext1OpType enum + makeString

Asm, offlineasm, BBQ/OMG/IPInt generators, FunctionParser, and assembler all stay at the working state.

Decision matrix (vs #191 which re-applies all 13 non-asm files)

#191 #192 (this) Conclusion
❌ fails ❌ fails OptionsStorage growth shifts a JSC::Config field something reads at a stale offset, OR the generated Ext1OpType enum
❌ fails ✅ passes WasmBBQJIT* / WasmOMGIRGenerator / WasmFunctionParser.h / assembler/*
✅ passes ✅ passes bug IS in asm despite identical handler bytes (COFF section/reloc?)

Not for merge — bisect preview only. See #190 for the full thread.

sosukesuzuki and others added 9 commits April 22, 2026 23:03
…f it does not call functions"

This reverts commit ef40cab.
This reverts commit bcd47e7.

This is the 8th and final IPInt-touching commit from the d550dd3
upstream merge. With this revert stacked on the 7 prior reverts,
InPlaceInterpreter64.asm, InPlaceInterpreter.asm, offlineasm/x86.rb,
and WasmIPIntGenerator.cpp are now byte-identical to d924138
(the previous upstream sync point). If the Windows-x64 pglite OOB
still reproduces on this preview, the IPInt source path is provably
unchanged from the last-good build and the cause is elsewhere.

Conflict resolution: _conversion_prefix guard restored to 0x12 with
the decodeLEBVarUInt32 macro the earlier reverts already brought back.
…sHeader.py from bcd47e7

Config-only slice. This grows OptionsStorage by one bool (shifting
JSC::Config fields after it) and adds Ext1OpType enum entries
0x13-0x16. Nothing else from bcd47e7.

If this fails pglite on Windows -> the bug is the OptionsStorage size
change shifting a JSC::Config field that something reads at a stale
offset (or the generated WasmOps.h enum).

If this passes -> the bug is in WasmBBQJIT*/WasmOMGIRGenerator/
WasmFunctionParser/assembler additions (compare against #191).
@coderabbitai

coderabbitai Bot commented Apr 23, 2026

Copy link
Copy Markdown

Walkthrough

This pull request removes wide integer arithmetic operations from WebAssembly, eliminates carry/borrow assembly instructions, refactors the In-Place Interpreter (IPInt) to use a pinned locals pointer and restructured LEB128 metadata encoding, and updates associated code generators and debugger integration.

Changes

Cohort / File(s) Summary
WebAssembly Test Deletions
JSTests/wasm/ipint-tests/ipint-test-leb-decode.js, ipint-test-simd-memory.js, ipint-test-simd-multi-byte-leb.js, JSTests/wasm/stress/atomic-cmpxchg-large-offset.js, memory64-atomics.js, wide-arithmetic.js
Removes comprehensive test suites covering LEB128 decoding, SIMD memory operations, atomic operations with large offsets, memory64 atomics, and wide arithmetic operations.
Assembly Instruction Removals
Source/JavaScriptCore/assembler/MacroAssemblerARM64.h, MacroAssemblerX86_64.h, X86Assembler.h
Deletes carry/borrow arithmetic helpers (add64AndSetFlags, addCarry64, sub64AndSetFlags, subBorrow64 on ARM64; addCarry64, subBorrow64 on x86-64) and removes corresponding x86 opcode definitions (ADC, SBB).
In-Place Interpreter Core Refactoring
Source/JavaScriptCore/llint/InPlaceInterpreter.asm, InPlaceInterpreter.cpp, InPlaceInterpreter.h
Introduces pinned PL register for locals access, rewrites LEB128 decoding macros, adds slow-path label standardization, updates call/OSR/catch handling to preserve/recompute PL, and adjusts debugger trap stack layout.
Offline Assembler Updates
Source/JavaScriptCore/offlineasm/arm64.rb, instructions.rb, x86.rb
Removes quadword arithmetic opcodes (addqs, subqs, adcq, sbcq, smulhq, umulhq) from ARM64 and x86 instruction dispatch, eliminating wide-arithmetic instruction emission.
BBQJIT Wide Arithmetic Removal
Source/JavaScriptCore/wasm/WasmBBQJIT.cpp, WasmBBQJIT.h, WasmBBQJIT64.cpp
Removes topValue offset parameter and deletes wide-arithmetic helper methods (addI64Add128, addI64Sub128, addI64MulWideS, addI64MulWideU).
IPInt Metadata & Code Generation Restructuring
Source/JavaScriptCore/wasm/WasmFunctionIPIntMetadataGenerator.h, WasmFunctionIPIntMetadataGenerator.cpp, WasmIPIntGenerator.h, WasmIPIntGenerator.cpp, WasmFunctionParser.h
Consolidates metadata helpers into LEB128-constant-focused API, removes per-instruction metadata structs (table/ref/element/data/atomic access), adds Const32/64/128Metadata structures, updates constant/index emission, and removes wide-arithmetic expression parsing.
IPInt OMG Code Generation
Source/JavaScriptCore/wasm/WasmOMGIRGenerator.cpp, WasmConstExprGenerator.cpp
Removes wide-arithmetic IR emitter helpers and tuple-type caching for 128-bit results; deletes constant-expression wide-operation stubs.
IPInt Slow Paths & Exception Handling
Source/JavaScriptCore/wasm/WasmIPIntSlowPaths.h, WasmIPIntSlowPaths.cpp
Replaces FrameAccess stack-based addressing with explicit IPIntLocal* pl pointer in loop_osr, exception retrieval/rethrow, and prepare_call slow paths; updates OSR buffer construction and exception slot access to use direct pointer indexing.
Debugger Integration Updates
Source/JavaScriptCore/wasm/debugger/WasmDebugServerUtilities.h, WasmDebugServerUtilities.cpp, WasmExecutionHandler.h, WasmExecutionHandler.cpp, WasmQueryHandler.cpp
Adds IPIntLocal* locals parameter to StopData constructors and debugger trap handlers, introduces localsFromFrame helper, and switches local access from FrameAccess to direct locals pointer indexing.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly describes the specific bisect scope (config-only re-application of commit bcd47e7), making it understandable to reviewers scanning the history.
Description check ✅ Passed The PR description is thorough and well-structured, providing context (Windows crash, bisect history), rationale (config-only testing), decision matrix, and explicit note that this is not for merge. However, it does not follow the provided template format (bug link, Reviewed by, bullet-point file changes).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h (1)

5066-5074: ⚠️ Potential issue | 🟠 Major

This commit violates its stated config-only scope by including MacroAssemblerX86_64.h.

The commit message declares "Config-only slice. This grows OptionsStorage by one bool... Nothing else from bcd47e7," listing only OptionsList.h, wasm.json, and generateWasmOpsHeader.py. However, the actual changes include Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h, which contains assembler logic (carry/borrow operations at lines 5071–5078).

Including assembler changes alongside config changes introduces a non-config variable into the bisect and invalidates attribution. Either revert the assembler file to match the baseline, or reconsider the commit's scope to reflect what was actually changed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h` around lines 5066 -
5074, The change illegally touched assembler logic in MacroAssemblerX86_64.h
(notably the add64(Address, RegisterID)/add64(RegisterID, RegisterID) additions
and the carry/borrow-related code near the carry/borrow operations), which
violates the commit's "config-only" scope; either revert MacroAssemblerX86_64.h
to the baseline (remove the assembler logic changes so only
OptionsList.h/wasm.json/generateWasmOpsHeader.py remain) or split this work into
a separate functional commit and update the commit message to reflect the
assembler changes (ensure the file MacroAssemblerX86_64.h no longer contains the
added assembler modifications like add64 overloads and any carry/borrow
alterations unless you create a new, properly scoped commit).
Source/JavaScriptCore/offlineasm/instructions.rb (1)

352-390: ⚠️ Potential issue | 🟠 Major

This change set breaks the “config-only” bisect isolation.

Lines 352–390 modify offlineasm opcode tables, which is outside the stated sub-bisect scope. That makes pass/fail results ambiguous (config shift vs opcode-table effects). Please remove this file from this bisect slice (or split it into a separate bisect step).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Source/JavaScriptCore/offlineasm/instructions.rb` around lines 352 - 390, The
change touches opcode tables X86_INSTRUCTIONS and X86_SIMD_INSTRUCTIONS which
breaks a config-only bisect; revert the modifications to those symbols in this
bisect slice (undo the added/removed entries in X86_INSTRUCTIONS and keep
X86_SIMD_INSTRUCTIONS unchanged) and move the opcode-table edits into a separate
commit/step, or remove this file from the current bisect so the slice remains
config-only; ensure the separate commit clearly contains only the
X86_INSTRUCTIONS/X86_SIMD_INSTRUCTIONS edits.
Source/JavaScriptCore/wasm/WasmIPIntSlowPaths.cpp (1)

478-492: ⚠️ Potential issue | 🟡 Minor

Type inconsistency with other exception handlers.

The rethrow_exception function declares IPIntStackEntry* pl but uses the same access pattern (pl[callee->localSizeToAlloc() + tryDepth - 1]) as the other exception handlers that use IPIntLocal* pl. This matches the header declaration issue flagged earlier.

If IPIntStackEntry and IPIntLocal are indeed compatible types, consider using IPIntLocal* here for consistency with retrieve_and_clear_exception, retrieve_clear_and_push_exception, and retrieve_clear_and_push_exception_and_arguments.

Suggested fix for type consistency
-WASM_IPINT_EXTERN_CPP_DECL(rethrow_exception, CallFrame* callFrame, IPIntStackEntry* pl, unsigned tryDepth)
+WASM_IPINT_EXTERN_CPP_DECL(rethrow_exception, CallFrame* callFrame, IPIntLocal* pl, unsigned tryDepth)

And correspondingly in the header file (line 81):

-WASM_IPINT_EXTERN_CPP_HIDDEN_DECL(rethrow_exception, CallFrame*, IPIntStackEntry* pl, unsigned tryDepth);
+WASM_IPINT_EXTERN_CPP_HIDDEN_DECL(rethrow_exception, CallFrame*, IPIntLocal* pl, unsigned tryDepth);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Source/JavaScriptCore/wasm/WasmIPIntSlowPaths.cpp` around lines 478 - 492,
The rethrow_exception function uses the same indexing pattern as other handlers
but takes IPIntStackEntry* pl, causing a type inconsistency; change the
parameter type to IPIntLocal* pl in rethrow_exception (and update the
corresponding declaration in the header) to match retrieve_and_clear_exception,
retrieve_clear_and_push_exception, and
retrieve_clear_and_push_exception_and_arguments, while keeping the same access
expression pl[callee->localSizeToAlloc() + tryDepth - 1] (ensure IPIntLocal and
IPIntStackEntry are compatible before switching and adjust the header prototype
accordingly).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Source/JavaScriptCore/wasm/WasmBBQJIT.cpp`:
- Around line 1034-1037: The change altered BBQ temporary indexing logic in
BBQJIT::topValue (and the related change at the call-result materialization
around the other modified spot) which must not be changed on this config-only
bisect branch; restore the original temp-index computation by reverting the
modified expression that constructs Value::fromTemp (i.e., remove the new
addition/subtraction of
enclosedHeight()/implicitSlots()/expressionStack().size() logic) and reintroduce
the previous indexing expression used for temp/materialized call results so BBQ
temp indexing remains identical to the working commit (ensure you update both
BBQJIT::topValue and the other call-result site to the original computation).

In `@Source/JavaScriptCore/wasm/WasmFunctionIPIntMetadataGenerator.cpp`:
- Around line 95-103: The IPInt::InstructionLengthMetadata written in
WasmFunctionIPIntMetadataGenerator.cpp's fast path incorrectly stores a bit from
the constant into .length; change the .length assignment in the short-i32.const
branch to store the actual instruction length (use safeCast<uint8_t>(length))
instead of safeCast<uint8_t>((value >> 7) & 1), so that the metadata (written
via m_metadata.grow and WRITE_TO_METADATA) consistently records the instruction
length for IPInt::InstructionLengthMetadata.

In `@Source/JavaScriptCore/wasm/WasmIPIntGenerator.cpp`:
- Around line 728-733: The vector-immediate producers (e.g.,
IPIntGenerator::addSIMDShuffle and the similar function at the 780-784 region)
currently only record instruction length and do not emit the new 128-bit
metadata or payload; update these functions to create and append
Const128Metadata and call addLEB128V128Constant() with the v128 immediate (the
128-bit shuffle mask or v128.const value) before/when calling
m_metadata->addLength/getCurrentInstructionLength(), so the Const128Metadata is
emitted and the payload written using addLEB128V128Constant(); reference the
symbols IPIntGenerator::addSIMDShuffle, Const128Metadata, and
addLEB128V128Constant when making the changes.

---

Outside diff comments:
In `@Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h`:
- Around line 5066-5074: The change illegally touched assembler logic in
MacroAssemblerX86_64.h (notably the add64(Address, RegisterID)/add64(RegisterID,
RegisterID) additions and the carry/borrow-related code near the carry/borrow
operations), which violates the commit's "config-only" scope; either revert
MacroAssemblerX86_64.h to the baseline (remove the assembler logic changes so
only OptionsList.h/wasm.json/generateWasmOpsHeader.py remain) or split this work
into a separate functional commit and update the commit message to reflect the
assembler changes (ensure the file MacroAssemblerX86_64.h no longer contains the
added assembler modifications like add64 overloads and any carry/borrow
alterations unless you create a new, properly scoped commit).

In `@Source/JavaScriptCore/offlineasm/instructions.rb`:
- Around line 352-390: The change touches opcode tables X86_INSTRUCTIONS and
X86_SIMD_INSTRUCTIONS which breaks a config-only bisect; revert the
modifications to those symbols in this bisect slice (undo the added/removed
entries in X86_INSTRUCTIONS and keep X86_SIMD_INSTRUCTIONS unchanged) and move
the opcode-table edits into a separate commit/step, or remove this file from the
current bisect so the slice remains config-only; ensure the separate commit
clearly contains only the X86_INSTRUCTIONS/X86_SIMD_INSTRUCTIONS edits.

In `@Source/JavaScriptCore/wasm/WasmIPIntSlowPaths.cpp`:
- Around line 478-492: The rethrow_exception function uses the same indexing
pattern as other handlers but takes IPIntStackEntry* pl, causing a type
inconsistency; change the parameter type to IPIntLocal* pl in rethrow_exception
(and update the corresponding declaration in the header) to match
retrieve_and_clear_exception, retrieve_clear_and_push_exception, and
retrieve_clear_and_push_exception_and_arguments, while keeping the same access
expression pl[callee->localSizeToAlloc() + tryDepth - 1] (ensure IPIntLocal and
IPIntStackEntry are compatible before switching and adjust the header prototype
accordingly).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e8a98750-93a6-4148-a904-939fabd6ba2f

📥 Commits

Reviewing files that changed from the base of the PR and between 7ab1748 and 7be90f6.

📒 Files selected for processing (33)
  • JSTests/wasm/ipint-tests/ipint-test-leb-decode.js
  • JSTests/wasm/ipint-tests/ipint-test-simd-memory.js
  • JSTests/wasm/ipint-tests/ipint-test-simd-multi-byte-leb.js
  • JSTests/wasm/stress/atomic-cmpxchg-large-offset.js
  • JSTests/wasm/stress/memory64-atomics.js
  • JSTests/wasm/stress/wide-arithmetic.js
  • Source/JavaScriptCore/assembler/MacroAssemblerARM64.h
  • Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h
  • Source/JavaScriptCore/assembler/X86Assembler.h
  • Source/JavaScriptCore/llint/InPlaceInterpreter.asm
  • Source/JavaScriptCore/llint/InPlaceInterpreter.cpp
  • Source/JavaScriptCore/llint/InPlaceInterpreter.h
  • Source/JavaScriptCore/llint/InPlaceInterpreter64.asm
  • Source/JavaScriptCore/offlineasm/arm64.rb
  • Source/JavaScriptCore/offlineasm/instructions.rb
  • Source/JavaScriptCore/offlineasm/x86.rb
  • Source/JavaScriptCore/wasm/WasmBBQJIT.cpp
  • Source/JavaScriptCore/wasm/WasmBBQJIT.h
  • Source/JavaScriptCore/wasm/WasmBBQJIT64.cpp
  • Source/JavaScriptCore/wasm/WasmConstExprGenerator.cpp
  • Source/JavaScriptCore/wasm/WasmFunctionIPIntMetadataGenerator.cpp
  • Source/JavaScriptCore/wasm/WasmFunctionIPIntMetadataGenerator.h
  • Source/JavaScriptCore/wasm/WasmFunctionParser.h
  • Source/JavaScriptCore/wasm/WasmIPIntGenerator.cpp
  • Source/JavaScriptCore/wasm/WasmIPIntGenerator.h
  • Source/JavaScriptCore/wasm/WasmIPIntSlowPaths.cpp
  • Source/JavaScriptCore/wasm/WasmIPIntSlowPaths.h
  • Source/JavaScriptCore/wasm/WasmOMGIRGenerator.cpp
  • Source/JavaScriptCore/wasm/debugger/WasmDebugServerUtilities.cpp
  • Source/JavaScriptCore/wasm/debugger/WasmDebugServerUtilities.h
  • Source/JavaScriptCore/wasm/debugger/WasmExecutionHandler.cpp
  • Source/JavaScriptCore/wasm/debugger/WasmExecutionHandler.h
  • Source/JavaScriptCore/wasm/debugger/WasmQueryHandler.cpp
💤 Files with no reviewable changes (14)
  • JSTests/wasm/ipint-tests/ipint-test-simd-multi-byte-leb.js
  • JSTests/wasm/ipint-tests/ipint-test-leb-decode.js
  • JSTests/wasm/ipint-tests/ipint-test-simd-memory.js
  • Source/JavaScriptCore/offlineasm/x86.rb
  • JSTests/wasm/stress/memory64-atomics.js
  • Source/JavaScriptCore/wasm/WasmConstExprGenerator.cpp
  • Source/JavaScriptCore/offlineasm/arm64.rb
  • JSTests/wasm/stress/wide-arithmetic.js
  • Source/JavaScriptCore/assembler/X86Assembler.h
  • JSTests/wasm/stress/atomic-cmpxchg-large-offset.js
  • Source/JavaScriptCore/wasm/WasmOMGIRGenerator.cpp
  • Source/JavaScriptCore/wasm/WasmFunctionParser.h
  • Source/JavaScriptCore/assembler/MacroAssemblerARM64.h
  • Source/JavaScriptCore/wasm/WasmBBQJIT64.cpp

Comment on lines +1034 to 1037
Value BBQJIT::topValue(TypeKind type)
{
return Value::fromTemp(type, currentControlData().enclosedHeight() + currentControlData().implicitSlots() + m_parser->expressionStack().size() + offset);
return Value::fromTemp(type, currentControlData().enclosedHeight() + currentControlData().implicitSlots() + m_parser->expressionStack().size());
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Don't change BBQ temp indexing on a config-only bisect branch.

Lines 1034-1037 and Line 4333 alter how BBQ materializes temp indices for values and call results. The PR objective explicitly says BBQ/OMG/IPInt generator code should stay at the working commit, so this behavior change invalidates the bisect's isolation even if the new indexing is internally consistent.

Also applies to: 4333-4333

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Source/JavaScriptCore/wasm/WasmBBQJIT.cpp` around lines 1034 - 1037, The
change altered BBQ temporary indexing logic in BBQJIT::topValue (and the related
change at the call-result materialization around the other modified spot) which
must not be changed on this config-only bisect branch; restore the original
temp-index computation by reverting the modified expression that constructs
Value::fromTemp (i.e., remove the new addition/subtraction of
enclosedHeight()/implicitSlots()/expressionStack().size() logic) and reintroduce
the previous indexing expression used for temp/materialized call results so BBQ
temp indexing remains identical to the working commit (ensure you update both
BBQJIT::topValue and the other call-result site to the original computation).

Comment on lines +95 to +103
if (type.isI32()) {
size_t size = m_metadata.size();
if (length == 2) {
IPInt::InstructionLengthMetadata mdConst {
.length = safeCast<uint8_t>((value >> 7) & 1)
};
m_metadata.grow(size + sizeof(mdConst));
WRITE_TO_METADATA(m_metadata.mutableSpan().data() + size, mdConst, IPInt::InstructionLengthMetadata);
} else {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n -C3 'InstructionLengthMetadata|Const32Metadata|I32Const|i32\.const|\.length\b' Source/JavaScriptCore/wasm

Repository: oven-sh/WebKit

Length of output: 50370


🏁 Script executed:

find Source/JavaScriptCore/wasm -name "*IPInt*" -type f | head -20

Repository: oven-sh/WebKit

Length of output: 523


🏁 Script executed:

rg -n "InstructionLengthMetadata" Source/JavaScriptCore/wasm/WasmIPIntGenerator.cpp -A 5 -B 2 | head -100

Repository: oven-sh/WebKit

Length of output: 417


🏁 Script executed:

rg -n "\.length\s*=" Source/JavaScriptCore/wasm/WasmIPIntGenerator.cpp | grep -i "metadata\|instruction" | head -20

Repository: oven-sh/WebKit

Length of output: 1475


🏁 Script executed:

rg -n "i32\.const|addLEB128ConstantAndLengthForType" Source/JavaScriptCore/wasm/WasmIPIntGenerator.cpp -B 3 -A 10 | head -150

Repository: oven-sh/WebKit

Length of output: 1347


🏁 Script executed:

rg -n "InstructionLengthMetadata\|addLEB128ConstantAndLengthForType" Source/JavaScriptCore/wasm/WasmIPIntSlowPaths.cpp -B 3 -A 8 | head -120

Repository: oven-sh/WebKit

Length of output: 40


🏁 Script executed:

rg -n "metadata.*\.length|\.length.*metadata" Source/JavaScriptCore/wasm/ --type cpp | head -30

Repository: oven-sh/WebKit

Length of output: 40


🏁 Script executed:

rg -n "struct.*Metadata|class.*Metadata" Source/JavaScriptCore/wasm/ -A 5 | grep -A 5 "InstructionLengthMetadata\|Const32Metadata"

Repository: oven-sh/WebKit

Length of output: 8483


🏁 Script executed:

rg -n "op.i32Const\|case.*0x41\|OpType::I32Const" Source/JavaScriptCore/wasm/WasmIPIntGenerator.cpp -B 2 -A 15 | head -80

Repository: oven-sh/WebKit

Length of output: 40


🏁 Script executed:

find Source/JavaScriptCore/wasm -name "*.h" -exec grep -l "InstructionLengthMetadata\|IPInt" {} \; | head -10

Repository: oven-sh/WebKit

Length of output: 1130


🏁 Script executed:

rg -n "read.*Metadata\|advance.*metadata\|metadata.*read\|load.*Metadata" Source/JavaScriptCore/wasm/WasmIPIntGenerator.cpp -A 3 -B 1 | head -100

Repository: oven-sh/WebKit

Length of output: 40


🏁 Script executed:

rg -n "metadataPtr|metadata\[|\.length" Source/JavaScriptCore/wasm/WasmIPIntGenerator.cpp | grep -v "getCurrentInstructionLength\|addLength" | head -50

Repository: oven-sh/WebKit

Length of output: 40


🏁 Script executed:

cat Source/JavaScriptCore/wasm/WasmIPIntGenerator.h | sed -n '142,157p'

Repository: oven-sh/WebKit

Length of output: 490


🏁 Script executed:

rg -n "Const32Metadata|short.*i32\|small.*const" Source/JavaScriptCore/wasm/WasmIPIntGenerator.cpp -B 3 -A 8 | head -120

Repository: oven-sh/WebKit

Length of output: 40


🏁 Script executed:

rg -n "\.instructionLength|InstructionLengthMetadata" Source/JavaScriptCore/wasm/WasmIPIntGenerator.cpp | grep -v "\.instructionLength = " | head -40

Repository: oven-sh/WebKit

Length of output: 159


🏁 Script executed:

rg -n "i32.*const|0x41" Source/JavaScriptCore/wasm/WasmIPIntGenerator.cpp -B 5 -A 10 | grep -A 15 "addConstant"

Repository: oven-sh/WebKit

Length of output: 40


🏁 Script executed:

rg -n "addConstant" Source/JavaScriptCore/wasm/WasmIPIntGenerator.cpp -B 2 -A 8

Repository: oven-sh/WebKit

Length of output: 974


Fix .length field for short-i32.const to store instruction length, not constant bits.

The fast path at lines 98–103 writes InstructionLengthMetadata with .length = safeCast<uint8_t>((value >> 7) & 1), storing a bit from the constant value instead of the actual instruction length. All other paths in the same function correctly store the actual length. The metadata structure is documented as carrying "length of current instruction" and the design comment indicates the value is embedded in bytecode while metadata holds only the instruction length. Using constant bits instead breaks this contract.

Proposed fix
         if (length == 2) {
             IPInt::InstructionLengthMetadata mdConst {
-                .length = safeCast<uint8_t>((value >> 7) & 1)
+                .length = safeCast<uint8_t>(length)
             };
             m_metadata.grow(size + sizeof(mdConst));
             WRITE_TO_METADATA(m_metadata.mutableSpan().data() + size, mdConst, IPInt::InstructionLengthMetadata);
         } else {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (type.isI32()) {
size_t size = m_metadata.size();
if (length == 2) {
IPInt::InstructionLengthMetadata mdConst {
.length = safeCast<uint8_t>((value >> 7) & 1)
};
m_metadata.grow(size + sizeof(mdConst));
WRITE_TO_METADATA(m_metadata.mutableSpan().data() + size, mdConst, IPInt::InstructionLengthMetadata);
} else {
if (type.isI32()) {
size_t size = m_metadata.size();
if (length == 2) {
IPInt::InstructionLengthMetadata mdConst {
.length = safeCast<uint8_t>(length)
};
m_metadata.grow(size + sizeof(mdConst));
WRITE_TO_METADATA(m_metadata.mutableSpan().data() + size, mdConst, IPInt::InstructionLengthMetadata);
} else {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Source/JavaScriptCore/wasm/WasmFunctionIPIntMetadataGenerator.cpp` around
lines 95 - 103, The IPInt::InstructionLengthMetadata written in
WasmFunctionIPIntMetadataGenerator.cpp's fast path incorrectly stores a bit from
the constant into .length; change the .length assignment in the short-i32.const
branch to store the actual instruction length (use safeCast<uint8_t>(length))
instead of safeCast<uint8_t>((value >> 7) & 1), so that the metadata (written
via m_metadata.grow and WRITE_TO_METADATA) consistently records the instruction
length for IPInt::InstructionLengthMetadata.

Comment on lines 728 to 733
[[nodiscard]] PartialResult IPIntGenerator::addSIMDShuffle(v128_t, ExpressionType, ExpressionType, ExpressionType&)
{
changeStackSize(-1);
m_metadata->addLength(getCurrentInstructionLength());
return { };
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Vector-immediate metadata is still not emitted.

Const128Metadata and addLEB128V128Constant() were added, but both vector-immediate producers here still write only instruction length. That leaves the new 128-bit metadata path unused and drops the payload for v128.const / shuffle-mask immediates.

Proposed fix
-[[nodiscard]] PartialResult IPIntGenerator::addSIMDShuffle(v128_t, ExpressionType, ExpressionType, ExpressionType&)
+[[nodiscard]] PartialResult IPIntGenerator::addSIMDShuffle(v128_t value, ExpressionType, ExpressionType, ExpressionType&)
 {
     changeStackSize(-1);
-    m_metadata->addLength(getCurrentInstructionLength());
+    m_metadata->addLEB128V128Constant(value, getCurrentInstructionLength());
     return { };
 }
@@
-IPIntGenerator::ExpressionType IPIntGenerator::addSIMDConstant(v128_t)
+IPIntGenerator::ExpressionType IPIntGenerator::addSIMDConstant(v128_t value)
 {
     changeStackSize(1);
-    m_metadata->addLength(getCurrentInstructionLength());
+    m_metadata->addLEB128V128Constant(value, getCurrentInstructionLength());
     return { };
 }

Also applies to: 780-784

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Source/JavaScriptCore/wasm/WasmIPIntGenerator.cpp` around lines 728 - 733,
The vector-immediate producers (e.g., IPIntGenerator::addSIMDShuffle and the
similar function at the 780-784 region) currently only record instruction length
and do not emit the new 128-bit metadata or payload; update these functions to
create and append Const128Metadata and call addLEB128V128Constant() with the
v128 immediate (the 128-bit shuffle mask or v128.const value) before/when
calling m_metadata->addLength/getCurrentInstructionLength(), so the
Const128Metadata is emitted and the payload written using
addLEB128V128Constant(); reference the symbols IPIntGenerator::addSIMDShuffle,
Const128Metadata, and addLEB128V128Constant when making the changes.

@github-actions

Copy link
Copy Markdown

Preview Builds

Commit Release Date
7be90f69 autobuild-preview-pr-192-7be90f69 2026-04-23 00:56:49 UTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants