[wasm][anyref] Decode anyref globals

Add support for decoding anyref globals, and some drive-by cleanups.

R=titzer@chromium.org

Bug: v8:7581
Change-Id: I3527f996a3fa1a890918a5924e951fbafa394cf2
Reviewed-on: https://chromium-review.googlesource.com/997655
Reviewed-by: Ben Titzer <titzer@chromium.org>
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52391}
This commit is contained in:
Andreas Haas 2018-04-05 12:49:26 +02:00 committed by Commit Bot
parent 7401022460
commit ae958346a0
4 changed files with 104 additions and 24 deletions

View File

@ -113,6 +113,8 @@ ValueType TypeOf(const WasmModule* module, const WasmInitExpr& expr) {
return kWasmF32;
case WasmInitExpr::kF64Const:
return kWasmF64;
case WasmInitExpr::kAnyRefConst:
return kWasmAnyRef;
default:
UNREACHABLE();
}
@ -945,30 +947,26 @@ class ModuleDecoderImpl : public Decoder {
global->mutability = consume_mutability();
const byte* pos = pc();
global->init = consume_init_expr(module, kWasmStmt);
switch (global->init.kind) {
case WasmInitExpr::kGlobalIndex: {
uint32_t other_index = global->init.val.global_index;
if (other_index >= index) {
errorf(pos,
"invalid global index in init expression, "
"index %u, other_index %u",
index, other_index);
} else if (module->globals[other_index].type != global->type) {
errorf(pos,
"type mismatch in global initialization "
"(from global #%u), expected %s, got %s",
other_index, WasmOpcodes::TypeName(global->type),
WasmOpcodes::TypeName(module->globals[other_index].type));
}
break;
if (global->init.kind == WasmInitExpr::kGlobalIndex) {
uint32_t other_index = global->init.val.global_index;
if (other_index >= index) {
errorf(pos,
"invalid global index in init expression, "
"index %u, other_index %u",
index, other_index);
} else if (module->globals[other_index].type != global->type) {
errorf(pos,
"type mismatch in global initialization "
"(from global #%u), expected %s, got %s",
other_index, WasmOpcodes::TypeName(global->type),
WasmOpcodes::TypeName(module->globals[other_index].type));
}
} else {
if (global->type != TypeOf(module, global->init)) {
errorf(pos, "type error in global initialization, expected %s, got %s",
WasmOpcodes::TypeName(global->type),
WasmOpcodes::TypeName(TypeOf(module, global->init)));
}
default:
if (global->type != TypeOf(module, global->init)) {
errorf(pos,
"type error in global initialization, expected %s, got %s",
WasmOpcodes::TypeName(global->type),
WasmOpcodes::TypeName(TypeOf(module, global->init)));
}
}
}
@ -1205,6 +1203,14 @@ class ModuleDecoderImpl : public Decoder {
len = operand.length;
break;
}
case kExprRefNull: {
if (FLAG_experimental_wasm_anyref) {
expr.kind = WasmInitExpr::kAnyRefConst;
len = 0;
break;
}
V8_FALLTHROUGH;
}
default: {
error("invalid opcode in initialization expression");
expr.kind = WasmInitExpr::kNone;

View File

@ -862,7 +862,8 @@ struct WasmInitExpr {
kI32Const,
kI64Const,
kF32Const,
kF64Const
kF64Const,
kAnyRefConst,
} kind;
union {

View File

@ -328,6 +328,9 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) {
static_cast<byte>(bit_cast<uint64_t>(static_cast<double>(val)) >> 40), \
static_cast<byte>(bit_cast<uint64_t>(static_cast<double>(val)) >> 48), \
static_cast<byte>(bit_cast<uint64_t>(static_cast<double>(val)) >> 56)
#define WASM_REF_NULL kExprRefNull
#define WASM_GET_LOCAL(index) kExprGetLocal, static_cast<byte>(index)
#define WASM_SET_LOCAL(index, val) val, kExprSetLocal, static_cast<byte>(index)
#define WASM_TEE_LOCAL(index, val) val, kExprTeeLocal, static_cast<byte>(index)

View File

@ -25,6 +25,7 @@ namespace module_decoder_unittest {
#define WASM_INIT_EXPR_F32(val) WASM_F32(val), kExprEnd
#define WASM_INIT_EXPR_I64(val) WASM_I64(val), kExprEnd
#define WASM_INIT_EXPR_F64(val) WASM_F64(val), kExprEnd
#define WASM_INIT_EXPR_ANYREF WASM_REF_NULL, kExprEnd
#define WASM_INIT_EXPR_GLOBAL(index) WASM_GET_GLOBAL(index), kExprEnd
#define SIZEOF_EMPTY_FUNCTION ((size_t)5)
@ -212,6 +213,67 @@ TEST_F(WasmModuleVerifyTest, OneGlobal) {
EXPECT_OFF_END_FAILURE(data, 1, sizeof(data));
}
TEST_F(WasmModuleVerifyTest, AnyRefGlobal) {
EXPERIMENTAL_FLAG_SCOPE(anyref);
static const byte data[] = {
SECTION(Global, 5), // --
1,
kLocalAnyRef, // local type
0, // immutable
WASM_INIT_EXPR_ANYREF // init
};
{
// Should decode to exactly one global.
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
EXPECT_EQ(1u, result.val->globals.size());
EXPECT_EQ(0u, result.val->functions.size());
EXPECT_EQ(0u, result.val->data_segments.size());
const WasmGlobal* global = &result.val->globals.back();
EXPECT_EQ(kWasmAnyRef, global->type);
EXPECT_FALSE(global->mutability);
EXPECT_EQ(WasmInitExpr::kAnyRefConst, global->init.kind);
}
}
TEST_F(WasmModuleVerifyTest, AnyRefGlobalWithGlobalInit) {
EXPERIMENTAL_FLAG_SCOPE(anyref);
static const byte data[] = {
SECTION(Import, 8), // section header
1, // number of imports
NAME_LENGTH(1), // --
'm', // module name
NAME_LENGTH(1), // --
'f', // global name
kExternalGlobal, // import kind
kLocalAnyRef, // type
0, // mutability
SECTION(Global, 6), // --
1,
kLocalAnyRef, // local type
0, // immutable
WASM_INIT_EXPR_GLOBAL(0),
};
{
// Should decode to exactly one global.
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
EXPECT_EQ(2u, result.val->globals.size());
EXPECT_EQ(0u, result.val->functions.size());
EXPECT_EQ(0u, result.val->data_segments.size());
const WasmGlobal* global = &result.val->globals.back();
EXPECT_EQ(kWasmAnyRef, global->type);
EXPECT_FALSE(global->mutability);
EXPECT_EQ(WasmInitExpr::kGlobalIndex, global->init.kind);
}
}
TEST_F(WasmModuleVerifyTest, Global_invalid_type) {
static const byte data[] = {
SECTION(Global, 6), // --
@ -1696,6 +1758,13 @@ TEST_F(WasmModuleVerifyTest, InitExpr_f64) {
EXPECT_INIT_EXPR(F64, f64, 77999.1, WASM_F64(77999.1));
}
TEST_F(WasmModuleVerifyTest, InitExpr_AnyRef) {
EXPERIMENTAL_FLAG_SCOPE(anyref);
static const byte data[] = {kExprRefNull, kExprEnd};
WasmInitExpr expr = DecodeWasmInitExprForTesting(data, data + sizeof(data));
EXPECT_EQ(WasmInitExpr::kAnyRefConst, expr.kind);
}
#undef EXPECT_INIT_EXPR
#define EXPECT_INIT_EXPR_FAIL(...) \
@ -1819,6 +1888,7 @@ TEST_F(WasmModuleCustomSectionTest, TwoKnownTwoUnknownSections) {
#undef WASM_INIT_EXPR_F32
#undef WASM_INIT_EXPR_I64
#undef WASM_INIT_EXPR_F64
#undef WASM_INIT_EXPR_ANYREF
#undef WASM_INIT_EXPR_GLOBAL
#undef SIZEOF_EMPTY_FUNCTION
#undef EMPTY_BODY