[vm] Reorder SubtypeTestCache inputs to improve non-dynamic cases.
In particular, avoid storing/comparing the destination type unless the
SubtypeTestCache was created for a dynamic AssertAssignable instruction.
TEST=vm/cc/STC_{Linear,Hash}Lookup, vm/cc/TTS
Bug: https://github.com/dart-lang/sdk/issues/48345
Change-Id: I279c69a668ce19785785cf71707acf951f2b2133
Cq-Include-Trybots: luci.dart.try:vm-aot-linux-debug-simriscv64-try,vm-aot-linux-debug-x64-try,vm-aot-linux-release-x64-try,vm-aot-linux-product-x64-try,vm-aot-linux-release-simarm64-try,vm-aot-linux-release-simarm_x64-try,vm-aot-linux-debug-x64c-try,vm-aot-tsan-linux-release-x64-try,vm-aot-mac-release-arm64-try,vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-aot-dwarf-linux-product-x64-try,vm-linux-release-ia32-try,vm-linux-debug-x64c-try,vm-linux-debug-x64-try,vm-linux-debug-simriscv64-try,vm-linux-release-simarm64-try,vm-linux-release-simarm-try,vm-mac-release-arm64-try,vm-mac-release-x64-try,vm-tsan-linux-release-x64-try,vm-reload-rollback-linux-release-x64-try,vm-reload-linux-release-x64-try,vm-ffi-qemu-linux-release-arm-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/310340
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
diff --git a/runtime/vm/app_snapshot.cc b/runtime/vm/app_snapshot.cc
index 335e3df..111fadd 100644
--- a/runtime/vm/app_snapshot.cc
+++ b/runtime/vm/app_snapshot.cc
@@ -3560,6 +3560,7 @@
AutoTraceObject(cache);
WriteField(cache, cache_);
s->Write<uint32_t>(cache->untag()->num_inputs_);
+ s->Write<uint32_t>(cache->untag()->num_occupied_);
}
}
@@ -3588,6 +3589,7 @@
SubtypeTestCache::InstanceSize());
cache->untag()->cache_ = static_cast<ArrayPtr>(d.ReadRef());
cache->untag()->num_inputs_ = d.Read<uint32_t>();
+ cache->untag()->num_occupied_ = d.Read<uint32_t>();
}
}
};
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index eb777bd..080f034 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -2329,12 +2329,9 @@
__ Comment("FunctionTypeTest");
__ BranchIfSmi(TypeTestABI::kInstanceReg, is_not_instance_lbl);
- // Load the type into the right register for the subtype test cache check.
- __ LoadUniqueObject(TypeTestABI::kDstTypeReg, type);
// Uninstantiated type class is known at compile time, but the type
// arguments are determined at runtime by the instantiator(s).
-
- return GenerateCallSubtypeTestStub(TypeTestStubKind::kTestTypeSevenArgs,
+ return GenerateCallSubtypeTestStub(TypeTestStubKind::kTestTypeSixArgs,
is_instance_lbl, is_not_instance_lbl);
}
@@ -2407,14 +2404,14 @@
FlowGraphCompiler::GetTypeTestStubKindForTypeParameter(
const TypeParameter& type_param) {
// If it's guaranteed, by type-parameter bound, that the type parameter will
- // never have a value of a function type, then we can safely do a 5-type
- // test instead of a 7-type test.
+ // never have a value of a function type, then we can safely do a 4-type
+ // test instead of a 6-type test.
AbstractType& bound = AbstractType::Handle(zone(), type_param.bound());
bound = bound.UnwrapFutureOr();
return !bound.IsTopTypeForSubtyping() && !bound.IsObjectType() &&
!bound.IsDartFunctionType() && bound.IsType()
- ? TypeTestStubKind::kTestTypeFiveArgs
- : TypeTestStubKind::kTestTypeSevenArgs;
+ ? TypeTestStubKind::kTestTypeFourArgs
+ : TypeTestStubKind::kTestTypeSixArgs;
}
// Generates quick and subtype cache tests when only the instance need be
@@ -2533,10 +2530,8 @@
}
}
- // Load the type into the right register for the subtype test cache check.
- __ LoadUniqueObject(TypeTestABI::kDstTypeReg, type);
// Regular subtype test cache involving instance's type arguments.
- return GenerateCallSubtypeTestStub(TypeTestStubKind::kTestTypeThreeArgs,
+ return GenerateCallSubtypeTestStub(TypeTestStubKind::kTestTypeTwoArgs,
is_instance_lbl, is_not_instance_lbl);
}
@@ -2664,8 +2659,6 @@
// Smi can be handled by type test cache.
__ Bind(¬_smi);
- // Load the type into the right register for the subtype test cache check.
- __ LoadUniqueObject(TypeTestABI::kDstTypeReg, type);
const auto test_kind = GetTypeTestStubKindForTypeParameter(type_param);
return GenerateCallSubtypeTestStub(test_kind, is_instance_lbl,
is_not_instance_lbl);
@@ -2676,11 +2669,9 @@
if (!type.IsFutureOrType()) {
__ BranchIfSmi(TypeTestABI::kInstanceReg, is_not_instance_lbl);
}
- // Load the type into the right register for the subtype test cache check.
- __ LoadUniqueObject(TypeTestABI::kDstTypeReg, type);
// Uninstantiated type class is known at compile time, but the type
// arguments are determined at runtime by the instantiator(s).
- return GenerateCallSubtypeTestStub(TypeTestStubKind::kTestTypeFiveArgs,
+ return GenerateCallSubtypeTestStub(TypeTestStubKind::kTestTypeFourArgs,
is_instance_lbl, is_not_instance_lbl);
}
return SubtypeTestCache::null();
@@ -2752,11 +2743,10 @@
#if !defined(TARGET_ARCH_IA32)
// Expected inputs (from TypeTestABI):
// - kInstanceReg: instance (preserved).
-// - kDstTypeReg: destination type (for test_kind != kTestTypeOneArg).
// - kInstantiatorTypeArgumentsReg: instantiator type arguments
-// (for test_kind == kTestTypeFiveArg or test_kind == kTestTypeSevenArg).
+// (for test_kind == kTestTypeFourArg or test_kind == kTestTypeSixArg).
// - kFunctionTypeArgumentsReg: function type arguments
-// (for test_kind == kTestTypeFiveArg or test_kind == kTestTypeSevenArg).
+// (for test_kind == kTestTypeFourArg or test_kind == kTestTypeSixArg).
//
// See the arch-specific GenerateSubtypeNTestCacheStub method to see which
// registers may need saving across this call.
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index f52116f..c04c8a2 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -1024,8 +1024,9 @@
enum class TypeTestStubKind {
kTestTypeOneArg = 1,
- kTestTypeThreeArgs = 3,
- kTestTypeFiveArgs = 5,
+ kTestTypeTwoArgs = 2,
+ kTestTypeFourArgs = 4,
+ kTestTypeSixArgs = 6,
kTestTypeSevenArgs = 7,
};
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index 8bdde80..2d2d22c 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -188,11 +188,11 @@
// Input registers (from TypeTestABI):
// - kInstanceReg: instance.
-// - kDstTypeReg: destination type (for test_kind != kTestTypeOneArg).
+// - kDstTypeReg: destination type (for test_kind == kTestTypeSevenArg).
// - kInstantiatorTypeArgumentsReg: instantiator type arguments
-// (for test_kind == kTestTypeFiveArg or test_kind == kTestTypeSevenArg).
+// (for test_kind == kTestTypeFourArg, kTestTypeSixArg, or kTestTypeSevenArg).
// - kFunctionTypeArgumentsReg: function type arguments
-// (for test_kind == kTestTypeFiveArg or test_kind == kTestTypeSevenArg).
+// (for test_kind == kTestTypeFourArg, kTestTypeSixArg, or kTestTypeSevenArg).
//
// Only preserves kInstanceReg from TypeTestABI, all other TypeTestABI
// registers may be used and thus must be saved by the caller.
@@ -200,15 +200,6 @@
TypeTestStubKind test_kind,
compiler::Label* is_instance_lbl,
compiler::Label* is_not_instance_lbl) {
- // Used for registers that may not have GC-safe values to push. Pushes
- // the null object if the condition is not met.
- auto conditional_push = [&](Register reg, bool condition) {
- if (condition) {
- __ pushl(reg);
- } else {
- __ PushObject(Object::null_object());
- }
- };
const intptr_t num_inputs = UsedInputsForTTSKind(test_kind);
const SubtypeTestCache& type_test_cache =
SubtypeTestCache::ZoneHandle(zone(), SubtypeTestCache::New(num_inputs));
@@ -217,9 +208,23 @@
__ LoadObject(TypeTestABI::kSubtypeTestCacheReg, type_test_cache);
__ pushl(TypeTestABI::kSubtypeTestCacheReg);
__ pushl(TypeTestABI::kInstanceReg);
- conditional_push(TypeTestABI::kDstTypeReg, num_inputs >= 3);
- conditional_push(TypeTestABI::kInstantiatorTypeArgumentsReg, num_inputs >= 4);
- conditional_push(TypeTestABI::kFunctionTypeArgumentsReg, num_inputs >= 5);
+ // Registers for unused inputs may not have GC-safe values to push, so push
+ // the null object if the input is unused instead.
+ if (num_inputs >= 7) {
+ __ pushl(TypeTestABI::kDstTypeReg);
+ } else {
+ __ PushObject(Object::null_object());
+ }
+ if (num_inputs >= 3) {
+ __ pushl(TypeTestABI::kInstantiatorTypeArgumentsReg);
+ } else {
+ __ PushObject(Object::null_object());
+ }
+ if (num_inputs >= 4) {
+ __ pushl(TypeTestABI::kFunctionTypeArgumentsReg);
+ } else {
+ __ PushObject(Object::null_object());
+ }
__ Call(stub_entry);
// Restore all but kSubtypeTestCacheReg (since it is the same as
// kSubtypeTestCacheResultReg). Since the generated code is documented as
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index c3ac863..966035a 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -293,12 +293,16 @@
return dart::StubCode::AllocateArray();
}
-const Code& StubCodeSubtype3TestCache() {
- return dart::StubCode::Subtype3TestCache();
+const Code& StubCodeSubtype2TestCache() {
+ return dart::StubCode::Subtype2TestCache();
}
-const Code& StubCodeSubtype5TestCache() {
- return dart::StubCode::Subtype5TestCache();
+const Code& StubCodeSubtype4TestCache() {
+ return dart::StubCode::Subtype4TestCache();
+}
+
+const Code& StubCodeSubtype6TestCache() {
+ return dart::StubCode::Subtype6TestCache();
}
const Code& StubCodeSubtype7TestCache() {
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index f721041..09ccdfb 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -215,8 +215,9 @@
#endif
const Code& StubCodeAllocateArray();
-const Code& StubCodeSubtype3TestCache();
-const Code& StubCodeSubtype5TestCache();
+const Code& StubCodeSubtype2TestCache();
+const Code& StubCodeSubtype4TestCache();
+const Code& StubCodeSubtype6TestCache();
const Code& StubCodeSubtype7TestCache();
class RuntimeEntry : public ValueObject {
@@ -1433,7 +1434,6 @@
static word cache_offset();
static word num_inputs_offset();
- static const word kHeaderSize;
static const word kMaxInputs;
static const word kTestEntryLength;
static const word kInstanceCidOrSignature;
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index 73a212d..be7d4c9 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -96,22 +96,20 @@
OneByteString_kMaxNewSpaceElements = 0x3fff4;
static constexpr dart::compiler::target::word
TwoByteString_kMaxNewSpaceElements = 0x1fffa;
-static constexpr dart::compiler::target::word SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kDestinationType = 0x1;
+ SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word SubtypeTestCache_kMaxInputs = 0x7;
@@ -703,7 +701,7 @@
static constexpr dart::compiler::target::word SuspendState_HeaderSize = 0x1c;
static constexpr dart::compiler::target::word String_InstanceSize = 0xc;
static constexpr dart::compiler::target::word SubtypeTestCache_InstanceSize =
- 0xc;
+ 0x10;
static constexpr dart::compiler::target::word LoadingUnit_InstanceSize = 0x14;
static constexpr dart::compiler::target::word
TransferableTypedData_InstanceSize = 0x4;
@@ -808,22 +806,20 @@
OneByteString_kMaxNewSpaceElements = 0x3fff0;
static constexpr dart::compiler::target::word
TwoByteString_kMaxNewSpaceElements = 0x1fff8;
-static constexpr dart::compiler::target::word SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kDestinationType = 0x1;
+ SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word SubtypeTestCache_kMaxInputs = 0x7;
@@ -1522,22 +1518,20 @@
OneByteString_kMaxNewSpaceElements = 0x3fff4;
static constexpr dart::compiler::target::word
TwoByteString_kMaxNewSpaceElements = 0x1fffa;
-static constexpr dart::compiler::target::word SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kDestinationType = 0x1;
+ SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word SubtypeTestCache_kMaxInputs = 0x7;
@@ -2128,7 +2122,7 @@
static constexpr dart::compiler::target::word SuspendState_HeaderSize = 0x1c;
static constexpr dart::compiler::target::word String_InstanceSize = 0xc;
static constexpr dart::compiler::target::word SubtypeTestCache_InstanceSize =
- 0xc;
+ 0x10;
static constexpr dart::compiler::target::word LoadingUnit_InstanceSize = 0x14;
static constexpr dart::compiler::target::word
TransferableTypedData_InstanceSize = 0x4;
@@ -2233,22 +2227,20 @@
OneByteString_kMaxNewSpaceElements = 0x3fff0;
static constexpr dart::compiler::target::word
TwoByteString_kMaxNewSpaceElements = 0x1fff8;
-static constexpr dart::compiler::target::word SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kDestinationType = 0x1;
+ SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word SubtypeTestCache_kMaxInputs = 0x7;
@@ -2950,22 +2942,20 @@
OneByteString_kMaxNewSpaceElements = 0x3fff0;
static constexpr dart::compiler::target::word
TwoByteString_kMaxNewSpaceElements = 0x1fff8;
-static constexpr dart::compiler::target::word SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kDestinationType = 0x1;
+ SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word SubtypeTestCache_kMaxInputs = 0x7;
@@ -3664,22 +3654,20 @@
OneByteString_kMaxNewSpaceElements = 0x3fff0;
static constexpr dart::compiler::target::word
TwoByteString_kMaxNewSpaceElements = 0x1fff8;
-static constexpr dart::compiler::target::word SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kDestinationType = 0x1;
+ SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word SubtypeTestCache_kMaxInputs = 0x7;
@@ -4379,22 +4367,20 @@
OneByteString_kMaxNewSpaceElements = 0x3fff4;
static constexpr dart::compiler::target::word
TwoByteString_kMaxNewSpaceElements = 0x1fffa;
-static constexpr dart::compiler::target::word SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kDestinationType = 0x1;
+ SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word SubtypeTestCache_kMaxInputs = 0x7;
@@ -4987,7 +4973,7 @@
static constexpr dart::compiler::target::word SuspendState_HeaderSize = 0x1c;
static constexpr dart::compiler::target::word String_InstanceSize = 0xc;
static constexpr dart::compiler::target::word SubtypeTestCache_InstanceSize =
- 0xc;
+ 0x10;
static constexpr dart::compiler::target::word LoadingUnit_InstanceSize = 0x14;
static constexpr dart::compiler::target::word
TransferableTypedData_InstanceSize = 0x4;
@@ -5092,22 +5078,20 @@
OneByteString_kMaxNewSpaceElements = 0x3fff0;
static constexpr dart::compiler::target::word
TwoByteString_kMaxNewSpaceElements = 0x1fff8;
-static constexpr dart::compiler::target::word SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kDestinationType = 0x1;
+ SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word SubtypeTestCache_kMaxInputs = 0x7;
@@ -5806,22 +5790,20 @@
OneByteString_kMaxNewSpaceElements = 0x3fff4;
static constexpr dart::compiler::target::word
TwoByteString_kMaxNewSpaceElements = 0x1fffa;
-static constexpr dart::compiler::target::word SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kDestinationType = 0x1;
+ SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word SubtypeTestCache_kMaxInputs = 0x7;
@@ -6408,7 +6390,7 @@
static constexpr dart::compiler::target::word SuspendState_HeaderSize = 0x1c;
static constexpr dart::compiler::target::word String_InstanceSize = 0xc;
static constexpr dart::compiler::target::word SubtypeTestCache_InstanceSize =
- 0xc;
+ 0x10;
static constexpr dart::compiler::target::word LoadingUnit_InstanceSize = 0x14;
static constexpr dart::compiler::target::word
TransferableTypedData_InstanceSize = 0x4;
@@ -6510,22 +6492,20 @@
OneByteString_kMaxNewSpaceElements = 0x3fff0;
static constexpr dart::compiler::target::word
TwoByteString_kMaxNewSpaceElements = 0x1fff8;
-static constexpr dart::compiler::target::word SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kDestinationType = 0x1;
+ SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word SubtypeTestCache_kMaxInputs = 0x7;
@@ -7216,22 +7196,20 @@
OneByteString_kMaxNewSpaceElements = 0x3fff4;
static constexpr dart::compiler::target::word
TwoByteString_kMaxNewSpaceElements = 0x1fffa;
-static constexpr dart::compiler::target::word SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kDestinationType = 0x1;
+ SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word SubtypeTestCache_kMaxInputs = 0x7;
@@ -7817,7 +7795,7 @@
static constexpr dart::compiler::target::word SuspendState_HeaderSize = 0x1c;
static constexpr dart::compiler::target::word String_InstanceSize = 0xc;
static constexpr dart::compiler::target::word SubtypeTestCache_InstanceSize =
- 0xc;
+ 0x10;
static constexpr dart::compiler::target::word LoadingUnit_InstanceSize = 0x14;
static constexpr dart::compiler::target::word
TransferableTypedData_InstanceSize = 0x4;
@@ -7919,22 +7897,20 @@
OneByteString_kMaxNewSpaceElements = 0x3fff0;
static constexpr dart::compiler::target::word
TwoByteString_kMaxNewSpaceElements = 0x1fff8;
-static constexpr dart::compiler::target::word SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kDestinationType = 0x1;
+ SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word SubtypeTestCache_kMaxInputs = 0x7;
@@ -8628,22 +8604,20 @@
OneByteString_kMaxNewSpaceElements = 0x3fff0;
static constexpr dart::compiler::target::word
TwoByteString_kMaxNewSpaceElements = 0x1fff8;
-static constexpr dart::compiler::target::word SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kDestinationType = 0x1;
+ SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word SubtypeTestCache_kMaxInputs = 0x7;
@@ -9334,22 +9308,20 @@
OneByteString_kMaxNewSpaceElements = 0x3fff0;
static constexpr dart::compiler::target::word
TwoByteString_kMaxNewSpaceElements = 0x1fff8;
-static constexpr dart::compiler::target::word SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kDestinationType = 0x1;
+ SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word SubtypeTestCache_kMaxInputs = 0x7;
@@ -10041,22 +10013,20 @@
OneByteString_kMaxNewSpaceElements = 0x3fff4;
static constexpr dart::compiler::target::word
TwoByteString_kMaxNewSpaceElements = 0x1fffa;
-static constexpr dart::compiler::target::word SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kDestinationType = 0x1;
+ SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word SubtypeTestCache_kMaxInputs = 0x7;
@@ -10644,7 +10614,7 @@
static constexpr dart::compiler::target::word SuspendState_HeaderSize = 0x1c;
static constexpr dart::compiler::target::word String_InstanceSize = 0xc;
static constexpr dart::compiler::target::word SubtypeTestCache_InstanceSize =
- 0xc;
+ 0x10;
static constexpr dart::compiler::target::word LoadingUnit_InstanceSize = 0x14;
static constexpr dart::compiler::target::word
TransferableTypedData_InstanceSize = 0x4;
@@ -10746,22 +10716,20 @@
OneByteString_kMaxNewSpaceElements = 0x3fff0;
static constexpr dart::compiler::target::word
TwoByteString_kMaxNewSpaceElements = 0x1fff8;
-static constexpr dart::compiler::target::word SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kDestinationType = 0x1;
+ SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word SubtypeTestCache_kMaxInputs = 0x7;
@@ -11463,22 +11431,20 @@
AOT_OneByteString_kMaxNewSpaceElements = 0x3fff4;
static constexpr dart::compiler::target::word
AOT_TwoByteString_kMaxNewSpaceElements = 0x1fffa;
-static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ AOT_SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kDestinationType = 0x1;
+ AOT_SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ AOT_SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kMaxInputs =
@@ -12140,7 +12106,7 @@
0x18;
static constexpr dart::compiler::target::word AOT_String_InstanceSize = 0xc;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_InstanceSize = 0xc;
+ AOT_SubtypeTestCache_InstanceSize = 0x10;
static constexpr dart::compiler::target::word AOT_LoadingUnit_InstanceSize =
0x14;
static constexpr dart::compiler::target::word
@@ -12252,22 +12218,20 @@
AOT_OneByteString_kMaxNewSpaceElements = 0x3fff0;
static constexpr dart::compiler::target::word
AOT_TwoByteString_kMaxNewSpaceElements = 0x1fff8;
-static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ AOT_SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kDestinationType = 0x1;
+ AOT_SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ AOT_SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kMaxInputs =
@@ -13044,22 +13008,20 @@
AOT_OneByteString_kMaxNewSpaceElements = 0x3fff0;
static constexpr dart::compiler::target::word
AOT_TwoByteString_kMaxNewSpaceElements = 0x1fff8;
-static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ AOT_SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kDestinationType = 0x1;
+ AOT_SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ AOT_SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kMaxInputs =
@@ -13835,22 +13797,20 @@
AOT_OneByteString_kMaxNewSpaceElements = 0x3fff0;
static constexpr dart::compiler::target::word
AOT_TwoByteString_kMaxNewSpaceElements = 0x1fff8;
-static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ AOT_SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kDestinationType = 0x1;
+ AOT_SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ AOT_SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kMaxInputs =
@@ -14626,22 +14586,20 @@
AOT_OneByteString_kMaxNewSpaceElements = 0x3fff0;
static constexpr dart::compiler::target::word
AOT_TwoByteString_kMaxNewSpaceElements = 0x1fff8;
-static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ AOT_SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kDestinationType = 0x1;
+ AOT_SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ AOT_SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kMaxInputs =
@@ -15419,22 +15377,20 @@
AOT_OneByteString_kMaxNewSpaceElements = 0x3fff4;
static constexpr dart::compiler::target::word
AOT_TwoByteString_kMaxNewSpaceElements = 0x1fffa;
-static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ AOT_SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kDestinationType = 0x1;
+ AOT_SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ AOT_SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kMaxInputs =
@@ -16097,7 +16053,7 @@
0x18;
static constexpr dart::compiler::target::word AOT_String_InstanceSize = 0xc;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_InstanceSize = 0xc;
+ AOT_SubtypeTestCache_InstanceSize = 0x10;
static constexpr dart::compiler::target::word AOT_LoadingUnit_InstanceSize =
0x14;
static constexpr dart::compiler::target::word
@@ -16209,22 +16165,20 @@
AOT_OneByteString_kMaxNewSpaceElements = 0x3fff0;
static constexpr dart::compiler::target::word
AOT_TwoByteString_kMaxNewSpaceElements = 0x1fff8;
-static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ AOT_SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kDestinationType = 0x1;
+ AOT_SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ AOT_SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kMaxInputs =
@@ -16998,22 +16952,20 @@
AOT_OneByteString_kMaxNewSpaceElements = 0x3fff4;
static constexpr dart::compiler::target::word
AOT_TwoByteString_kMaxNewSpaceElements = 0x1fffa;
-static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ AOT_SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kDestinationType = 0x1;
+ AOT_SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ AOT_SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kMaxInputs =
@@ -17669,7 +17621,7 @@
0x18;
static constexpr dart::compiler::target::word AOT_String_InstanceSize = 0xc;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_InstanceSize = 0xc;
+ AOT_SubtypeTestCache_InstanceSize = 0x10;
static constexpr dart::compiler::target::word AOT_LoadingUnit_InstanceSize =
0x14;
static constexpr dart::compiler::target::word
@@ -17778,22 +17730,20 @@
AOT_OneByteString_kMaxNewSpaceElements = 0x3fff0;
static constexpr dart::compiler::target::word
AOT_TwoByteString_kMaxNewSpaceElements = 0x1fff8;
-static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ AOT_SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kDestinationType = 0x1;
+ AOT_SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ AOT_SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kMaxInputs =
@@ -18561,22 +18511,20 @@
AOT_OneByteString_kMaxNewSpaceElements = 0x3fff0;
static constexpr dart::compiler::target::word
AOT_TwoByteString_kMaxNewSpaceElements = 0x1fff8;
-static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ AOT_SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kDestinationType = 0x1;
+ AOT_SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ AOT_SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kMaxInputs =
@@ -19343,22 +19291,20 @@
AOT_OneByteString_kMaxNewSpaceElements = 0x3fff0;
static constexpr dart::compiler::target::word
AOT_TwoByteString_kMaxNewSpaceElements = 0x1fff8;
-static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ AOT_SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kDestinationType = 0x1;
+ AOT_SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ AOT_SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kMaxInputs =
@@ -20125,22 +20071,20 @@
AOT_OneByteString_kMaxNewSpaceElements = 0x3fff0;
static constexpr dart::compiler::target::word
AOT_TwoByteString_kMaxNewSpaceElements = 0x1fff8;
-static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ AOT_SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kDestinationType = 0x1;
+ AOT_SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ AOT_SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kMaxInputs =
@@ -20909,22 +20853,20 @@
AOT_OneByteString_kMaxNewSpaceElements = 0x3fff4;
static constexpr dart::compiler::target::word
AOT_TwoByteString_kMaxNewSpaceElements = 0x1fffa;
-static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ AOT_SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kDestinationType = 0x1;
+ AOT_SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ AOT_SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kMaxInputs =
@@ -21581,7 +21523,7 @@
0x18;
static constexpr dart::compiler::target::word AOT_String_InstanceSize = 0xc;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_InstanceSize = 0xc;
+ AOT_SubtypeTestCache_InstanceSize = 0x10;
static constexpr dart::compiler::target::word AOT_LoadingUnit_InstanceSize =
0x14;
static constexpr dart::compiler::target::word
@@ -21690,22 +21632,20 @@
AOT_OneByteString_kMaxNewSpaceElements = 0x3fff0;
static constexpr dart::compiler::target::word
AOT_TwoByteString_kMaxNewSpaceElements = 0x1fff8;
-static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kHeaderSize =
- 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kFunctionTypeArguments = 0x4;
+ AOT_SubtypeTestCache_kFunctionTypeArguments = 0x3;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kInstanceCidOrSignature = 0x0;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kDestinationType = 0x1;
+ AOT_SubtypeTestCache_kDestinationType = 0x6;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x6;
+ AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 0x5;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x5;
+ AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 0x4;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstanceTypeArguments = 0x2;
+ AOT_SubtypeTestCache_kInstanceTypeArguments = 0x1;
static constexpr dart::compiler::target::word
- AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x3;
+ AOT_SubtypeTestCache_kInstantiatorTypeArguments = 0x2;
static constexpr dart::compiler::target::word
AOT_SubtypeTestCache_kTestEntryLength = 0x8;
static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kMaxInputs =
diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h
index b2d58f0..2ac6d96 100644
--- a/runtime/vm/compiler/runtime_offsets_list.h
+++ b/runtime/vm/compiler/runtime_offsets_list.h
@@ -94,7 +94,6 @@
CONSTANT(String, kMaxElements) \
CONSTANT(OneByteString, kMaxNewSpaceElements) \
CONSTANT(TwoByteString, kMaxNewSpaceElements) \
- CONSTANT(SubtypeTestCache, kHeaderSize) \
CONSTANT(SubtypeTestCache, kFunctionTypeArguments) \
CONSTANT(SubtypeTestCache, kInstanceCidOrSignature) \
CONSTANT(SubtypeTestCache, kDestinationType) \
diff --git a/runtime/vm/compiler/stub_code_compiler.cc b/runtime/vm/compiler/stub_code_compiler.cc
index 2b8d1d3..495a676 100644
--- a/runtime/vm/compiler/stub_code_compiler.cc
+++ b/runtime/vm/compiler/stub_code_compiler.cc
@@ -1094,14 +1094,16 @@
__ BranchIf(EQUAL, &call_runtime, Assembler::kNearJump);
// Use the number of inputs used by the STC to determine which stub to call.
- Label call_3, call_5;
+ Label call_2, call_4, call_6;
__ Comment("Check number of STC inputs");
__ LoadFromSlot(TypeTestABI::kScratchReg, TypeTestABI::kSubtypeTestCacheReg,
Slot::SubtypeTestCache_num_inputs());
- __ CompareImmediate(TypeTestABI::kScratchReg, 3);
- __ BranchIf(EQUAL, &call_3, Assembler::kNearJump);
- __ CompareImmediate(TypeTestABI::kScratchReg, 5);
- __ BranchIf(EQUAL, &call_5, Assembler::kNearJump);
+ __ CompareImmediate(TypeTestABI::kScratchReg, 2);
+ __ BranchIf(EQUAL, &call_2, Assembler::kNearJump);
+ __ CompareImmediate(TypeTestABI::kScratchReg, 4);
+ __ BranchIf(EQUAL, &call_4, Assembler::kNearJump);
+ __ CompareImmediate(TypeTestABI::kScratchReg, 6);
+ __ BranchIf(EQUAL, &call_6, Assembler::kNearJump);
#if defined(DEBUG)
// Verify we have the all inputs case.
Label perform_check;
@@ -1122,20 +1124,30 @@
__ Jump(&call_runtime, Assembler::kNearJump);
}
- __ Bind(&call_5);
+ __ Bind(&call_6);
{
- __ Comment("Call 5 input STC check");
- __ Call(StubCodeSubtype5TestCache());
+ __ Comment("Call 6 input STC check");
+ __ Call(StubCodeSubtype6TestCache());
__ CompareObject(TypeTestABI::kSubtypeTestCacheResultReg,
CastHandle<Object>(TrueObject()));
__ BranchIf(EQUAL, &done); // Cache said: yes.
__ Jump(&call_runtime, Assembler::kNearJump);
}
- __ Bind(&call_3);
+ __ Bind(&call_4);
{
- __ Comment("Call 3 input STC check");
- __ Call(StubCodeSubtype3TestCache());
+ __ Comment("Call 4 input STC check");
+ __ Call(StubCodeSubtype4TestCache());
+ __ CompareObject(TypeTestABI::kSubtypeTestCacheResultReg,
+ CastHandle<Object>(TrueObject()));
+ __ BranchIf(EQUAL, &done); // Cache said: yes.
+ __ Jump(&call_runtime, Assembler::kNearJump);
+ }
+
+ __ Bind(&call_2);
+ {
+ __ Comment("Call 2 input STC check");
+ __ Call(StubCodeSubtype2TestCache());
__ CompareObject(TypeTestABI::kSubtypeTestCacheResultReg,
CastHandle<Object>(TrueObject()));
__ BranchIf(EQUAL, &done); // Cache said: yes.
@@ -2559,6 +2571,107 @@
}
#if !defined(TARGET_ARCH_IA32)
+static void GenerateSubtypeTestCacheLoop(Assembler* assembler,
+ int n,
+ Register null_reg,
+ Register cache_entry_reg,
+ Register instance_cid_or_sig_reg,
+ Register instance_type_args_reg,
+ Register parent_fun_type_args_reg,
+ Register delayed_type_args_reg,
+ Label* found,
+ Label* not_found,
+ Label* next_iteration) {
+ __ Comment("Loop");
+ // LoadAcquireCompressed assumes the loaded value is a heap object and
+ // extends it with the heap bits if compressed. However, the entry may be
+ // a Smi.
+ //
+ // Instead, just use LoadAcquire to load the lower bits when compressed and
+ // only compare the low bits of the loaded value using CompareObjectRegisters.
+ __ LoadAcquire(TypeTestABI::kScratchReg, cache_entry_reg,
+ target::kCompressedWordSize *
+ target::SubtypeTestCache::kInstanceCidOrSignature,
+ kObjectBytes);
+ __ CompareObjectRegisters(TypeTestABI::kScratchReg, null_reg);
+ __ BranchIf(EQUAL, not_found, Assembler::kNearJump);
+ __ CompareObjectRegisters(TypeTestABI::kScratchReg, instance_cid_or_sig_reg);
+ if (n == 1) {
+ __ BranchIf(EQUAL, found, Assembler::kNearJump);
+ return;
+ }
+
+ __ BranchIf(NOT_EQUAL, next_iteration, Assembler::kNearJump);
+ __ CompareWithMemoryValue(
+ instance_type_args_reg,
+ Address(cache_entry_reg,
+ target::kCompressedWordSize *
+ target::SubtypeTestCache::kInstanceTypeArguments),
+ kObjectBytes);
+ if (n == 2) {
+ __ BranchIf(EQUAL, found, Assembler::kNearJump);
+ return;
+ }
+
+ __ BranchIf(NOT_EQUAL, next_iteration, Assembler::kNearJump);
+ __ CompareWithMemoryValue(
+ TypeTestABI::kInstantiatorTypeArgumentsReg,
+ Address(cache_entry_reg,
+ target::kCompressedWordSize *
+ target::SubtypeTestCache::kInstantiatorTypeArguments),
+ kObjectBytes);
+ if (n == 3) {
+ __ BranchIf(EQUAL, found, Assembler::kNearJump);
+ return;
+ }
+
+ __ BranchIf(NOT_EQUAL, next_iteration, Assembler::kNearJump);
+ __ CompareWithMemoryValue(
+ TypeTestABI::kFunctionTypeArgumentsReg,
+ Address(cache_entry_reg,
+ target::kCompressedWordSize *
+ target::SubtypeTestCache::kFunctionTypeArguments),
+ kObjectBytes);
+ if (n == 4) {
+ __ BranchIf(EQUAL, found, Assembler::kNearJump);
+ return;
+ }
+
+ __ BranchIf(NOT_EQUAL, next_iteration, Assembler::kNearJump);
+ __ CompareWithMemoryValue(
+ parent_fun_type_args_reg,
+ Address(
+ cache_entry_reg,
+ target::kCompressedWordSize *
+ target::SubtypeTestCache::kInstanceParentFunctionTypeArguments),
+ kObjectBytes);
+ if (n == 5) {
+ __ BranchIf(EQUAL, found, Assembler::kNearJump);
+ return;
+ }
+
+ __ BranchIf(NOT_EQUAL, next_iteration, Assembler::kNearJump);
+ __ CompareWithMemoryValue(
+ delayed_type_args_reg,
+ Address(
+ cache_entry_reg,
+ target::kCompressedWordSize *
+ target::SubtypeTestCache::kInstanceDelayedFunctionTypeArguments),
+ kObjectBytes);
+ if (n == 6) {
+ __ BranchIf(EQUAL, found, Assembler::kNearJump);
+ return;
+ }
+
+ __ BranchIf(NOT_EQUAL, next_iteration, Assembler::kNearJump);
+ __ CompareWithMemoryValue(
+ TypeTestABI::kDstTypeReg,
+ Address(cache_entry_reg, target::kCompressedWordSize *
+ target::SubtypeTestCache::kDestinationType),
+ kObjectBytes);
+ __ BranchIf(EQUAL, found, Assembler::kNearJump);
+}
+
void StubCodeCompiler::GenerateSubtypeTestCacheSearch(
Assembler* assembler,
int n,
@@ -2579,15 +2692,17 @@
ASSERT(instance_cid_or_sig_reg != kNoRegister);
ASSERT(!input_regs.ContainsRegister(instance_cid_or_sig_reg));
input_regs.AddRegister(instance_cid_or_sig_reg);
- if (n >= 3) {
+ if (n >= 2) {
ASSERT(instance_type_args_reg != kNoRegister);
ASSERT(!input_regs.ContainsRegister(instance_type_args_reg));
input_regs.AddRegister(instance_type_args_reg);
}
- if (n >= 7) {
+ if (n >= 5) {
ASSERT(parent_fun_type_args_reg != kNoRegister);
ASSERT(!input_regs.ContainsRegister(parent_fun_type_args_reg));
input_regs.AddRegister(parent_fun_type_args_reg);
+ }
+ if (n >= 6) {
ASSERT(!input_regs.ContainsRegister(TypeTestABI::kInstanceReg));
ASSERT(delayed_type_args_reg != kNoRegister);
ASSERT(!input_regs.ContainsRegister(delayed_type_args_reg));
@@ -2595,11 +2710,21 @@
} else {
ASSERT(!input_regs.ContainsRegister(TypeTestABI::kInstanceReg));
}
+ // We can allow the use of the registers below only if we're not expecting
+ // them as an inspected input.
+ if (n >= 3) {
+ ASSERT(!input_regs.ContainsRegister(
+ TypeTestABI::kInstantiatorTypeArgumentsReg));
+ }
+ if (n >= 4) {
+ ASSERT(
+ !input_regs.ContainsRegister(TypeTestABI::kFunctionTypeArgumentsReg));
+ }
+ if (n >= 7) {
+ ASSERT(!input_regs.ContainsRegister(TypeTestABI::kDstTypeReg));
+ }
+ // We use this as a scratch, so it has to be distinct from the others.
ASSERT(!input_regs.ContainsRegister(TypeTestABI::kScratchReg));
- ASSERT(!input_regs.ContainsRegister(TypeTestABI::kDstTypeReg));
- ASSERT(
- !input_regs.ContainsRegister(TypeTestABI::kInstantiatorTypeArgumentsReg));
- ASSERT(!input_regs.ContainsRegister(TypeTestABI::kFunctionTypeArgumentsReg));
#endif
Label loop;
@@ -2617,15 +2742,24 @@
// TODO(sstrickl): Handle hash-based tables in the stub and load the first
// entry to check here instead of generating a false negative.
__ BranchIf(GREATER, not_found);
- __ AddImmediate(
- cache_entry_reg,
- target::Array::data_offset() - kHeapObjectTag +
- target::kCompressedWordSize * target::SubtypeTestCache::kHeaderSize);
+ __ AddImmediate(cache_entry_reg,
+ target::Array::data_offset() - kHeapObjectTag);
Label not_closure;
- if (n >= 5) {
+ if (n >= 4) {
__ LoadClassIdMayBeSmi(instance_cid_or_sig_reg, TypeTestABI::kInstanceReg);
} else {
+ // If the type is fully instantiated, then it can be determined at compile
+ // time whether Smi is a subtype of the type or not. Thus, this code should
+ // never be called with a Smi instance.
+#if defined(DEBUG)
+ // Double-check this in DEBUG mode, instead of getting a segfault.
+ Label not_smi;
+ __ BranchIfNotSmi(TypeTestABI::kInstanceReg, ¬_smi,
+ Assembler::kNearJump);
+ __ Breakpoint();
+ __ Bind(¬_smi);
+#endif
__ LoadClassId(instance_cid_or_sig_reg, TypeTestABI::kInstanceReg);
}
__ CompareImmediate(instance_cid_or_sig_reg, kClosureCid);
@@ -2640,22 +2774,25 @@
__ LoadCompressed(instance_cid_or_sig_reg,
FieldAddress(instance_cid_or_sig_reg,
target::Function::signature_offset()));
- if (n >= 3) {
+ if (n >= 2) {
__ LoadCompressed(
instance_type_args_reg,
FieldAddress(TypeTestABI::kInstanceReg,
target::Closure::instantiator_type_arguments_offset()));
- if (n >= 7) {
- __ LoadCompressed(
- parent_fun_type_args_reg,
- FieldAddress(TypeTestABI::kInstanceReg,
- target::Closure::function_type_arguments_offset()));
- __ LoadCompressed(
- delayed_type_args_reg,
- FieldAddress(TypeTestABI::kInstanceReg,
- target::Closure::delayed_type_arguments_offset()));
- }
}
+ if (n >= 5) {
+ __ LoadCompressed(
+ parent_fun_type_args_reg,
+ FieldAddress(TypeTestABI::kInstanceReg,
+ target::Closure::function_type_arguments_offset()));
+ }
+ if (n >= 6) {
+ __ LoadCompressed(
+ delayed_type_args_reg,
+ FieldAddress(TypeTestABI::kInstanceReg,
+ target::Closure::delayed_type_arguments_offset()));
+ }
+
__ Jump(&loop, Assembler::kNearJump);
}
@@ -2663,7 +2800,7 @@
{
__ Comment("Non-Closure");
__ Bind(¬_closure);
- if (n >= 3) {
+ if (n >= 2) {
Label has_no_type_arguments;
__ LoadClassById(TypeTestABI::kScratchReg, instance_cid_or_sig_reg);
__ MoveRegister(instance_type_args_reg, null_reg);
@@ -2679,92 +2816,22 @@
TypeTestABI::kScratchReg);
__ Bind(&has_no_type_arguments);
__ Comment("No type arguments");
-
- if (n >= 7) {
- __ MoveRegister(parent_fun_type_args_reg, null_reg);
- __ MoveRegister(delayed_type_args_reg, null_reg);
- }
}
__ SmiTag(instance_cid_or_sig_reg);
+ if (n >= 5) {
+ __ MoveRegister(parent_fun_type_args_reg, null_reg);
+ }
+ if (n >= 6) {
+ __ MoveRegister(delayed_type_args_reg, null_reg);
+ }
}
Label next_iteration, found;
__ Bind(&loop);
- __ Comment("Loop");
- // LoadAcquireCompressed assumes the loaded value is a heap object and
- // extends it with the heap bits if compressed. However, the entry may be
- // a Smi.
- //
- // Instead, just use LoadAcquire to load the lower bits when compressed and
- // only compare the low bits of the loaded value using CompareObjectRegisters.
- __ LoadAcquire(TypeTestABI::kScratchReg, cache_entry_reg,
- target::kCompressedWordSize *
- target::SubtypeTestCache::kInstanceCidOrSignature,
- kObjectBytes);
- __ CompareObjectRegisters(TypeTestABI::kScratchReg, null_reg);
- __ BranchIf(EQUAL, not_found, Assembler::kNearJump);
- __ CompareObjectRegisters(TypeTestABI::kScratchReg, instance_cid_or_sig_reg);
- if (n == 1) {
- __ BranchIf(EQUAL, &found, Assembler::kNearJump);
- } else {
- __ BranchIf(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
- __ CompareWithMemoryValue(
- TypeTestABI::kDstTypeReg,
- Address(cache_entry_reg,
- target::kCompressedWordSize *
- target::SubtypeTestCache::kDestinationType),
- kObjectBytes);
- __ BranchIf(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
- __ CompareWithMemoryValue(
- instance_type_args_reg,
- Address(cache_entry_reg,
- target::kCompressedWordSize *
- target::SubtypeTestCache::kInstanceTypeArguments),
- kObjectBytes);
- if (n == 3) {
- __ BranchIf(EQUAL, &found, Assembler::kNearJump);
- } else {
- __ BranchIf(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
- __ CompareWithMemoryValue(
- TypeTestABI::kInstantiatorTypeArgumentsReg,
- Address(cache_entry_reg,
- target::kCompressedWordSize *
- target::SubtypeTestCache::kInstantiatorTypeArguments),
- kObjectBytes);
- __ BranchIf(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
- __ CompareWithMemoryValue(
- TypeTestABI::kFunctionTypeArgumentsReg,
- Address(cache_entry_reg,
- target::kCompressedWordSize *
- target::SubtypeTestCache::kFunctionTypeArguments),
- kObjectBytes);
-
- if (n == 5) {
- __ BranchIf(EQUAL, &found, Assembler::kNearJump);
- } else {
- ASSERT(n == 7);
- __ BranchIf(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
-
- __ CompareWithMemoryValue(
- parent_fun_type_args_reg,
- Address(cache_entry_reg,
- target::kCompressedWordSize *
- target::SubtypeTestCache::
- kInstanceParentFunctionTypeArguments),
- kObjectBytes);
- __ BranchIf(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
- __ CompareWithMemoryValue(
- delayed_type_args_reg,
- Address(cache_entry_reg,
- target::kCompressedWordSize *
- target::SubtypeTestCache::
- kInstanceDelayedFunctionTypeArguments),
- kObjectBytes);
- __ BranchIf(EQUAL, &found, Assembler::kNearJump);
- }
- }
- }
-
+ GenerateSubtypeTestCacheLoop(assembler, n, null_reg, cache_entry_reg,
+ instance_cid_or_sig_reg, instance_type_args_reg,
+ parent_fun_type_args_reg, delayed_type_args_reg,
+ &found, not_found, &next_iteration);
__ Bind(&next_iteration);
__ Comment("Next iteration");
__ AddImmediate(
@@ -2776,6 +2843,31 @@
}
#endif
+// See comment on [GenerateSubtypeNTestCacheStub].
+void StubCodeCompiler::GenerateSubtype1TestCacheStub() {
+ GenerateSubtypeNTestCacheStub(assembler, 1);
+}
+
+// See comment on [GenerateSubtypeNTestCacheStub].
+void StubCodeCompiler::GenerateSubtype2TestCacheStub() {
+ GenerateSubtypeNTestCacheStub(assembler, 2);
+}
+
+// See comment on [GenerateSubtypeNTestCacheStub].
+void StubCodeCompiler::GenerateSubtype4TestCacheStub() {
+ GenerateSubtypeNTestCacheStub(assembler, 4);
+}
+
+// See comment on [GenerateSubtypeNTestCacheStub].
+void StubCodeCompiler::GenerateSubtype6TestCacheStub() {
+ GenerateSubtypeNTestCacheStub(assembler, 6);
+}
+
+// See comment on [GenerateSubtypeNTestCacheStub].
+void StubCodeCompiler::GenerateSubtype7TestCacheStub() {
+ GenerateSubtypeNTestCacheStub(assembler, 7);
+}
+
} // namespace compiler
} // namespace dart
diff --git a/runtime/vm/compiler/stub_code_compiler.h b/runtime/vm/compiler/stub_code_compiler.h
index 39a853e..c0e369d 100644
--- a/runtime/vm/compiler/stub_code_compiler.h
+++ b/runtime/vm/compiler/stub_code_compiler.h
@@ -119,6 +119,7 @@
// `StubCode::*<stub-name>Shared{With,Without}FpuRegsStub()`
static intptr_t WordOffsetFromFpToCpuRegister(Register cpu_register);
+ private:
#if !defined(TARGET_ARCH_IA32)
// Generates the code for searching a subtype test cache for an entry that
// matches the contents of the TypeTestABI registers. If no matching
@@ -126,29 +127,31 @@
// continues immediately after the loop and [cache_entry_reg] points to
// the start of the matching cache entry.
//
- // The following registers must be provided, that is, they cannot be
- // kNoRegister for any [n]:
- // - null_reg
- // - cache_entry_reg
- // - instance_cid_or_sig_reg
+ // The following registers from TypeTestABI are inputs under the following
+ // conditions:
+ // - kScratchReg: always
+ // - kInstanceReg: always
+ // - kDstTypeReg: [n] >= 3
+ // - kInstantiatorTypeArgumentsReg: [n] >= 4
+ // - kFunctionTypeArgumentsReg: [n] >= 5
//
- // The following registers must be provided for [n] >= 3:
- // - instance_type_args_reg
+ // Has the following input registers in addition to those in TypeTestABI:
+ // - null_reg: contains the ObjectPtr for Object::null()
+ // - cache_entry_reg: contains the ArrayPtr for the backing array of the STC
//
- // The following registers must be provided for [n] >= 7:
- // - parent_fun_type_args_reg
- // - delayed_type_args_reg
+ // The following registers must be provided for the given conditions and
+ // are clobbered:
+ // - instance_cid_or_sig_reg: always
+ // - instance_type_args_reg: [n] >= 2
+ // - parent_fun_type_args_reg: [n] >= 6
+ // - delayed_type_args_reg: [n] >= 7
//
- // All provided registers must be distinct, and in addition, all provided
- // registers must be distinct from the following TypeTestABI registers:
- // - kScratchReg
- // - kDstTypeReg
- // - kInstantiatorTypeArgumentsReg
- // - kFunctionTypeArgumentsReg
+ // Note that all input registers must be distinct, except for the case
+ // of kInstanceReg and [delayed_type_args_reg], which are allowed to overlap.
//
- // and all but [delayed_type_args_reg] must be distinct from the following
- // TypeTestABI register:
- // - kInstanceReg
+ // Also note that if any non-TypeTestABI registers overlap with any
+ // non-scratch TypeTestABI registers, the original value of the TypeTestABI
+ // register must be restored afterwards.
static void GenerateSubtypeTestCacheSearch(Assembler* assembler,
int n,
Register null_reg,
@@ -160,7 +163,10 @@
Label* not_found);
#endif
- private:
+ // Common function for generating the different SubtypeTestCache search
+ // stubs. Check architecture-specific version for inputs/outputs.
+ static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n);
+
// Common function for generating InitLateStaticField and
// InitLateFinalStaticField stubs.
void GenerateInitLateStaticFieldStub(bool is_final);
diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc
index def834f..4b752dd 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm.cc
@@ -2689,15 +2689,16 @@
// Inputs (all preserved, mostly from TypeTestABI struct):
// - kSubtypeTestCacheReg: SubtypeTestCacheLayout
// - kInstanceReg: instance to test against.
-// - kDstTypeReg: destination type (for n>=3).
-// - kInstantiatorTypeArgumentsReg: instantiator type arguments (for n=5).
-// - kFunctionTypeArgumentsReg: function type arguments (for n=5).
+// - kDstTypeReg: destination type (for n>=7).
+// - kInstantiatorTypeArgumentsReg: instantiator type arguments (for n>=3).
+// - kFunctionTypeArgumentsReg: function type arguments (for n>=4).
// - LR: return address.
//
// Outputs (from TypeTestABI struct):
// - kSubtypeTestCacheResultReg: the cached result, or null if not found.
-static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
- ASSERT(n == 1 || n == 3 || n == 5 || n == 7);
+void StubCodeCompiler::GenerateSubtypeNTestCacheStub(Assembler* assembler,
+ int n) {
+ ASSERT(n == 1 || n == 2 || n == 4 || n == 6 || n == 7);
RegisterSet saved_registers;
// Safe as the original value of TypeTestABI::kSubtypeTestCacheReg is only
@@ -2705,28 +2706,28 @@
const Register kCacheArrayReg = TypeTestABI::kSubtypeTestCacheReg;
saved_registers.AddRegister(kCacheArrayReg);
- // Registers that are only used for n >= 3 and must be preserved if used.
- Register kInstanceInstantiatorTypeArgumentsReg = kNoRegister;
- // Registers that are only used for n >= 7 and must be preserved if used.
- Register kInstanceParentFunctionTypeArgumentsReg = kNoRegister;
- Register kInstanceDelayedFunctionTypeArgumentsReg = kNoRegister;
-
// NOTFP must be preserved for bare payloads, otherwise CODE_REG.
const bool use_bare_payloads = FLAG_precompiled_mode;
// For this, we choose the register that need not be preserved of the pair.
const Register kNullReg = use_bare_payloads ? CODE_REG : NOTFP;
__ LoadObject(kNullReg, NullObject());
- // Free up registers to be used to store values checked in the loop.
- if (n >= 3) {
+ // Free up additional registers needed for checks in the loop. Initially
+ // define them as kNoRegister so any unexpected uses are caught.
+ Register kInstanceInstantiatorTypeArgumentsReg = kNoRegister;
+ if (n >= 2) {
kInstanceInstantiatorTypeArgumentsReg = PP;
saved_registers.AddRegister(kInstanceInstantiatorTypeArgumentsReg);
}
- if (n >= 7) {
+ Register kInstanceParentFunctionTypeArgumentsReg = kNoRegister;
+ if (n >= 5) {
// For this, we choose the register that must be preserved of the pair.
kInstanceParentFunctionTypeArgumentsReg =
use_bare_payloads ? NOTFP : CODE_REG;
saved_registers.AddRegister(kInstanceParentFunctionTypeArgumentsReg);
+ }
+ Register kInstanceDelayedFunctionTypeArgumentsReg = kNoRegister;
+ if (n >= 6) {
// We retrieve all the needed fields from the instance during loop
// initialization and store them in registers, so we don't need the value
// of kInstanceReg during the loop and just need to save and restore it.
@@ -2738,12 +2739,12 @@
__ PushRegisters(saved_registers);
Label not_found;
- StubCodeCompiler::GenerateSubtypeTestCacheSearch(
- assembler, n, kNullReg, kCacheArrayReg,
- STCInternalRegs::kInstanceCidOrSignatureReg,
- kInstanceInstantiatorTypeArgumentsReg,
- kInstanceParentFunctionTypeArgumentsReg,
- kInstanceDelayedFunctionTypeArgumentsReg, ¬_found);
+ GenerateSubtypeTestCacheSearch(assembler, n, kNullReg, kCacheArrayReg,
+ STCInternalRegs::kInstanceCidOrSignatureReg,
+ kInstanceInstantiatorTypeArgumentsReg,
+ kInstanceParentFunctionTypeArgumentsReg,
+ kInstanceDelayedFunctionTypeArgumentsReg,
+ ¬_found);
__ Comment("Found");
__ LoadCompressed(
@@ -2760,26 +2761,6 @@
__ Ret();
}
-// See comment on [GenerateSubtypeNTestCacheStub].
-void StubCodeCompiler::GenerateSubtype1TestCacheStub() {
- GenerateSubtypeNTestCacheStub(assembler, 1);
-}
-
-// See comment on [GenerateSubtypeNTestCacheStub].
-void StubCodeCompiler::GenerateSubtype3TestCacheStub() {
- GenerateSubtypeNTestCacheStub(assembler, 3);
-}
-
-// See comment on [GenerateSubtypeNTestCacheStub].
-void StubCodeCompiler::GenerateSubtype5TestCacheStub() {
- GenerateSubtypeNTestCacheStub(assembler, 5);
-}
-
-// See comment on[GenerateSubtypeNTestCacheStub].
-void StubCodeCompiler::GenerateSubtype7TestCacheStub() {
- GenerateSubtypeNTestCacheStub(assembler, 7);
-}
-
// Return the current stack pointer address, used to do stack alignment checks.
void StubCodeCompiler::GenerateGetCStackPointerStub() {
__ mov(R0, Operand(SP));
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
index 97ba42f..cb559d1 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -3006,15 +3006,16 @@
// Inputs (all preserved, mostly from TypeTestABI struct):
// - kSubtypeTestCacheReg: UntaggedSubtypeTestCache
// - kInstanceReg: instance to test against.
-// - kDstTypeReg: destination type (for n>=3).
-// - kInstantiatorTypeArgumentsReg: instantiator type arguments (for n=5).
-// - kFunctionTypeArgumentsReg: function type arguments (for n=5).
+// - kDstTypeReg: destination type (for n>=7).
+// - kInstantiatorTypeArgumentsReg: instantiator type arguments (for n>=3).
+// - kFunctionTypeArgumentsReg: function type arguments (for n>=4).
// - LR: return address.
//
// Outputs (from TypeTestABI struct):
// - kSubtypeTestCacheResultReg: the cached result, or null if not found.
-static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
- ASSERT(n == 1 || n == 3 || n == 5 || n == 7);
+void StubCodeCompiler::GenerateSubtypeNTestCacheStub(Assembler* assembler,
+ int n) {
+ ASSERT(n == 1 || n == 2 || n == 4 || n == 6 || n == 7);
// We could initialize kSubtypeTestCacheResultReg with null and use that as
// the null register up until exit, which means we'd just need to return
@@ -3030,7 +3031,7 @@
const Register kCacheArrayReg = TypeTestABI::kSubtypeTestCacheResultReg;
Label not_found;
- StubCodeCompiler::GenerateSubtypeTestCacheSearch(
+ GenerateSubtypeTestCacheSearch(
assembler, n, NULL_REG, kCacheArrayReg,
STCInternalRegs::kInstanceCidOrSignatureReg,
STCInternalRegs::kInstanceInstantiatorTypeArgumentsReg,
@@ -3050,26 +3051,6 @@
__ Ret();
}
-// See comment on [GenerateSubtypeNTestCacheStub].
-void StubCodeCompiler::GenerateSubtype1TestCacheStub() {
- GenerateSubtypeNTestCacheStub(assembler, 1);
-}
-
-// See comment on [GenerateSubtypeNTestCacheStub].
-void StubCodeCompiler::GenerateSubtype3TestCacheStub() {
- GenerateSubtypeNTestCacheStub(assembler, 3);
-}
-
-// See comment on [GenerateSubtypeNTestCacheStub].
-void StubCodeCompiler::GenerateSubtype5TestCacheStub() {
- GenerateSubtypeNTestCacheStub(assembler, 5);
-}
-
-// See comment on [GenerateSubtypeNTestCacheStub].
-void StubCodeCompiler::GenerateSubtype7TestCacheStub() {
- GenerateSubtypeNTestCacheStub(assembler, 7);
-}
-
void StubCodeCompiler::GenerateGetCStackPointerStub() {
__ mov(R0, CSP);
__ ret();
diff --git a/runtime/vm/compiler/stub_code_compiler_ia32.cc b/runtime/vm/compiler/stub_code_compiler_ia32.cc
index 6523a7d..9fd1a9f 100644
--- a/runtime/vm/compiler/stub_code_compiler_ia32.cc
+++ b/runtime/vm/compiler/stub_code_compiler_ia32.cc
@@ -2310,11 +2310,132 @@
#endif // defined(PRODUCT)
}
+// Constants used for generating subtype test cache lookup stubs.
+// We represent the depth of as a depth from the top of the stack at the
+// start of the stub. That is, depths for input values are non-negative and
+// depths for values pushed during the stub are negative.
+
+struct STCInternal : AllStatic {
+ // Used to initialize depths for conditionally-pushed values.
+ static constexpr intptr_t kNoDepth = kIntptrMin;
+
+ // These inputs are always on the stack when the SubtypeNTestCacheStub is
+ // called. These absolute depths will be converted to relative depths within
+ // the stub to compensate for additional pushed values.
+ static constexpr intptr_t kFunctionTypeArgumentsDepth = 1;
+ static constexpr intptr_t kInstantiatorTypeArgumentsDepth = 2;
+ static constexpr intptr_t kDestinationTypeDepth = 3;
+ static constexpr intptr_t kInstanceDepth = 4;
+ static constexpr intptr_t kCacheDepth = 5;
+
+ // Non-stack values are stored in non-kInstanceReg registers from TypeTestABI.
+ static constexpr Register kCacheArrayReg =
+ TypeTestABI::kInstantiatorTypeArgumentsReg;
+ static constexpr Register kScratchReg = TypeTestABI::kSubtypeTestCacheReg;
+ static constexpr Register kInstanceCidOrSignatureReg =
+ TypeTestABI::kFunctionTypeArgumentsReg;
+ static constexpr Register kInstanceInstantiatorTypeArgumentsReg =
+ TypeTestABI::kDstTypeReg;
+};
+
+static void GenerateSubtypeTestCacheLoop(
+ Assembler* assembler,
+ int n,
+ intptr_t original_tos_offset,
+ intptr_t parent_function_type_args_depth,
+ intptr_t delayed_type_args_depth,
+ Label* found,
+ Label* not_found,
+ Label* next_iteration) {
+ const auto& raw_null = Immediate(target::ToRawPointer(NullObject()));
+
+ // Compares a value at the given depth from the stack to the value in src.
+ auto compare_to_stack = [&](Register src, intptr_t depth) {
+ ASSERT(original_tos_offset + depth >= 0);
+ __ CompareToStack(src, original_tos_offset + depth);
+ };
+
+ __ LoadAcquireCompressed(
+ STCInternal::kScratchReg, STCInternal::kCacheArrayReg,
+ target::kCompressedWordSize *
+ target::SubtypeTestCache::kInstanceCidOrSignature);
+ __ cmpl(STCInternal::kScratchReg, raw_null);
+ __ j(EQUAL, not_found, Assembler::kNearJump);
+ __ cmpl(STCInternal::kScratchReg, STCInternal::kInstanceCidOrSignatureReg);
+ if (n == 1) {
+ __ j(EQUAL, found, Assembler::kNearJump);
+ return;
+ }
+ __ j(NOT_EQUAL, next_iteration, Assembler::kNearJump);
+ __ cmpl(STCInternal::kInstanceInstantiatorTypeArgumentsReg,
+ Address(STCInternal::kCacheArrayReg,
+ target::kWordSize *
+ target::SubtypeTestCache::kInstanceTypeArguments));
+ if (n == 2) {
+ __ j(EQUAL, found, Assembler::kNearJump);
+ return;
+ }
+ __ j(NOT_EQUAL, next_iteration, Assembler::kNearJump);
+ __ movl(STCInternal::kScratchReg,
+ Address(STCInternal::kCacheArrayReg,
+ target::kWordSize *
+ target::SubtypeTestCache::kInstantiatorTypeArguments));
+ compare_to_stack(STCInternal::kScratchReg,
+ STCInternal::kInstantiatorTypeArgumentsDepth);
+ if (n == 3) {
+ __ j(EQUAL, found, Assembler::kNearJump);
+ return;
+ }
+ __ j(NOT_EQUAL, next_iteration, Assembler::kNearJump);
+ __ movl(STCInternal::kScratchReg,
+ Address(STCInternal::kCacheArrayReg,
+ target::kWordSize *
+ target::SubtypeTestCache::kFunctionTypeArguments));
+ compare_to_stack(STCInternal::kScratchReg,
+ STCInternal::kFunctionTypeArgumentsDepth);
+ if (n == 4) {
+ __ j(EQUAL, found, Assembler::kNearJump);
+ return;
+ }
+ __ j(NOT_EQUAL, next_iteration, Assembler::kNearJump);
+ __ movl(
+ STCInternal::kScratchReg,
+ Address(
+ STCInternal::kCacheArrayReg,
+ target::kWordSize *
+ target::SubtypeTestCache::kInstanceParentFunctionTypeArguments));
+ compare_to_stack(STCInternal::kScratchReg, parent_function_type_args_depth);
+ if (n == 5) {
+ __ j(EQUAL, found, Assembler::kNearJump);
+ return;
+ }
+ __ j(NOT_EQUAL, next_iteration, Assembler::kNearJump);
+ __ movl(
+ STCInternal::kScratchReg,
+ Address(
+ STCInternal::kCacheArrayReg,
+ target::kWordSize *
+ target::SubtypeTestCache::kInstanceDelayedFunctionTypeArguments));
+ compare_to_stack(STCInternal::kScratchReg, delayed_type_args_depth);
+ if (n == 6) {
+ __ j(EQUAL, found, Assembler::kNearJump);
+ return;
+ }
+ __ j(NOT_EQUAL, next_iteration, Assembler::kNearJump);
+ __ movl(
+ STCInternal::kScratchReg,
+ Address(STCInternal::kCacheArrayReg,
+ target::kWordSize * target::SubtypeTestCache::kDestinationType));
+ compare_to_stack(STCInternal::kScratchReg,
+ STCInternal::kDestinationTypeDepth);
+ __ j(EQUAL, found, Assembler::kNearJump);
+}
+
// Used to check class and type arguments. Arguments passed on stack:
// TOS + 0: return address.
-// TOS + 1: function type arguments (only if n == 4, can be raw_null).
-// TOS + 2: instantiator type arguments (only if n == 4, can be raw_null).
-// TOS + 3: destination_type (only used if n >= 3).
+// TOS + 1: function type arguments (only used if n >= 4, can be raw_null).
+// TOS + 2: instantiator type arguments (only used if n >= 3, can be raw_null).
+// TOS + 3: destination_type (only used if n >= 7).
// TOS + 4: instance.
// TOS + 5: SubtypeTestCache.
//
@@ -2322,107 +2443,73 @@
//
// Result in SubtypeTestCacheReg::kResultReg: null -> not found, otherwise
// result (true or false).
-static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
- ASSERT(n == 1 || n == 3 || n == 5 || n == 7);
-
- // We represent the depth of as a depth from the top of the stack at the
- // start of the stub. That is, depths for input values are non-negative and
- // depths for values pushed during the stub are negative.
-
- // Used to initialize depths for conditionally-pushed values.
- const intptr_t kNoDepth = kIntptrMin;
- // Offset of the original top of the stack from the current top of stack.
- intptr_t original_tos_offset = 0;
-
- // Inputs use relative depths.
- static constexpr intptr_t kFunctionTypeArgumentsDepth = 1;
- static constexpr intptr_t kInstantiatorTypeArgumentsDepth = 2;
- static constexpr intptr_t kDestinationTypeDepth = 3;
- static constexpr intptr_t kInstanceDepth = 4;
- static constexpr intptr_t kCacheDepth = 5;
- // Others use absolute depths. We initialize conditionally pushed values to
- // kNoInput for extra checking.
- intptr_t kInstanceParentFunctionTypeArgumentsDepth = kNoDepth;
- intptr_t kInstanceDelayedFunctionTypeArgumentsDepth = kNoDepth;
-
- // Other values are stored in non-kInstanceReg registers from TypeTestABI.
- const Register kCacheArrayReg = TypeTestABI::kInstantiatorTypeArgumentsReg;
- const Register kScratchReg = TypeTestABI::kSubtypeTestCacheReg;
- const Register kInstanceCidOrSignature =
- TypeTestABI::kFunctionTypeArgumentsReg;
- const Register kInstanceInstantiatorTypeArgumentsReg =
- TypeTestABI::kDstTypeReg;
-
- // Loads a value at the given depth from the stack into dst.
- auto load_from_stack = [&](Register dst, intptr_t depth) {
- ASSERT(depth != kNoDepth);
- __ LoadFromStack(dst, original_tos_offset + depth);
- };
-
- // Compares a value at the given depth from the stack to the value in src.
- auto compare_to_stack = [&](Register src, intptr_t depth) {
- ASSERT(depth != kNoDepth);
- __ CompareToStack(src, original_tos_offset + depth);
- };
+void StubCodeCompiler::GenerateSubtypeNTestCacheStub(Assembler* assembler,
+ int n) {
+ ASSERT(n == 1 || n == 2 || n == 4 || n == 6 || n == 7);
const auto& raw_null = Immediate(target::ToRawPointer(NullObject()));
- load_from_stack(TypeTestABI::kInstanceReg, kInstanceDepth);
+ __ LoadFromStack(TypeTestABI::kInstanceReg, STCInternal::kInstanceDepth);
// Loop initialization (moved up here to avoid having all dependent loads
// after each other)
- load_from_stack(kCacheArrayReg, kCacheDepth);
+ __ LoadFromStack(STCInternal::kCacheArrayReg, STCInternal::kCacheDepth);
// We avoid a load-acquire barrier here by relying on the fact that all other
// loads from the array are data-dependent loads.
- __ movl(
- kCacheArrayReg,
- FieldAddress(kCacheArrayReg, target::SubtypeTestCache::cache_offset()));
+ __ movl(STCInternal::kCacheArrayReg,
+ FieldAddress(STCInternal::kCacheArrayReg,
+ target::SubtypeTestCache::cache_offset()));
// There is a maximum size for linear caches that is smaller than the size
// of any hash-based cache, so we check the size of the backing array to
// determine if this is a linear or hash-based cache.
- __ LoadFromSlot(kScratchReg, kCacheArrayReg, Slot::Array_length());
- __ CompareImmediate(kScratchReg,
+ __ LoadFromSlot(STCInternal::kScratchReg, STCInternal::kCacheArrayReg,
+ Slot::Array_length());
+ __ CompareImmediate(STCInternal::kScratchReg,
target::ToRawSmi(SubtypeTestCache::kMaxLinearCacheSize));
- Label not_found_before_push;
// For IA32, we never handle hash caches in the stub, as there's too much
// register pressure.
- __ BranchIf(GREATER, ¬_found_before_push);
- __ AddImmediate(
- kCacheArrayReg,
- target::Array::data_offset() - kHeapObjectTag +
- target::kCompressedWordSize * target::SubtypeTestCache::kHeaderSize);
+ Label is_linear;
+ __ BranchIf(LESS_EQUAL, &is_linear, Assembler::kNearJump);
+ // Return null so that we'll continue to the runtime for hash-based caches.
+ __ movl(TypeTestABI::kSubtypeTestCacheResultReg, raw_null);
+ __ ret();
+ __ Bind(&is_linear);
+ __ AddImmediate(STCInternal::kCacheArrayReg,
+ target::Array::data_offset() - kHeapObjectTag);
Label loop, not_closure;
- if (n >= 5) {
- __ LoadClassIdMayBeSmi(kInstanceCidOrSignature, TypeTestABI::kInstanceReg);
+ if (n >= 4) {
+ __ LoadClassIdMayBeSmi(STCInternal::kInstanceCidOrSignatureReg,
+ TypeTestABI::kInstanceReg);
} else {
- __ LoadClassId(kInstanceCidOrSignature, TypeTestABI::kInstanceReg);
+ __ LoadClassId(STCInternal::kInstanceCidOrSignatureReg,
+ TypeTestABI::kInstanceReg);
}
- __ cmpl(kInstanceCidOrSignature, Immediate(kClosureCid));
+ __ cmpl(STCInternal::kInstanceCidOrSignatureReg, Immediate(kClosureCid));
__ j(NOT_EQUAL, ¬_closure, Assembler::kNearJump);
// Closure handling.
{
- __ movl(kInstanceCidOrSignature,
+ __ movl(STCInternal::kInstanceCidOrSignatureReg,
FieldAddress(TypeTestABI::kInstanceReg,
target::Closure::function_offset()));
- __ movl(kInstanceCidOrSignature,
- FieldAddress(kInstanceCidOrSignature,
+ __ movl(STCInternal::kInstanceCidOrSignatureReg,
+ FieldAddress(STCInternal::kInstanceCidOrSignatureReg,
target::Function::signature_offset()));
- if (n >= 3) {
+ if (n >= 2) {
__ movl(
- kInstanceInstantiatorTypeArgumentsReg,
+ STCInternal::kInstanceInstantiatorTypeArgumentsReg,
FieldAddress(TypeTestABI::kInstanceReg,
target::Closure::instantiator_type_arguments_offset()));
- if (n >= 7) {
- __ pushl(
- FieldAddress(TypeTestABI::kInstanceReg,
- target::Closure::delayed_type_arguments_offset()));
- __ pushl(
- FieldAddress(TypeTestABI::kInstanceReg,
- target::Closure::function_type_arguments_offset()));
- }
+ }
+ if (n >= 5) {
+ __ pushl(FieldAddress(TypeTestABI::kInstanceReg,
+ target::Closure::function_type_arguments_offset()));
+ }
+ if (n >= 6) {
+ __ pushl(FieldAddress(TypeTestABI::kInstanceReg,
+ target::Closure::delayed_type_arguments_offset()));
}
__ jmp(&loop, Assembler::kNearJump);
}
@@ -2430,127 +2517,82 @@
// Non-Closure handling.
{
__ Bind(¬_closure);
- if (n >= 3) {
+ if (n >= 2) {
Label has_no_type_arguments;
- __ LoadClassById(kScratchReg, kInstanceCidOrSignature);
- __ movl(kInstanceInstantiatorTypeArgumentsReg, raw_null);
+ __ LoadClassById(STCInternal::kScratchReg,
+ STCInternal::kInstanceCidOrSignatureReg);
+ __ movl(STCInternal::kInstanceInstantiatorTypeArgumentsReg, raw_null);
__ movl(
- kScratchReg,
- FieldAddress(kScratchReg,
+ STCInternal::kScratchReg,
+ FieldAddress(STCInternal::kScratchReg,
target::Class::
host_type_arguments_field_offset_in_words_offset()));
- __ cmpl(kScratchReg, Immediate(target::Class::kNoTypeArguments));
+ __ cmpl(STCInternal::kScratchReg,
+ Immediate(target::Class::kNoTypeArguments));
__ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump);
- __ movl(kInstanceInstantiatorTypeArgumentsReg,
- FieldAddress(TypeTestABI::kInstanceReg, kScratchReg, TIMES_4, 0));
+ __ movl(STCInternal::kInstanceInstantiatorTypeArgumentsReg,
+ FieldAddress(TypeTestABI::kInstanceReg, STCInternal::kScratchReg,
+ TIMES_4, 0));
__ Bind(&has_no_type_arguments);
-
- if (n >= 7) {
- __ pushl(raw_null); // delayed.
- __ pushl(raw_null); // function.
- }
}
- __ SmiTag(kInstanceCidOrSignature);
+ __ SmiTag(STCInternal::kInstanceCidOrSignatureReg);
+ if (n >= 5) {
+ __ pushl(raw_null); // parent function.
+ }
+ if (n >= 6) {
+ __ pushl(raw_null); // delayed.
+ }
}
- if (n >= 7) {
- // Now that instance handling is done, both the delayed and parent function
- // type arguments stack slots have been set, so any input uses must be
- // offset by the new values and the new values can now be accessed in
- // the following code without issue when n >= 6.
- original_tos_offset = 2;
- kInstanceDelayedFunctionTypeArgumentsDepth = -1;
- kInstanceParentFunctionTypeArgumentsDepth = -2;
+ // Offset of the original top of the stack from the current top of stack.
+ intptr_t original_tos_offset = 0;
+
+ // Additional data conditionally stored on the stack use negative depths
+ // that will be non-negative when adjusted for original_tos_offset. We
+ // initialize conditionally pushed values to kNoInput for extra checking.
+ intptr_t kInstanceParentFunctionTypeArgumentsDepth = STCInternal::kNoDepth;
+ intptr_t kInstanceDelayedFunctionTypeArgumentsDepth = STCInternal::kNoDepth;
+
+ // Now that instance handling is done, both the delayed and parent function
+ // type arguments stack slots have been set, so any input uses must be
+ // offset by the new values and the new values can now be accessed in
+ // the following code without issue when n >= 6.
+ if (n >= 5) {
+ original_tos_offset++;
+ kInstanceParentFunctionTypeArgumentsDepth = -original_tos_offset;
+ }
+ if (n >= 6) {
+ original_tos_offset++;
+ kInstanceDelayedFunctionTypeArgumentsDepth = -original_tos_offset;
}
Label found, not_found, done, next_iteration;
// Loop header.
__ Bind(&loop);
- __ LoadAcquireCompressed(
- kScratchReg, kCacheArrayReg,
- target::kCompressedWordSize *
- target::SubtypeTestCache::kInstanceCidOrSignature);
- __ cmpl(kScratchReg, raw_null);
- __ j(EQUAL, ¬_found, Assembler::kNearJump);
- __ cmpl(kScratchReg, kInstanceCidOrSignature);
- if (n == 1) {
- __ j(EQUAL, &found, Assembler::kNearJump);
- } else {
- __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
- __ movl(kScratchReg,
- Address(kCacheArrayReg,
- target::kWordSize *
- target::SubtypeTestCache::kDestinationType));
- compare_to_stack(kScratchReg, kDestinationTypeDepth);
- __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
- __ cmpl(kInstanceInstantiatorTypeArgumentsReg,
- Address(kCacheArrayReg,
- target::kWordSize *
- target::SubtypeTestCache::kInstanceTypeArguments));
- if (n == 3) {
- __ j(EQUAL, &found, Assembler::kNearJump);
- } else {
- __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
- __ movl(
- kScratchReg,
- Address(kCacheArrayReg,
- target::kWordSize *
- target::SubtypeTestCache::kInstantiatorTypeArguments));
- compare_to_stack(kScratchReg, kInstantiatorTypeArgumentsDepth);
- __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
- __ movl(kScratchReg,
- Address(kCacheArrayReg,
- target::kWordSize *
- target::SubtypeTestCache::kFunctionTypeArguments));
- compare_to_stack(kScratchReg, kFunctionTypeArgumentsDepth);
- if (n == 5) {
- __ j(EQUAL, &found, Assembler::kNearJump);
- } else {
- ASSERT(n == 7);
- __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
-
- __ movl(kScratchReg,
- Address(kCacheArrayReg,
- target::kWordSize *
- target::SubtypeTestCache::
- kInstanceParentFunctionTypeArguments));
- compare_to_stack(kScratchReg,
- kInstanceParentFunctionTypeArgumentsDepth);
- __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
- __ movl(kScratchReg,
- Address(kCacheArrayReg,
- target::kWordSize *
- target::SubtypeTestCache::
- kInstanceDelayedFunctionTypeArguments));
- compare_to_stack(kScratchReg,
- kInstanceDelayedFunctionTypeArgumentsDepth);
- __ j(EQUAL, &found, Assembler::kNearJump);
- }
- }
- }
+ GenerateSubtypeTestCacheLoop(assembler, n, original_tos_offset,
+ kInstanceParentFunctionTypeArgumentsDepth,
+ kInstanceDelayedFunctionTypeArgumentsDepth,
+ &found, ¬_found, &next_iteration);
__ Bind(&next_iteration);
- __ addl(kCacheArrayReg,
+ __ addl(STCInternal::kCacheArrayReg,
Immediate(target::kWordSize *
target::SubtypeTestCache::kTestEntryLength));
__ jmp(&loop, Assembler::kNearJump);
__ Bind(&found);
- if (n >= 7) {
- __ Drop(2);
- original_tos_offset = 0; // In case we add any input uses after this point.
+ if (n >= 5) {
+ __ Drop(original_tos_offset);
}
__ movl(TypeTestABI::kSubtypeTestCacheResultReg,
- Address(kCacheArrayReg,
+ Address(STCInternal::kCacheArrayReg,
target::kWordSize * target::SubtypeTestCache::kTestResult));
__ ret();
__ Bind(¬_found);
- if (n >= 7) {
- __ Drop(2);
- original_tos_offset = 0; // In case we add any input uses after this point.
+ if (n >= 5) {
+ __ Drop(original_tos_offset);
}
- __ Bind(¬_found_before_push);
// In the not found case, even though the field that determines occupancy was
// null, another thread might be updating the cache and in the middle of
// filling in the entry. Thus, we load the null object explicitly instead of
@@ -2559,26 +2601,6 @@
__ ret();
}
-// See comment on [GenerateSubtypeNTestCacheStub].
-void StubCodeCompiler::GenerateSubtype1TestCacheStub() {
- GenerateSubtypeNTestCacheStub(assembler, 1);
-}
-
-// See comment on [GenerateSubtypeNTestCacheStub].
-void StubCodeCompiler::GenerateSubtype3TestCacheStub() {
- GenerateSubtypeNTestCacheStub(assembler, 3);
-}
-
-// See comment on [GenerateSubtypeNTestCacheStub].
-void StubCodeCompiler::GenerateSubtype5TestCacheStub() {
- GenerateSubtypeNTestCacheStub(assembler, 5);
-}
-
-// See comment on [GenerateSubtypeNTestCacheStub].
-void StubCodeCompiler::GenerateSubtype7TestCacheStub() {
- GenerateSubtypeNTestCacheStub(assembler, 7);
-}
-
// Return the current stack pointer address, used to do stack alignment checks.
// TOS + 0: return address
// Result in EAX.
diff --git a/runtime/vm/compiler/stub_code_compiler_riscv.cc b/runtime/vm/compiler/stub_code_compiler_riscv.cc
index 8c79853..1ad795d 100644
--- a/runtime/vm/compiler/stub_code_compiler_riscv.cc
+++ b/runtime/vm/compiler/stub_code_compiler_riscv.cc
@@ -2801,15 +2801,16 @@
// Inputs (all preserved, mostly from TypeTestABI struct):
// - kSubtypeTestCacheReg: UntaggedSubtypeTestCache
// - kInstanceReg: instance to test against.
-// - kDstTypeReg: destination type (for n>=3).
-// - kInstantiatorTypeArgumentsReg: instantiator type arguments (for n=5).
-// - kFunctionTypeArgumentsReg: function type arguments (for n=5).
+// - kDstTypeReg: destination type (for n>=7).
+// - kInstantiatorTypeArgumentsReg: instantiator type arguments (for n>=3).
+// - kFunctionTypeArgumentsReg: function type arguments (for n>=4).
// - RA: return address.
//
// Outputs (from TypeTestABI struct):
// - kSubtypeTestCacheResultReg: the cached result, or null if not found.
-static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
- ASSERT(n == 1 || n == 3 || n == 5 || n == 7);
+void StubCodeCompiler::GenerateSubtypeNTestCacheStub(Assembler* assembler,
+ int n) {
+ ASSERT(n == 1 || n == 2 || n == 4 || n == 6 || n == 7);
// We could initialize kSubtypeTestCacheResultReg with null and use that as
// the null register up until exit, which means we'd just need to return
@@ -2825,7 +2826,7 @@
const Register kCacheArrayReg = TypeTestABI::kSubtypeTestCacheResultReg;
Label not_found;
- StubCodeCompiler::GenerateSubtypeTestCacheSearch(
+ GenerateSubtypeTestCacheSearch(
assembler, n, NULL_REG, kCacheArrayReg,
STCInternalRegs::kInstanceCidOrSignatureReg,
STCInternalRegs::kInstanceInstantiatorTypeArgumentsReg,
@@ -2845,26 +2846,6 @@
__ Ret();
}
-// See comment on [GenerateSubtypeNTestCacheStub].
-void StubCodeCompiler::GenerateSubtype1TestCacheStub() {
- GenerateSubtypeNTestCacheStub(assembler, 1);
-}
-
-// See comment on [GenerateSubtypeNTestCacheStub].
-void StubCodeCompiler::GenerateSubtype3TestCacheStub() {
- GenerateSubtypeNTestCacheStub(assembler, 3);
-}
-
-// See comment on [GenerateSubtypeNTestCacheStub].
-void StubCodeCompiler::GenerateSubtype5TestCacheStub() {
- GenerateSubtypeNTestCacheStub(assembler, 5);
-}
-
-// See comment on [GenerateSubtypeNTestCacheStub].
-void StubCodeCompiler::GenerateSubtype7TestCacheStub() {
- GenerateSubtypeNTestCacheStub(assembler, 7);
-}
-
void StubCodeCompiler::GenerateGetCStackPointerStub() {
__ mv(A0, SP);
__ ret();
diff --git a/runtime/vm/compiler/stub_code_compiler_x64.cc b/runtime/vm/compiler/stub_code_compiler_x64.cc
index de79112..9079c27 100644
--- a/runtime/vm/compiler/stub_code_compiler_x64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_x64.cc
@@ -2964,16 +2964,17 @@
// Input registers (all preserved, from TypeTestABI struct):
// - kSubtypeTestCacheReg: UntaggedSubtypeTestCache
// - kInstanceReg: instance to test against (must be preserved).
-// - kDstTypeReg: destination type (for n>=3).
-// - kInstantiatorTypeArgumentsReg : instantiator type arguments (for n>=5).
-// - kFunctionTypeArgumentsReg : function type arguments (for n>=5).
+// - kDstTypeReg: destination type (for n>=7).
+// - kInstantiatorTypeArgumentsReg : instantiator type arguments (for n>=3).
+// - kFunctionTypeArgumentsReg : function type arguments (for n>=4).
// Inputs from stack:
// - TOS + 0: return address.
//
// Outputs (from TypeTestABI struct):
// - kSubtypeTestCacheResultReg: the cached result, or null if not found.
-static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
- ASSERT(n == 1 || n == 3 || n == 5 || n == 7);
+void StubCodeCompiler::GenerateSubtypeNTestCacheStub(Assembler* assembler,
+ int n) {
+ ASSERT(n == 1 || n == 2 || n == 4 || n == 6 || n == 7);
RegisterSet saved_registers;
// Until we have the result, we use the result register to store the null
@@ -2982,21 +2983,22 @@
const Register kNullReg = TypeTestABI::kSubtypeTestCacheResultReg;
__ LoadObject(kNullReg, NullObject());
- // Only used for n >= 7, so set conditionally in that case to catch misuse.
+ // Free up additional registers needed for checks in the loop. Initially
+ // define them as kNoRegister so any unexpected uses are caught.
Register kInstanceParentFunctionTypeArgumentsReg = kNoRegister;
- Register kInstanceDelayedFunctionTypeArgumentsReg = kNoRegister;
-
- // Free up these 2 registers to be used for 7-value test.
- if (n >= 7) {
+ if (n >= 5) {
kInstanceParentFunctionTypeArgumentsReg = PP;
saved_registers.AddRegister(kInstanceParentFunctionTypeArgumentsReg);
+ }
+ Register kInstanceDelayedFunctionTypeArgumentsReg = kNoRegister;
+ if (n >= 6) {
kInstanceDelayedFunctionTypeArgumentsReg = CODE_REG;
saved_registers.AddRegister(kInstanceDelayedFunctionTypeArgumentsReg);
}
__ PushRegisters(saved_registers);
Label done;
- StubCodeCompiler::GenerateSubtypeTestCacheSearch(
+ GenerateSubtypeTestCacheSearch(
assembler, n, kNullReg, STCInternalRegs::kCacheEntryReg,
STCInternalRegs::kInstanceCidOrSignatureReg,
STCInternalRegs::kInstanceInstantiatorTypeArgumentsReg,
@@ -3018,26 +3020,6 @@
__ Ret();
}
-// See comment on [GenerateSubtypeNTestCacheStub].
-void StubCodeCompiler::GenerateSubtype1TestCacheStub() {
- GenerateSubtypeNTestCacheStub(assembler, 1);
-}
-
-// See comment on [GenerateSubtypeNTestCacheStub].
-void StubCodeCompiler::GenerateSubtype3TestCacheStub() {
- GenerateSubtypeNTestCacheStub(assembler, 3);
-}
-
-// See comment on [GenerateSubtypeNTestCacheStub].
-void StubCodeCompiler::GenerateSubtype5TestCacheStub() {
- GenerateSubtypeNTestCacheStub(assembler, 5);
-}
-
-// See comment on [GenerateSubtypeNTestCacheStub].
-void StubCodeCompiler::GenerateSubtype7TestCacheStub() {
- GenerateSubtypeNTestCacheStub(assembler, 7);
-}
-
// Return the current stack pointer address, used to stack alignment
// checks.
// TOS + 0: return address
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 39f1980..f310b9c 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -19168,11 +19168,9 @@
void SubtypeTestCache::Init() {
const auto& array =
- Array::Handle(Array::New(kHeaderSize + kTestEntryLength, Heap::kOld));
- // Set the number of occupied entries to 0 and mark the first (only) entry
- // unoccupied before making this array visible.
- array.SetAt(kNumOccupiedIndex, Object::smi_zero());
- array.SetAt(kHeaderSize + kInstanceCidOrSignature, Object::null_object());
+ Array::Handle(Array::NewUninitialized(kTestEntryLength, Heap::kOld));
+ // Mark the first (only) entry unoccupied before making this array visible.
+ array.SetAt(kInstanceCidOrSignature, Object::null_object());
cached_array_ = array.ptr();
}
@@ -19182,10 +19180,8 @@
SubtypeTestCachePtr SubtypeTestCache::New(intptr_t num_inputs) {
ASSERT(Object::subtypetestcache_class() != Class::null());
- // While the SubtypeTestCache runtime code is written so that any value in
- // [1..kMaxInputs] works, we only expect the following values in practice.
- ASSERT(num_inputs == 1 || num_inputs == 3 || num_inputs == 5 ||
- num_inputs == 7);
+ ASSERT(num_inputs >= 1);
+ ASSERT(num_inputs <= kMaxInputs);
SubtypeTestCache& result = SubtypeTestCache::Handle();
{
// SubtypeTestCache objects are long living objects, allocate them in the
@@ -19197,6 +19193,7 @@
result ^= raw;
result.untag()->num_inputs_ = num_inputs;
}
+ result.set_num_occupied(0);
result.set_cache(Array::Handle(cached_array_));
return result.ptr();
}
@@ -19212,11 +19209,14 @@
untag()->set_cache<std::memory_order_release>(value.ptr());
}
+void SubtypeTestCache::set_num_occupied(intptr_t value) const {
+ ASSERT(Utils::IsUint(32, value));
+ untag()->num_occupied_ = value;
+}
+
intptr_t SubtypeTestCache::NumberOfChecks() const {
ASSERT(!IsNull());
- NoSafepointScope no_safepoint;
- return RawSmiValue(Smi::RawCast(
- cache()->untag()->element<std::memory_order_acquire>(kNumOccupiedIndex)));
+ return num_occupied();
}
intptr_t SubtypeTestCache::NumEntries() const {
@@ -19230,7 +19230,7 @@
bool SubtypeTestCache::IsHash() const {
if (IsNull()) return false;
- return RawSmiValue(cache()->untag()->length()) > kMaxLinearCacheSize;
+ return Array::LengthOf(cache()) > kMaxLinearCacheSize;
}
bool SubtypeTestCache::IsHash(const Array& array) {
@@ -19281,24 +19281,24 @@
entry.Set<kTestResult>(test_result);
switch (num_inputs()) {
case 7:
+ entry.Set<kDestinationType>(destination_type);
+ FALL_THROUGH;
+ case 6:
entry.Set<kInstanceDelayedFunctionTypeArguments>(
instance_delayed_type_arguments);
FALL_THROUGH;
- case 6:
+ case 5:
entry.Set<kInstanceParentFunctionTypeArguments>(
instance_parent_function_type_arguments);
FALL_THROUGH;
- case 5:
+ case 4:
entry.Set<kFunctionTypeArguments>(function_type_arguments);
FALL_THROUGH;
- case 4:
+ case 3:
entry.Set<kInstantiatorTypeArguments>(instantiator_type_arguments);
FALL_THROUGH;
- case 3:
- entry.Set<kInstanceTypeArguments>(instance_type_arguments);
- FALL_THROUGH;
case 2:
- entry.Set<kDestinationType>(destination_type);
+ entry.Set<kInstanceTypeArguments>(instance_type_arguments);
FALL_THROUGH;
case 1:
// If this is a new backing array, we don't need store-release barriers,
@@ -19318,16 +19318,9 @@
default:
UNREACHABLE();
}
- // Similarly, we set the metadata afterwards with a store-release barrier to
- // ensure that any reader that sees the updated count can depend on at least
- // that number of entries being occupied, for example, all entries up to that
- // count being occupied in a linear cache.
- const Smi& new_count = Smi::Handle(zone, Smi::New(old_num + 1));
+ set_num_occupied(old_num + 1);
if (was_grown) {
- data.SetAt(kNumOccupiedIndex, new_count);
set_cache(data);
- } else {
- data.SetAtRelease(kNumOccupiedIndex, new_count);
}
return loc.entry;
}
@@ -19344,41 +19337,41 @@
const TypeArguments& instance_delayed_type_arguments) {
switch (num_inputs) {
case 7:
+ if (t.Get<SubtypeTestCache::kDestinationType>() !=
+ destination_type.ptr()) {
+ return false;
+ }
+ FALL_THROUGH;
+ case 6:
if (t.Get<SubtypeTestCache::kInstanceDelayedFunctionTypeArguments>() !=
instance_delayed_type_arguments.ptr()) {
return false;
}
FALL_THROUGH;
- case 6:
+ case 5:
if (t.Get<SubtypeTestCache::kInstanceParentFunctionTypeArguments>() !=
instance_parent_function_type_arguments.ptr()) {
return false;
}
FALL_THROUGH;
- case 5:
+ case 4:
if (t.Get<SubtypeTestCache::kFunctionTypeArguments>() !=
function_type_arguments.ptr()) {
return false;
}
FALL_THROUGH;
- case 4:
+ case 3:
if (t.Get<SubtypeTestCache::kInstantiatorTypeArguments>() !=
instantiator_type_arguments.ptr()) {
return false;
}
FALL_THROUGH;
- case 3:
+ case 2:
if (t.Get<SubtypeTestCache::kInstanceTypeArguments>() !=
instance_type_arguments.ptr()) {
return false;
}
FALL_THROUGH;
- case 2:
- if (t.Get<SubtypeTestCache::kDestinationType>() !=
- destination_type.ptr()) {
- return false;
- }
- FALL_THROUGH;
case 1:
// We don't need to perform load-acquire semantics when re-retrieving
// the kInstanceCidOrSignature field, as this is performed only if the
@@ -19421,23 +19414,23 @@
: Smi::Cast(instance_class_id_or_signature).Value();
switch (num_inputs) {
case 7:
- hash = CombineHashes(hash, instance_delayed_type_arguments.Hash());
+ hash = CombineHashes(hash, destination_type.Hash());
FALL_THROUGH;
case 6:
+ hash = CombineHashes(hash, instance_delayed_type_arguments.Hash());
+ FALL_THROUGH;
+ case 5:
hash =
CombineHashes(hash, instance_parent_function_type_arguments.Hash());
FALL_THROUGH;
- case 5:
+ case 4:
hash = CombineHashes(hash, function_type_arguments.Hash());
FALL_THROUGH;
- case 4:
+ case 3:
hash = CombineHashes(hash, instantiator_type_arguments.Hash());
FALL_THROUGH;
- case 3:
- hash = CombineHashes(hash, instance_type_arguments.Hash());
- FALL_THROUGH;
case 2:
- hash = CombineHashes(hash, destination_type.Hash());
+ hash = CombineHashes(hash, instance_type_arguments.Hash());
FALL_THROUGH;
case 1:
break;
@@ -19470,20 +19463,14 @@
probe_distance++;
}
}
- // We should always get the next slot for a linear cache.
- ASSERT(is_hash || probe == NumberOfChecks(array));
return {probe, false};
}
-intptr_t SubtypeTestCache::NumberOfChecks(const Array& array) {
- return Smi::Value(Smi::RawCast(array.AtAcquire(kNumOccupiedIndex)));
-}
-
ArrayPtr SubtypeTestCache::EnsureCapacity(Zone* zone,
const Array& array,
intptr_t new_occupied,
bool* was_grown) const {
- ASSERT(new_occupied > NumberOfChecks(array));
+ ASSERT(new_occupied > NumberOfChecks());
ASSERT(was_grown != nullptr);
// How many entries are in the current array (including unoccupied entries).
const intptr_t current_capacity = NumEntries(array);
@@ -19514,13 +19501,13 @@
Utils::Minimum(current_capacity + (current_capacity >> 1),
kMaxLinearCacheEntries) +
1;
- const intptr_t cache_size = kHeaderSize + new_capacity * kTestEntryLength;
+ const intptr_t cache_size = new_capacity * kTestEntryLength;
ASSERT(cache_size <= kMaxLinearCacheSize);
const auto& new_data =
Array::Handle(zone, Array::Grow(array, cache_size, Heap::kOld));
ASSERT(!new_data.IsNull());
- // No need to adjust the number of occupied entries or old entries, as they
- // are copied over by Array::Grow. Just mark any new entries as unoccupied.
+ // No need to adjust old entries, as they are copied over by Array::Grow.
+ // Just mark any new entries as unoccupied.
SubtypeTestCacheTable table(new_data);
for (intptr_t i = current_capacity; i < new_capacity; i++) {
const auto& tuple = table.At(i);
@@ -19541,18 +19528,11 @@
// appendix, 2nd edition).
ASSERT(Utils::IsPowerOfTwo(new_capacity));
ASSERT(LoadFactor(new_occupied, new_capacity) < kMaxLoadFactor);
- const intptr_t new_size = kHeaderSize + new_capacity * kTestEntryLength;
+ const intptr_t new_size = new_capacity * kTestEntryLength;
const auto& new_data =
Array::Handle(zone, Array::NewUninitialized(new_size, Heap::kOld));
ASSERT(!new_data.IsNull());
- // First copy over the metadata in new_data using the existing Object handle.
- for (intptr_t i = 0; i < kHeaderSize; i++) {
- instance_cid_or_signature = array.At(i);
- new_data.SetAt(i, instance_cid_or_signature);
- }
- // Set the object handle back to null for later use.
- instance_cid_or_signature = Object::null();
- // Then mark all the entries in new_data as unoccupied.
+ // Mark all the entries in new_data as unoccupied.
SubtypeTestCacheTable to_table(new_data);
for (const auto& tuple : to_table) {
tuple.Set<kInstanceCidOrSignature>(instance_cid_or_signature);
@@ -19588,24 +19568,24 @@
to_tuple.Set<kTestResult>(test_result);
switch (used_inputs) {
case 7:
+ to_tuple.Set<kDestinationType>(destination_type);
+ FALL_THROUGH;
+ case 6:
to_tuple.Set<kInstanceDelayedFunctionTypeArguments>(
instance_delayed_type_arguments);
FALL_THROUGH;
- case 6:
+ case 5:
to_tuple.Set<kInstanceParentFunctionTypeArguments>(
instance_parent_function_type_arguments);
FALL_THROUGH;
- case 5:
+ case 4:
to_tuple.Set<kFunctionTypeArguments>(function_type_arguments);
FALL_THROUGH;
- case 4:
+ case 3:
to_tuple.Set<kInstantiatorTypeArguments>(instantiator_type_arguments);
FALL_THROUGH;
- case 3:
- to_tuple.Set<kInstanceTypeArguments>(instance_type_arguments);
- FALL_THROUGH;
case 2:
- to_tuple.Set<kDestinationType>(destination_type);
+ to_tuple.Set<kInstanceTypeArguments>(instance_type_arguments);
FALL_THROUGH;
case 1:
to_tuple.Set<kInstanceCidOrSignature>(instance_cid_or_signature);
@@ -19679,24 +19659,24 @@
ASSERT(!instance_class_id_or_signature->IsNull());
switch (num_inputs) {
case 7:
+ *destination_type = entry.Get<kDestinationType>();
+ FALL_THROUGH;
+ case 6:
*instance_delayed_type_arguments =
entry.Get<kInstanceDelayedFunctionTypeArguments>();
FALL_THROUGH;
- case 6:
+ case 5:
*instance_parent_function_type_arguments =
entry.Get<kInstanceParentFunctionTypeArguments>();
FALL_THROUGH;
- case 5:
+ case 4:
*function_type_arguments = entry.Get<kFunctionTypeArguments>();
FALL_THROUGH;
- case 4:
+ case 3:
*instantiator_type_arguments = entry.Get<kInstantiatorTypeArguments>();
FALL_THROUGH;
- case 3:
- *instance_type_arguments = entry.Get<kInstanceTypeArguments>();
- FALL_THROUGH;
case 2:
- *destination_type = entry.Get<kDestinationType>();
+ *instance_type_arguments = entry.Get<kInstanceTypeArguments>();
FALL_THROUGH;
case 1:
break;
@@ -19812,12 +19792,12 @@
"%" Pd ": [ %#" Px ", %#" Px ", %#" Px ", %#" Px ", %#" Px ", %#" Px
", %#" Px ", %#" Px " ]",
index, static_cast<uword>(instance_class_id_or_signature.ptr()),
- static_cast<uword>(destination_type.ptr()),
static_cast<uword>(instance_type_arguments.ptr()),
static_cast<uword>(instantiator_type_arguments.ptr()),
static_cast<uword>(function_type_arguments.ptr()),
static_cast<uword>(instance_parent_function_type_arguments.ptr()),
static_cast<uword>(instance_delayed_type_arguments.ptr()),
+ static_cast<uword>(destination_type.ptr()),
static_cast<uword>(result.ptr()));
if (instance_class_id_or_signature.IsSmi()) {
buffer->Printf("%sclass id: %" Pd "", separator,
@@ -19827,21 +19807,6 @@
"%ssignature: %s", separator,
FunctionType::Cast(instance_class_id_or_signature).ToCString());
}
- if (!destination_type.IsNull()) {
- buffer->Printf("%sdestination type: %s", separator,
- destination_type.ToCString());
- if (!destination_type.IsInstantiated()) {
- AbstractType& test_type = AbstractType::Handle(
- zone, destination_type.InstantiateFrom(instantiator_type_arguments,
- function_type_arguments,
- kAllFree, Heap::kNew));
- const auto type_class_id = test_type.type_class_id();
- buffer->Printf("%sinstantiated type: %s", separator,
- test_type.ToCString());
- buffer->Printf("%sinstantiated type class id: %d", separator,
- type_class_id);
- }
- }
if (!instance_type_arguments.IsNull()) {
if (instance_class_id_or_signature.IsSmi()) {
buffer->Printf("%sinstance type arguments: %s", separator,
@@ -19868,6 +19833,21 @@
buffer->Printf("%sclosure delayed function type arguments: %s", separator,
instance_delayed_type_arguments.ToCString());
}
+ if (!destination_type.IsNull()) {
+ buffer->Printf("%sdestination type: %s", separator,
+ destination_type.ToCString());
+ if (!destination_type.IsInstantiated()) {
+ AbstractType& test_type = AbstractType::Handle(
+ zone, destination_type.InstantiateFrom(instantiator_type_arguments,
+ function_type_arguments,
+ kAllFree, Heap::kNew));
+ const auto type_class_id = test_type.type_class_id();
+ buffer->Printf("%sinstantiated type: %s", separator,
+ test_type.ToCString());
+ buffer->Printf("%sinstantiated type class id: %d", separator,
+ type_class_id);
+ }
+ }
buffer->Printf("%sresult: %s", separator, result.ToCString());
}
@@ -19881,7 +19861,8 @@
? nullptr
: OS::SCreate(zone, "%s%s", line_prefix, line_prefix);
const intptr_t num_entries = NumEntries();
- buffer->Printf("SubtypeTestCache(%" Pd "", num_inputs());
+ buffer->Printf("SubtypeTestCache(%" Pd ", %" Pd "", num_inputs(),
+ num_occupied());
for (intptr_t i = 0; i < num_entries; i++) {
if (!IsOccupied(i)) continue;
buffer->Printf(",%s{", separator);
@@ -19892,6 +19873,7 @@
}
void SubtypeTestCache::Reset() const {
+ set_num_occupied(0);
set_cache(Array::Handle(cached_array_));
}
@@ -19903,6 +19885,8 @@
if (ptr() == other.ptr()) {
return true;
}
+ if (num_inputs() != other.num_inputs()) return false;
+ if (num_occupied() != other.num_occupied()) return false;
return Array::Handle(cache()).Equals(Array::Handle(other.cache()));
}
@@ -19921,13 +19905,14 @@
auto& entry_cache = Array::Handle(zone, cache());
entry_cache = entry_cache.Copy();
result.set_cache(entry_cache);
+ result.set_num_occupied(num_occupied());
return result.ptr();
}
bool SubtypeTestCache::IsOccupied(intptr_t index) const {
ASSERT(!IsNull());
const intptr_t cache_index =
- kHeaderSize + index * kTestEntryLength + kInstanceCidOrSignature;
+ index * kTestEntryLength + kInstanceCidOrSignature;
NoSafepointScope no_safepoint;
return cache()->untag()->element<std::memory_order_acquire>(cache_index) !=
Object::null();
@@ -19935,10 +19920,13 @@
intptr_t SubtypeTestCache::UsedInputsForType(const AbstractType& type) {
if (type.IsType()) {
- return type.IsInstantiated() ? 3 : 5;
+ return type.IsInstantiated() ? 2 : 4;
}
- // Default to the max number of inputs for other cases.
- return kMaxInputs;
+ // Default to all inputs except for the destination type, which must be
+ // statically known, otherwise this method wouldn't be called.
+ static_assert(kDestinationType == kMaxInputs - 1,
+ "destination type is not last input");
+ return kMaxInputs - 1;
}
const char* SubtypeTestCache::ToCString() const {
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 7c04cf1..12827cb 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -7406,9 +7406,8 @@
class SubtypeTestCache : public Object {
public:
- // The contents of the backing array storage is a header followed by
- // a number of entry tuples. Any entry that is unoccupied has the null value
- // as its first component.
+ // The contents of the backing array storage is a number of entry tuples.
+ // Any entry that is unoccupied has the null value as its first component.
//
// If the cache is linear, the entries can be accessed in a linear fashion:
// all occupied entries come first, followed by at least one unoccupied
@@ -7419,16 +7418,6 @@
// If the cache is hash-based, the array is instead treated as a hash table
// probed by using a hash value derived from the inputs.
- enum Header {
- // The number of occupied entries in the cache as a Smi.
- //
- // Note: accesses outside of the subtype test cache mutex must have acquire
- // semantics. In C++ code, use NumOccupied to retrieve the number of
- // occupied entries.
- kNumOccupiedIndex = 0,
- kHeaderSize,
- };
-
// The tuple of values stored in a given entry.
//
// Note that occupied entry contents are never modified. That means reading a
@@ -7442,19 +7431,19 @@
// stored in the instantiator type arguments slot.
enum Entries {
kInstanceCidOrSignature = 0,
- kDestinationType = 1,
- kInstanceTypeArguments = 2,
- kInstantiatorTypeArguments = 3,
- kFunctionTypeArguments = 4,
- kInstanceParentFunctionTypeArguments = 5,
- kInstanceDelayedFunctionTypeArguments = 6,
+ kInstanceTypeArguments = 1,
+ kInstantiatorTypeArguments = 2,
+ kFunctionTypeArguments = 3,
+ kInstanceParentFunctionTypeArguments = 4,
+ kInstanceDelayedFunctionTypeArguments = 5,
+ kDestinationType = 6,
kTestResult = 7,
kTestEntryLength = 8,
};
// Assumes only one non-input entry in the array, kTestResult.
static_assert(kInstanceCidOrSignature == 0 &&
- kInstanceDelayedFunctionTypeArguments + 1 == kTestResult &&
+ kDestinationType + 1 == kTestResult &&
kTestResult + 1 == kTestEntryLength,
"Need to adjust number of max inputs");
static constexpr intptr_t kMaxInputs = kTestResult;
@@ -7576,6 +7565,8 @@
}
intptr_t num_inputs() const { return untag()->num_inputs_; }
+ intptr_t num_occupied() const { return untag()->num_occupied_; }
+
// The maximum number of occupied entries for a linear subtype test cache
// before swapping to a hash table-based cache. Exposed publicly for tests.
#if defined(TARGET_ARCH_IA32)
@@ -7600,10 +7591,6 @@
return occupied / static_cast<double>(capacity);
}
- // Retrieves the number of occupied entries in a cache backed by the given
- // array.
- static intptr_t NumberOfChecks(const Array& array);
-
// Retrieves the number of entries (occupied or unoccupied) in a cache
// backed by the given array.
static intptr_t NumEntries(const Array& array);
@@ -7655,7 +7642,7 @@
// The maximum size of the array backing a linear cache. All hash based
// caches are guaranteed to have sizes larger than this.
static constexpr intptr_t kMaxLinearCacheSize =
- kHeaderSize + (kMaxLinearCacheEntries + 1) * kTestEntryLength;
+ (kMaxLinearCacheEntries + 1) * kTestEntryLength;
private:
// The initial number of entries used when converting from a linear to
@@ -7669,6 +7656,7 @@
static constexpr double kMaxLoadFactor = 0.71;
void set_cache(const Array& value) const;
+ void set_num_occupied(intptr_t value) const;
// Like GetCurrentCheck, but takes the backing storage array.
static void GetCheckFromArray(
@@ -13454,14 +13442,13 @@
using SubtypeTestCacheTable = ArrayOfTuplesView<SubtypeTestCache::Entries,
std::tuple<Object,
+ TypeArguments,
+ TypeArguments,
+ TypeArguments,
+ TypeArguments,
+ TypeArguments,
AbstractType,
- TypeArguments,
- TypeArguments,
- TypeArguments,
- TypeArguments,
- TypeArguments,
- Bool>,
- SubtypeTestCache::kHeaderSize>;
+ Bool>>;
using MegamorphicCacheEntries =
ArrayOfTuplesView<MegamorphicCache::EntryType, std::tuple<Smi, Object>>;
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index ee18c81..5674458 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -8407,8 +8407,7 @@
const auto& array = Array::Handle(zone, cache.cache());
for (intptr_t i = 0; i < cache.NumEntries(); i++) {
if (!cache.IsOccupied(i)) continue;
- const intptr_t entry_start =
- SubtypeTestCache::kHeaderSize + i * SubtypeTestCache::kTestEntryLength;
+ const intptr_t entry_start = i * SubtypeTestCache::kTestEntryLength;
{
const intptr_t cid =
array.At(entry_start + SubtypeTestCache::kTestResult)
@@ -8432,6 +8431,9 @@
}
switch (used_inputs) {
+ USED_INPUT_CASE(SubtypeTestCache::kDestinationType,
+ IsConcreteTypeClassId(cid));
+ FALL_THROUGH;
USED_INPUT_CASE(SubtypeTestCache::kInstanceDelayedFunctionTypeArguments,
cid == kNullCid || cid == kTypeArgumentsCid);
FALL_THROUGH;
@@ -8447,9 +8449,6 @@
USED_INPUT_CASE(SubtypeTestCache::kInstanceTypeArguments,
cid == kNullCid || cid == kTypeArgumentsCid);
FALL_THROUGH;
- USED_INPUT_CASE(SubtypeTestCache::kDestinationType,
- IsConcreteTypeClassId(cid));
- FALL_THROUGH;
USED_INPUT_CASE(SubtypeTestCache::kInstanceCidOrSignature,
cid == kSmiCid || cid == kFunctionTypeCid);
break;
@@ -8512,6 +8511,23 @@
delayed_type_arguments, &got_index, got_result));
EXPECT_EQ(expected_index, got_index);
EXPECT(got_result->ptr() == expected_result.ptr());
+ if (num_inputs < (SubtypeTestCache::kInstanceTypeArguments + 1)) {
+ // Match replacing unused instance type arguments with null.
+ EXPECT(cache.HasCheck(instance_class_id_or_signature, destination_type,
+ tav_null, instantiator_type_arguments,
+ function_type_arguments,
+ parent_function_type_arguments,
+ delayed_type_arguments, &got_index, got_result));
+ EXPECT_EQ(expected_index, got_index);
+ EXPECT(got_result->ptr() == expected_result.ptr());
+ } else {
+ // No match replacing used instance type arguments with null.
+ EXPECT(!cache.HasCheck(
+ instance_class_id_or_signature, destination_type, tav_null,
+ instantiator_type_arguments, function_type_arguments,
+ parent_function_type_arguments, delayed_type_arguments,
+ /*index=*/nullptr, /*result=*/nullptr));
+ }
if (num_inputs < (SubtypeTestCache::kInstantiatorTypeArguments + 1)) {
// Match replacing unused instantiator type arguments with null.
EXPECT(cache.HasCheck(instance_class_id_or_signature, destination_type,
@@ -8580,6 +8596,26 @@
parent_function_type_arguments, tav_null,
/*index=*/nullptr, /*result=*/nullptr));
}
+ // Make sure we're not accidentally using the same type as the input below.
+ RELEASE_ASSERT(destination_type.ptr() != Type::VoidType());
+ if (num_inputs < (SubtypeTestCache::kDestinationType + 1)) {
+ // Match replacing unused destination type argument with the null type.
+ EXPECT(cache.HasCheck(instance_class_id_or_signature, Object::void_type(),
+ instance_type_arguments, instantiator_type_arguments,
+ function_type_arguments,
+ parent_function_type_arguments,
+ delayed_type_arguments, &got_index, got_result));
+ EXPECT_EQ(expected_index, got_index);
+ EXPECT(got_result->ptr() == expected_result.ptr());
+ } else {
+ // No match replacing used destination type argument with the null type.
+ EXPECT(!cache.HasCheck(instance_class_id_or_signature, Object::void_type(),
+ instance_type_arguments, instantiator_type_arguments,
+ function_type_arguments,
+ parent_function_type_arguments,
+ delayed_type_arguments,
+ /*index=*/nullptr, /*result=*/nullptr));
+ }
// Once hash-based, should stay a hash-based cache.
EXPECT(!was_hash || cache.IsHash());
}
@@ -8588,18 +8624,18 @@
intptr_t num_classes,
bool expect_hash) {
TextBuffer buffer(MB);
- buffer.AddString("class D<S> {}\n");
- buffer.AddString("D<int> createInstanceD() => D<int>();");
- buffer.AddString("D<int> Function() createClosureD() => () => D<int>();\n");
+ buffer.AddString("class D {}\n");
+ buffer.AddString("D createInstanceD() => D();");
+ buffer.AddString("D Function() createClosureD() => () => D();\n");
for (intptr_t i = 0; i < num_classes; i++) {
- buffer.Printf(R"(class C%)" Pd R"(<S> extends D<S> {}
+ buffer.Printf(R"(class C%)" Pd R"( extends D {}
)"
- R"(C%)" Pd R"(<int> createInstanceC%)" Pd R"(() => C%)" Pd
- R"(<int>();
+ R"(C%)" Pd R"( createInstanceC%)" Pd R"(() => C%)" Pd
+ R"(();
)"
- R"(C%)" Pd R"(<int> Function() createClosureC%)" Pd
+ R"(C%)" Pd R"( Function() createClosureC%)" Pd
R"(() => () => C%)" Pd
- R"(<int>();
+ R"(();
)",
i, i, i, i, i, i, i);
}
@@ -8633,9 +8669,11 @@
auto& type_closure_d_int =
FunctionType::CheckedHandle(zone, closure_d.GetType(Heap::kNew));
- const auto& stc3 = SubtypeTestCache::Handle(zone, SubtypeTestCache::New(3));
- const auto& stc5 = SubtypeTestCache::Handle(zone, SubtypeTestCache::New(5));
- const auto& stc7 = SubtypeTestCache::Handle(zone, SubtypeTestCache::New(7));
+ // Test all the possible input values.
+ const SubtypeTestCache* stcs[SubtypeTestCache::kMaxInputs];
+ for (intptr_t i = 0; i < SubtypeTestCache::kMaxInputs; i++) {
+ stcs[i] = &SubtypeTestCache::Handle(zone, SubtypeTestCache::New(i + 1));
+ }
auto& class_c = Class::Handle(zone);
auto& instance_c = Instance::Handle(zone);
@@ -8684,17 +8722,13 @@
EXPECT(!instance_c.IsClosure());
instance_class_id_or_signature = Smi::New(instance_c.GetClassId());
- SubtypeTestCacheEntryTest(
- thread, stc3, instance_class_id_or_signature, type_instance_d_int,
- instance_type_arguments, instantiator_type_arguments,
- function_type_arguments, parent_function_type_arguments,
- delayed_type_arguments, expected_result, &got_result);
-
- SubtypeTestCacheEntryTest(
- thread, stc5, instance_class_id_or_signature, type_instance_d_int,
- instance_type_arguments, instantiator_type_arguments,
- function_type_arguments, parent_function_type_arguments,
- delayed_type_arguments, expected_result, &got_result);
+ for (intptr_t i = 0; i < 5; i++) {
+ SubtypeTestCacheEntryTest(
+ thread, *stcs[i], instance_class_id_or_signature, type_instance_d_int,
+ instance_type_arguments, instantiator_type_arguments,
+ function_type_arguments, parent_function_type_arguments,
+ delayed_type_arguments, expected_result, &got_result);
+ }
auto const function_name = OS::SCreate(zone, "createClosureC%" Pd "", i);
closure_c ^= Invoke(root_lib, function_name);
@@ -8703,18 +8737,18 @@
instance_class_id_or_signature =
Function::Cast(instance_class_id_or_signature).signature();
- SubtypeTestCacheEntryTest(
- thread, stc7, instance_class_id_or_signature, type_closure_d_int,
- instance_type_arguments, instantiator_type_arguments,
- function_type_arguments, parent_function_type_arguments,
- delayed_type_arguments, expected_result, &got_result);
+ for (intptr_t i = 5; i < SubtypeTestCache::kMaxInputs; i++) {
+ SubtypeTestCacheEntryTest(
+ thread, *stcs[i], instance_class_id_or_signature, type_closure_d_int,
+ instance_type_arguments, instantiator_type_arguments,
+ function_type_arguments, parent_function_type_arguments,
+ delayed_type_arguments, expected_result, &got_result);
+ }
}
- SubtypeTestCacheCheckContents(zone, stc3);
- SubtypeTestCacheCheckContents(zone, stc5);
- SubtypeTestCacheCheckContents(zone, stc7);
- EXPECT_EQ(expect_hash, stc3.IsHash());
- EXPECT_EQ(expect_hash, stc5.IsHash());
- EXPECT_EQ(expect_hash, stc7.IsHash());
+ for (intptr_t i = 0; i < SubtypeTestCache::kMaxInputs; i++) {
+ SubtypeTestCacheCheckContents(zone, *stcs[i]);
+ EXPECT_EQ(expect_hash, stcs[i]->IsHash());
+ }
}
TEST_CASE(STC_LinearLookup) {
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 275c8a8..ec6b79b 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -2498,6 +2498,7 @@
VISIT_FROM(cache)
VISIT_TO(cache)
uint32_t num_inputs_;
+ uint32_t num_occupied_;
};
class UntaggedLoadingUnit : public UntaggedObject {
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 988e155..6177c5c 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -986,12 +986,12 @@
" raw entry: [ %#" Px ", %#" Px ", %#" Px ", %#" Px ", %#" Px
", %#" Px ", %#" Px ", %#" Px " ]\n",
static_cast<uword>(instance_class_id_or_signature.ptr()),
- static_cast<uword>(destination_type.ptr()),
static_cast<uword>(instance_type_arguments.ptr()),
static_cast<uword>(instantiator_type_arguments.ptr()),
static_cast<uword>(function_type_arguments.ptr()),
static_cast<uword>(instance_parent_function_type_arguments.ptr()),
static_cast<uword>(instance_delayed_type_arguments.ptr()),
+ static_cast<uword>(destination_type.ptr()),
static_cast<uword>(result.ptr()));
THR_Print("%s", buffer.buffer());
}
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index 127cdd4..95c01d7 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -67,10 +67,12 @@
switch (i) {
case 1:
return StubCode::Subtype1TestCache();
- case 3:
- return StubCode::Subtype3TestCache();
- case 5:
- return StubCode::Subtype5TestCache();
+ case 2:
+ return StubCode::Subtype2TestCache();
+ case 4:
+ return StubCode::Subtype4TestCache();
+ case 6:
+ return StubCode::Subtype6TestCache();
case 7:
return StubCode::Subtype7TestCache();
default:
diff --git a/runtime/vm/stub_code_list.h b/runtime/vm/stub_code_list.h
index d56a3b2..fe906968 100644
--- a/runtime/vm/stub_code_list.h
+++ b/runtime/vm/stub_code_list.h
@@ -108,8 +108,9 @@
V(NullIsAssignableToType) \
V(NullIsAssignableToTypeNullSafe) \
V(Subtype1TestCache) \
- V(Subtype3TestCache) \
- V(Subtype5TestCache) \
+ V(Subtype2TestCache) \
+ V(Subtype4TestCache) \
+ V(Subtype6TestCache) \
V(Subtype7TestCache) \
VM_TYPE_TESTING_STUB_CODE_LIST(V) \
V(CallClosureNoSuchMethod) \