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