Reland "Reland "[wasm-gc] Ref types: Convert dataref to structref""
This is a reland of commit3b883e787d
Fixed a test case that was merged in the meantime still using the old kExprRefAsData which is now called kExprRefAsStruct. Original change's description: > Reland "[wasm-gc] Ref types: Convert dataref to structref" > > This is a reland of commit20327d1599
> > Changed in reland: > - Added new flag wasm-gc-structref-as-dataref which defaults to true > and preserves the existing behavior. > - Passing --no-wasm-gc-structref-as-dataref enables the new behavior. > - The flag affects static subtyping information between structref and > arrays and the corresponding cast, test and br_on instructions. > - Even with the old behavior the name still changed to "structref". > > Original change's description: > > [wasm-gc] Ref types: Convert dataref to structref > > > > This change changes the type hierarchy in a non-backwards compatible > > way: dataref is replaced with structref meaning that arrayref is > > no longer a subtype of it. > > > > Bug: v8:7748 > > Change-Id: I965267d9ed11ea7c7d7df133cc39ee63e6b5abc3 > > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3929041 > > Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> > > Commit-Queue: Matthias Liedtke <mliedtke@chromium.org> > > Cr-Commit-Position: refs/heads/main@{#83515} > > Bug: v8:7748 > Change-Id: I2d8dd49dbc56246c087ac93452a87f860ead2195 > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3945109 > Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> > Commit-Queue: Matthias Liedtke <mliedtke@chromium.org> > Cr-Commit-Position: refs/heads/main@{#83697} Bug: v8:7748 Change-Id: I54f7b141ffc5b7597420fa0c838412be825a260b Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3952936 Auto-Submit: Matthias Liedtke <mliedtke@chromium.org> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Commit-Queue: Matthias Liedtke <mliedtke@chromium.org> Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Cr-Commit-Position: refs/heads/main@{#83706}
This commit is contained in:
parent
aed66041b3
commit
d4a3ebeb2b
@ -5431,12 +5431,12 @@ WasmGraphBuilder::Callbacks WasmGraphBuilder::BranchCallbacks(
|
||||
|
||||
void WasmGraphBuilder::DataCheck(Node* object, bool object_can_be_null,
|
||||
Callbacks callbacks, bool null_succeeds) {
|
||||
// TODO(7748): Only used for backwards compatibility in combination with
|
||||
// v8_flags.wasm_gc_structref_as_dataref. Remove.
|
||||
if (object_can_be_null) {
|
||||
if (null_succeeds) {
|
||||
callbacks.succeed_if(IsNull(object), BranchHint::kFalse);
|
||||
} else {
|
||||
// TODO(7748): Is the extra null check actually beneficial for
|
||||
// performance?
|
||||
callbacks.fail_if(IsNull(object), BranchHint::kFalse);
|
||||
}
|
||||
}
|
||||
@ -5530,8 +5530,8 @@ Node* WasmGraphBuilder::RefTestAbstract(Node* object, wasm::HeapType type,
|
||||
return RefIsEq(object, is_nullable, null_succeeds);
|
||||
case wasm::HeapType::kI31:
|
||||
return RefIsI31(object, null_succeeds);
|
||||
case wasm::HeapType::kData:
|
||||
return RefIsData(object, is_nullable, null_succeeds);
|
||||
case wasm::HeapType::kStruct:
|
||||
return RefIsStruct(object, is_nullable, null_succeeds);
|
||||
case wasm::HeapType::kArray:
|
||||
return RefIsArray(object, is_nullable, null_succeeds);
|
||||
case wasm::HeapType::kAny:
|
||||
@ -5572,36 +5572,52 @@ Node* WasmGraphBuilder::RefIsEq(Node* object, bool object_can_be_null,
|
||||
return done.PhiAt(0);
|
||||
}
|
||||
|
||||
Node* WasmGraphBuilder::RefIsData(Node* object, bool object_can_be_null,
|
||||
bool null_succeeds) {
|
||||
Node* WasmGraphBuilder::RefIsStruct(Node* object, bool object_can_be_null,
|
||||
bool null_succeeds) {
|
||||
auto done = gasm_->MakeLabel(MachineRepresentation::kWord32);
|
||||
DataCheck(object, object_can_be_null, TestCallbacks(&done), null_succeeds);
|
||||
if (!v8_flags.wasm_gc_structref_as_dataref) {
|
||||
ManagedObjectInstanceCheck(object, object_can_be_null, WASM_STRUCT_TYPE,
|
||||
TestCallbacks(&done), null_succeeds);
|
||||
} else {
|
||||
DataCheck(object, object_can_be_null, TestCallbacks(&done), null_succeeds);
|
||||
}
|
||||
gasm_->Goto(&done, Int32Constant(1));
|
||||
gasm_->Bind(&done);
|
||||
return done.PhiAt(0);
|
||||
}
|
||||
|
||||
Node* WasmGraphBuilder::RefAsData(Node* object, bool object_can_be_null,
|
||||
wasm::WasmCodePosition position) {
|
||||
Node* WasmGraphBuilder::RefAsStruct(Node* object, bool object_can_be_null,
|
||||
wasm::WasmCodePosition position) {
|
||||
bool null_succeeds = false;
|
||||
auto done = gasm_->MakeLabel();
|
||||
DataCheck(object, object_can_be_null, CastCallbacks(&done, position),
|
||||
null_succeeds);
|
||||
if (!v8_flags.wasm_gc_structref_as_dataref) {
|
||||
ManagedObjectInstanceCheck(object, object_can_be_null, WASM_STRUCT_TYPE,
|
||||
CastCallbacks(&done, position), null_succeeds);
|
||||
} else {
|
||||
DataCheck(object, object_can_be_null, CastCallbacks(&done, position),
|
||||
null_succeeds);
|
||||
}
|
||||
gasm_->Goto(&done);
|
||||
gasm_->Bind(&done);
|
||||
return object;
|
||||
}
|
||||
|
||||
void WasmGraphBuilder::BrOnData(Node* object, Node* /*rtt*/,
|
||||
WasmTypeCheckConfig config,
|
||||
Node** match_control, Node** match_effect,
|
||||
Node** no_match_control,
|
||||
Node** no_match_effect) {
|
||||
void WasmGraphBuilder::BrOnStruct(Node* object, Node* /*rtt*/,
|
||||
WasmTypeCheckConfig config,
|
||||
Node** match_control, Node** match_effect,
|
||||
Node** no_match_control,
|
||||
Node** no_match_effect) {
|
||||
bool null_succeeds = false;
|
||||
BrOnCastAbs(match_control, match_effect, no_match_control, no_match_effect,
|
||||
[=](Callbacks callbacks) -> void {
|
||||
return DataCheck(object, config.object_can_be_null, callbacks,
|
||||
null_succeeds);
|
||||
if (!v8_flags.wasm_gc_structref_as_dataref) {
|
||||
return ManagedObjectInstanceCheck(
|
||||
object, config.object_can_be_null, WASM_STRUCT_TYPE,
|
||||
callbacks, null_succeeds);
|
||||
} else {
|
||||
return DataCheck(object, config.object_can_be_null, callbacks,
|
||||
null_succeeds);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -6407,7 +6423,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
||||
gasm_->Bind(&done);
|
||||
return done.PhiAt(0);
|
||||
}
|
||||
case wasm::HeapType::kData:
|
||||
case wasm::HeapType::kStruct:
|
||||
case wasm::HeapType::kArray:
|
||||
// TODO(7748): Update this when JS interop is settled.
|
||||
if (type.kind() == wasm::kRefNull) {
|
||||
@ -6548,7 +6564,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
||||
case wasm::HeapType::kI31:
|
||||
UNREACHABLE();
|
||||
case wasm::HeapType::kFunc:
|
||||
case wasm::HeapType::kData:
|
||||
case wasm::HeapType::kStruct:
|
||||
case wasm::HeapType::kArray:
|
||||
case wasm::HeapType::kEq:
|
||||
default: {
|
||||
|
@ -501,12 +501,12 @@ class WasmGraphBuilder {
|
||||
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* RefIsData(Node* object, bool object_can_be_null, bool null_succeeds);
|
||||
Node* RefAsData(Node* object, bool object_can_be_null,
|
||||
wasm::WasmCodePosition position);
|
||||
void BrOnData(Node* object, Node* rtt, WasmTypeCheckConfig config,
|
||||
Node** match_control, Node** match_effect,
|
||||
Node** no_match_control, Node** no_match_effect);
|
||||
Node* RefIsStruct(Node* object, bool object_can_be_null, bool null_succeeds);
|
||||
Node* RefAsStruct(Node* object, bool object_can_be_null,
|
||||
wasm::WasmCodePosition position);
|
||||
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);
|
||||
|
@ -1116,6 +1116,8 @@ DEFINE_IMPLICATION(experimental_wasm_stack_switching,
|
||||
experimental_wasm_type_reflection)
|
||||
|
||||
DEFINE_BOOL(wasm_gc_js_interop, true, "experimental WasmGC-JS interop")
|
||||
DEFINE_BOOL(wasm_gc_structref_as_dataref, true,
|
||||
"compatibility mode: Treat structref as dataref")
|
||||
|
||||
DEFINE_BOOL(wasm_staging, false, "enable staged wasm features")
|
||||
|
||||
|
@ -5997,8 +5997,8 @@ class LiftoffCompiler {
|
||||
return RefIsEq(decoder, obj, result_val, null_succeeds);
|
||||
case HeapType::kI31:
|
||||
return RefIsI31(decoder, obj, result_val, null_succeeds);
|
||||
case HeapType::kData:
|
||||
return RefIsData(decoder, obj, result_val, null_succeeds);
|
||||
case HeapType::kStruct:
|
||||
return RefIsStruct(decoder, obj, result_val, null_succeeds);
|
||||
case HeapType::kArray:
|
||||
return RefIsArray(decoder, obj, result_val, null_succeeds);
|
||||
case HeapType::kAny:
|
||||
@ -6139,15 +6139,19 @@ class LiftoffCompiler {
|
||||
}
|
||||
|
||||
// Abstract type checkers. They all fall through on match.
|
||||
void DataCheck(TypeCheck& check, const FreezeCacheState& frozen) {
|
||||
void StructCheck(TypeCheck& check, const FreezeCacheState& frozen) {
|
||||
LoadInstanceType(check, frozen, check.no_match);
|
||||
// We're going to test a range of WasmObject instance types with a single
|
||||
// unsigned comparison.
|
||||
Register tmp = check.instance_type();
|
||||
__ emit_i32_subi(tmp, tmp, FIRST_WASM_OBJECT_TYPE);
|
||||
__ emit_i32_cond_jumpi(kUnsignedGreaterThan, check.no_match, tmp,
|
||||
LAST_WASM_OBJECT_TYPE - FIRST_WASM_OBJECT_TYPE,
|
||||
frozen);
|
||||
LiftoffRegister instance_type(check.instance_type());
|
||||
if (!v8_flags.wasm_gc_structref_as_dataref) {
|
||||
__ emit_i32_cond_jumpi(kUnequal, check.no_match, check.instance_type(),
|
||||
WASM_STRUCT_TYPE, frozen);
|
||||
} else {
|
||||
Register tmp = check.instance_type();
|
||||
__ emit_i32_subi(tmp, tmp, FIRST_WASM_OBJECT_TYPE);
|
||||
__ emit_i32_cond_jumpi(kUnsignedGreaterThan, check.no_match, tmp,
|
||||
LAST_WASM_OBJECT_TYPE - FIRST_WASM_OBJECT_TYPE,
|
||||
frozen);
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayCheck(TypeCheck& check, const FreezeCacheState& frozen) {
|
||||
@ -6206,9 +6210,9 @@ class LiftoffCompiler {
|
||||
__ PushRegister(kI32, result);
|
||||
}
|
||||
|
||||
void RefIsData(FullDecoder* /* decoder */, const Value& object,
|
||||
Value* /* result_val */, bool null_succeeds = false) {
|
||||
AbstractTypeCheck<&LiftoffCompiler::DataCheck>(object, null_succeeds);
|
||||
void RefIsStruct(FullDecoder* /* decoder */, const Value& object,
|
||||
Value* /* result_val */, bool null_succeeds = false) {
|
||||
AbstractTypeCheck<&LiftoffCompiler::StructCheck>(object, null_succeeds);
|
||||
}
|
||||
|
||||
void RefIsEq(FullDecoder* /* decoder */, const Value& object,
|
||||
@ -6238,9 +6242,9 @@ class LiftoffCompiler {
|
||||
(this->*type_checker)(check, frozen);
|
||||
}
|
||||
|
||||
void RefAsData(FullDecoder* decoder, const Value& object,
|
||||
Value* /* result */) {
|
||||
AbstractTypeCast<&LiftoffCompiler::DataCheck>(object, decoder, kRef);
|
||||
void RefAsStruct(FullDecoder* decoder, const Value& object,
|
||||
Value* /* result */) {
|
||||
AbstractTypeCast<&LiftoffCompiler::StructCheck>(object, decoder, kRef);
|
||||
}
|
||||
|
||||
void RefAsI31(FullDecoder* decoder, const Value& object, Value* result) {
|
||||
@ -6294,9 +6298,9 @@ class LiftoffCompiler {
|
||||
__ bind(&end);
|
||||
}
|
||||
|
||||
void BrOnData(FullDecoder* decoder, const Value& object,
|
||||
Value* /* value_on_branch */, uint32_t br_depth) {
|
||||
BrOnAbstractType<&LiftoffCompiler::DataCheck>(object, decoder, br_depth);
|
||||
void BrOnStruct(FullDecoder* decoder, const Value& object,
|
||||
Value* /* value_on_branch */, uint32_t br_depth) {
|
||||
BrOnAbstractType<&LiftoffCompiler::StructCheck>(object, decoder, br_depth);
|
||||
}
|
||||
|
||||
void BrOnI31(FullDecoder* decoder, const Value& object,
|
||||
@ -6309,9 +6313,10 @@ class LiftoffCompiler {
|
||||
BrOnAbstractType<&LiftoffCompiler::ArrayCheck>(object, decoder, br_depth);
|
||||
}
|
||||
|
||||
void BrOnNonData(FullDecoder* decoder, const Value& object,
|
||||
Value* /* value_on_branch */, uint32_t br_depth) {
|
||||
BrOnNonAbstractType<&LiftoffCompiler::DataCheck>(object, decoder, br_depth);
|
||||
void BrOnNonStruct(FullDecoder* decoder, const Value& object,
|
||||
Value* /* value_on_branch */, uint32_t br_depth) {
|
||||
BrOnNonAbstractType<&LiftoffCompiler::StructCheck>(object, decoder,
|
||||
br_depth);
|
||||
}
|
||||
|
||||
void BrOnNonI31(FullDecoder* decoder, const Value& object,
|
||||
|
@ -238,7 +238,7 @@ HeapType read_heap_type(Decoder* decoder, const byte* pc,
|
||||
switch (code) {
|
||||
case kEqRefCode:
|
||||
case kI31RefCode:
|
||||
case kDataRefCode:
|
||||
case kStructRefCode:
|
||||
case kArrayRefCode:
|
||||
case kAnyRefCode:
|
||||
case kNoneCode:
|
||||
@ -313,7 +313,7 @@ ValueType read_value_type(Decoder* decoder, const byte* pc,
|
||||
switch (code) {
|
||||
case kEqRefCode:
|
||||
case kI31RefCode:
|
||||
case kDataRefCode:
|
||||
case kStructRefCode:
|
||||
case kArrayRefCode:
|
||||
case kAnyRefCode:
|
||||
case kNoneCode:
|
||||
@ -1076,17 +1076,18 @@ struct ControlBase : public PcForErrors<validate> {
|
||||
uint32_t depth) \
|
||||
F(BrOnCastFail, const Value& obj, const Value& rtt, \
|
||||
Value* result_on_fallthrough, uint32_t depth) \
|
||||
F(RefIsData, const Value& object, Value* result) \
|
||||
F(RefIsStruct, const Value& object, Value* result) \
|
||||
F(RefIsEq, const Value& object, Value* result) \
|
||||
F(RefIsI31, const Value& object, Value* result) \
|
||||
F(RefIsArray, const Value& object, Value* result) \
|
||||
F(RefAsData, const Value& object, Value* result) \
|
||||
F(RefAsStruct, const Value& object, Value* result) \
|
||||
F(RefAsI31, const Value& object, Value* result) \
|
||||
F(RefAsArray, const Value& object, Value* result) \
|
||||
F(BrOnData, const Value& object, Value* value_on_branch, uint32_t br_depth) \
|
||||
F(BrOnStruct, const Value& object, Value* value_on_branch, \
|
||||
uint32_t br_depth) \
|
||||
F(BrOnI31, const Value& object, Value* value_on_branch, uint32_t br_depth) \
|
||||
F(BrOnArray, const Value& object, Value* value_on_branch, uint32_t br_depth) \
|
||||
F(BrOnNonData, const Value& object, Value* value_on_fallthrough, \
|
||||
F(BrOnNonStruct, const Value& object, Value* value_on_fallthrough, \
|
||||
uint32_t br_depth) \
|
||||
F(BrOnNonI31, const Value& object, Value* value_on_fallthrough, \
|
||||
uint32_t br_depth) \
|
||||
@ -2045,10 +2046,10 @@ class WasmDecoder : public Decoder {
|
||||
return length + array_imm.length + data_imm.length;
|
||||
}
|
||||
case kExprBrOnArray:
|
||||
case kExprBrOnData:
|
||||
case kExprBrOnStruct:
|
||||
case kExprBrOnI31:
|
||||
case kExprBrOnNonArray:
|
||||
case kExprBrOnNonData:
|
||||
case kExprBrOnNonStruct:
|
||||
case kExprBrOnNonI31: {
|
||||
BranchDepthImmediate<validate> imm(decoder, pc + length);
|
||||
if (io) io->BranchDepth(imm);
|
||||
@ -2081,10 +2082,10 @@ class WasmDecoder : public Decoder {
|
||||
case kExprI31GetS:
|
||||
case kExprI31GetU:
|
||||
case kExprRefAsArray:
|
||||
case kExprRefAsData:
|
||||
case kExprRefAsStruct:
|
||||
case kExprRefAsI31:
|
||||
case kExprRefIsArray:
|
||||
case kExprRefIsData:
|
||||
case kExprRefIsStruct:
|
||||
case kExprRefIsI31:
|
||||
case kExprExternInternalize:
|
||||
case kExprExternExternalize:
|
||||
@ -4816,9 +4817,12 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
|
||||
Value obj = Peek(1);
|
||||
Value value = CreateValue(kWasmI32);
|
||||
if (!VALIDATE(IsSubtypeOf(obj.type, kWasmFuncRef, this->module_) ||
|
||||
IsSubtypeOf(obj.type, kWasmDataRef, this->module_) ||
|
||||
IsSubtypeOf(obj.type, kWasmStructRef, this->module_) ||
|
||||
IsSubtypeOf(obj.type, kWasmArrayRef, this->module_) ||
|
||||
obj.type.is_bottom())) {
|
||||
PopTypeError(0, obj, "subtype of (ref null func) or (ref null data)");
|
||||
PopTypeError(0, obj,
|
||||
"subtype of (ref null func), (ref null struct) or (ref "
|
||||
"null array)");
|
||||
return 0;
|
||||
}
|
||||
if (current_code_reachable_and_ok_) {
|
||||
@ -4862,9 +4866,12 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
|
||||
opcode_length += imm.length;
|
||||
Value obj = Peek(0);
|
||||
if (!VALIDATE(IsSubtypeOf(obj.type, kWasmFuncRef, this->module_) ||
|
||||
IsSubtypeOf(obj.type, kWasmDataRef, this->module_) ||
|
||||
IsSubtypeOf(obj.type, kWasmStructRef, this->module_) ||
|
||||
IsSubtypeOf(obj.type, kWasmArrayRef, this->module_) ||
|
||||
obj.type.is_bottom())) {
|
||||
PopTypeError(0, obj, "subtype of (ref null func) or (ref null data)");
|
||||
PopTypeError(0, obj,
|
||||
"subtype of (ref null func), (ref null struct) or (ref "
|
||||
"null array)");
|
||||
return 0;
|
||||
}
|
||||
Value value = CreateValue(ValueType::RefMaybeNull(
|
||||
@ -4886,9 +4893,12 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
|
||||
Push(rtt);
|
||||
Value obj = Peek(1);
|
||||
if (!VALIDATE(IsSubtypeOf(obj.type, kWasmFuncRef, this->module_) ||
|
||||
IsSubtypeOf(obj.type, kWasmDataRef, this->module_) ||
|
||||
IsSubtypeOf(obj.type, kWasmStructRef, this->module_) ||
|
||||
IsSubtypeOf(obj.type, kWasmArrayRef, this->module_) ||
|
||||
obj.type.is_bottom())) {
|
||||
PopTypeError(0, obj, "subtype of (ref null func) or (ref null data)");
|
||||
PopTypeError(0, obj,
|
||||
"subtype of (ref null func), (ref null struct) or (ref "
|
||||
"null array)");
|
||||
return 0;
|
||||
}
|
||||
// If either value is bottom, we emit the most specific type possible.
|
||||
@ -4943,9 +4953,12 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
|
||||
// anyway.
|
||||
Value obj = Peek(0);
|
||||
if (!VALIDATE(IsSubtypeOf(obj.type, kWasmFuncRef, this->module_) ||
|
||||
IsSubtypeOf(obj.type, kWasmDataRef, this->module_) ||
|
||||
IsSubtypeOf(obj.type, kWasmStructRef, this->module_) ||
|
||||
IsSubtypeOf(obj.type, kWasmArrayRef, this->module_) ||
|
||||
obj.type.is_bottom())) {
|
||||
PopTypeError(0, obj, "subtype of (ref null func) or (ref null data)");
|
||||
PopTypeError(0, obj,
|
||||
"subtype of (ref null func), (ref null struct) or (ref "
|
||||
"null array)");
|
||||
return 0;
|
||||
}
|
||||
Control* c = control_at(branch_depth.depth);
|
||||
@ -5010,9 +5023,12 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
|
||||
CALL_INTERFACE_IF_OK_AND_REACHABLE(RttCanon, imm.index, &rtt);
|
||||
Value obj = Peek(0);
|
||||
if (!VALIDATE(IsSubtypeOf(obj.type, kWasmFuncRef, this->module_) ||
|
||||
IsSubtypeOf(obj.type, kWasmDataRef, this->module_) ||
|
||||
IsSubtypeOf(obj.type, kWasmStructRef, this->module_) ||
|
||||
IsSubtypeOf(obj.type, kWasmArrayRef, this->module_) ||
|
||||
obj.type.is_bottom())) {
|
||||
PopTypeError(0, obj, "subtype of (ref null func) or (ref null data)");
|
||||
PopTypeError(0, obj,
|
||||
"subtype of (ref null func), (ref null struct) or (ref "
|
||||
"null array)");
|
||||
return 0;
|
||||
}
|
||||
Control* c = control_at(branch_depth.depth);
|
||||
@ -5092,7 +5108,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
|
||||
Push(result); \
|
||||
return opcode_length; \
|
||||
}
|
||||
ABSTRACT_TYPE_CHECK(Data)
|
||||
ABSTRACT_TYPE_CHECK(Struct)
|
||||
ABSTRACT_TYPE_CHECK(I31)
|
||||
ABSTRACT_TYPE_CHECK(Array)
|
||||
#undef ABSTRACT_TYPE_CHECK
|
||||
@ -5126,12 +5142,12 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
|
||||
Push(result); \
|
||||
return opcode_length; \
|
||||
}
|
||||
ABSTRACT_TYPE_CAST(Data)
|
||||
ABSTRACT_TYPE_CAST(Struct)
|
||||
ABSTRACT_TYPE_CAST(I31)
|
||||
ABSTRACT_TYPE_CAST(Array)
|
||||
#undef ABSTRACT_TYPE_CAST
|
||||
|
||||
case kExprBrOnData:
|
||||
case kExprBrOnStruct:
|
||||
case kExprBrOnArray:
|
||||
case kExprBrOnI31: {
|
||||
NON_CONST_ONLY
|
||||
@ -5157,7 +5173,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
|
||||
Value obj = Peek(0, 0, kWasmAnyRef);
|
||||
Drop(obj);
|
||||
HeapType::Representation heap_type =
|
||||
opcode == kExprBrOnData ? HeapType::kData
|
||||
opcode == kExprBrOnStruct ? HeapType::kStruct
|
||||
: opcode == kExprBrOnArray ? HeapType::kArray
|
||||
: HeapType::kI31;
|
||||
Value result_on_branch = CreateValue(ValueType::Ref(heap_type));
|
||||
@ -5168,8 +5184,9 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
|
||||
// {result_on_branch} which was passed-by-value to {Push}.
|
||||
Value* value_on_branch = stack_value(1);
|
||||
if (V8_LIKELY(current_code_reachable_and_ok_)) {
|
||||
if (opcode == kExprBrOnData) {
|
||||
CALL_INTERFACE(BrOnData, obj, value_on_branch, branch_depth.depth);
|
||||
if (opcode == kExprBrOnStruct) {
|
||||
CALL_INTERFACE(BrOnStruct, obj, value_on_branch,
|
||||
branch_depth.depth);
|
||||
} else if (opcode == kExprBrOnArray) {
|
||||
CALL_INTERFACE(BrOnArray, obj, value_on_branch, branch_depth.depth);
|
||||
} else {
|
||||
@ -5181,7 +5198,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
|
||||
Push(obj); // Restore stack state on fallthrough.
|
||||
return opcode_length + branch_depth.length;
|
||||
}
|
||||
case kExprBrOnNonData:
|
||||
case kExprBrOnNonStruct:
|
||||
case kExprBrOnNonArray:
|
||||
case kExprBrOnNonI31: {
|
||||
NON_CONST_ONLY
|
||||
@ -5202,14 +5219,14 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
|
||||
|
||||
Value obj = Peek(0, 0, kWasmAnyRef);
|
||||
HeapType::Representation heap_type =
|
||||
opcode == kExprBrOnNonData ? HeapType::kData
|
||||
opcode == kExprBrOnNonStruct ? HeapType::kStruct
|
||||
: opcode == kExprBrOnNonArray ? HeapType::kArray
|
||||
: HeapType::kI31;
|
||||
Value value_on_fallthrough = CreateValue(ValueType::Ref(heap_type));
|
||||
|
||||
if (V8_LIKELY(current_code_reachable_and_ok_)) {
|
||||
if (opcode == kExprBrOnNonData) {
|
||||
CALL_INTERFACE(BrOnNonData, obj, &value_on_fallthrough,
|
||||
if (opcode == kExprBrOnNonStruct) {
|
||||
CALL_INTERFACE(BrOnNonStruct, obj, &value_on_fallthrough,
|
||||
branch_depth.depth);
|
||||
} else if (opcode == kExprBrOnNonArray) {
|
||||
CALL_INTERFACE(BrOnNonArray, obj, &value_on_fallthrough,
|
||||
|
@ -1314,30 +1314,30 @@ class WasmGraphBuildingInterface {
|
||||
null_succeeds));
|
||||
}
|
||||
|
||||
void RefIsData(FullDecoder* decoder, const Value& object, Value* result) {
|
||||
void RefIsStruct(FullDecoder* decoder, const Value& object, Value* result) {
|
||||
bool null_succeeds = false;
|
||||
SetAndTypeNode(result,
|
||||
builder_->RefIsData(object.node, object.type.is_nullable(),
|
||||
null_succeeds));
|
||||
builder_->RefIsStruct(object.node, object.type.is_nullable(),
|
||||
null_succeeds));
|
||||
}
|
||||
|
||||
void RefAsData(FullDecoder* decoder, const Value& object, Value* result) {
|
||||
TFNode* cast_object = builder_->RefAsData(
|
||||
void RefAsStruct(FullDecoder* decoder, const Value& object, Value* result) {
|
||||
TFNode* cast_object = builder_->RefAsStruct(
|
||||
object.node, object.type.is_nullable(), decoder->position());
|
||||
TFNode* rename = builder_->TypeGuard(cast_object, result->type);
|
||||
SetAndTypeNode(result, rename);
|
||||
}
|
||||
|
||||
void BrOnData(FullDecoder* decoder, const Value& object,
|
||||
Value* value_on_branch, uint32_t br_depth) {
|
||||
BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnData>(
|
||||
void BrOnStruct(FullDecoder* decoder, const Value& object,
|
||||
Value* value_on_branch, uint32_t br_depth) {
|
||||
BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnStruct>(
|
||||
decoder, object, Value{nullptr, kWasmBottom}, value_on_branch, br_depth,
|
||||
true);
|
||||
}
|
||||
|
||||
void BrOnNonData(FullDecoder* decoder, const Value& object,
|
||||
Value* value_on_fallthrough, uint32_t br_depth) {
|
||||
BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnData>(
|
||||
void BrOnNonStruct(FullDecoder* decoder, const Value& object,
|
||||
Value* value_on_fallthrough, uint32_t br_depth) {
|
||||
BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnStruct>(
|
||||
decoder, object, Value{nullptr, kWasmBottom}, value_on_fallthrough,
|
||||
br_depth, false);
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ class HeapType {
|
||||
kFunc = kV8MaxWasmTypes, // shorthand: c
|
||||
kEq, // shorthand: q
|
||||
kI31, // shorthand: j
|
||||
kData, // shorthand: o
|
||||
kStruct, // shorthand: o
|
||||
kArray, // shorthand: g
|
||||
kAny, //
|
||||
kExtern, // shorthand: a.
|
||||
@ -90,8 +90,8 @@ class HeapType {
|
||||
return HeapType(kAny);
|
||||
case ValueTypeCode::kExternRefCode:
|
||||
return HeapType(kExtern);
|
||||
case ValueTypeCode::kDataRefCode:
|
||||
return HeapType(kData);
|
||||
case ValueTypeCode::kStructRefCode:
|
||||
return HeapType(kStruct);
|
||||
case ValueTypeCode::kArrayRefCode:
|
||||
return HeapType(kArray);
|
||||
case ValueTypeCode::kStringRefCode:
|
||||
@ -156,8 +156,8 @@ class HeapType {
|
||||
return std::string("eq");
|
||||
case kI31:
|
||||
return std::string("i31");
|
||||
case kData:
|
||||
return std::string("data");
|
||||
case kStruct:
|
||||
return std::string("struct");
|
||||
case kArray:
|
||||
return std::string("array");
|
||||
case kExtern:
|
||||
@ -195,8 +195,8 @@ class HeapType {
|
||||
return mask | kEqRefCode;
|
||||
case kI31:
|
||||
return mask | kI31RefCode;
|
||||
case kData:
|
||||
return mask | kDataRefCode;
|
||||
case kStruct:
|
||||
return mask | kStructRefCode;
|
||||
case kArray:
|
||||
return mask | kArrayRefCode;
|
||||
case kExtern:
|
||||
@ -550,8 +550,8 @@ class ValueType {
|
||||
return kAnyRefCode;
|
||||
case HeapType::kI31:
|
||||
return kI31RefCode;
|
||||
case HeapType::kData:
|
||||
return kDataRefCode;
|
||||
case HeapType::kStruct:
|
||||
return kStructRefCode;
|
||||
case HeapType::kArray:
|
||||
return kArrayRefCode;
|
||||
case HeapType::kString:
|
||||
@ -702,7 +702,7 @@ constexpr ValueType kWasmAnyRef = ValueType::RefNull(HeapType::kAny);
|
||||
constexpr ValueType kWasmExternRef = ValueType::RefNull(HeapType::kExtern);
|
||||
constexpr ValueType kWasmEqRef = ValueType::RefNull(HeapType::kEq);
|
||||
constexpr ValueType kWasmI31Ref = ValueType::RefNull(HeapType::kI31);
|
||||
constexpr ValueType kWasmDataRef = ValueType::RefNull(HeapType::kData);
|
||||
constexpr ValueType kWasmStructRef = ValueType::RefNull(HeapType::kStruct);
|
||||
constexpr ValueType kWasmArrayRef = ValueType::RefNull(HeapType::kArray);
|
||||
constexpr ValueType kWasmStringRef = ValueType::RefNull(HeapType::kString);
|
||||
constexpr ValueType kWasmStringViewWtf8 =
|
||||
|
@ -48,7 +48,7 @@ enum ValueTypeCode : uint8_t {
|
||||
kRefNullCode = 0x6c,
|
||||
kRefCode = 0x6b,
|
||||
kI31RefCode = 0x6a,
|
||||
kDataRefCode = 0x67,
|
||||
kStructRefCode = 0x67,
|
||||
kArrayRefCode = 0x66,
|
||||
kNoneCode = 0x65,
|
||||
kStringRefCode = 0x64,
|
||||
|
@ -1174,8 +1174,8 @@ void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
string->StringEquals(v8_str(isolate, "eqref"))) {
|
||||
type = i::wasm::kWasmEqRef;
|
||||
} else if (enabled_features.has_gc() &&
|
||||
string->StringEquals(v8_str(isolate, "dataref"))) {
|
||||
type = i::wasm::kWasmDataRef;
|
||||
string->StringEquals(v8_str(isolate, "structref"))) {
|
||||
type = i::wasm::kWasmStructRef;
|
||||
} else if (enabled_features.has_gc() &&
|
||||
string->StringEquals(v8_str(isolate, "arrayref"))) {
|
||||
type = i::wasm::kWasmArrayRef;
|
||||
@ -1390,8 +1390,8 @@ bool GetValueType(Isolate* isolate, MaybeLocal<Value> maybe,
|
||||
string->StringEquals(v8_str(isolate, "anyref"))) {
|
||||
*type = i::wasm::kWasmAnyRef;
|
||||
} else if (enabled_features.has_gc() &&
|
||||
string->StringEquals(v8_str(isolate, "dataref"))) {
|
||||
*type = i::wasm::kWasmDataRef;
|
||||
string->StringEquals(v8_str(isolate, "structref"))) {
|
||||
*type = i::wasm::kWasmStructRef;
|
||||
} else if (enabled_features.has_gc() &&
|
||||
string->StringEquals(v8_str(isolate, "arrayref"))) {
|
||||
*type = i::wasm::kWasmArrayRef;
|
||||
@ -1747,7 +1747,7 @@ void EncodeExceptionValues(v8::Isolate* isolate,
|
||||
case i::wasm::HeapType::kAny:
|
||||
case i::wasm::HeapType::kEq:
|
||||
case i::wasm::HeapType::kI31:
|
||||
case i::wasm::HeapType::kData:
|
||||
case i::wasm::HeapType::kStruct:
|
||||
case i::wasm::HeapType::kArray:
|
||||
case i::wasm::HeapType::kString:
|
||||
case i::wasm::HeapType::kStringViewWtf8:
|
||||
@ -2263,7 +2263,7 @@ void WasmObjectToJSReturnValue(v8::ReturnValue<v8::Value>& return_value,
|
||||
return;
|
||||
case i::wasm::HeapType::kBottom:
|
||||
UNREACHABLE();
|
||||
case i::wasm::HeapType::kData:
|
||||
case i::wasm::HeapType::kStruct:
|
||||
case i::wasm::HeapType::kArray:
|
||||
case i::wasm::HeapType::kEq:
|
||||
case i::wasm::HeapType::kAny: {
|
||||
@ -2572,7 +2572,7 @@ void WebAssemblyExceptionGetArg(
|
||||
case i::wasm::HeapType::kAny:
|
||||
case i::wasm::HeapType::kEq:
|
||||
case i::wasm::HeapType::kI31:
|
||||
case i::wasm::HeapType::kData:
|
||||
case i::wasm::HeapType::kStruct:
|
||||
case i::wasm::HeapType::kArray:
|
||||
case i::wasm::HeapType::kString:
|
||||
case i::wasm::HeapType::kStringViewWtf8:
|
||||
@ -2636,7 +2636,7 @@ void WebAssemblyExceptionGetArg(
|
||||
case i::wasm::HeapType::kEq:
|
||||
case i::wasm::HeapType::kI31:
|
||||
case i::wasm::HeapType::kArray:
|
||||
case i::wasm::HeapType::kData:
|
||||
case i::wasm::HeapType::kStruct:
|
||||
case i::wasm::HeapType::kString:
|
||||
case i::wasm::HeapType::kStringViewWtf8:
|
||||
case i::wasm::HeapType::kStringViewWtf16:
|
||||
|
@ -325,7 +325,7 @@ void WasmTableObject::Set(Isolate* isolate, Handle<WasmTableObject> table,
|
||||
case wasm::HeapType::kStringViewWtf16:
|
||||
case wasm::HeapType::kStringViewIter:
|
||||
case wasm::HeapType::kEq:
|
||||
case wasm::HeapType::kData:
|
||||
case wasm::HeapType::kStruct:
|
||||
case wasm::HeapType::kArray:
|
||||
case wasm::HeapType::kAny:
|
||||
case wasm::HeapType::kI31:
|
||||
@ -373,7 +373,7 @@ Handle<Object> WasmTableObject::Get(Isolate* isolate,
|
||||
case wasm::HeapType::kString:
|
||||
case wasm::HeapType::kEq:
|
||||
case wasm::HeapType::kI31:
|
||||
case wasm::HeapType::kData:
|
||||
case wasm::HeapType::kStruct:
|
||||
case wasm::HeapType::kArray:
|
||||
case wasm::HeapType::kAny:
|
||||
return entry;
|
||||
@ -2291,15 +2291,16 @@ MaybeHandle<Object> JSToWasmObject(Isolate* isolate, const WasmModule* module,
|
||||
*error_message = "null is not allowed for (ref any)";
|
||||
return {};
|
||||
}
|
||||
case HeapType::kData: {
|
||||
case HeapType::kStruct: {
|
||||
if (v8_flags.wasm_gc_js_interop
|
||||
? value->IsWasmStruct() || value->IsWasmArray()
|
||||
? value->IsWasmStruct() ||
|
||||
(value->IsWasmArray() &&
|
||||
v8_flags.wasm_gc_structref_as_dataref)
|
||||
: TryUnpackObjectWrapper(isolate, value)) {
|
||||
return value;
|
||||
}
|
||||
*error_message =
|
||||
"dataref object must be null (if nullable) or a wasm "
|
||||
"struct/array";
|
||||
"structref object must be null (if nullable) or a wasm struct";
|
||||
return {};
|
||||
}
|
||||
case HeapType::kArray: {
|
||||
|
@ -714,16 +714,16 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig,
|
||||
V(BrOnCast, 0xfb46, _, "br_on_cast") \
|
||||
V(BrOnCastFail, 0xfb47, _, "br_on_cast_fail") \
|
||||
V(RefCastNop, 0xfb4c, _, "ref.cast_nop") \
|
||||
V(RefIsData, 0xfb51, _, "ref.is_data") \
|
||||
V(RefIsStruct, 0xfb51, _, "ref.is_struct") \
|
||||
V(RefIsI31, 0xfb52, _, "ref.is_i31") \
|
||||
V(RefIsArray, 0xfb53, _, "ref.is_array") \
|
||||
V(RefAsData, 0xfb59, _, "ref.as_data") \
|
||||
V(RefAsStruct, 0xfb59, _, "ref.as_struct") \
|
||||
V(RefAsI31, 0xfb5a, _, "ref.as_i31") \
|
||||
V(RefAsArray, 0xfb5b, _, "ref.as_array") \
|
||||
V(BrOnData, 0xfb61, _, "br_on_data") \
|
||||
V(BrOnStruct, 0xfb61, _, "br_on_struct") \
|
||||
V(BrOnI31, 0xfb62, _, "br_on_i31") \
|
||||
V(BrOnArray, 0xfb66, _, "br_on_array") \
|
||||
V(BrOnNonData, 0xfb64, _, "br_on_non_data") \
|
||||
V(BrOnNonStruct, 0xfb64, _, "br_on_non_struct") \
|
||||
V(BrOnNonI31, 0xfb65, _, "br_on_non_i31") \
|
||||
V(BrOnNonArray, 0xfb67, _, "br_on_non_array") \
|
||||
V(ExternInternalize, 0xfb70, _, "extern.internalize") \
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "src/wasm/wasm-subtyping.h"
|
||||
|
||||
#include "src/base/v8-fallthrough.h"
|
||||
#include "src/wasm/canonical-types.h"
|
||||
#include "src/wasm/wasm-module.h"
|
||||
|
||||
@ -104,7 +105,7 @@ HeapType::Representation NullSentinelImpl(HeapType type,
|
||||
case HeapType::kI31:
|
||||
case HeapType::kNone:
|
||||
case HeapType::kEq:
|
||||
case HeapType::kData:
|
||||
case HeapType::kStruct:
|
||||
case HeapType::kArray:
|
||||
case HeapType::kAny:
|
||||
case HeapType::kString:
|
||||
@ -211,12 +212,17 @@ V8_NOINLINE V8_EXPORT_PRIVATE bool IsHeapSubtypeOfImpl(
|
||||
case HeapType::kExtern:
|
||||
return super_heap == HeapType::kExtern;
|
||||
case HeapType::kI31:
|
||||
case HeapType::kData:
|
||||
case HeapType::kStruct:
|
||||
case HeapType::kArray:
|
||||
if (v8_flags.wasm_gc_structref_as_dataref &&
|
||||
sub_heap.representation() == HeapType::kArray) {
|
||||
// TODO(7748): Remove temporary workaround for backwards compatibility.
|
||||
return super_heap == HeapType::kArray ||
|
||||
super_heap == HeapType::kStruct || super_heap == HeapType::kEq ||
|
||||
super_heap == HeapType::kAny;
|
||||
}
|
||||
return super_heap == sub_heap || super_heap == HeapType::kEq ||
|
||||
super_heap == HeapType::kAny;
|
||||
case HeapType::kArray:
|
||||
return super_heap == HeapType::kArray || super_heap == HeapType::kData ||
|
||||
super_heap == HeapType::kEq || super_heap == HeapType::kAny;
|
||||
case HeapType::kString:
|
||||
// stringref is a subtype of anyref under wasm-gc.
|
||||
return sub_heap == super_heap ||
|
||||
@ -256,8 +262,12 @@ V8_NOINLINE V8_EXPORT_PRIVATE bool IsHeapSubtypeOfImpl(
|
||||
switch (super_heap.representation()) {
|
||||
case HeapType::kFunc:
|
||||
return sub_module->has_signature(sub_index);
|
||||
case HeapType::kStruct:
|
||||
if (!v8_flags.wasm_gc_structref_as_dataref) {
|
||||
return sub_module->has_struct(sub_index);
|
||||
}
|
||||
V8_FALLTHROUGH;
|
||||
case HeapType::kEq:
|
||||
case HeapType::kData:
|
||||
case HeapType::kAny:
|
||||
return !sub_module->has_signature(sub_index);
|
||||
case HeapType::kArray:
|
||||
@ -345,14 +355,25 @@ HeapType::Representation CommonAncestor(uint32_t type_index1,
|
||||
DCHECK_EQ(kind2, kind1);
|
||||
return HeapType::kFunc;
|
||||
case TypeDefinition::kStruct:
|
||||
DCHECK_NE(kind2, TypeDefinition::kFunction);
|
||||
return HeapType::kData;
|
||||
if (v8_flags.wasm_gc_structref_as_dataref) {
|
||||
DCHECK_NE(kind2, TypeDefinition::kFunction);
|
||||
return HeapType::kStruct;
|
||||
}
|
||||
switch (kind2) {
|
||||
case TypeDefinition::kFunction:
|
||||
UNREACHABLE();
|
||||
case TypeDefinition::kStruct:
|
||||
return HeapType::kStruct;
|
||||
case TypeDefinition::kArray:
|
||||
return HeapType::kEq;
|
||||
}
|
||||
case TypeDefinition::kArray:
|
||||
switch (kind2) {
|
||||
case TypeDefinition::kFunction:
|
||||
UNREACHABLE();
|
||||
case TypeDefinition::kStruct:
|
||||
return HeapType::kData;
|
||||
return v8_flags.wasm_gc_structref_as_dataref ? HeapType::kStruct
|
||||
: HeapType::kEq;
|
||||
case TypeDefinition::kArray:
|
||||
return HeapType::kArray;
|
||||
}
|
||||
@ -380,7 +401,7 @@ HeapType::Representation CommonAncestorWithGeneric(HeapType heap1,
|
||||
case HeapType::kNone:
|
||||
return HeapType::kI31;
|
||||
case HeapType::kEq:
|
||||
case HeapType::kData:
|
||||
case HeapType::kStruct:
|
||||
case HeapType::kArray:
|
||||
return HeapType::kEq;
|
||||
case HeapType::kAny:
|
||||
@ -394,12 +415,14 @@ HeapType::Representation CommonAncestorWithGeneric(HeapType heap1,
|
||||
return module2->has_signature(heap2.ref_index()) ? HeapType::kBottom
|
||||
: HeapType::kEq;
|
||||
}
|
||||
case HeapType::kData:
|
||||
case HeapType::kStruct:
|
||||
switch (heap2.representation()) {
|
||||
case HeapType::kData:
|
||||
case HeapType::kArray:
|
||||
case HeapType::kStruct:
|
||||
case HeapType::kNone:
|
||||
return HeapType::kData;
|
||||
return HeapType::kStruct;
|
||||
case HeapType::kArray:
|
||||
return v8_flags.wasm_gc_structref_as_dataref ? HeapType::kStruct
|
||||
: HeapType::kEq;
|
||||
case HeapType::kI31:
|
||||
case HeapType::kEq:
|
||||
return HeapType::kEq;
|
||||
@ -412,15 +435,17 @@ HeapType::Representation CommonAncestorWithGeneric(HeapType heap1,
|
||||
UNREACHABLE();
|
||||
default:
|
||||
return module2->has_signature(heap2.ref_index()) ? HeapType::kBottom
|
||||
: HeapType::kData;
|
||||
: module2->has_struct(heap2.ref_index()) ? HeapType::kStruct
|
||||
: v8_flags.wasm_gc_structref_as_dataref ? HeapType::kStruct
|
||||
: HeapType::kEq;
|
||||
}
|
||||
case HeapType::kArray:
|
||||
switch (heap2.representation()) {
|
||||
case HeapType::kArray:
|
||||
case HeapType::kNone:
|
||||
return HeapType::kArray;
|
||||
case HeapType::kData:
|
||||
return HeapType::kData;
|
||||
case HeapType::kStruct:
|
||||
return HeapType::kEq;
|
||||
case HeapType::kI31:
|
||||
case HeapType::kEq:
|
||||
return HeapType::kEq;
|
||||
@ -432,9 +457,12 @@ HeapType::Representation CommonAncestorWithGeneric(HeapType heap1,
|
||||
case HeapType::kNoFunc:
|
||||
UNREACHABLE();
|
||||
default:
|
||||
return module2->has_array(heap2.ref_index()) ? HeapType::kArray
|
||||
: module2->has_struct(heap2.ref_index()) ? HeapType::kData
|
||||
: HeapType::kBottom;
|
||||
return module2->has_array(heap2.ref_index()) ? HeapType::kArray
|
||||
: module2->has_struct(heap2.ref_index())
|
||||
? (v8_flags.wasm_gc_structref_as_dataref
|
||||
? HeapType::kStruct
|
||||
: HeapType::kEq)
|
||||
: HeapType::kBottom;
|
||||
}
|
||||
case HeapType::kAny:
|
||||
return HeapType::kAny;
|
||||
@ -446,7 +474,7 @@ HeapType::Representation CommonAncestorWithGeneric(HeapType heap1,
|
||||
switch (heap2.representation()) {
|
||||
case HeapType::kArray:
|
||||
case HeapType::kNone:
|
||||
case HeapType::kData:
|
||||
case HeapType::kStruct:
|
||||
case HeapType::kI31:
|
||||
case HeapType::kEq:
|
||||
case HeapType::kAny:
|
||||
|
@ -571,7 +571,7 @@ WASM_COMPILED_EXEC_TEST(BrOnCast) {
|
||||
const byte other_type_index = tester.DefineStruct({F(kWasmF32, true)});
|
||||
|
||||
const byte kTestStructStatic = tester.DefineFunction(
|
||||
tester.sigs.i_v(), {kWasmI32, kWasmDataRef},
|
||||
tester.sigs.i_v(), {kWasmI32, kWasmStructRef},
|
||||
{WASM_BLOCK_R(
|
||||
ValueType::RefNull(type_index), WASM_LOCAL_SET(0, WASM_I32V(111)),
|
||||
// Pipe a struct through a local so it's statically typed
|
||||
@ -593,7 +593,7 @@ WASM_COMPILED_EXEC_TEST(BrOnCast) {
|
||||
kExprI32Add, kExprEnd});
|
||||
|
||||
const byte kTestNull = tester.DefineFunction(
|
||||
tester.sigs.i_v(), {kWasmI32, kWasmDataRef},
|
||||
tester.sigs.i_v(), {kWasmI32, kWasmStructRef},
|
||||
{WASM_BLOCK_R(
|
||||
ValueType::RefNull(type_index), WASM_LOCAL_SET(0, WASM_I32V(111)),
|
||||
WASM_LOCAL_GET(1), // Put a nullref onto the value stack.
|
||||
@ -604,7 +604,7 @@ WASM_COMPILED_EXEC_TEST(BrOnCast) {
|
||||
WASM_DROP, WASM_LOCAL_GET(0), kExprEnd});
|
||||
|
||||
const byte kTypedAfterBranch = tester.DefineFunction(
|
||||
tester.sigs.i_v(), {kWasmI32, kWasmDataRef},
|
||||
tester.sigs.i_v(), {kWasmI32, kWasmStructRef},
|
||||
{WASM_LOCAL_SET(1, WASM_STRUCT_NEW(type_index, WASM_I32V(42))),
|
||||
WASM_BLOCK_I(
|
||||
// The inner block should take the early branch with a struct
|
||||
@ -645,7 +645,7 @@ WASM_COMPILED_EXEC_TEST(BrOnCastFail) {
|
||||
#define FUNCTION_BODY(value) \
|
||||
WASM_LOCAL_SET(0, WASM_SEQ(value)), \
|
||||
WASM_BLOCK( \
|
||||
WASM_BLOCK_R(kWasmDataRef, WASM_LOCAL_GET(0), \
|
||||
WASM_BLOCK_R(kWasmStructRef, WASM_LOCAL_GET(0), \
|
||||
WASM_BR_ON_CAST_FAIL(0, type0), \
|
||||
WASM_GC_OP(kExprStructGet), type0, 0, kExprReturn), \
|
||||
kExprBrOnNull, 0, WASM_GC_OP(kExprRefCast), type1, \
|
||||
@ -653,16 +653,17 @@ WASM_COMPILED_EXEC_TEST(BrOnCastFail) {
|
||||
WASM_I32V(null_value), kExprEnd
|
||||
|
||||
const byte kBranchTaken = tester.DefineFunction(
|
||||
tester.sigs.i_v(), {kWasmDataRef},
|
||||
tester.sigs.i_v(), {kWasmStructRef},
|
||||
{FUNCTION_BODY(
|
||||
WASM_STRUCT_NEW(type1, WASM_I64V(10), WASM_I32V(field1_value)))});
|
||||
|
||||
const byte kBranchNotTaken = tester.DefineFunction(
|
||||
tester.sigs.i_v(), {kWasmDataRef},
|
||||
tester.sigs.i_v(), {kWasmStructRef},
|
||||
{FUNCTION_BODY(WASM_STRUCT_NEW(type0, WASM_I32V(field0_value)))});
|
||||
|
||||
const byte kNull = tester.DefineFunction(
|
||||
tester.sigs.i_v(), {kWasmDataRef}, {FUNCTION_BODY(WASM_REF_NULL(type0))});
|
||||
const byte kNull =
|
||||
tester.DefineFunction(tester.sigs.i_v(), {kWasmStructRef},
|
||||
{FUNCTION_BODY(WASM_REF_NULL(type0))});
|
||||
|
||||
const byte kUnrelatedTypes = tester.DefineFunction(
|
||||
tester.sigs.i_v(), {ValueType::RefNull(type1)},
|
||||
@ -671,11 +672,11 @@ WASM_COMPILED_EXEC_TEST(BrOnCastFail) {
|
||||
#undef FUNCTION_BODY
|
||||
|
||||
const byte kBranchTakenStatic = tester.DefineFunction(
|
||||
tester.sigs.i_v(), {kWasmDataRef},
|
||||
tester.sigs.i_v(), {kWasmStructRef},
|
||||
{WASM_LOCAL_SET(
|
||||
0, WASM_STRUCT_NEW(type1, WASM_I64V(10), WASM_I32V(field1_value))),
|
||||
WASM_BLOCK(
|
||||
WASM_BLOCK_R(kWasmDataRef, WASM_LOCAL_GET(0),
|
||||
WASM_BLOCK_R(kWasmStructRef, WASM_LOCAL_GET(0),
|
||||
WASM_BR_ON_CAST_FAIL(0, type0),
|
||||
WASM_GC_OP(kExprStructGet), type0, 0, kExprReturn),
|
||||
kExprBrOnNull, 0, WASM_GC_OP(kExprRefCast), type1,
|
||||
@ -1559,7 +1560,7 @@ WASM_COMPILED_EXEC_TEST(CallAbstractNullTypeImplicitConversion) {
|
||||
{kWasmFuncRef, kNoFuncCode},
|
||||
{kWasmEqRef, kNoneCode},
|
||||
{kWasmI31Ref.AsNullable(), kNoneCode},
|
||||
{kWasmDataRef.AsNullable(), kNoneCode},
|
||||
{kWasmStructRef.AsNullable(), kNoneCode},
|
||||
{kWasmArrayRef.AsNullable(), kNoneCode},
|
||||
{kWasmAnyRef, kNoneCode},
|
||||
{kWasmExternRef, kNoExternCode},
|
||||
@ -1602,14 +1603,15 @@ WASM_COMPILED_EXEC_TEST(CastNullRef) {
|
||||
tester.sigs.i_v(), {},
|
||||
{WASM_REF_IS_NULL(WASM_REF_AS_ARRAY(WASM_REF_NULL(kNoneCode))),
|
||||
kExprEnd});
|
||||
byte to_data = tester.DefineFunction(
|
||||
byte to_struct = tester.DefineFunction(
|
||||
tester.sigs.i_v(), {},
|
||||
{WASM_REF_IS_NULL(WASM_REF_AS_DATA(WASM_REF_NULL(kNoneCode))), kExprEnd});
|
||||
{WASM_REF_IS_NULL(WASM_REF_AS_STRUCT(WASM_REF_NULL(kNoneCode))),
|
||||
kExprEnd});
|
||||
byte to_i31 = tester.DefineFunction(
|
||||
tester.sigs.i_v(), {},
|
||||
{WASM_REF_IS_NULL(WASM_REF_AS_I31(WASM_REF_NULL(kNoneCode))), kExprEnd});
|
||||
byte struct_idx = tester.DefineStruct({F(wasm::kWasmI32, true)});
|
||||
byte to_struct = tester.DefineFunction(
|
||||
byte to_struct_idx = tester.DefineFunction(
|
||||
tester.sigs.i_v(), {},
|
||||
{WASM_REF_IS_NULL(WASM_REF_CAST(WASM_REF_NULL(kNoneCode), struct_idx)),
|
||||
kExprEnd});
|
||||
@ -1617,10 +1619,10 @@ WASM_COMPILED_EXEC_TEST(CastNullRef) {
|
||||
// Generic casts trap on null.
|
||||
tester.CheckHasThrown(to_non_null);
|
||||
tester.CheckHasThrown(to_array);
|
||||
tester.CheckHasThrown(to_data);
|
||||
tester.CheckHasThrown(to_struct);
|
||||
tester.CheckHasThrown(to_i31);
|
||||
// Static ref.cast succeeds.
|
||||
tester.CheckResult(to_struct, 1);
|
||||
tester.CheckResult(to_struct_idx, 1);
|
||||
}
|
||||
|
||||
WASM_COMPILED_EXEC_TEST(CallReftypeParameters) {
|
||||
@ -1673,9 +1675,9 @@ WASM_COMPILED_EXEC_TEST(AbstractTypeChecks) {
|
||||
tester.AddGlobal(ValueType::RefNull(sig_index), false,
|
||||
WasmInitExpr::RefFuncConst(function_index));
|
||||
|
||||
byte kDataCheckNull = tester.DefineFunction(
|
||||
byte kStructCheckNull = tester.DefineFunction(
|
||||
tester.sigs.i_v(), {},
|
||||
{WASM_REF_IS_DATA(WASM_REF_NULL(kAnyRefCode)), kExprEnd});
|
||||
{WASM_REF_IS_STRUCT(WASM_REF_NULL(kAnyRefCode)), kExprEnd});
|
||||
byte kArrayCheckNull = tester.DefineFunction(
|
||||
tester.sigs.i_v(), {},
|
||||
{WASM_REF_IS_ARRAY(WASM_REF_NULL(kAnyRefCode)), kExprEnd});
|
||||
@ -1683,9 +1685,9 @@ WASM_COMPILED_EXEC_TEST(AbstractTypeChecks) {
|
||||
tester.sigs.i_v(), {},
|
||||
{WASM_REF_IS_I31(WASM_REF_NULL(kAnyRefCode)), kExprEnd});
|
||||
|
||||
byte kDataCastNull =
|
||||
byte kStructCastNull =
|
||||
tester.DefineFunction(tester.sigs.i_v(), {},
|
||||
{WASM_REF_AS_DATA(WASM_REF_NULL(kAnyRefCode)),
|
||||
{WASM_REF_AS_STRUCT(WASM_REF_NULL(kAnyRefCode)),
|
||||
WASM_DROP, WASM_I32V(1), kExprEnd});
|
||||
byte kArrayCastNull =
|
||||
tester.DefineFunction(tester.sigs.i_v(), {},
|
||||
@ -1701,9 +1703,9 @@ WASM_COMPILED_EXEC_TEST(AbstractTypeChecks) {
|
||||
{WASM_LOCAL_SET(0, WASM_SEQ(value)), \
|
||||
WASM_REF_IS_##type(WASM_LOCAL_GET(0)), kExprEnd})
|
||||
|
||||
byte kDataCheckSuccess =
|
||||
TYPE_CHECK(DATA, WASM_ARRAY_NEW_DEFAULT(array_index, WASM_I32V(10)));
|
||||
byte kDataCheckFailure = TYPE_CHECK(DATA, WASM_I31_NEW(WASM_I32V(42)));
|
||||
byte kStructCheckSuccess =
|
||||
TYPE_CHECK(STRUCT, WASM_STRUCT_NEW_DEFAULT(struct_index));
|
||||
byte kStructCheckFailure = TYPE_CHECK(STRUCT, WASM_I31_NEW(WASM_I32V(42)));
|
||||
byte kArrayCheckSuccess =
|
||||
TYPE_CHECK(ARRAY, WASM_ARRAY_NEW_DEFAULT(array_index, WASM_I32V(10)));
|
||||
byte kArrayCheckFailure =
|
||||
@ -1719,12 +1721,12 @@ WASM_COMPILED_EXEC_TEST(AbstractTypeChecks) {
|
||||
WASM_REF_AS_##type(WASM_LOCAL_GET(0)), WASM_DROP, \
|
||||
WASM_I32V(1), kExprEnd})
|
||||
|
||||
byte kDataCastSuccess =
|
||||
TYPE_CAST(DATA, WASM_ARRAY_NEW_DEFAULT(array_index, WASM_I32V(10)));
|
||||
byte kDataCastFailure = TYPE_CAST(DATA, WASM_I31_NEW(WASM_I32V(42)));
|
||||
byte kStructCastSuccess =
|
||||
TYPE_CAST(STRUCT, WASM_STRUCT_NEW_DEFAULT(struct_index));
|
||||
byte kStructCastFailure = TYPE_CAST(STRUCT, WASM_I31_NEW(WASM_I32V(42)));
|
||||
byte kArrayCastSuccess =
|
||||
TYPE_CAST(DATA, WASM_ARRAY_NEW_DEFAULT(array_index, WASM_I32V(10)));
|
||||
byte kArrayCastFailure = TYPE_CAST(DATA, WASM_I31_NEW(WASM_I32V(42)));
|
||||
TYPE_CAST(ARRAY, WASM_ARRAY_NEW_DEFAULT(array_index, WASM_I32V(10)));
|
||||
byte kArrayCastFailure = TYPE_CAST(ARRAY, WASM_I31_NEW(WASM_I32V(42)));
|
||||
byte kI31CastSuccess = TYPE_CAST(I31, WASM_I31_NEW(WASM_I32V(42)));
|
||||
byte kI31CastFailure =
|
||||
TYPE_CAST(I31, WASM_ARRAY_NEW_DEFAULT(array_index, WASM_I32V(10)));
|
||||
@ -1741,9 +1743,9 @@ WASM_COMPILED_EXEC_TEST(AbstractTypeChecks) {
|
||||
WASM_RETURN(WASM_I32V(0)))), \
|
||||
kExprEnd})
|
||||
|
||||
byte kBrOnDataTaken =
|
||||
BR_ON(DATA, Data, WASM_ARRAY_NEW_DEFAULT(array_index, WASM_I32V(10)));
|
||||
byte kBrOnDataNotTaken = BR_ON(DATA, Data, WASM_REF_NULL(kNoneCode));
|
||||
byte kBrOnStructTaken =
|
||||
BR_ON(STRUCT, Struct, WASM_STRUCT_NEW_DEFAULT(struct_index));
|
||||
byte kBrOnStructNotTaken = BR_ON(STRUCT, Struct, WASM_REF_NULL(kNoneCode));
|
||||
byte kBrOnArrayTaken =
|
||||
BR_ON(ARRAY, Array, WASM_ARRAY_NEW_DEFAULT(array_index, WASM_I32V(10)));
|
||||
byte kBrOnArrayNotTaken = BR_ON(ARRAY, Array, WASM_I31_NEW(WASM_I32V(42)));
|
||||
@ -1763,9 +1765,10 @@ WASM_COMPILED_EXEC_TEST(AbstractTypeChecks) {
|
||||
WASM_RETURN(WASM_I32V(1)))), \
|
||||
kExprEnd})
|
||||
|
||||
byte kBrOnNonDataNotTaken =
|
||||
BR_ON_NON(DATA, Data, WASM_ARRAY_NEW_DEFAULT(array_index, WASM_I32V(10)));
|
||||
byte kBrOnNonDataTaken = BR_ON_NON(DATA, Data, WASM_REF_NULL(kNoneCode));
|
||||
byte kBrOnNonStructNotTaken =
|
||||
BR_ON_NON(STRUCT, Struct, WASM_STRUCT_NEW_DEFAULT(struct_index));
|
||||
byte kBrOnNonStructTaken =
|
||||
BR_ON_NON(STRUCT, Struct, WASM_REF_NULL(kNoneCode));
|
||||
byte kBrOnNonArrayNotTaken = BR_ON_NON(
|
||||
ARRAY, Array, WASM_ARRAY_NEW_DEFAULT(array_index, WASM_I32V(10)));
|
||||
byte kBrOnNonArrayTaken =
|
||||
@ -1777,39 +1780,39 @@ WASM_COMPILED_EXEC_TEST(AbstractTypeChecks) {
|
||||
|
||||
tester.CompileModule();
|
||||
|
||||
tester.CheckResult(kDataCheckNull, 0);
|
||||
tester.CheckResult(kStructCheckNull, 0);
|
||||
tester.CheckResult(kArrayCheckNull, 0);
|
||||
tester.CheckResult(kI31CheckNull, 0);
|
||||
|
||||
tester.CheckHasThrown(kDataCastNull);
|
||||
tester.CheckHasThrown(kStructCastNull);
|
||||
tester.CheckHasThrown(kArrayCastNull);
|
||||
tester.CheckHasThrown(kI31CastNull);
|
||||
|
||||
tester.CheckResult(kDataCheckSuccess, 1);
|
||||
tester.CheckResult(kStructCheckSuccess, 1);
|
||||
tester.CheckResult(kArrayCheckSuccess, 1);
|
||||
tester.CheckResult(kI31CheckSuccess, 1);
|
||||
|
||||
tester.CheckResult(kDataCheckFailure, 0);
|
||||
tester.CheckResult(kStructCheckFailure, 0);
|
||||
tester.CheckResult(kArrayCheckFailure, 0);
|
||||
tester.CheckResult(kI31CheckFailure, 0);
|
||||
|
||||
tester.CheckResult(kDataCastSuccess, 1);
|
||||
tester.CheckResult(kStructCastSuccess, 1);
|
||||
tester.CheckResult(kArrayCastSuccess, 1);
|
||||
tester.CheckResult(kI31CastSuccess, 1);
|
||||
|
||||
tester.CheckHasThrown(kDataCastFailure);
|
||||
tester.CheckHasThrown(kStructCastFailure);
|
||||
tester.CheckHasThrown(kArrayCastFailure);
|
||||
tester.CheckHasThrown(kI31CastFailure);
|
||||
|
||||
tester.CheckResult(kBrOnDataTaken, 1);
|
||||
tester.CheckResult(kBrOnDataNotTaken, 0);
|
||||
tester.CheckResult(kBrOnStructTaken, 1);
|
||||
tester.CheckResult(kBrOnStructNotTaken, 0);
|
||||
tester.CheckResult(kBrOnArrayTaken, 1);
|
||||
tester.CheckResult(kBrOnArrayNotTaken, 0);
|
||||
tester.CheckResult(kBrOnI31Taken, 1);
|
||||
tester.CheckResult(kBrOnI31NotTaken, 0);
|
||||
|
||||
tester.CheckResult(kBrOnNonDataTaken, 0);
|
||||
tester.CheckResult(kBrOnNonDataNotTaken, 1);
|
||||
tester.CheckResult(kBrOnNonStructTaken, 0);
|
||||
tester.CheckResult(kBrOnNonStructNotTaken, 1);
|
||||
tester.CheckResult(kBrOnNonArrayTaken, 0);
|
||||
tester.CheckResult(kBrOnNonArrayNotTaken, 1);
|
||||
tester.CheckResult(kBrOnNonI31Taken, 0);
|
||||
@ -1824,7 +1827,7 @@ WASM_COMPILED_EXEC_TEST(CastsBenchmark) {
|
||||
const byte SubType = tester.DefineStruct(
|
||||
{F(wasm::kWasmI32, true), F(wasm::kWasmI32, true)}, SuperType);
|
||||
|
||||
const byte ListType = tester.DefineArray(kWasmDataRef, true);
|
||||
const byte ListType = tester.DefineArray(kWasmStructRef, true);
|
||||
|
||||
const byte List =
|
||||
tester.AddGlobal(ValueType::RefNull(ListType), true,
|
||||
@ -2014,9 +2017,9 @@ WASM_COMPILED_EXEC_TEST(JsAccess) {
|
||||
WasmGCTester tester(execution_tier);
|
||||
const byte type_index = tester.DefineStruct({F(wasm::kWasmI32, true)});
|
||||
ValueType kRefType = ref(type_index);
|
||||
ValueType kSupertypeToI[] = {kWasmI32, kWasmDataRef};
|
||||
ValueType kSupertypeToI[] = {kWasmI32, kWasmStructRef};
|
||||
FunctionSig sig_t_v(1, 0, &kRefType);
|
||||
FunctionSig sig_super_v(1, 0, &kWasmDataRef);
|
||||
FunctionSig sig_super_v(1, 0, &kWasmStructRef);
|
||||
FunctionSig sig_i_super(1, 1, kSupertypeToI);
|
||||
|
||||
tester.DefineExportedFunction(
|
||||
|
@ -539,21 +539,21 @@ inline uint16_t ExtractPrefixedOpcodeBytes(WasmOpcode opcode) {
|
||||
#define WASM_GC_INTERNALIZE(extern) extern, WASM_GC_OP(kExprExternInternalize)
|
||||
#define WASM_GC_EXTERNALIZE(ref) ref, WASM_GC_OP(kExprExternExternalize)
|
||||
|
||||
#define WASM_REF_IS_DATA(ref) ref, WASM_GC_OP(kExprRefIsData)
|
||||
#define WASM_REF_IS_STRUCT(ref) ref, WASM_GC_OP(kExprRefIsStruct)
|
||||
#define WASM_REF_IS_ARRAY(ref) ref, WASM_GC_OP(kExprRefIsArray)
|
||||
#define WASM_REF_IS_I31(ref) ref, WASM_GC_OP(kExprRefIsI31)
|
||||
#define WASM_REF_AS_DATA(ref) ref, WASM_GC_OP(kExprRefAsData)
|
||||
#define WASM_REF_AS_STRUCT(ref) ref, WASM_GC_OP(kExprRefAsStruct)
|
||||
#define WASM_REF_AS_ARRAY(ref) ref, WASM_GC_OP(kExprRefAsArray)
|
||||
#define WASM_REF_AS_I31(ref) ref, WASM_GC_OP(kExprRefAsI31)
|
||||
#define WASM_BR_ON_ARRAY(depth) \
|
||||
WASM_GC_OP(kExprBrOnArray), static_cast<byte>(depth)
|
||||
#define WASM_BR_ON_DATA(depth) \
|
||||
WASM_GC_OP(kExprBrOnData), static_cast<byte>(depth)
|
||||
#define WASM_BR_ON_STRUCT(depth) \
|
||||
WASM_GC_OP(kExprBrOnStruct), static_cast<byte>(depth)
|
||||
#define WASM_BR_ON_I31(depth) WASM_GC_OP(kExprBrOnI31), static_cast<byte>(depth)
|
||||
#define WASM_BR_ON_NON_ARRAY(depth) \
|
||||
WASM_GC_OP(kExprBrOnNonArray), static_cast<byte>(depth)
|
||||
#define WASM_BR_ON_NON_DATA(depth) \
|
||||
WASM_GC_OP(kExprBrOnNonData), static_cast<byte>(depth)
|
||||
#define WASM_BR_ON_NON_STRUCT(depth) \
|
||||
WASM_GC_OP(kExprBrOnNonStruct), static_cast<byte>(depth)
|
||||
#define WASM_BR_ON_NON_I31(depth) \
|
||||
WASM_GC_OP(kExprBrOnNonI31), static_cast<byte>(depth)
|
||||
|
||||
|
@ -131,7 +131,7 @@ ValueType GetValueTypeHelper(DataRange* data, bool liftoff_as_reference,
|
||||
kWasmNullExternRef, kWasmNullFuncRef});
|
||||
}
|
||||
if (include_generics == kIncludeGenerics) {
|
||||
types.insert(types.end(), {kWasmDataRef, kWasmAnyRef, kWasmEqRef});
|
||||
types.insert(types.end(), {kWasmStructRef, kWasmAnyRef, kWasmEqRef});
|
||||
}
|
||||
|
||||
// The last index of user-defined types allowed is different based on the
|
||||
@ -2111,8 +2111,10 @@ void WasmGenerator::GenerateRef(HeapType type, DataRange* data,
|
||||
}
|
||||
random = data->get<uint8_t>() % (num_data_types + emit_i31ref);
|
||||
}
|
||||
if (random < num_data_types) {
|
||||
GenerateRef(HeapType(HeapType::kData), data, nullability);
|
||||
if (random < num_structs_) {
|
||||
GenerateRef(HeapType(HeapType::kStruct), data, nullability);
|
||||
} else if (random < num_data_types) {
|
||||
GenerateRef(HeapType(HeapType::kArray), data, nullability);
|
||||
} else {
|
||||
GenerateRef(HeapType(HeapType::kI31), data, nullability);
|
||||
}
|
||||
@ -2132,18 +2134,18 @@ void WasmGenerator::GenerateRef(HeapType type, DataRange* data,
|
||||
GenerateRef(HeapType(random), data, nullability);
|
||||
return;
|
||||
}
|
||||
case HeapType::kData: {
|
||||
case HeapType::kStruct: {
|
||||
DCHECK(liftoff_as_reference_);
|
||||
constexpr uint8_t fallback_to_dataref = 2;
|
||||
uint8_t random = data->get<uint8_t>() %
|
||||
(num_arrays_ + num_structs_ + fallback_to_dataref);
|
||||
uint8_t random =
|
||||
data->get<uint8_t>() % (num_structs_ + fallback_to_dataref);
|
||||
// Try generating one of the alternatives
|
||||
// and continue to the rest of the methods in case it fails.
|
||||
if (random >= num_arrays_ + num_structs_) {
|
||||
if (random >= num_structs_) {
|
||||
if (GenerateOneOf(alternatives_other, type, data, nullability)) {
|
||||
return;
|
||||
}
|
||||
random = data->get<uint8_t>() % (num_arrays_ + num_structs_);
|
||||
random = data->get<uint8_t>() % num_structs_;
|
||||
}
|
||||
GenerateRef(HeapType(random), data, nullability);
|
||||
return;
|
||||
@ -2384,7 +2386,7 @@ WasmInitExpr GenerateInitExpr(Zone* zone, WasmModuleBuilder* builder,
|
||||
}
|
||||
case kRef: {
|
||||
switch (type.heap_type().representation()) {
|
||||
case HeapType::kData:
|
||||
case HeapType::kStruct:
|
||||
case HeapType::kAny:
|
||||
case HeapType::kEq: {
|
||||
// We materialize all these types with a struct because they are all
|
||||
|
@ -231,8 +231,8 @@ std::string HeapTypeToJSByteEncoding(HeapType heap_type) {
|
||||
return "kEqRefCode";
|
||||
case HeapType::kI31:
|
||||
return "kI31RefCode";
|
||||
case HeapType::kData:
|
||||
return "kDataRefCode";
|
||||
case HeapType::kStruct:
|
||||
return "kStructRefCode";
|
||||
case HeapType::kArray:
|
||||
return "kArrayRefCode";
|
||||
case HeapType::kAny:
|
||||
@ -260,8 +260,8 @@ std::string HeapTypeToConstantName(HeapType heap_type) {
|
||||
return "kWasmEqRef";
|
||||
case HeapType::kI31:
|
||||
return "kWasmI31Ref";
|
||||
case HeapType::kData:
|
||||
return "kWasmDataRef";
|
||||
case HeapType::kStruct:
|
||||
return "kWasmStructRef";
|
||||
case HeapType::kArray:
|
||||
return "kWasmArrayRef";
|
||||
case HeapType::kExtern:
|
||||
@ -309,7 +309,7 @@ std::string ValueTypeToConstantName(ValueType type) {
|
||||
return "kWasmAnyRef";
|
||||
case HeapType::kBottom:
|
||||
UNREACHABLE();
|
||||
case HeapType::kData:
|
||||
case HeapType::kStruct:
|
||||
case HeapType::kArray:
|
||||
case HeapType::kI31:
|
||||
default:
|
||||
|
@ -9,12 +9,12 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
|
||||
var builder = new WasmModuleBuilder();
|
||||
|
||||
var sig_index = builder.addType({params: [kWasmDataRef], results: [kWasmI32]});
|
||||
var sig_index = builder.addType({params: [kWasmStructRef], results: [kWasmI32]});
|
||||
|
||||
var sub1 = builder.addStruct([makeField(kWasmI32, true)]);
|
||||
var sub2 = builder.addStruct([makeField(kWasmI32, false)]);
|
||||
|
||||
builder.addFunction('producer', makeSig([], [kWasmDataRef]))
|
||||
builder.addFunction('producer', makeSig([], [kWasmStructRef]))
|
||||
.addBody([
|
||||
kExprI32Const, 10,
|
||||
kGCPrefix, kExprStructNew, sub1])
|
||||
|
@ -10,7 +10,7 @@ let builder = new WasmModuleBuilder();
|
||||
|
||||
builder.addFunction('repro', kSig_v_v)
|
||||
.exportFunc()
|
||||
.addLocals(wasmRefNullType(kWasmDataRef), 1)
|
||||
.addLocals(wasmRefNullType(kWasmStructRef), 1)
|
||||
.addBody([
|
||||
kExprI32Const, 0,
|
||||
kExprIf, kWasmVoid,
|
||||
|
@ -9,7 +9,7 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
var builder = new WasmModuleBuilder();
|
||||
|
||||
var sig_index = builder.addType(
|
||||
{params: [wasmRefType(kWasmDataRef)], results: []});
|
||||
{params: [wasmRefType(kWasmStructRef)], results: []});
|
||||
|
||||
builder.addFunction('main', sig_index).addBody([]).exportFunc();
|
||||
|
||||
|
@ -123,7 +123,7 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
.addBody([
|
||||
kExprLocalGet, 0, // offset in table
|
||||
kExprTableGet, table,
|
||||
kGCPrefix, kExprRefAsData,
|
||||
kGCPrefix, kExprRefAsArray,
|
||||
kGCPrefix, kExprRefCast, array_type_index,
|
||||
kExprLocalGet, 1, // index in the array
|
||||
kGCPrefix, kExprArrayGet, array_type_index,
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --experimental-wasm-gc
|
||||
// Flags: --experimental-wasm-gc --no-wasm-gc-structref-as-dataref
|
||||
|
||||
d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
|
||||
@ -43,7 +43,7 @@ d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
["Array", array],
|
||||
["I31", kI31RefCode],
|
||||
["AnyArray", kArrayRefCode],
|
||||
["Data", kDataRefCode],
|
||||
["Struct", kStructRefCode],
|
||||
["Eq", kEqRefCode],
|
||||
// 'ref.test any' is semantically the same as '!ref.is_null' here.
|
||||
["Any", kAnyRefCode],
|
||||
@ -108,14 +108,14 @@ d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
assertEquals([0, 0], wasm.refTestAnyArray(1));
|
||||
assertEquals([0, 0], wasm.refTestAnyArray({'JavaScript': 'Object'}));
|
||||
|
||||
assertEquals([0, 1], wasm.refTestData(null));
|
||||
assertEquals([0, 0], wasm.refTestData(undefined));
|
||||
assertEquals([1, 1], wasm.refTestData(wasm.createStructSuper()));
|
||||
assertEquals([1, 1], wasm.refTestData(wasm.createStructSub()));
|
||||
assertEquals([1, 1], wasm.refTestData(wasm.createArray()));
|
||||
assertEquals([0, 0], wasm.refTestData(wasm.createFuncRef()));
|
||||
assertEquals([0, 0], wasm.refTestData(1));
|
||||
assertEquals([0, 0], wasm.refTestData({'JavaScript': 'Object'}));
|
||||
assertEquals([0, 1], wasm.refTestStruct(null));
|
||||
assertEquals([0, 0], wasm.refTestStruct(undefined));
|
||||
assertEquals([1, 1], wasm.refTestStruct(wasm.createStructSuper()));
|
||||
assertEquals([1, 1], wasm.refTestStruct(wasm.createStructSub()));
|
||||
assertEquals([0, 0], wasm.refTestStruct(wasm.createArray()));
|
||||
assertEquals([0, 0], wasm.refTestStruct(wasm.createFuncRef()));
|
||||
assertEquals([0, 0], wasm.refTestStruct(1));
|
||||
assertEquals([0, 0], wasm.refTestStruct({'JavaScript': 'Object'}));
|
||||
|
||||
assertEquals([0, 1], wasm.refTestEq(null));
|
||||
assertEquals([0, 0], wasm.refTestEq(undefined));
|
||||
|
@ -2,7 +2,7 @@
|
||||
// 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
|
||||
// Flags: --experimental-wasm-gc --experimental-wasm-type-reflection --no-wasm-gc-structref-as-dataref
|
||||
|
||||
d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
|
||||
@ -110,7 +110,7 @@ d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
let types = {
|
||||
any: kWasmAnyRef,
|
||||
eq: kWasmEqRef,
|
||||
data: kWasmDataRef,
|
||||
struct: kWasmStructRef,
|
||||
anyArray: kWasmArrayRef,
|
||||
array: wasmRefNullType(array),
|
||||
structSuper: wasmRefNullType(structSuper),
|
||||
@ -137,7 +137,7 @@ d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
values: ['nullref', 'i31ref', 'structSuper', 'structSub', 'array'],
|
||||
targets: {
|
||||
eq: ['i31ref', 'structSuper', 'structSub', 'array'],
|
||||
data: ['structSuper', 'structSub', 'array'],
|
||||
struct: ['structSuper', 'structSub'],
|
||||
anyArray: ['array'],
|
||||
array: ['array'],
|
||||
structSuper: ['structSuper', 'structSub'],
|
||||
@ -149,7 +149,7 @@ d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
values: ['nullref', 'i31ref', 'structSuper', 'structSub', 'array'],
|
||||
targets: {
|
||||
eq: ['i31ref', 'structSuper', 'structSub', 'array'],
|
||||
data: ['structSuper', 'structSub', 'array'],
|
||||
struct: ['structSuper', 'structSub'],
|
||||
anyArray: ['array'],
|
||||
array: ['array'],
|
||||
structSuper: ['structSuper', 'structSub'],
|
||||
@ -157,11 +157,11 @@ d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
}
|
||||
},
|
||||
{
|
||||
source: 'data',
|
||||
values: ['nullref', 'structSuper', 'structSub', 'array'],
|
||||
source: 'struct',
|
||||
values: ['nullref', 'structSuper', 'structSub'],
|
||||
targets: {
|
||||
eq: ['structSuper', 'structSub', 'array'],
|
||||
data: ['structSuper', 'structSub', 'array'],
|
||||
eq: ['structSuper', 'structSub'],
|
||||
struct: ['structSuper', 'structSub'],
|
||||
anyArray: ['array'],
|
||||
array: ['array'],
|
||||
structSuper: ['structSuper', 'structSub'],
|
||||
@ -173,7 +173,7 @@ d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
values: ['nullref', 'array'],
|
||||
targets: {
|
||||
eq: ['array'],
|
||||
data: ['array'],
|
||||
struct: [],
|
||||
anyArray: ['array'],
|
||||
array: ['array'],
|
||||
structSuper: [],
|
||||
@ -185,7 +185,7 @@ d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
values: ['nullref', 'structSuper', 'structSub'],
|
||||
targets: {
|
||||
eq: ['structSuper', 'structSub'],
|
||||
data: ['structSuper', 'structSub'],
|
||||
struct: ['structSuper', 'structSub'],
|
||||
anyArray: [],
|
||||
array: [],
|
||||
structSuper: ['structSuper', 'structSub'],
|
||||
|
@ -20,7 +20,7 @@ builder.addFunction('getHelloArray', makeSig([], [kWasmArrayRef]))
|
||||
|
||||
builder.addFunction('getChar', makeSig([kWasmArrayRef, kWasmI32], [kWasmI32]))
|
||||
.addBody([
|
||||
kExprLocalGet, 0, kGCPrefix, kExprRefAsData, kGCPrefix,
|
||||
kExprLocalGet, 0, kGCPrefix, kExprRefAsArray, kGCPrefix,
|
||||
kExprRefCast, i16Array, kExprLocalGet, 1, kGCPrefix, kExprArrayGetS,
|
||||
i16Array
|
||||
])
|
||||
|
@ -11,7 +11,7 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
let struct = builder.addStruct([makeField(kWasmI32, true)]);
|
||||
|
||||
builder.addFunction("main", kSig_i_i)
|
||||
.addLocals(wasmRefNullType(kWasmDataRef), 1)
|
||||
.addLocals(wasmRefNullType(kWasmStructRef), 1)
|
||||
.addBody([
|
||||
kExprLocalGet, 0,
|
||||
kGCPrefix, kExprStructNew, struct,
|
||||
|
@ -16,7 +16,7 @@ builder.addFunction('readStruct', makeSig([kWasmExternRef], [kWasmI32]))
|
||||
.addBody([
|
||||
kExprLocalGet, 0, // --
|
||||
kGCPrefix, kExprExternInternalize, // --
|
||||
kGCPrefix, kExprRefAsData, // --
|
||||
kGCPrefix, kExprRefAsStruct, // --
|
||||
kGCPrefix, kExprRefCast, struct_type, // --
|
||||
kGCPrefix, kExprStructGet, struct_type, 0, // --
|
||||
]);
|
||||
|
@ -70,7 +70,7 @@ for (const wasm_obj of [struct, array]) {
|
||||
testThrowsRepeated(
|
||||
() => new WebAssembly.Tag({parameters: [wasm_obj]}), TypeError);
|
||||
|
||||
let tag = new WebAssembly.Tag({parameters: ['dataref']});
|
||||
let tag = new WebAssembly.Tag({parameters: ['structref']});
|
||||
testThrowsRepeated(() => new WebAssembly.Exception(wasm_obj), TypeError);
|
||||
testThrowsRepeated(() => new WebAssembly.Exception(tag, wasm_obj), TypeError);
|
||||
repeated(() => new WebAssembly.Exception(tag, [wasm_obj]));
|
||||
|
@ -551,7 +551,7 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
|
||||
builder.addFunction("main", makeSig([kWasmExternRef], [kWasmI32]))
|
||||
.addBody([kExprLocalGet, 0, kGCPrefix, kExprExternInternalize,
|
||||
kGCPrefix, kExprRefAsData,
|
||||
kGCPrefix, kExprRefAsStruct,
|
||||
kGCPrefix, kExprRefCast, struct_a,
|
||||
kExprCallFunction, callee.index])
|
||||
.exportFunc();
|
||||
|
@ -3,6 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --experimental-wasm-gc --experimental-wasm-stringref
|
||||
// Flags: --no-wasm-gc-structref-as-dataref
|
||||
d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
|
||||
// Test type checks when creating a global with a value imported from a global
|
||||
@ -301,7 +302,7 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
builder.addFunction("get_struct_val", makeSig([], [kWasmI32]))
|
||||
.addBody([
|
||||
kExprGlobalGet, 0,
|
||||
kGCPrefix, kExprRefAsData,
|
||||
kGCPrefix, kExprRefAsStruct,
|
||||
kGCPrefix, kExprRefCast, struct_type,
|
||||
kGCPrefix, kExprStructGet, struct_type, 0,
|
||||
])
|
||||
@ -309,7 +310,7 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
builder.addFunction("get_array_val", makeSig([], [kWasmI32]))
|
||||
.addBody([
|
||||
kExprGlobalGet, 0,
|
||||
kGCPrefix, kExprRefAsData,
|
||||
kGCPrefix, kExprRefAsArray,
|
||||
kGCPrefix, kExprRefCast, array_type,
|
||||
kExprI32Const, 0,
|
||||
kGCPrefix, kExprArrayGet, array_type,
|
||||
@ -369,7 +370,7 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
builder.addFunction("get_struct_val", makeSig([], [kWasmI32]))
|
||||
.addBody([
|
||||
kExprGlobalGet, 0,
|
||||
kGCPrefix, kExprRefAsData,
|
||||
kGCPrefix, kExprRefAsStruct,
|
||||
kGCPrefix, kExprRefCast, struct_type,
|
||||
kGCPrefix, kExprStructGet, struct_type, 0,
|
||||
])
|
||||
@ -377,7 +378,7 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
builder.addFunction("get_array_val", makeSig([], [kWasmI32]))
|
||||
.addBody([
|
||||
kExprGlobalGet, 0,
|
||||
kGCPrefix, kExprRefAsData,
|
||||
kGCPrefix, kExprRefAsArray,
|
||||
kGCPrefix, kExprRefCast, array_type,
|
||||
kExprI32Const, 0,
|
||||
kGCPrefix, kExprArrayGet, array_type,
|
||||
@ -414,34 +415,25 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
assertThrows(() => eqref_global.value = "string", TypeError);
|
||||
})();
|
||||
|
||||
(function TestDataRefGlobalFromJS() {
|
||||
(function TestStructRefGlobalFromJS() {
|
||||
print(arguments.callee.name);
|
||||
let dataref_global = new WebAssembly.Global(
|
||||
{ value: "dataref", mutable: true }, null);
|
||||
assertNull(dataref_global.value);
|
||||
let structref_global = new WebAssembly.Global(
|
||||
{ value: "structref", mutable: true }, null);
|
||||
assertNull(structref_global.value);
|
||||
|
||||
let builder = new WasmModuleBuilder();
|
||||
builder.addImportedGlobal("imports", "dataref_global", kWasmDataRef, true);
|
||||
builder.addImportedGlobal("imports", "structref_global", kWasmStructRef, true);
|
||||
let struct_type = builder.addStruct([makeField(kWasmI32, false)]);
|
||||
let array_type = builder.addArray(kWasmI32);
|
||||
|
||||
builder.addFunction("get_struct_val", makeSig([], [kWasmI32]))
|
||||
.addBody([
|
||||
kExprGlobalGet, 0,
|
||||
kGCPrefix, kExprRefAsData,
|
||||
kGCPrefix, kExprRefAsStruct,
|
||||
kGCPrefix, kExprRefCast, struct_type,
|
||||
kGCPrefix, kExprStructGet, struct_type, 0,
|
||||
])
|
||||
.exportFunc();
|
||||
builder.addFunction("get_array_val", makeSig([], [kWasmI32]))
|
||||
.addBody([
|
||||
kExprGlobalGet, 0,
|
||||
kGCPrefix, kExprRefAsData,
|
||||
kGCPrefix, kExprRefCast, array_type,
|
||||
kExprI32Const, 0,
|
||||
kGCPrefix, kExprArrayGet, array_type,
|
||||
])
|
||||
.exportFunc();
|
||||
builder.addFunction("create_struct", makeSig([kWasmI32], [kWasmExternRef]))
|
||||
.addBody([
|
||||
kExprLocalGet, 0,
|
||||
@ -455,18 +447,17 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
kGCPrefix, kExprExternExternalize])
|
||||
.exportFunc();
|
||||
|
||||
let instance = builder.instantiate({imports : {dataref_global}});
|
||||
let instance = builder.instantiate({imports : {structref_global}});
|
||||
let wasm = instance.exports;
|
||||
|
||||
dataref_global.value = wasm.create_struct(42);
|
||||
structref_global.value = wasm.create_struct(42);
|
||||
assertEquals(42, wasm.get_struct_val());
|
||||
dataref_global.value = wasm.create_array(43);
|
||||
assertEquals(43, wasm.get_array_val());
|
||||
dataref_global.value = null;
|
||||
assertEquals(null, dataref_global.value);
|
||||
structref_global.value = null;
|
||||
assertEquals(null, structref_global.value);
|
||||
|
||||
assertThrows(() => dataref_global.value = undefined, TypeError);
|
||||
assertThrows(() => dataref_global.value = "string", TypeError);
|
||||
assertThrows(() => structref_global.value = undefined, TypeError);
|
||||
assertThrows(() => structref_global.value = "string", TypeError);
|
||||
assertThrows(() => structref_global.value = wasm.create_array(1), TypeError);
|
||||
})();
|
||||
|
||||
(function TestArrayRefGlobalFromJS() {
|
||||
@ -483,7 +474,7 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
builder.addFunction("get_array_val", makeSig([], [kWasmI32]))
|
||||
.addBody([
|
||||
kExprGlobalGet, 0,
|
||||
kGCPrefix, kExprRefAsData,
|
||||
kGCPrefix, kExprRefAsArray,
|
||||
kGCPrefix, kExprRefCast, array_type,
|
||||
kExprI32Const, 0,
|
||||
kGCPrefix, kExprArrayGet, array_type,
|
||||
|
@ -162,7 +162,7 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
kGCPrefix, kExprStructGet, composite_struct_index, 0])
|
||||
.exportFunc();
|
||||
|
||||
builder.addFunction("field_2_default", makeSig([], [kWasmDataRef]))
|
||||
builder.addFunction("field_2_default", makeSig([], [kWasmStructRef]))
|
||||
.addBody([
|
||||
kExprGlobalGet, global_default.index,
|
||||
kGCPrefix, kExprStructGet, composite_struct_index, 1])
|
||||
@ -245,7 +245,7 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
kGCPrefix, kExprStructGet, struct_index, 0])
|
||||
.exportFunc();
|
||||
|
||||
builder.addFunction("element1", makeSig([], [kWasmDataRef]))
|
||||
builder.addFunction("element1", makeSig([], [kWasmStructRef]))
|
||||
.addBody([
|
||||
kExprGlobalGet, global.index,
|
||||
kExprI32Const, 1,
|
||||
|
@ -2,14 +2,15 @@
|
||||
// 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-stringref --wasm-gc-js-interop
|
||||
// Flags: --experimental-wasm-gc --experimental-wasm-stringref
|
||||
// Flags: --wasm-gc-js-interop --no-wasm-gc-structref-as-dataref
|
||||
|
||||
d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
|
||||
let tableTypes = {
|
||||
"anyref": kWasmAnyRef,
|
||||
"eqref": kWasmEqRef,
|
||||
"dataref": kWasmDataRef,
|
||||
"structref": kWasmStructRef,
|
||||
"arrayref": kWasmArrayRef,
|
||||
};
|
||||
|
||||
@ -74,7 +75,7 @@ for (let [typeName, type] of Object.entries(tableTypes)) {
|
||||
builder.addFunction("tableGetStructVal", getValSig)
|
||||
.addBody([
|
||||
kExprLocalGet, 0, kExprTableGet, 0,
|
||||
kGCPrefix, kExprRefAsData,
|
||||
kGCPrefix, kExprRefAsStruct,
|
||||
kGCPrefix, kExprRefCast, struct,
|
||||
kGCPrefix, kExprStructGet, struct, 0,
|
||||
])
|
||||
@ -82,7 +83,7 @@ for (let [typeName, type] of Object.entries(tableTypes)) {
|
||||
builder.addFunction("tableGetArrayVal", getValSig)
|
||||
.addBody([
|
||||
kExprLocalGet, 0, kExprTableGet, 0,
|
||||
kGCPrefix, kExprRefAsData,
|
||||
kGCPrefix, kExprRefAsArray,
|
||||
kGCPrefix, kExprRefCast, array,
|
||||
kExprI32Const, 0,
|
||||
kGCPrefix, kExprArrayGet, array,
|
||||
@ -106,21 +107,10 @@ for (let [typeName, type] of Object.entries(tableTypes)) {
|
||||
])
|
||||
.exportFunc();
|
||||
|
||||
let blockSig = builder.addType(makeSig([kWasmAnyRef], [kWasmEqRef]));
|
||||
let castExternToEqRef = [
|
||||
kGCPrefix, kExprExternInternalize,
|
||||
kExprBlock, blockSig,
|
||||
kGCPrefix, kExprBrOnI31, 0,
|
||||
kGCPrefix, kExprBrOnData, 0,
|
||||
// non-data, non-i31
|
||||
kExprUnreachable, // conversion failure
|
||||
kExprEnd,
|
||||
];
|
||||
|
||||
builder.addFunction("createNull", creatorSig)
|
||||
.addBody([kExprRefNull, kNullRefCode])
|
||||
.exportFunc();
|
||||
let i31Sig = typeName != "dataref" && typeName != "arrayref"
|
||||
let i31Sig = typeName != "structref" && typeName != "arrayref"
|
||||
? creatorSig : creatorAnySig;
|
||||
builder.addFunction("createI31", i31Sig)
|
||||
.addBody([kExprI32Const, 12, kGCPrefix, kExprI31New])
|
||||
@ -129,7 +119,8 @@ for (let [typeName, type] of Object.entries(tableTypes)) {
|
||||
builder.addFunction("createStruct", structSig)
|
||||
.addBody([kExprI32Const, 12, kGCPrefix, kExprStructNew, struct])
|
||||
.exportFunc();
|
||||
builder.addFunction("createArray", creatorSig)
|
||||
let arraySig = typeName != "structref" ? creatorSig : creatorAnySig;
|
||||
builder.addFunction("createArray", arraySig)
|
||||
.addBody([
|
||||
kExprI32Const, 12,
|
||||
kGCPrefix, kExprArrayNewFixed, array, 1
|
||||
@ -159,7 +150,7 @@ for (let [typeName, type] of Object.entries(tableTypes)) {
|
||||
assertEquals(null, wasm.tableGet(1));
|
||||
assertEquals(null, table.get(1));
|
||||
// Set i31.
|
||||
if (typeName != "dataref" && typeName != "arrayref") {
|
||||
if (typeName != "structref" && typeName != "arrayref") {
|
||||
table.set(2, wasm.exported(wasm.createI31));
|
||||
assertSame(table.get(2), wasm.tableGet(2));
|
||||
wasm.tableSet(3, wasm.createI31);
|
||||
@ -177,13 +168,15 @@ for (let [typeName, type] of Object.entries(tableTypes)) {
|
||||
assertNotSame(table.get(4), table.get(5));
|
||||
}
|
||||
// Set array.
|
||||
table.set(6, wasm.exported(wasm.createArray));
|
||||
assertSame(table.get(6), wasm.tableGet(6));
|
||||
assertEquals(12, wasm.tableGetArrayVal(6));
|
||||
wasm.tableSet(7, wasm.createArray);
|
||||
assertSame(table.get(7), wasm.tableGet(7));
|
||||
assertEquals(12, wasm.tableGetArrayVal(7));
|
||||
assertNotSame(table.get(6), table.get(7));
|
||||
if (typeName != "structref") {
|
||||
table.set(6, wasm.exported(wasm.createArray));
|
||||
assertSame(table.get(6), wasm.tableGet(6));
|
||||
assertEquals(12, wasm.tableGetArrayVal(6));
|
||||
wasm.tableSet(7, wasm.createArray);
|
||||
assertSame(table.get(7), wasm.tableGet(7));
|
||||
assertEquals(12, wasm.tableGetArrayVal(7));
|
||||
assertNotSame(table.get(6), table.get(7));
|
||||
}
|
||||
|
||||
// Set stringref.
|
||||
if (typeName == "anyref") {
|
||||
@ -217,7 +210,7 @@ for (let [typeName, type] of Object.entries(tableTypes)) {
|
||||
let invalidValues = {
|
||||
"anyref": [],
|
||||
"eqref": [],
|
||||
"dataref": ["I31"],
|
||||
"structref": ["I31", "Array"],
|
||||
"arrayref": ["I31", "Struct"],
|
||||
};
|
||||
for (let invalidType of invalidValues[typeName]) {
|
||||
|
@ -186,7 +186,7 @@ d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
builder.addFunction("struct_getter", kSig_i_v)
|
||||
.addBody([
|
||||
kExprI32Const, 2, kExprTableGet, 0,
|
||||
kGCPrefix, kExprRefAsData, kGCPrefix, kExprRefCast, struct_type,
|
||||
kGCPrefix, kExprRefAsStruct, kGCPrefix, kExprRefCast, struct_type,
|
||||
kGCPrefix, kExprStructGet, struct_type, 0])
|
||||
.exportFunc();
|
||||
|
||||
@ -250,7 +250,7 @@ d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
builder.addFunction("struct_getter", kSig_i_i)
|
||||
.addBody([
|
||||
kExprLocalGet, 0, kExprTableGet, 0,
|
||||
kGCPrefix, kExprRefAsData, kGCPrefix, kExprRefCast, struct_type,
|
||||
kGCPrefix, kExprRefAsStruct, kGCPrefix, kExprRefCast, struct_type,
|
||||
kGCPrefix, kExprStructGet, struct_type, 0])
|
||||
.exportFunc();
|
||||
|
||||
|
@ -14,16 +14,16 @@ let identical_struct_index = builder.addStruct([makeField(kWasmI32, true)]);
|
||||
let distinct_struct_index = builder.addStruct([makeField(kWasmI64, true)]);
|
||||
|
||||
let struct_init = builder.addFunction("struct_init",
|
||||
makeSig([], [kWasmDataRef]))
|
||||
makeSig([], [kWasmStructRef]))
|
||||
.addBody([kGCPrefix, kExprStructNewDefault, struct_index])
|
||||
.exportFunc();
|
||||
let test_pass = builder.addFunction("test_pass",
|
||||
makeSig([kWasmDataRef], [kWasmI32]))
|
||||
makeSig([kWasmStructRef], [kWasmI32]))
|
||||
.addBody([kExprLocalGet, 0,
|
||||
kGCPrefix, kExprRefTestDeprecated, identical_struct_index])
|
||||
.exportFunc();
|
||||
let test_fail = builder.addFunction("test_fail",
|
||||
makeSig([kWasmDataRef], [kWasmI32]))
|
||||
makeSig([kWasmStructRef], [kWasmI32]))
|
||||
.addBody([kExprLocalGet, 0,
|
||||
kGCPrefix, kExprRefTestDeprecated, distinct_struct_index])
|
||||
.exportFunc();
|
||||
|
@ -188,7 +188,7 @@ function instantiate(buffer, ffi) {
|
||||
print(arguments.callee.name);
|
||||
// These are all positive type indices (e.g. kI31RefCode and not kWasmI31Ref)
|
||||
// and should be treated as such.
|
||||
let indices = [kI31RefCode, kDataRefCode, 200, 400];
|
||||
let indices = [kI31RefCode, kStructRefCode, 200, 400];
|
||||
let kMaxIndex = 400;
|
||||
let builder = new WasmModuleBuilder();
|
||||
for (let i = 0; i <= kMaxIndex; i++) {
|
||||
|
@ -43,7 +43,7 @@ let instance = (() => {
|
||||
kExprBlock, kWasmVoid,
|
||||
kExprLocalGet, 0,
|
||||
kExprBrOnNull, 0,
|
||||
kGCPrefix, kExprRefAsData,
|
||||
kGCPrefix, kExprRefAsStruct,
|
||||
kGCPrefix, kExprRefCast, struct,
|
||||
kGCPrefix, kExprStructGet, struct, 0, // value
|
||||
kExprI32Const, 0, // isNull
|
||||
@ -64,7 +64,7 @@ let instance = (() => {
|
||||
kExprLocalGet, 0,
|
||||
kGCPrefix, kExprExternInternalize,
|
||||
kExprBrOnNull, 0,
|
||||
kGCPrefix, kExprRefAsData,
|
||||
kGCPrefix, kExprRefAsStruct,
|
||||
kGCPrefix, kExprRefCast, struct,
|
||||
kGCPrefix, kExprStructGet, struct, 0, // value
|
||||
kExprI32Const, 0, // isNull
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --experimental-wasm-gc
|
||||
// Flags: --experimental-wasm-gc --no-wasm-gc-structref-as-dataref
|
||||
|
||||
d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
|
||||
@ -16,11 +16,11 @@ let instance = (() => {
|
||||
.addBody([kExprLocalGet, 0, kExprI32Const, 1, kExprI32Add])
|
||||
.exportAs('inc');
|
||||
|
||||
builder.addFunction('struct_producer', makeSig([], [kWasmDataRef]))
|
||||
builder.addFunction('struct_producer', makeSig([], [kWasmStructRef]))
|
||||
.addBody([kGCPrefix, kExprStructNewDefault, struct])
|
||||
.exportFunc();
|
||||
|
||||
builder.addFunction('array_producer', makeSig([], [kWasmDataRef]))
|
||||
builder.addFunction('array_producer', makeSig([], [kWasmArrayRef]))
|
||||
.addBody([
|
||||
kExprI32Const, 10,
|
||||
kGCPrefix, kExprArrayNewDefault, array
|
||||
@ -36,12 +36,11 @@ let instance = (() => {
|
||||
.exportFunc();
|
||||
|
||||
let test_types = {
|
||||
struct: kWasmDataRef,
|
||||
array: kWasmDataRef,
|
||||
struct: kWasmStructRef,
|
||||
array: kWasmArrayRef,
|
||||
raw_struct: struct,
|
||||
raw_array: array,
|
||||
typed_func: sig,
|
||||
data: kWasmDataRef,
|
||||
eq: kWasmEqRef,
|
||||
func: kWasmFuncRef,
|
||||
any: kWasmAnyRef,
|
||||
@ -67,15 +66,18 @@ let instance = (() => {
|
||||
// Wasm-exposed null is the same as JS null.
|
||||
assertEquals(instance.exports.struct_null(), null);
|
||||
|
||||
// We can roundtrip a struct as dataref.
|
||||
instance.exports.data_id(instance.exports.struct_producer());
|
||||
// We can roundtrip an array as dataref.
|
||||
instance.exports.data_id(instance.exports.array_producer());
|
||||
// We can roundtrip null as dataref.
|
||||
instance.exports.data_id(instance.exports.data_null());
|
||||
// We cannot roundtrip an i31 as dataref.
|
||||
// We can roundtrip a struct as structref.
|
||||
instance.exports.struct_id(instance.exports.struct_producer());
|
||||
// We cannot roundtrip an array as structref.
|
||||
assertThrows(
|
||||
() => instance.exports.data_id(instance.exports.i31_as_eq_producer()),
|
||||
() => instance.exports.struct_id(instance.exports.array_producer()),
|
||||
TypeError,
|
||||
'type incompatibility when transforming from/to JS');
|
||||
// We can roundtrip null as structref.
|
||||
instance.exports.struct_id(instance.exports.struct_null());
|
||||
// We cannot roundtrip an i31 as structref.
|
||||
assertThrows(
|
||||
() => instance.exports.struct_id(instance.exports.i31_as_eq_producer()),
|
||||
TypeError,
|
||||
'type incompatibility when transforming from/to JS');
|
||||
|
||||
@ -86,7 +88,7 @@ instance.exports.eq_id(instance.exports.array_producer());
|
||||
// We can roundtrip an i31 as eqref.
|
||||
instance.exports.eq_id(instance.exports.i31_as_eq_producer());
|
||||
// We can roundtrip any null as eqref.
|
||||
instance.exports.eq_id(instance.exports.data_null());
|
||||
instance.exports.eq_id(instance.exports.struct_null());
|
||||
instance.exports.eq_id(instance.exports.eq_null());
|
||||
instance.exports.eq_id(instance.exports.func_null());
|
||||
// We cannot roundtrip a func as eqref.
|
||||
|
@ -125,7 +125,7 @@ let kWasmEqRef = -0x13;
|
||||
let kWasmI31Ref = -0x16;
|
||||
let kWasmNullExternRef = -0x17;
|
||||
let kWasmNullFuncRef = -0x18;
|
||||
let kWasmDataRef = -0x19;
|
||||
let kWasmStructRef = -0x19;
|
||||
let kWasmArrayRef = -0x1a;
|
||||
let kWasmNullRef = -0x1b;
|
||||
let kWasmStringRef = -0x1c;
|
||||
@ -143,7 +143,7 @@ let kEqRefCode = kWasmEqRef & kLeb128Mask;
|
||||
let kI31RefCode = kWasmI31Ref & kLeb128Mask;
|
||||
let kNullExternRefCode = kWasmNullExternRef & kLeb128Mask;
|
||||
let kNullFuncRefCode = kWasmNullFuncRef & kLeb128Mask;
|
||||
let kDataRefCode = kWasmDataRef & kLeb128Mask;
|
||||
let kStructRefCode = kWasmStructRef & kLeb128Mask;
|
||||
let kArrayRefCode = kWasmArrayRef & kLeb128Mask;
|
||||
let kNullRefCode = kWasmNullRef & kLeb128Mask;
|
||||
let kStringRefCode = kWasmStringRef & kLeb128Mask;
|
||||
@ -517,13 +517,13 @@ let kExprRefCastNop = 0x4c;
|
||||
let kExprRefIsData = 0x51;
|
||||
let kExprRefIsI31 = 0x52;
|
||||
let kExprRefIsArray = 0x53;
|
||||
let kExprRefAsData = 0x59;
|
||||
let kExprRefAsStruct = 0x59;
|
||||
let kExprRefAsI31 = 0x5a;
|
||||
let kExprRefAsArray = 0x5b;
|
||||
let kExprBrOnData = 0x61;
|
||||
let kExprBrOnStruct = 0x61;
|
||||
let kExprBrOnI31 = 0x62;
|
||||
let kExprBrOnArray = 0x66;
|
||||
let kExprBrOnNonData = 0x64;
|
||||
let kExprBrOnNonStruct = 0x64;
|
||||
let kExprBrOnNonI31 = 0x65;
|
||||
let kExprBrOnNonArray = 0x67;
|
||||
let kExprExternInternalize = 0x70;
|
||||
|
@ -1173,8 +1173,8 @@ TEST_F(FunctionBodyDecoderTest, UnreachableRefTypes) {
|
||||
ExpectValidates(FunctionSig::Build(zone(), {struct_type}, {}),
|
||||
{WASM_UNREACHABLE, WASM_GC_OP(kExprRefCast), struct_index});
|
||||
|
||||
ExpectValidates(FunctionSig::Build(zone(), {kWasmDataRef}, {}),
|
||||
{WASM_UNREACHABLE, WASM_GC_OP(kExprRefAsData)});
|
||||
ExpectValidates(FunctionSig::Build(zone(), {kWasmStructRef}, {}),
|
||||
{WASM_UNREACHABLE, WASM_GC_OP(kExprRefAsStruct)});
|
||||
|
||||
ExpectValidates(FunctionSig::Build(zone(), {}, {struct_type_null}),
|
||||
{WASM_UNREACHABLE, WASM_LOCAL_GET(0), kExprBrOnNull, 0,
|
||||
@ -4311,8 +4311,8 @@ TEST_F(FunctionBodyDecoderTest, RefTestCast) {
|
||||
|
||||
std::tuple<HeapType::Representation, HeapType::Representation, bool, bool>
|
||||
tests[] = {
|
||||
std::make_tuple(HeapType::kData, array_heap, true, true),
|
||||
std::make_tuple(HeapType::kData, super_struct_heap, true, true),
|
||||
std::make_tuple(HeapType::kArray, array_heap, true, true),
|
||||
std::make_tuple(HeapType::kStruct, super_struct_heap, true, true),
|
||||
std::make_tuple(HeapType::kFunc, func_heap_1, true, true),
|
||||
std::make_tuple(func_heap_1, func_heap_1, true, true),
|
||||
std::make_tuple(func_heap_1, func_heap_2, true, true),
|
||||
@ -4350,8 +4350,8 @@ TEST_F(FunctionBodyDecoderTest, RefTestCast) {
|
||||
WASM_HEAP_TYPE(to_heap))});
|
||||
} else {
|
||||
std::string error_message =
|
||||
"[0] expected subtype of (ref null func) or (ref null data), found "
|
||||
"local.get of type " +
|
||||
"[0] expected subtype of (ref null func), (ref null struct) or (ref "
|
||||
"null array), found local.get of type " +
|
||||
test_reps[1].name();
|
||||
ExpectFailure(&test_sig,
|
||||
{WASM_REF_TEST_DEPRECATED(WASM_LOCAL_GET(0),
|
||||
@ -4381,8 +4381,8 @@ TEST_F(FunctionBodyDecoderTest, RefTestCast) {
|
||||
ExpectFailure(sigs.v_v(),
|
||||
{WASM_REF_TEST_DEPRECATED(WASM_I32V(1), array_heap), kExprDrop},
|
||||
kAppendEnd,
|
||||
"ref.test[0] expected subtype of (ref null func) or "
|
||||
"(ref null data), found i32.const of type i32");
|
||||
"ref.test[0] expected subtype of (ref null func), (ref null "
|
||||
"struct) or (ref null array), found i32.const of type i32");
|
||||
ExpectFailure(sigs.v_v(),
|
||||
{WASM_REF_TEST(WASM_I32V(1), array_heap), kExprDrop},
|
||||
kAppendEnd,
|
||||
@ -4391,8 +4391,8 @@ TEST_F(FunctionBodyDecoderTest, RefTestCast) {
|
||||
ExpectFailure(sigs.v_v(),
|
||||
{WASM_REF_CAST(WASM_I32V(1), array_heap), kExprDrop},
|
||||
kAppendEnd,
|
||||
"ref.cast[0] expected subtype of (ref null func) or "
|
||||
"(ref null data), found i32.const of type i32");
|
||||
"ref.cast[0] expected subtype of (ref null func), (ref null "
|
||||
"struct) or (ref null array), found i32.const of type i32");
|
||||
}
|
||||
|
||||
TEST_F(FunctionBodyDecoderTest, BrOnCastOrCastFail) {
|
||||
@ -4437,17 +4437,18 @@ TEST_F(FunctionBodyDecoderTest, BrOnCastOrCastFail) {
|
||||
kAppendEnd, "type error in branch[0] (expected i32, got (ref null 0))");
|
||||
|
||||
// Argument type error.
|
||||
ExpectFailure(FunctionSig::Build(this->zone(), {subtype}, {kWasmExternRef}),
|
||||
{WASM_LOCAL_GET(0), WASM_BR_ON_CAST(0, sub_struct),
|
||||
WASM_GC_OP(kExprRefCast), sub_struct},
|
||||
kAppendEnd,
|
||||
"br_on_cast[0] expected subtype of (ref null func) or "
|
||||
"(ref null data), found local.get of type externref");
|
||||
ExpectFailure(FunctionSig::Build(this->zone(), {supertype}, {kWasmExternRef}),
|
||||
{WASM_LOCAL_GET(0), WASM_BR_ON_CAST_FAIL(0, sub_struct)},
|
||||
kAppendEnd,
|
||||
"br_on_cast_fail[0] expected subtype of (ref null func) "
|
||||
"or (ref null data), found local.get of type externref");
|
||||
ExpectFailure(
|
||||
FunctionSig::Build(this->zone(), {subtype}, {kWasmExternRef}),
|
||||
{WASM_LOCAL_GET(0), WASM_BR_ON_CAST(0, sub_struct),
|
||||
WASM_GC_OP(kExprRefCast), sub_struct},
|
||||
kAppendEnd,
|
||||
"br_on_cast[0] expected subtype of (ref null func), (ref null struct) or "
|
||||
"(ref null array), found local.get of type externref");
|
||||
ExpectFailure(
|
||||
FunctionSig::Build(this->zone(), {supertype}, {kWasmExternRef}),
|
||||
{WASM_LOCAL_GET(0), WASM_BR_ON_CAST_FAIL(0, sub_struct)}, kAppendEnd,
|
||||
"br_on_cast_fail[0] expected subtype of (ref null func), (ref null "
|
||||
"struct) or (ref null array), found local.get of type externref");
|
||||
}
|
||||
|
||||
TEST_F(FunctionBodyDecoderTest, BrOnAbstractType) {
|
||||
@ -4458,11 +4459,11 @@ TEST_F(FunctionBodyDecoderTest, BrOnAbstractType) {
|
||||
ValueType kNonNullableFunc = ValueType::Ref(HeapType::kFunc);
|
||||
|
||||
ExpectValidates(
|
||||
FunctionSig::Build(this->zone(), {kWasmDataRef}, {kWasmAnyRef}),
|
||||
{WASM_LOCAL_GET(0), WASM_BR_ON_DATA(0), WASM_GC_OP(kExprRefAsData)});
|
||||
FunctionSig::Build(this->zone(), {kWasmStructRef}, {kWasmAnyRef}),
|
||||
{WASM_LOCAL_GET(0), WASM_BR_ON_STRUCT(0), WASM_GC_OP(kExprRefAsStruct)});
|
||||
ExpectValidates(
|
||||
FunctionSig::Build(this->zone(), {kWasmAnyRef}, {kWasmAnyRef}),
|
||||
{WASM_LOCAL_GET(0), WASM_BR_ON_NON_DATA(0)});
|
||||
{WASM_LOCAL_GET(0), WASM_BR_ON_NON_STRUCT(0)});
|
||||
ExpectValidates(
|
||||
FunctionSig::Build(this->zone(), {kWasmI31Ref}, {kWasmAnyRef}),
|
||||
{WASM_LOCAL_GET(0), WASM_BR_ON_I31(0), WASM_GC_OP(kExprRefAsI31)});
|
||||
@ -4472,20 +4473,21 @@ TEST_F(FunctionBodyDecoderTest, BrOnAbstractType) {
|
||||
|
||||
// Wrong branch type.
|
||||
ExpectFailure(FunctionSig::Build(this->zone(), {}, {kWasmAnyRef}),
|
||||
{WASM_LOCAL_GET(0), WASM_BR_ON_DATA(0), WASM_UNREACHABLE},
|
||||
{WASM_LOCAL_GET(0), WASM_BR_ON_STRUCT(0), WASM_UNREACHABLE},
|
||||
kAppendEnd,
|
||||
"br_on_data must target a branch of arity at least 1");
|
||||
"br_on_struct must target a branch of arity at least 1");
|
||||
ExpectFailure(
|
||||
FunctionSig::Build(this->zone(), {kNonNullableFunc}, {kWasmAnyRef}),
|
||||
{WASM_LOCAL_GET(0), WASM_BR_ON_NON_DATA(0)}, kAppendEnd,
|
||||
{WASM_LOCAL_GET(0), WASM_BR_ON_NON_STRUCT(0)}, kAppendEnd,
|
||||
"type error in branch[0] (expected (ref func), got anyref)");
|
||||
|
||||
// Wrong fallthrough type.
|
||||
ExpectFailure(FunctionSig::Build(this->zone(), {kWasmDataRef}, {kWasmAnyRef}),
|
||||
{WASM_LOCAL_GET(0), WASM_BR_ON_DATA(0)}, kAppendEnd,
|
||||
"type error in fallthru[0] (expected dataref, got anyref)");
|
||||
ExpectFailure(
|
||||
FunctionSig::Build(this->zone(), {kWasmStructRef}, {kWasmAnyRef}),
|
||||
{WASM_LOCAL_GET(0), WASM_BR_ON_STRUCT(0)}, kAppendEnd,
|
||||
"type error in fallthru[0] (expected structref, got anyref)");
|
||||
ExpectFailure(FunctionSig::Build(this->zone(), {kWasmAnyRef}, {kWasmAnyRef}),
|
||||
{WASM_BLOCK_I(WASM_LOCAL_GET(0), WASM_BR_ON_NON_DATA(0))},
|
||||
{WASM_BLOCK_I(WASM_LOCAL_GET(0), WASM_BR_ON_NON_STRUCT(0))},
|
||||
kAppendEnd,
|
||||
"type error in branch[0] (expected i32, got anyref)");
|
||||
|
||||
|
@ -193,7 +193,7 @@ struct ValueTypePair {
|
||||
{kAnyRefCode, kWasmAnyRef}, // --
|
||||
{kEqRefCode, kWasmEqRef}, // --
|
||||
{kI31RefCode, kWasmI31Ref}, // --
|
||||
{kDataRefCode, kWasmDataRef}, // --
|
||||
{kStructRefCode, kWasmStructRef}, // --
|
||||
{kArrayRefCode, kWasmArrayRef}, // --
|
||||
{kNoneCode, kWasmNullRef}, // --
|
||||
{kStringRefCode, kWasmStringRef}, // --
|
||||
|
@ -64,6 +64,7 @@ void DefineSignature(WasmModule* module,
|
||||
|
||||
TEST_F(WasmSubtypingTest, Subtyping) {
|
||||
FLAG_SCOPE(experimental_wasm_gc);
|
||||
FLAG_VALUE_SCOPE(wasm_gc_structref_as_dataref, false);
|
||||
v8::internal::AccountingAllocator allocator;
|
||||
WasmModule module1_(std::make_unique<Zone>(&allocator, ZONE_NAME));
|
||||
WasmModule module2_(std::make_unique<Zone>(&allocator, ZONE_NAME));
|
||||
@ -130,7 +131,7 @@ TEST_F(WasmSubtypingTest, Subtyping) {
|
||||
kWasmS128};
|
||||
constexpr ValueType ref_types[] = {
|
||||
kWasmFuncRef, kWasmEqRef, // --
|
||||
kWasmDataRef, kWasmArrayRef, // --
|
||||
kWasmStructRef, kWasmArrayRef, // --
|
||||
kWasmI31Ref, kWasmAnyRef, // --
|
||||
kWasmExternRef, kWasmNullExternRef, // --
|
||||
kWasmNullRef, kWasmNullFuncRef, // --
|
||||
@ -201,17 +202,15 @@ TEST_F(WasmSubtypingTest, Subtyping) {
|
||||
ref_type == kWasmStringViewWtf8 ||
|
||||
ref_type == kWasmStringViewWtf16;
|
||||
SCOPED_TRACE("ref_type: " + ref_type.name());
|
||||
// Concrete reference types, i31ref and dataref are subtypes of eqref,
|
||||
// externref/funcref/anyref/functions are not.
|
||||
// Concrete reference types, i31ref, structref and arrayref are subtypes
|
||||
// of eqref, externref/funcref/anyref/functions are not.
|
||||
SUBTYPE_IFF(ref_type, kWasmEqRef,
|
||||
ref_type != kWasmAnyRef && !is_any_func && !is_extern &&
|
||||
!is_string_view && ref_type != kWasmStringRef);
|
||||
// Struct/array types are subtypes of dataref.
|
||||
SUBTYPE_IFF(ref_type, kWasmDataRef,
|
||||
ref_type == kWasmDataRef || ref_type == kWasmArrayRef ||
|
||||
ref_type == kWasmNullRef || ref_type == ref(0) ||
|
||||
ref_type == ref(2) || ref_type == refNull(0) ||
|
||||
ref_type == refNull(2));
|
||||
// Struct types are subtypes of structref.
|
||||
SUBTYPE_IFF(ref_type, kWasmStructRef,
|
||||
ref_type == kWasmStructRef || ref_type == kWasmNullRef ||
|
||||
ref_type == ref(0) || ref_type == refNull(0));
|
||||
// Array types are subtypes of arrayref.
|
||||
SUBTYPE_IFF(ref_type, kWasmArrayRef,
|
||||
ref_type == kWasmArrayRef || ref_type == ref(2) ||
|
||||
@ -379,33 +378,32 @@ TEST_F(WasmSubtypingTest, Subtyping) {
|
||||
}
|
||||
|
||||
// Abstract types vs abstract types.
|
||||
UNION(kWasmEqRef, kWasmDataRef, kWasmEqRef);
|
||||
UNION(kWasmEqRef, kWasmStructRef, kWasmEqRef);
|
||||
UNION(kWasmEqRef, kWasmI31Ref, kWasmEqRef);
|
||||
UNION(kWasmEqRef, kWasmArrayRef, kWasmEqRef);
|
||||
UNION(kWasmEqRef, kWasmNullRef, kWasmEqRef);
|
||||
UNION(kWasmDataRef, kWasmI31Ref, kWasmEqRef);
|
||||
UNION(kWasmDataRef, kWasmArrayRef, kWasmDataRef);
|
||||
UNION(kWasmDataRef, kWasmNullRef, kWasmDataRef.AsNullable());
|
||||
UNION(kWasmStructRef, kWasmI31Ref, kWasmEqRef);
|
||||
UNION(kWasmStructRef, kWasmArrayRef, kWasmEqRef);
|
||||
UNION(kWasmStructRef, kWasmNullRef, kWasmStructRef.AsNullable());
|
||||
UNION(kWasmI31Ref.AsNonNull(), kWasmArrayRef.AsNonNull(),
|
||||
kWasmEqRef.AsNonNull());
|
||||
UNION(kWasmI31Ref, kWasmNullRef, kWasmI31Ref.AsNullable());
|
||||
UNION(kWasmArrayRef, kWasmNullRef, kWasmArrayRef.AsNullable());
|
||||
UNION(kWasmDataRef.AsNonNull(), kWasmI31Ref.AsNonNull(),
|
||||
UNION(kWasmStructRef.AsNonNull(), kWasmI31Ref.AsNonNull(),
|
||||
kWasmEqRef.AsNonNull());
|
||||
UNION(kWasmDataRef, kWasmArrayRef, kWasmDataRef);
|
||||
UNION(kWasmI31Ref.AsNonNull(), kWasmArrayRef, kWasmEqRef);
|
||||
UNION(kWasmAnyRef, kWasmNullRef, kWasmAnyRef);
|
||||
UNION(kWasmExternRef, kWasmNullExternRef, kWasmExternRef);
|
||||
UNION(kWasmFuncRef, kWasmNullFuncRef, kWasmFuncRef);
|
||||
|
||||
INTERSECTION(kWasmExternRef, kWasmEqRef, kWasmBottom);
|
||||
INTERSECTION(kWasmExternRef, kWasmDataRef, kWasmBottom);
|
||||
INTERSECTION(kWasmExternRef, kWasmStructRef, kWasmBottom);
|
||||
INTERSECTION(kWasmExternRef, kWasmI31Ref.AsNonNull(), kWasmBottom);
|
||||
INTERSECTION(kWasmExternRef, kWasmArrayRef, kWasmBottom);
|
||||
INTERSECTION(kWasmExternRef, kWasmNullRef, kWasmBottom);
|
||||
INTERSECTION(kWasmExternRef, kWasmFuncRef, kWasmBottom);
|
||||
INTERSECTION(kWasmNullExternRef, kWasmEqRef, kWasmBottom);
|
||||
INTERSECTION(kWasmNullExternRef, kWasmDataRef, kWasmBottom);
|
||||
INTERSECTION(kWasmNullExternRef, kWasmStructRef, kWasmBottom);
|
||||
INTERSECTION(kWasmNullExternRef, kWasmI31Ref, kWasmBottom);
|
||||
INTERSECTION(kWasmNullExternRef, kWasmArrayRef, kWasmBottom);
|
||||
INTERSECTION(kWasmNullExternRef, kWasmNullRef, kWasmBottom);
|
||||
@ -413,13 +411,13 @@ TEST_F(WasmSubtypingTest, Subtyping) {
|
||||
INTERSECTION(kWasmNullExternRef, kWasmExternRef.AsNonNull(), kWasmBottom);
|
||||
|
||||
INTERSECTION(kWasmFuncRef, kWasmEqRef, kWasmBottom);
|
||||
INTERSECTION(kWasmFuncRef, kWasmDataRef, kWasmBottom);
|
||||
INTERSECTION(kWasmFuncRef, kWasmStructRef, kWasmBottom);
|
||||
INTERSECTION(kWasmFuncRef, kWasmI31Ref.AsNonNull(), kWasmBottom);
|
||||
INTERSECTION(kWasmFuncRef, kWasmArrayRef, kWasmBottom);
|
||||
INTERSECTION(kWasmFuncRef, kWasmNullRef, kWasmBottom);
|
||||
INTERSECTION(kWasmFuncRef, kWasmNullExternRef, kWasmBottom);
|
||||
INTERSECTION(kWasmNullFuncRef, kWasmEqRef, kWasmBottom);
|
||||
INTERSECTION(kWasmNullFuncRef, kWasmDataRef, kWasmBottom);
|
||||
INTERSECTION(kWasmNullFuncRef, kWasmStructRef, kWasmBottom);
|
||||
INTERSECTION(kWasmNullFuncRef, kWasmI31Ref, kWasmBottom);
|
||||
INTERSECTION(kWasmNullFuncRef, kWasmArrayRef, kWasmBottom);
|
||||
INTERSECTION(kWasmNullFuncRef, kWasmNullRef, kWasmBottom);
|
||||
@ -427,14 +425,14 @@ TEST_F(WasmSubtypingTest, Subtyping) {
|
||||
INTERSECTION(kWasmNullFuncRef, kWasmFuncRef.AsNonNull(), kWasmBottom);
|
||||
INTERSECTION(kWasmNullFuncRef, kWasmNullExternRef, kWasmBottom);
|
||||
|
||||
INTERSECTION(kWasmEqRef, kWasmDataRef, kWasmDataRef);
|
||||
INTERSECTION(kWasmEqRef, kWasmStructRef, kWasmStructRef);
|
||||
INTERSECTION(kWasmEqRef, kWasmI31Ref, kWasmI31Ref);
|
||||
INTERSECTION(kWasmEqRef, kWasmArrayRef, kWasmArrayRef);
|
||||
INTERSECTION(kWasmEqRef, kWasmNullRef, kWasmNullRef);
|
||||
INTERSECTION(kWasmEqRef, kWasmFuncRef, kWasmBottom);
|
||||
INTERSECTION(kWasmDataRef, kWasmI31Ref, kWasmNullRef);
|
||||
INTERSECTION(kWasmDataRef, kWasmArrayRef, kWasmArrayRef);
|
||||
INTERSECTION(kWasmDataRef, kWasmNullRef, kWasmNullRef);
|
||||
INTERSECTION(kWasmStructRef, kWasmI31Ref, kWasmNullRef);
|
||||
INTERSECTION(kWasmStructRef, kWasmArrayRef, kWasmNullRef);
|
||||
INTERSECTION(kWasmStructRef, kWasmNullRef, kWasmNullRef);
|
||||
INTERSECTION(kWasmI31Ref, kWasmArrayRef, kWasmNullRef);
|
||||
INTERSECTION(kWasmI31Ref.AsNonNull(), kWasmNullRef, kWasmBottom);
|
||||
INTERSECTION(kWasmArrayRef.AsNonNull(), kWasmNullRef, kWasmBottom);
|
||||
@ -464,11 +462,11 @@ TEST_F(WasmSubtypingTest, Subtyping) {
|
||||
INTERSECTION(kWasmEqRef, array_type, array_type);
|
||||
INTERSECTION(kWasmEqRef, function_type, kWasmBottom);
|
||||
|
||||
UNION(kWasmDataRef, struct_type, kWasmDataRef);
|
||||
UNION(kWasmDataRef, array_type, kWasmDataRef);
|
||||
INTERSECTION(kWasmDataRef, struct_type, struct_type);
|
||||
INTERSECTION(kWasmDataRef, array_type, array_type);
|
||||
INTERSECTION(kWasmDataRef, function_type, kWasmBottom);
|
||||
UNION(kWasmStructRef, struct_type, kWasmStructRef);
|
||||
UNION(kWasmStructRef, array_type, kWasmEqRef);
|
||||
INTERSECTION(kWasmStructRef, struct_type, struct_type);
|
||||
INTERSECTION(kWasmStructRef, array_type, kWasmBottom);
|
||||
INTERSECTION(kWasmStructRef, function_type, kWasmBottom);
|
||||
|
||||
UNION(kWasmI31Ref, struct_type, kWasmEqRef);
|
||||
UNION(kWasmI31Ref, array_type, kWasmEqRef);
|
||||
@ -476,7 +474,7 @@ TEST_F(WasmSubtypingTest, Subtyping) {
|
||||
INTERSECTION(kWasmI31Ref, array_type, kWasmBottom);
|
||||
INTERSECTION(kWasmI31Ref, function_type, kWasmBottom);
|
||||
|
||||
UNION(kWasmArrayRef, struct_type, kWasmDataRef);
|
||||
UNION(kWasmArrayRef, struct_type, kWasmEqRef);
|
||||
UNION(kWasmArrayRef, array_type, kWasmArrayRef);
|
||||
INTERSECTION(kWasmArrayRef, struct_type, kWasmBottom);
|
||||
INTERSECTION(kWasmArrayRef, array_type, array_type);
|
||||
@ -490,7 +488,7 @@ TEST_F(WasmSubtypingTest, Subtyping) {
|
||||
INTERSECTION(kWasmNullRef, function_type, kWasmBottom);
|
||||
|
||||
// Indexed types of different kinds.
|
||||
UNION(struct_type, array_type, kWasmDataRef.AsNonNull());
|
||||
UNION(struct_type, array_type, kWasmEqRef.AsNonNull());
|
||||
INTERSECTION(struct_type, array_type, kWasmBottom);
|
||||
INTERSECTION(struct_type, function_type, kWasmBottom);
|
||||
INTERSECTION(array_type, function_type, kWasmBottom);
|
||||
@ -498,8 +496,9 @@ TEST_F(WasmSubtypingTest, Subtyping) {
|
||||
// Nullable vs. non-nullable.
|
||||
UNION(struct_type, struct_type.AsNullable(), struct_type.AsNullable());
|
||||
INTERSECTION(struct_type, struct_type.AsNullable(), struct_type);
|
||||
UNION(kWasmDataRef, kWasmDataRef.AsNullable(), kWasmDataRef.AsNullable());
|
||||
INTERSECTION(kWasmDataRef, kWasmDataRef.AsNullable(), kWasmDataRef);
|
||||
UNION(kWasmStructRef, kWasmStructRef.AsNullable(),
|
||||
kWasmStructRef.AsNullable());
|
||||
INTERSECTION(kWasmStructRef, kWasmStructRef.AsNullable(), kWasmStructRef);
|
||||
|
||||
// Concrete types of the same kind.
|
||||
// Subtyping relation.
|
||||
@ -512,7 +511,7 @@ TEST_F(WasmSubtypingTest, Subtyping) {
|
||||
// No common ancestor.
|
||||
UNION(ref(6), refNull(2), kWasmArrayRef.AsNullable());
|
||||
INTERSECTION(ref(6), refNull(2), kWasmBottom);
|
||||
UNION(ref(0), ref(17), kWasmDataRef.AsNonNull());
|
||||
UNION(ref(0), ref(17), kWasmStructRef.AsNonNull());
|
||||
INTERSECTION(ref(0), ref(17), kWasmBottom);
|
||||
UNION(ref(10), refNull(11), kWasmFuncRef);
|
||||
INTERSECTION(ref(10), refNull(11), kWasmBottom);
|
||||
|
Loading…
Reference in New Issue
Block a user