Commit b592c968 authored by Matthias Liedtke's avatar Matthias Liedtke Committed by V8 LUCI CQ

[wasm-gc] Internalize JS init value in Table::grow(number, init_value)

This change follows up on 3cc93154 on which Table::grow() was missed.

Bug: v8:7748
Change-Id: I83dc4e4894354ad8c97e577da03d67a36f6d9443
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3858227Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Auto-Submit: Matthias Liedtke <mliedtke@chromium.org>
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82752}
parent fb6d80fa
......@@ -541,7 +541,8 @@ RUNTIME_FUNCTION(Runtime_WasmTableGrow) {
Handle<WasmTableObject> table(
WasmTableObject::cast(instance.tables().get(table_index)), isolate);
int result = WasmTableObject::Grow(isolate, table, delta, value);
int result = WasmTableObject::Grow(isolate, table, delta, value,
WasmTableObject::kWasm);
return Smi::FromInt(result);
}
......
......@@ -2018,13 +2018,9 @@ auto Table::grow(size_t delta, const Ref* ref) -> bool {
i::Isolate* isolate = table->GetIsolate();
i::HandleScope scope(isolate);
i::Handle<i::Object> obj = WasmRefToV8(isolate, ref);
// TODO(7748): Generalize the condition if other table types are allowed.
if ((table->type() == i::wasm::kWasmFuncRef || table->type().has_index()) &&
!obj->IsNull()) {
obj = i::WasmInternalFunction::FromExternal(obj, isolate).ToHandleChecked();
}
int result = i::WasmTableObject::Grow(isolate, table,
static_cast<uint32_t>(delta), obj);
int result =
i::WasmTableObject::Grow(isolate, table, static_cast<uint32_t>(delta),
obj, i::WasmTableObject::kJS);
return result >= 0;
}
......
......@@ -2258,16 +2258,8 @@ void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
init_value = DefaultReferenceValue(i_isolate, receiver->type());
}
// TODO(7748): Generalize this if other table types are allowed.
bool has_function_type =
receiver->type() == i::wasm::kWasmFuncRef || receiver->type().has_index();
if (has_function_type && !init_value->IsNull()) {
init_value = i::WasmInternalFunction::FromExternal(init_value, i_isolate)
.ToHandleChecked();
}
int old_size =
i::WasmTableObject::Grow(i_isolate, receiver, grow_by, init_value);
int old_size = i::WasmTableObject::Grow(i_isolate, receiver, grow_by,
init_value, i::WasmTableObject::kJS);
if (old_size < 0) {
thrower.RangeError("failed to grow table by %u", grow_by);
......
......@@ -253,7 +253,8 @@ void WasmTableObject::AddDispatchTable(Isolate* isolate,
}
int WasmTableObject::Grow(Isolate* isolate, Handle<WasmTableObject> table,
uint32_t count, Handle<Object> init_value) {
uint32_t count, Handle<Object> init_value,
ValueRepr entry_repr) {
uint32_t old_size = table->current_length();
if (count == 0) return old_size; // Degenerate case: nothing to do.
......@@ -305,6 +306,42 @@ int WasmTableObject::Grow(Isolate* isolate, Handle<WasmTableObject> table,
instance, table_index, new_size);
}
// Instead of passing through the representation, perform an eager
// internalization of the value to avoid repeating it for every entry.
if (entry_repr == ValueRepr::kJS && !init_value->IsNull()) {
switch (table->type().heap_representation()) {
case wasm::HeapType::kExtern:
case wasm::HeapType::kString:
case wasm::HeapType::kStringViewWtf8:
case wasm::HeapType::kStringViewWtf16:
case wasm::HeapType::kStringViewIter:
break;
case wasm::HeapType::kFunc:
init_value = i::WasmInternalFunction::FromExternal(init_value, isolate)
.ToHandleChecked();
break;
case wasm::HeapType::kEq:
case wasm::HeapType::kData:
case wasm::HeapType::kArray:
case wasm::HeapType::kAny:
case wasm::HeapType::kI31:
if (!i::FLAG_wasm_gc_js_interop && entry_repr == ValueRepr::kJS) {
i::wasm::TryUnpackObjectWrapper(isolate, init_value);
}
break;
case wasm::HeapType::kBottom:
UNREACHABLE();
default:
DCHECK(!table->instance().IsUndefined());
// TODO(7748): Relax this once we have struct/array/i31ref tables.
DCHECK(WasmInstanceObject::cast(table->instance())
.module()
->has_signature(table->type().ref_index()));
init_value = i::WasmInternalFunction::FromExternal(init_value, isolate)
.ToHandleChecked();
}
}
for (uint32_t entry = old_size; entry < new_size; ++entry) {
WasmTableObject::Set(isolate, table, entry, init_value, ValueRepr::kWasm);
}
......
......@@ -176,9 +176,12 @@ class WasmTableObject
public:
inline wasm::ValueType type();
enum ValueRepr { kJS, kWasm };
V8_EXPORT_PRIVATE static int Grow(Isolate* isolate,
Handle<WasmTableObject> table,
uint32_t count, Handle<Object> init_value);
uint32_t count, Handle<Object> init_value,
ValueRepr entry_repr);
V8_EXPORT_PRIVATE static Handle<WasmTableObject> New(
Isolate* isolate, Handle<WasmInstanceObject> instance,
......@@ -196,8 +199,6 @@ class WasmTableObject
static bool IsValidElement(Isolate* isolate, Handle<WasmTableObject> table,
Handle<Object> entry);
enum ValueRepr { kJS, kWasm };
V8_EXPORT_PRIVATE static void Set(Isolate* isolate,
Handle<WasmTableObject> table,
uint32_t index, Handle<Object> entry,
......
......@@ -1942,7 +1942,8 @@ class WasmInterpreterInternals {
isolate_);
auto delta = Pop().to<uint32_t>();
auto value = Pop().to_ref();
int32_t result = WasmTableObject::Grow(isolate_, table, delta, value);
int32_t result = WasmTableObject::Grow(isolate_, table, delta, value,
WasmTableObject::kWasm);
Push(WasmValue(result));
*len += imm.length;
return true;
......
......@@ -43,15 +43,16 @@ for (let [typeName, type] of Object.entries(tableTypes)) {
let builder = new WasmModuleBuilder();
const size = 10;
const maxSize = 15;
let table = new WebAssembly.Table({
initial: size, maximum: size, element: typeName
initial: size, maximum: maxSize, element: typeName
});
let creatorSig = builder.addType(makeSig([], [type]));
let struct = builder.addStruct([makeField(kWasmI32, false)]);
let array = builder.addArray(kWasmI32, true);
builder.addImportedTable("imports", "table", size, size, type);
builder.addImportedTable("imports", "table", size, maxSize, type);
builder.addFunction("tableSet",
makeSig([kWasmI32, wasmRefType(creatorSig)], []))
.addBody([
......@@ -180,4 +181,12 @@ for (let [typeName, type] of Object.entries(tableTypes)) {
for (let i = 0; i < size; ++i) {
JSON.stringify(table.get(i));
}
if (typeName != "arrayref") {
// Grow table with explicit value.
table.grow(2, wasm.exported(wasm.createStruct));
assertEquals(12, wasm.tableGetStructVal(size));
assertEquals(12, wasm.tableGetStructVal(size + 1));
assertTraps(kTrapTableOutOfBounds, () => wasm.tableGetStructVal(size + 2));
}
}
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