[wasm] Add support for 'except_ref' value type.
This adds experimental support for an 'except_ref' value type for caught exceptions as per the exception handling proposal. In the current for it is only allowed to have such types in the stack or in a local, support for having it as part of any signature was left out. The default value for a local of type 'except_ref' is the 'ref_null' value for now. Since this value cannot escape a wasm function, the concrete value is not actually observable. R=ahaas@chromium.org TEST=unittests/LocalDeclDecoderTest.ExceptRef,mjsunit/wasm/exceptions BUG=v8:8091 Change-Id: I7bd65274327a833262f8749cbe0e24e737f6e0c1 Reviewed-on: https://chromium-review.googlesource.com/1196510 Reviewed-by: Andreas Haas <ahaas@chromium.org> Commit-Queue: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#55526}
This commit is contained in:
parent
b9540d447f
commit
f19a70681d
@ -737,6 +737,13 @@ class WasmDecoder : public Decoder {
|
|||||||
}
|
}
|
||||||
decoder->error(decoder->pc() - 1, "invalid local type");
|
decoder->error(decoder->pc() - 1, "invalid local type");
|
||||||
return false;
|
return false;
|
||||||
|
case kLocalExceptRef:
|
||||||
|
if (enabled.eh) {
|
||||||
|
type = kWasmExceptRef;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
decoder->error(decoder->pc() - 1, "invalid local type");
|
||||||
|
return false;
|
||||||
case kLocalS128:
|
case kLocalS128:
|
||||||
if (enabled.simd) {
|
if (enabled.simd) {
|
||||||
type = kWasmS128;
|
type = kWasmS128;
|
||||||
|
@ -99,6 +99,12 @@ class WasmGraphBuildingInterface {
|
|||||||
// instance parameter.
|
// instance parameter.
|
||||||
TFNode* start = builder_->Start(
|
TFNode* start = builder_->Start(
|
||||||
static_cast<int>(decoder->sig_->parameter_count() + 1 + 1));
|
static_cast<int>(decoder->sig_->parameter_count() + 1 + 1));
|
||||||
|
ssa_env->effect = start;
|
||||||
|
ssa_env->control = start;
|
||||||
|
// Initialize effect and control before initializing the locals default
|
||||||
|
// values (which might require instance loads) or loading the context.
|
||||||
|
builder_->set_effect_ptr(&ssa_env->effect);
|
||||||
|
builder_->set_control_ptr(&ssa_env->control);
|
||||||
// Initialize the instance parameter (index 0).
|
// Initialize the instance parameter (index 0).
|
||||||
builder_->set_instance_node(builder_->Param(kWasmInstanceParameterIndex));
|
builder_->set_instance_node(builder_->Param(kWasmInstanceParameterIndex));
|
||||||
// Initialize local variables. Parameters are shifted by 1 because of the
|
// Initialize local variables. Parameters are shifted by 1 because of the
|
||||||
@ -115,11 +121,6 @@ class WasmGraphBuildingInterface {
|
|||||||
ssa_env->locals[index++] = node;
|
ssa_env->locals[index++] = node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ssa_env->effect = start;
|
|
||||||
ssa_env->control = start;
|
|
||||||
// Initialize effect and control before loading the context.
|
|
||||||
builder_->set_effect_ptr(&ssa_env->effect);
|
|
||||||
builder_->set_control_ptr(&ssa_env->control);
|
|
||||||
LoadContextIntoSsa(ssa_env);
|
LoadContextIntoSsa(ssa_env);
|
||||||
SetEnv(ssa_env);
|
SetEnv(ssa_env);
|
||||||
}
|
}
|
||||||
@ -596,6 +597,8 @@ class WasmGraphBuildingInterface {
|
|||||||
return builder_->Float64Constant(0);
|
return builder_->Float64Constant(0);
|
||||||
case kWasmS128:
|
case kWasmS128:
|
||||||
return builder_->S128Zero();
|
return builder_->S128Zero();
|
||||||
|
case kWasmExceptRef:
|
||||||
|
return builder_->RefNull();
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ enum ValueType : uint8_t {
|
|||||||
kWasmS128,
|
kWasmS128,
|
||||||
kWasmAnyRef,
|
kWasmAnyRef,
|
||||||
kWasmAnyFunc,
|
kWasmAnyFunc,
|
||||||
|
kWasmExceptRef,
|
||||||
kWasmVar,
|
kWasmVar,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -220,6 +221,8 @@ class V8_EXPORT_PRIVATE ValueTypes {
|
|||||||
return kLocalS128;
|
return kLocalS128;
|
||||||
case kWasmAnyRef:
|
case kWasmAnyRef:
|
||||||
return kLocalAnyRef;
|
return kLocalAnyRef;
|
||||||
|
case kWasmExceptRef:
|
||||||
|
return kLocalExceptRef;
|
||||||
case kWasmStmt:
|
case kWasmStmt:
|
||||||
return kLocalVoid;
|
return kLocalVoid;
|
||||||
default:
|
default:
|
||||||
|
@ -25,7 +25,8 @@ enum ValueTypeCode : uint8_t {
|
|||||||
kLocalF64 = 0x7c,
|
kLocalF64 = 0x7c,
|
||||||
kLocalS128 = 0x7b,
|
kLocalS128 = 0x7b,
|
||||||
kLocalAnyFunc = 0x70,
|
kLocalAnyFunc = 0x70,
|
||||||
kLocalAnyRef = 0x6f
|
kLocalAnyRef = 0x6f,
|
||||||
|
kLocalExceptRef = 0x68,
|
||||||
};
|
};
|
||||||
// Binary encoding of other types.
|
// Binary encoding of other types.
|
||||||
constexpr uint8_t kWasmFunctionTypeCode = 0x60;
|
constexpr uint8_t kWasmFunctionTypeCode = 0x60;
|
||||||
|
@ -7,6 +7,19 @@
|
|||||||
load("test/mjsunit/wasm/wasm-constants.js");
|
load("test/mjsunit/wasm/wasm-constants.js");
|
||||||
load("test/mjsunit/wasm/wasm-module-builder.js");
|
load("test/mjsunit/wasm/wasm-module-builder.js");
|
||||||
|
|
||||||
|
// First we just test that "except_ref" local variables are allowed.
|
||||||
|
(function TestLocalExceptRef() {
|
||||||
|
let builder = new WasmModuleBuilder();
|
||||||
|
builder.addFunction("push_and_drop_except_ref", kSig_v_v)
|
||||||
|
.addBody([
|
||||||
|
kExprGetLocal, 0,
|
||||||
|
kExprDrop,
|
||||||
|
]).addLocals({except_count: 1}).exportFunc();
|
||||||
|
let instance = builder.instantiate();
|
||||||
|
|
||||||
|
assertDoesNotThrow(instance.exports.push_and_drop_except_ref);
|
||||||
|
})();
|
||||||
|
|
||||||
// The following method doesn't attempt to catch an raised exception.
|
// The following method doesn't attempt to catch an raised exception.
|
||||||
(function TestThrowSimple() {
|
(function TestThrowSimple() {
|
||||||
let builder = new WasmModuleBuilder();
|
let builder = new WasmModuleBuilder();
|
||||||
|
@ -91,6 +91,7 @@ let kWasmF32 = 0x7d;
|
|||||||
let kWasmF64 = 0x7c;
|
let kWasmF64 = 0x7c;
|
||||||
let kWasmS128 = 0x7b;
|
let kWasmS128 = 0x7b;
|
||||||
let kWasmAnyRef = 0x6f;
|
let kWasmAnyRef = 0x6f;
|
||||||
|
let kWasmExceptRef = 0x68;
|
||||||
|
|
||||||
let kExternalFunction = 0;
|
let kExternalFunction = 0;
|
||||||
let kExternalTable = 1;
|
let kExternalTable = 1;
|
||||||
|
@ -569,6 +569,9 @@ class WasmModuleBuilder {
|
|||||||
if (l.s128_count > 0) {
|
if (l.s128_count > 0) {
|
||||||
local_decls.push({count: l.s128_count, type: kWasmS128});
|
local_decls.push({count: l.s128_count, type: kWasmS128});
|
||||||
}
|
}
|
||||||
|
if (l.except_count > 0) {
|
||||||
|
local_decls.push({count: l.except_count, type: kWasmExceptRef});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let header = new Binary;
|
let header = new Binary;
|
||||||
|
@ -3127,6 +3127,20 @@ TEST_F(LocalDeclDecoderTest, UseEncoder) {
|
|||||||
pos = ExpectRun(map, pos, kWasmI64, 212);
|
pos = ExpectRun(map, pos, kWasmI64, 212);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(LocalDeclDecoderTest, ExceptRef) {
|
||||||
|
WASM_FEATURE_SCOPE(eh);
|
||||||
|
ValueType type = kWasmExceptRef;
|
||||||
|
const byte data[] = {1, 1,
|
||||||
|
static_cast<byte>(ValueTypes::ValueTypeCodeFor(type))};
|
||||||
|
BodyLocalDecls decls(zone());
|
||||||
|
bool result = DecodeLocalDecls(&decls, data, data + sizeof(data));
|
||||||
|
EXPECT_TRUE(result);
|
||||||
|
EXPECT_EQ(1u, decls.type_list.size());
|
||||||
|
|
||||||
|
TypesOfLocals map = decls.type_list;
|
||||||
|
EXPECT_EQ(type, map[0]);
|
||||||
|
}
|
||||||
|
|
||||||
class BytecodeIteratorTest : public TestWithZone {};
|
class BytecodeIteratorTest : public TestWithZone {};
|
||||||
|
|
||||||
TEST_F(BytecodeIteratorTest, SimpleForeach) {
|
TEST_F(BytecodeIteratorTest, SimpleForeach) {
|
||||||
|
Loading…
Reference in New Issue
Block a user