Skip to content

Commit 6eaeccf

Browse files
alexmarkovCommit Queue
authored andcommitted
[vm] Handle null field values in record type testing stubs
TEST=vm/cc/TTS_RecordSubtypeRangeCheck Issue: #60419 Change-Id: Ibe85d1da750e0c8feb82415df36990927a6413e2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/419483 Reviewed-by: Tess Strickland <[email protected]> Commit-Queue: Alexander Markov <[email protected]>
1 parent 68fd76f commit 6eaeccf

File tree

2 files changed

+33
-4
lines changed

2 files changed

+33
-4
lines changed

runtime/vm/type_testing_stubs.cc

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -735,11 +735,17 @@ void TypeTestingStubGenerator::BuildOptimizedRecordSubtypeRangeCheck(
735735

736736
field_type_class = field_type.type_class();
737737
ASSERT(!field_type_class.IsNull());
738+
const bool null_is_assignable = Instance::NullIsAssignableTo(field_type);
738739

739-
const CidRangeVector& ranges = hi->SubtypeRangesForClass(
740-
field_type_class,
741-
/*include_abstract=*/false,
742-
/*exclude_null=*/!Instance::NullIsAssignableTo(field_type));
740+
if (null_is_assignable) {
741+
__ CompareObject(TTSInternalRegs::kScratchReg, Object::null_object());
742+
__ BranchIf(EQUAL, &next);
743+
}
744+
745+
const CidRangeVector& ranges =
746+
hi->SubtypeRangesForClass(field_type_class,
747+
/*include_abstract=*/false,
748+
/*exclude_null=*/!null_is_assignable);
743749

744750
const bool smi_is_ok = smi_type.IsSubtypeOf(field_type, Heap::kNew);
745751
__ BranchIfSmi(TTSInternalRegs::kScratchReg,

runtime/vm/type_testing_stubs_test.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,6 +1239,8 @@ const char* kRecordSubtypeRangeCheckScript =
12391239
getRecordType2() => getType<(A, int, String)>();
12401240
@pragma("vm:entry-point", "call")
12411241
getRecordType3() => getType<(int, D)>();
1242+
@pragma("vm:entry-point", "call")
1243+
getRecordType4() => getType<(int?, A?)>();
12421244
12431245
@pragma("vm:entry-point", "call")
12441246
createObj1() => (1, B());
@@ -1256,6 +1258,10 @@ const char* kRecordSubtypeRangeCheckScript =
12561258
createObj7() => (3, D<int>());
12571259
@pragma("vm:entry-point", "call")
12581260
createObj8() => (D<int>(), 3);
1261+
@pragma("vm:entry-point", "call")
1262+
createObj9() => (1, null);
1263+
@pragma("vm:entry-point", "call")
1264+
createObj10() => (null, null);
12591265
)";
12601266

12611267
ISOLATE_UNIT_TEST_CASE(TTS_RecordSubtypeRangeCheck) {
@@ -1268,6 +1274,8 @@ ISOLATE_UNIT_TEST_CASE(TTS_RecordSubtypeRangeCheck) {
12681274
Object::Handle(Invoke(root_library, "getRecordType2")));
12691275
const auto& type3 = AbstractType::Cast(
12701276
Object::Handle(Invoke(root_library, "getRecordType3")));
1277+
const auto& type4 = AbstractType::Cast(
1278+
Object::Handle(Invoke(root_library, "getRecordType4")));
12711279

12721280
const auto& obj1 = Object::Handle(Invoke(root_library, "createObj1"));
12731281
const auto& obj2 = Object::Handle(Invoke(root_library, "createObj2"));
@@ -1277,17 +1285,23 @@ ISOLATE_UNIT_TEST_CASE(TTS_RecordSubtypeRangeCheck) {
12771285
const auto& obj6 = Object::Handle(Invoke(root_library, "createObj6"));
12781286
const auto& obj7 = Object::Handle(Invoke(root_library, "createObj7"));
12791287
const auto& obj8 = Object::Handle(Invoke(root_library, "createObj8"));
1288+
const auto& obj9 = Object::Handle(Invoke(root_library, "createObj9"));
1289+
const auto& obj10 = Object::Handle(Invoke(root_library, "createObj10"));
12801290

12811291
const auto& tav_null = TypeArguments::Handle(TypeArguments::null());
12821292

12831293
// (1, B()) as (int, A)
12841294
// (1, 'bye') as (int, A)
12851295
// (1, foo: B()) as (int, A)
12861296
// (1, B(), 2) as (int, A)
1297+
// (1, null) as (int, A)
1298+
// (null, null) as (int, A)
12871299
RunTTSTest(type1, {obj1, tav_null, tav_null});
12881300
RunTTSTest(type1, Failure({obj2, tav_null, tav_null}));
12891301
RunTTSTest(type1, Failure({obj3, tav_null, tav_null}));
12901302
RunTTSTest(type1, Failure({obj4, tav_null, tav_null}));
1303+
RunTTSTest(type1, Failure({obj9, tav_null, tav_null}));
1304+
RunTTSTest(type1, Failure({obj10, tav_null, tav_null}));
12911305

12921306
// (C(), 2, 'hi') as (A, int, String)
12931307
// (D(), 2, 'hi') as (A, int, String)
@@ -1298,6 +1312,15 @@ ISOLATE_UNIT_TEST_CASE(TTS_RecordSubtypeRangeCheck) {
12981312
// (D<int>(), 3) as (int, D)
12991313
RunTTSTest(type3, {obj7, tav_null, tav_null});
13001314
RunTTSTest(type3, Failure({obj8, tav_null, tav_null}));
1315+
1316+
// (1, B()) as (int?, A?)
1317+
// (1, 'bye') as (int?, A?)
1318+
// (1, null) as (int?, A?)
1319+
// (null, null) as (int?, A?)
1320+
RunTTSTest(type4, {obj1, tav_null, tav_null});
1321+
RunTTSTest(type4, Failure({obj2, tav_null, tav_null}));
1322+
RunTTSTest(type4, {obj9, tav_null, tav_null});
1323+
RunTTSTest(type4, {obj10, tav_null, tav_null});
13011324
}
13021325

13031326
ISOLATE_UNIT_TEST_CASE(TTS_Generic_Implements_Instantiated_Interface) {

0 commit comments

Comments
 (0)