[wasm-gc] Always use JSToWasmObject at the JS-to-Wasm boundary
- Remove the {ValueRepr} parameter from Wasm table and global object internals. It is now the responsibility of the user to transform to/from a JS object. This removes duplicate work in some cases (type checking in the caller, transforming in the callee). - For the reverse direction in the JS API, introduce {WasmObjectToJSReturnValue}. Bug: v8:7748 Change-Id: Ie7625cc0f08d38fe74dbe57e69004de2d93b8a11 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3876184 Reviewed-by: Simon Zünd <szuend@chromium.org> Reviewed-by: Matthias Liedtke <mliedtke@chromium.org> Commit-Queue: Manos Koukoutos <manoskouk@chromium.org> Cr-Commit-Position: refs/heads/main@{#83031}
This commit is contained in:
parent
a77183b126
commit
b5919c416a
@ -1035,8 +1035,7 @@ Handle<ArrayList> AddWasmTableObjectInternalProperties(
|
||||
int length = table->current_length();
|
||||
Handle<FixedArray> entries = isolate->factory()->NewFixedArray(length);
|
||||
for (int i = 0; i < length; ++i) {
|
||||
Handle<Object> entry =
|
||||
WasmTableObject::Get(isolate, table, i, WasmTableObject::kWasm);
|
||||
Handle<Object> entry = WasmTableObject::Get(isolate, table, i);
|
||||
wasm::WasmValue wasm_value(entry, table->type());
|
||||
Handle<WasmModuleObject> module(
|
||||
WasmInstanceObject::cast(table->instance()).module_object(), isolate);
|
||||
|
@ -458,8 +458,7 @@ RUNTIME_FUNCTION(Runtime_WasmFunctionTableGet) {
|
||||
return ThrowWasmError(isolate, MessageTemplate::kWasmTrapTableOutOfBounds);
|
||||
}
|
||||
|
||||
return *WasmTableObject::Get(isolate, table, entry_index,
|
||||
WasmTableObject::kWasm);
|
||||
return *WasmTableObject::Get(isolate, table, entry_index);
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_WasmFunctionTableSet) {
|
||||
@ -483,8 +482,7 @@ RUNTIME_FUNCTION(Runtime_WasmFunctionTableSet) {
|
||||
if (!WasmTableObject::IsInBounds(isolate, table, entry_index)) {
|
||||
return ThrowWasmError(isolate, MessageTemplate::kWasmTrapTableOutOfBounds);
|
||||
}
|
||||
WasmTableObject::Set(isolate, table, entry_index, element,
|
||||
WasmTableObject::kWasm);
|
||||
WasmTableObject::Set(isolate, table, entry_index, element);
|
||||
return ReadOnlyRoots(isolate).undefined_value();
|
||||
}
|
||||
|
||||
@ -548,8 +546,7 @@ RUNTIME_FUNCTION(Runtime_WasmTableGrow) {
|
||||
|
||||
Handle<WasmTableObject> table(
|
||||
WasmTableObject::cast(instance.tables().get(table_index)), isolate);
|
||||
int result = WasmTableObject::Grow(isolate, table, delta, value,
|
||||
WasmTableObject::kWasm);
|
||||
int result = WasmTableObject::Grow(isolate, table, delta, value);
|
||||
|
||||
return Smi::FromInt(result);
|
||||
}
|
||||
|
@ -1858,10 +1858,16 @@ auto Global::get() const -> Val {
|
||||
return Val(v8_global->GetF64());
|
||||
case i::wasm::kRef:
|
||||
case i::wasm::kRefNull: {
|
||||
// TODO(7748): Make sure this works for all heap types.
|
||||
// TODO(7748): Handle types other than funcref and externref if needed.
|
||||
StoreImpl* store = impl(this)->store();
|
||||
i::HandleScope scope(store->i_isolate());
|
||||
return Val(V8RefValueToWasm(store, v8_global->GetRef()));
|
||||
i::Handle<i::Object> result = v8_global->GetRef();
|
||||
if (result->IsWasmInternalFunction()) {
|
||||
result =
|
||||
handle(i::Handle<i::WasmInternalFunction>::cast(result)->external(),
|
||||
v8_global->GetIsolate());
|
||||
}
|
||||
return Val(V8RefValueToWasm(store, result));
|
||||
}
|
||||
case i::wasm::kRtt:
|
||||
case i::wasm::kS128:
|
||||
@ -1887,14 +1893,16 @@ void Global::set(const Val& val) {
|
||||
case F64:
|
||||
return v8_global->SetF64(val.f64());
|
||||
case ANYREF:
|
||||
return v8_global->SetExternRef(
|
||||
return v8_global->SetRef(
|
||||
WasmRefToV8(impl(this)->store()->i_isolate(), val.ref()));
|
||||
case FUNCREF: {
|
||||
i::Isolate* isolate = impl(this)->store()->i_isolate();
|
||||
bool result =
|
||||
v8_global->SetFuncRef(isolate, WasmRefToV8(isolate, val.ref()));
|
||||
DCHECK(result);
|
||||
USE(result);
|
||||
auto external = WasmRefToV8(impl(this)->store()->i_isolate(), val.ref());
|
||||
const char* error_message;
|
||||
auto internal = i::wasm::JSToWasmObject(isolate, nullptr, external,
|
||||
v8_global->type(), &error_message)
|
||||
.ToHandleChecked();
|
||||
v8_global->SetRef(internal);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
@ -1984,13 +1992,18 @@ auto Table::type() const -> own<TableType> {
|
||||
return TableType::make(ValType::make(kind), Limits(min, max));
|
||||
}
|
||||
|
||||
// TODO(7748): Handle types other than funcref and externref if needed.
|
||||
auto Table::get(size_t index) const -> own<Ref> {
|
||||
i::Handle<i::WasmTableObject> table = impl(this)->v8_object();
|
||||
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 = i::WasmTableObject::Get(
|
||||
isolate, table, static_cast<uint32_t>(index), i::WasmTableObject::kJS);
|
||||
i::Handle<i::Object> result =
|
||||
i::WasmTableObject::Get(isolate, table, static_cast<uint32_t>(index));
|
||||
if (result->IsWasmInternalFunction()) {
|
||||
result = handle(
|
||||
i::Handle<i::WasmInternalFunction>::cast(result)->external(), isolate);
|
||||
}
|
||||
DCHECK(result->IsNull(isolate) || result->IsJSReceiver());
|
||||
return V8RefValueToWasm(impl(this)->store(), result);
|
||||
}
|
||||
@ -2001,9 +2014,13 @@ auto Table::set(size_t index, const Ref* ref) -> bool {
|
||||
i::Isolate* isolate = table->GetIsolate();
|
||||
i::HandleScope handle_scope(isolate);
|
||||
i::Handle<i::Object> obj = WasmRefToV8(isolate, ref);
|
||||
// TODO(12868): Enforce type restrictions for stringref tables.
|
||||
i::WasmTableObject::Set(isolate, table, static_cast<uint32_t>(index), obj,
|
||||
i::WasmTableObject::kJS);
|
||||
const char* error_message;
|
||||
i::Handle<i::Object> obj_as_wasm =
|
||||
i::wasm::JSToWasmObject(isolate, nullptr, obj, table->type(),
|
||||
&error_message)
|
||||
.ToHandleChecked();
|
||||
i::WasmTableObject::Set(isolate, table, static_cast<uint32_t>(index),
|
||||
obj_as_wasm);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2017,9 +2034,13 @@ 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);
|
||||
int result =
|
||||
i::WasmTableObject::Grow(isolate, table, static_cast<uint32_t>(delta),
|
||||
obj, i::WasmTableObject::kJS);
|
||||
const char* error_message;
|
||||
i::Handle<i::Object> obj_as_wasm =
|
||||
i::wasm::JSToWasmObject(isolate, nullptr, obj, table->type(),
|
||||
&error_message)
|
||||
.ToHandleChecked();
|
||||
int result = i::WasmTableObject::Grow(
|
||||
isolate, table, static_cast<uint32_t>(delta), obj_as_wasm);
|
||||
return result >= 0;
|
||||
}
|
||||
|
||||
|
@ -1535,25 +1535,14 @@ bool InstanceBuilder::ProcessImportedGlobal(Handle<WasmInstanceObject> instance,
|
||||
|
||||
if (global.type.is_reference()) {
|
||||
const char* error_message;
|
||||
if (wasm::JSToWasmObject(isolate_, module_, value, global.type,
|
||||
&error_message)
|
||||
.is_null()) {
|
||||
Handle<Object> wasm_value;
|
||||
if (!wasm::JSToWasmObject(isolate_, module_, value, global.type,
|
||||
&error_message)
|
||||
.ToHandle(&wasm_value)) {
|
||||
ReportLinkError(error_message, global_index, module_name, import_name);
|
||||
return false;
|
||||
}
|
||||
if (IsSubtypeOf(global.type, kWasmFuncRef, module_) && !value->IsNull()) {
|
||||
value =
|
||||
WasmInternalFunction::FromExternal(value, isolate_).ToHandleChecked();
|
||||
} else if (!v8_flags.wasm_gc_js_interop &&
|
||||
global.type.heap_representation() != HeapType::kExtern &&
|
||||
!value->IsNull()) {
|
||||
bool unpacked = TryUnpackObjectWrapper(isolate_, value);
|
||||
// Excluding SMIs and stringrefs, every value received here, must have
|
||||
// been wrapped. This is ensured by JSToWasmObject().
|
||||
DCHECK_EQ(unpacked, !value->IsSmi() && !value->IsString());
|
||||
USE(unpacked); // Prevent nused warning if DCHECKs disabled.
|
||||
}
|
||||
WriteGlobalValue(global, WasmValue(value, global.type));
|
||||
WriteGlobalValue(global, WasmValue(wasm_value, global.type));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2011,8 +2000,7 @@ void InstanceBuilder::SetTableInitialValues(
|
||||
for (uint32_t entry_index = 0; entry_index < table.initial_size;
|
||||
entry_index++) {
|
||||
WasmTableObject::Set(isolate_, table_object, entry_index,
|
||||
to_value(result).to_ref(),
|
||||
WasmTableObject::kWasm);
|
||||
to_value(result).to_ref());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2061,7 +2049,7 @@ base::Optional<MessageTemplate> LoadElemSegmentImpl(
|
||||
zone, entry, elem_segment.type, isolate, instance);
|
||||
if (is_error(result)) return to_error(result);
|
||||
WasmTableObject::Set(isolate, table_object, entry_index,
|
||||
to_value(result).to_ref(), WasmTableObject::kWasm);
|
||||
to_value(result).to_ref());
|
||||
}
|
||||
}
|
||||
return {};
|
||||
|
@ -1224,15 +1224,18 @@ void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
|
||||
if (initial > 0 && args.Length() >= 2 && !args[1]->IsUndefined()) {
|
||||
i::Handle<i::Object> element = Utils::OpenHandle(*args[1]);
|
||||
if (!i::WasmTableObject::IsValidJSElement(i_isolate, table_obj, element)) {
|
||||
const char* error_message;
|
||||
if (!i::WasmTableObject::JSToWasmElement(i_isolate, table_obj, element,
|
||||
&error_message)
|
||||
.ToHandle(&element)) {
|
||||
thrower.TypeError(
|
||||
"Argument 2 must be undefined, null, or a value of type compatible "
|
||||
"with the type of the new table.");
|
||||
"Argument 2 must be undefined or a value of type compatible "
|
||||
"with the type of the new table: %s.",
|
||||
error_message);
|
||||
return;
|
||||
}
|
||||
for (uint32_t index = 0; index < static_cast<uint32_t>(initial); ++index) {
|
||||
i::WasmTableObject::Set(i_isolate, table_obj, index, element,
|
||||
i::WasmTableObject::kJS);
|
||||
i::WasmTableObject::Set(i_isolate, table_obj, index, element);
|
||||
}
|
||||
} else if (initial > 0) {
|
||||
switch (table_obj->type().heap_representation()) {
|
||||
@ -1439,26 +1442,6 @@ bool ToF64(Local<v8::Value> value, Local<Context> context, double* f64_value) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool checkAndUnpackAnyRef(i::Isolate* i_isolate,
|
||||
i::Handle<i::Object>& in_out_value,
|
||||
i::wasm::ValueType type, ErrorThrower& thrower) {
|
||||
const char* error_message = nullptr;
|
||||
auto module = nullptr;
|
||||
bool valid = !internal::wasm::JSToWasmObject(i_isolate, module, in_out_value,
|
||||
type, &error_message)
|
||||
.is_null();
|
||||
if (!valid) {
|
||||
DCHECK(error_message != nullptr);
|
||||
thrower.TypeError("%s", error_message);
|
||||
return false;
|
||||
}
|
||||
if (!internal::v8_flags.wasm_gc_js_interop) {
|
||||
internal::wasm::TryUnpackObjectWrapper(i_isolate, in_out_value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// WebAssembly.Global
|
||||
@ -1561,72 +1544,24 @@ void WebAssemblyGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
break;
|
||||
}
|
||||
case i::wasm::kRef:
|
||||
case i::wasm::kRefNull: {
|
||||
switch (type.heap_representation()) {
|
||||
case i::wasm::HeapType::kExtern: {
|
||||
if (args.Length() < 2) {
|
||||
// When no initial value is provided, we have to use the WebAssembly
|
||||
// default value 'null', and not the JS default value 'undefined'.
|
||||
global_obj->SetExternRef(i_isolate->factory()->null_value());
|
||||
break;
|
||||
}
|
||||
global_obj->SetExternRef(Utils::OpenHandle(*value));
|
||||
break;
|
||||
}
|
||||
case i::wasm::HeapType::kFunc: {
|
||||
if (args.Length() < 2) {
|
||||
// When no initial value is provided, we have to use the WebAssembly
|
||||
// default value 'null', and not the JS default value 'undefined'.
|
||||
global_obj->SetFuncRef(i_isolate,
|
||||
i_isolate->factory()->null_value());
|
||||
break;
|
||||
}
|
||||
|
||||
if (!global_obj->SetFuncRef(i_isolate, Utils::OpenHandle(*value))) {
|
||||
thrower.TypeError(
|
||||
"The value of funcref globals must be null or an "
|
||||
"exported function");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case i::wasm::HeapType::kString: {
|
||||
if (args.Length() < 2) {
|
||||
thrower.TypeError(
|
||||
"Missing initial value when creating stringref global");
|
||||
break;
|
||||
}
|
||||
|
||||
DCHECK_EQ(type.nullability(), i::wasm::kNullable);
|
||||
if (!value->IsNull() && !value->IsString()) {
|
||||
thrower.TypeError(
|
||||
"The value of stringref globals must be null or a string");
|
||||
break;
|
||||
}
|
||||
|
||||
global_obj->SetStringRef(Utils::OpenHandle(*value));
|
||||
break;
|
||||
}
|
||||
case internal::wasm::HeapType::kBottom:
|
||||
UNREACHABLE();
|
||||
case i::wasm::HeapType::kEq:
|
||||
case internal::wasm::HeapType::kI31:
|
||||
case internal::wasm::HeapType::kData:
|
||||
case internal::wasm::HeapType::kArray:
|
||||
case internal::wasm::HeapType::kAny: {
|
||||
internal::Handle<internal::Object> value_handle =
|
||||
Utils::OpenHandle(*value);
|
||||
if (checkAndUnpackAnyRef(i_isolate, value_handle, type, thrower)) {
|
||||
global_obj->SetAnyRef(value_handle);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case internal::wasm::HeapType::kStringViewWtf8:
|
||||
case internal::wasm::HeapType::kStringViewWtf16:
|
||||
case internal::wasm::HeapType::kStringViewIter:
|
||||
default:
|
||||
// TODO(7748): Implement these.
|
||||
UNIMPLEMENTED();
|
||||
if (args.Length() < 2) {
|
||||
thrower.TypeError("Non-defaultable global needs initial value");
|
||||
break;
|
||||
}
|
||||
V8_FALLTHROUGH;
|
||||
case i::wasm::kRefNull: {
|
||||
// We need the wasm default value {null} over {undefined}.
|
||||
i::Handle<i::Object> value_handle =
|
||||
(args.Length() < 2) ? i_isolate->factory()->null_value()
|
||||
: Utils::OpenHandle(*value);
|
||||
const char* error_message;
|
||||
if (!i::wasm::JSToWasmObject(i_isolate, nullptr, value_handle, type,
|
||||
&error_message)
|
||||
.ToHandle(&value_handle)) {
|
||||
thrower.TypeError("%s", error_message);
|
||||
break;
|
||||
}
|
||||
global_obj->SetRef(value_handle);
|
||||
break;
|
||||
}
|
||||
case i::wasm::kRtt:
|
||||
@ -2270,9 +2205,11 @@ void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
|
||||
if (args.Length() >= 2 && !args[1]->IsUndefined()) {
|
||||
init_value = Utils::OpenHandle(*args[1]);
|
||||
if (!i::WasmTableObject::IsValidJSElement(i_isolate, receiver,
|
||||
init_value)) {
|
||||
thrower.TypeError("Argument 1 must be a valid type for the table");
|
||||
const char* error_message;
|
||||
if (!i::WasmTableObject::JSToWasmElement(i_isolate, receiver, init_value,
|
||||
&error_message)
|
||||
.ToHandle(&init_value)) {
|
||||
thrower.TypeError("Argument 1 is invalid: %s", error_message);
|
||||
return;
|
||||
}
|
||||
} else if (receiver->type().is_non_nullable()) {
|
||||
@ -2283,9 +2220,8 @@ void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
init_value = DefaultReferenceValue(i_isolate, receiver->type());
|
||||
}
|
||||
|
||||
int old_size = i::WasmTableObject::Grow(i_isolate, receiver, grow_by,
|
||||
init_value, i::WasmTableObject::kJS);
|
||||
|
||||
int old_size =
|
||||
i::WasmTableObject::Grow(i_isolate, receiver, grow_by, init_value);
|
||||
if (old_size < 0) {
|
||||
thrower.RangeError("failed to grow table by %u", grow_by);
|
||||
return;
|
||||
@ -2294,6 +2230,83 @@ void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
return_value.Set(old_size);
|
||||
}
|
||||
|
||||
namespace {
|
||||
void WasmObjectToJSReturnValue(v8::ReturnValue<v8::Value>& return_value,
|
||||
i::Handle<i::Object> value,
|
||||
i::wasm::HeapType::Representation repr,
|
||||
const i::wasm::WasmModule* module,
|
||||
i::Isolate* isolate,
|
||||
ScheduledErrorThrower* thrower) {
|
||||
switch (repr) {
|
||||
case i::wasm::HeapType::kExtern:
|
||||
case i::wasm::HeapType::kString:
|
||||
// TODO(7748): Make sure i31ref is compatible with Smi, or transform here.
|
||||
case i::wasm::HeapType::kI31:
|
||||
return_value.Set(Utils::ToLocal(value));
|
||||
return;
|
||||
case i::wasm::HeapType::kFunc: {
|
||||
if (!value->IsNull()) {
|
||||
DCHECK(value->IsWasmInternalFunction());
|
||||
value =
|
||||
handle(i::Handle<i::WasmInternalFunction>::cast(value)->external(),
|
||||
isolate);
|
||||
}
|
||||
return_value.Set(Utils::ToLocal(value));
|
||||
return;
|
||||
}
|
||||
case i::wasm::HeapType::kStringViewWtf8:
|
||||
thrower->TypeError("stringview_wtf8 has no JS representation");
|
||||
return;
|
||||
case i::wasm::HeapType::kStringViewWtf16:
|
||||
thrower->TypeError("stringview_wtf16 has no JS representation");
|
||||
return;
|
||||
case i::wasm::HeapType::kStringViewIter:
|
||||
thrower->TypeError("stringview_iter has no JS representation");
|
||||
return;
|
||||
case i::wasm::HeapType::kBottom:
|
||||
UNREACHABLE();
|
||||
case i::wasm::HeapType::kData:
|
||||
case i::wasm::HeapType::kArray:
|
||||
case i::wasm::HeapType::kEq:
|
||||
case i::wasm::HeapType::kAny: {
|
||||
if (!i::v8_flags.wasm_gc_js_interop && value->IsWasmObject()) {
|
||||
// Transform wasm object into JS-compliant representation.
|
||||
i::Handle<i::JSObject> wrapper =
|
||||
isolate->factory()->NewJSObject(isolate->object_function());
|
||||
i::JSObject::AddProperty(
|
||||
isolate, wrapper, isolate->factory()->wasm_wrapped_object_symbol(),
|
||||
value, i::NONE);
|
||||
value = wrapper;
|
||||
}
|
||||
return_value.Set(Utils::ToLocal(value));
|
||||
return;
|
||||
}
|
||||
default:
|
||||
if (module->has_signature(repr)) {
|
||||
if (!value->IsNull()) {
|
||||
DCHECK(value->IsWasmInternalFunction());
|
||||
value = handle(
|
||||
i::Handle<i::WasmInternalFunction>::cast(value)->external(),
|
||||
isolate);
|
||||
}
|
||||
return_value.Set(Utils::ToLocal(value));
|
||||
return;
|
||||
}
|
||||
if (!i::v8_flags.wasm_gc_js_interop && value->IsWasmObject()) {
|
||||
// Transform wasm object into JS-compliant representation.
|
||||
i::Handle<i::JSObject> wrapper =
|
||||
isolate->factory()->NewJSObject(isolate->object_function());
|
||||
i::JSObject::AddProperty(
|
||||
isolate, wrapper, isolate->factory()->wasm_wrapped_object_symbol(),
|
||||
value, i::NONE);
|
||||
value = wrapper;
|
||||
}
|
||||
return_value.Set(Utils::ToLocal(value));
|
||||
return;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// WebAssembly.Table.get(num) -> any
|
||||
void WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
v8::Isolate* isolate = args.GetIsolate();
|
||||
@ -2325,11 +2338,17 @@ void WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
return;
|
||||
}
|
||||
|
||||
i::Handle<i::Object> result = i::WasmTableObject::Get(
|
||||
i_isolate, receiver, index, i::WasmTableObject::kJS);
|
||||
i::Handle<i::Object> result =
|
||||
i::WasmTableObject::Get(i_isolate, receiver, index);
|
||||
|
||||
v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
|
||||
return_value.Set(Utils::ToLocal(result));
|
||||
const i::wasm::WasmModule* module =
|
||||
receiver->instance().IsWasmInstanceObject()
|
||||
? i::WasmInstanceObject::cast(receiver->instance()).module()
|
||||
: nullptr;
|
||||
WasmObjectToJSReturnValue(return_value, result,
|
||||
receiver->type().heap_representation(), module,
|
||||
i_isolate, &thrower);
|
||||
}
|
||||
|
||||
// WebAssembly.Table.set(num, any)
|
||||
@ -2351,19 +2370,26 @@ void WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
return;
|
||||
}
|
||||
|
||||
i::Handle<i::Object> element =
|
||||
args.Length() >= 2
|
||||
? Utils::OpenHandle(*args[1])
|
||||
: DefaultReferenceValue(i_isolate, table_object->type());
|
||||
|
||||
if (!i::WasmTableObject::IsValidJSElement(i_isolate, table_object, element)) {
|
||||
thrower.TypeError("Argument 1 is invalid for table of type %s",
|
||||
i::Handle<i::Object> element;
|
||||
if (args.Length() >= 2) {
|
||||
element = Utils::OpenHandle(*args[1]);
|
||||
} else if (table_object->type().is_defaultable()) {
|
||||
element = DefaultReferenceValue(i_isolate, table_object->type());
|
||||
} else {
|
||||
thrower.TypeError("Table of non-defaultable type %s needs explicit element",
|
||||
table_object->type().name().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
i::WasmTableObject::Set(i_isolate, table_object, index, element,
|
||||
i::WasmTableObject::kJS);
|
||||
const char* error_message;
|
||||
if (!i::WasmTableObject::JSToWasmElement(i_isolate, table_object, element,
|
||||
&error_message)
|
||||
.ToHandle(&element)) {
|
||||
thrower.TypeError("Argument 1 is invalid for table: %s", error_message);
|
||||
return;
|
||||
}
|
||||
|
||||
i::WasmTableObject::Set(i_isolate, table_object, index, element);
|
||||
}
|
||||
|
||||
// WebAssembly.Table.type() -> TableType
|
||||
@ -2688,57 +2714,16 @@ void WebAssemblyGlobalGetValueCommon(
|
||||
thrower.TypeError("Can't get the value of s128 WebAssembly.Global");
|
||||
break;
|
||||
case i::wasm::kRef:
|
||||
case i::wasm::kRefNull:
|
||||
switch (receiver->type().heap_representation()) {
|
||||
case i::wasm::HeapType::kExtern:
|
||||
case i::wasm::HeapType::kString:
|
||||
return_value.Set(Utils::ToLocal(receiver->GetRef()));
|
||||
break;
|
||||
case i::wasm::HeapType::kFunc: {
|
||||
i::Handle<i::Object> result = receiver->GetRef();
|
||||
if (result->IsWasmInternalFunction()) {
|
||||
result = handle(
|
||||
i::Handle<i::WasmInternalFunction>::cast(result)->external(),
|
||||
i_isolate);
|
||||
}
|
||||
return_value.Set(Utils::ToLocal(result));
|
||||
break;
|
||||
}
|
||||
case i::wasm::HeapType::kStringViewWtf8:
|
||||
thrower.TypeError("stringview_wtf8 has no JS representation");
|
||||
break;
|
||||
case i::wasm::HeapType::kStringViewWtf16:
|
||||
thrower.TypeError("stringview_wtf16 has no JS representation");
|
||||
break;
|
||||
case i::wasm::HeapType::kStringViewIter:
|
||||
thrower.TypeError("stringview_iter has no JS representation");
|
||||
break;
|
||||
case i::wasm::HeapType::kBottom:
|
||||
UNREACHABLE();
|
||||
case i::wasm::HeapType::kI31:
|
||||
case i::wasm::HeapType::kData:
|
||||
case i::wasm::HeapType::kArray:
|
||||
case i::wasm::HeapType::kEq:
|
||||
case i::wasm::HeapType::kAny: {
|
||||
i::Handle<i::Object> result = receiver->GetRef();
|
||||
if (!i::v8_flags.wasm_gc_js_interop && result->IsWasmObject()) {
|
||||
// Transform wasm object into JS-compliant representation.
|
||||
i::Handle<i::JSObject> wrapper =
|
||||
i_isolate->factory()->NewJSObject(i_isolate->object_function());
|
||||
i::JSObject::AddProperty(
|
||||
i_isolate, wrapper,
|
||||
i_isolate->factory()->wasm_wrapped_object_symbol(), result,
|
||||
i::NONE);
|
||||
result = wrapper;
|
||||
}
|
||||
return_value.Set(Utils::ToLocal(result));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// TODO(7748): Implement these.
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
case i::wasm::kRefNull: {
|
||||
const i::wasm::WasmModule* module =
|
||||
receiver->instance().IsWasmInstanceObject()
|
||||
? i::WasmInstanceObject::cast(receiver->instance()).module()
|
||||
: nullptr;
|
||||
WasmObjectToJSReturnValue(return_value, receiver->GetRef(),
|
||||
receiver->type().heap_representation(), module,
|
||||
i_isolate, &thrower);
|
||||
break;
|
||||
}
|
||||
case i::wasm::kRtt:
|
||||
UNIMPLEMENTED(); // TODO(7748): Implement.
|
||||
case i::wasm::kI8:
|
||||
@ -2808,70 +2793,23 @@ void WebAssemblyGlobalSetValue(
|
||||
thrower.TypeError("Can't set the value of s128 WebAssembly.Global");
|
||||
break;
|
||||
case i::wasm::kRef:
|
||||
case i::wasm::kRefNull:
|
||||
switch (receiver->type().heap_representation()) {
|
||||
case i::wasm::HeapType::kExtern:
|
||||
receiver->SetExternRef(Utils::OpenHandle(*args[0]));
|
||||
break;
|
||||
case i::wasm::HeapType::kFunc: {
|
||||
if (!receiver->SetFuncRef(i_isolate, Utils::OpenHandle(*args[0]))) {
|
||||
thrower.TypeError(
|
||||
"value of an funcref reference must be either null or an "
|
||||
"exported function");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case i::wasm::HeapType::kString: {
|
||||
if (!args[0]->IsString()) {
|
||||
if (args[0]->IsNull()) {
|
||||
if (receiver->type().nullability() == i::wasm::kNonNullable) {
|
||||
thrower.TypeError(
|
||||
"Can't set non-nullable stringref global to null");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
thrower.TypeError(
|
||||
receiver->type().nullability() == i::wasm::kNonNullable
|
||||
? "Non-nullable stringref global can only hold a string"
|
||||
: "Stringref global can only hold null or a string");
|
||||
break;
|
||||
}
|
||||
}
|
||||
receiver->SetStringRef(Utils::OpenHandle(*args[0]));
|
||||
break;
|
||||
}
|
||||
case i::wasm::HeapType::kStringViewWtf8:
|
||||
thrower.TypeError("stringview_wtf8 has no JS representation");
|
||||
break;
|
||||
case i::wasm::HeapType::kStringViewWtf16:
|
||||
thrower.TypeError("stringview_wtf16 has no JS representation");
|
||||
break;
|
||||
case i::wasm::HeapType::kStringViewIter:
|
||||
thrower.TypeError("stringview_iter has no JS representation");
|
||||
break;
|
||||
case i::wasm::HeapType::kBottom:
|
||||
UNREACHABLE();
|
||||
case i::wasm::HeapType::kI31:
|
||||
case i::wasm::HeapType::kData:
|
||||
case i::wasm::HeapType::kArray:
|
||||
case i::wasm::HeapType::kEq:
|
||||
case i::wasm::HeapType::kAny: {
|
||||
internal::Handle<internal::Object> value_handle =
|
||||
Utils::OpenHandle(*args[0]);
|
||||
if (checkAndUnpackAnyRef(i_isolate, value_handle, receiver->type(),
|
||||
thrower)) {
|
||||
receiver->SetAnyRef(value_handle);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// TODO(7748): Implement these.
|
||||
UNIMPLEMENTED();
|
||||
case i::wasm::kRefNull: {
|
||||
const i::wasm::WasmModule* module =
|
||||
receiver->instance().IsWasmInstanceObject()
|
||||
? i::WasmInstanceObject::cast(receiver->instance()).module()
|
||||
: nullptr;
|
||||
i::Handle<i::Object> value = Utils::OpenHandle(*args[0]);
|
||||
const char* error_message;
|
||||
if (!i::wasm::JSToWasmObject(i_isolate, module, value, receiver->type(),
|
||||
&error_message)
|
||||
.ToHandle(&value)) {
|
||||
thrower.TypeError("%s", error_message);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
receiver->SetRef(value);
|
||||
return;
|
||||
}
|
||||
case i::wasm::kRtt:
|
||||
// TODO(7748): Implement.
|
||||
UNIMPLEMENTED();
|
||||
case i::wasm::kI8:
|
||||
case i::wasm::kI16:
|
||||
case i::wasm::kBottom:
|
||||
|
@ -166,33 +166,8 @@ void WasmGlobalObject::SetF64(double value) {
|
||||
base::WriteUnalignedValue(address(), value);
|
||||
}
|
||||
|
||||
void WasmGlobalObject::SetExternRef(Handle<Object> value) {
|
||||
DCHECK(type().is_reference_to(wasm::HeapType::kExtern));
|
||||
tagged_buffer().set(offset(), *value);
|
||||
}
|
||||
|
||||
void WasmGlobalObject::SetAnyRef(Handle<Object> value) {
|
||||
DCHECK(type().is_reference_to(wasm::HeapType::kAny) ||
|
||||
type().is_reference_to(wasm::HeapType::kEq) ||
|
||||
type().is_reference_to(wasm::HeapType::kData) ||
|
||||
type().is_reference_to(wasm::HeapType::kArray) ||
|
||||
type().is_reference_to(wasm::HeapType::kI31));
|
||||
tagged_buffer().set(offset(), *value);
|
||||
}
|
||||
|
||||
bool WasmGlobalObject::SetFuncRef(Isolate* isolate, Handle<Object> value) {
|
||||
DCHECK_EQ(type(), wasm::kWasmFuncRef);
|
||||
if (value->IsNull() ||
|
||||
WasmInternalFunction::FromExternal(value, isolate).ToHandle(&value)) {
|
||||
tagged_buffer().set(offset(), *value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void WasmGlobalObject::SetStringRef(Handle<Object> value) {
|
||||
DCHECK_EQ(type(), wasm::kWasmStringRef);
|
||||
DCHECK(value->IsNull() || value->IsString());
|
||||
void WasmGlobalObject::SetRef(Handle<Object> value) {
|
||||
DCHECK(type().is_object_reference());
|
||||
tagged_buffer().set(offset(), *value);
|
||||
}
|
||||
|
||||
|
@ -207,8 +207,7 @@ void WasmTableObject::AddDispatchTable(Isolate* isolate,
|
||||
}
|
||||
|
||||
int WasmTableObject::Grow(Isolate* isolate, Handle<WasmTableObject> table,
|
||||
uint32_t count, Handle<Object> init_value,
|
||||
ValueRepr entry_repr) {
|
||||
uint32_t count, Handle<Object> init_value) {
|
||||
uint32_t old_size = table->current_length();
|
||||
if (count == 0) return old_size; // Degenerate case: nothing to do.
|
||||
|
||||
@ -260,49 +259,8 @@ 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 (!v8_flags.wasm_gc_js_interop && entry_repr == ValueRepr::kJS) {
|
||||
wasm::TryUnpackObjectWrapper(isolate, init_value);
|
||||
}
|
||||
break;
|
||||
case wasm::HeapType::kBottom:
|
||||
UNREACHABLE();
|
||||
default:
|
||||
DCHECK(!table->instance().IsUndefined());
|
||||
const bool kIsFunc = WasmInstanceObject::cast(table->instance())
|
||||
.module()
|
||||
->has_signature(table->type().ref_index());
|
||||
if (kIsFunc) {
|
||||
init_value =
|
||||
i::WasmInternalFunction::FromExternal(init_value, isolate)
|
||||
.ToHandleChecked();
|
||||
} else if (!i::FLAG_wasm_gc_js_interop &&
|
||||
entry_repr == ValueRepr::kJS) {
|
||||
i::wasm::TryUnpackObjectWrapper(isolate, init_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t entry = old_size; entry < new_size; ++entry) {
|
||||
WasmTableObject::Set(isolate, table, entry, init_value, ValueRepr::kWasm);
|
||||
WasmTableObject::Set(isolate, table, entry, init_value);
|
||||
}
|
||||
return old_size;
|
||||
}
|
||||
@ -313,36 +271,31 @@ bool WasmTableObject::IsInBounds(Isolate* isolate,
|
||||
return entry_index < static_cast<uint32_t>(table->current_length());
|
||||
}
|
||||
|
||||
bool WasmTableObject::IsValidJSElement(Isolate* isolate,
|
||||
Handle<WasmTableObject> table,
|
||||
Handle<Object> entry) {
|
||||
MaybeHandle<Object> WasmTableObject::JSToWasmElement(
|
||||
Isolate* isolate, Handle<WasmTableObject> table, Handle<Object> entry,
|
||||
const char** error_message) {
|
||||
// Any `entry` has to be in its JS representation.
|
||||
DCHECK(!entry->IsWasmInternalFunction());
|
||||
DCHECK_IMPLIES(!v8_flags.wasm_gc_js_interop,
|
||||
!entry->IsWasmArray() && !entry->IsWasmStruct());
|
||||
const char* error_message;
|
||||
const WasmModule* module =
|
||||
!table->instance().IsUndefined()
|
||||
? WasmInstanceObject::cast(table->instance()).module()
|
||||
: nullptr;
|
||||
return !wasm::JSToWasmObject(isolate, module, entry, table->type(),
|
||||
&error_message)
|
||||
.is_null();
|
||||
return wasm::JSToWasmObject(isolate, module, entry, table->type(),
|
||||
error_message);
|
||||
}
|
||||
|
||||
void WasmTableObject::SetFunctionTableEntry(
|
||||
Isolate* isolate, Handle<WasmTableObject> table, Handle<FixedArray> entries,
|
||||
int entry_index, Handle<Object> entry, ValueRepr entry_repr) {
|
||||
void WasmTableObject::SetFunctionTableEntry(Isolate* isolate,
|
||||
Handle<WasmTableObject> table,
|
||||
Handle<FixedArray> entries,
|
||||
int entry_index,
|
||||
Handle<Object> entry) {
|
||||
if (entry->IsNull(isolate)) {
|
||||
ClearDispatchTables(isolate, table, entry_index); // Degenerate case.
|
||||
entries->set(entry_index, ReadOnlyRoots(isolate).null_value());
|
||||
return;
|
||||
}
|
||||
if (entry_repr == ValueRepr::kJS) {
|
||||
entry =
|
||||
i::WasmInternalFunction::FromExternal(entry, isolate).ToHandleChecked();
|
||||
}
|
||||
|
||||
Handle<Object> external =
|
||||
handle(Handle<WasmInternalFunction>::cast(entry)->external(), isolate);
|
||||
|
||||
@ -366,12 +319,9 @@ void WasmTableObject::SetFunctionTableEntry(
|
||||
}
|
||||
|
||||
void WasmTableObject::Set(Isolate* isolate, Handle<WasmTableObject> table,
|
||||
uint32_t index, Handle<Object> entry,
|
||||
ValueRepr entry_repr) {
|
||||
uint32_t index, Handle<Object> entry) {
|
||||
// Callers need to perform bounds checks, type check, and error handling.
|
||||
DCHECK(IsInBounds(isolate, table, index));
|
||||
DCHECK_IMPLIES(entry_repr == WasmTableObject::kJS,
|
||||
IsValidJSElement(isolate, table, entry));
|
||||
|
||||
Handle<FixedArray> entries(table->entries(), isolate);
|
||||
// The FixedArray is addressed with int's.
|
||||
@ -383,22 +333,16 @@ void WasmTableObject::Set(Isolate* isolate, Handle<WasmTableObject> table,
|
||||
case wasm::HeapType::kStringViewWtf8:
|
||||
case wasm::HeapType::kStringViewWtf16:
|
||||
case wasm::HeapType::kStringViewIter:
|
||||
entries->set(entry_index, *entry);
|
||||
return;
|
||||
case wasm::HeapType::kFunc:
|
||||
SetFunctionTableEntry(isolate, table, entries, entry_index, entry,
|
||||
entry_repr);
|
||||
return;
|
||||
case wasm::HeapType::kEq:
|
||||
case wasm::HeapType::kData:
|
||||
case wasm::HeapType::kArray:
|
||||
case wasm::HeapType::kAny:
|
||||
case wasm::HeapType::kI31:
|
||||
if (!v8_flags.wasm_gc_js_interop && entry_repr == ValueRepr::kJS) {
|
||||
wasm::TryUnpackObjectWrapper(isolate, entry);
|
||||
}
|
||||
entries->set(entry_index, *entry);
|
||||
return;
|
||||
case wasm::HeapType::kFunc:
|
||||
SetFunctionTableEntry(isolate, table, entries, entry_index, entry);
|
||||
return;
|
||||
case wasm::HeapType::kBottom:
|
||||
UNREACHABLE();
|
||||
default:
|
||||
@ -406,14 +350,9 @@ void WasmTableObject::Set(Isolate* isolate, Handle<WasmTableObject> table,
|
||||
if (WasmInstanceObject::cast(table->instance())
|
||||
.module()
|
||||
->has_signature(table->type().ref_index())) {
|
||||
SetFunctionTableEntry(isolate, table, entries, entry_index, entry,
|
||||
entry_repr);
|
||||
SetFunctionTableEntry(isolate, table, entries, entry_index, entry);
|
||||
return;
|
||||
}
|
||||
// Indexed struct and array types.
|
||||
if (!i::FLAG_wasm_gc_js_interop && entry_repr == ValueRepr::kJS) {
|
||||
i::wasm::TryUnpackObjectWrapper(isolate, entry);
|
||||
}
|
||||
entries->set(entry_index, *entry);
|
||||
return;
|
||||
}
|
||||
@ -421,7 +360,7 @@ void WasmTableObject::Set(Isolate* isolate, Handle<WasmTableObject> table,
|
||||
|
||||
Handle<Object> WasmTableObject::Get(Isolate* isolate,
|
||||
Handle<WasmTableObject> table,
|
||||
uint32_t index, ValueRepr as_repr) {
|
||||
uint32_t index) {
|
||||
Handle<FixedArray> entries(table->entries(), isolate);
|
||||
// Callers need to perform bounds checks and error handling.
|
||||
DCHECK(IsInBounds(isolate, table, index));
|
||||
@ -439,35 +378,16 @@ Handle<Object> WasmTableObject::Get(Isolate* isolate,
|
||||
case wasm::HeapType::kStringViewWtf8:
|
||||
case wasm::HeapType::kStringViewWtf16:
|
||||
case wasm::HeapType::kStringViewIter:
|
||||
DCHECK(as_repr != ValueRepr::kJS); // No representation in JavaScript.
|
||||
return entry;
|
||||
case wasm::HeapType::kExtern:
|
||||
case wasm::HeapType::kString:
|
||||
return entry;
|
||||
case wasm::HeapType::kEq:
|
||||
case wasm::HeapType::kI31:
|
||||
case wasm::HeapType::kData:
|
||||
case wasm::HeapType::kArray:
|
||||
case wasm::HeapType::kAny:
|
||||
if (as_repr == ValueRepr::kJS && !v8_flags.wasm_gc_js_interop &&
|
||||
entry->IsWasmObject()) {
|
||||
// Transform wasm object into JS-compliant representation.
|
||||
Handle<JSObject> wrapper =
|
||||
isolate->factory()->NewJSObject(isolate->object_function());
|
||||
JSObject::AddProperty(isolate, wrapper,
|
||||
isolate->factory()->wasm_wrapped_object_symbol(),
|
||||
entry, NONE);
|
||||
return wrapper;
|
||||
}
|
||||
return entry;
|
||||
case wasm::HeapType::kFunc:
|
||||
if (entry->IsWasmInternalFunction()) {
|
||||
return as_repr == ValueRepr::kJS
|
||||
? handle(
|
||||
Handle<WasmInternalFunction>::cast(entry)->external(),
|
||||
isolate)
|
||||
: entry;
|
||||
}
|
||||
if (entry->IsWasmInternalFunction()) return entry;
|
||||
break;
|
||||
case wasm::HeapType::kBottom:
|
||||
UNREACHABLE();
|
||||
@ -477,26 +397,10 @@ Handle<Object> WasmTableObject::Get(Isolate* isolate,
|
||||
WasmInstanceObject::cast(table->instance()).module();
|
||||
if (module->has_array(table->type().ref_index()) ||
|
||||
module->has_struct(table->type().ref_index())) {
|
||||
if (as_repr == ValueRepr::kJS && !FLAG_wasm_gc_js_interop &&
|
||||
!entry->IsNull()) {
|
||||
// Transform wasm object into JS-compliant representation.
|
||||
Handle<JSObject> wrapper =
|
||||
isolate->factory()->NewJSObject(isolate->object_function());
|
||||
JSObject::AddProperty(
|
||||
isolate, wrapper,
|
||||
isolate->factory()->wasm_wrapped_object_symbol(), entry, NONE);
|
||||
return wrapper;
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
DCHECK(module->has_signature(table->type().ref_index()));
|
||||
if (entry->IsWasmInternalFunction()) {
|
||||
return as_repr == ValueRepr::kJS
|
||||
? handle(
|
||||
Handle<WasmInternalFunction>::cast(entry)->external(),
|
||||
isolate)
|
||||
: entry;
|
||||
}
|
||||
if (entry->IsWasmInternalFunction()) return entry;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -512,8 +416,7 @@ Handle<Object> WasmTableObject::Get(Isolate* isolate,
|
||||
WasmInstanceObject::GetOrCreateWasmInternalFunction(isolate, instance,
|
||||
function_index);
|
||||
entries->set(entry_index, *internal);
|
||||
return as_repr == ValueRepr::kJS ? handle(internal->external(), isolate)
|
||||
: internal;
|
||||
return internal;
|
||||
}
|
||||
|
||||
void WasmTableObject::Fill(Isolate* isolate, Handle<WasmTableObject> table,
|
||||
@ -525,7 +428,7 @@ void WasmTableObject::Fill(Isolate* isolate, Handle<WasmTableObject> table,
|
||||
DCHECK_LE(start + count, table->current_length());
|
||||
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
WasmTableObject::Set(isolate, table, start + i, entry, ValueRepr::kWasm);
|
||||
WasmTableObject::Set(isolate, table, start + i, entry);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1431,10 +1334,8 @@ bool WasmInstanceObject::CopyTableEntries(Isolate* isolate,
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
uint32_t src_index = copy_backward ? (src + count - i - 1) : src + i;
|
||||
uint32_t dst_index = copy_backward ? (dst + count - i - 1) : dst + i;
|
||||
auto repr =
|
||||
WasmTableObject::kWasm; // Do not externalize / internalize values.
|
||||
auto value = WasmTableObject::Get(isolate, table_src, src_index, repr);
|
||||
WasmTableObject::Set(isolate, table_dst, dst_index, value, repr);
|
||||
auto value = WasmTableObject::Get(isolate, table_src, src_index);
|
||||
WasmTableObject::Set(isolate, table_dst, dst_index, value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -2335,8 +2236,10 @@ Handle<AsmWasmData> AsmWasmData::New(
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace wasm {
|
||||
|
||||
namespace {
|
||||
// If {in_out_value} is a wrapped wasm struct/array, it gets unwrapped in-place
|
||||
// and this returns {true}. Otherwise, the value remains unchanged and this
|
||||
// returns {false}.
|
||||
bool TryUnpackObjectWrapper(Isolate* isolate, Handle<Object>& in_out_value) {
|
||||
if (in_out_value->IsUndefined(isolate) || in_out_value->IsNull(isolate) ||
|
||||
!in_out_value->IsJSObject()) {
|
||||
@ -2349,7 +2252,9 @@ bool TryUnpackObjectWrapper(Isolate* isolate, Handle<Object>& in_out_value) {
|
||||
in_out_value = it.GetDataValue();
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace wasm {
|
||||
MaybeHandle<Object> JSToWasmObject(Isolate* isolate, const WasmModule* module,
|
||||
Handle<Object> value, ValueType expected,
|
||||
const char** error_message) {
|
||||
@ -2376,7 +2281,8 @@ MaybeHandle<Object> JSToWasmObject(Isolate* isolate, const WasmModule* module,
|
||||
case kRef: {
|
||||
// TODO(7748): Follow any changes in proposed JS API. In particular,
|
||||
// finalize the v8_flags.wasm_gc_js_interop situation.
|
||||
// TODO(7748): Allow all in-range numbers for i31.
|
||||
// TODO(7748): Allow all in-range numbers for i31. Make sure to convert
|
||||
// Smis to i31refs if needed.
|
||||
// TODO(7748): Streamline interaction of undefined and (ref any).
|
||||
HeapType::Representation repr = expected.heap_representation();
|
||||
switch (repr) {
|
||||
|
@ -176,12 +176,9 @@ 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,
|
||||
ValueRepr entry_repr);
|
||||
uint32_t count, Handle<Object> init_value);
|
||||
|
||||
V8_EXPORT_PRIVATE static Handle<WasmTableObject> New(
|
||||
Isolate* isolate, Handle<WasmInstanceObject> instance,
|
||||
@ -196,18 +193,21 @@ class WasmTableObject
|
||||
static bool IsInBounds(Isolate* isolate, Handle<WasmTableObject> table,
|
||||
uint32_t entry_index);
|
||||
|
||||
static bool IsValidJSElement(Isolate* isolate, Handle<WasmTableObject> table,
|
||||
Handle<Object> entry);
|
||||
// Thin wrapper around {JsToWasmObject}.
|
||||
static MaybeHandle<Object> JSToWasmElement(Isolate* isolate,
|
||||
Handle<WasmTableObject> table,
|
||||
Handle<Object> entry,
|
||||
const char** error_message);
|
||||
|
||||
// This function will not handle JS objects; i.e., {entry} needs to be in wasm
|
||||
// representation.
|
||||
V8_EXPORT_PRIVATE static void Set(Isolate* isolate,
|
||||
Handle<WasmTableObject> table,
|
||||
uint32_t index, Handle<Object> entry,
|
||||
ValueRepr entry_repr);
|
||||
uint32_t index, Handle<Object> entry);
|
||||
|
||||
V8_EXPORT_PRIVATE static Handle<Object> Get(Isolate* isolate,
|
||||
Handle<WasmTableObject> table,
|
||||
uint32_t index,
|
||||
ValueRepr as_repr);
|
||||
uint32_t index);
|
||||
|
||||
V8_EXPORT_PRIVATE static void Fill(Isolate* isolate,
|
||||
Handle<WasmTableObject> table,
|
||||
@ -249,7 +249,7 @@ class WasmTableObject
|
||||
static void SetFunctionTableEntry(Isolate* isolate,
|
||||
Handle<WasmTableObject> table,
|
||||
Handle<FixedArray> entries, int entry_index,
|
||||
Handle<Object> entry, ValueRepr entry_repr);
|
||||
Handle<Object> entry);
|
||||
|
||||
TQ_OBJECT_CONSTRUCTORS(WasmTableObject)
|
||||
};
|
||||
@ -314,10 +314,8 @@ class WasmGlobalObject
|
||||
inline void SetI64(int64_t value);
|
||||
inline void SetF32(float value);
|
||||
inline void SetF64(double value);
|
||||
inline void SetExternRef(Handle<Object> value);
|
||||
inline void SetAnyRef(Handle<Object> value);
|
||||
inline bool SetFuncRef(Isolate* isolate, Handle<Object> value);
|
||||
inline void SetStringRef(Handle<Object> value);
|
||||
// {value} must be an object in Wasm representation.
|
||||
inline void SetRef(Handle<Object> value);
|
||||
|
||||
private:
|
||||
// This function returns the address of the global's data in the
|
||||
@ -1075,11 +1073,6 @@ namespace wasm {
|
||||
MaybeHandle<Object> JSToWasmObject(Isolate* isolate, const WasmModule* module,
|
||||
Handle<Object> value, ValueType expected,
|
||||
const char** error_message);
|
||||
|
||||
// If {in_out_value} is a wrapped wasm struct/array, it gets unwrapped in-place
|
||||
// and this returns {true}. Otherwise, the value remains unchanged and this
|
||||
// returns {false}.
|
||||
bool TryUnpackObjectWrapper(Isolate* isolate, Handle<Object>& in_out_value);
|
||||
} // namespace wasm
|
||||
|
||||
} // namespace internal
|
||||
|
@ -377,8 +377,7 @@ void CheckTable(Isolate* isolate, Handle<WasmTableObject> table, Args... args) {
|
||||
CHECK_EQ(table->current_length(), args_length);
|
||||
Handle<Object> handles[] = {args...};
|
||||
for (uint32_t i = 0; i < args_length; ++i) {
|
||||
CHECK(WasmTableObject::Get(isolate, table, i, WasmTableObject::kWasm)
|
||||
.is_identical_to(handles[i]));
|
||||
CHECK(WasmTableObject::Get(isolate, table, i).is_identical_to(handles[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@ -573,11 +572,11 @@ void TestTableCopyElems(TestExecutionTier execution_tier, int table_dst,
|
||||
r.builder().instance_object()->tables().get(table_dst)),
|
||||
isolate);
|
||||
r.CheckCallViaJS(0, 0, 0, kTableSize);
|
||||
auto f0 = WasmTableObject::Get(isolate, table, 0, WasmTableObject::kWasm);
|
||||
auto f1 = WasmTableObject::Get(isolate, table, 1, WasmTableObject::kWasm);
|
||||
auto f2 = WasmTableObject::Get(isolate, table, 2, WasmTableObject::kWasm);
|
||||
auto f3 = WasmTableObject::Get(isolate, table, 3, WasmTableObject::kWasm);
|
||||
auto f4 = WasmTableObject::Get(isolate, table, 4, WasmTableObject::kWasm);
|
||||
auto f0 = WasmTableObject::Get(isolate, table, 0);
|
||||
auto f1 = WasmTableObject::Get(isolate, table, 1);
|
||||
auto f2 = WasmTableObject::Get(isolate, table, 2);
|
||||
auto f3 = WasmTableObject::Get(isolate, table, 3);
|
||||
auto f4 = WasmTableObject::Get(isolate, table, 4);
|
||||
|
||||
if (table_dst == table_src) {
|
||||
CheckTable(isolate, table, f0, f1, f2, f3, f4);
|
||||
@ -723,11 +722,11 @@ void TestTableCopyOobWrites(TestExecutionTier execution_tier, int table_dst,
|
||||
isolate);
|
||||
// Fill the dst table with values from the src table, to make checks easier.
|
||||
r.CheckCallViaJS(0, 0, 0, kTableSize);
|
||||
auto f0 = WasmTableObject::Get(isolate, table, 0, WasmTableObject::kWasm);
|
||||
auto f1 = WasmTableObject::Get(isolate, table, 1, WasmTableObject::kWasm);
|
||||
auto f2 = WasmTableObject::Get(isolate, table, 2, WasmTableObject::kWasm);
|
||||
auto f3 = WasmTableObject::Get(isolate, table, 3, WasmTableObject::kWasm);
|
||||
auto f4 = WasmTableObject::Get(isolate, table, 4, WasmTableObject::kWasm);
|
||||
auto f0 = WasmTableObject::Get(isolate, table, 0);
|
||||
auto f1 = WasmTableObject::Get(isolate, table, 1);
|
||||
auto f2 = WasmTableObject::Get(isolate, table, 2);
|
||||
auto f3 = WasmTableObject::Get(isolate, table, 3);
|
||||
auto f4 = WasmTableObject::Get(isolate, table, 4);
|
||||
|
||||
CheckTable(isolate, table, f0, f1, f2, f3, f4);
|
||||
|
||||
|
@ -336,8 +336,8 @@ TEST(WrapperReplacement_IndirectExport) {
|
||||
Handle<WasmTableObject> table(
|
||||
WasmTableObject::cast(instance->tables().get(table_index)), isolate);
|
||||
// Get the Wasm function through the exported table.
|
||||
Handle<Object> function = WasmTableObject::Get(
|
||||
isolate, table, function_index, WasmTableObject::kWasm);
|
||||
Handle<Object> function =
|
||||
WasmTableObject::Get(isolate, table, function_index);
|
||||
Handle<WasmExportedFunction> indirect_function(
|
||||
WasmExportedFunction::cast(
|
||||
WasmInternalFunction::cast(*function).external()),
|
||||
|
@ -1942,8 +1942,7 @@ class WasmInterpreterInternals {
|
||||
isolate_);
|
||||
auto delta = Pop().to<uint32_t>();
|
||||
auto value = Pop().to_ref();
|
||||
int32_t result = WasmTableObject::Grow(isolate_, table, delta, value,
|
||||
WasmTableObject::kWasm);
|
||||
int32_t result = WasmTableObject::Grow(isolate_, table, delta, value);
|
||||
Push(WasmValue(result));
|
||||
*len += imm.length;
|
||||
return true;
|
||||
@ -3703,8 +3702,8 @@ class WasmInterpreterInternals {
|
||||
if (entry_index >= table_size) {
|
||||
return DoTrap(kTrapTableOutOfBounds, pc);
|
||||
}
|
||||
Handle<Object> value = WasmTableObject::Get(
|
||||
isolate_, table, entry_index, WasmTableObject::kWasm);
|
||||
Handle<Object> value =
|
||||
WasmTableObject::Get(isolate_, table, entry_index);
|
||||
Push(WasmValue(value, table->type()));
|
||||
len = 1 + imm.length;
|
||||
break;
|
||||
@ -3722,8 +3721,7 @@ class WasmInterpreterInternals {
|
||||
if (entry_index >= table_size) {
|
||||
return DoTrap(kTrapTableOutOfBounds, pc);
|
||||
}
|
||||
WasmTableObject::Set(isolate_, table, entry_index, value,
|
||||
WasmTableObject::kWasm);
|
||||
WasmTableObject::Set(isolate_, table, entry_index, value);
|
||||
len = 1 + imm.length;
|
||||
break;
|
||||
}
|
||||
|
@ -715,18 +715,19 @@ assertThrows(
|
||||
/must be convertible to a valid number/);
|
||||
assertThrows(
|
||||
() => set.call(tbl1, 0, undefined), TypeError,
|
||||
/Argument 1 is invalid for table of type funcref/);
|
||||
/Argument 1 is invalid for table: /);
|
||||
assertThrows(
|
||||
() => set.call(tbl1, undefined, undefined), TypeError,
|
||||
/must be convertible to a valid number/);
|
||||
assertThrows(
|
||||
() => set.call(tbl1, 0, {}), TypeError,
|
||||
/Argument 1 is invalid for table of type funcref/);
|
||||
assertThrows(() => set.call(tbl1, 0, function() {}),
|
||||
TypeError, /Argument 1 is invalid for table of type funcref/);
|
||||
/Argument 1 is invalid for table:.*null.*or a Wasm function object/);
|
||||
assertThrows(
|
||||
() => set.call(tbl1, 0, function() {}), TypeError,
|
||||
/Argument 1 is invalid for table:.*null.*or a Wasm function object/);
|
||||
assertThrows(
|
||||
() => set.call(tbl1, 0, Math.sin), TypeError,
|
||||
/Argument 1 is invalid for table of type funcref/);
|
||||
/Argument 1 is invalid for table:.*null.*or a Wasm function object/);
|
||||
assertThrows(
|
||||
() => set.call(tbl1, {valueOf() { throw Error('hai') }}, null), Error,
|
||||
'hai');
|
||||
|
@ -99,7 +99,7 @@ d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
assertThrows(
|
||||
() => instance.exports.table.set(0, exporting_instance.exports.addition),
|
||||
TypeError,
|
||||
/Argument 1 is invalid for table of type \(ref null 0\)/);
|
||||
/Argument 1 is invalid for table: assigned exported function has to be a subtype of the expected type/);
|
||||
})();
|
||||
|
||||
(function TestNonNullableTables() {
|
||||
|
@ -197,10 +197,10 @@ function assertInvalid(fn, message) {
|
||||
TypeError, msg);
|
||||
}
|
||||
|
||||
assertThrows(()=>new WebAssembly.Global({ value: 'stringref' }),
|
||||
TypeError,
|
||||
"WebAssembly.Global(): " +
|
||||
"Missing initial value when creating stringref global");
|
||||
// String with default initializer.
|
||||
// TODO(12868): Is this the intended behavior?
|
||||
let null_str = new WebAssembly.Global({ value: 'stringref' });
|
||||
assertEquals(null, null_str.value);
|
||||
|
||||
let kSig_w_v = makeSig([], [kWasmStringRef]);
|
||||
let kSig_v_w = makeSig([kWasmStringRef], []);
|
||||
@ -302,8 +302,8 @@ function assertInvalid(fn, message) {
|
||||
let unsupportedGetMessage =
|
||||
`WebAssembly.Table.get(): ${type} has no JS representation`;
|
||||
let unsupportedSetMessage =
|
||||
'WebAssembly.Table.set(): Argument 1 is invalid for table of type '
|
||||
+ `${type}ref`;
|
||||
'WebAssembly.Table.set(): Argument 1 is invalid for table: '
|
||||
+ `${type} has no JS representation`;
|
||||
assertThrows(()=>table.get(0), TypeError, unsupportedGetMessage);
|
||||
assertThrows(()=>{table.set(0, null);}, TypeError, unsupportedSetMessage);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user