Skip to content

Commit d34b082

Browse files
sstricklCommit Queue
authored andcommitted
[vm,dyn_modules] Handle hash-based SubtypeTestCaches in the interpreter.
To do this, factor out the main search loop from SubtypeTestCache::FindKeyOrUnused into a method suitable for calling from the interpreter. Then, the only work on the interpreter side is to calculate the initial index at which to start probing for entries. TEST=ci Change-Id: I620c3904458158519066074565218b6e4a77eea9 Cq-Include-Trybots: luci.dart.try:vm-linux-debug-x64-try,vm-aot-linux-debug-x64-try,vm-dyn-linux-debug-x64-try,vm-aot-dyn-linux-debug-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/444080 Reviewed-by: Alexander Markov <[email protected]> Commit-Queue: Tess Strickland <[email protected]>
1 parent ac36c62 commit d34b082

File tree

3 files changed

+251
-125
lines changed

3 files changed

+251
-125
lines changed

runtime/vm/interpreter.cc

Lines changed: 87 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,9 +1186,7 @@ bool Interpreter::AssertAssignable(Thread* thread,
11861186
ObjectPtr* args,
11871187
SubtypeTestCachePtr cache) {
11881188
ObjectPtr null_value = Object::null();
1189-
if ((cache != null_value) &&
1190-
(Smi::Value(cache->untag()->cache()->untag()->length()) <=
1191-
SubtypeTestCache::kMaxLinearCacheSize)) {
1189+
if (cache != null_value) {
11921190
InstancePtr instance = Instance::RawCast(args[0]);
11931191
AbstractTypePtr dst_type = AbstractType::RawCast(args[1]);
11941192
TypeArgumentsPtr instantiator_type_arguments =
@@ -1232,36 +1230,95 @@ bool Interpreter::AssertAssignable(Thread* thread,
12321230
}
12331231

12341232
ArrayPtr entries = cache->untag()->cache();
1235-
for (intptr_t i = 0; entries->untag()->element(i) != null_value;
1236-
i += SubtypeTestCache::kTestEntryLength) {
1237-
if ((entries->untag()->element(
1238-
i + SubtypeTestCache::kInstanceCidOrSignature) ==
1239-
instance_cid_or_function) &&
1240-
(entries->untag()->element(
1241-
i + SubtypeTestCache::kInstanceTypeArguments) ==
1242-
instance_type_arguments) &&
1243-
(entries->untag()->element(
1244-
i + SubtypeTestCache::kInstantiatorTypeArguments) ==
1245-
instantiator_type_arguments) &&
1246-
(entries->untag()->element(
1247-
i + SubtypeTestCache::kFunctionTypeArguments) ==
1248-
function_type_arguments) &&
1249-
(entries->untag()->element(
1250-
i + SubtypeTestCache::kInstanceParentFunctionTypeArguments) ==
1251-
parent_function_type_arguments) &&
1252-
(entries->untag()->element(
1253-
i + SubtypeTestCache::kInstanceDelayedFunctionTypeArguments) ==
1254-
delayed_function_type_arguments) &&
1255-
(entries->untag()->element(i + SubtypeTestCache::kDestinationType) ==
1256-
dst_type)) {
1257-
if (Bool::True().ptr() ==
1258-
entries->untag()->element(i + SubtypeTestCache::kTestResult)) {
1259-
return true;
1260-
} else {
1261-
break;
1233+
const intptr_t num_inputs = cache->untag()->num_inputs_;
1234+
// The search in a linear-based STC starts at 0.
1235+
intptr_t probe = 0;
1236+
if (SubtypeTestCache::IsHash(entries)) {
1237+
// Perform the same hash as SubtypeTestCache::FindKeyOrUnused.
1238+
//
1239+
// Control flows to AssertAssignableCallRuntime if any of the individual
1240+
// hashes are 0 (which denotes the hash is not yet computed).
1241+
if (cid == kClosureCid) {
1242+
auto sig = AbstractType::RawCast(instance_cid_or_function);
1243+
probe = RawSmiValue(sig->untag()->hash());
1244+
if (probe == 0) goto AssertAssignableCallRuntime;
1245+
} else {
1246+
probe = cid;
1247+
}
1248+
switch (num_inputs) {
1249+
case 7: {
1250+
intptr_t h = RawSmiValue(dst_type->untag()->hash());
1251+
if (h == 0) goto AssertAssignableCallRuntime;
1252+
probe = CombineHashes(probe, h);
12621253
}
1254+
FALL_THROUGH;
1255+
case 6: {
1256+
intptr_t h = TypeArguments::kAllDynamicHash;
1257+
if (delayed_function_type_arguments != null_value) {
1258+
h = RawSmiValue(delayed_function_type_arguments->untag()->hash());
1259+
if (h == 0) goto AssertAssignableCallRuntime;
1260+
}
1261+
probe = CombineHashes(probe, h);
1262+
}
1263+
FALL_THROUGH;
1264+
case 5: {
1265+
intptr_t h = TypeArguments::kAllDynamicHash;
1266+
if (parent_function_type_arguments != null_value) {
1267+
h = RawSmiValue(parent_function_type_arguments->untag()->hash());
1268+
if (h == 0) goto AssertAssignableCallRuntime;
1269+
}
1270+
probe = CombineHashes(probe, h);
1271+
}
1272+
FALL_THROUGH;
1273+
case 4: {
1274+
intptr_t h = TypeArguments::kAllDynamicHash;
1275+
if (function_type_arguments != null_value) {
1276+
h = RawSmiValue(function_type_arguments->untag()->hash());
1277+
if (h == 0) goto AssertAssignableCallRuntime;
1278+
}
1279+
probe = CombineHashes(probe, h);
1280+
}
1281+
FALL_THROUGH;
1282+
case 3: {
1283+
intptr_t h = TypeArguments::kAllDynamicHash;
1284+
if (instantiator_type_arguments != null_value) {
1285+
h = RawSmiValue(instantiator_type_arguments->untag()->hash());
1286+
if (h == 0) goto AssertAssignableCallRuntime;
1287+
}
1288+
probe = CombineHashes(probe, h);
1289+
}
1290+
FALL_THROUGH;
1291+
case 2: {
1292+
intptr_t h = TypeArguments::kAllDynamicHash;
1293+
if (instance_type_arguments != null_value) {
1294+
h = RawSmiValue(instance_type_arguments->untag()->hash());
1295+
if (h == 0) goto AssertAssignableCallRuntime;
1296+
}
1297+
probe = CombineHashes(probe, h);
1298+
}
1299+
FALL_THROUGH;
1300+
case 1:
1301+
// Already included in the hash.
1302+
break;
1303+
default:
1304+
UNREACHABLE();
12631305
}
1306+
probe = FinalizeHash(probe);
1307+
// The number of entries for a hash-based cache is a power of 2,
1308+
// so use it as a mask to get a valid entry index from the hash.
1309+
probe = probe & (SubtypeTestCache::NumEntries(entries) - 1);
1310+
}
1311+
BoolPtr test_result = nullptr;
1312+
auto loc = SubtypeTestCache::FindKeyOrUnusedFromProbe(
1313+
entries, num_inputs, probe, instance_cid_or_function, dst_type,
1314+
instance_type_arguments, instantiator_type_arguments,
1315+
function_type_arguments, parent_function_type_arguments,
1316+
delayed_function_type_arguments, &test_result);
1317+
if (loc.present && test_result == Bool::True().ptr()) {
1318+
return true;
12641319
}
1320+
// Either there is no matching entry or the matching entry had a false test
1321+
// result, so a runtime call is needed to generate an appropriate error.
12651322
}
12661323

12671324
AssertAssignableCallRuntime:

0 commit comments

Comments
 (0)