[wasm] Introduce the TrapIf and TrapUnless operators to generate trap code.
Some instructions in WebAssembly trap for some inputs, which means that the
execution is terminated and (at least at the moment) a JavaScript exception is
thrown. Examples for traps are out-of-bounds memory accesses, or integer
divisions by zero.
Without the TrapIf and TrapUnless operators trap check in WebAssembly introduces 5
TurboFan nodes (branch, if_true, if_false, trap-reason constant, trap-position
constant), in addition to the trap condition itself. Additionally, each
WebAssembly function has four TurboFan nodes (merge, effect_phi, 2 phis) whose
number of inputs is linear to the number of trap checks in the function.
Especially for functions with high numbers of trap checks we observe a
significant slowdown in compilation time, down to 0.22 MiB/s in the sqlite
benchmark instead of the average of 3 MiB/s in other benchmarks. By introducing
a TrapIf common operator only a single node is necessary per trap check, in
addition to the trap condition. Also the nodes which are shared between trap
checks (merge, effect_phi, 2 phis) would disappear. First measurements suggest a
speedup of 30-50% on average.
This CL only implements TrapIf and TrapUnless on x64. The implementation is also
hidden behind the --wasm-trap-if flag.
Please take a special look at how the source position is transfered from the
instruction selector to the code generator, and at the context that is used for
the runtime call.
R=titzer@chromium.org
Review-Url: https://codereview.chromium.org/2562393002
Cr-Commit-Position: refs/heads/master@{#41720}
2016-12-15 13:31:29 +00:00
|
|
|
// Copyright 2016 the V8 project authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
|
|
|
// Flags: --expose-wasm --trap-if
|
|
|
|
|
|
|
|
load("test/mjsunit/wasm/wasm-constants.js");
|
|
|
|
load("test/mjsunit/wasm/wasm-module-builder.js");
|
|
|
|
|
|
|
|
// Collect the Callsite objects instead of just a string:
|
|
|
|
Error.prepareStackTrace = function(error, frames) {
|
|
|
|
return frames;
|
|
|
|
};
|
|
|
|
|
|
|
|
var builder = new WasmModuleBuilder();
|
|
|
|
|
|
|
|
var sig_index = builder.addType(kSig_i_v)
|
|
|
|
|
|
|
|
// Build a function to resemble this code:
|
|
|
|
// if (idx < 2) {
|
|
|
|
// return load(-2 / idx);
|
|
|
|
// } else if (idx == 2) {
|
|
|
|
// unreachable;
|
|
|
|
// } else {
|
|
|
|
// return call_indirect(idx);
|
|
|
|
// }
|
|
|
|
// There are four different traps which are triggered by different input values:
|
|
|
|
// (0) division by zero; (1) mem oob; (2) unreachable; (3) invalid call target
|
|
|
|
// Each of them also has a different location where it traps.
|
|
|
|
builder.addFunction("main", kSig_i_i)
|
|
|
|
.addBody([
|
|
|
|
// offset 1
|
2016-12-21 13:43:00 +00:00
|
|
|
kExprBlock, kWasmI32,
|
[wasm] Introduce the TrapIf and TrapUnless operators to generate trap code.
Some instructions in WebAssembly trap for some inputs, which means that the
execution is terminated and (at least at the moment) a JavaScript exception is
thrown. Examples for traps are out-of-bounds memory accesses, or integer
divisions by zero.
Without the TrapIf and TrapUnless operators trap check in WebAssembly introduces 5
TurboFan nodes (branch, if_true, if_false, trap-reason constant, trap-position
constant), in addition to the trap condition itself. Additionally, each
WebAssembly function has four TurboFan nodes (merge, effect_phi, 2 phis) whose
number of inputs is linear to the number of trap checks in the function.
Especially for functions with high numbers of trap checks we observe a
significant slowdown in compilation time, down to 0.22 MiB/s in the sqlite
benchmark instead of the average of 3 MiB/s in other benchmarks. By introducing
a TrapIf common operator only a single node is necessary per trap check, in
addition to the trap condition. Also the nodes which are shared between trap
checks (merge, effect_phi, 2 phis) would disappear. First measurements suggest a
speedup of 30-50% on average.
This CL only implements TrapIf and TrapUnless on x64. The implementation is also
hidden behind the --wasm-trap-if flag.
Please take a special look at how the source position is transfered from the
instruction selector to the code generator, and at the context that is used for
the runtime call.
R=titzer@chromium.org
Review-Url: https://codereview.chromium.org/2562393002
Cr-Commit-Position: refs/heads/master@{#41720}
2016-12-15 13:31:29 +00:00
|
|
|
kExprGetLocal, 0,
|
|
|
|
kExprI32Const, 2,
|
|
|
|
kExprI32LtU,
|
2016-12-21 13:43:00 +00:00
|
|
|
kExprIf, kWasmStmt,
|
[wasm] Introduce the TrapIf and TrapUnless operators to generate trap code.
Some instructions in WebAssembly trap for some inputs, which means that the
execution is terminated and (at least at the moment) a JavaScript exception is
thrown. Examples for traps are out-of-bounds memory accesses, or integer
divisions by zero.
Without the TrapIf and TrapUnless operators trap check in WebAssembly introduces 5
TurboFan nodes (branch, if_true, if_false, trap-reason constant, trap-position
constant), in addition to the trap condition itself. Additionally, each
WebAssembly function has four TurboFan nodes (merge, effect_phi, 2 phis) whose
number of inputs is linear to the number of trap checks in the function.
Especially for functions with high numbers of trap checks we observe a
significant slowdown in compilation time, down to 0.22 MiB/s in the sqlite
benchmark instead of the average of 3 MiB/s in other benchmarks. By introducing
a TrapIf common operator only a single node is necessary per trap check, in
addition to the trap condition. Also the nodes which are shared between trap
checks (merge, effect_phi, 2 phis) would disappear. First measurements suggest a
speedup of 30-50% on average.
This CL only implements TrapIf and TrapUnless on x64. The implementation is also
hidden behind the --wasm-trap-if flag.
Please take a special look at how the source position is transfered from the
instruction selector to the code generator, and at the context that is used for
the runtime call.
R=titzer@chromium.org
Review-Url: https://codereview.chromium.org/2562393002
Cr-Commit-Position: refs/heads/master@{#41720}
2016-12-15 13:31:29 +00:00
|
|
|
// offset 9
|
|
|
|
kExprI32Const, 0x7e /* -2 */,
|
|
|
|
kExprGetLocal, 0,
|
|
|
|
kExprI32DivU,
|
|
|
|
// offset 15
|
|
|
|
kExprI32LoadMem, 0, 0,
|
|
|
|
kExprBr, 1,
|
|
|
|
kExprEnd,
|
|
|
|
// offset 21
|
|
|
|
kExprGetLocal, 0,
|
|
|
|
kExprI32Const, 2,
|
|
|
|
kExprI32Eq,
|
2016-12-21 13:43:00 +00:00
|
|
|
kExprIf, kWasmStmt,
|
[wasm] Introduce the TrapIf and TrapUnless operators to generate trap code.
Some instructions in WebAssembly trap for some inputs, which means that the
execution is terminated and (at least at the moment) a JavaScript exception is
thrown. Examples for traps are out-of-bounds memory accesses, or integer
divisions by zero.
Without the TrapIf and TrapUnless operators trap check in WebAssembly introduces 5
TurboFan nodes (branch, if_true, if_false, trap-reason constant, trap-position
constant), in addition to the trap condition itself. Additionally, each
WebAssembly function has four TurboFan nodes (merge, effect_phi, 2 phis) whose
number of inputs is linear to the number of trap checks in the function.
Especially for functions with high numbers of trap checks we observe a
significant slowdown in compilation time, down to 0.22 MiB/s in the sqlite
benchmark instead of the average of 3 MiB/s in other benchmarks. By introducing
a TrapIf common operator only a single node is necessary per trap check, in
addition to the trap condition. Also the nodes which are shared between trap
checks (merge, effect_phi, 2 phis) would disappear. First measurements suggest a
speedup of 30-50% on average.
This CL only implements TrapIf and TrapUnless on x64. The implementation is also
hidden behind the --wasm-trap-if flag.
Please take a special look at how the source position is transfered from the
instruction selector to the code generator, and at the context that is used for
the runtime call.
R=titzer@chromium.org
Review-Url: https://codereview.chromium.org/2562393002
Cr-Commit-Position: refs/heads/master@{#41720}
2016-12-15 13:31:29 +00:00
|
|
|
kExprUnreachable,
|
|
|
|
kExprEnd,
|
|
|
|
// offset 30
|
|
|
|
kExprGetLocal, 0,
|
|
|
|
kExprCallIndirect, sig_index, kTableZero,
|
|
|
|
kExprEnd,
|
|
|
|
])
|
|
|
|
.exportAs("main");
|
|
|
|
builder.appendToTable([0]);
|
|
|
|
|
|
|
|
var module = builder.instantiate();
|
|
|
|
|
|
|
|
function testWasmTrap(value, reason, position) {
|
|
|
|
try {
|
|
|
|
module.exports.main(value);
|
|
|
|
fail("expected wasm exception");
|
|
|
|
} catch (e) {
|
|
|
|
assertEquals(kTrapMsgs[reason], e.message, "trap reason");
|
|
|
|
assertEquals(3, e.stack.length, "number of frames");
|
|
|
|
assertEquals(0, e.stack[0].getLineNumber(), "wasmFunctionIndex");
|
|
|
|
assertEquals(position, e.stack[0].getPosition(), "position");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// The actual tests:
|
|
|
|
testWasmTrap(0, kTrapDivByZero, 14);
|
|
|
|
testWasmTrap(1, kTrapMemOutOfBounds, 15);
|
|
|
|
testWasmTrap(2, kTrapUnreachable, 28);
|
|
|
|
testWasmTrap(3, kTrapFuncInvalid, 32);
|