Index: runtime/vm/flow_graph_compiler_arm64.cc |
diff --git a/runtime/vm/flow_graph_compiler_arm64.cc b/runtime/vm/flow_graph_compiler_arm64.cc |
index 7448b07e9236d1b4673a644d43b81afef3962dea..9fd1d429e96c5bd29f1b978bb6a6a098ea5f298c 100644 |
--- a/runtime/vm/flow_graph_compiler_arm64.cc |
+++ b/runtime/vm/flow_graph_compiler_arm64.cc |
@@ -64,14 +64,13 @@ bool FlowGraphCompiler::SupportsHardwareDivision() { |
void FlowGraphCompiler::EnterIntrinsicMode() { |
ASSERT(!intrinsic_mode()); |
intrinsic_mode_ = true; |
- assembler()->set_constant_pool_allowed(false); |
+ ASSERT(!assembler()->constant_pool_allowed()); |
} |
void FlowGraphCompiler::ExitIntrinsicMode() { |
ASSERT(intrinsic_mode()); |
intrinsic_mode_ = false; |
- assembler()->set_constant_pool_allowed(true); |
} |
@@ -186,7 +185,7 @@ void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler, |
ASSERT(deopt_env() != NULL); |
- __ BranchLink(&StubCode::DeoptimizeLabel(), PP); |
+ __ BranchLink(&StubCode::DeoptimizeLabel()); |
set_pc_offset(assem->CodeSize()); |
#undef __ |
} |
@@ -200,9 +199,9 @@ void FlowGraphCompiler::GenerateBoolToJump(Register bool_register, |
Label* is_true, |
Label* is_false) { |
Label fall_through; |
- __ CompareObject(bool_register, Object::null_object(), PP); |
+ __ CompareObject(bool_register, Object::null_object()); |
__ b(&fall_through, EQ); |
- __ CompareObject(bool_register, Bool::True(), PP); |
+ __ CompareObject(bool_register, Bool::True()); |
__ b(is_true, EQ); |
__ b(is_false); |
__ Bind(&fall_through); |
@@ -222,18 +221,18 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub( |
ASSERT(temp_reg == kNoRegister); // Unused on ARM. |
const SubtypeTestCache& type_test_cache = |
SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); |
- __ LoadUniqueObject(R2, type_test_cache, PP); |
+ __ LoadUniqueObject(R2, type_test_cache); |
if (test_kind == kTestTypeOneArg) { |
ASSERT(type_arguments_reg == kNoRegister); |
- __ LoadObject(R1, Object::null_object(), PP); |
- __ BranchLink(&StubCode::Subtype1TestCacheLabel(), PP); |
+ __ LoadObject(R1, Object::null_object()); |
+ __ BranchLink(&StubCode::Subtype1TestCacheLabel()); |
} else if (test_kind == kTestTypeTwoArgs) { |
ASSERT(type_arguments_reg == kNoRegister); |
- __ LoadObject(R1, Object::null_object(), PP); |
- __ BranchLink(&StubCode::Subtype2TestCacheLabel(), PP); |
+ __ LoadObject(R1, Object::null_object()); |
+ __ BranchLink(&StubCode::Subtype2TestCacheLabel()); |
} else if (test_kind == kTestTypeThreeArgs) { |
ASSERT(type_arguments_reg == R1); |
- __ BranchLink(&StubCode::Subtype3TestCacheLabel(), PP); |
+ __ BranchLink(&StubCode::Subtype3TestCacheLabel()); |
} else { |
UNREACHABLE(); |
} |
@@ -282,8 +281,8 @@ FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest( |
if (is_raw_type) { |
const Register kClassIdReg = R2; |
// dynamic type argument, check only classes. |
- __ LoadClassId(kClassIdReg, kInstanceReg, PP); |
- __ CompareImmediate(kClassIdReg, type_class.id(), PP); |
+ __ LoadClassId(kClassIdReg, kInstanceReg); |
+ __ CompareImmediate(kClassIdReg, type_class.id()); |
__ b(is_instance_lbl, EQ); |
// List is a very common case. |
if (IsListClass(type_class)) { |
@@ -327,7 +326,7 @@ void FlowGraphCompiler::CheckClassIds(Register class_id_reg, |
Label* is_equal_lbl, |
Label* is_not_equal_lbl) { |
for (intptr_t i = 0; i < class_ids.length(); i++) { |
- __ CompareImmediate(class_id_reg, class_ids[i], PP); |
+ __ CompareImmediate(class_id_reg, class_ids[i]); |
__ b(is_equal_lbl, EQ); |
} |
__ b(is_not_equal_lbl); |
@@ -363,23 +362,23 @@ bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest( |
} |
// Compare if the classes are equal. |
const Register kClassIdReg = R2; |
- __ LoadClassId(kClassIdReg, kInstanceReg, PP); |
- __ CompareImmediate(kClassIdReg, type_class.id(), PP); |
+ __ LoadClassId(kClassIdReg, kInstanceReg); |
+ __ CompareImmediate(kClassIdReg, type_class.id()); |
__ b(is_instance_lbl, EQ); |
// See ClassFinalizer::ResolveSuperTypeAndInterfaces for list of restricted |
// interfaces. |
// Bool interface can be implemented only by core class Bool. |
if (type.IsBoolType()) { |
- __ CompareImmediate(kClassIdReg, kBoolCid, PP); |
+ __ CompareImmediate(kClassIdReg, kBoolCid); |
__ b(is_instance_lbl, EQ); |
__ b(is_not_instance_lbl); |
return false; |
} |
if (type.IsFunctionType()) { |
// Check if instance is a closure. |
- __ LoadClassById(R3, kClassIdReg, PP); |
- __ LoadFieldFromOffset(R3, R3, Class::signature_function_offset(), PP); |
- __ CompareObject(R3, Object::null_object(), PP); |
+ __ LoadClassById(R3, kClassIdReg); |
+ __ LoadFieldFromOffset(R3, R3, Class::signature_function_offset()); |
+ __ CompareObject(R3, Object::null_object()); |
__ b(is_instance_lbl, NE); |
} |
// Custom checking for numbers (Smi, Mint, Bigint and Double). |
@@ -412,12 +411,12 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup( |
Label* is_not_instance_lbl) { |
__ Comment("Subtype1TestCacheLookup"); |
const Register kInstanceReg = R0; |
- __ LoadClass(R1, kInstanceReg, PP); |
+ __ LoadClass(R1, kInstanceReg); |
// R1: instance class. |
// Check immediate superclass equality. |
- __ LoadFieldFromOffset(R2, R1, Class::super_type_offset(), PP); |
- __ LoadFieldFromOffset(R2, R2, Type::type_class_offset(), PP); |
- __ CompareObject(R2, type_class, PP); |
+ __ LoadFieldFromOffset(R2, R1, Class::super_type_offset()); |
+ __ LoadFieldFromOffset(R2, R2, Type::type_class_offset()); |
+ __ CompareObject(R2, type_class); |
__ b(is_instance_lbl, EQ); |
const Register kTypeArgumentsReg = kNoRegister; |
@@ -447,24 +446,24 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( |
__ ldr(R1, Address(SP)); // Get instantiator type arguments. |
// R1: instantiator type arguments. |
// Check if type arguments are null, i.e. equivalent to vector of dynamic. |
- __ CompareObject(R1, Object::null_object(), PP); |
+ __ CompareObject(R1, Object::null_object()); |
__ b(is_instance_lbl, EQ); |
__ LoadFieldFromOffset( |
- R2, R1, TypeArguments::type_at_offset(type_param.index()), PP); |
+ R2, R1, TypeArguments::type_at_offset(type_param.index())); |
// R2: concrete type of type. |
// Check if type argument is dynamic. |
- __ CompareObject(R2, Type::ZoneHandle(Type::DynamicType()), PP); |
+ __ CompareObject(R2, Type::ZoneHandle(Type::DynamicType())); |
__ b(is_instance_lbl, EQ); |
- __ CompareObject(R2, Type::ZoneHandle(Type::ObjectType()), PP); |
+ __ CompareObject(R2, Type::ZoneHandle(Type::ObjectType())); |
__ b(is_instance_lbl, EQ); |
// For Smi check quickly against int and num interfaces. |
Label not_smi; |
__ tsti(R0, Immediate(kSmiTagMask)); // Value is Smi? |
__ b(¬_smi, NE); |
- __ CompareObject(R2, Type::ZoneHandle(Type::IntType()), PP); |
+ __ CompareObject(R2, Type::ZoneHandle(Type::IntType())); |
__ b(is_instance_lbl, EQ); |
- __ CompareObject(R2, Type::ZoneHandle(Type::Number()), PP); |
+ __ CompareObject(R2, Type::ZoneHandle(Type::Number())); |
__ b(is_instance_lbl, EQ); |
// Smi must be handled in runtime. |
Label fall_through; |
@@ -593,7 +592,7 @@ void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos, |
// We can only inline this null check if the type is instantiated at compile |
// time, since an uninstantiated type at compile time could be Object or |
// dynamic at run time. |
- __ CompareObject(R0, Object::null_object(), PP); |
+ __ CompareObject(R0, Object::null_object()); |
__ b(type.IsNullType() ? &is_instance : &is_not_instance, EQ); |
} |
@@ -609,13 +608,13 @@ void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos, |
// Load instantiator (R2) and its type arguments (R1). |
__ ldr(R1, Address(SP, 0 * kWordSize)); |
__ ldr(R2, Address(SP, 1 * kWordSize)); |
- __ PushObject(Object::null_object(), PP); // Make room for the result. |
+ __ PushObject(Object::null_object()); // Make room for the result. |
__ Push(R0); // Push the instance. |
- __ PushObject(type, PP); // Push the type. |
+ __ PushObject(type); // Push the type. |
// Push instantiator (R2) and its type arguments (R1). |
__ Push(R2); |
__ Push(R1); |
- __ LoadUniqueObject(R0, test_cache, PP); |
+ __ LoadUniqueObject(R0, test_cache); |
__ Push(R0); |
GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs); |
// Pop the parameters supplied to the runtime entry. The result of the |
@@ -623,21 +622,21 @@ void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos, |
__ Drop(5); |
if (negate_result) { |
__ Pop(R1); |
- __ LoadObject(R0, Bool::True(), PP); |
+ __ LoadObject(R0, Bool::True()); |
__ CompareRegisters(R1, R0); |
__ b(&done, NE); |
- __ LoadObject(R0, Bool::False(), PP); |
+ __ LoadObject(R0, Bool::False()); |
} else { |
__ Pop(R0); |
} |
__ b(&done); |
} |
__ Bind(&is_not_instance); |
- __ LoadObject(R0, Bool::Get(negate_result), PP); |
+ __ LoadObject(R0, Bool::Get(negate_result)); |
__ b(&done); |
__ Bind(&is_instance); |
- __ LoadObject(R0, Bool::Get(!negate_result), PP); |
+ __ LoadObject(R0, Bool::Get(!negate_result)); |
__ Bind(&done); |
// Remove instantiator (R2) and its type arguments (R1). |
__ Drop(2); |
@@ -672,15 +671,15 @@ void FlowGraphCompiler::GenerateAssertAssignable(intptr_t token_pos, |
__ Push(R1); |
// A null object is always assignable and is returned as result. |
Label is_assignable, runtime_call; |
- __ CompareObject(R0, Object::null_object(), PP); |
+ __ CompareObject(R0, Object::null_object()); |
__ b(&is_assignable, EQ); |
// Generate throw new TypeError() if the type is malformed or malbounded. |
if (dst_type.IsMalformedOrMalbounded()) { |
- __ PushObject(Object::null_object(), PP); // Make room for the result. |
+ __ PushObject(Object::null_object()); // Make room for the result. |
__ Push(R0); // Push the source object. |
- __ PushObject(dst_name, PP); // Push the name of the destination. |
- __ PushObject(dst_type, PP); // Push the type of the destination. |
+ __ PushObject(dst_name); // Push the name of the destination. |
+ __ PushObject(dst_type); // Push the type of the destination. |
GenerateRuntimeCall(token_pos, |
deopt_id, |
kBadTypeErrorRuntimeEntry, |
@@ -705,14 +704,14 @@ void FlowGraphCompiler::GenerateAssertAssignable(intptr_t token_pos, |
// Load instantiator (R2) and its type arguments (R1). |
__ ldr(R1, Address(SP)); |
__ ldr(R2, Address(SP, 1 * kWordSize)); |
- __ PushObject(Object::null_object(), PP); // Make room for the result. |
+ __ PushObject(Object::null_object()); // Make room for the result. |
__ Push(R0); // Push the source object. |
- __ PushObject(dst_type, PP); // Push the type of the destination. |
+ __ PushObject(dst_type); // Push the type of the destination. |
// Push instantiator (R2) and its type arguments (R1). |
__ Push(R2); |
__ Push(R1); |
- __ PushObject(dst_name, PP); // Push the name of the destination. |
- __ LoadUniqueObject(R0, test_cache, PP); |
+ __ PushObject(dst_name); // Push the name of the destination. |
+ __ LoadUniqueObject(R0, test_cache); |
__ Push(R0); |
GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs); |
// Pop the parameters supplied to the runtime entry. The result of the |
@@ -758,20 +757,20 @@ void FlowGraphCompiler::CopyParameters() { |
const int max_num_pos_args = num_fixed_params + num_opt_pos_params; |
__ LoadFieldFromOffset( |
- R8, R4, ArgumentsDescriptor::positional_count_offset(), PP); |
+ R8, R4, ArgumentsDescriptor::positional_count_offset()); |
// Check that min_num_pos_args <= num_pos_args. |
Label wrong_num_arguments; |
- __ CompareImmediate(R8, Smi::RawValue(min_num_pos_args), PP); |
+ __ CompareImmediate(R8, Smi::RawValue(min_num_pos_args)); |
__ b(&wrong_num_arguments, LT); |
// Check that num_pos_args <= max_num_pos_args. |
- __ CompareImmediate(R8, Smi::RawValue(max_num_pos_args), PP); |
+ __ CompareImmediate(R8, Smi::RawValue(max_num_pos_args)); |
__ b(&wrong_num_arguments, GT); |
// Copy positional arguments. |
// Argument i passed at fp[kParamEndSlotFromFp + num_args - i] is copied |
// to fp[kFirstLocalSlotFromFp - i]. |
- __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset(), PP); |
+ __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset()); |
// Since R7 and R8 are Smi, use LSL 2 instead of LSL 3. |
// Let R7 point to the last passed positional argument, i.e. to |
// fp[kParamEndSlotFromFp + num_args - (num_pos_args - 1)]. |
@@ -781,7 +780,7 @@ void FlowGraphCompiler::CopyParameters() { |
// Let R6 point to the last copied positional argument, i.e. to |
// fp[kFirstLocalSlotFromFp - (num_pos_args - 1)]. |
- __ AddImmediate(R6, FP, (kFirstLocalSlotFromFp + 1) * kWordSize, PP); |
+ __ AddImmediate(R6, FP, (kFirstLocalSlotFromFp + 1) * kWordSize); |
__ sub(R6, R6, Operand(R8, LSL, 2)); // R8 is a Smi. |
__ SmiUntag(R8); |
Label loop, loop_condition; |
@@ -825,14 +824,14 @@ void FlowGraphCompiler::CopyParameters() { |
opt_param_position[i + 1] = pos; |
} |
// Generate code handling each optional parameter in alphabetical order. |
- __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset(), PP); |
+ __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset()); |
__ LoadFieldFromOffset( |
- R8, R4, ArgumentsDescriptor::positional_count_offset(), PP); |
+ R8, R4, ArgumentsDescriptor::positional_count_offset()); |
__ SmiUntag(R8); |
// Let R7 point to the first passed argument, i.e. to |
// fp[kParamEndSlotFromFp + num_args - 0]; num_args (R7) is Smi. |
__ add(R7, FP, Operand(R7, LSL, 2)); |
- __ AddImmediate(R7, R7, kParamEndSlotFromFp * kWordSize, PP); |
+ __ AddImmediate(R7, R7, kParamEndSlotFromFp * kWordSize); |
// Let R6 point to the entry of the first named argument. |
__ add(R6, R4, Operand( |
ArgumentsDescriptor::first_named_entry_offset() - kHeapObjectTag)); |
@@ -841,13 +840,13 @@ void FlowGraphCompiler::CopyParameters() { |
const int param_pos = opt_param_position[i]; |
// Check if this named parameter was passed in. |
// Load R5 with the name of the argument. |
- __ LoadFromOffset(R5, R6, ArgumentsDescriptor::name_offset(), PP); |
+ __ LoadFromOffset(R5, R6, ArgumentsDescriptor::name_offset()); |
ASSERT(opt_param[i]->name().IsSymbol()); |
- __ CompareObject(R5, opt_param[i]->name(), PP); |
+ __ CompareObject(R5, opt_param[i]->name()); |
__ b(&load_default_value, NE); |
// Load R5 with passed-in argument at provided arg_pos, i.e. at |
// fp[kParamEndSlotFromFp + num_args - arg_pos]. |
- __ LoadFromOffset(R5, R6, ArgumentsDescriptor::position_offset(), PP); |
+ __ LoadFromOffset(R5, R6, ArgumentsDescriptor::position_offset()); |
// R5 is arg_pos as Smi. |
// Point to next named entry. |
__ add(R6, R6, Operand(ArgumentsDescriptor::named_entry_size())); |
@@ -861,14 +860,14 @@ void FlowGraphCompiler::CopyParameters() { |
const Object& value = Object::ZoneHandle( |
parsed_function().default_parameter_values().At( |
param_pos - num_fixed_params)); |
- __ LoadObject(R5, value, PP); |
+ __ LoadObject(R5, value); |
__ Bind(&assign_optional_parameter); |
// Assign R5 to fp[kFirstLocalSlotFromFp - param_pos]. |
// We do not use the final allocation index of the variable here, i.e. |
// scope->VariableAt(i)->index(), because captured variables still need |
// to be copied to the context that is not yet allocated. |
const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; |
- __ StoreToOffset(R5, FP, computed_param_pos * kWordSize, PP); |
+ __ StoreToOffset(R5, FP, computed_param_pos * kWordSize); |
} |
delete[] opt_param; |
delete[] opt_param_position; |
@@ -876,13 +875,13 @@ void FlowGraphCompiler::CopyParameters() { |
// Check that R6 now points to the null terminator in the arguments |
// descriptor. |
__ ldr(R5, Address(R6)); |
- __ CompareObject(R5, Object::null_object(), PP); |
+ __ CompareObject(R5, Object::null_object()); |
__ b(&all_arguments_processed, EQ); |
} |
} else { |
ASSERT(num_opt_pos_params > 0); |
__ LoadFieldFromOffset( |
- R8, R4, ArgumentsDescriptor::positional_count_offset(), PP); |
+ R8, R4, ArgumentsDescriptor::positional_count_offset()); |
__ SmiUntag(R8); |
for (int i = 0; i < num_opt_pos_params; i++) { |
Label next_parameter; |
@@ -890,22 +889,22 @@ void FlowGraphCompiler::CopyParameters() { |
// arguments have been passed, where k is param_pos, the position of this |
// optional parameter in the formal parameter list. |
const int param_pos = num_fixed_params + i; |
- __ CompareImmediate(R8, param_pos, PP); |
+ __ CompareImmediate(R8, param_pos); |
__ b(&next_parameter, GT); |
// Load R5 with default argument. |
const Object& value = Object::ZoneHandle( |
parsed_function().default_parameter_values().At(i)); |
- __ LoadObject(R5, value, PP); |
+ __ LoadObject(R5, value); |
// Assign R5 to fp[kFirstLocalSlotFromFp - param_pos]. |
// We do not use the final allocation index of the variable here, i.e. |
// scope->VariableAt(i)->index(), because captured variables still need |
// to be copied to the context that is not yet allocated. |
const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; |
- __ StoreToOffset(R5, FP, computed_param_pos * kWordSize, PP); |
+ __ StoreToOffset(R5, FP, computed_param_pos * kWordSize); |
__ Bind(&next_parameter); |
} |
if (check_correct_named_args) { |
- __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset(), PP); |
+ __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset()); |
__ SmiUntag(R7); |
// Check that R8 equals R7, i.e. no named arguments passed. |
__ CompareRegisters(R8, R7); |
@@ -915,8 +914,12 @@ void FlowGraphCompiler::CopyParameters() { |
__ Bind(&wrong_num_arguments); |
if (function.IsClosureFunction()) { |
+ ASSERT(assembler()->constant_pool_allowed()); |
__ LeaveDartFrame(); // The arguments are still on the stack. |
+ // Do not use caller's pool ptr in branch. |
+ ASSERT(!assembler()->constant_pool_allowed()); |
__ BranchPatchable(&StubCode::CallClosureNoSuchMethodLabel()); |
+ __ set_constant_pool_allowed(true); |
// The noSuchMethod call may return to the caller, but not here. |
} else if (check_correct_named_args) { |
__ Stop("Wrong arguments"); |
@@ -930,11 +933,11 @@ void FlowGraphCompiler::CopyParameters() { |
// an issue anymore. |
// R4 : arguments descriptor array. |
- __ LoadFieldFromOffset(R8, R4, ArgumentsDescriptor::count_offset(), PP); |
+ __ LoadFieldFromOffset(R8, R4, ArgumentsDescriptor::count_offset()); |
__ SmiUntag(R8); |
__ add(R7, FP, Operand((kParamEndSlotFromFp + 1) * kWordSize)); |
const Address original_argument_addr(R7, R8, UXTX, Address::Scaled); |
- __ LoadObject(TMP, Object::null_object(), PP); |
+ __ LoadObject(TMP, Object::null_object()); |
Label null_args_loop, null_args_loop_condition; |
__ b(&null_args_loop_condition); |
__ Bind(&null_args_loop); |
@@ -950,8 +953,8 @@ void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) { |
// SP: receiver. |
// Sequence node has one return node, its input is load field node. |
__ Comment("Inlined Getter"); |
- __ LoadFromOffset(R0, SP, 0 * kWordSize, PP); |
- __ LoadFromOffset(R0, R0, offset - kHeapObjectTag, PP); |
+ __ LoadFromOffset(R0, SP, 0 * kWordSize); |
+ __ LoadFromOffset(R0, R0, offset - kHeapObjectTag); |
__ ret(); |
} |
@@ -962,55 +965,56 @@ void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) { |
// SP+0: value. |
// Sequence node has one store node and one return NULL node. |
__ Comment("Inlined Setter"); |
- __ LoadFromOffset(R0, SP, 1 * kWordSize, PP); // Receiver. |
- __ LoadFromOffset(R1, SP, 0 * kWordSize, PP); // Value. |
- __ StoreIntoObjectOffset(R0, offset, R1, PP); |
- __ LoadObject(R0, Object::null_object(), PP); |
+ __ LoadFromOffset(R0, SP, 1 * kWordSize); // Receiver. |
+ __ LoadFromOffset(R1, SP, 0 * kWordSize); // Value. |
+ __ StoreIntoObjectOffset(R0, offset, R1); |
+ __ LoadObject(R0, Object::null_object()); |
__ ret(); |
} |
void FlowGraphCompiler::EmitFrameEntry() { |
const Function& function = parsed_function().function(); |
- Register new_pp = kNoPP; |
+ Register new_pp = kNoRegister; |
if (CanOptimizeFunction() && |
function.IsOptimizable() && |
(!is_optimizing() || may_reoptimize())) { |
const Register function_reg = R6; |
+ const Register saved_pp = R7; |
new_pp = R13; |
+ // The pool pointer is not setup before entering the Dart frame. |
+ // Preserve PP of caller. |
+ __ mov(saved_pp, PP); |
- // Set up pool pointer in new_pp. |
- __ LoadPoolPointer(new_pp); |
+ // Temporarily setup pool pointer for this dart function. |
+ __ LoadPoolPointer(); |
// Load function object using the callee's pool pointer. |
- __ LoadObject(function_reg, function, new_pp); |
+ __ LoadObject(function_reg, function); |
+ // Preserve new PP and restore PP of caller. |
+ __ mov(new_pp, PP); |
+ __ mov(PP, saved_pp); |
+ __ set_constant_pool_allowed(false); |
// Patch point is after the eventually inlined function object. |
entry_patch_pc_offset_ = assembler()->CodeSize(); |
__ LoadFieldFromOffset( |
- R7, function_reg, Function::usage_counter_offset(), new_pp, kWord); |
+ R7, function_reg, Function::usage_counter_offset(), kWord); |
// Reoptimization of an optimized function is triggered by counting in |
// IC stubs, but not at the entry of the function. |
if (!is_optimizing()) { |
__ add(R7, R7, Operand(1)); |
__ StoreFieldToOffset( |
- R7, function_reg, Function::usage_counter_offset(), new_pp, kWord); |
+ R7, function_reg, Function::usage_counter_offset(), kWord); |
} |
- __ CompareImmediate(R7, GetOptimizationThreshold(), new_pp); |
+ __ CompareImmediate(R7, GetOptimizationThreshold()); |
ASSERT(function_reg == R6); |
Label dont_optimize; |
__ b(&dont_optimize, LT); |
- __ Branch(&StubCode::OptimizeFunctionLabel(), new_pp); |
+ __ Branch(&StubCode::OptimizeFunctionLabel()); |
__ Bind(&dont_optimize); |
} else if (!flow_graph().IsCompiledForOsr()) { |
- // We have to load the PP here too because a load of an external label |
- // may be patched at the AddCurrentDescriptor below. |
- new_pp = R13; |
- |
- // Set up pool pointer in new_pp. |
- __ LoadPoolPointer(new_pp); |
- |
entry_patch_pc_offset_ = assembler()->CodeSize(); |
} |
__ Comment("Enter frame"); |
@@ -1040,6 +1044,7 @@ void FlowGraphCompiler::CompileGraph() { |
TryIntrinsify(); |
EmitFrameEntry(); |
+ ASSERT(assembler()->constant_pool_allowed()); |
const Function& function = parsed_function().function(); |
@@ -1063,17 +1068,21 @@ void FlowGraphCompiler::CompileGraph() { |
__ Comment("Check argument count"); |
// Check that exactly num_fixed arguments are passed in. |
Label correct_num_arguments, wrong_num_arguments; |
- __ LoadFieldFromOffset(R0, R4, ArgumentsDescriptor::count_offset(), PP); |
- __ CompareImmediate(R0, Smi::RawValue(num_fixed_params), PP); |
+ __ LoadFieldFromOffset(R0, R4, ArgumentsDescriptor::count_offset()); |
+ __ CompareImmediate(R0, Smi::RawValue(num_fixed_params)); |
__ b(&wrong_num_arguments, NE); |
__ LoadFieldFromOffset(R1, R4, |
- ArgumentsDescriptor::positional_count_offset(), PP); |
+ ArgumentsDescriptor::positional_count_offset()); |
__ CompareRegisters(R0, R1); |
__ b(&correct_num_arguments, EQ); |
__ Bind(&wrong_num_arguments); |
if (function.IsClosureFunction()) { |
+ ASSERT(assembler()->constant_pool_allowed()); |
__ LeaveDartFrame(); // The arguments are still on the stack. |
+ // Do not use caller's pool ptr in branch. |
+ ASSERT(!assembler()->constant_pool_allowed()); |
__ BranchPatchable(&StubCode::CallClosureNoSuchMethodLabel()); |
+ __ set_constant_pool_allowed(true); |
// The noSuchMethod call may return to the caller, but not here. |
} else { |
__ Stop("Wrong number of arguments"); |
@@ -1101,22 +1110,22 @@ void FlowGraphCompiler::CompileGraph() { |
const intptr_t context_index = |
parsed_function().current_context_var()->index(); |
if (num_locals > 1) { |
- __ LoadObject(R0, Object::null_object(), PP); |
+ __ LoadObject(R0, Object::null_object()); |
} |
for (intptr_t i = 0; i < num_locals; ++i) { |
// Subtract index i (locals lie at lower addresses than FP). |
if (((slot_base - i) == context_index)) { |
if (function.IsClosureFunction()) { |
- __ StoreToOffset(CTX, FP, (slot_base - i) * kWordSize, PP); |
+ __ StoreToOffset(CTX, FP, (slot_base - i) * kWordSize); |
} else { |
const Context& empty_context = Context::ZoneHandle( |
zone(), isolate()->object_store()->empty_context()); |
- __ LoadObject(R1, empty_context, PP); |
- __ StoreToOffset(R1, FP, (slot_base - i) * kWordSize, PP); |
+ __ LoadObject(R1, empty_context); |
+ __ StoreToOffset(R1, FP, (slot_base - i) * kWordSize); |
} |
} else { |
ASSERT(num_locals > 1); |
- __ StoreToOffset(R0, FP, (slot_base - i) * kWordSize, PP); |
+ __ StoreToOffset(R0, FP, (slot_base - i) * kWordSize); |
} |
} |
} |
@@ -1124,6 +1133,7 @@ void FlowGraphCompiler::CompileGraph() { |
VisitBlocks(); |
__ brk(0); |
+ ASSERT(assembler()->constant_pool_allowed()); |
GenerateDeferredCode(); |
// Emit function patching code. This will be swapped with the first 3 |
@@ -1198,13 +1208,14 @@ void FlowGraphCompiler::EmitEdgeCounter() { |
// overflow; and though we do not reset the counters when we optimize or |
// deoptimize, there is a bound on the number of |
// optimization/deoptimization cycles we will attempt. |
+ ASSERT(assembler_->constant_pool_allowed()); |
const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); |
counter.SetAt(0, Smi::Handle(Smi::New(0))); |
__ Comment("Edge counter"); |
- __ LoadUniqueObject(R0, counter, PP); |
- __ LoadFieldFromOffset(TMP, R0, Array::element_offset(0), PP); |
+ __ LoadUniqueObject(R0, counter); |
+ __ LoadFieldFromOffset(TMP, R0, Array::element_offset(0)); |
__ add(TMP, TMP, Operand(Smi::RawValue(1))); |
- __ StoreFieldToOffset(TMP, R0, Array::element_offset(0), PP); |
+ __ StoreFieldToOffset(TMP, R0, Array::element_offset(0)); |
} |
@@ -1223,8 +1234,8 @@ void FlowGraphCompiler::EmitOptimizedInstanceCall( |
// reoptimized and which counter needs to be incremented. |
// Pass the function explicitly, it is used in IC stub. |
- __ LoadObject(R6, parsed_function().function(), PP); |
- __ LoadUniqueObject(R5, ic_data, PP); |
+ __ LoadObject(R6, parsed_function().function()); |
+ __ LoadUniqueObject(R5, ic_data); |
GenerateDartCall(deopt_id, |
token_pos, |
target_label, |
@@ -1241,7 +1252,7 @@ void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, |
intptr_t token_pos, |
LocationSummary* locs) { |
ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0); |
- __ LoadUniqueObject(R5, ic_data, PP); |
+ __ LoadUniqueObject(R5, ic_data); |
GenerateDartCall(deopt_id, |
token_pos, |
target_label, |
@@ -1267,16 +1278,16 @@ void FlowGraphCompiler::EmitMegamorphicInstanceCall( |
const Register receiverR = R0; |
const Register cacheR = R1; |
const Register targetR = R1; |
- __ LoadFromOffset(receiverR, SP, (argument_count - 1) * kWordSize, PP); |
- __ LoadObject(cacheR, cache, PP); |
+ __ LoadFromOffset(receiverR, SP, (argument_count - 1) * kWordSize); |
+ __ LoadObject(cacheR, cache); |
if (FLAG_use_megamorphic_stub) { |
- __ BranchLink(&StubCode::MegamorphicLookupLabel(), PP); |
+ __ BranchLink(&StubCode::MegamorphicLookupLabel()); |
} else { |
StubCode::EmitMegamorphicLookup(assembler(), receiverR, cacheR, targetR); |
} |
- __ LoadObject(R5, ic_data, PP); |
- __ LoadObject(R4, arguments_descriptor, PP); |
+ __ LoadObject(R5, ic_data); |
+ __ LoadObject(R4, arguments_descriptor); |
__ blr(targetR); |
AddCurrentDescriptor(RawPcDescriptors::kOther, |
Isolate::kNoDeoptId, token_pos); |
@@ -1302,7 +1313,7 @@ void FlowGraphCompiler::EmitUnoptimizedStaticCall( |
const uword label_address = |
StubCode::UnoptimizedStaticCallEntryPoint(ic_data.NumArgsTested()); |
ExternalLabel target_label(label_address); |
- __ LoadObject(R5, ic_data, PP); |
+ __ LoadObject(R5, ic_data); |
GenerateDartCall(deopt_id, |
token_pos, |
&target_label, |
@@ -1319,7 +1330,7 @@ void FlowGraphCompiler::EmitOptimizedStaticCall( |
intptr_t deopt_id, |
intptr_t token_pos, |
LocationSummary* locs) { |
- __ LoadObject(R4, arguments_descriptor, PP); |
+ __ LoadObject(R4, arguments_descriptor); |
// Do not use the code from the function, but let the code be patched so that |
// we can record the outgoing edges to other code. |
GenerateDartCall(deopt_id, |
@@ -1340,7 +1351,7 @@ Condition FlowGraphCompiler::EmitEqualityRegConstCompare( |
if (needs_number_check) { |
ASSERT(!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint()); |
__ Push(reg); |
- __ PushObject(obj, PP); |
+ __ PushObject(obj); |
if (is_optimizing()) { |
__ BranchLinkPatchable( |
&StubCode::OptimizedIdenticalWithNumberCheckLabel()); |
@@ -1357,7 +1368,7 @@ Condition FlowGraphCompiler::EmitEqualityRegConstCompare( |
__ Drop(1); // Discard constant. |
__ Pop(reg); // Restore 'reg'. |
} else { |
- __ CompareObject(reg, obj, PP); |
+ __ CompareObject(reg, obj); |
} |
return EQ; |
} |
@@ -1480,8 +1491,8 @@ void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, |
argument_names)); |
// Load receiver into R0. |
- __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize, PP); |
- __ LoadObject(R4, arguments_descriptor, PP); |
+ __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize); |
+ __ LoadObject(R4, arguments_descriptor); |
const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid; |
const intptr_t kNumChecks = ic_data.NumberOfChecks(); |
@@ -1527,12 +1538,12 @@ void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, |
// will fail if there was only one check and receiver is not Smi. |
if (kSortedLen == 0) return; |
- __ LoadClassId(R2, R0, PP); |
+ __ LoadClassId(R2, R0); |
for (intptr_t i = 0; i < kSortedLen; i++) { |
const bool kIsLastCheck = (i == (kSortedLen - 1)); |
ASSERT(sorted[i].cid != kSmiCid); |
Label next_test; |
- __ CompareImmediate(R2, sorted[i].cid, PP); |
+ __ CompareImmediate(R2, sorted[i].cid); |
if (kIsLastCheck) { |
__ b(failed, NE); |
} else { |
@@ -1571,20 +1582,20 @@ void ParallelMoveResolver::EmitMove(int index) { |
} else { |
ASSERT(destination.IsStackSlot()); |
const intptr_t dest_offset = destination.ToStackSlotOffset(); |
- __ StoreToOffset(source.reg(), destination.base_reg(), dest_offset, PP); |
+ __ StoreToOffset(source.reg(), destination.base_reg(), dest_offset); |
} |
} else if (source.IsStackSlot()) { |
if (destination.IsRegister()) { |
const intptr_t source_offset = source.ToStackSlotOffset(); |
__ LoadFromOffset( |
- destination.reg(), source.base_reg(), source_offset, PP); |
+ destination.reg(), source.base_reg(), source_offset); |
} else { |
ASSERT(destination.IsStackSlot()); |
const intptr_t source_offset = source.ToStackSlotOffset(); |
const intptr_t dest_offset = destination.ToStackSlotOffset(); |
ScratchRegisterScope tmp(this, kNoRegister); |
- __ LoadFromOffset(tmp.reg(), source.base_reg(), source_offset, PP); |
- __ StoreToOffset(tmp.reg(), destination.base_reg(), dest_offset, PP); |
+ __ LoadFromOffset(tmp.reg(), source.base_reg(), source_offset); |
+ __ StoreToOffset(tmp.reg(), destination.base_reg(), dest_offset); |
} |
} else if (source.IsFpuRegister()) { |
if (destination.IsFpuRegister()) { |
@@ -1593,37 +1604,37 @@ void ParallelMoveResolver::EmitMove(int index) { |
if (destination.IsDoubleStackSlot()) { |
const intptr_t dest_offset = destination.ToStackSlotOffset(); |
VRegister src = source.fpu_reg(); |
- __ StoreDToOffset(src, destination.base_reg(), dest_offset, PP); |
+ __ StoreDToOffset(src, destination.base_reg(), dest_offset); |
} else { |
ASSERT(destination.IsQuadStackSlot()); |
const intptr_t dest_offset = destination.ToStackSlotOffset(); |
__ StoreQToOffset( |
- source.fpu_reg(), destination.base_reg(), dest_offset, PP); |
+ source.fpu_reg(), destination.base_reg(), dest_offset); |
} |
} |
} else if (source.IsDoubleStackSlot()) { |
if (destination.IsFpuRegister()) { |
const intptr_t source_offset = source.ToStackSlotOffset(); |
const VRegister dst = destination.fpu_reg(); |
- __ LoadDFromOffset(dst, source.base_reg(), source_offset, PP); |
+ __ LoadDFromOffset(dst, source.base_reg(), source_offset); |
} else { |
ASSERT(destination.IsDoubleStackSlot()); |
const intptr_t source_offset = source.ToStackSlotOffset(); |
const intptr_t dest_offset = destination.ToStackSlotOffset(); |
- __ LoadDFromOffset(VTMP, source.base_reg(), source_offset, PP); |
- __ StoreDToOffset(VTMP, destination.base_reg(), dest_offset, PP); |
+ __ LoadDFromOffset(VTMP, source.base_reg(), source_offset); |
+ __ StoreDToOffset(VTMP, destination.base_reg(), dest_offset); |
} |
} else if (source.IsQuadStackSlot()) { |
if (destination.IsFpuRegister()) { |
const intptr_t source_offset = source.ToStackSlotOffset(); |
__ LoadQFromOffset( |
- destination.fpu_reg(), source.base_reg(), source_offset, PP); |
+ destination.fpu_reg(), source.base_reg(), source_offset); |
} else { |
ASSERT(destination.IsQuadStackSlot()); |
const intptr_t source_offset = source.ToStackSlotOffset(); |
const intptr_t dest_offset = destination.ToStackSlotOffset(); |
- __ LoadQFromOffset(VTMP, source.base_reg(), source_offset, PP); |
- __ StoreQToOffset(VTMP, destination.base_reg(), dest_offset, PP); |
+ __ LoadQFromOffset(VTMP, source.base_reg(), source_offset); |
+ __ StoreQToOffset(VTMP, destination.base_reg(), dest_offset); |
} |
} else { |
ASSERT(source.IsConstant()); |
@@ -1632,10 +1643,9 @@ void ParallelMoveResolver::EmitMove(int index) { |
if (constant.IsSmi() && |
(source.constant_instruction()->representation() == kUnboxedInt32)) { |
__ LoadImmediate(destination.reg(), |
- static_cast<int32_t>(Smi::Cast(constant).Value()), |
- PP); |
+ static_cast<int32_t>(Smi::Cast(constant).Value())); |
} else { |
- __ LoadObject(destination.reg(), constant, PP); |
+ __ LoadObject(destination.reg(), constant); |
} |
} else if (destination.IsFpuRegister()) { |
const VRegister dst = destination.fpu_reg(); |
@@ -1643,19 +1653,19 @@ void ParallelMoveResolver::EmitMove(int index) { |
__ veor(dst, dst, dst); |
} else { |
ScratchRegisterScope tmp(this, kNoRegister); |
- __ LoadObject(tmp.reg(), constant, PP); |
- __ LoadDFieldFromOffset(dst, tmp.reg(), Double::value_offset(), PP); |
+ __ LoadObject(tmp.reg(), constant); |
+ __ LoadDFieldFromOffset(dst, tmp.reg(), Double::value_offset()); |
} |
} else if (destination.IsDoubleStackSlot()) { |
if (Utils::DoublesBitEqual(Double::Cast(constant).value(), 0.0)) { |
__ veor(VTMP, VTMP, VTMP); |
} else { |
ScratchRegisterScope tmp(this, kNoRegister); |
- __ LoadObject(tmp.reg(), constant, PP); |
- __ LoadDFieldFromOffset(VTMP, tmp.reg(), Double::value_offset(), PP); |
+ __ LoadObject(tmp.reg(), constant); |
+ __ LoadDFieldFromOffset(VTMP, tmp.reg(), Double::value_offset()); |
} |
const intptr_t dest_offset = destination.ToStackSlotOffset(); |
- __ StoreDToOffset(VTMP, destination.base_reg(), dest_offset, PP); |
+ __ StoreDToOffset(VTMP, destination.base_reg(), dest_offset); |
} else { |
ASSERT(destination.IsStackSlot()); |
const intptr_t dest_offset = destination.ToStackSlotOffset(); |
@@ -1663,12 +1673,11 @@ void ParallelMoveResolver::EmitMove(int index) { |
if (constant.IsSmi() && |
(source.constant_instruction()->representation() == kUnboxedInt32)) { |
__ LoadImmediate(tmp.reg(), |
- static_cast<int32_t>(Smi::Cast(constant).Value()), |
- PP); |
+ static_cast<int32_t>(Smi::Cast(constant).Value())); |
} else { |
- __ LoadObject(tmp.reg(), constant, PP); |
+ __ LoadObject(tmp.reg(), constant); |
} |
- __ StoreToOffset(tmp.reg(), destination.base_reg(), dest_offset, PP); |
+ __ StoreToOffset(tmp.reg(), destination.base_reg(), dest_offset); |
} |
} |
@@ -1719,12 +1728,12 @@ void ParallelMoveResolver::EmitSwap(int index) { |
: source.ToStackSlotOffset(); |
if (double_width) { |
- __ LoadDFromOffset(VTMP, base_reg, slot_offset, PP); |
- __ StoreDToOffset(reg, base_reg, slot_offset, PP); |
+ __ LoadDFromOffset(VTMP, base_reg, slot_offset); |
+ __ StoreDToOffset(reg, base_reg, slot_offset); |
__ fmovdd(reg, VTMP); |
} else { |
- __ LoadQFromOffset(VTMP, base_reg, slot_offset, PP); |
- __ StoreQToOffset(reg, base_reg, slot_offset, PP); |
+ __ LoadQFromOffset(VTMP, base_reg, slot_offset); |
+ __ StoreQToOffset(reg, base_reg, slot_offset); |
__ vmov(reg, VTMP); |
} |
} else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) { |
@@ -1733,20 +1742,20 @@ void ParallelMoveResolver::EmitSwap(int index) { |
ScratchFpuRegisterScope ensure_scratch(this, kNoFpuRegister); |
VRegister scratch = ensure_scratch.reg(); |
- __ LoadDFromOffset(VTMP, source.base_reg(), source_offset, PP); |
- __ LoadDFromOffset(scratch, destination.base_reg(), dest_offset, PP); |
- __ StoreDToOffset(VTMP, destination.base_reg(), dest_offset, PP); |
- __ StoreDToOffset(scratch, source.base_reg(), source_offset, PP); |
+ __ LoadDFromOffset(VTMP, source.base_reg(), source_offset); |
+ __ LoadDFromOffset(scratch, destination.base_reg(), dest_offset); |
+ __ StoreDToOffset(VTMP, destination.base_reg(), dest_offset); |
+ __ StoreDToOffset(scratch, source.base_reg(), source_offset); |
} else if (source.IsQuadStackSlot() && destination.IsQuadStackSlot()) { |
const intptr_t source_offset = source.ToStackSlotOffset(); |
const intptr_t dest_offset = destination.ToStackSlotOffset(); |
ScratchFpuRegisterScope ensure_scratch(this, kNoFpuRegister); |
VRegister scratch = ensure_scratch.reg(); |
- __ LoadQFromOffset(VTMP, source.base_reg(), source_offset, PP); |
- __ LoadQFromOffset(scratch, destination.base_reg(), dest_offset, PP); |
- __ StoreQToOffset(VTMP, destination.base_reg(), dest_offset, PP); |
- __ StoreQToOffset(scratch, source.base_reg(), source_offset, PP); |
+ __ LoadQFromOffset(VTMP, source.base_reg(), source_offset); |
+ __ LoadQFromOffset(scratch, destination.base_reg(), dest_offset); |
+ __ StoreQToOffset(VTMP, destination.base_reg(), dest_offset); |
+ __ StoreQToOffset(scratch, source.base_reg(), source_offset); |
} else { |
UNREACHABLE(); |
} |
@@ -1799,8 +1808,8 @@ void ParallelMoveResolver::Exchange(Register reg, |
intptr_t stack_offset) { |
ScratchRegisterScope tmp(this, reg); |
__ mov(tmp.reg(), reg); |
- __ LoadFromOffset(reg, base_reg, stack_offset, PP); |
- __ StoreToOffset(tmp.reg(), base_reg, stack_offset, PP); |
+ __ LoadFromOffset(reg, base_reg, stack_offset); |
+ __ StoreToOffset(tmp.reg(), base_reg, stack_offset); |
} |
@@ -1810,10 +1819,10 @@ void ParallelMoveResolver::Exchange(Register base_reg1, |
intptr_t stack_offset2) { |
ScratchRegisterScope tmp1(this, kNoRegister); |
ScratchRegisterScope tmp2(this, tmp1.reg()); |
- __ LoadFromOffset(tmp1.reg(), base_reg1, stack_offset1, PP); |
- __ LoadFromOffset(tmp2.reg(), base_reg2, stack_offset2, PP); |
- __ StoreToOffset(tmp1.reg(), base_reg2, stack_offset2, PP); |
- __ StoreToOffset(tmp2.reg(), base_reg1, stack_offset1, PP); |
+ __ LoadFromOffset(tmp1.reg(), base_reg1, stack_offset1); |
+ __ LoadFromOffset(tmp2.reg(), base_reg2, stack_offset2); |
+ __ StoreToOffset(tmp1.reg(), base_reg2, stack_offset2); |
+ __ StoreToOffset(tmp2.reg(), base_reg1, stack_offset1); |
} |