[wasm-gc] Make extern.* instructions constant
Bug: v8:7748 Change-Id: Iabd6419055a7ec4824e58edfc38ac1d30b7f7be1 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4194193 Commit-Queue: Manos Koukoutos <manoskouk@chromium.org> Reviewed-by: Matthias Liedtke <mliedtke@chromium.org> Cr-Commit-Position: refs/heads/main@{#85482}
This commit is contained in:
parent
22bef706e1
commit
ca27aeeff1
@ -42,6 +42,33 @@ void ConstantExpressionInterface::S128Const(FullDecoder* decoder,
|
||||
result->runtime_value = WasmValue(imm.value, kWasmS128);
|
||||
}
|
||||
|
||||
void ConstantExpressionInterface::UnOp(FullDecoder* decoder, WasmOpcode opcode,
|
||||
const Value& input, Value* result) {
|
||||
if (!generate_value()) return;
|
||||
switch (opcode) {
|
||||
case kExprExternExternalize: {
|
||||
const char* error_message = nullptr;
|
||||
result->runtime_value = WasmValue(
|
||||
WasmToJSObject(isolate_, input.runtime_value.to_ref(),
|
||||
input.type.heap_type(), &error_message)
|
||||
.ToHandleChecked(),
|
||||
ValueType::RefMaybeNull(HeapType::kExtern, input.type.nullability()));
|
||||
break;
|
||||
}
|
||||
case kExprExternInternalize: {
|
||||
const char* error_message = nullptr;
|
||||
result->runtime_value = WasmValue(
|
||||
JSToWasmObject(isolate_, input.runtime_value.to_ref(), kWasmAnyRef,
|
||||
&error_message)
|
||||
.ToHandleChecked(),
|
||||
ValueType::RefMaybeNull(HeapType::kAny, input.type.nullability()));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
void ConstantExpressionInterface::BinOp(FullDecoder* decoder, WasmOpcode opcode,
|
||||
const Value& lhs, const Value& rhs,
|
||||
Value* result) {
|
||||
|
@ -970,6 +970,7 @@ struct ControlBase : public PcForErrors<ValidationTag::full_validation> {
|
||||
F(S128Const, Simd128Immediate& imm, Value* result) \
|
||||
F(GlobalGet, Value* result, const GlobalIndexImmediate& imm) \
|
||||
F(DoReturn, uint32_t drop_values) \
|
||||
F(UnOp, WasmOpcode opcode, const Value& value, Value* result) \
|
||||
F(BinOp, WasmOpcode opcode, const Value& lhs, const Value& rhs, \
|
||||
Value* result) \
|
||||
F(RefNull, ValueType type, Value* result) \
|
||||
@ -1000,7 +1001,6 @@ struct ControlBase : public PcForErrors<ValidationTag::full_validation> {
|
||||
F(FallThruTo, Control* c) \
|
||||
F(PopControl, Control* block) \
|
||||
/* Instructions: */ \
|
||||
F(UnOp, WasmOpcode opcode, const Value& value, Value* result) \
|
||||
F(RefAsNonNull, const Value& arg, Value* result) \
|
||||
F(Drop) \
|
||||
F(LocalGet, Value* result, const IndexImmediate& imm) \
|
||||
@ -5708,7 +5708,6 @@ class WasmFullDecoder : public WasmDecoder<ValidationTag, decoding_mode> {
|
||||
return opcode_length + branch_depth.length;
|
||||
}
|
||||
case kExprExternInternalize: {
|
||||
NON_CONST_ONLY
|
||||
Value extern_val = Peek(0, 0, kWasmExternRef);
|
||||
ValueType intern_type = ValueType::RefMaybeNull(
|
||||
HeapType::kAny, Nullability(extern_val.type.is_nullable()));
|
||||
@ -5720,7 +5719,6 @@ class WasmFullDecoder : public WasmDecoder<ValidationTag, decoding_mode> {
|
||||
return opcode_length;
|
||||
}
|
||||
case kExprExternExternalize: {
|
||||
NON_CONST_ONLY
|
||||
Value val = Peek(0, 0, kWasmAnyRef);
|
||||
ValueType extern_type = ValueType::RefMaybeNull(
|
||||
HeapType::kExtern, Nullability(val.type.is_nullable()));
|
||||
|
@ -2261,55 +2261,15 @@ void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
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,
|
||||
i::wasm::HeapType type, i::Isolate* isolate,
|
||||
ScheduledErrorThrower* thrower) {
|
||||
switch (repr) {
|
||||
case i::wasm::HeapType::kExtern:
|
||||
case i::wasm::HeapType::kString:
|
||||
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::kStruct:
|
||||
case i::wasm::HeapType::kArray:
|
||||
case i::wasm::HeapType::kEq:
|
||||
case i::wasm::HeapType::kAny: {
|
||||
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;
|
||||
const char* error_message = nullptr;
|
||||
i::MaybeHandle<i::Object> maybe_result =
|
||||
i::wasm::WasmToJSObject(isolate, value, type, &error_message);
|
||||
if (maybe_result.is_null()) {
|
||||
thrower->TypeError("%s", error_message);
|
||||
} else {
|
||||
return_value.Set(Utils::ToLocal(maybe_result.ToHandleChecked()));
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
@ -2349,12 +2309,7 @@ void WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
i::WasmTableObject::Get(i_isolate, receiver, index);
|
||||
|
||||
v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
|
||||
const i::wasm::WasmModule* module =
|
||||
receiver->instance().IsWasmInstanceObject()
|
||||
? i::WasmInstanceObject::cast(receiver->instance()).module()
|
||||
: nullptr;
|
||||
WasmObjectToJSReturnValue(return_value, result,
|
||||
receiver->type().heap_representation(), module,
|
||||
WasmObjectToJSReturnValue(return_value, result, receiver->type().heap_type(),
|
||||
i_isolate, &thrower);
|
||||
}
|
||||
|
||||
@ -2722,13 +2677,9 @@ void WebAssemblyGlobalGetValueCommon(
|
||||
break;
|
||||
case i::wasm::kRef:
|
||||
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);
|
||||
receiver->type().heap_type(), i_isolate,
|
||||
&thrower);
|
||||
break;
|
||||
}
|
||||
case i::wasm::kRtt:
|
||||
|
@ -2415,6 +2415,49 @@ MaybeHandle<Object> JSToWasmObject(Isolate* isolate, const WasmModule* module,
|
||||
return JSToWasmObject(isolate, value, expected_canonical, error_message);
|
||||
}
|
||||
|
||||
MaybeHandle<Object> WasmToJSObject(Isolate* isolate, Handle<Object> value,
|
||||
HeapType type, const char** error_message) {
|
||||
switch (type.representation()) {
|
||||
case i::wasm::HeapType::kExtern:
|
||||
case i::wasm::HeapType::kString:
|
||||
case i::wasm::HeapType::kI31:
|
||||
case i::wasm::HeapType::kStruct:
|
||||
case i::wasm::HeapType::kArray:
|
||||
case i::wasm::HeapType::kEq:
|
||||
case i::wasm::HeapType::kAny:
|
||||
return value;
|
||||
case i::wasm::HeapType::kFunc: {
|
||||
if (!value->IsNull()) {
|
||||
DCHECK(value->IsWasmInternalFunction());
|
||||
return handle(
|
||||
i::Handle<i::WasmInternalFunction>::cast(value)->external(),
|
||||
isolate);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
case i::wasm::HeapType::kStringViewWtf8:
|
||||
*error_message = "stringview_wtf8 has no JS representation";
|
||||
return {};
|
||||
case i::wasm::HeapType::kStringViewWtf16:
|
||||
*error_message = "stringview_wtf16 has no JS representation";
|
||||
return {};
|
||||
case i::wasm::HeapType::kStringViewIter:
|
||||
*error_message = "stringview_iter has no JS representation";
|
||||
return {};
|
||||
case i::wasm::HeapType::kBottom:
|
||||
UNREACHABLE();
|
||||
default:
|
||||
if (value->IsWasmInternalFunction()) {
|
||||
return handle(
|
||||
i::Handle<i::WasmInternalFunction>::cast(value)->external(),
|
||||
isolate);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace wasm
|
||||
|
||||
} // namespace internal
|
||||
|
@ -1077,6 +1077,12 @@ MaybeHandle<Object> JSToWasmObject(Isolate* isolate, Handle<Object> value,
|
||||
MaybeHandle<Object> JSToWasmObject(Isolate* isolate, const WasmModule* module,
|
||||
Handle<Object> value, ValueType expected,
|
||||
const char** error_message);
|
||||
|
||||
// Takes a {value} in the Wasm representation and tries to transform it to the
|
||||
// respective JS representation. If the transformation fails, the empty handle
|
||||
// is returned.
|
||||
MaybeHandle<Object> WasmToJSObject(Isolate* isolate, Handle<Object> value,
|
||||
HeapType type, const char** error_message);
|
||||
} // namespace wasm
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -370,6 +370,12 @@ class InitExprInterface {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
void UnOp(FullDecoder* decoder, WasmOpcode opcode, const Value& value,
|
||||
Value* result) {
|
||||
// TODO(12089): Implement.
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
void RefNull(FullDecoder* decoder, ValueType type, Value* result) {
|
||||
os_ << "kExprRefNull, " << HeapTypeToJSByteEncoding(type.heap_type())
|
||||
<< ", ";
|
||||
|
@ -396,8 +396,59 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
.exportFunc()
|
||||
|
||||
builder.addGlobal(wasmRefType(struct_index), false,
|
||||
[kExprRefFunc, func.index + 1, kExprStructNew, struct_index]);
|
||||
[kExprRefFunc, func.index + 1, kExprStructNew,
|
||||
struct_index]);
|
||||
|
||||
assertThrows(() => builder.instantiate(), WebAssembly.CompileError,
|
||||
/function index #1 is out of bounds/);
|
||||
})();
|
||||
|
||||
(function TestExternConstantExpr() {
|
||||
print(arguments.callee.name);
|
||||
|
||||
let imported_struct = (function () {
|
||||
let builder = new WasmModuleBuilder();
|
||||
|
||||
let struct = builder.addStruct([makeField(kWasmI32, true)]);
|
||||
|
||||
let global = builder.addGlobal(
|
||||
wasmRefType(struct), false,
|
||||
[kExprI32Const, 42, kGCPrefix, kExprStructNew, struct])
|
||||
.exportAs("global");
|
||||
|
||||
return builder.instantiate().exports.global.value;
|
||||
})();
|
||||
|
||||
let builder = new WasmModuleBuilder();
|
||||
|
||||
let struct = builder.addStruct([makeField(kWasmI32, true)]);
|
||||
|
||||
let imported = builder.addImportedGlobal("m", "ext", kWasmExternRef, false)
|
||||
|
||||
let internal = builder.addGlobal(
|
||||
kWasmAnyRef, false,
|
||||
[kExprGlobalGet, imported, kGCPrefix, kExprExternInternalize]);
|
||||
|
||||
builder.addGlobal(
|
||||
kWasmExternRef, false,
|
||||
[kExprGlobalGet, internal.index, kGCPrefix, kExprExternExternalize])
|
||||
.exportAs("exported")
|
||||
|
||||
builder.addFunction("getter", kSig_i_v)
|
||||
.addBody([kExprGlobalGet, internal.index,
|
||||
kGCPrefix, kExprRefCast, struct,
|
||||
kGCPrefix, kExprStructGet, struct, 0])
|
||||
.exportFunc();
|
||||
|
||||
builder.addFunction("getter_fail", kSig_i_v)
|
||||
.addBody([kExprGlobalGet, internal.index,
|
||||
kGCPrefix, kExprRefCast, kI31RefCode,
|
||||
kGCPrefix, kExprI31GetS])
|
||||
.exportFunc();
|
||||
|
||||
let instance = builder.instantiate({m: {ext: imported_struct}});
|
||||
|
||||
assertSame(instance.exports.exported.value, imported_struct);
|
||||
assertEquals(42, instance.exports.getter());
|
||||
assertTraps(kTrapIllegalCast, () => instance.exports.getter_fail());
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user