[wasm-gc] Add new ref.cast null taking any reference
This extends crrev.com/c/3948663 (ref.cast) by adding the new "ref.cast null" which only behaves different for null for which it doesn't trap but instead casts the null value to the target (null)type. Bug: v8:7748 Change-Id: I3ac85d83cc06c95af8830c1c60ae2f28414e2570 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3960329 Reviewed-by: Manos Koukoutos <manoskouk@chromium.org> Commit-Queue: Matthias Liedtke <mliedtke@chromium.org> Cr-Commit-Position: refs/heads/main@{#83934}
This commit is contained in:
parent
c9e8be7cd3
commit
1688cad47f
@ -5590,18 +5590,19 @@ Node* WasmGraphBuilder::RefCast(Node* object, Node* rtt,
|
||||
}
|
||||
|
||||
Node* WasmGraphBuilder::RefCastAbstract(Node* object, wasm::HeapType type,
|
||||
wasm::WasmCodePosition position) {
|
||||
wasm::WasmCodePosition position,
|
||||
bool null_succeeds) {
|
||||
bool is_nullable =
|
||||
compiler::NodeProperties::GetType(object).AsWasm().type.is_nullable();
|
||||
switch (type.representation()) {
|
||||
case wasm::HeapType::kEq:
|
||||
return RefAsEq(object, is_nullable, position);
|
||||
return RefAsEq(object, is_nullable, position, null_succeeds);
|
||||
case wasm::HeapType::kI31:
|
||||
return RefAsI31(object, position);
|
||||
return RefAsI31(object, position, null_succeeds);
|
||||
case wasm::HeapType::kStruct:
|
||||
return RefAsStruct(object, is_nullable, position);
|
||||
return RefAsStruct(object, is_nullable, position, null_succeeds);
|
||||
case wasm::HeapType::kArray:
|
||||
return RefAsArray(object, is_nullable, position);
|
||||
return RefAsArray(object, is_nullable, position, null_succeeds);
|
||||
case wasm::HeapType::kAny:
|
||||
// Any may never need a cast as it is either implicitly convertible or
|
||||
// never convertible for any given type.
|
||||
@ -5635,8 +5636,8 @@ Node* WasmGraphBuilder::RefIsEq(Node* object, bool object_can_be_null,
|
||||
}
|
||||
|
||||
Node* WasmGraphBuilder::RefAsEq(Node* object, bool object_can_be_null,
|
||||
wasm::WasmCodePosition position) {
|
||||
bool null_succeeds = false;
|
||||
wasm::WasmCodePosition position,
|
||||
bool null_succeeds) {
|
||||
auto done = gasm_->MakeLabel();
|
||||
EqCheck(object, object_can_be_null, CastCallbacks(&done, position),
|
||||
null_succeeds);
|
||||
@ -5660,8 +5661,8 @@ Node* WasmGraphBuilder::RefIsStruct(Node* object, bool object_can_be_null,
|
||||
}
|
||||
|
||||
Node* WasmGraphBuilder::RefAsStruct(Node* object, bool object_can_be_null,
|
||||
wasm::WasmCodePosition position) {
|
||||
bool null_succeeds = false;
|
||||
wasm::WasmCodePosition position,
|
||||
bool null_succeeds) {
|
||||
auto done = gasm_->MakeLabel();
|
||||
if (!v8_flags.wasm_gc_structref_as_dataref) {
|
||||
ManagedObjectInstanceCheck(object, object_can_be_null, WASM_STRUCT_TYPE,
|
||||
@ -5705,8 +5706,8 @@ Node* WasmGraphBuilder::RefIsArray(Node* object, bool object_can_be_null,
|
||||
}
|
||||
|
||||
Node* WasmGraphBuilder::RefAsArray(Node* object, bool object_can_be_null,
|
||||
wasm::WasmCodePosition position) {
|
||||
bool null_succeeds = false;
|
||||
wasm::WasmCodePosition position,
|
||||
bool null_succeeds) {
|
||||
auto done = gasm_->MakeLabel();
|
||||
ManagedObjectInstanceCheck(object, object_can_be_null, WASM_ARRAY_TYPE,
|
||||
CastCallbacks(&done, position), null_succeeds);
|
||||
@ -5741,8 +5742,16 @@ Node* WasmGraphBuilder::RefIsI31(Node* object, bool null_succeeds) {
|
||||
return gasm_->IsI31(object);
|
||||
}
|
||||
|
||||
Node* WasmGraphBuilder::RefAsI31(Node* object,
|
||||
wasm::WasmCodePosition position) {
|
||||
Node* WasmGraphBuilder::RefAsI31(Node* object, wasm::WasmCodePosition position,
|
||||
bool null_succeeds) {
|
||||
if (null_succeeds) {
|
||||
auto done = gasm_->MakeLabel();
|
||||
gasm_->GotoIf(gasm_->IsNull(object), &done);
|
||||
TrapIfFalse(wasm::kTrapIllegalCast, gasm_->IsI31(object), position);
|
||||
gasm_->Goto(&done);
|
||||
gasm_->Bind(&done);
|
||||
return object;
|
||||
}
|
||||
TrapIfFalse(wasm::kTrapIllegalCast, gasm_->IsI31(object), position);
|
||||
return object;
|
||||
}
|
||||
|
@ -498,27 +498,28 @@ class WasmGraphBuilder {
|
||||
Node* RefCast(Node* object, Node* rtt, WasmTypeCheckConfig config,
|
||||
wasm::WasmCodePosition position);
|
||||
Node* RefCastAbstract(Node* object, wasm::HeapType type,
|
||||
wasm::WasmCodePosition position);
|
||||
wasm::WasmCodePosition position, bool null_succeeds);
|
||||
void BrOnCast(Node* object, Node* rtt, WasmTypeCheckConfig config,
|
||||
Node** match_control, Node** match_effect,
|
||||
Node** no_match_control, Node** no_match_effect);
|
||||
Node* RefIsEq(Node* object, bool object_can_be_null, bool null_succeeds);
|
||||
Node* RefAsEq(Node* object, bool object_can_be_null,
|
||||
wasm::WasmCodePosition position);
|
||||
wasm::WasmCodePosition position, bool null_succeeds);
|
||||
Node* RefIsStruct(Node* object, bool object_can_be_null, bool null_succeeds);
|
||||
Node* RefAsStruct(Node* object, bool object_can_be_null,
|
||||
wasm::WasmCodePosition position);
|
||||
wasm::WasmCodePosition position, bool null_succeeds);
|
||||
void BrOnStruct(Node* object, Node* rtt, WasmTypeCheckConfig config,
|
||||
Node** match_control, Node** match_effect,
|
||||
Node** no_match_control, Node** no_match_effect);
|
||||
Node* RefIsArray(Node* object, bool object_can_be_null, bool null_succeeds);
|
||||
Node* RefAsArray(Node* object, bool object_can_be_null,
|
||||
wasm::WasmCodePosition position);
|
||||
wasm::WasmCodePosition position, bool null_succeeds);
|
||||
void BrOnArray(Node* object, Node* rtt, WasmTypeCheckConfig config,
|
||||
Node** match_control, Node** match_effect,
|
||||
Node** no_match_control, Node** no_match_effect);
|
||||
Node* RefIsI31(Node* object, bool null_succeeds);
|
||||
Node* RefAsI31(Node* object, wasm::WasmCodePosition position);
|
||||
Node* RefAsI31(Node* object, wasm::WasmCodePosition position,
|
||||
bool null_succeeds);
|
||||
void BrOnI31(Node* object, Node* rtt, WasmTypeCheckConfig config,
|
||||
Node** match_control, Node** match_effect,
|
||||
Node** no_match_control, Node** no_match_effect);
|
||||
|
@ -5979,16 +5979,16 @@ class LiftoffCompiler {
|
||||
}
|
||||
|
||||
void RefCastAbstract(FullDecoder* decoder, const Value& obj, HeapType type,
|
||||
Value* result_val) {
|
||||
Value* result_val, bool null_succeeds) {
|
||||
switch (type.representation()) {
|
||||
case HeapType::kEq:
|
||||
return RefAsEq(decoder, obj, result_val);
|
||||
return RefAsEq(decoder, obj, result_val, null_succeeds);
|
||||
case HeapType::kI31:
|
||||
return RefAsI31(decoder, obj, result_val);
|
||||
return RefAsI31(decoder, obj, result_val, null_succeeds);
|
||||
case HeapType::kStruct:
|
||||
return RefAsStruct(decoder, obj, result_val);
|
||||
return RefAsStruct(decoder, obj, result_val, null_succeeds);
|
||||
case HeapType::kArray:
|
||||
return RefAsArray(decoder, obj, result_val);
|
||||
return RefAsArray(decoder, obj, result_val, null_succeeds);
|
||||
case HeapType::kAny:
|
||||
// Any may never need a cast as it is either implicitly convertible or
|
||||
// never convertible for any given type.
|
||||
@ -6194,31 +6194,44 @@ class LiftoffCompiler {
|
||||
|
||||
template <TypeChecker type_checker>
|
||||
void AbstractTypeCast(const Value& object, FullDecoder* decoder,
|
||||
ValueKind result_kind) {
|
||||
bool null_succeeds = false; // TODO(mliedtke): Use parameter.
|
||||
ValueKind result_kind, bool null_succeeds = false) {
|
||||
Label match;
|
||||
Label* trap_label =
|
||||
AddOutOfLineTrap(decoder, WasmCode::kThrowWasmTrapIllegalCast);
|
||||
TypeCheck check(object.type, trap_label, null_succeeds);
|
||||
Initialize(check, kPeek);
|
||||
FREEZE_STATE(frozen);
|
||||
|
||||
if (null_succeeds && check.obj_type.is_nullable()) {
|
||||
__ emit_cond_jump(kEqual, &match, kRefNull, check.obj_reg,
|
||||
check.null_reg(), frozen);
|
||||
}
|
||||
(this->*type_checker)(check, frozen);
|
||||
__ bind(&match);
|
||||
}
|
||||
|
||||
void RefAsEq(FullDecoder* decoder, const Value& object, Value* result) {
|
||||
AbstractTypeCast<&LiftoffCompiler::EqCheck>(object, decoder, kRef);
|
||||
void RefAsEq(FullDecoder* decoder, const Value& object, Value* result,
|
||||
bool null_succeeds = false) {
|
||||
AbstractTypeCast<&LiftoffCompiler::EqCheck>(object, decoder, kRef,
|
||||
null_succeeds);
|
||||
}
|
||||
|
||||
void RefAsStruct(FullDecoder* decoder, const Value& object,
|
||||
Value* /* result */) {
|
||||
AbstractTypeCast<&LiftoffCompiler::StructCheck>(object, decoder, kRef);
|
||||
Value* /* result */, bool null_succeeds = false) {
|
||||
AbstractTypeCast<&LiftoffCompiler::StructCheck>(object, decoder, kRef,
|
||||
null_succeeds);
|
||||
}
|
||||
|
||||
void RefAsI31(FullDecoder* decoder, const Value& object, Value* result) {
|
||||
AbstractTypeCast<&LiftoffCompiler::I31Check>(object, decoder, kRef);
|
||||
void RefAsI31(FullDecoder* decoder, const Value& object, Value* result,
|
||||
bool null_succeeds = false) {
|
||||
AbstractTypeCast<&LiftoffCompiler::I31Check>(object, decoder, kRef,
|
||||
null_succeeds);
|
||||
}
|
||||
|
||||
void RefAsArray(FullDecoder* decoder, const Value& object, Value* result) {
|
||||
AbstractTypeCast<&LiftoffCompiler::ArrayCheck>(object, decoder, kRef);
|
||||
void RefAsArray(FullDecoder* decoder, const Value& object, Value* result,
|
||||
bool null_succeeds = false) {
|
||||
AbstractTypeCast<&LiftoffCompiler::ArrayCheck>(object, decoder, kRef,
|
||||
null_succeeds);
|
||||
}
|
||||
|
||||
template <TypeChecker type_checker>
|
||||
|
@ -1078,7 +1078,8 @@ struct ControlBase : public PcForErrors<ValidationTag::full_validation> {
|
||||
bool null_succeeds) \
|
||||
F(RefCast, const Value& obj, const Value& rtt, Value* result, \
|
||||
bool null_succeeds) \
|
||||
F(RefCastAbstract, const Value& obj, HeapType type, Value* result) \
|
||||
F(RefCastAbstract, const Value& obj, HeapType type, Value* result, \
|
||||
bool null_succeeds) \
|
||||
F(AssertNull, const Value& obj, Value* result) \
|
||||
F(AssertNotNull, const Value& obj, Value* result) \
|
||||
F(BrOnCast, const Value& obj, const Value& rtt, Value* result_on_branch, \
|
||||
@ -2139,6 +2140,7 @@ class WasmDecoder : public Decoder {
|
||||
return length + imm.length;
|
||||
}
|
||||
case kExprRefCast:
|
||||
case kExprRefCastNull:
|
||||
case kExprRefTest:
|
||||
case kExprRefTestNull: {
|
||||
HeapTypeImmediate imm(WasmFeatures::All(), decoder, pc + length,
|
||||
@ -2378,6 +2380,7 @@ class WasmDecoder : public Decoder {
|
||||
case kExprRefTestNull:
|
||||
case kExprRefTestDeprecated:
|
||||
case kExprRefCast:
|
||||
case kExprRefCastNull:
|
||||
case kExprRefCastDeprecated:
|
||||
case kExprRefCastNop:
|
||||
case kExprBrOnCast:
|
||||
@ -4804,7 +4807,8 @@ class WasmFullDecoder : public WasmDecoder<ValidationTag, decoding_mode> {
|
||||
Push(value);
|
||||
return opcode_length;
|
||||
}
|
||||
case kExprRefCast: {
|
||||
case kExprRefCast:
|
||||
case kExprRefCastNull: {
|
||||
NON_CONST_ONLY
|
||||
HeapTypeImmediate imm(this->enabled_, this, this->pc_ + opcode_length,
|
||||
this->module_, validate);
|
||||
@ -4834,8 +4838,7 @@ class WasmFullDecoder : public WasmDecoder<ValidationTag, decoding_mode> {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO(mliedtke): Add support for ref.cast null.
|
||||
bool null_succeeds = false;
|
||||
bool null_succeeds = opcode == kExprRefCastNull;
|
||||
Value value = CreateValue(ValueType::RefMaybeNull(
|
||||
imm.type, (obj.type.is_bottom() || !null_succeeds)
|
||||
? kNonNullable
|
||||
@ -4874,7 +4877,8 @@ class WasmFullDecoder : public WasmDecoder<ValidationTag, decoding_mode> {
|
||||
if (rtt.has_value()) {
|
||||
CALL_INTERFACE(RefCast, obj, rtt.value(), &value, null_succeeds);
|
||||
} else {
|
||||
CALL_INTERFACE(RefCastAbstract, obj, target_type, &value);
|
||||
CALL_INTERFACE(RefCastAbstract, obj, target_type, &value,
|
||||
null_succeeds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1243,10 +1243,11 @@ class WasmGraphBuildingInterface {
|
||||
}
|
||||
|
||||
void RefCastAbstract(FullDecoder* decoder, const Value& object,
|
||||
wasm::HeapType type, Value* result) {
|
||||
wasm::HeapType type, Value* result, bool null_succeeds) {
|
||||
TFNode* node = object.node;
|
||||
if (!v8_flags.experimental_wasm_assume_ref_cast_succeeds) {
|
||||
node = builder_->RefCastAbstract(object.node, type, decoder->position());
|
||||
node = builder_->RefCastAbstract(object.node, type, decoder->position(),
|
||||
null_succeeds);
|
||||
}
|
||||
SetAndTypeNode(result, builder_->TypeGuard(node, result->type));
|
||||
}
|
||||
@ -1307,8 +1308,10 @@ class WasmGraphBuildingInterface {
|
||||
}
|
||||
|
||||
void RefAsStruct(FullDecoder* decoder, const Value& object, Value* result) {
|
||||
TFNode* cast_object = builder_->RefAsStruct(
|
||||
object.node, object.type.is_nullable(), decoder->position());
|
||||
bool null_succeeds = false;
|
||||
TFNode* cast_object =
|
||||
builder_->RefAsStruct(object.node, object.type.is_nullable(),
|
||||
decoder->position(), null_succeeds);
|
||||
TFNode* rename = builder_->TypeGuard(cast_object, result->type);
|
||||
SetAndTypeNode(result, rename);
|
||||
}
|
||||
@ -1335,8 +1338,10 @@ class WasmGraphBuildingInterface {
|
||||
}
|
||||
|
||||
void RefAsArray(FullDecoder* decoder, const Value& object, Value* result) {
|
||||
TFNode* cast_object = builder_->RefAsArray(
|
||||
object.node, object.type.is_nullable(), decoder->position());
|
||||
bool null_succeeds = false;
|
||||
TFNode* cast_object =
|
||||
builder_->RefAsArray(object.node, object.type.is_nullable(),
|
||||
decoder->position(), null_succeeds);
|
||||
TFNode* rename = builder_->TypeGuard(cast_object, result->type);
|
||||
SetAndTypeNode(result, rename);
|
||||
}
|
||||
@ -1361,7 +1366,9 @@ class WasmGraphBuildingInterface {
|
||||
}
|
||||
|
||||
void RefAsI31(FullDecoder* decoder, const Value& object, Value* result) {
|
||||
TFNode* cast_object = builder_->RefAsI31(object.node, decoder->position());
|
||||
bool null_succeeds = false;
|
||||
TFNode* cast_object =
|
||||
builder_->RefAsI31(object.node, decoder->position(), null_succeeds);
|
||||
TFNode* rename = builder_->TypeGuard(cast_object, result->type);
|
||||
SetAndTypeNode(result, rename);
|
||||
}
|
||||
|
@ -711,6 +711,7 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig,
|
||||
V(RefTestNull, 0xfb48, _, "ref.test null") \
|
||||
V(RefTestDeprecated, 0xfb44, _, "ref.test") \
|
||||
V(RefCast, 0xfb41, _, "ref.cast") \
|
||||
V(RefCastNull, 0xfb49, _, "ref.cast null") \
|
||||
V(RefCastDeprecated, 0xfb45, _, "ref.cast") \
|
||||
V(BrOnCast, 0xfb46, _, "br_on_cast") \
|
||||
V(BrOnCastFail, 0xfb47, _, "br_on_cast_fail") \
|
||||
|
@ -67,6 +67,15 @@ d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
kGCPrefix, kExprRefCast, typeCode,
|
||||
kGCPrefix, kExprExternExternalize,
|
||||
]).exportFunc();
|
||||
|
||||
builder.addFunction(`refCastNull${typeName}`,
|
||||
makeSig([kWasmExternRef], [kWasmExternRef]))
|
||||
.addBody([
|
||||
kExprLocalGet, 0,
|
||||
kGCPrefix, kExprExternInternalize,
|
||||
kGCPrefix, kExprRefCastNull, typeCode,
|
||||
kGCPrefix, kExprExternExternalize,
|
||||
]).exportFunc();
|
||||
});
|
||||
|
||||
var instance = builder.instantiate();
|
||||
@ -178,7 +187,6 @@ d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastArray(1));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastArray(jsObj));
|
||||
|
||||
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastI31(null));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastI31(undefined));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastI31(structSuperObj));
|
||||
@ -223,4 +231,77 @@ d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
assertSame(funcObj, wasm.refCastAny(funcObj));
|
||||
assertEquals(1, wasm.refCastAny(1));
|
||||
assertSame(jsObj, wasm.refCastAny(jsObj));
|
||||
|
||||
// ref.cast null
|
||||
assertSame(null, wasm.refCastNullStructSuper(null));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullStructSuper(undefined));
|
||||
assertSame(structSuperObj, wasm.refCastNullStructSuper(structSuperObj));
|
||||
assertSame(structSubObj, wasm.refCastNullStructSuper(structSubObj));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullStructSuper(arrayObj));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullStructSuper(funcObj));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullStructSuper(1));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullStructSuper(jsObj));
|
||||
|
||||
assertSame(null, wasm.refCastNullStructSub(null));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullStructSub(undefined));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullStructSub(structSuperObj));
|
||||
assertSame(structSubObj, wasm.refCastNullStructSub(structSubObj));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullStructSub(arrayObj));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullStructSub(funcObj));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullStructSub(1));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullStructSub(jsObj));
|
||||
|
||||
assertSame(null, wasm.refCastNullArray(null));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullArray(undefined));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullArray(structSuperObj));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullArray(structSubObj));
|
||||
assertSame(arrayObj, wasm.refCastNullArray(arrayObj));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullArray(funcObj));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullArray(1));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullArray(jsObj));
|
||||
|
||||
assertSame(null, wasm.refCastNullI31(null));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullI31(undefined));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullI31(structSuperObj));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullI31(structSubObj));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullI31(arrayObj));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullI31(funcObj));
|
||||
assertEquals(1, wasm.refCastNullI31(1));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullI31(jsObj));
|
||||
|
||||
assertSame(null, wasm.refCastNullAnyArray(null));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullAnyArray(undefined));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullAnyArray(structSuperObj));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullAnyArray(structSubObj));
|
||||
assertSame(arrayObj, wasm.refCastNullAnyArray(arrayObj));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullAnyArray(funcObj));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullAnyArray(1));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullAnyArray(jsObj));
|
||||
|
||||
assertSame(null, wasm.refCastNullStruct(null));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullStruct(undefined));
|
||||
assertSame(structSuperObj, wasm.refCastNullStruct(structSuperObj));
|
||||
assertSame(structSubObj, wasm.refCastNullStruct(structSubObj));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullStruct(arrayObj));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullStruct(funcObj));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullStruct(1));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullStruct(jsObj));
|
||||
|
||||
assertSame(null, wasm.refCastNullEq(null));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullEq(undefined));
|
||||
assertSame(structSuperObj, wasm.refCastNullEq(structSuperObj));
|
||||
assertSame(structSubObj, wasm.refCastNullEq(structSubObj));
|
||||
assertSame(arrayObj, wasm.refCastNullEq(arrayObj));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullEq(funcObj));
|
||||
assertEquals(1, wasm.refCastNullEq(1));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastNullEq(jsObj));
|
||||
|
||||
assertSame(null, wasm.refCastNullAny(null));
|
||||
assertSame(undefined, wasm.refCastNullAny(undefined));
|
||||
assertSame(structSuperObj, wasm.refCastNullAny(structSuperObj));
|
||||
assertSame(structSubObj, wasm.refCastNullAny(structSubObj));
|
||||
assertSame(arrayObj, wasm.refCastNullAny(arrayObj));
|
||||
assertSame(funcObj, wasm.refCastNullAny(funcObj));
|
||||
assertEquals(1, wasm.refCastNullAny(1));
|
||||
assertSame(jsObj, wasm.refCastNullAny(jsObj));
|
||||
})();
|
||||
|
@ -26,6 +26,7 @@ d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
kExprRefTest,
|
||||
kExprRefTestNull,
|
||||
kExprRefCast,
|
||||
kExprRefCastNull,
|
||||
];
|
||||
|
||||
for (let [source_type, target_type_imm] of types) {
|
||||
|
@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --experimental-wasm-gc --experimental-wasm-type-reflection --no-wasm-gc-structref-as-dataref
|
||||
// Flags: --experimental-wasm-gc --experimental-wasm-type-reflection
|
||||
// Flags: --no-wasm-gc-structref-as-dataref
|
||||
|
||||
d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
|
||||
@ -316,6 +317,15 @@ d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
kGCPrefix, kExprRefCast, heapType,
|
||||
kExprRefIsNull, // We can't expose the cast object to JS in most cases.
|
||||
]).exportFunc();
|
||||
|
||||
builder.addFunction(`cast_null_${test.source}_to_${target}`,
|
||||
makeSig([wasmRefType(creatorType)], [kWasmI32]))
|
||||
.addBody([
|
||||
kExprLocalGet, 0,
|
||||
kExprCallRef, creatorType,
|
||||
kGCPrefix, kExprRefCastNull, heapType,
|
||||
kExprRefIsNull, // We can't expose the cast object to JS in most cases.
|
||||
]).exportFunc();
|
||||
}
|
||||
}
|
||||
|
||||
@ -341,6 +351,13 @@ d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
} else {
|
||||
assertTraps(kTrapIllegalCast, () => cast(create_value));
|
||||
}
|
||||
let castNull = wasm[`cast_null_${test.source}_to_${target}`];
|
||||
if (validValues.includes(value) || value == "nullref") {
|
||||
let expected = value == "nullref" ? 1 : 0;
|
||||
assertEquals(expected, castNull(create_value));
|
||||
} else {
|
||||
assertTraps(kTrapIllegalCast, () => castNull(create_value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -513,6 +513,7 @@ let kExprRefTest = 0x40;
|
||||
let kExprRefTestNull = 0x48;
|
||||
let kExprRefTestDeprecated = 0x44;
|
||||
let kExprRefCast = 0x41;
|
||||
let kExprRefCastNull = 0x49;
|
||||
let kExprRefCastDeprecated = 0x45;
|
||||
let kExprBrOnCast = 0x46;
|
||||
let kExprBrOnCastFail = 0x47;
|
||||
|
Loading…
Reference in New Issue
Block a user