Index: runtime/vm/flow_graph_compiler_arm.cc |
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc |
index ab827c7f88d0433f06d150eeb543fd28218da04a..047c40b6278680c2f72bb32ea8aaa350f1070350 100644 |
--- a/runtime/vm/flow_graph_compiler_arm.cc |
+++ b/runtime/vm/flow_graph_compiler_arm.cc |
@@ -208,8 +208,8 @@ void FlowGraphCompiler::GenerateBoolToJump(Register bool_register, |
// R0: instance (must be preserved). |
-// R1: instantiator type arguments (if used). |
-// R2: function type arguments (if used). |
+// R2: instantiator type arguments (if used). |
+// R1: function type arguments (if used). |
// R3: type test cache. |
RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub( |
TypeTestStubKind test_kind, |
@@ -233,8 +233,8 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub( |
ASSERT(function_type_arguments_reg == kNoRegister); |
__ BranchLink(*StubCode::Subtype2TestCache_entry()); |
} else if (test_kind == kTestTypeFourArgs) { |
- ASSERT(instantiator_type_arguments_reg == R1); |
- ASSERT(function_type_arguments_reg == R2); |
+ ASSERT(instantiator_type_arguments_reg == R2); |
+ ASSERT(function_type_arguments_reg == R1); |
__ BranchLink(*StubCode::Subtype4TestCache_entry()); |
} else { |
UNREACHABLE(); |
@@ -448,13 +448,14 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( |
// Skip check if destination is a dynamic type. |
if (type.IsTypeParameter()) { |
const TypeParameter& type_param = TypeParameter::Cast(type); |
- __ ldr(R1, Address(SP, 1 * kWordSize)); // Get instantiator type args. |
- __ ldr(R2, Address(SP, 0 * kWordSize)); // Get function type args. |
- // TODO(regis): Renumber registers and use ldm. |
- // R1: instantiator type arguments. |
- // R2: function type arguments. |
+ const Register kInstantiatorTypeArgumentsReg = R2; |
+ const Register kFunctionTypeArgumentsReg = R1; |
+ __ ldm(IA, SP, (1 << kFunctionTypeArgumentsReg) | |
+ (1 << kInstantiatorTypeArgumentsReg)); |
+ // R2: instantiator type arguments. |
+ // R1: function type arguments. |
const Register kTypeArgumentsReg = |
- type_param.IsClassTypeParameter() ? R1 : R2; |
+ type_param.IsClassTypeParameter() ? R2 : R1; |
// Check if type arguments are null, i.e. equivalent to vector of dynamic. |
__ CompareObject(kTypeArgumentsReg, Object::null_object()); |
__ b(is_instance_lbl, EQ); |
@@ -482,11 +483,9 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( |
__ Bind(¬_smi); |
// R0: instance. |
- // R1: instantiator type arguments. |
- // R2: function type arguments. |
+ // R2: instantiator type arguments. |
+ // R1: function type arguments. |
const Register kInstanceReg = R0; |
- const Register kInstantiatorTypeArgumentsReg = R1; |
- const Register kFunctionTypeArgumentsReg = R2; |
const Register kTempReg = kNoRegister; |
const SubtypeTestCache& type_test_cache = SubtypeTestCache::ZoneHandle( |
zone(), GenerateCallSubtypeTestStub( |
@@ -498,13 +497,12 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( |
} |
if (type.IsType()) { |
const Register kInstanceReg = R0; |
- const Register kInstantiatorTypeArgumentsReg = R1; |
- const Register kFunctionTypeArgumentsReg = R2; |
+ const Register kInstantiatorTypeArgumentsReg = R2; |
+ const Register kFunctionTypeArgumentsReg = R1; |
__ tst(kInstanceReg, Operand(kSmiTagMask)); // Is instance Smi? |
__ b(is_not_instance_lbl, EQ); |
- __ ldr(kInstantiatorTypeArgumentsReg, Address(SP, 1 * kWordSize)); |
- __ ldr(kFunctionTypeArgumentsReg, Address(SP, 0 * kWordSize)); |
- // TODO(regis): Renumber registers and use ldm. |
+ __ ldm(IA, SP, (1 << kFunctionTypeArgumentsReg) | |
+ (1 << kInstantiatorTypeArgumentsReg)); |
// Uninstantiated type class is known at compile time, but the type |
// arguments are determined at runtime by the instantiator(s). |
const Register kTempReg = kNoRegister; |
@@ -519,12 +517,12 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( |
// Inputs: |
// - R0: instance being type checked (preserved). |
-// - R1: optional instantiator type arguments (preserved). |
-// - R2: optional function type arguments (preserved). |
+// - R2: optional instantiator type arguments (preserved). |
+// - R1: optional function type arguments (preserved). |
// Clobbers R3, R4, R8, R9. |
// Returns: |
-// - preserved instance in R0, optional instantiator type arguments in R1, and |
-// optional function type arguments in R2. |
+// - preserved instance in R0, optional instantiator type arguments in R2, and |
+// optional function type arguments in R1. |
// Note that this inlined code must be followed by the runtime_call code, as it |
// may fall through to it. Otherwise, this inline code will jump to the label |
// is_instance or to the label is_not_instance. |
@@ -572,8 +570,8 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof( |
// - Class equality (only if class is not parameterized). |
// Inputs: |
// - R0: object. |
-// - R1: instantiator type arguments or raw_null. |
-// - R2: function type arguments or raw_null. |
+// - R2: instantiator type arguments or raw_null. |
+// - R1: function type arguments or raw_null. |
// Returns: |
// - true or false in R0. |
void FlowGraphCompiler::GenerateInstanceOf(TokenPosition token_pos, |
@@ -582,11 +580,10 @@ void FlowGraphCompiler::GenerateInstanceOf(TokenPosition token_pos, |
LocationSummary* locs) { |
ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded()); |
ASSERT(!type.IsObjectType() && !type.IsDynamicType()); |
- |
- __ Push(R1); // Store instantiator type arguments. |
- __ Push(R2); // Store function type arguments. |
- // TODO(regis): Renumber registers and use PushList. |
- |
+ const Register kInstantiatorTypeArgumentsReg = R2; |
+ const Register kFunctionTypeArgumentsReg = R1; |
+ __ PushList((1 << kInstantiatorTypeArgumentsReg) | |
+ (1 << kFunctionTypeArgumentsReg)); |
Label is_instance, is_not_instance; |
// If type is instantiated and non-parameterized, we can inline code |
// checking whether the tested instance is a Smi. |
@@ -611,15 +608,13 @@ void FlowGraphCompiler::GenerateInstanceOf(TokenPosition token_pos, |
Label done; |
if (!test_cache.IsNull()) { |
// Generate runtime call. |
- __ ldr(R1, Address(SP, 1 * kWordSize)); // Get instantiator type args. |
- __ ldr(R2, Address(SP, 0 * kWordSize)); // Get function type args. |
- // TODO(regis): Renumber registers and use ldm. |
+ __ ldm(IA, SP, (1 << kFunctionTypeArgumentsReg) | |
+ (1 << kInstantiatorTypeArgumentsReg)); |
__ PushObject(Object::null_object()); // Make room for the result. |
__ Push(R0); // Push the instance. |
__ PushObject(type); // Push the type. |
- __ Push(R1); // Instantiator type arguments. |
- __ Push(R2); // Function type arguments. |
- // TODO(regis): Renumber registers and use PushList. |
+ __ PushList((1 << kInstantiatorTypeArgumentsReg) | |
+ (1 << kFunctionTypeArgumentsReg)); |
__ LoadUniqueObject(R0, test_cache); |
__ Push(R0); |
GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs); |
@@ -647,8 +642,8 @@ void FlowGraphCompiler::GenerateInstanceOf(TokenPosition token_pos, |
// - Class equality (only if class is not parameterized). |
// Inputs: |
// - R0: instance being type checked. |
-// - R1: instantiator type arguments or raw_null. |
-// - R2: function type arguments or raw_null. |
+// - R2: instantiator type arguments or raw_null. |
+// - R1: function type arguments or raw_null. |
// Returns: |
// - object in R0 for successful assignable check (or throws TypeError). |
// Performance notes: positive checks must be quick, negative checks can be slow |
@@ -664,9 +659,10 @@ void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos, |
// Assignable check is skipped in FlowGraphBuilder, not here. |
ASSERT(dst_type.IsMalformedOrMalbounded() || |
(!dst_type.IsDynamicType() && !dst_type.IsObjectType())); |
- __ Push(R1); // Store instantiator type arguments. |
- __ Push(R2); // Store function type arguments. |
- // TODO(regis): Renumber registers and use PushList. |
+ const Register kInstantiatorTypeArgumentsReg = R2; |
+ const Register kFunctionTypeArgumentsReg = R1; |
+ __ PushList((1 << kInstantiatorTypeArgumentsReg) | |
+ (1 << kFunctionTypeArgumentsReg)); |
// A null object is always assignable and is returned as result. |
Label is_assignable, runtime_call; |
__ CompareObject(R0, Object::null_object()); |
@@ -684,9 +680,8 @@ void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos, |
__ bkpt(0); |
__ Bind(&is_assignable); // For a null object. |
- __ Pop(R2); // Remove pushed function type arguments. |
- __ Pop(R1); // Remove pushed instantiator type arguments. |
- // TODO(regis): Renumber registers and use PopList. |
+ __ PopList((1 << kFunctionTypeArgumentsReg) | |
+ (1 << kInstantiatorTypeArgumentsReg)); |
return; |
} |
@@ -696,15 +691,13 @@ void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos, |
&runtime_call); |
__ Bind(&runtime_call); |
- __ ldr(R1, Address(SP, 1 * kWordSize)); // Get instantiator type args. |
- __ ldr(R2, Address(SP, 0 * kWordSize)); // Get function type args. |
- // TODO(regis): Renumber registers and use ldm. |
+ __ ldm(IA, SP, (1 << kFunctionTypeArgumentsReg) | |
+ (1 << kInstantiatorTypeArgumentsReg)); |
__ PushObject(Object::null_object()); // Make room for the result. |
__ Push(R0); // Push the source object. |
__ PushObject(dst_type); // Push the type of the destination. |
- __ Push(R1); // Instantiator type arguments. |
- __ Push(R2); // Function type arguments. |
- // TODO(regis): Renumber registers and use PushList. |
+ __ PushList((1 << kInstantiatorTypeArgumentsReg) | |
+ (1 << kFunctionTypeArgumentsReg)); |
__ PushObject(dst_name); // Push the name of the destination. |
__ LoadUniqueObject(R0, test_cache); |
__ Push(R0); |
@@ -715,9 +708,8 @@ void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos, |
__ Pop(R0); |
__ Bind(&is_assignable); |
- __ Pop(R2); // Remove pushed function type arguments. |
- __ Pop(R1); // Remove pushed instantiator type arguments. |
- // TODO(regis): Renumber registers and use PopList. |
+ __ PopList((1 << kFunctionTypeArgumentsReg) | |
+ (1 << kInstantiatorTypeArgumentsReg)); |
} |
@@ -1436,14 +1428,13 @@ void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { |
// Store fpu registers with the lowest register number at the lowest |
// address. |
intptr_t offset = 0; |
+ __ mov(IP, Operand(SP)); |
for (intptr_t i = 0; i < kNumberOfFpuRegisters; ++i) { |
QRegister fpu_reg = static_cast<QRegister>(i); |
if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) { |
- DRegister d1 = EvenDRegisterOf(fpu_reg); |
- DRegister d2 = OddDRegisterOf(fpu_reg); |
- // TODO(regis): merge stores using vstmd instruction. |
- __ vstrd(d1, Address(SP, offset)); |
- __ vstrd(d2, Address(SP, offset + 2 * kWordSize)); |
+ DRegister d = EvenDRegisterOf(fpu_reg); |
+ ASSERT(d + 1 == OddDRegisterOf(fpu_reg)); |
+ __ vstmd(IA_W, IP, d, 2); |
offset += kFpuRegisterSize; |
} |
} |
@@ -1485,16 +1476,13 @@ void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) { |
for (intptr_t i = 0; i < kNumberOfFpuRegisters; ++i) { |
QRegister fpu_reg = static_cast<QRegister>(i); |
if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) { |
- DRegister d1 = EvenDRegisterOf(fpu_reg); |
- DRegister d2 = OddDRegisterOf(fpu_reg); |
- // TODO(regis): merge loads using vldmd instruction. |
- __ vldrd(d1, Address(SP, offset)); |
- __ vldrd(d2, Address(SP, offset + 2 * kWordSize)); |
+ DRegister d = EvenDRegisterOf(fpu_reg); |
+ ASSERT(d + 1 == OddDRegisterOf(fpu_reg)); |
+ __ vldmd(IA_W, SP, d, 2); |
offset += kFpuRegisterSize; |
} |
} |
ASSERT(offset == (fpu_regs_count * kFpuRegisterSize)); |
- __ AddImmediate(SP, offset); |
} |
} |