Commit 5855e44c authored by jpp's avatar jpp Committed by Commit bot

[V8][Wasm] Wasm throws.

This CL implements the throw wasm opcode. This is a pre-requisite for
implementing try-catches in wasm.

BUG=

Review-Url: https://codereview.chromium.org/2339053003
Cr-Commit-Position: refs/heads/master@{#39449}
parent c2cf8b11
......@@ -1703,6 +1703,29 @@ Node* WasmGraphBuilder::GrowMemory(Node* input) {
return result;
}
Node* WasmGraphBuilder::Throw(Node* input) {
MachineOperatorBuilder* machine = jsgraph()->machine();
// Pass the thrown value as two SMIs:
//
// upper = static_cast<uint32_t>(input) >> 16;
// lower = input & 0xFFFF;
//
// This is needed because we can't safely call BuildChangeInt32ToTagged from
// this method.
//
// TODO(wasm): figure out how to properly pass this to the runtime function.
Node* upper = BuildChangeInt32ToSmi(
graph()->NewNode(machine->Word32Shr(), input, Int32Constant(16)));
Node* lower = BuildChangeInt32ToSmi(
graph()->NewNode(machine->Word32And(), input, Int32Constant(0xFFFFu)));
Node* parameters[] = {lower, upper}; // thrown value
return BuildCallToRuntime(Runtime::kWasmThrow, jsgraph(),
module_->instance->context, parameters,
arraysize(parameters), effect_, *control_);
}
Node* WasmGraphBuilder::BuildI32DivS(Node* left, Node* right,
wasm::WasmCodePosition position) {
MachineOperatorBuilder* m = jsgraph()->machine();
......
......@@ -134,6 +134,7 @@ class WasmGraphBuilder {
Node* Unop(wasm::WasmOpcode opcode, Node* input,
wasm::WasmCodePosition position = wasm::kNoCodePosition);
Node* GrowMemory(Node* input);
Node* Throw(Node* input);
unsigned InputCount(Node* node);
bool IsPhiWithMerge(Node* phi, Node* merge);
void AppendToMerge(Node* merge, Node* from);
......@@ -306,6 +307,7 @@ class WasmGraphBuilder {
Node* BuildJavaScriptToNumber(Node* node, Node* context, Node* effect,
Node* control);
Node* BuildChangeInt32ToTagged(Node* value);
Node* BuildChangeFloat64ToTagged(Node* value);
Node* BuildChangeTaggedToFloat64(Node* value);
......
......@@ -21,8 +21,7 @@ namespace internal {
RUNTIME_FUNCTION(Runtime_WasmGrowMemory) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
uint32_t delta_pages = 0;
CHECK(args[0]->ToUint32(&delta_pages));
CONVERT_UINT32_ARG_CHECKED(delta_pages, 0);
Handle<JSObject> module_instance;
{
......@@ -118,5 +117,17 @@ RUNTIME_FUNCTION(Runtime_WasmThrowTypeError) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kWasmTrapTypeError));
}
RUNTIME_FUNCTION(Runtime_WasmThrow) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_SMI_ARG_CHECKED(lower, 0);
CONVERT_SMI_ARG_CHECKED(upper, 1);
const int32_t thrown_value = (upper << 16) | lower;
return isolate->Throw(*isolate->factory()->NewNumberFromInt(thrown_value));
}
} // namespace internal
} // namespace v8
......@@ -914,7 +914,8 @@ namespace internal {
#define FOR_EACH_INTRINSIC_WASM(F) \
F(WasmGrowMemory, 1, 1) \
F(WasmThrowTypeError, 0, 1)
F(WasmThrowTypeError, 0, 1) \
F(WasmThrow, 2, 1)
#define FOR_EACH_INTRINSIC_RETURN_PAIR(F) \
F(LoadLookupSlotForCall, 1, 2)
......
......@@ -667,9 +667,8 @@ class WasmFullDecoder : public WasmDecoder {
}
case kExprThrow: {
CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype);
Pop(0, kAstI32);
// TODO(jpp): start exception propagation.
Value value = Pop(0, kAstI32);
BUILD(Throw, value.node);
break;
}
case kExprTry: {
......
// Copyright 2015 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 --wasm-eh-prototype
load("test/mjsunit/wasm/wasm-constants.js");
load("test/mjsunit/wasm/wasm-module-builder.js");
var module = (function () {
var builder = new WasmModuleBuilder();
builder.addFunction("throw_param_if_not_zero", kSig_i_i)
.addBody([
kExprGetLocal, 0,
kExprI32Const, 0,
kExprI32Ne,
kExprIf,
kExprGetLocal, 0,
kExprThrow,
kExprEnd,
kExprI32Const, 1
])
.exportFunc()
builder.addFunction("throw_20", kSig_v_v)
.addBody([
kExprI32Const, 20,
kExprThrow
])
.exportFunc()
builder.addFunction("throw_expr_with_params", kSig_v_ddi)
.addBody([
// p2 * (p0 + min(p0, p1))|0 - 20
kExprGetLocal, 2,
kExprGetLocal, 0,
kExprGetLocal, 0,
kExprGetLocal, 1,
kExprF64Min,
kExprF64Add,
kExprI32SConvertF64,
kExprI32Mul,
kExprI32Const, 20,
kExprI32Sub,
kExprThrow
])
.exportFunc()
return builder.instantiate();
})();
// Check the module exists.
assertFalse(module === undefined);
assertFalse(module === null);
assertFalse(module === 0);
assertEquals("object", typeof module.exports);
assertEquals("function", typeof module.exports.throw_param_if_not_zero);
assertEquals(1, module.exports.throw_param_if_not_zero(0));
assertWasmThrows(10, function() { module.exports.throw_param_if_not_zero(10) });
assertWasmThrows(-1, function() { module.exports.throw_param_if_not_zero(-1) });
assertWasmThrows(20, module.exports.throw_20);
assertWasmThrows(
-8, function() { module.exports.throw_expr_with_params(1.5, 2.5, 4); });
assertWasmThrows(
12, function() { module.exports.throw_expr_with_params(5.7, 2.5, 4); });
......@@ -106,6 +106,7 @@ var kSig_v_ii = makeSig([kAstI32, kAstI32], []);
var kSig_v_iii = makeSig([kAstI32, kAstI32, kAstI32], []);
var kSig_v_d = makeSig([kAstF64], []);
var kSig_v_dd = makeSig([kAstF64, kAstF64], []);
var kSig_v_ddi = makeSig([kAstF64, kAstF64, kAstI32], []);
function makeSig(params, results) {
return {params: params, results: results};
......@@ -143,6 +144,7 @@ var kExprBrIf = 0x07;
var kExprBrTable = 0x08;
var kExprReturn = 0x09;
var kExprUnreachable = 0x0a;
var kExprThrow = 0xfa;
var kExprEnd = 0x0f;
var kExprI32Const = 0x10;
......@@ -348,3 +350,20 @@ function assertTraps(trap, code) {
}
throw new MjsUnitAssertionError("Did not trap, expected: " + kTrapMsgs[trap]);
}
function assertWasmThrows(value, code) {
assertEquals("number", typeof(value));
try {
if (typeof code === 'function') {
code();
} else {
eval(code);
}
} catch (e) {
assertEquals("number", typeof e);
assertEquals(value, e);
// Success.
return;
}
throw new MjsUnitAssertionError("Did not throw at all, expected: " + value);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment