Commit 702cd822 authored by Clemens Backes's avatar Clemens Backes Committed by Commit Bot

[wasm] Store current table length separately

We want to grow the table entries exponentially, so the entries length
will not reflect the actual size of the table any more. Hence, introduce
another field on {WasmTableObject} to store the actual length.

R=mstarzinger@chromium.org
CC=ecmziegler@chromium.org

Bug: v8:10018
Change-Id: Ie8252f33fddda3ae60dd24bd8db148fd67262226
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1939050
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65200}
parent 42a56e03
...@@ -3381,26 +3381,25 @@ void WasmGraphBuilder::BoundsCheckTable(uint32_t table_index, Node* entry_index, ...@@ -3381,26 +3381,25 @@ void WasmGraphBuilder::BoundsCheckTable(uint32_t table_index, Node* entry_index,
Node* tables = LOAD_INSTANCE_FIELD(Tables, MachineType::TaggedPointer()); Node* tables = LOAD_INSTANCE_FIELD(Tables, MachineType::TaggedPointer());
Node* table = LOAD_FIXED_ARRAY_SLOT_ANY(tables, table_index); Node* table = LOAD_FIXED_ARRAY_SLOT_ANY(tables, table_index);
int storage_field_size = int length_field_size = WasmTableObject::kCurrentLengthOffsetEnd -
WasmTableObject::kEntriesOffsetEnd - WasmTableObject::kEntriesOffset + 1; WasmTableObject::kCurrentLengthOffset + 1;
Node* storage = LOAD_RAW( Node* length_smi = LOAD_RAW(
table, wasm::ObjectAccess::ToTagged(WasmTableObject::kEntriesOffset), table,
assert_size(storage_field_size, MachineType::TaggedPointer())); wasm::ObjectAccess::ToTagged(WasmTableObject::kCurrentLengthOffset),
assert_size(length_field_size, MachineType::TaggedSigned()));
int length_field_size = Node* length = BuildChangeSmiToInt32(length_smi);
FixedArray::kLengthOffsetEnd - FixedArray::kLengthOffset + 1;
Node* storage_size =
LOAD_RAW(storage, wasm::ObjectAccess::ToTagged(FixedArray::kLengthOffset),
assert_size(length_field_size, MachineType::TaggedSigned()));
storage_size = BuildChangeSmiToInt32(storage_size);
// Bounds check against the table size. // Bounds check against the table size.
Node* in_bounds = graph()->NewNode(mcgraph()->machine()->Uint32LessThan(), Node* in_bounds = graph()->NewNode(mcgraph()->machine()->Uint32LessThan(),
entry_index, storage_size); entry_index, length);
TrapIfFalse(trap_reason, in_bounds, position); TrapIfFalse(trap_reason, in_bounds, position);
if (base_node) { if (base_node) {
*base_node = storage; int storage_field_size = WasmTableObject::kEntriesOffsetEnd -
WasmTableObject::kEntriesOffset + 1;
*base_node = LOAD_RAW(
table, wasm::ObjectAccess::ToTagged(WasmTableObject::kEntriesOffset),
assert_size(storage_field_size, MachineType::TaggedPointer()));
} }
} }
...@@ -5073,19 +5072,14 @@ Node* WasmGraphBuilder::TableSize(uint32_t table_index) { ...@@ -5073,19 +5072,14 @@ Node* WasmGraphBuilder::TableSize(uint32_t table_index) {
Node* tables = LOAD_INSTANCE_FIELD(Tables, MachineType::TaggedPointer()); Node* tables = LOAD_INSTANCE_FIELD(Tables, MachineType::TaggedPointer());
Node* table = LOAD_FIXED_ARRAY_SLOT_ANY(tables, table_index); Node* table = LOAD_FIXED_ARRAY_SLOT_ANY(tables, table_index);
int storage_field_size = WasmTableObject::kElementsOffsetEnd - int length_field_size = WasmTableObject::kCurrentLengthOffsetEnd -
WasmTableObject::kElementsOffset + 1; WasmTableObject::kCurrentLengthOffset + 1;
Node* storage = LOAD_RAW( Node* length_smi = LOAD_RAW(
table, wasm::ObjectAccess::ToTagged(WasmTableObject::kEntriesOffset), table,
assert_size(storage_field_size, MachineType::TaggedPointer())); wasm::ObjectAccess::ToTagged(WasmTableObject::kCurrentLengthOffset),
assert_size(length_field_size, MachineType::TaggedSigned()));
int length_field_size =
FixedArray::kLengthOffsetEnd - FixedArray::kLengthOffset + 1;
Node* table_size =
LOAD_RAW(storage, wasm::ObjectAccess::ToTagged(FixedArray::kLengthOffset),
assert_size(length_field_size, MachineType::TaggedSigned()));
return BuildChangeSmiToInt32(table_size); return BuildChangeSmiToInt32(length_smi);
} }
Node* WasmGraphBuilder::TableFill(uint32_t table_index, Node* start, Node* WasmGraphBuilder::TableFill(uint32_t table_index, Node* start,
......
...@@ -562,7 +562,7 @@ RUNTIME_FUNCTION(Runtime_WasmTableFill) { ...@@ -562,7 +562,7 @@ RUNTIME_FUNCTION(Runtime_WasmTableFill) {
Handle<WasmTableObject> table( Handle<WasmTableObject> table(
WasmTableObject::cast(instance->tables().get(table_index)), isolate); WasmTableObject::cast(instance->tables().get(table_index)), isolate);
uint32_t table_size = static_cast<uint32_t>(table->entries().length()); uint32_t table_size = table->current_length();
if (start > table_size) { if (start > table_size) {
return ThrowTableOutOfBounds(isolate, instance); return ThrowTableOutOfBounds(isolate, instance);
......
...@@ -1822,7 +1822,7 @@ auto Table::type() const -> own<TableType> { ...@@ -1822,7 +1822,7 @@ auto Table::type() const -> own<TableType> {
auto Table::get(size_t index) const -> own<Ref> { auto Table::get(size_t index) const -> own<Ref> {
i::Handle<i::WasmTableObject> table = impl(this)->v8_object(); i::Handle<i::WasmTableObject> table = impl(this)->v8_object();
if (index >= table->current_length()) return own<Ref>(); if (index >= static_cast<size_t>(table->current_length())) return own<Ref>();
i::Isolate* isolate = table->GetIsolate(); i::Isolate* isolate = table->GetIsolate();
i::HandleScope handle_scope(isolate); i::HandleScope handle_scope(isolate);
i::Handle<i::Object> result = i::Handle<i::Object> result =
...@@ -1835,7 +1835,7 @@ auto Table::get(size_t index) const -> own<Ref> { ...@@ -1835,7 +1835,7 @@ auto Table::get(size_t index) const -> own<Ref> {
auto Table::set(size_t index, const Ref* ref) -> bool { auto Table::set(size_t index, const Ref* ref) -> bool {
i::Handle<i::WasmTableObject> table = impl(this)->v8_object(); i::Handle<i::WasmTableObject> table = impl(this)->v8_object();
if (index >= table->current_length()) return false; if (index >= static_cast<size_t>(table->current_length())) return false;
i::Isolate* isolate = table->GetIsolate(); i::Isolate* isolate = table->GetIsolate();
i::HandleScope handle_scope(isolate); i::HandleScope handle_scope(isolate);
i::Handle<i::Object> obj = WasmRefToV8(isolate, ref); i::Handle<i::Object> obj = WasmRefToV8(isolate, ref);
......
...@@ -490,7 +490,7 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() { ...@@ -490,7 +490,7 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
auto table_object = handle(WasmTableObject::cast(instance->tables().get( auto table_object = handle(WasmTableObject::cast(instance->tables().get(
elem_segment.table_index)), elem_segment.table_index)),
isolate_); isolate_);
size_t table_size = table_object->entries().length(); size_t table_size = table_object->current_length();
if (!base::IsInBounds(base, elem_segment.entries.size(), table_size)) { if (!base::IsInBounds(base, elem_segment.entries.size(), table_size)) {
thrower_->LinkError("table initializer is out of bounds"); thrower_->LinkError("table initializer is out of bounds");
return {}; return {};
...@@ -909,7 +909,7 @@ bool InstanceBuilder::ProcessImportedFunction( ...@@ -909,7 +909,7 @@ bool InstanceBuilder::ProcessImportedFunction(
bool InstanceBuilder::InitializeImportedIndirectFunctionTable( bool InstanceBuilder::InitializeImportedIndirectFunctionTable(
Handle<WasmInstanceObject> instance, int table_index, int import_index, Handle<WasmInstanceObject> instance, int table_index, int import_index,
Handle<WasmTableObject> table_object) { Handle<WasmTableObject> table_object) {
int imported_table_size = table_object->entries().length(); int imported_table_size = table_object->current_length();
// Allocate a new dispatch table. // Allocate a new dispatch table.
WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize( WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
instance, table_index, imported_table_size); instance, table_index, imported_table_size);
...@@ -968,7 +968,7 @@ bool InstanceBuilder::ProcessImportedTable(Handle<WasmInstanceObject> instance, ...@@ -968,7 +968,7 @@ bool InstanceBuilder::ProcessImportedTable(Handle<WasmInstanceObject> instance,
auto table_object = Handle<WasmTableObject>::cast(value); auto table_object = Handle<WasmTableObject>::cast(value);
int imported_table_size = table_object->entries().length(); int imported_table_size = table_object->current_length();
if (imported_table_size < static_cast<int>(table.initial_size)) { if (imported_table_size < static_cast<int>(table.initial_size)) {
thrower_->LinkError("table import %d is smaller than initial %d, got %u", thrower_->LinkError("table import %d is smaller than initial %d, got %u",
import_index, table.initial_size, imported_table_size); import_index, table.initial_size, imported_table_size);
...@@ -1634,7 +1634,7 @@ bool LoadElemSegmentImpl(Isolate* isolate, Handle<WasmInstanceObject> instance, ...@@ -1634,7 +1634,7 @@ bool LoadElemSegmentImpl(Isolate* isolate, Handle<WasmInstanceObject> instance,
// TODO(wasm): Move this functionality into wasm-objects, since it is used // TODO(wasm): Move this functionality into wasm-objects, since it is used
// for both instantiation and in the implementation of the table.init // for both instantiation and in the implementation of the table.init
// instruction. // instruction.
if (!base::IsInBounds(dst, count, table_object->entries().length()) || if (!base::IsInBounds(dst, count, table_object->current_length()) ||
!base::IsInBounds(src, count, elem_segment.entries.size())) { !base::IsInBounds(src, count, elem_segment.entries.size())) {
return false; return false;
} }
......
...@@ -110,6 +110,7 @@ bool WasmModuleObject::is_asm_js() { ...@@ -110,6 +110,7 @@ bool WasmModuleObject::is_asm_js() {
// WasmTableObject // WasmTableObject
ACCESSORS(WasmTableObject, entries, FixedArray, kEntriesOffset) ACCESSORS(WasmTableObject, entries, FixedArray, kEntriesOffset)
SMI_ACCESSORS(WasmTableObject, current_length, kCurrentLengthOffset)
ACCESSORS(WasmTableObject, maximum_length, Object, kMaximumLengthOffset) ACCESSORS(WasmTableObject, maximum_length, Object, kMaximumLengthOffset)
ACCESSORS(WasmTableObject, dispatch_tables, FixedArray, kDispatchTablesOffset) ACCESSORS(WasmTableObject, dispatch_tables, FixedArray, kDispatchTablesOffset)
SMI_ACCESSORS(WasmTableObject, raw_type, kRawTypeOffset) SMI_ACCESSORS(WasmTableObject, raw_type, kRawTypeOffset)
...@@ -391,8 +392,6 @@ OPTIONAL_ACCESSORS(WasmDebugInfo, c_wasm_entry_map, Managed<wasm::SignatureMap>, ...@@ -391,8 +392,6 @@ OPTIONAL_ACCESSORS(WasmDebugInfo, c_wasm_entry_map, Managed<wasm::SignatureMap>,
#undef WRITE_PRIMITIVE_FIELD #undef WRITE_PRIMITIVE_FIELD
#undef PRIMITIVE_ACCESSORS #undef PRIMITIVE_ACCESSORS
uint32_t WasmTableObject::current_length() { return entries().length(); }
wasm::ValueType WasmTableObject::type() { wasm::ValueType WasmTableObject::type() {
return static_cast<wasm::ValueType>(raw_type()); return static_cast<wasm::ValueType>(raw_type());
} }
......
...@@ -435,9 +435,10 @@ Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate, ...@@ -435,9 +435,10 @@ Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate,
isolate->factory()->NewJSObject(table_ctor)); isolate->factory()->NewJSObject(table_ctor));
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
table_obj->set_raw_type(static_cast<int>(type));
table_obj->set_entries(*backing_store); table_obj->set_entries(*backing_store);
table_obj->set_current_length(initial);
table_obj->set_maximum_length(*max); table_obj->set_maximum_length(*max);
table_obj->set_raw_type(static_cast<int>(type));
table_obj->set_dispatch_tables(ReadOnlyRoots(isolate).empty_fixed_array()); table_obj->set_dispatch_tables(ReadOnlyRoots(isolate).empty_fixed_array());
if (entries != nullptr) { if (entries != nullptr) {
...@@ -487,6 +488,7 @@ int WasmTableObject::Grow(Isolate* isolate, Handle<WasmTableObject> table, ...@@ -487,6 +488,7 @@ int WasmTableObject::Grow(Isolate* isolate, Handle<WasmTableObject> table,
auto new_store = isolate->factory()->CopyFixedArrayAndGrow( auto new_store = isolate->factory()->CopyFixedArrayAndGrow(
handle(table->entries(), isolate), count); handle(table->entries(), isolate), count);
table->set_entries(*new_store, WriteBarrierMode::UPDATE_WRITE_BARRIER); table->set_entries(*new_store, WriteBarrierMode::UPDATE_WRITE_BARRIER);
table->set_current_length(new_size);
Handle<FixedArray> dispatch_tables(table->dispatch_tables(), isolate); Handle<FixedArray> dispatch_tables(table->dispatch_tables(), isolate);
DCHECK_EQ(0, dispatch_tables->length() % kDispatchTableNumElements); DCHECK_EQ(0, dispatch_tables->length() % kDispatchTableNumElements);
...@@ -519,9 +521,7 @@ int WasmTableObject::Grow(Isolate* isolate, Handle<WasmTableObject> table, ...@@ -519,9 +521,7 @@ int WasmTableObject::Grow(Isolate* isolate, Handle<WasmTableObject> table,
bool WasmTableObject::IsInBounds(Isolate* isolate, bool WasmTableObject::IsInBounds(Isolate* isolate,
Handle<WasmTableObject> table, Handle<WasmTableObject> table,
uint32_t entry_index) { uint32_t entry_index) {
return (entry_index < return entry_index < static_cast<uint32_t>(table->current_length());
static_cast<uint32_t>(std::numeric_limits<int>::max()) &&
static_cast<int>(entry_index) < table->entries().length());
} }
bool WasmTableObject::IsValidElement(Isolate* isolate, bool WasmTableObject::IsValidElement(Isolate* isolate,
...@@ -629,9 +629,9 @@ void WasmTableObject::Fill(Isolate* isolate, Handle<WasmTableObject> table, ...@@ -629,9 +629,9 @@ void WasmTableObject::Fill(Isolate* isolate, Handle<WasmTableObject> table,
uint32_t start, Handle<Object> entry, uint32_t start, Handle<Object> entry,
uint32_t count) { uint32_t count) {
// Bounds checks must be done by the caller. // Bounds checks must be done by the caller.
DCHECK_LE(start, table->entries().length()); DCHECK_LE(start, table->current_length());
DCHECK_LE(count, table->entries().length()); DCHECK_LE(count, table->current_length());
DCHECK_LE(start + count, table->entries().length()); DCHECK_LE(start + count, table->current_length());
for (uint32_t i = 0; i < count; i++) { for (uint32_t i = 0; i < count; i++) {
WasmTableObject::Set(isolate, table, start + i, entry); WasmTableObject::Set(isolate, table, start + i, entry);
...@@ -775,7 +775,7 @@ void WasmTableObject::GetFunctionTableEntry( ...@@ -775,7 +775,7 @@ void WasmTableObject::GetFunctionTableEntry(
bool* is_valid, bool* is_null, MaybeHandle<WasmInstanceObject>* instance, bool* is_valid, bool* is_null, MaybeHandle<WasmInstanceObject>* instance,
int* function_index, MaybeHandle<WasmJSFunction>* maybe_js_function) { int* function_index, MaybeHandle<WasmJSFunction>* maybe_js_function) {
DCHECK_EQ(table->type(), wasm::kWasmFuncRef); DCHECK_EQ(table->type(), wasm::kWasmFuncRef);
DCHECK_LT(entry_index, table->entries().length()); DCHECK_LT(entry_index, table->current_length());
// We initialize {is_valid} with {true}. We may change it later. // We initialize {is_valid} with {true}. We may change it later.
*is_valid = true; *is_valid = true;
Handle<Object> element(table->entries().get(entry_index), isolate); Handle<Object> element(table->entries().get(entry_index), isolate);
...@@ -1441,8 +1441,8 @@ bool WasmInstanceObject::CopyTableEntries(Isolate* isolate, ...@@ -1441,8 +1441,8 @@ bool WasmInstanceObject::CopyTableEntries(Isolate* isolate,
WasmTableObject::cast(instance->tables().get(table_dst_index)), isolate); WasmTableObject::cast(instance->tables().get(table_dst_index)), isolate);
auto table_src = handle( auto table_src = handle(
WasmTableObject::cast(instance->tables().get(table_src_index)), isolate); WasmTableObject::cast(instance->tables().get(table_src_index)), isolate);
uint32_t max_dst = static_cast<uint32_t>(table_dst->entries().length()); uint32_t max_dst = table_dst->current_length();
uint32_t max_src = static_cast<uint32_t>(table_src->entries().length()); uint32_t max_src = table_src->current_length();
bool copy_backward = src < dst; bool copy_backward = src < dst;
if (!base::IsInBounds(dst, count, max_dst) || if (!base::IsInBounds(dst, count, max_dst) ||
!base::IsInBounds(src, count, max_src)) { !base::IsInBounds(src, count, max_src)) {
......
...@@ -204,6 +204,7 @@ class V8_EXPORT_PRIVATE WasmTableObject : public JSObject { ...@@ -204,6 +204,7 @@ class V8_EXPORT_PRIVATE WasmTableObject : public JSObject {
DECL_CAST(WasmTableObject) DECL_CAST(WasmTableObject)
DECL_ACCESSORS(entries, FixedArray) DECL_ACCESSORS(entries, FixedArray)
DECL_INT_ACCESSORS(current_length)
// TODO(titzer): introduce DECL_I64_ACCESSORS macro // TODO(titzer): introduce DECL_I64_ACCESSORS macro
DECL_ACCESSORS(maximum_length, Object) DECL_ACCESSORS(maximum_length, Object)
DECL_ACCESSORS(dispatch_tables, FixedArray) DECL_ACCESSORS(dispatch_tables, FixedArray)
...@@ -216,7 +217,6 @@ class V8_EXPORT_PRIVATE WasmTableObject : public JSObject { ...@@ -216,7 +217,6 @@ class V8_EXPORT_PRIVATE WasmTableObject : public JSObject {
DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize, DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
TORQUE_GENERATED_WASM_TABLE_OBJECT_FIELDS) TORQUE_GENERATED_WASM_TABLE_OBJECT_FIELDS)
inline uint32_t current_length();
inline wasm::ValueType type(); inline wasm::ValueType type();
static int Grow(Isolate* isolate, Handle<WasmTableObject> table, static int Grow(Isolate* isolate, Handle<WasmTableObject> table,
......
...@@ -64,6 +64,7 @@ extern class WasmModuleObject extends JSObject { ...@@ -64,6 +64,7 @@ extern class WasmModuleObject extends JSObject {
extern class WasmTableObject extends JSObject { extern class WasmTableObject extends JSObject {
entries: FixedArray; entries: FixedArray;
current_length: Smi;
maximum_length: Smi|HeapNumber|Undefined; maximum_length: Smi|HeapNumber|Undefined;
dispatch_tables: FixedArray; dispatch_tables: FixedArray;
raw_type: Smi; raw_type: Smi;
......
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