[VM/compiler] Cleanup ABIs for instantiation and type testing code and stubs.

Change-Id: Ifc211c98804fcaff5b7788f6823ea631d2867974
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/140441
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Régis Crelier <regis@google.com>
This commit is contained in:
Regis Crelier
2020-03-24 15:54:39 +00:00
committed by commit-bot@chromium.org
parent 6ce852bd89
commit 0bc8474383
16 changed files with 315 additions and 261 deletions
@@ -359,8 +359,7 @@ bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
const Class& type_class = Class::Handle(zone(), type.type_class());
ASSERT(type_class.NumTypeArguments() == 0);
const Register kInstanceReg = R0;
__ tst(kInstanceReg, compiler::Operand(kSmiTagMask));
__ tst(TypeTestABI::kInstanceReg, compiler::Operand(kSmiTagMask));
// If instance is Smi, check directly.
const Class& smi_class = Class::Handle(zone(), Smi::Class());
if (Class::IsSubtypeOf(smi_class, Object::null_type_arguments(), type,
@@ -371,7 +370,7 @@ bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
__ b(is_not_instance_lbl, EQ);
}
const Register kClassIdReg = R2;
__ LoadClassId(kClassIdReg, kInstanceReg);
__ LoadClassId(kClassIdReg, TypeTestABI::kInstanceReg);
// Bool interface can be implemented only by core class Bool.
if (type.IsBoolType()) {
__ CompareImmediate(kClassIdReg, kBoolCid);
@@ -460,7 +459,8 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest(
// Skip check if destination is a dynamic type.
if (type.IsTypeParameter()) {
const TypeParameter& type_param = TypeParameter::Cast(type);
static_assert(kFunctionTypeArgumentsReg < kInstantiatorTypeArgumentsReg,
static_assert(TypeTestABI::kFunctionTypeArgumentsReg <
TypeTestABI::kInstantiatorTypeArgumentsReg,
"Should be ordered to load arguments with one instruction");
__ ldm(IA, SP,
(1 << TypeTestABI::kFunctionTypeArgumentsReg) |
@@ -346,18 +346,17 @@ bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
const Class& type_class = Class::Handle(zone(), type.type_class());
ASSERT(type_class.NumTypeArguments() == 0);
const Register kInstanceReg = R0;
// If instance is Smi, check directly.
const Class& smi_class = Class::Handle(zone(), Smi::Class());
if (Class::IsSubtypeOf(smi_class, Object::null_type_arguments(), type,
Heap::kOld)) {
// Fast case for type = int/num/top-type.
__ BranchIfSmi(kInstanceReg, is_instance_lbl);
__ BranchIfSmi(TypeTestABI::kInstanceReg, is_instance_lbl);
} else {
__ BranchIfSmi(kInstanceReg, is_not_instance_lbl);
__ BranchIfSmi(TypeTestABI::kInstanceReg, is_not_instance_lbl);
}
const Register kClassIdReg = R2;
__ LoadClassId(kClassIdReg, kInstanceReg);
__ LoadClassId(kClassIdReg, TypeTestABI::kInstanceReg);
// Bool interface can be implemented only by core class Bool.
if (type.IsBoolType()) {
__ CompareImmediate(kClassIdReg, kBoolCid);
@@ -256,10 +256,9 @@ FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
ASSERT(!type.IsFunctionType());
const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
ASSERT(type_class.NumTypeArguments() > 0);
const Register kInstanceReg = EAX;
const Type& smi_type = Type::Handle(zone(), Type::SmiType());
const bool smi_is_ok = smi_type.IsSubtypeOf(type, Heap::kOld);
__ testl(kInstanceReg, compiler::Immediate(kSmiTagMask));
__ testl(TypeTestABI::kInstanceReg, compiler::Immediate(kSmiTagMask));
if (smi_is_ok) {
// Fast case for type = FutureOr<int/num/top-type>.
__ j(ZERO, is_instance_lbl);
@@ -276,7 +275,7 @@ FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
if (is_raw_type) {
const Register kClassIdReg = ECX;
// dynamic type argument, check only classes.
__ LoadClassId(kClassIdReg, kInstanceReg);
__ LoadClassId(kClassIdReg, TypeTestABI::kInstanceReg);
__ cmpl(kClassIdReg, compiler::Immediate(type_class.id()));
__ j(EQUAL, is_instance_lbl);
// List is a very common case.
@@ -300,10 +299,10 @@ FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
const Register kInstantiatorTypeArgumentsReg = kNoRegister;
const Register kFunctionTypeArgumentsReg = kNoRegister;
const Register kTempReg = EDI;
return GenerateCallSubtypeTestStub(kTestTypeTwoArgs, kInstanceReg,
kInstantiatorTypeArgumentsReg,
kFunctionTypeArgumentsReg, kTempReg,
is_instance_lbl, is_not_instance_lbl);
return GenerateCallSubtypeTestStub(
kTestTypeTwoArgs, TypeTestABI::kInstanceReg,
kInstantiatorTypeArgumentsReg, kFunctionTypeArgumentsReg, kTempReg,
is_instance_lbl, is_not_instance_lbl);
}
void FlowGraphCompiler::CheckClassIds(Register class_id_reg,
@@ -333,8 +332,7 @@ bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
const Class& type_class = Class::Handle(zone(), type.type_class());
ASSERT(type_class.NumTypeArguments() == 0);
const Register kInstanceReg = EAX;
__ testl(kInstanceReg, compiler::Immediate(kSmiTagMask));
__ testl(TypeTestABI::kInstanceReg, compiler::Immediate(kSmiTagMask));
// If instance is Smi, check directly.
const Class& smi_class = Class::Handle(zone(), Smi::Class());
if (Class::IsSubtypeOf(smi_class, Object::null_type_arguments(), type,
@@ -345,7 +343,7 @@ bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
__ j(ZERO, is_not_instance_lbl);
}
const Register kClassIdReg = ECX;
__ LoadClassId(kClassIdReg, kInstanceReg);
__ LoadClassId(kClassIdReg, TypeTestABI::kInstanceReg);
// Bool interface can be implemented only by core class Bool.
if (type.IsBoolType()) {
__ cmpl(kClassIdReg, compiler::Immediate(kBoolCid));
@@ -394,14 +392,13 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup(
compiler::Label* is_instance_lbl,
compiler::Label* is_not_instance_lbl) {
__ Comment("Subtype1TestCacheLookup");
const Register kInstanceReg = EAX;
#if defined(DEBUG)
compiler::Label ok;
__ BranchIfNotSmi(kInstanceReg, &ok);
__ BranchIfNotSmi(TypeTestABI::kInstanceReg, &ok);
__ Breakpoint();
__ Bind(&ok);
#endif
__ LoadClassId(EDI, kInstanceReg);
__ LoadClassId(EDI, TypeTestABI::kInstanceReg);
__ LoadClassById(ECX, EDI);
// ECX: instance class.
// Check immediate superclass equality.
@@ -413,7 +410,7 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup(
const Register kInstantiatorTypeArgumentsReg = kNoRegister;
const Register kFunctionTypeArgumentsReg = kNoRegister;
const Register kTempReg = EDI;
return GenerateCallSubtypeTestStub(kTestTypeOneArg, kInstanceReg,
return GenerateCallSubtypeTestStub(kTestTypeOneArg, TypeTestABI::kInstanceReg,
kInstantiatorTypeArgumentsReg,
kFunctionTypeArgumentsReg, kTempReg,
is_instance_lbl, is_not_instance_lbl);
@@ -428,7 +425,6 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest(
compiler::Label* is_instance_lbl,
compiler::Label* is_not_instance_lbl) {
__ Comment("UninstantiatedTypeTest");
const Register kInstanceReg = EAX;
const Register kTempReg = EDI;
ASSERT(!type.IsInstantiated());
ASSERT(!type.IsFunctionType());
@@ -444,9 +440,10 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest(
compiler::Address(ESP, 0 * kWordSize)); // Get function type args.
// EDX: instantiator type arguments.
// ECX: function type arguments.
const Register kTypeArgumentsReg = type_param.IsClassTypeParameter()
? kInstantiatorTypeArgumentsReg
: kFunctionTypeArgumentsReg;
const Register kTypeArgumentsReg =
type_param.IsClassTypeParameter()
? TypeTestABI::kInstantiatorTypeArgumentsReg
: TypeTestABI::kFunctionTypeArgumentsReg;
// Check if type arguments are null, i.e. equivalent to vector of dynamic.
__ cmpl(kTypeArgumentsReg, raw_null);
__ j(EQUAL, is_instance_lbl);
@@ -478,27 +475,30 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest(
const auto test_kind = GetTypeTestStubKindForTypeParameter(type_param);
const SubtypeTestCache& type_test_cache = SubtypeTestCache::ZoneHandle(
zone(), GenerateCallSubtypeTestStub(
test_kind, kInstanceReg, kInstantiatorTypeArgumentsReg,
kFunctionTypeArgumentsReg, kTempReg, is_instance_lbl,
is_not_instance_lbl));
test_kind, TypeTestABI::kInstanceReg,
TypeTestABI::kInstantiatorTypeArgumentsReg,
TypeTestABI::kFunctionTypeArgumentsReg, kTempReg,
is_instance_lbl, is_not_instance_lbl));
return type_test_cache.raw();
}
if (type.IsType()) {
// Smi is FutureOr<T>, when T is a top type or int or num.
if (!type.IsFutureOrType()) {
__ testl(kInstanceReg,
__ testl(TypeTestABI::kInstanceReg,
compiler::Immediate(kSmiTagMask)); // Is instance Smi?
__ j(ZERO, is_not_instance_lbl);
}
__ movl(kInstantiatorTypeArgumentsReg,
__ movl(TypeTestABI::kInstantiatorTypeArgumentsReg,
compiler::Address(ESP, 1 * kWordSize));
__ movl(kFunctionTypeArgumentsReg, compiler::Address(ESP, 0 * kWordSize));
__ movl(TypeTestABI::kFunctionTypeArgumentsReg,
compiler::Address(ESP, 0 * kWordSize));
// Uninstantiated type class is known at compile time, but the type
// arguments are determined at runtime by the instantiator(s).
return GenerateCallSubtypeTestStub(kTestTypeFourArgs, kInstanceReg,
kInstantiatorTypeArgumentsReg,
kFunctionTypeArgumentsReg, kTempReg,
is_instance_lbl, is_not_instance_lbl);
return GenerateCallSubtypeTestStub(
kTestTypeFourArgs, TypeTestABI::kInstanceReg,
TypeTestABI::kInstantiatorTypeArgumentsReg,
TypeTestABI::kFunctionTypeArgumentsReg, kTempReg, is_instance_lbl,
is_not_instance_lbl);
}
return SubtypeTestCache::null();
}
@@ -511,18 +511,18 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateFunctionTypeTest(
const AbstractType& type,
compiler::Label* is_instance_lbl,
compiler::Label* is_not_instance_lbl) {
const Register kInstanceReg = EAX;
__ Comment("FunctionTypeTest");
__ testl(kInstanceReg, compiler::Immediate(kSmiTagMask));
__ testl(TypeTestABI::kInstanceReg, compiler::Immediate(kSmiTagMask));
__ j(ZERO, is_not_instance_lbl);
// Uninstantiated type class is known at compile time, but the type
// arguments are determined at runtime by the instantiator(s).
const Register kTempReg = EDI;
return GenerateCallSubtypeTestStub(kTestTypeSixArgs, kInstanceReg,
kInstantiatorTypeArgumentsReg,
kFunctionTypeArgumentsReg, kTempReg,
is_instance_lbl, is_not_instance_lbl);
return GenerateCallSubtypeTestStub(
kTestTypeSixArgs, TypeTestABI::kInstanceReg,
TypeTestABI::kInstantiatorTypeArgumentsReg,
TypeTestABI::kFunctionTypeArgumentsReg, kTempReg, is_instance_lbl,
is_not_instance_lbl);
}
// Inputs:
@@ -628,8 +628,8 @@ void FlowGraphCompiler::GenerateInstanceOf(TokenPosition token_pos,
__ PushObject(Object::null_object()); // Make room for the result.
__ pushl(EAX); // Push the instance.
__ PushObject(type); // Push the type.
__ pushl(kInstantiatorTypeArgumentsReg);
__ pushl(kFunctionTypeArgumentsReg);
__ pushl(TypeTestABI::kInstantiatorTypeArgumentsReg);
__ pushl(TypeTestABI::kFunctionTypeArgumentsReg);
__ LoadObject(EAX, test_cache);
__ pushl(EAX);
GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
@@ -673,8 +673,8 @@ void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
// Assignable check is skipped in FlowGraphBuilder, not here.
ASSERT(!dst_type.IsTopTypeForAssignability());
__ pushl(kInstantiatorTypeArgumentsReg);
__ pushl(kFunctionTypeArgumentsReg);
__ pushl(TypeTestABI::kInstantiatorTypeArgumentsReg);
__ pushl(TypeTestABI::kFunctionTypeArgumentsReg);
compiler::Label is_assignable, runtime_call;
if (Instance::NullIsAssignableTo(dst_type)) {
@@ -691,15 +691,15 @@ void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
__ Bind(&runtime_call);
__ movl(
kInstantiatorTypeArgumentsReg,
TypeTestABI::kInstantiatorTypeArgumentsReg,
compiler::Address(ESP, 1 * kWordSize)); // Get instantiator type args.
__ movl(kFunctionTypeArgumentsReg,
__ movl(TypeTestABI::kFunctionTypeArgumentsReg,
compiler::Address(ESP, 0 * kWordSize)); // Get function type args.
__ PushObject(Object::null_object()); // Make room for the result.
__ pushl(EAX); // Push the source object.
__ PushObject(dst_type); // Push the type of the destination.
__ pushl(kInstantiatorTypeArgumentsReg);
__ pushl(kFunctionTypeArgumentsReg);
__ pushl(TypeTestABI::kInstantiatorTypeArgumentsReg);
__ pushl(TypeTestABI::kFunctionTypeArgumentsReg);
__ PushObject(dst_name); // Push the name of the destination.
__ LoadObject(EAX, test_cache);
__ pushl(EAX);
@@ -711,8 +711,8 @@ void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
__ popl(EAX);
__ Bind(&is_assignable);
__ popl(kFunctionTypeArgumentsReg);
__ popl(kInstantiatorTypeArgumentsReg);
__ popl(TypeTestABI::kFunctionTypeArgumentsReg);
__ popl(TypeTestABI::kInstantiatorTypeArgumentsReg);
}
void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) {
@@ -360,8 +360,7 @@ bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
const Class& type_class = Class::Handle(zone(), type.type_class());
ASSERT(type_class.NumTypeArguments() == 0);
const Register kInstanceReg = RAX;
__ testq(kInstanceReg, compiler::Immediate(kSmiTagMask));
__ testq(TypeTestABI::kInstanceReg, compiler::Immediate(kSmiTagMask));
// If instance is Smi, check directly.
const Class& smi_class = Class::Handle(zone(), Smi::Class());
if (Class::IsSubtypeOf(smi_class, Object::null_type_arguments(), type,
@@ -372,7 +371,7 @@ bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
__ j(ZERO, is_not_instance_lbl);
}
const Register kClassIdReg = R10;
__ LoadClassId(kClassIdReg, kInstanceReg);
__ LoadClassId(kClassIdReg, TypeTestABI::kInstanceReg);
// Bool interface can be implemented only by core class Bool.
if (type.IsBoolType()) {
__ cmpl(kClassIdReg, compiler::Immediate(kBoolCid));
+18 -10
View File
@@ -736,8 +736,8 @@ LocationSummary* AssertSubtypeInstr::MakeLocationSummary(Zone* zone,
const intptr_t kNumTemps = 0;
LocationSummary* summary = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
summary->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
summary->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
summary->set_in(0, Location::RegisterLocation(R2)); // Instant. type args.
summary->set_in(1, Location::RegisterLocation(R1)); // Function type args.
return summary;
}
@@ -3318,9 +3318,12 @@ LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone,
const intptr_t kNumTemps = 0;
LocationSummary* locs = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
locs->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
locs->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
locs->set_out(0, Location::RegisterLocation(R0));
locs->set_in(0, Location::RegisterLocation(
InstantiationABI::kInstantiatorTypeArgumentsReg));
locs->set_in(1, Location::RegisterLocation(
InstantiationABI::kFunctionTypeArgumentsReg));
locs->set_out(0,
Location::RegisterLocation(InstantiationABI::kResultTypeReg));
return locs;
}
@@ -3334,7 +3337,8 @@ void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
// A runtime call to instantiate the type is required.
__ PushObject(Object::null_object()); // Make room for the result.
__ PushObject(type());
static_assert(kFunctionTypeArgumentsReg < kInstantiatorTypeArgumentsReg,
static_assert(InstantiationABI::kFunctionTypeArgumentsReg <
InstantiationABI::kInstantiatorTypeArgumentsReg,
"Should be ordered to push arguments with one instruction");
__ PushList((1 << instantiator_type_args_reg) |
(1 << function_type_args_reg));
@@ -3351,9 +3355,12 @@ LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
const intptr_t kNumTemps = 0;
LocationSummary* locs = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
locs->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
locs->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
locs->set_out(0, Location::RegisterLocation(kResultTypeArgumentsReg));
locs->set_in(0, Location::RegisterLocation(
InstantiationABI::kInstantiatorTypeArgumentsReg));
locs->set_in(1, Location::RegisterLocation(
InstantiationABI::kFunctionTypeArgumentsReg));
locs->set_out(
0, Location::RegisterLocation(InstantiationABI::kResultTypeArgumentsReg));
return locs;
}
@@ -3380,7 +3387,8 @@ void InstantiateTypeArgumentsInstr::EmitNativeCode(
__ b(&type_arguments_instantiated, EQ);
}
// Lookup cache in stub before calling runtime.
__ LoadObject(kUninstantiatedTypeArgumentsReg, type_arguments());
__ LoadObject(InstantiationABI::kUninstantiatedTypeArgumentsReg,
type_arguments());
compiler->GenerateCall(token_pos(), GetStub(), RawPcDescriptors::kOther,
locs());
__ Bind(&type_arguments_instantiated);
+16 -9
View File
@@ -627,8 +627,8 @@ LocationSummary* AssertSubtypeInstr::MakeLocationSummary(Zone* zone,
const intptr_t kNumTemps = 0;
LocationSummary* summary = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
summary->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
summary->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
summary->set_in(0, Location::RegisterLocation(R2)); // Instant. type args.
summary->set_in(1, Location::RegisterLocation(R1)); // Function type args.
return summary;
}
@@ -2809,9 +2809,12 @@ LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone,
const intptr_t kNumTemps = 0;
LocationSummary* locs = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
locs->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
locs->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
locs->set_out(0, Location::RegisterLocation(R0));
locs->set_in(0, Location::RegisterLocation(
InstantiationABI::kInstantiatorTypeArgumentsReg));
locs->set_in(1, Location::RegisterLocation(
InstantiationABI::kFunctionTypeArgumentsReg));
locs->set_out(0,
Location::RegisterLocation(InstantiationABI::kResultTypeReg));
return locs;
}
@@ -2839,9 +2842,12 @@ LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
const intptr_t kNumTemps = 0;
LocationSummary* locs = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
locs->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
locs->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
locs->set_out(0, Location::RegisterLocation(kResultTypeArgumentsReg));
locs->set_in(0, Location::RegisterLocation(
InstantiationABI::kInstantiatorTypeArgumentsReg));
locs->set_in(1, Location::RegisterLocation(
InstantiationABI::kFunctionTypeArgumentsReg));
locs->set_out(
0, Location::RegisterLocation(InstantiationABI::kResultTypeArgumentsReg));
return locs;
}
@@ -2871,7 +2877,8 @@ void InstantiateTypeArgumentsInstr::EmitNativeCode(
__ Bind(&non_null_type_args);
}
// Lookup cache in stub before calling runtime.
__ LoadObject(kUninstantiatedTypeArgumentsReg, type_arguments());
__ LoadObject(InstantiationABI::kUninstantiatedTypeArgumentsReg,
type_arguments());
compiler->GenerateCall(token_pos(), GetStub(), RawPcDescriptors::kOther,
locs());
__ Bind(&type_arguments_instantiated);
+29 -17
View File
@@ -368,8 +368,10 @@ LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
LocationSummary* summary = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
summary->set_in(0, Location::RegisterLocation(EAX)); // Value.
summary->set_in(1, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
summary->set_in(2, Location::RegisterLocation(kFunctionTypeArgumentsReg));
summary->set_in(1, Location::RegisterLocation(
TypeTestABI::kInstantiatorTypeArgumentsReg));
summary->set_in(
2, Location::RegisterLocation(TypeTestABI::kFunctionTypeArgumentsReg));
summary->set_out(0, Location::RegisterLocation(EAX));
return summary;
}
@@ -380,8 +382,8 @@ LocationSummary* AssertSubtypeInstr::MakeLocationSummary(Zone* zone,
const intptr_t kNumTemps = 0;
LocationSummary* summary = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
summary->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
summary->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
summary->set_in(0, Location::RegisterLocation(EDX)); // Instant. type args.
summary->set_in(1, Location::RegisterLocation(ECX)); // Function type args.
return summary;
}
@@ -2229,17 +2231,20 @@ LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone,
const intptr_t kNumTemps = 0;
LocationSummary* summary = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
summary->set_in(0, Location::RegisterLocation(EAX)); // Instance.
summary->set_in(1, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
summary->set_in(2, Location::RegisterLocation(kFunctionTypeArgumentsReg));
summary->set_in(0, Location::RegisterLocation(TypeTestABI::kInstanceReg));
summary->set_in(1, Location::RegisterLocation(
TypeTestABI::kInstantiatorTypeArgumentsReg));
summary->set_in(
2, Location::RegisterLocation(TypeTestABI::kFunctionTypeArgumentsReg));
summary->set_out(0, Location::RegisterLocation(EAX));
return summary;
}
void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(locs()->in(0).reg() == EAX); // Value.
ASSERT(locs()->in(1).reg() == kInstantiatorTypeArgumentsReg);
ASSERT(locs()->in(2).reg() == kFunctionTypeArgumentsReg);
ASSERT(locs()->in(0).reg() == TypeTestABI::kInstanceReg);
ASSERT(locs()->in(1).reg() == TypeTestABI::kInstantiatorTypeArgumentsReg);
ASSERT(locs()->in(2).reg() == TypeTestABI::kFunctionTypeArgumentsReg);
compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs());
ASSERT(locs()->out(0).reg() == EAX);
@@ -2488,9 +2493,12 @@ LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone,
const intptr_t kNumTemps = 0;
LocationSummary* locs = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
locs->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
locs->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
locs->set_out(0, Location::RegisterLocation(EAX));
locs->set_in(0, Location::RegisterLocation(
InstantiationABI::kInstantiatorTypeArgumentsReg));
locs->set_in(1, Location::RegisterLocation(
InstantiationABI::kFunctionTypeArgumentsReg));
locs->set_out(0,
Location::RegisterLocation(InstantiationABI::kResultTypeReg));
return locs;
}
@@ -2519,9 +2527,12 @@ LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
const intptr_t kNumTemps = 0;
LocationSummary* locs = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
locs->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
locs->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
locs->set_out(0, Location::RegisterLocation(kResultTypeArgumentsReg));
locs->set_in(0, Location::RegisterLocation(
InstantiationABI::kInstantiatorTypeArgumentsReg));
locs->set_in(1, Location::RegisterLocation(
InstantiationABI::kFunctionTypeArgumentsReg));
locs->set_out(
0, Location::RegisterLocation(InstantiationABI::kResultTypeArgumentsReg));
return locs;
}
@@ -2551,7 +2562,8 @@ void InstantiateTypeArgumentsInstr::EmitNativeCode(
__ Bind(&non_null_type_args);
}
// Lookup cache in stub before calling runtime.
__ LoadObject(kUninstantiatedTypeArgumentsReg, type_arguments());
__ LoadObject(InstantiationABI::kUninstantiatedTypeArgumentsReg,
type_arguments());
compiler->GenerateCall(token_pos(), GetStub(), RawPcDescriptors::kOther,
locs());
__ Bind(&type_arguments_instantiated);
+18 -11
View File
@@ -582,8 +582,8 @@ LocationSummary* AssertSubtypeInstr::MakeLocationSummary(Zone* zone,
const intptr_t kNumTemps = 0;
LocationSummary* summary = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
summary->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
summary->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
summary->set_in(0, Location::RegisterLocation(RDX)); // Instant. type args.
summary->set_in(1, Location::RegisterLocation(RCX)); // Function type args.
return summary;
}
@@ -2505,8 +2505,8 @@ LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone,
void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(locs()->in(0).reg() == TypeTestABI::kInstanceReg);
ASSERT(locs()->in(1).reg() == kInstantiatorTypeArgumentsReg);
ASSERT(locs()->in(2).reg() == kFunctionTypeArgumentsReg);
ASSERT(locs()->in(1).reg() == TypeTestABI::kInstantiatorTypeArgumentsReg);
ASSERT(locs()->in(2).reg() == TypeTestABI::kFunctionTypeArgumentsReg);
compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs());
ASSERT(locs()->out(0).reg() == RAX);
@@ -2801,9 +2801,12 @@ LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone,
const intptr_t kNumTemps = 0;
LocationSummary* locs = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
locs->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
locs->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
locs->set_out(0, Location::RegisterLocation(RAX));
locs->set_in(0, Location::RegisterLocation(
InstantiationABI::kInstantiatorTypeArgumentsReg));
locs->set_in(1, Location::RegisterLocation(
InstantiationABI::kFunctionTypeArgumentsReg));
locs->set_out(0,
Location::RegisterLocation(InstantiationABI::kResultTypeReg));
return locs;
}
@@ -2832,9 +2835,12 @@ LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
const intptr_t kNumTemps = 0;
LocationSummary* locs = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
locs->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
locs->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
locs->set_out(0, Location::RegisterLocation(kResultTypeArgumentsReg));
locs->set_in(0, Location::RegisterLocation(
InstantiationABI::kInstantiatorTypeArgumentsReg));
locs->set_in(1, Location::RegisterLocation(
InstantiationABI::kFunctionTypeArgumentsReg));
locs->set_out(
0, Location::RegisterLocation(InstantiationABI::kResultTypeArgumentsReg));
return locs;
}
@@ -2863,7 +2869,8 @@ void InstantiateTypeArgumentsInstr::EmitNativeCode(
__ j(EQUAL, &type_arguments_instantiated, compiler::Assembler::kNearJump);
__ Bind(&non_null_type_args);
}
__ LoadObject(kUninstantiatedTypeArgumentsReg, type_arguments());
__ LoadObject(InstantiationABI::kUninstantiatedTypeArgumentsReg,
type_arguments());
compiler->GenerateCall(token_pos(), GetStub(), RawPcDescriptors::kOther,
locs());
__ Bind(&type_arguments_instantiated);
+38 -38
View File
@@ -2960,9 +2960,8 @@ void StubCodeCompiler::GenerateDefaultNullableTypeTestStub(
Assembler* assembler) {
Label done;
const Register kInstanceReg = R0;
// Fast case for 'null'.
__ CompareObject(kInstanceReg, NullObject());
__ CompareObject(TypeTestABI::kInstanceReg, NullObject());
__ BranchIf(EQUAL, &done);
__ ldr(CODE_REG, Address(THR, target::Thread::slow_type_test_stub_offset()));
@@ -3014,10 +3013,9 @@ void StubCodeCompiler::GenerateLazySpecializeTypeTestStub(
// Used instead of LazySpecializeTypeTestStub when null is assignable.
void StubCodeCompiler::GenerateLazySpecializeNullableTypeTestStub(
Assembler* assembler) {
const Register kInstanceReg = R0;
Label done;
__ CompareObject(kInstanceReg, NullObject());
__ CompareObject(TypeTestABI::kInstanceReg, NullObject());
__ BranchIf(EQUAL, &done);
__ ldr(CODE_REG,
@@ -3033,43 +3031,41 @@ void StubCodeCompiler::GenerateLazySpecializeNullableTypeTestStub(
void StubCodeCompiler::GenerateSlowTypeTestStub(Assembler* assembler) {
Label done, call_runtime;
const Register kInstanceReg = R0;
const Register kDstTypeReg = R8;
const Register kSubtypeTestCacheReg = R3;
__ EnterStubFrame();
// If the subtype-cache is null, it needs to be lazily-created by the runtime.
__ CompareObject(kSubtypeTestCacheReg, NullObject());
__ CompareObject(TypeTestABI::kSubtypeTestCacheReg, NullObject());
__ BranchIf(EQUAL, &call_runtime);
const Register kTmp = R9;
// If this is not a [Type] object, we'll go to the runtime.
Label is_simple_case, is_complex_case;
__ LoadClassId(kTmp, kDstTypeReg);
__ LoadClassId(kTmp, TypeTestABI::kDstTypeReg);
__ cmp(kTmp, Operand(kTypeCid));
__ BranchIf(NOT_EQUAL, &is_complex_case);
// Check whether this [Type] is instantiated/uninstantiated.
__ ldrb(kTmp, FieldAddress(kDstTypeReg, target::Type::type_state_offset()));
__ ldrb(kTmp, FieldAddress(TypeTestABI::kDstTypeReg,
target::Type::type_state_offset()));
__ cmp(kTmp,
Operand(target::RawAbstractType::kTypeStateFinalizedInstantiated));
__ BranchIf(NOT_EQUAL, &is_complex_case);
// Check whether this [Type] is a function type.
__ ldr(kTmp, FieldAddress(kDstTypeReg, target::Type::signature_offset()));
__ ldr(kTmp, FieldAddress(TypeTestABI::kDstTypeReg,
target::Type::signature_offset()));
__ CompareObject(kTmp, NullObject());
__ BranchIf(NOT_EQUAL, &is_complex_case);
// This [Type] could be a FutureOr. Subtype2TestCache does not support Smi.
__ BranchIfSmi(kInstanceReg, &is_complex_case);
__ BranchIfSmi(TypeTestABI::kInstanceReg, &is_complex_case);
// Fall through to &is_simple_case
const intptr_t kRegsToSave = (1 << kSubtypeTestCacheReg) |
(1 << kDstTypeReg) |
(1 << kFunctionTypeArgumentsReg);
const intptr_t kRegsToSave = (1 << TypeTestABI::kSubtypeTestCacheReg) |
(1 << TypeTestABI::kDstTypeReg) |
(1 << TypeTestABI::kFunctionTypeArgumentsReg);
__ Bind(&is_simple_case);
{
@@ -3565,7 +3561,7 @@ void StubCodeCompiler::GenerateInstantiateTypeArgumentsStub(
Assembler* assembler) {
// Lookup cache before calling runtime.
__ ldr(R0, compiler::FieldAddress(
kUninstantiatedTypeArgumentsReg,
InstantiationABI::kUninstantiatedTypeArgumentsReg,
target::TypeArguments::instantiations_offset()));
__ AddImmediate(R0, compiler::target::Array::data_offset() - kHeapObjectTag);
// The instantiations cache is initialized with Object::zero_array() and is
@@ -3575,13 +3571,14 @@ void StubCodeCompiler::GenerateInstantiateTypeArgumentsStub(
__ ldr(R4, compiler::Address(
R0, TypeArguments::Instantiation::kInstantiatorTypeArgsIndex *
target::kWordSize));
__ cmp(R4, compiler::Operand(kInstantiatorTypeArgumentsReg));
__ cmp(R4,
compiler::Operand(InstantiationABI::kInstantiatorTypeArgumentsReg));
__ b(&next, NE);
// Using IP as destination register and reading it immediately is safe.
__ ldr(IP, compiler::Address(
R0, TypeArguments::Instantiation::kFunctionTypeArgsIndex *
target::kWordSize));
__ cmp(IP, compiler::Operand(kFunctionTypeArgumentsReg));
__ cmp(IP, compiler::Operand(InstantiationABI::kFunctionTypeArgumentsReg));
__ b(&found, EQ);
__ Bind(&next);
__ AddImmediate(
@@ -3593,21 +3590,22 @@ void StubCodeCompiler::GenerateInstantiateTypeArgumentsStub(
// A runtime call to instantiate the type arguments is required.
__ EnterStubFrame();
__ PushObject(Object::null_object()); // Make room for the result.
static_assert(
(kUninstantiatedTypeArgumentsReg > kInstantiatorTypeArgumentsReg) &&
(kInstantiatorTypeArgumentsReg > kFunctionTypeArgumentsReg),
"Should be ordered to push arguments with one instruction");
__ PushList((1 << kUninstantiatedTypeArgumentsReg) |
(1 << kInstantiatorTypeArgumentsReg) |
(1 << kFunctionTypeArgumentsReg));
static_assert((InstantiationABI::kUninstantiatedTypeArgumentsReg >
InstantiationABI::kInstantiatorTypeArgumentsReg) &&
(InstantiationABI::kInstantiatorTypeArgumentsReg >
InstantiationABI::kFunctionTypeArgumentsReg),
"Should be ordered to push arguments with one instruction");
__ PushList((1 << InstantiationABI::kUninstantiatedTypeArgumentsReg) |
(1 << InstantiationABI::kInstantiatorTypeArgumentsReg) |
(1 << InstantiationABI::kFunctionTypeArgumentsReg));
__ CallRuntime(kInstantiateTypeArgumentsRuntimeEntry, 3);
__ Drop(3); // Drop 2 type vectors, and uninstantiated type.
__ Pop(kResultTypeArgumentsReg); // Pop instantiated type arguments.
__ Pop(InstantiationABI::kResultTypeArgumentsReg);
__ LeaveStubFrame();
__ Ret();
__ Bind(&found);
__ ldr(kResultTypeArgumentsReg,
__ ldr(InstantiationABI::kResultTypeArgumentsReg,
compiler::Address(
R0, TypeArguments::Instantiation::kInstantiatedTypeArgsIndex *
target::kWordSize));
@@ -3620,16 +3618,17 @@ void StubCodeCompiler::
// Return the instantiator type arguments if its nullability is compatible for
// sharing, otherwise proceed to instantiation cache lookup.
compiler::Label cache_lookup;
__ ldr(R0,
compiler::FieldAddress(kUninstantiatedTypeArgumentsReg,
target::TypeArguments::nullability_offset()));
__ ldr(R0, compiler::FieldAddress(
InstantiationABI::kUninstantiatedTypeArgumentsReg,
target::TypeArguments::nullability_offset()));
__ ldr(R4,
compiler::FieldAddress(kInstantiatorTypeArgumentsReg,
compiler::FieldAddress(InstantiationABI::kInstantiatorTypeArgumentsReg,
target::TypeArguments::nullability_offset()));
__ and_(R4, R4, Operand(R0));
__ cmp(R4, Operand(R0));
__ b(&cache_lookup, NE);
__ mov(kResultTypeArgumentsReg, Operand(kInstantiatorTypeArgumentsReg));
__ mov(InstantiationABI::kResultTypeArgumentsReg,
Operand(InstantiationABI::kInstantiatorTypeArgumentsReg));
__ Ret();
__ Bind(&cache_lookup);
@@ -3641,16 +3640,17 @@ void StubCodeCompiler::GenerateInstantiateTypeArgumentsMayShareFunctionTAStub(
// Return the function type arguments if its nullability is compatible for
// sharing, otherwise proceed to instantiation cache lookup.
compiler::Label cache_lookup;
__ ldr(R0,
compiler::FieldAddress(kUninstantiatedTypeArgumentsReg,
target::TypeArguments::nullability_offset()));
__ ldr(R0, compiler::FieldAddress(
InstantiationABI::kUninstantiatedTypeArgumentsReg,
target::TypeArguments::nullability_offset()));
__ ldr(R4,
compiler::FieldAddress(kFunctionTypeArgumentsReg,
compiler::FieldAddress(InstantiationABI::kFunctionTypeArgumentsReg,
target::TypeArguments::nullability_offset()));
__ and_(R4, R4, Operand(R0));
__ cmp(R4, Operand(R0));
__ b(&cache_lookup, NE);
__ mov(kResultTypeArgumentsReg, Operand(kFunctionTypeArgumentsReg));
__ mov(InstantiationABI::kResultTypeArgumentsReg,
Operand(InstantiationABI::kFunctionTypeArgumentsReg));
__ Ret();
__ Bind(&cache_lookup);
+35 -32
View File
@@ -3081,10 +3081,8 @@ void StubCodeCompiler::GenerateDefaultNullableTypeTestStub(
Assembler* assembler) {
Label done;
const Register kInstanceReg = R0;
// Fast case for 'null'.
__ CompareObject(kInstanceReg, NullObject());
__ CompareObject(TypeTestABI::kInstanceReg, NullObject());
__ BranchIf(EQUAL, &done);
// Tail call the [SubtypeTestCache]-based implementation.
@@ -3138,10 +3136,9 @@ void StubCodeCompiler::GenerateLazySpecializeTypeTestStub(
// Used instead of LazySpecializeTypeTestStub when null is assignable.
void StubCodeCompiler::GenerateLazySpecializeNullableTypeTestStub(
Assembler* assembler) {
const Register kInstanceReg = R0;
Label done;
__ CompareObject(kInstanceReg, NullObject());
__ CompareObject(TypeTestABI::kInstanceReg, NullObject());
__ BranchIf(EQUAL, &done);
__ ldr(CODE_REG,
@@ -3157,57 +3154,60 @@ void StubCodeCompiler::GenerateLazySpecializeNullableTypeTestStub(
void StubCodeCompiler::GenerateSlowTypeTestStub(Assembler* assembler) {
Label done, call_runtime;
const Register kInstanceReg = R0;
const Register kSubtypeTestCacheReg = R3;
const Register kDstTypeReg = R8;
__ EnterStubFrame();
// If the subtype-cache is null, it needs to be lazily-created by the runtime.
__ CompareObject(kSubtypeTestCacheReg, NullObject());
__ CompareObject(TypeTestABI::kSubtypeTestCacheReg, NullObject());
__ BranchIf(EQUAL, &call_runtime);
const Register kTmp = R9;
// If this is not a [Type] object, we'll go to the runtime.
Label is_simple_case, is_complex_case;
__ LoadClassId(kTmp, kDstTypeReg);
__ LoadClassId(kTmp, TypeTestABI::kDstTypeReg);
__ cmp(kTmp, Operand(kTypeCid));
__ BranchIf(NOT_EQUAL, &is_complex_case);
// Check whether this [Type] is instantiated/uninstantiated.
__ ldr(kTmp, FieldAddress(kDstTypeReg, target::Type::type_state_offset()),
kByte);
__ ldr(
kTmp,
FieldAddress(TypeTestABI::kDstTypeReg, target::Type::type_state_offset()),
kByte);
__ cmp(kTmp,
Operand(target::RawAbstractType::kTypeStateFinalizedInstantiated));
__ BranchIf(NOT_EQUAL, &is_complex_case);
// Check whether this [Type] is a function type.
__ ldr(kTmp, FieldAddress(kDstTypeReg, target::Type::signature_offset()));
__ ldr(kTmp, FieldAddress(TypeTestABI::kDstTypeReg,
target::Type::signature_offset()));
__ CompareObject(kTmp, NullObject());
__ BranchIf(NOT_EQUAL, &is_complex_case);
// This [Type] could be a FutureOr. Subtype2TestCache does not support Smi.
__ BranchIfSmi(kInstanceReg, &is_complex_case);
__ BranchIfSmi(TypeTestABI::kInstanceReg, &is_complex_case);
// Fall through to &is_simple_case
__ Bind(&is_simple_case);
{
__ PushPair(kFunctionTypeArgumentsReg, kSubtypeTestCacheReg);
__ PushPair(TypeTestABI::kFunctionTypeArgumentsReg,
TypeTestABI::kSubtypeTestCacheReg);
__ BranchLink(StubCodeSubtype2TestCache());
__ CompareObject(R1, CastHandle<Object>(TrueObject()));
__ PopPair(kFunctionTypeArgumentsReg, kSubtypeTestCacheReg);
__ PopPair(TypeTestABI::kFunctionTypeArgumentsReg,
TypeTestABI::kSubtypeTestCacheReg);
__ BranchIf(EQUAL, &done); // Cache said: yes.
__ Jump(&call_runtime);
}
__ Bind(&is_complex_case);
{
__ PushPair(kFunctionTypeArgumentsReg, kSubtypeTestCacheReg);
__ PushPair(TypeTestABI::kFunctionTypeArgumentsReg,
TypeTestABI::kSubtypeTestCacheReg);
__ BranchLink(StubCodeSubtype6TestCache());
__ CompareObject(R1, CastHandle<Object>(TrueObject()));
__ PopPair(kFunctionTypeArgumentsReg, kSubtypeTestCacheReg);
__ PopPair(TypeTestABI::kFunctionTypeArgumentsReg,
TypeTestABI::kSubtypeTestCacheReg);
__ BranchIf(EQUAL, &done); // Cache said: yes.
// Fall through to runtime_call
}
@@ -3685,7 +3685,7 @@ void StubCodeCompiler::GenerateAsynchronousGapMarkerStub(Assembler* assembler) {
void StubCodeCompiler::GenerateInstantiateTypeArgumentsStub(
Assembler* assembler) {
// Lookup cache before calling runtime.
__ LoadFieldFromOffset(R0, kUninstantiatedTypeArgumentsReg,
__ LoadFieldFromOffset(R0, InstantiationABI::kUninstantiatedTypeArgumentsReg,
target::TypeArguments::instantiations_offset());
__ AddImmediate(R0, Array::data_offset() - kHeapObjectTag);
// The instantiations cache is initialized with Object::zero_array() and is
@@ -3695,12 +3695,12 @@ void StubCodeCompiler::GenerateInstantiateTypeArgumentsStub(
__ LoadFromOffset(R5, R0,
TypeArguments::Instantiation::kInstantiatorTypeArgsIndex *
target::kWordSize);
__ CompareRegisters(R5, kInstantiatorTypeArgumentsReg);
__ CompareRegisters(R5, InstantiationABI::kInstantiatorTypeArgumentsReg);
__ b(&next, NE);
__ LoadFromOffset(
R4, R0,
TypeArguments::Instantiation::kFunctionTypeArgsIndex * target::kWordSize);
__ CompareRegisters(R4, kFunctionTypeArgumentsReg);
__ CompareRegisters(R4, InstantiationABI::kFunctionTypeArgumentsReg);
__ b(&found, EQ);
__ Bind(&next);
__ AddImmediate(
@@ -3711,16 +3711,17 @@ void StubCodeCompiler::GenerateInstantiateTypeArgumentsStub(
// Instantiate non-null type arguments.
// A runtime call to instantiate the type arguments is required.
__ EnterStubFrame();
__ PushPair(kUninstantiatedTypeArgumentsReg, NULL_REG);
__ PushPair(kFunctionTypeArgumentsReg, kInstantiatorTypeArgumentsReg);
__ PushPair(InstantiationABI::kUninstantiatedTypeArgumentsReg, NULL_REG);
__ PushPair(InstantiationABI::kFunctionTypeArgumentsReg,
InstantiationABI::kInstantiatorTypeArgumentsReg);
__ CallRuntime(kInstantiateTypeArgumentsRuntimeEntry, 3);
__ Drop(3); // Drop 2 type vectors, and uninstantiated type.
__ Pop(kResultTypeArgumentsReg); // Pop instantiated type arguments.
__ Pop(InstantiationABI::kResultTypeArgumentsReg);
__ LeaveStubFrame();
__ Ret();
__ Bind(&found);
__ LoadFromOffset(kResultTypeArgumentsReg, R0,
__ LoadFromOffset(InstantiationABI::kResultTypeArgumentsReg, R0,
TypeArguments::Instantiation::kInstantiatedTypeArgsIndex *
target::kWordSize);
__ Ret();
@@ -3732,14 +3733,15 @@ void StubCodeCompiler::
// Return the instantiator type arguments if its nullability is compatible for
// sharing, otherwise proceed to instantiation cache lookup.
compiler::Label cache_lookup;
__ LoadFieldFromOffset(R0, kUninstantiatedTypeArgumentsReg,
__ LoadFieldFromOffset(R0, InstantiationABI::kUninstantiatedTypeArgumentsReg,
target::TypeArguments::nullability_offset());
__ LoadFieldFromOffset(R4, kInstantiatorTypeArgumentsReg,
__ LoadFieldFromOffset(R4, InstantiationABI::kInstantiatorTypeArgumentsReg,
target::TypeArguments::nullability_offset());
__ and_(R4, R4, Operand(R0));
__ cmp(R4, Operand(R0));
__ b(&cache_lookup, NE);
__ mov(kResultTypeArgumentsReg, kInstantiatorTypeArgumentsReg);
__ mov(InstantiationABI::kResultTypeArgumentsReg,
InstantiationABI::kInstantiatorTypeArgumentsReg);
__ Ret();
__ Bind(&cache_lookup);
@@ -3751,14 +3753,15 @@ void StubCodeCompiler::GenerateInstantiateTypeArgumentsMayShareFunctionTAStub(
// Return the function type arguments if its nullability is compatible for
// sharing, otherwise proceed to instantiation cache lookup.
compiler::Label cache_lookup;
__ LoadFieldFromOffset(R0, kUninstantiatedTypeArgumentsReg,
__ LoadFieldFromOffset(R0, InstantiationABI::kUninstantiatedTypeArgumentsReg,
target::TypeArguments::nullability_offset());
__ LoadFieldFromOffset(R4, kFunctionTypeArgumentsReg,
__ LoadFieldFromOffset(R4, InstantiationABI::kFunctionTypeArgumentsReg,
target::TypeArguments::nullability_offset());
__ and_(R4, R4, Operand(R0));
__ cmp(R4, Operand(R0));
__ b(&cache_lookup, NE);
__ mov(kResultTypeArgumentsReg, kFunctionTypeArgumentsReg);
__ mov(InstantiationABI::kResultTypeArgumentsReg,
InstantiationABI::kFunctionTypeArgumentsReg);
__ Ret();
__ Bind(&cache_lookup);
+38 -35
View File
@@ -2385,14 +2385,12 @@ static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
static intptr_t kInstanceOffsetInBytes = 3 * target::kWordSize;
static intptr_t kCacheOffsetInBytes = 4 * target::kWordSize;
const Register kInstanceReg = EAX;
const Register kInstanceCidOrFunction = ECX;
const Register kInstanceInstantiatorTypeArgumentsReg = EBX;
const auto& raw_null = Immediate(target::ToRawPointer(NullObject()));
__ movl(kInstanceReg, Address(ESP, kInstanceOffsetInBytes));
__ movl(TypeTestABI::kInstanceReg, Address(ESP, kInstanceOffsetInBytes));
// Loop initialization (moved up here to avoid having all dependent loads
// after each other)
@@ -2402,9 +2400,9 @@ static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
Label loop, not_closure;
if (n >= 4) {
__ LoadClassIdMayBeSmi(kInstanceCidOrFunction, kInstanceReg);
__ LoadClassIdMayBeSmi(kInstanceCidOrFunction, TypeTestABI::kInstanceReg);
} else {
__ LoadClassId(kInstanceCidOrFunction, kInstanceReg);
__ LoadClassId(kInstanceCidOrFunction, TypeTestABI::kInstanceReg);
}
__ cmpl(kInstanceCidOrFunction, Immediate(kClosureCid));
__ j(NOT_EQUAL, &not_closure, Assembler::kNearJump);
@@ -2412,17 +2410,20 @@ static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
// Closure handling.
{
__ movl(kInstanceCidOrFunction,
FieldAddress(kInstanceReg, target::Closure::function_offset()));
FieldAddress(TypeTestABI::kInstanceReg,
target::Closure::function_offset()));
if (n >= 2) {
__ movl(
kInstanceInstantiatorTypeArgumentsReg,
FieldAddress(kInstanceReg,
FieldAddress(TypeTestABI::kInstanceReg,
target::Closure::instantiator_type_arguments_offset()));
if (n >= 6) {
__ pushl(FieldAddress(
kInstanceReg, target::Closure::delayed_type_arguments_offset()));
__ pushl(FieldAddress(
kInstanceReg, target::Closure::function_type_arguments_offset()));
__ pushl(
FieldAddress(TypeTestABI::kInstanceReg,
target::Closure::delayed_type_arguments_offset()));
__ pushl(
FieldAddress(TypeTestABI::kInstanceReg,
target::Closure::function_type_arguments_offset()));
}
}
__ jmp(&loop, Assembler::kNearJump);
@@ -2442,7 +2443,7 @@ static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
__ cmpl(EDI, Immediate(target::Class::kNoTypeArguments));
__ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump);
__ movl(kInstanceInstantiatorTypeArgumentsReg,
FieldAddress(kInstanceReg, EDI, TIMES_4, 0));
FieldAddress(TypeTestABI::kInstanceReg, EDI, TIMES_4, 0));
__ Bind(&has_no_type_arguments);
if (n >= 6) {
@@ -2915,9 +2916,9 @@ void StubCodeCompiler::GenerateAsynchronousGapMarkerStub(Assembler* assembler) {
void StubCodeCompiler::GenerateInstantiateTypeArgumentsStub(
Assembler* assembler) {
// Lookup cache before calling runtime.
__ pushl(kUninstantiatedTypeArgumentsReg); // Preserve reg.
__ pushl(InstantiationABI::kUninstantiatedTypeArgumentsReg); // Preserve reg.
__ movl(EAX, compiler::FieldAddress(
kUninstantiatedTypeArgumentsReg,
InstantiationABI::kUninstantiatedTypeArgumentsReg,
target::TypeArguments::instantiations_offset()));
__ leal(EAX, compiler::FieldAddress(EAX, Array::data_offset()));
// The instantiations cache is initialized with Object::zero_array() and is
@@ -2928,12 +2929,12 @@ void StubCodeCompiler::GenerateInstantiateTypeArgumentsStub(
compiler::Address(
EAX, TypeArguments::Instantiation::kInstantiatorTypeArgsIndex *
target::kWordSize));
__ cmpl(EDI, kInstantiatorTypeArgumentsReg);
__ cmpl(EDI, InstantiationABI::kInstantiatorTypeArgumentsReg);
__ j(NOT_EQUAL, &next, compiler::Assembler::kNearJump);
__ movl(EBX, compiler::Address(
EAX, TypeArguments::Instantiation::kFunctionTypeArgsIndex *
target::kWordSize));
__ cmpl(EBX, kFunctionTypeArgumentsReg);
__ cmpl(EBX, InstantiationABI::kFunctionTypeArgumentsReg);
__ j(EQUAL, &found, compiler::Assembler::kNearJump);
__ Bind(&next);
__ addl(EAX, compiler::Immediate(TypeArguments::Instantiation::kSizeInWords *
@@ -2944,21 +2945,21 @@ void StubCodeCompiler::GenerateInstantiateTypeArgumentsStub(
// Instantiate non-null type arguments.
// A runtime call to instantiate the type arguments is required.
__ popl(kUninstantiatedTypeArgumentsReg); // Restore reg.
__ popl(InstantiationABI::kUninstantiatedTypeArgumentsReg); // Restore reg.
__ EnterStubFrame();
__ PushObject(Object::null_object()); // Make room for the result.
__ pushl(kUninstantiatedTypeArgumentsReg);
__ pushl(kInstantiatorTypeArgumentsReg); // Push instantiator type arguments.
__ pushl(kFunctionTypeArgumentsReg); // Push function type arguments.
__ pushl(InstantiationABI::kUninstantiatedTypeArgumentsReg);
__ pushl(InstantiationABI::kInstantiatorTypeArgumentsReg);
__ pushl(InstantiationABI::kFunctionTypeArgumentsReg);
__ CallRuntime(kInstantiateTypeArgumentsRuntimeEntry, 3);
__ Drop(3); // Drop 2 type vectors, and uninstantiated args.
__ popl(kResultTypeArgumentsReg); // Pop instantiated type arguments.
__ popl(InstantiationABI::kResultTypeArgumentsReg);
__ LeaveFrame();
__ ret();
__ Bind(&found);
__ popl(kUninstantiatedTypeArgumentsReg); // Drop reg.
__ movl(kResultTypeArgumentsReg,
__ popl(InstantiationABI::kUninstantiatedTypeArgumentsReg); // Drop reg.
__ movl(InstantiationABI::kResultTypeArgumentsReg,
compiler::Address(
EAX, TypeArguments::Instantiation::kInstantiatedTypeArgsIndex *
target::kWordSize));
@@ -2971,16 +2972,17 @@ void StubCodeCompiler::
// Return the instantiator type arguments if its nullability is compatible for
// sharing, otherwise proceed to instantiation cache lookup.
compiler::Label cache_lookup;
__ movl(EAX,
compiler::FieldAddress(kUninstantiatedTypeArgumentsReg,
target::TypeArguments::nullability_offset()));
__ movl(EDI,
compiler::FieldAddress(kInstantiatorTypeArgumentsReg,
target::TypeArguments::nullability_offset()));
__ movl(EAX, compiler::FieldAddress(
InstantiationABI::kUninstantiatedTypeArgumentsReg,
target::TypeArguments::nullability_offset()));
__ movl(EDI, compiler::FieldAddress(
InstantiationABI::kInstantiatorTypeArgumentsReg,
target::TypeArguments::nullability_offset()));
__ andl(EDI, EAX);
__ cmpl(EDI, EAX);
__ j(NOT_EQUAL, &cache_lookup, compiler::Assembler::kNearJump);
__ movl(kResultTypeArgumentsReg, kInstantiatorTypeArgumentsReg);
__ movl(InstantiationABI::kResultTypeArgumentsReg,
InstantiationABI::kInstantiatorTypeArgumentsReg);
__ ret();
__ Bind(&cache_lookup);
@@ -2992,16 +2994,17 @@ void StubCodeCompiler::GenerateInstantiateTypeArgumentsMayShareFunctionTAStub(
// Return the function type arguments if its nullability is compatible for
// sharing, otherwise proceed to instantiation cache lookup.
compiler::Label cache_lookup;
__ movl(EAX,
compiler::FieldAddress(kUninstantiatedTypeArgumentsReg,
target::TypeArguments::nullability_offset()));
__ movl(EAX, compiler::FieldAddress(
InstantiationABI::kUninstantiatedTypeArgumentsReg,
target::TypeArguments::nullability_offset()));
__ movl(EDI,
compiler::FieldAddress(kFunctionTypeArgumentsReg,
compiler::FieldAddress(InstantiationABI::kFunctionTypeArgumentsReg,
target::TypeArguments::nullability_offset()));
__ andl(EDI, EAX);
__ cmpl(EDI, EAX);
__ j(NOT_EQUAL, &cache_lookup, compiler::Assembler::kNearJump);
__ movl(kResultTypeArgumentsReg, kFunctionTypeArgumentsReg);
__ movl(InstantiationABI::kResultTypeArgumentsReg,
InstantiationABI::kFunctionTypeArgumentsReg);
__ ret();
__ Bind(&cache_lookup);
+32 -36
View File
@@ -3030,10 +3030,8 @@ void StubCodeCompiler::GenerateDefaultNullableTypeTestStub(
Assembler* assembler) {
Label done;
const Register kInstanceReg = RAX;
// Fast case for 'null'.
__ CompareObject(kInstanceReg, NullObject());
__ CompareObject(TypeTestABI::kInstanceReg, NullObject());
__ BranchIf(EQUAL, &done);
__ movq(CODE_REG, Address(THR, target::Thread::slow_type_test_stub_offset()));
@@ -3086,12 +3084,10 @@ void StubCodeCompiler::GenerateLazySpecializeTypeTestStub(
// Used instead of LazySpecializeTypeTestStub when null is assignable.
void StubCodeCompiler::GenerateLazySpecializeNullableTypeTestStub(
Assembler* assembler) {
const Register kInstanceReg = RAX;
Label done;
// Fast case for 'null'.
__ CompareObject(kInstanceReg, NullObject());
__ CompareObject(TypeTestABI::kInstanceReg, NullObject());
__ BranchIf(EQUAL, &done);
__ movq(
@@ -3108,36 +3104,34 @@ void StubCodeCompiler::GenerateLazySpecializeNullableTypeTestStub(
void StubCodeCompiler::GenerateSlowTypeTestStub(Assembler* assembler) {
Label done, call_runtime;
const Register kInstanceReg = RAX;
const Register kDstTypeReg = RBX;
const Register kSubtypeTestCacheReg = R9;
__ EnterStubFrame();
// If the subtype-cache is null, it needs to be lazily-created by the runtime.
__ CompareObject(kSubtypeTestCacheReg, NullObject());
__ CompareObject(TypeTestABI::kSubtypeTestCacheReg, NullObject());
__ BranchIf(EQUAL, &call_runtime);
const Register kTmp = RDI;
// If this is not a [Type] object, we'll go to the runtime.
Label is_simple_case, is_complex_case;
__ LoadClassId(kTmp, kDstTypeReg);
__ LoadClassId(kTmp, TypeTestABI::kDstTypeReg);
__ cmpq(kTmp, Immediate(kTypeCid));
__ BranchIf(NOT_EQUAL, &is_complex_case);
// Check whether this [Type] is instantiated/uninstantiated.
__ cmpb(FieldAddress(kDstTypeReg, target::Type::type_state_offset()),
Immediate(target::RawAbstractType::kTypeStateFinalizedInstantiated));
__ cmpb(
FieldAddress(TypeTestABI::kDstTypeReg, target::Type::type_state_offset()),
Immediate(target::RawAbstractType::kTypeStateFinalizedInstantiated));
__ BranchIf(NOT_EQUAL, &is_complex_case);
// Check whether this [Type] is a function type.
__ movq(kTmp, FieldAddress(kDstTypeReg, target::Type::signature_offset()));
__ movq(kTmp, FieldAddress(TypeTestABI::kDstTypeReg,
target::Type::signature_offset()));
__ CompareObject(kTmp, NullObject());
__ BranchIf(NOT_EQUAL, &is_complex_case);
// This [Type] could be a FutureOr. Subtype2TestCache does not support Smi.
__ BranchIfSmi(kInstanceReg, &is_complex_case);
__ BranchIfSmi(TypeTestABI::kInstanceReg, &is_complex_case);
// Fall through to &is_simple_case
@@ -3622,7 +3616,7 @@ void StubCodeCompiler::GenerateInstantiateTypeArgumentsStub(
Assembler* assembler) {
// Lookup cache before calling runtime.
__ movq(RAX, compiler::FieldAddress(
kUninstantiatedTypeArgumentsReg,
InstantiationABI::kUninstantiatedTypeArgumentsReg,
target::TypeArguments::instantiations_offset()));
__ leaq(RAX, compiler::FieldAddress(RAX, Array::data_offset()));
// The instantiations cache is initialized with Object::zero_array() and is
@@ -3633,12 +3627,12 @@ void StubCodeCompiler::GenerateInstantiateTypeArgumentsStub(
compiler::Address(
RAX, TypeArguments::Instantiation::kInstantiatorTypeArgsIndex *
target::kWordSize));
__ cmpq(RDI, kInstantiatorTypeArgumentsReg);
__ cmpq(RDI, InstantiationABI::kInstantiatorTypeArgumentsReg);
__ j(NOT_EQUAL, &next, compiler::Assembler::kNearJump);
__ movq(R10, compiler::Address(
RAX, TypeArguments::Instantiation::kFunctionTypeArgsIndex *
target::kWordSize));
__ cmpq(R10, kFunctionTypeArgumentsReg);
__ cmpq(R10, InstantiationABI::kFunctionTypeArgumentsReg);
__ j(EQUAL, &found, compiler::Assembler::kNearJump);
__ Bind(&next);
__ addq(RAX, compiler::Immediate(TypeArguments::Instantiation::kSizeInWords *
@@ -3651,17 +3645,17 @@ void StubCodeCompiler::GenerateInstantiateTypeArgumentsStub(
// A runtime call to instantiate the type arguments is required.
__ EnterStubFrame();
__ PushObject(Object::null_object()); // Make room for the result.
__ pushq(kUninstantiatedTypeArgumentsReg);
__ pushq(kInstantiatorTypeArgumentsReg); // Push instantiator type arguments.
__ pushq(kFunctionTypeArgumentsReg); // Push function type arguments.
__ pushq(InstantiationABI::kUninstantiatedTypeArgumentsReg);
__ pushq(InstantiationABI::kInstantiatorTypeArgumentsReg);
__ pushq(InstantiationABI::kFunctionTypeArgumentsReg);
__ CallRuntime(kInstantiateTypeArgumentsRuntimeEntry, 3);
__ Drop(3); // Drop 2 type vectors, and uninstantiated type.
__ popq(kResultTypeArgumentsReg); // Pop instantiated type arguments.
__ popq(InstantiationABI::kResultTypeArgumentsReg);
__ LeaveStubFrame();
__ ret();
__ Bind(&found);
__ movq(kResultTypeArgumentsReg,
__ movq(InstantiationABI::kResultTypeArgumentsReg,
compiler::Address(
RAX, TypeArguments::Instantiation::kInstantiatedTypeArgsIndex *
target::kWordSize));
@@ -3674,16 +3668,17 @@ void StubCodeCompiler::
// Return the instantiator type arguments if its nullability is compatible for
// sharing, otherwise proceed to instantiation cache lookup.
compiler::Label cache_lookup;
__ movq(RAX,
compiler::FieldAddress(kUninstantiatedTypeArgumentsReg,
target::TypeArguments::nullability_offset()));
__ movq(RDI,
compiler::FieldAddress(kInstantiatorTypeArgumentsReg,
target::TypeArguments::nullability_offset()));
__ movq(RAX, compiler::FieldAddress(
InstantiationABI::kUninstantiatedTypeArgumentsReg,
target::TypeArguments::nullability_offset()));
__ movq(RDI, compiler::FieldAddress(
InstantiationABI::kInstantiatorTypeArgumentsReg,
target::TypeArguments::nullability_offset()));
__ andq(RDI, RAX);
__ cmpq(RDI, RAX);
__ j(NOT_EQUAL, &cache_lookup, compiler::Assembler::kNearJump);
__ movq(kResultTypeArgumentsReg, kInstantiatorTypeArgumentsReg);
__ movq(InstantiationABI::kResultTypeArgumentsReg,
InstantiationABI::kInstantiatorTypeArgumentsReg);
__ ret();
__ Bind(&cache_lookup);
@@ -3695,16 +3690,17 @@ void StubCodeCompiler::GenerateInstantiateTypeArgumentsMayShareFunctionTAStub(
// Return the function type arguments if its nullability is compatible for
// sharing, otherwise proceed to instantiation cache lookup.
compiler::Label cache_lookup;
__ movq(RAX,
compiler::FieldAddress(kUninstantiatedTypeArgumentsReg,
target::TypeArguments::nullability_offset()));
__ movq(RAX, compiler::FieldAddress(
InstantiationABI::kUninstantiatedTypeArgumentsReg,
target::TypeArguments::nullability_offset()));
__ movq(RDI,
compiler::FieldAddress(kFunctionTypeArgumentsReg,
compiler::FieldAddress(InstantiationABI::kFunctionTypeArgumentsReg,
target::TypeArguments::nullability_offset()));
__ andq(RDI, RAX);
__ cmpq(RDI, RAX);
__ j(NOT_EQUAL, &cache_lookup, compiler::Assembler::kNearJump);
__ movq(kResultTypeArgumentsReg, kFunctionTypeArgumentsReg);
__ movq(InstantiationABI::kResultTypeArgumentsReg,
InstantiationABI::kFunctionTypeArgumentsReg);
__ ret();
__ Bind(&cache_lookup);
+7 -4
View File
@@ -311,10 +311,13 @@ const Register kWriteBarrierSlotReg = R9;
const Register kAllocationStubTypeArgumentsReg = R3;
// ABI for instantiation stubs.
const Register kUninstantiatedTypeArgumentsReg = R3;
const Register kInstantiatorTypeArgumentsReg = R2;
const Register kFunctionTypeArgumentsReg = R1;
const Register kResultTypeArgumentsReg = R0;
struct InstantiationABI {
static const Register kUninstantiatedTypeArgumentsReg = R3;
static const Register kInstantiatorTypeArgumentsReg = R2;
static const Register kFunctionTypeArgumentsReg = R1;
static const Register kResultTypeArgumentsReg = R0;
static const Register kResultTypeReg = R0;
};
// Calling convention when calling TypeTestingStub and SubtypeTestCacheStub.
struct TypeTestABI {
+7 -4
View File
@@ -143,10 +143,13 @@ const Register kWriteBarrierSlotReg = R25;
const Register kAllocationStubTypeArgumentsReg = R1;
// ABI for instantiation stubs.
const Register kUninstantiatedTypeArgumentsReg = R3;
const Register kInstantiatorTypeArgumentsReg = R2;
const Register kFunctionTypeArgumentsReg = R1;
const Register kResultTypeArgumentsReg = R0;
struct InstantiationABI {
static const Register kUninstantiatedTypeArgumentsReg = R3;
static const Register kInstantiatorTypeArgumentsReg = R2;
static const Register kFunctionTypeArgumentsReg = R1;
static const Register kResultTypeArgumentsReg = R0;
static const Register kResultTypeReg = R0;
};
// Calling convention when calling TypeTestingStub and SubtypeTestCacheStub.
struct TypeTestABI {
+17 -6
View File
@@ -92,13 +92,24 @@ const Register kWriteBarrierSlotReg = EDI;
const Register kAllocationStubTypeArgumentsReg = EDX;
// ABI for instantiation stubs.
const Register kUninstantiatedTypeArgumentsReg = EBX;
const Register kInstantiatorTypeArgumentsReg = EDX;
const Register kFunctionTypeArgumentsReg = ECX;
const Register kResultTypeArgumentsReg = EAX;
struct InstantiationABI {
static const Register kUninstantiatedTypeArgumentsReg = EBX;
static const Register kInstantiatorTypeArgumentsReg = EDX;
static const Register kFunctionTypeArgumentsReg = ECX;
static const Register kResultTypeArgumentsReg = EAX;
static const Register kResultTypeReg = EAX;
};
// TODO(regis): Add ABIs for type testing stubs and is-type test stubs instead
// of reusing the constants of the instantiation stubs ABI.
// Calling convention when calling SubtypeTestCacheStub.
// Although ia32 uses a stack-based calling convention, we keep the same
// 'TypeTestABI' name for symmetry with other architectures with a proper ABI.
// Note that ia32 has no support for type testing stubs.
struct TypeTestABI {
static const Register kInstanceReg = EAX;
static const Register kDstTypeReg = EBX;
static const Register kInstantiatorTypeArgumentsReg = EDX;
static const Register kFunctionTypeArgumentsReg = ECX;
};
typedef uint32_t RegList;
const RegList kAllCpuRegistersList = 0xFF;
+7 -4
View File
@@ -133,10 +133,13 @@ const Register kWriteBarrierSlotReg = R13;
const Register kAllocationStubTypeArgumentsReg = RDX;
// ABI for instantiation stubs.
const Register kUninstantiatedTypeArgumentsReg = RBX;
const Register kInstantiatorTypeArgumentsReg = RDX;
const Register kFunctionTypeArgumentsReg = RCX;
const Register kResultTypeArgumentsReg = RAX;
struct InstantiationABI {
static const Register kUninstantiatedTypeArgumentsReg = RBX;
static const Register kInstantiatorTypeArgumentsReg = RDX;
static const Register kFunctionTypeArgumentsReg = RCX;
static const Register kResultTypeArgumentsReg = RAX;
static const Register kResultTypeReg = RAX;
};
// Calling convention when calling TypeTestingStub and SubtypeTestCacheStub.
struct TypeTestABI {