Skip to content

Issue 139 - #141

Draft
andreaTP wants to merge 3 commits into
bytecodealliance:mainfrom
andreaTP:issue-139
Draft

Issue 139#141
andreaTP wants to merge 3 commits into
bytecodealliance:mainfrom
andreaTP:issue-139

Conversation

@andreaTP

@andreaTP andreaTP commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Fix #139

to be reviewed

…#139)

computeMaxTempSlots was missing STRUCT_NEW, THROW, ARRAY_NEW_FIXED,
and CALL (hasTooManyParameters). When these instructions appeared
inside a try_table body, their temp slot usage overflowed into the
try-save area, corrupting saved GC ref values.

In the Kotlin/Wasm reproducer, struct.new inside a try_table overwrote
the try-save slot holding a String literal with an RTTI struct,
causing String.plus to receive the wrong reference and eventually
array.len to trap on a null array.
…itters

Replace the manually-maintained computeMaxTempSlots switch in
WasmAnalyzer with a data-driven approach. Each emitter that uses
temp slots now declares a TempSlotCalculator at registration time
in EmitterMap. This makes it impossible to add a new temp-slot-using
opcode without also declaring its slot requirement.

- Add TempSlotCalculator interface to Emitters
- Extend Builder.intrinsic() with a 3-arg overload
- Move all slot calculations from WasmAnalyzer switch to EmitterMap
- Replace 140-line switch with 10-line generic loop
- Keep assertTempSlotInRange runtime guard as safety net
The Kotlin/Wasm module uses non-canonical LEB128 size encodings
from the Kotlin compiler, similar to main.go.wasm.

@andreaTP andreaTP left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Almost ready, the testing is solid but the implementation needs a little tweak for human(and machine) readability.

.intrinsic(
CompilerOpCode.DROP_KEEP,
Emitters::DROP_KEEP,
(ins, module) -> {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Counting temp slots in lambdas and inline clutter readability and seems to mix concerns

.intrinsic(
CompilerOpCode.BR_ON_CAST_FAIL_CHECK, Emitters::BR_ON_CAST_FAIL_CHECK)
.build();
private static FunctionType resolveTagType(int tagIdx, WasmModule module) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

do we have something similar somewhere else in the codebase?

return ValType.builder().fromId(id).build().resolve(ctx.typeSection());
}

private static void assertTempSlotInRange(Context ctx, int slotsNeeded) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is a clear indication for developers, we should make sure this doesn't spill to user land in absence of bugs.

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.

Compiler traps on array.len of a null array where the interpreter runs the same module fine (Kotlin/Wasm)

1 participant