[wasm][bulk] Update the element segment decoding to the new spec changes
The element segment encoding in the bulk memory proposal changed recently. With this CL the V8 implementation gets up to date again. R=thibaudm@chromium.org Bug: v8:9658 Change-Id: I4f45d04369400356a6f3aaed9570c7870f5f97bd Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1778022 Reviewed-by: Thibaud Michaud <thibaudm@chromium.org> Commit-Queue: Andreas Haas <ahaas@chromium.org> Cr-Commit-Position: refs/heads/master@{#63836}
This commit is contained in:
parent
e92e8871dd
commit
d8b0c1e3e7
@ -797,9 +797,11 @@ class ModuleDecoderImpl : public Decoder {
|
||||
const byte* pos = pc();
|
||||
|
||||
bool is_active;
|
||||
bool functions_as_elements;
|
||||
uint32_t table_index;
|
||||
WasmInitExpr offset;
|
||||
consume_segment_header("table index", &is_active, &table_index, &offset);
|
||||
consume_element_segment_header(&is_active, &functions_as_elements,
|
||||
&table_index, &offset);
|
||||
if (failed()) return;
|
||||
|
||||
if (is_active) {
|
||||
@ -814,12 +816,6 @@ class ModuleDecoderImpl : public Decoder {
|
||||
table_index);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ValueType type = consume_reference_type();
|
||||
if (!ValueTypes::IsSubType(kWasmFuncRef, type)) {
|
||||
error(pc_ - 1, "invalid element segment type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t num_elem =
|
||||
@ -832,8 +828,8 @@ class ModuleDecoderImpl : public Decoder {
|
||||
|
||||
WasmElemSegment* init = &module_->elem_segments.back();
|
||||
for (uint32_t j = 0; j < num_elem; j++) {
|
||||
uint32_t index = is_active ? consume_element_func_index()
|
||||
: consume_passive_element();
|
||||
uint32_t index = functions_as_elements ? consume_element_expr()
|
||||
: consume_element_func_index();
|
||||
if (failed()) break;
|
||||
init->entries.push_back(index);
|
||||
}
|
||||
@ -910,8 +906,7 @@ class ModuleDecoderImpl : public Decoder {
|
||||
bool is_active;
|
||||
uint32_t memory_index;
|
||||
WasmInitExpr dest_addr;
|
||||
consume_segment_header("memory index", &is_active, &memory_index,
|
||||
&dest_addr);
|
||||
consume_data_segment_header(&is_active, &memory_index, &dest_addr);
|
||||
if (failed()) break;
|
||||
|
||||
if (is_active && memory_index != 0) {
|
||||
@ -1681,8 +1676,103 @@ class ModuleDecoderImpl : public Decoder {
|
||||
return attribute;
|
||||
}
|
||||
|
||||
void consume_segment_header(const char* name, bool* is_active,
|
||||
uint32_t* index, WasmInitExpr* offset) {
|
||||
void consume_element_segment_header(bool* is_active,
|
||||
bool* functions_as_elements,
|
||||
uint32_t* table_index,
|
||||
WasmInitExpr* offset) {
|
||||
const byte* pos = pc();
|
||||
uint8_t flag;
|
||||
if (enabled_features_.bulk_memory || enabled_features_.anyref) {
|
||||
flag = consume_u8("flag");
|
||||
} else {
|
||||
uint32_t table_index = consume_u32v("table index");
|
||||
// The only valid flag value without bulk_memory or anyref is '0'.
|
||||
if (table_index != 0) {
|
||||
error(
|
||||
"Element segments with table indices require "
|
||||
"--experimental-wasm-bulk-memory or --experimental-wasm-anyref");
|
||||
return;
|
||||
}
|
||||
flag = 0;
|
||||
}
|
||||
|
||||
// The mask for the bit in the flag which indicates if the segment is
|
||||
// active or not.
|
||||
constexpr uint8_t kIsPassiveMask = 0x01;
|
||||
// The mask for the bit in the flag which indicates if the segment has an
|
||||
// explicit table index field.
|
||||
constexpr uint8_t kHasTableIndexMask = 0x02;
|
||||
// The mask for the bit in the flag which indicates if the functions of this
|
||||
// segment are defined as function indices (=0) or elements(=1).
|
||||
constexpr uint8_t kFunctionsAsElementsMask = 0x04;
|
||||
constexpr uint8_t kFullMask =
|
||||
kIsPassiveMask | kHasTableIndexMask | kFunctionsAsElementsMask;
|
||||
|
||||
bool is_passive = flag & kIsPassiveMask;
|
||||
*is_active = !is_passive;
|
||||
*functions_as_elements = flag & kFunctionsAsElementsMask;
|
||||
bool has_table_index = flag & kHasTableIndexMask;
|
||||
|
||||
if (is_passive && !enabled_features_.bulk_memory) {
|
||||
error("Passive element segments require --experimental-wasm-bulk-memory");
|
||||
return;
|
||||
}
|
||||
if (*functions_as_elements && !enabled_features_.bulk_memory) {
|
||||
error(
|
||||
"Illegal segment flag. Did you forget "
|
||||
"--experimental-wasm-bulk-memory?");
|
||||
return;
|
||||
}
|
||||
if (flag != 0 && !enabled_features_.bulk_memory &&
|
||||
!enabled_features_.anyref) {
|
||||
error(
|
||||
"Invalid segment flag. Did you forget "
|
||||
"--experimental-wasm-bulk-memory or --experimental-wasm-anyref?");
|
||||
return;
|
||||
}
|
||||
if ((flag & kFullMask) != flag || (!(*is_active) && has_table_index)) {
|
||||
errorf(pos, "illegal flag value %u. Must be 0, 1, 2, 4, 5 or 6", flag);
|
||||
}
|
||||
|
||||
if (has_table_index) {
|
||||
*table_index = consume_u32v("table index");
|
||||
} else {
|
||||
*table_index = 0;
|
||||
}
|
||||
|
||||
if (*is_active) {
|
||||
*offset = consume_init_expr(module_.get(), kWasmI32);
|
||||
}
|
||||
|
||||
if (*is_active && !has_table_index) {
|
||||
// Active segments without table indices are a special case for backwards
|
||||
// compatibility. These cases have an implicit element kind or element
|
||||
// type, so we are done already with the segment header.
|
||||
return;
|
||||
}
|
||||
|
||||
if (*functions_as_elements) {
|
||||
// We have to check that there is an element type of type FuncRef. All
|
||||
// other element types are not valid yet.
|
||||
ValueType type = consume_reference_type();
|
||||
if (!ValueTypes::IsSubType(kWasmFuncRef, type)) {
|
||||
error(pc_ - 1, "invalid element segment type");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// We have to check that there is an element kind of type Function. All
|
||||
// other element kinds are not valid yet.
|
||||
uint8_t val = consume_u8("element kind");
|
||||
ImportExportKindCode kind = static_cast<ImportExportKindCode>(val);
|
||||
if (kind != kExternalFunction) {
|
||||
errorf(pos, "illegal element kind %x. Must be 0x00", val);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void consume_data_segment_header(bool* is_active, uint32_t* index,
|
||||
WasmInitExpr* offset) {
|
||||
const byte* pos = pc();
|
||||
uint32_t flag = consume_u32v("flag");
|
||||
|
||||
@ -1718,7 +1808,7 @@ class ModuleDecoderImpl : public Decoder {
|
||||
}
|
||||
if (flag == SegmentFlags::kActiveWithIndex) {
|
||||
*is_active = true;
|
||||
*index = consume_u32v(name);
|
||||
*index = consume_u32v("memory index");
|
||||
*offset = consume_init_expr(module_.get(), kWasmI32);
|
||||
}
|
||||
}
|
||||
@ -1734,7 +1824,7 @@ class ModuleDecoderImpl : public Decoder {
|
||||
return index;
|
||||
}
|
||||
|
||||
uint32_t consume_passive_element() {
|
||||
uint32_t consume_element_expr() {
|
||||
uint32_t index = WasmElemSegment::kNullIndex;
|
||||
uint8_t opcode = consume_u8("element opcode");
|
||||
if (failed()) return index;
|
||||
|
@ -27,12 +27,14 @@
|
||||
#define ACTIVE_NO_INDEX 0
|
||||
#define PASSIVE 1
|
||||
#define ACTIVE_WITH_INDEX 2
|
||||
#define PASSIVE_WITH_ELEMENTS 5
|
||||
#define ACTIVE_WITH_ELEMENTS 6
|
||||
|
||||
// The table index field in an element segment was repurposed as a flags field.
|
||||
// To specify a table index, we have to set the flag value to 2, followed by
|
||||
// the table index.
|
||||
#define TABLE_INDEX0 U32V_1(ACTIVE_NO_INDEX)
|
||||
#define TABLE_INDEX(v) U32V_1(ACTIVE_WITH_INDEX), U32V_1(v)
|
||||
#define TABLE_INDEX0 static_cast<byte>(ACTIVE_NO_INDEX)
|
||||
#define TABLE_INDEX(v) static_cast<byte>(ACTIVE_WITH_INDEX), U32V_1(v)
|
||||
|
||||
#define ZERO_ALIGNMENT 0
|
||||
#define ZERO_OFFSET 0
|
||||
|
@ -84,6 +84,7 @@ let kSharedHasMaximumFlag = 3;
|
||||
let kActiveNoIndex = 0;
|
||||
let kPassive = 1;
|
||||
let kActiveWithIndex = 2;
|
||||
let kPassiveWithElements = 5;
|
||||
|
||||
// Function declaration flags
|
||||
let kDeclFunctionName = 0x01;
|
||||
@ -1164,13 +1165,16 @@ class WasmModuleBuilder {
|
||||
}
|
||||
section.emit_u32v(init.base);
|
||||
section.emit_u8(kExprEnd);
|
||||
if (init.table != 0) {
|
||||
section.emit_u8(kExternalFunction);
|
||||
}
|
||||
section.emit_u32v(init.array.length);
|
||||
for (let index of init.array) {
|
||||
section.emit_u32v(index);
|
||||
}
|
||||
} else {
|
||||
// Passive segment.
|
||||
section.emit_u8(kPassive); // flags
|
||||
section.emit_u8(kPassiveWithElements); // flags
|
||||
section.emit_u8(kWasmAnyFunc);
|
||||
section.emit_u32v(init.array.length);
|
||||
for (let index of init.array) {
|
||||
|
@ -1086,6 +1086,7 @@ TEST_F(WasmModuleVerifyTest, ElementSectionMultipleTables) {
|
||||
FUNC_INDEX(0), // function
|
||||
TABLE_INDEX(1), // element for table 1
|
||||
WASM_INIT_EXPR_I32V_1(7), // index
|
||||
kExternalFunction, // type
|
||||
2, // elements count
|
||||
FUNC_INDEX(0), // entry 0
|
||||
FUNC_INDEX(0)), // entry 1
|
||||
@ -1132,15 +1133,18 @@ TEST_F(WasmModuleVerifyTest, ElementSectionMixedTables) {
|
||||
FUNC_INDEX(0), // function
|
||||
TABLE_INDEX(1), // element for table 1
|
||||
WASM_INIT_EXPR_I32V_1(7), // index
|
||||
kExternalFunction, // type
|
||||
2, // elements count
|
||||
FUNC_INDEX(0), // entry 0
|
||||
FUNC_INDEX(0), // entry 1
|
||||
TABLE_INDEX(2), // element for table 2
|
||||
WASM_INIT_EXPR_I32V_1(12), // index
|
||||
kExternalFunction, // type
|
||||
1, // elements count
|
||||
FUNC_INDEX(0), // function
|
||||
TABLE_INDEX(3), // element for table 1
|
||||
WASM_INIT_EXPR_I32V_1(17), // index
|
||||
kExternalFunction, // type
|
||||
2, // elements count
|
||||
FUNC_INDEX(0), // entry 0
|
||||
FUNC_INDEX(0)), // entry 1
|
||||
@ -1173,6 +1177,7 @@ TEST_F(WasmModuleVerifyTest, ElementSectionMultipleTablesArbitraryOrder) {
|
||||
FUNC_INDEX(0), // function
|
||||
TABLE_INDEX(1), // element for table 0
|
||||
WASM_INIT_EXPR_I32V_1(7), // index
|
||||
kExternalFunction, // type
|
||||
2, // elements count
|
||||
FUNC_INDEX(0), // entry 0
|
||||
FUNC_INDEX(0), // entry 1
|
||||
@ -1219,10 +1224,12 @@ TEST_F(WasmModuleVerifyTest, ElementSectionMixedTablesArbitraryOrder) {
|
||||
4, // entry count
|
||||
TABLE_INDEX(2), // element for table 0
|
||||
WASM_INIT_EXPR_I32V_1(10), // index
|
||||
kExternalFunction, // type
|
||||
1, // elements count
|
||||
FUNC_INDEX(0), // function
|
||||
TABLE_INDEX(3), // element for table 1
|
||||
WASM_INIT_EXPR_I32V_1(17), // index
|
||||
kExternalFunction, // type
|
||||
2, // elements count
|
||||
FUNC_INDEX(0), // entry 0
|
||||
FUNC_INDEX(0), // entry 1
|
||||
@ -1232,6 +1239,7 @@ TEST_F(WasmModuleVerifyTest, ElementSectionMixedTablesArbitraryOrder) {
|
||||
FUNC_INDEX(0), // function
|
||||
TABLE_INDEX(1), // element for table 1
|
||||
WASM_INIT_EXPR_I32V_1(7), // index
|
||||
kExternalFunction, // type
|
||||
2, // elements count
|
||||
FUNC_INDEX(0), // entry 0
|
||||
FUNC_INDEX(0)), // entry 1
|
||||
@ -1262,6 +1270,7 @@ TEST_F(WasmModuleVerifyTest, ElementSectionInitAnyRefTableWithFuncRef) {
|
||||
FUNC_INDEX(0), // function
|
||||
TABLE_INDEX(1), // element for table 1
|
||||
WASM_INIT_EXPR_I32V_1(7), // index
|
||||
kExternalFunction, // type
|
||||
2, // elements count
|
||||
FUNC_INDEX(0), // entry 0
|
||||
FUNC_INDEX(0)), // entry 1
|
||||
@ -1309,6 +1318,7 @@ TEST_F(WasmModuleVerifyTest, ElementSectionDontInitAnyRefImportedTable) {
|
||||
FUNC_INDEX(0), // function
|
||||
TABLE_INDEX(1), // element for table 1
|
||||
WASM_INIT_EXPR_I32V_1(17), // index
|
||||
kExternalFunction, // type
|
||||
2, // elements count
|
||||
FUNC_INDEX(0), // entry 0
|
||||
FUNC_INDEX(0)), // entry 1
|
||||
@ -2359,6 +2369,26 @@ TEST_F(WasmModuleVerifyTest, PassiveDataSegment) {
|
||||
EXPECT_OFF_END_FAILURE(data, arraysize(data) - 5);
|
||||
}
|
||||
|
||||
TEST_F(WasmModuleVerifyTest, ActiveElementSegmentWithElements) {
|
||||
static const byte data[] = {
|
||||
// sig#0 -----------------------------------------------------------------
|
||||
SIGNATURES_SECTION_VOID_VOID,
|
||||
// funcs -----------------------------------------------------------------
|
||||
ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
|
||||
// table declaration -----------------------------------------------------
|
||||
SECTION(Table, ENTRY_COUNT(1), kLocalFuncRef, 0, 1),
|
||||
// element segments -----------------------------------------------------
|
||||
SECTION(Element, ENTRY_COUNT(1), ACTIVE_WITH_ELEMENTS, TABLE_INDEX0,
|
||||
WASM_INIT_EXPR_I32V_1(0), kLocalFuncRef, U32V_1(3),
|
||||
REF_FUNC_ELEMENT(0), REF_FUNC_ELEMENT(0), REF_NULL_ELEMENT),
|
||||
// code ------------------------------------------------------------------
|
||||
ONE_EMPTY_BODY};
|
||||
EXPECT_FAILURE(data);
|
||||
WASM_FEATURE_SCOPE(bulk_memory);
|
||||
EXPECT_VERIFIES(data);
|
||||
EXPECT_OFF_END_FAILURE(data, arraysize(data) - 5);
|
||||
}
|
||||
|
||||
TEST_F(WasmModuleVerifyTest, PassiveElementSegment) {
|
||||
static const byte data[] = {
|
||||
// sig#0 -----------------------------------------------------------------
|
||||
@ -2368,8 +2398,9 @@ TEST_F(WasmModuleVerifyTest, PassiveElementSegment) {
|
||||
// table declaration -----------------------------------------------------
|
||||
SECTION(Table, ENTRY_COUNT(1), kLocalFuncRef, 0, 1),
|
||||
// element segments -----------------------------------------------------
|
||||
SECTION(Element, ENTRY_COUNT(1), PASSIVE, kLocalFuncRef, U32V_1(3),
|
||||
REF_FUNC_ELEMENT(0), REF_FUNC_ELEMENT(0), REF_NULL_ELEMENT),
|
||||
SECTION(Element, ENTRY_COUNT(1), PASSIVE_WITH_ELEMENTS, kLocalFuncRef,
|
||||
U32V_1(3), REF_FUNC_ELEMENT(0), REF_FUNC_ELEMENT(0),
|
||||
REF_NULL_ELEMENT),
|
||||
// code ------------------------------------------------------------------
|
||||
ONE_EMPTY_BODY};
|
||||
EXPECT_FAILURE(data);
|
||||
@ -2387,13 +2418,33 @@ TEST_F(WasmModuleVerifyTest, PassiveElementSegmentAnyRef) {
|
||||
// table declaration -----------------------------------------------------
|
||||
SECTION(Table, ENTRY_COUNT(1), kLocalFuncRef, 0, 1),
|
||||
// element segments -----------------------------------------------------
|
||||
SECTION(Element, ENTRY_COUNT(1), PASSIVE, kLocalAnyRef, U32V_1(0)),
|
||||
SECTION(Element, ENTRY_COUNT(1), PASSIVE_WITH_ELEMENTS, kLocalAnyRef,
|
||||
U32V_1(0)),
|
||||
// code ------------------------------------------------------------------
|
||||
ONE_EMPTY_BODY};
|
||||
WASM_FEATURE_SCOPE(bulk_memory);
|
||||
EXPECT_FAILURE(data);
|
||||
}
|
||||
|
||||
TEST_F(WasmModuleVerifyTest, PassiveElementSegmentWithIndices) {
|
||||
static const byte data[] = {
|
||||
// sig#0 -----------------------------------------------------------------
|
||||
SIGNATURES_SECTION_VOID_VOID,
|
||||
// funcs -----------------------------------------------------------------
|
||||
ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
|
||||
// table declaration -----------------------------------------------------
|
||||
SECTION(Table, ENTRY_COUNT(1), kLocalFuncRef, 0, 1),
|
||||
// element segments -----------------------------------------------------
|
||||
SECTION(Element, ENTRY_COUNT(1), PASSIVE, kExternalFunction,
|
||||
ENTRY_COUNT(3), U32V_1(0), U32V_1(0), U32V_1(0)),
|
||||
// code ------------------------------------------------------------------
|
||||
ONE_EMPTY_BODY};
|
||||
EXPECT_FAILURE(data);
|
||||
WASM_FEATURE_SCOPE(bulk_memory);
|
||||
EXPECT_VERIFIES(data);
|
||||
EXPECT_OFF_END_FAILURE(data, arraysize(data) - 5);
|
||||
}
|
||||
|
||||
TEST_F(WasmModuleVerifyTest, DataCountSectionCorrectPlacement) {
|
||||
static const byte data[] = {SECTION(Element, ENTRY_COUNT(0)),
|
||||
SECTION(DataCount, ENTRY_COUNT(0)),
|
||||
|
@ -1 +1 @@
|
||||
1e0e2435efac858f3269de548d7c795fb6173ca8
|
||||
2ecf4038f24fc08bd9da504f15942d3abb5ec685
|
@ -1 +1 @@
|
||||
088e8722b3fe99ea3a67a9852e787f461f348d0b
|
||||
f9bd936c708402051f87f4ac8940d1916112a15a
|
@ -10,15 +10,9 @@
|
||||
# the bulk-memory proposal. Since we've enabled bulk-memory by default, we
|
||||
# need to update to use its testsuite.
|
||||
'linking': [FAIL],
|
||||
'binary-leb128': [FAIL],
|
||||
'elem': [FAIL],
|
||||
'data': [FAIL],
|
||||
# TODO(v8:9658): The encoding of element segments changed in the bulk memory
|
||||
# proposal
|
||||
'proposals/bulk-memory-operations/bulk': [FAIL],
|
||||
'proposals/bulk-memory-operations/table_init': [FAIL],
|
||||
'proposals/bulk-memory-operations/table_copy': [FAIL],
|
||||
'proposals/bulk-memory-operations/elem': [FAIL],
|
||||
'proposals/bulk-memory-operations/binary': [FAIL],
|
||||
# TODO(mstarzinger): Roll newest tests into "js-types" repository.
|
||||
'proposals/js-types/exports': [FAIL],
|
||||
'proposals/js-types/globals': [FAIL],
|
||||
|
Loading…
Reference in New Issue
Block a user