summaryrefslogtreecommitdiff
path: root/src/wasm2js.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm2js.h')
-rw-r--r--src/wasm2js.h68
1 files changed, 63 insertions, 5 deletions
diff --git a/src/wasm2js.h b/src/wasm2js.h
index 5adcdb740..3accfad75 100644
--- a/src/wasm2js.h
+++ b/src/wasm2js.h
@@ -1437,8 +1437,11 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
Ref store =
ValueBuilder::makeCall(ABI::wasm2js::SCRATCH_STORE_F32,
visit(curr->value, EXPRESSION_RESULT));
+ // 32-bit scratch memory uses index 2, so that it does not
+ // conflict with indexes 0, 1 which are used for 64-bit, see
+ // comment where |scratchBuffer| is defined.
Ref load = ValueBuilder::makeCall(ABI::wasm2js::SCRATCH_LOAD_I32,
- ValueBuilder::makeInt(0));
+ ValueBuilder::makeInt(2));
return ValueBuilder::makeSeq(store, load);
}
// generate (~~expr), what Emscripten does
@@ -1528,9 +1531,12 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
ABI::wasm2js::ensureHelpers(module,
ABI::wasm2js::SCRATCH_LOAD_F32);
+ // 32-bit scratch memory uses index 2, so that it does not
+ // conflict with indexes 0, 1 which are used for 64-bit, see
+ // comment where |scratchBuffer| is defined.
Ref store =
ValueBuilder::makeCall(ABI::wasm2js::SCRATCH_STORE_I32,
- ValueBuilder::makeNum(0),
+ ValueBuilder::makeNum(2),
visit(curr->value, EXPRESSION_RESULT));
Ref load = ValueBuilder::makeCall(ABI::wasm2js::SCRATCH_LOAD_F32);
return ValueBuilder::makeSeq(store, load);
@@ -2462,8 +2468,60 @@ void Wasm2JSGlue::emitSpecialSupport() {
return;
}
+ // Scratch memory uses 3 indexes, each referring to 4 bytes. Indexes 0, 1 are
+ // used for 64-bit operations, while 2 is for 32-bit. These operations need
+ // separate indexes because we need to handle the case where the optimizer
+ // reorders a 32-bit reinterpret in between a 64-bit's split-out parts.
+ // That situation can occur because the 64-bit reinterpret was split up into
+ // pieces early, in the 64-bit lowering pass, while the 32-bit reinterprets
+ // are lowered only at the very end, and until then the optimizer sees wasm
+ // reinterprets which have no side effects (but they will have the side effect
+ // of altering scratch memory). That is, conceptual code like this:
+ //
+ // a = reinterpret_64(b)
+ // x = reinterpret_32(y)
+ //
+ // turns into
+ //
+ // scratch_write(b)
+ // a_low = scratch_read(0)
+ // a_high = scratch_read(1)
+ // x = reinterpret_32(y)
+ //
+ // (Note how the single wasm instruction for a 64-bit reinterpret turns into
+ // multiple operations. We have to do such splitting, because in JS we will
+ // have to have separate operations to receive each 32-bit chunk anyhow. A
+ // *32*-bit reinterpret *could* be a single function, but given we have the
+ // separate functions anyhow for the 64-bit case, it's more compact to reuse
+ // those.)
+ // At this point, the scratch_* functions look like they have side effects to
+ // the optimizer (which is true, as they modify scratch memory), but the
+ // reinterpret_32 is still a normal wasm instruction without side effects, so
+ // the optimizer might do this:
+ //
+ // scratch_write(b)
+ // a_low = scratch_read(0)
+ // x = reinterpret_32(y) ;; this moved one line up
+ // a_high = scratch_read(1)
+ //
+ // When we do lower the reinterpret_32 into JS, we get:
+ //
+ // scratch_write(b)
+ // a_low = scratch_read(0)
+ // scratch_write(y)
+ // x = scratch_read()
+ // a_high = scratch_read(1)
+ //
+ // The second write occurs before the first's values have been read, so they
+ // interfere.
+ //
+ // There isn't a problem with reordering 32-bit reinterprets with each other
+ // as each is lowered into a pair of write+read in JS (after the wasm
+ // optimizer runs), so they are guaranteed to be adjacent (and a JS optimizer
+ // that runs later will handle that ok since they are calls, which can always
+ // have side effects).
out << R"(
- var scratchBuffer = new ArrayBuffer(8);
+ var scratchBuffer = new ArrayBuffer(16);
var i32ScratchView = new Int32Array(scratchBuffer);
var f32ScratchView = new Float32Array(scratchBuffer);
var f64ScratchView = new Float64Array(scratchBuffer);
@@ -2494,13 +2552,13 @@ void Wasm2JSGlue::emitSpecialSupport() {
} else if (import->base == ABI::wasm2js::SCRATCH_STORE_F32) {
out << R"(
function wasm2js_scratch_store_f32(value) {
- f32ScratchView[0] = value;
+ f32ScratchView[2] = value;
}
)";
} else if (import->base == ABI::wasm2js::SCRATCH_LOAD_F32) {
out << R"(
function wasm2js_scratch_load_f32() {
- return f32ScratchView[0];
+ return f32ScratchView[2];
}
)";
} else if (import->base == ABI::wasm2js::SCRATCH_STORE_F64) {