[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:
Manos Koukoutos 2023-01-26 07:10:35 +01:00 committed by V8 LUCI CQ
parent 22bef706e1
commit ca27aeeff1
7 changed files with 146 additions and 64 deletions

View File

@ -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) {

View File

@ -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()));

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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())
<< ", ";

View File

@ -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());
})();