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

[wasm] Refactoring ahead of element segment changes

See related CL for context.

Changes:
- In InitExprInterface, add the ability to evaluate function references
  as index only. Remove the global buffers and use the ones passed with
  the instance object instead.
- In WasmElemSegment, add a field indicating if elements should be
  parsed as expressions or indices. Change module-decoder.cc to reflect
  this change.
- In module-instantiate, change the signatures of LoadElemSegment,
  LoadElemSegmentImpl, and EvaluateInitExpr. Move the latter out of
  InstanceBuilder.

Change-Id: I1df54393b2005fba49380654bdd40429bd4869dd
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3364081Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78470}
parent 76d47dec
...@@ -52,14 +52,20 @@ void InitExprInterface::RefNull(FullDecoder* decoder, ValueType type, ...@@ -52,14 +52,20 @@ void InitExprInterface::RefNull(FullDecoder* decoder, ValueType type,
void InitExprInterface::RefFunc(FullDecoder* decoder, uint32_t function_index, void InitExprInterface::RefFunc(FullDecoder* decoder, uint32_t function_index,
Value* result) { Value* result) {
if (isolate_ != nullptr) { if (isolate_ == nullptr) {
auto internal = WasmInstanceObject::GetOrCreateWasmInternalFunction(
isolate_, instance_, function_index);
result->runtime_value = WasmValue(
internal, ValueType::Ref(module_->functions[function_index].sig_index,
kNonNullable));
} else {
outer_module_->functions[function_index].declared = true; outer_module_->functions[function_index].declared = true;
return;
}
ValueType type = ValueType::Ref(module_->functions[function_index].sig_index,
kNonNullable);
if (function_strictness_ == kStrictFunctions) {
Handle<WasmInternalFunction> internal =
WasmInstanceObject::GetOrCreateWasmInternalFunction(isolate_, instance_,
function_index);
result->runtime_value = WasmValue(internal, type);
} else {
result->runtime_value =
WasmValue(handle(Smi::FromInt(function_index), isolate_), type);
} }
} }
...@@ -67,11 +73,18 @@ void InitExprInterface::GlobalGet(FullDecoder* decoder, Value* result, ...@@ -67,11 +73,18 @@ void InitExprInterface::GlobalGet(FullDecoder* decoder, Value* result,
const GlobalIndexImmediate<validate>& imm) { const GlobalIndexImmediate<validate>& imm) {
if (isolate_ == nullptr) return; if (isolate_ == nullptr) return;
const WasmGlobal& global = module_->globals[imm.index]; const WasmGlobal& global = module_->globals[imm.index];
DCHECK(!global.mutability);
result->runtime_value = result->runtime_value =
global.type.is_numeric() global.type.is_numeric()
? WasmValue(GetRawUntaggedGlobalPtr(global), global.type) ? WasmValue(
: WasmValue(handle(tagged_globals_->get(global.offset), isolate_), reinterpret_cast<byte*>(
global.type); instance_->untagged_globals_buffer().backing_store()) +
global.offset,
global.type)
: WasmValue(
handle(instance_->tagged_globals_buffer().get(global.offset),
isolate_),
global.type);
} }
void InitExprInterface::StructNewWithRtt( void InitExprInterface::StructNewWithRtt(
...@@ -175,11 +188,6 @@ void InitExprInterface::DoReturn(FullDecoder* decoder, ...@@ -175,11 +188,6 @@ void InitExprInterface::DoReturn(FullDecoder* decoder,
if (isolate_ != nullptr) result_ = decoder->stack_value(1)->runtime_value; if (isolate_ != nullptr) result_ = decoder->stack_value(1)->runtime_value;
} }
byte* InitExprInterface::GetRawUntaggedGlobalPtr(const WasmGlobal& global) {
return reinterpret_cast<byte*>(untagged_globals_->backing_store()) +
global.offset;
}
} // namespace wasm } // namespace wasm
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -44,16 +44,20 @@ class InitExprInterface { ...@@ -44,16 +44,20 @@ class InitExprInterface {
using FullDecoder = using FullDecoder =
WasmFullDecoder<validate, InitExprInterface, decoding_mode>; WasmFullDecoder<validate, InitExprInterface, decoding_mode>;
// Controls how function references are computed. {kLazyFunctions} means that
// only the index of the function will be computed, as a Smi.
// {kStrictFunctions} means we fully compute the function reference through
// {WasmInstanceObject::GetOrCreateWasmInternalFunction}.
enum FunctionStrictness { kLazyFunctions, kStrictFunctions };
InitExprInterface(const WasmModule* module, Isolate* isolate, InitExprInterface(const WasmModule* module, Isolate* isolate,
Handle<WasmInstanceObject> instance, Handle<WasmInstanceObject> instance,
Handle<FixedArray> tagged_globals, FunctionStrictness function_strictness)
Handle<JSArrayBuffer> untagged_globals)
: module_(module), : module_(module),
outer_module_(nullptr), outer_module_(nullptr),
isolate_(isolate), isolate_(isolate),
instance_(instance), instance_(instance),
tagged_globals_(tagged_globals), function_strictness_(function_strictness) {
untagged_globals_(untagged_globals) {
DCHECK_NOT_NULL(isolate); DCHECK_NOT_NULL(isolate);
} }
...@@ -81,16 +85,13 @@ class InitExprInterface { ...@@ -81,16 +85,13 @@ class InitExprInterface {
bool end_found() { return end_found_; } bool end_found() { return end_found_; }
private: private:
byte* GetRawUntaggedGlobalPtr(const WasmGlobal& global);
bool end_found_ = false; bool end_found_ = false;
WasmValue result_; WasmValue result_;
const WasmModule* module_; const WasmModule* module_;
WasmModule* outer_module_; WasmModule* outer_module_;
Isolate* isolate_; Isolate* isolate_;
Handle<WasmInstanceObject> instance_; Handle<WasmInstanceObject> instance_;
Handle<FixedArray> tagged_globals_; FunctionStrictness function_strictness_;
Handle<JSArrayBuffer> untagged_globals_;
}; };
} // namespace wasm } // namespace wasm
......
...@@ -990,9 +990,7 @@ class ModuleDecoderImpl : public Decoder { ...@@ -990,9 +990,7 @@ class ModuleDecoderImpl : public Decoder {
consume_count("element count", FLAG_wasm_max_table_size); consume_count("element count", FLAG_wasm_max_table_size);
for (uint32_t i = 0; i < element_count; ++i) { for (uint32_t i = 0; i < element_count; ++i) {
bool expressions_as_elements; WasmElemSegment segment = consume_element_segment_header();
WasmElemSegment segment =
consume_element_segment_header(&expressions_as_elements);
if (failed()) return; if (failed()) return;
DCHECK_NE(segment.type, kWasmBottom); DCHECK_NE(segment.type, kWasmBottom);
...@@ -1001,7 +999,7 @@ class ModuleDecoderImpl : public Decoder { ...@@ -1001,7 +999,7 @@ class ModuleDecoderImpl : public Decoder {
for (uint32_t j = 0; j < num_elem; j++) { for (uint32_t j = 0; j < num_elem; j++) {
WasmElemSegment::Entry init = WasmElemSegment::Entry init =
expressions_as_elements segment.element_type == WasmElemSegment::kExpressionElements
? consume_element_expr() ? consume_element_expr()
: WasmElemSegment::Entry(WasmElemSegment::Entry::kRefFuncEntry, : WasmElemSegment::Entry(WasmElemSegment::Entry::kRefFuncEntry,
consume_element_func_index()); consume_element_func_index());
...@@ -1910,8 +1908,7 @@ class ModuleDecoderImpl : public Decoder { ...@@ -1910,8 +1908,7 @@ class ModuleDecoderImpl : public Decoder {
return attribute; return attribute;
} }
WasmElemSegment consume_element_segment_header( WasmElemSegment consume_element_segment_header() {
bool* expressions_as_elements) {
const byte* pos = pc(); const byte* pos = pc();
// The mask for the bit in the flag which indicates if the segment is // The mask for the bit in the flag which indicates if the segment is
...@@ -1941,7 +1938,10 @@ class ModuleDecoderImpl : public Decoder { ...@@ -1941,7 +1938,10 @@ class ModuleDecoderImpl : public Decoder {
: WasmElemSegment::kStatusActive; : WasmElemSegment::kStatusActive;
const bool is_active = status == WasmElemSegment::kStatusActive; const bool is_active = status == WasmElemSegment::kStatusActive;
*expressions_as_elements = flag & kExpressionsAsElementsMask; WasmElemSegment::ElementType element_type =
flag & kExpressionsAsElementsMask
? WasmElemSegment::kExpressionElements
: WasmElemSegment::kFunctionIndexElements;
const bool has_table_index = const bool has_table_index =
is_active && (flag & kHasTableIndexOrIsDeclarativeMask); is_active && (flag & kHasTableIndexOrIsDeclarativeMask);
...@@ -1965,7 +1965,7 @@ class ModuleDecoderImpl : public Decoder { ...@@ -1965,7 +1965,7 @@ class ModuleDecoderImpl : public Decoder {
const bool backwards_compatible_mode = const bool backwards_compatible_mode =
is_active && !(flag & kHasTableIndexOrIsDeclarativeMask); is_active && !(flag & kHasTableIndexOrIsDeclarativeMask);
ValueType type; ValueType type;
if (*expressions_as_elements) { if (element_type == WasmElemSegment::kExpressionElements) {
type = type =
backwards_compatible_mode ? kWasmFuncRef : consume_reference_type(); backwards_compatible_mode ? kWasmFuncRef : consume_reference_type();
if (is_active && !IsSubtypeOf(type, table_type, this->module_.get())) { if (is_active && !IsSubtypeOf(type, table_type, this->module_.get())) {
...@@ -2008,9 +2008,9 @@ class ModuleDecoderImpl : public Decoder { ...@@ -2008,9 +2008,9 @@ class ModuleDecoderImpl : public Decoder {
} }
if (is_active) { if (is_active) {
return {type, table_index, std::move(offset)}; return {type, table_index, std::move(offset), element_type};
} else { } else {
return {type, status == WasmElemSegment::kStatusDeclarative}; return {type, status, element_type};
} }
} }
......
...@@ -349,6 +349,9 @@ class InstanceBuilder { ...@@ -349,6 +349,9 @@ class InstanceBuilder {
std::vector<Handle<WasmTagObject>> tags_wrappers_; std::vector<Handle<WasmTagObject>> tags_wrappers_;
Handle<WasmExportedFunction> start_function_; Handle<WasmExportedFunction> start_function_;
std::vector<SanitizedImport> sanitized_imports_; std::vector<SanitizedImport> sanitized_imports_;
// We pass this {Zone} to the temporary {WasmFullDecoder} we allocate during
// each call to {EvaluateInitExpression}. This has been found to improve
// performance a bit over allocating a new {Zone} each time.
Zone init_expr_zone_; Zone init_expr_zone_;
// Helper routines to print out errors with imports. // Helper routines to print out errors with imports.
...@@ -448,9 +451,6 @@ class InstanceBuilder { ...@@ -448,9 +451,6 @@ class InstanceBuilder {
// Process initialization of globals. // Process initialization of globals.
void InitGlobals(Handle<WasmInstanceObject> instance); void InitGlobals(Handle<WasmInstanceObject> instance);
WasmValue EvaluateInitExpression(WireBytesRef init, ValueType expected,
Handle<WasmInstanceObject> instance);
// Process the exports, creating wrappers for functions, tables, memories, // Process the exports, creating wrappers for functions, tables, memories,
// and globals. // and globals.
void ProcessExports(Handle<WasmInstanceObject> instance); void ProcessExports(Handle<WasmInstanceObject> instance);
...@@ -914,6 +914,28 @@ bool HasDefaultToNumberBehaviour(Isolate* isolate, ...@@ -914,6 +914,28 @@ bool HasDefaultToNumberBehaviour(Isolate* isolate,
// Just a default function, which will convert to "Nan". Accept this. // Just a default function, which will convert to "Nan". Accept this.
return true; return true;
} }
WasmValue EvaluateInitExpression(
Zone* zone, WireBytesRef init, ValueType expected, Isolate* isolate,
Handle<WasmInstanceObject> instance,
InitExprInterface::FunctionStrictness function_strictness =
InitExprInterface::kStrictFunctions) {
base::Vector<const byte> module_bytes =
instance->module_object().native_module()->wire_bytes();
FunctionBody body(FunctionSig::Build(zone, {expected}, {}), init.offset(),
module_bytes.begin() + init.offset(),
module_bytes.begin() + init.end_offset());
WasmFeatures detected;
// We use kFullValidation so we do not have to create another instance of
// WasmFullDecoder, which would cost us >50Kb binary code size.
WasmFullDecoder<Decoder::kFullValidation, InitExprInterface, kInitExpression>
decoder(zone, instance->module(), WasmFeatures::All(), &detected, body,
instance->module(), isolate, instance, function_strictness);
decoder.DecodeFunctionBody();
return decoder.interface().result();
}
} // namespace } // namespace
// Look up an import value in the {ffi_} object specifically for linking an // Look up an import value in the {ffi_} object specifically for linking an
...@@ -975,7 +997,8 @@ void InstanceBuilder::LoadDataSegments(Handle<WasmInstanceObject> instance) { ...@@ -975,7 +997,8 @@ void InstanceBuilder::LoadDataSegments(Handle<WasmInstanceObject> instance) {
size_t dest_offset; size_t dest_offset;
if (module_->is_memory64) { if (module_->is_memory64) {
uint64_t dest_offset_64 = uint64_t dest_offset_64 =
EvaluateInitExpression(segment.dest_addr, kWasmI64, instance) EvaluateInitExpression(&init_expr_zone_, segment.dest_addr, kWasmI64,
isolate_, instance)
.to_u64(); .to_u64();
// Clamp to {std::numeric_limits<size_t>::max()}, which is always an // Clamp to {std::numeric_limits<size_t>::max()}, which is always an
// invalid offset. // invalid offset.
...@@ -983,9 +1006,9 @@ void InstanceBuilder::LoadDataSegments(Handle<WasmInstanceObject> instance) { ...@@ -983,9 +1006,9 @@ void InstanceBuilder::LoadDataSegments(Handle<WasmInstanceObject> instance) {
dest_offset = static_cast<size_t>(std::min( dest_offset = static_cast<size_t>(std::min(
dest_offset_64, uint64_t{std::numeric_limits<size_t>::max()})); dest_offset_64, uint64_t{std::numeric_limits<size_t>::max()}));
} else { } else {
dest_offset = dest_offset = EvaluateInitExpression(&init_expr_zone_, segment.dest_addr,
EvaluateInitExpression(segment.dest_addr, kWasmI32, instance) kWasmI32, isolate_, instance)
.to_u32(); .to_u32();
} }
if (!base::IsInBounds<size_t>(dest_offset, size, instance->memory_size())) { if (!base::IsInBounds<size_t>(dest_offset, size, instance->memory_size())) {
...@@ -1651,26 +1674,6 @@ T* InstanceBuilder::GetRawUntaggedGlobalPtr(const WasmGlobal& global) { ...@@ -1651,26 +1674,6 @@ T* InstanceBuilder::GetRawUntaggedGlobalPtr(const WasmGlobal& global) {
return reinterpret_cast<T*>(raw_buffer_ptr(untagged_globals_, global.offset)); return reinterpret_cast<T*>(raw_buffer_ptr(untagged_globals_, global.offset));
} }
WasmValue InstanceBuilder::EvaluateInitExpression(
WireBytesRef init, ValueType expected,
Handle<WasmInstanceObject> instance) {
base::Vector<const byte> module_bytes =
instance->module_object().native_module()->wire_bytes();
FunctionBody body(FunctionSig::Build(&init_expr_zone_, {expected}, {}),
init.offset(), module_bytes.begin() + init.offset(),
module_bytes.begin() + init.end_offset());
WasmFeatures detected;
// We use kFullValidation so we do not have to create another instance of
// WasmFullDecoder, which would cost us >50Kb binary code size.
WasmFullDecoder<Decoder::kFullValidation, InitExprInterface, kInitExpression>
decoder(&init_expr_zone_, module_, WasmFeatures::All(), &detected, body,
module_, isolate_, instance, tagged_globals_, untagged_globals_);
decoder.DecodeFunctionBody();
return decoder.interface().result();
}
// Process initialization of globals. // Process initialization of globals.
void InstanceBuilder::InitGlobals(Handle<WasmInstanceObject> instance) { void InstanceBuilder::InitGlobals(Handle<WasmInstanceObject> instance) {
for (const WasmGlobal& global : module_->globals) { for (const WasmGlobal& global : module_->globals) {
...@@ -1678,8 +1681,8 @@ void InstanceBuilder::InitGlobals(Handle<WasmInstanceObject> instance) { ...@@ -1678,8 +1681,8 @@ void InstanceBuilder::InitGlobals(Handle<WasmInstanceObject> instance) {
// Happens with imported globals. // Happens with imported globals.
if (!global.init.is_set()) continue; if (!global.init.is_set()) continue;
WasmValue value = WasmValue value = EvaluateInitExpression(&init_expr_zone_, global.init,
EvaluateInitExpression(global.init, global.type, instance); global.type, isolate_, instance);
if (global.type.is_reference()) { if (global.type.is_reference()) {
tagged_globals_->set(global.offset, *value.to_ref()); tagged_globals_->set(global.offset, *value.to_ref());
...@@ -1960,7 +1963,8 @@ void InstanceBuilder::InitializeIndirectFunctionTables( ...@@ -1960,7 +1963,8 @@ void InstanceBuilder::InitializeIndirectFunctionTables(
auto table_object = handle( auto table_object = handle(
WasmTableObject::cast(instance->tables().get(table_index)), isolate_); WasmTableObject::cast(instance->tables().get(table_index)), isolate_);
Handle<Object> value = Handle<Object> value =
EvaluateInitExpression(table.initial_value, table.type, instance) EvaluateInitExpression(&init_expr_zone_, table.initial_value,
table.type, isolate_, instance)
.to_ref(); .to_ref();
if (value.is_null()) { if (value.is_null()) {
for (uint32_t entry_index = 0; entry_index < table.initial_size; for (uint32_t entry_index = 0; entry_index < table.initial_size;
...@@ -1994,7 +1998,9 @@ void InstanceBuilder::InitializeIndirectFunctionTables( ...@@ -1994,7 +1998,9 @@ void InstanceBuilder::InitializeIndirectFunctionTables(
} }
} }
bool LoadElemSegmentImpl(Isolate* isolate, Handle<WasmInstanceObject> instance, namespace {
bool LoadElemSegmentImpl(Zone* zone, Isolate* isolate,
Handle<WasmInstanceObject> instance,
Handle<WasmTableObject> table_object, Handle<WasmTableObject> table_object,
uint32_t table_index, uint32_t segment_index, uint32_t table_index, uint32_t segment_index,
uint32_t dst, uint32_t src, size_t count) { uint32_t dst, uint32_t src, size_t count) {
...@@ -2049,6 +2055,7 @@ bool LoadElemSegmentImpl(Isolate* isolate, Handle<WasmInstanceObject> instance, ...@@ -2049,6 +2055,7 @@ bool LoadElemSegmentImpl(Isolate* isolate, Handle<WasmInstanceObject> instance,
} }
return true; return true;
} }
} // namespace
void InstanceBuilder::LoadTableSegments(Handle<WasmInstanceObject> instance) { void InstanceBuilder::LoadTableSegments(Handle<WasmInstanceObject> instance) {
for (uint32_t segment_index = 0; for (uint32_t segment_index = 0;
...@@ -2058,14 +2065,14 @@ void InstanceBuilder::LoadTableSegments(Handle<WasmInstanceObject> instance) { ...@@ -2058,14 +2065,14 @@ void InstanceBuilder::LoadTableSegments(Handle<WasmInstanceObject> instance) {
if (elem_segment.status != WasmElemSegment::kStatusActive) continue; if (elem_segment.status != WasmElemSegment::kStatusActive) continue;
uint32_t table_index = elem_segment.table_index; uint32_t table_index = elem_segment.table_index;
uint32_t dst = uint32_t dst = EvaluateInitExpression(&init_expr_zone_, elem_segment.offset,
EvaluateInitExpression(elem_segment.offset, kWasmI32, instance) kWasmI32, isolate_, instance)
.to_u32(); .to_u32();
uint32_t src = 0; uint32_t src = 0;
size_t count = elem_segment.entries.size(); size_t count = elem_segment.entries.size();
bool success = LoadElemSegmentImpl( bool success = LoadElemSegmentImpl(
isolate_, instance, &init_expr_zone_, isolate_, instance,
handle(WasmTableObject::cast( handle(WasmTableObject::cast(
instance->tables().get(elem_segment.table_index)), instance->tables().get(elem_segment.table_index)),
isolate_), isolate_),
...@@ -2108,8 +2115,13 @@ void InstanceBuilder::InitializeTags(Handle<WasmInstanceObject> instance) { ...@@ -2108,8 +2115,13 @@ void InstanceBuilder::InitializeTags(Handle<WasmInstanceObject> instance) {
bool LoadElemSegment(Isolate* isolate, Handle<WasmInstanceObject> instance, bool LoadElemSegment(Isolate* isolate, Handle<WasmInstanceObject> instance,
uint32_t table_index, uint32_t segment_index, uint32_t dst, uint32_t table_index, uint32_t segment_index, uint32_t dst,
uint32_t src, uint32_t count) { uint32_t src, uint32_t count) {
AccountingAllocator allocator;
// This {Zone} will be used only by the temporary WasmFullDecoder allocated
// down the line from this call. Therefore it is safe to stack-allocate it
// here.
Zone zone(&allocator, "LoadElemSegment");
return LoadElemSegmentImpl( return LoadElemSegmentImpl(
isolate, instance, &zone, isolate, instance,
handle(WasmTableObject::cast(instance->tables().get(table_index)), handle(WasmTableObject::cast(instance->tables().get(table_index)),
isolate), isolate),
table_index, segment_index, dst, src, count); table_index, segment_index, dst, src, count);
......
...@@ -23,6 +23,7 @@ class JSReceiver; ...@@ -23,6 +23,7 @@ class JSReceiver;
class WasmInitExpr; class WasmInitExpr;
class WasmModuleObject; class WasmModuleObject;
class WasmInstanceObject; class WasmInstanceObject;
class Zone;
template <typename T> template <typename T>
class Handle; class Handle;
......
...@@ -116,45 +116,53 @@ struct WasmDataSegment { ...@@ -116,45 +116,53 @@ struct WasmDataSegment {
// Static representation of wasm element segment (table initializer). // Static representation of wasm element segment (table initializer).
struct WasmElemSegment { struct WasmElemSegment {
enum Status {
kStatusActive, // copied automatically during instantiation.
kStatusPassive, // copied explicitly after instantiation.
kStatusDeclarative // purely declarative and never copied.
};
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) {}
};
enum ElementType { kFunctionIndexElements, kExpressionElements };
// Construct an active segment. // Construct an active segment.
WasmElemSegment(ValueType type, uint32_t table_index, WireBytesRef offset) WasmElemSegment(ValueType type, uint32_t table_index, WireBytesRef offset,
: type(type), ElementType element_type)
: status(kStatusActive),
type(type),
table_index(table_index), table_index(table_index),
offset(std::move(offset)), offset(std::move(offset)),
status(kStatusActive) {} element_type(element_type) {}
// Construct a passive or declarative segment, which has no table index or // Construct a passive or declarative segment, which has no table index or
// offset. // offset.
WasmElemSegment(ValueType type, bool declarative) WasmElemSegment(ValueType type, Status status, ElementType element_type)
: type(type), : status(status), type(type), table_index(0), element_type(element_type) {
table_index(0), DCHECK_NE(status, kStatusActive);
status(declarative ? kStatusDeclarative : kStatusPassive) {} }
// Construct a passive or declarative segment, which has no table index or // Default constructor. Constucts an invalid segment.
// offset.
WasmElemSegment() WasmElemSegment()
: type(kWasmBottom), table_index(0), status(kStatusActive) {} : status(kStatusActive),
type(kWasmBottom),
table_index(0),
element_type(kFunctionIndexElements) {}
WasmElemSegment(const WasmElemSegment&) = delete; WasmElemSegment(const WasmElemSegment&) = delete;
WasmElemSegment(WasmElemSegment&&) V8_NOEXCEPT = default; WasmElemSegment(WasmElemSegment&&) V8_NOEXCEPT = default;
WasmElemSegment& operator=(const WasmElemSegment&) = delete; WasmElemSegment& operator=(const WasmElemSegment&) = delete;
WasmElemSegment& operator=(WasmElemSegment&&) V8_NOEXCEPT = default; WasmElemSegment& operator=(WasmElemSegment&&) V8_NOEXCEPT = default;
Status status;
ValueType type; ValueType type;
uint32_t table_index; uint32_t table_index;
WireBytesRef offset; WireBytesRef offset;
struct Entry { ElementType element_type;
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; std::vector<Entry> entries;
enum Status {
kStatusActive, // copied automatically during instantiation.
kStatusPassive, // copied explicitly after instantiation.
kStatusDeclarative // purely declarative and never copied.
} status;
}; };
// Static representation of a wasm import. // Static representation of a wasm import.
......
...@@ -326,7 +326,9 @@ uint32_t TestingModuleBuilder::AddPassiveElementSegment( ...@@ -326,7 +326,9 @@ uint32_t TestingModuleBuilder::AddPassiveElementSegment(
uint32_t index = static_cast<uint32_t>(test_module_->elem_segments.size()); uint32_t index = static_cast<uint32_t>(test_module_->elem_segments.size());
DCHECK_EQ(index, dropped_elem_segments_.size()); DCHECK_EQ(index, dropped_elem_segments_.size());
test_module_->elem_segments.emplace_back(kWasmFuncRef, false); test_module_->elem_segments.emplace_back(
kWasmFuncRef, WasmElemSegment::kStatusPassive,
WasmElemSegment::kFunctionIndexElements);
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( elem_segment.entries.push_back(
......
...@@ -159,20 +159,15 @@ class TestModuleBuilder { ...@@ -159,20 +159,15 @@ class TestModuleBuilder {
} }
byte AddPassiveElementSegment(wasm::ValueType type) { byte AddPassiveElementSegment(wasm::ValueType type) {
mod.elem_segments.emplace_back(type, false); mod.elem_segments.emplace_back(type, WasmElemSegment::kStatusPassive,
auto& init = mod.elem_segments.back(); WasmElemSegment::kExpressionElements);
// Add 5 empty elements.
for (uint32_t j = 0; j < 5; j++) {
init.entries.push_back(WasmElemSegment::Entry(
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,
mod.elem_segments.back().entries.push_back(WasmElemSegment::Entry( WasmElemSegment::kStatusDeclarative,
WasmElemSegment::Entry::kRefNullEntry, HeapType::kFunc)); WasmElemSegment::kExpressionElements);
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