Commit c06a8e23 authored by Manos Koukoutos's avatar Manos Koukoutos Committed by V8 LUCI CQ

[wasm] Do not use WasmInitExpr for element segments

Changes:
- Use a lightweight WasmElemSegment::Entry struct to store element
  segment entries in a WasmModule.
- Also, restructure LoadElemSegmentImpl to handle all types of
  global.get entries correctly.
- Simplify InitializeIndirectFunctionTables and make it handle all types
  of entries correctly.
- In the above two cases, reject WasmJSFunctions for now.

Bug: v8:11895
Change-Id: Ie714f8c7f1af8959486138d2ad49bc622a89276d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2991248
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75513}
parent b0bcedcc
...@@ -916,10 +916,11 @@ class ModuleDecoderImpl : public Decoder { ...@@ -916,10 +916,11 @@ class ModuleDecoderImpl : public Decoder {
consume_count("number of elements", max_table_init_entries()); consume_count("number of elements", max_table_init_entries());
for (uint32_t j = 0; j < num_elem; j++) { for (uint32_t j = 0; j < num_elem; j++) {
WasmInitExpr init = WasmElemSegment::Entry init =
expressions_as_elements expressions_as_elements
? consume_element_expr() ? consume_element_expr()
: WasmInitExpr::RefFuncConst(consume_element_func_index()); : WasmElemSegment::Entry(WasmElemSegment::Entry::kRefFuncEntry,
consume_element_func_index());
if (failed()) return; if (failed()) return;
if (!IsSubtypeOf(TypeOf(init), segment.type, module_.get())) { if (!IsSubtypeOf(TypeOf(init), segment.type, module_.get())) {
errorf(pc_, errorf(pc_,
...@@ -928,7 +929,7 @@ class ModuleDecoderImpl : public Decoder { ...@@ -928,7 +929,7 @@ class ModuleDecoderImpl : public Decoder {
segment.type.name().c_str(), TypeOf(init).name().c_str()); segment.type.name().c_str(), TypeOf(init).name().c_str());
return; return;
} }
segment.entries.push_back(std::move(init)); segment.entries.push_back(init);
} }
module_->elem_segments.push_back(std::move(segment)); module_->elem_segments.push_back(std::move(segment));
} }
...@@ -1423,8 +1424,16 @@ class ModuleDecoderImpl : public Decoder { ...@@ -1423,8 +1424,16 @@ class ModuleDecoderImpl : public Decoder {
AccountingAllocator allocator_; AccountingAllocator allocator_;
Zone init_expr_zone_{&allocator_, "initializer expression zone"}; Zone init_expr_zone_{&allocator_, "initializer expression zone"};
ValueType TypeOf(const WasmInitExpr& expr) { ValueType TypeOf(WasmElemSegment::Entry entry) {
return expr.type(module_.get(), enabled_features_); switch (entry.kind) {
case WasmElemSegment::Entry::kGlobalGetEntry:
return module_->globals[entry.index].type;
case WasmElemSegment::Entry::kRefFuncEntry:
return ValueType::Ref(module_->functions[entry.index].sig_index,
kNonNullable);
case WasmElemSegment::Entry::kRefNullEntry:
return ValueType::Ref(entry.index, kNullable);
}
} }
bool has_seen_unordered_section(SectionCode section_code) { bool has_seen_unordered_section(SectionCode section_code) {
...@@ -1991,9 +2000,10 @@ class ModuleDecoderImpl : public Decoder { ...@@ -1991,9 +2000,10 @@ class ModuleDecoderImpl : public Decoder {
return index; return index;
} }
// TODO(manoskouk): When reftypes lands, remove this and use // TODO(manoskouk): When reftypes lands, consider if we can implement this
// consume_init_expr() instead. // with consume_init_expr(). It will require changes in module-instantiate.cc,
WasmInitExpr consume_element_expr() { // in {LoadElemSegmentImpl}.
WasmElemSegment::Entry consume_element_expr() {
uint8_t opcode = consume_u8("element opcode"); uint8_t opcode = consume_u8("element opcode");
if (failed()) return {}; if (failed()) return {};
switch (opcode) { switch (opcode) {
...@@ -2002,13 +2012,14 @@ class ModuleDecoderImpl : public Decoder { ...@@ -2002,13 +2012,14 @@ class ModuleDecoderImpl : public Decoder {
this->pc(), module_.get()); this->pc(), module_.get());
consume_bytes(imm.length, "ref.null immediate"); consume_bytes(imm.length, "ref.null immediate");
expect_u8("end opcode", kExprEnd); expect_u8("end opcode", kExprEnd);
return WasmInitExpr::RefNullConst(imm.type.representation()); return {WasmElemSegment::Entry::kRefNullEntry,
static_cast<uint32_t>(imm.type.representation())};
} }
case kExprRefFunc: { case kExprRefFunc: {
uint32_t index = consume_element_func_index(); uint32_t index = consume_element_func_index();
if (failed()) return {}; if (failed()) return {};
expect_u8("end opcode", kExprEnd); expect_u8("end opcode", kExprEnd);
return WasmInitExpr::RefFuncConst(index); return {WasmElemSegment::Entry::kRefFuncEntry, index};
} }
case kExprGlobalGet: { case kExprGlobalGet: {
if (!enabled_features_.has_reftypes()) { if (!enabled_features_.has_reftypes()) {
...@@ -2025,7 +2036,7 @@ class ModuleDecoderImpl : public Decoder { ...@@ -2025,7 +2036,7 @@ class ModuleDecoderImpl : public Decoder {
return {}; return {};
} }
expect_u8("end opcode", kExprEnd); expect_u8("end opcode", kExprEnd);
return WasmInitExpr::GlobalGet(index); return {WasmElemSegment::Entry::kGlobalGetEntry, index};
} }
default: default:
error("invalid opcode in element"); error("invalid opcode in element");
......
This diff is collapsed.
...@@ -135,7 +135,13 @@ struct WasmElemSegment { ...@@ -135,7 +135,13 @@ struct WasmElemSegment {
ValueType type; ValueType type;
uint32_t table_index; uint32_t table_index;
WireBytesRef offset; WireBytesRef offset;
std::vector<WasmInitExpr> entries; struct Entry {
enum Kind { kGlobalGetEntry, kRefFuncEntry, kRefNullEntry } kind;
uint32_t index;
Entry(Kind kind, uint32_t index) : kind(kind), index(index) {}
Entry() : kind(kRefNullEntry), index(0) {}
};
std::vector<Entry> entries;
enum Status { enum Status {
kStatusActive, // copied automatically during instantiation. kStatusActive, // copied automatically during instantiation.
kStatusPassive, // copied explicitly after instantiation. kStatusPassive, // copied explicitly after instantiation.
......
...@@ -302,7 +302,8 @@ uint32_t TestingModuleBuilder::AddPassiveElementSegment( ...@@ -302,7 +302,8 @@ uint32_t TestingModuleBuilder::AddPassiveElementSegment(
test_module_->elem_segments.emplace_back(kWasmFuncRef, false); test_module_->elem_segments.emplace_back(kWasmFuncRef, false);
auto& elem_segment = test_module_->elem_segments.back(); auto& elem_segment = test_module_->elem_segments.back();
for (uint32_t entry : entries) { for (uint32_t entry : entries) {
elem_segment.entries.push_back(WasmInitExpr::RefFuncConst(entry)); elem_segment.entries.push_back(
WasmElemSegment::Entry(WasmElemSegment::Entry::kRefFuncEntry, entry));
} }
// The vector pointers may have moved, so update the instance object. // The vector pointers may have moved, so update the instance object.
......
...@@ -159,37 +159,17 @@ std::ostream& operator<<(std::ostream& os, const PrintName& name) { ...@@ -159,37 +159,17 @@ std::ostream& operator<<(std::ostream& os, const PrintName& name) {
return os.write(name.name.begin(), name.name.size()); return os.write(name.name.begin(), name.name.size());
} }
std::ostream& operator<<(std::ostream& os, const WasmInitExpr& expr) { std::ostream& operator<<(std::ostream& os, WasmElemSegment::Entry entry) {
os << "WasmInitExpr."; os << "WasmInitExpr.";
switch (expr.kind()) { switch (entry.kind) {
case WasmInitExpr::kNone: case WasmElemSegment::Entry::kGlobalGetEntry:
UNREACHABLE(); os << "GlobalGet(" << entry.index;
case WasmInitExpr::kS128Const:
case WasmInitExpr::kRttCanon:
case WasmInitExpr::kRttSub:
case WasmInitExpr::kRttFreshSub:
case WasmInitExpr::kRefNullConst:
case WasmInitExpr::kStructNewWithRtt:
case WasmInitExpr::kArrayInit:
// TODO(manoskouk): Implement these.
UNIMPLEMENTED();
case WasmInitExpr::kGlobalGet:
os << "GlobalGet(" << expr.immediate().index;
break;
case WasmInitExpr::kI32Const:
os << "I32Const(" << expr.immediate().i32_const;
break;
case WasmInitExpr::kI64Const:
os << "I64Const(" << expr.immediate().i64_const;
break;
case WasmInitExpr::kF32Const:
os << "F32Const(" << expr.immediate().f32_const;
break; break;
case WasmInitExpr::kF64Const: case WasmElemSegment::Entry::kRefFuncEntry:
os << "F64Const(" << expr.immediate().f64_const; os << "RefFunc(" << entry.index;
break; break;
case WasmInitExpr::kRefFuncConst: case WasmElemSegment::Entry::kRefNullEntry:
os << "RefFunc(" << expr.immediate().index; os << "RefNull(" << HeapType(entry.index).name().c_str();
break; break;
} }
return os << ")"; return os << ")";
......
...@@ -161,16 +161,16 @@ class TestModuleBuilder { ...@@ -161,16 +161,16 @@ class TestModuleBuilder {
auto& init = mod.elem_segments.back(); auto& init = mod.elem_segments.back();
// Add 5 empty elements. // Add 5 empty elements.
for (uint32_t j = 0; j < 5; j++) { for (uint32_t j = 0; j < 5; j++) {
init.entries.push_back( init.entries.push_back(WasmElemSegment::Entry(
WasmInitExpr::RefNullConst(type.heap_representation())); WasmElemSegment::Entry::kRefNullEntry, type.heap_representation()));
} }
return static_cast<byte>(mod.elem_segments.size() - 1); return static_cast<byte>(mod.elem_segments.size() - 1);
} }
byte AddDeclarativeElementSegment() { byte AddDeclarativeElementSegment() {
mod.elem_segments.emplace_back(kWasmFuncRef, true); mod.elem_segments.emplace_back(kWasmFuncRef, true);
mod.elem_segments.back().entries.push_back( mod.elem_segments.back().entries.push_back(WasmElemSegment::Entry(
WasmInitExpr::RefNullConst(HeapType::kFunc)); WasmElemSegment::Entry::kRefNullEntry, HeapType::kFunc));
return static_cast<byte>(mod.elem_segments.size() - 1); return static_cast<byte>(mod.elem_segments.size() - 1);
} }
......
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