| Index: runtime/vm/flow_graph_compiler_x64.cc
|
| ===================================================================
|
| --- runtime/vm/flow_graph_compiler_x64.cc (revision 27291)
|
| +++ runtime/vm/flow_graph_compiler_x64.cc (working copy)
|
| @@ -61,10 +61,9 @@
|
| // The real frame starts here.
|
| builder->MarkFrameStart();
|
|
|
| - // Callee's PC marker is not used anymore. Pass Function::null() to set to 0.
|
| + // Current PP, FP, and PC.
|
| + builder->AddPp(current->function(), slot_ix++);
|
| builder->AddPcMarker(Function::Handle(), slot_ix++);
|
| -
|
| - // Current FP and PC.
|
| builder->AddCallerFp(slot_ix++);
|
| builder->AddReturnAddress(current->function(), deopt_id(), slot_ix++);
|
|
|
| @@ -80,13 +79,14 @@
|
| builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++);
|
| }
|
|
|
| - // Current PC marker and caller FP.
|
| - builder->AddPcMarker(current->function(), slot_ix++);
|
| - builder->AddCallerFp(slot_ix++);
|
| -
|
| Environment* previous = current;
|
| current = current->outer();
|
| while (current != NULL) {
|
| + // PP, FP, and PC.
|
| + builder->AddPp(current->function(), slot_ix++);
|
| + builder->AddPcMarker(previous->function(), slot_ix++);
|
| + builder->AddCallerFp(slot_ix++);
|
| +
|
| // For any outer environment the deopt id is that of the call instruction
|
| // which is recorded in the outer environment.
|
| builder->AddReturnAddress(current->function(),
|
| @@ -110,10 +110,6 @@
|
| slot_ix++);
|
| }
|
|
|
| - // PC marker and caller FP.
|
| - builder->AddPcMarker(current->function(), slot_ix++);
|
| - builder->AddCallerFp(slot_ix++);
|
| -
|
| // Iterate on the outer environment.
|
| previous = current;
|
| current = current->outer();
|
| @@ -121,7 +117,11 @@
|
| // The previous pointer is now the outermost environment.
|
| ASSERT(previous != NULL);
|
|
|
| - // For the outermost environment, set caller PC.
|
| + // For the outermost environment, set caller PC, caller PP, and caller FP.
|
| + builder->AddCallerPp(slot_ix++);
|
| + // PC marker.
|
| + builder->AddPcMarker(previous->function(), slot_ix++);
|
| + builder->AddCallerFp(slot_ix++);
|
| builder->AddCallerPc(slot_ix++);
|
|
|
| // For the outermost environment, set the incoming arguments.
|
| @@ -146,7 +146,7 @@
|
|
|
| ASSERT(deopt_env() != NULL);
|
|
|
| - __ call(&StubCode::DeoptimizeLabel());
|
| + __ Call(&StubCode::DeoptimizeLabel(), PP);
|
| set_pc_offset(assem->CodeSize());
|
| __ int3();
|
| #undef __
|
| @@ -160,10 +160,8 @@
|
| void FlowGraphCompiler::GenerateBoolToJump(Register bool_register,
|
| Label* is_true,
|
| Label* is_false) {
|
| - const Immediate& raw_null =
|
| - Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| Label fall_through;
|
| - __ cmpq(bool_register, raw_null);
|
| + __ CompareObject(bool_register, Object::Handle());
|
| __ j(EQUAL, &fall_through, Assembler::kNearJump);
|
| __ CompareObject(bool_register, Bool::True());
|
| __ j(EQUAL, is_true);
|
| @@ -182,22 +180,20 @@
|
| Label* is_not_instance_lbl) {
|
| const SubtypeTestCache& type_test_cache =
|
| SubtypeTestCache::ZoneHandle(SubtypeTestCache::New());
|
| - const Immediate& raw_null =
|
| - Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| - __ LoadObject(temp_reg, type_test_cache);
|
| + __ LoadObject(temp_reg, type_test_cache, PP);
|
| __ pushq(temp_reg); // Subtype test cache.
|
| __ pushq(instance_reg); // Instance.
|
| if (test_kind == kTestTypeOneArg) {
|
| ASSERT(type_arguments_reg == kNoRegister);
|
| - __ pushq(raw_null);
|
| - __ call(&StubCode::Subtype1TestCacheLabel());
|
| + __ PushObject(Object::Handle());
|
| + __ Call(&StubCode::Subtype1TestCacheLabel(), PP);
|
| } else if (test_kind == kTestTypeTwoArgs) {
|
| ASSERT(type_arguments_reg == kNoRegister);
|
| - __ pushq(raw_null);
|
| - __ call(&StubCode::Subtype2TestCacheLabel());
|
| + __ PushObject(Object::Handle());
|
| + __ Call(&StubCode::Subtype2TestCacheLabel(), PP);
|
| } else if (test_kind == kTestTypeThreeArgs) {
|
| __ pushq(type_arguments_reg);
|
| - __ call(&StubCode::Subtype3TestCacheLabel());
|
| + __ Call(&StubCode::Subtype3TestCacheLabel(), PP);
|
| } else {
|
| UNREACHABLE();
|
| }
|
| @@ -342,11 +338,9 @@
|
| }
|
| if (type.IsFunctionType()) {
|
| // Check if instance is a closure.
|
| - const Immediate& raw_null =
|
| - Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| __ LoadClassById(R13, kClassIdReg);
|
| __ movq(R13, FieldAddress(R13, Class::signature_function_offset()));
|
| - __ cmpq(R13, raw_null);
|
| + __ CompareObject(R13, Object::Handle());
|
| __ j(NOT_EQUAL, is_instance_lbl);
|
| }
|
| // Custom checking for numbers (Smi, Mint, Bigint and Double).
|
| @@ -409,15 +403,13 @@
|
| __ Comment("UninstantiatedTypeTest");
|
| ASSERT(!type.IsInstantiated());
|
| // Skip check if destination is a dynamic type.
|
| - const Immediate& raw_null =
|
| - Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| if (type.IsTypeParameter()) {
|
| const TypeParameter& type_param = TypeParameter::Cast(type);
|
| // Load instantiator (or null) and instantiator type arguments on stack.
|
| __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments.
|
| // RDX: instantiator type arguments.
|
| // Check if type argument is dynamic.
|
| - __ cmpq(RDX, raw_null);
|
| + __ CompareObject(RDX, Object::Handle());
|
| __ j(EQUAL, is_instance_lbl);
|
| // Can handle only type arguments that are instances of TypeArguments.
|
| // (runtime checks canonicalize type arguments).
|
| @@ -430,7 +422,7 @@
|
| // Check if type argument is dynamic.
|
| __ CompareObject(RDI, Type::ZoneHandle(Type::DynamicType()));
|
| __ j(EQUAL, is_instance_lbl);
|
| - __ cmpq(RDI, raw_null);
|
| + __ CompareObject(RDI, Object::Handle());
|
| __ j(EQUAL, is_instance_lbl);
|
| const Type& object_type = Type::ZoneHandle(Type::ObjectType());
|
| __ CompareObject(RDI, object_type);
|
| @@ -570,8 +562,6 @@
|
| LocationSummary* locs) {
|
| ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded());
|
|
|
| - const Immediate& raw_null =
|
| - Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| Label is_instance, is_not_instance;
|
| __ pushq(RCX); // Store instantiator on stack.
|
| __ pushq(RDX); // Store instantiator type arguments.
|
| @@ -585,7 +575,7 @@
|
| // 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.
|
| - __ cmpq(RAX, raw_null);
|
| + __ CompareObject(RAX, Object::Handle());
|
| __ j(EQUAL, &is_not_instance);
|
| }
|
|
|
| @@ -605,7 +595,7 @@
|
| __ PushObject(type); // Push the type.
|
| __ pushq(RCX); // TODO(srdjan): Pass instantiator instead of null.
|
| __ pushq(RDX); // Instantiator type arguments.
|
| - __ LoadObject(RAX, test_cache);
|
| + __ LoadObject(RAX, test_cache, PP);
|
| __ pushq(RAX);
|
| GenerateCallRuntime(token_pos,
|
| deopt_id,
|
| @@ -617,21 +607,21 @@
|
| __ Drop(5);
|
| if (negate_result) {
|
| __ popq(RDX);
|
| - __ LoadObject(RAX, Bool::True());
|
| + __ LoadObject(RAX, Bool::True(), PP);
|
| __ cmpq(RDX, RAX);
|
| __ j(NOT_EQUAL, &done, Assembler::kNearJump);
|
| - __ LoadObject(RAX, Bool::False());
|
| + __ LoadObject(RAX, Bool::False(), PP);
|
| } else {
|
| __ popq(RAX);
|
| }
|
| __ jmp(&done, Assembler::kNearJump);
|
| }
|
| __ Bind(&is_not_instance);
|
| - __ LoadObject(RAX, Bool::Get(negate_result));
|
| + __ LoadObject(RAX, Bool::Get(negate_result), PP);
|
| __ jmp(&done, Assembler::kNearJump);
|
|
|
| __ Bind(&is_instance);
|
| - __ LoadObject(RAX, Bool::Get(!negate_result));
|
| + __ LoadObject(RAX, Bool::Get(!negate_result), PP);
|
| __ Bind(&done);
|
| __ popq(RDX); // Remove pushed instantiator type arguments.
|
| __ popq(RCX); // Remove pushed instantiator.
|
| @@ -664,10 +654,8 @@
|
| __ pushq(RCX); // Store instantiator.
|
| __ pushq(RDX); // Store instantiator type arguments.
|
| // A null object is always assignable and is returned as result.
|
| - const Immediate& raw_null =
|
| - Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| Label is_assignable, runtime_call;
|
| - __ cmpq(RAX, raw_null);
|
| + __ CompareObject(RAX, Object::Handle());
|
| __ j(EQUAL, &is_assignable);
|
|
|
| if (!FLAG_eliminate_type_checks || dst_type.IsMalformed()) {
|
| @@ -720,7 +708,7 @@
|
| __ pushq(RCX); // Instantiator.
|
| __ pushq(RDX); // Instantiator type arguments.
|
| __ PushObject(dst_name); // Push the name of the destination.
|
| - __ LoadObject(RAX, test_cache);
|
| + __ LoadObject(RAX, test_cache, PP);
|
| __ pushq(RAX);
|
| GenerateCallRuntime(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs);
|
| // Pop the parameters supplied to the runtime entry. The result of the
|
| @@ -765,7 +753,7 @@
|
| __ pushq(RAX);
|
| *push_emitted = true;
|
| }
|
| - __ LoadObject(RAX, loc.constant());
|
| + __ LoadObject(RAX, loc.constant(), PP);
|
| __ movq(dest, RAX);
|
| } else if (loc.IsRegister()) {
|
| if (*push_emitted && loc.reg() == RAX) {
|
| @@ -895,8 +883,6 @@
|
| __ j(POSITIVE, &loop, Assembler::kNearJump);
|
|
|
| // Copy or initialize optional named arguments.
|
| - const Immediate& raw_null =
|
| - Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| Label all_arguments_processed;
|
| #ifdef DEBUG
|
| const bool check_correct_named_args = true;
|
| @@ -958,7 +944,7 @@
|
| const Object& value = Object::ZoneHandle(
|
| parsed_function().default_parameter_values().At(
|
| param_pos - num_fixed_params));
|
| - __ LoadObject(RAX, value);
|
| + __ LoadObject(RAX, value, PP);
|
| __ Bind(&assign_optional_parameter);
|
| // Assign RAX to fp[kFirstLocalSlotFromFp - param_pos].
|
| // We do not use the final allocation index of the variable here, i.e.
|
| @@ -973,7 +959,8 @@
|
| if (check_correct_named_args) {
|
| // Check that RDI now points to the null terminator in the arguments
|
| // descriptor.
|
| - __ cmpq(Address(RDI, 0), raw_null);
|
| + __ LoadObject(TMP, Object::Handle(), PP);
|
| + __ cmpq(Address(RDI, 0), TMP);
|
| __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
|
| }
|
| } else {
|
| @@ -992,7 +979,7 @@
|
| // Load RAX with default argument.
|
| const Object& value = Object::ZoneHandle(
|
| parsed_function().default_parameter_values().At(i));
|
| - __ LoadObject(RAX, value);
|
| + __ LoadObject(RAX, value, PP);
|
| // Assign RAX 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
|
| @@ -1018,8 +1005,8 @@
|
| const ICData& ic_data = ICData::ZoneHandle(
|
| ICData::New(function, Symbols::Call(), Object::empty_array(),
|
| Isolate::kNoDeoptId, kNumArgsChecked));
|
| - __ LoadObject(RBX, ic_data);
|
| - __ LeaveFrame(); // The arguments are still on the stack.
|
| + __ LoadObject(RBX, ic_data, PP);
|
| + __ LeaveFrameWithPP(); // The arguments are still on the stack.
|
| __ jmp(&StubCode::CallNoSuchMethodFunctionLabel());
|
| // The noSuchMethod call may return to the caller, but not here.
|
| __ int3();
|
| @@ -1037,12 +1024,13 @@
|
| // R10 : arguments descriptor array.
|
| __ movq(RCX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
|
| __ SmiUntag(RCX);
|
| + __ LoadObject(R12, Object::Handle(), PP);
|
| Label null_args_loop, null_args_loop_condition;
|
| __ jmp(&null_args_loop_condition, Assembler::kNearJump);
|
| const Address original_argument_addr(
|
| RBP, RCX, TIMES_8, (kParamEndSlotFromFp + 1) * kWordSize);
|
| __ Bind(&null_args_loop);
|
| - __ movq(original_argument_addr, raw_null);
|
| + __ movq(original_argument_addr, R12);
|
| __ Bind(&null_args_loop_condition);
|
| __ decq(RCX);
|
| __ j(POSITIVE, &null_args_loop, Assembler::kNearJump);
|
| @@ -1067,20 +1055,43 @@
|
| __ movq(RAX, Address(RSP, 2 * kWordSize)); // Receiver.
|
| __ movq(RBX, Address(RSP, 1 * kWordSize)); // Value.
|
| __ StoreIntoObject(RAX, FieldAddress(RAX, offset), RBX);
|
| - const Immediate& raw_null =
|
| - Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| - __ movq(RAX, raw_null);
|
| + __ LoadObject(RAX, Object::Handle(), PP);
|
| __ ret();
|
| }
|
|
|
|
|
| void FlowGraphCompiler::EmitFrameEntry() {
|
| const Function& function = parsed_function().function();
|
| + Register new_pp = kNoRegister;
|
| + Register new_pc = kNoRegister;
|
| if (CanOptimizeFunction() &&
|
| function.is_optimizable() &&
|
| (!is_optimizing() || may_reoptimize())) {
|
| const Register function_reg = RDI;
|
| - __ LoadObject(function_reg, function);
|
| + new_pp = R13;
|
| + new_pc = R12;
|
| +
|
| + Label next;
|
| + __ nop(4); // Need a fixed size sequence on frame entry.
|
| + __ call(&next);
|
| + __ Bind(&next);
|
| +
|
| + const intptr_t object_pool_pc_dist =
|
| + Instructions::HeaderSize() - Instructions::object_pool_offset() +
|
| + __ CodeSize();
|
| + const intptr_t offset =
|
| + Assembler::kEntryPointToPcMarkerOffset - __ CodeSize();
|
| + __ popq(new_pc);
|
| + if (offset != 0) {
|
| + __ addq(new_pc, Immediate(offset));
|
| + }
|
| +
|
| + // Load callee's pool pointer.
|
| + __ movq(new_pp, Address(new_pc, -object_pool_pc_dist - offset));
|
| +
|
| + // Load function object using the callee's pool pointer.
|
| + __ LoadObject(function_reg, function, new_pp);
|
| +
|
| // Patch point is after the eventually inlined function object.
|
| AddCurrentDescriptor(PcDescriptors::kEntryPatch,
|
| Isolate::kNoDeoptId,
|
| @@ -1096,8 +1107,30 @@
|
| Immediate(FLAG_optimization_counter_threshold));
|
| }
|
| ASSERT(function_reg == RDI);
|
| - __ j(GREATER_EQUAL, &StubCode::OptimizeFunctionLabel());
|
| + __ J(GREATER_EQUAL, &StubCode::OptimizeFunctionLabel(), R13);
|
| } 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;
|
| + new_pc = R12;
|
| +
|
| + Label next;
|
| + __ nop(4); // Need a fixed size sequence on frame entry.
|
| + __ call(&next);
|
| + __ Bind(&next);
|
| +
|
| + const intptr_t object_pool_pc_dist =
|
| + Instructions::HeaderSize() - Instructions::object_pool_offset() +
|
| + __ CodeSize();
|
| + const intptr_t offset =
|
| + Assembler::kEntryPointToPcMarkerOffset - __ CodeSize();
|
| + __ popq(new_pc);
|
| + if (offset != 0) {
|
| + __ addq(new_pc, Immediate(offset));
|
| + }
|
| +
|
| + // Load callee's pool pointer.
|
| + __ movq(new_pp, Address(new_pc, -object_pool_pc_dist - offset));
|
| AddCurrentDescriptor(PcDescriptors::kEntryPatch,
|
| Isolate::kNoDeoptId,
|
| 0); // No token position.
|
| @@ -1108,10 +1141,10 @@
|
| - flow_graph().num_stack_locals()
|
| - flow_graph().num_copied_params();
|
| ASSERT(extra_slots >= 0);
|
| - __ EnterOsrFrame(extra_slots * kWordSize);
|
| + __ EnterOsrFrame(extra_slots * kWordSize, new_pp, new_pc);
|
| } else {
|
| ASSERT(StackSize() >= 0);
|
| - __ EnterDartFrame(StackSize() * kWordSize);
|
| + __ EnterDartFrameWithInfo(StackSize() * kWordSize, new_pp, new_pc);
|
| }
|
| }
|
|
|
| @@ -1165,8 +1198,8 @@
|
| const ICData& ic_data = ICData::ZoneHandle(
|
| ICData::New(function, name, Object::empty_array(),
|
| Isolate::kNoDeoptId, kNumArgsChecked));
|
| - __ LoadObject(RBX, ic_data);
|
| - __ LeaveFrame(); // The arguments are still on the stack.
|
| + __ LoadObject(RBX, ic_data, PP);
|
| + __ LeaveFrameWithPP(); // The arguments are still on the stack.
|
| __ jmp(&StubCode::CallNoSuchMethodFunctionLabel());
|
| // The noSuchMethod call may return to the caller, but not here.
|
| __ int3();
|
| @@ -1184,9 +1217,7 @@
|
| if (!is_optimizing() && (num_locals > 0)) {
|
| __ Comment("Initialize spill slots");
|
| const intptr_t slot_base = parsed_function().first_stack_local_index();
|
| - const Immediate& raw_null =
|
| - Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| - __ movq(RAX, raw_null);
|
| + __ LoadObject(RAX, Object::Handle(), PP);
|
| for (intptr_t i = 0; i < num_locals; ++i) {
|
| // Subtract index i (locals lie at lower addresses than RBP).
|
| __ movq(Address(RBP, (slot_base - i) * kWordSize), RAX);
|
| @@ -1213,11 +1244,15 @@
|
| AddCurrentDescriptor(PcDescriptors::kPatchCode,
|
| Isolate::kNoDeoptId,
|
| 0); // No token position.
|
| - __ jmp(&StubCode::FixCallersTargetLabel());
|
| + // This is patched up to a point in FrameEntry where the PP for the
|
| + // current function is in R13 instead of PP.
|
| + __ JmpPatchable(&StubCode::FixCallersTargetLabel(), R13);
|
| +
|
| + // TOOD(zra): Is this descriptor used?
|
| AddCurrentDescriptor(PcDescriptors::kLazyDeoptJump,
|
| Isolate::kNoDeoptId,
|
| 0); // No token position.
|
| - __ jmp(&StubCode::DeoptimizeLazyLabel());
|
| + __ Jmp(&StubCode::DeoptimizeLazyLabel(), PP);
|
| }
|
|
|
|
|
| @@ -1225,7 +1260,7 @@
|
| const ExternalLabel* label,
|
| PcDescriptors::Kind kind,
|
| LocationSummary* locs) {
|
| - __ call(label);
|
| + __ Call(label, PP);
|
| AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos);
|
| RecordSafepoint(locs);
|
| }
|
| @@ -1236,7 +1271,7 @@
|
| const ExternalLabel* label,
|
| PcDescriptors::Kind kind,
|
| LocationSummary* locs) {
|
| - __ call(label);
|
| + __ CallPatchable(label);
|
| AddCurrentDescriptor(kind, deopt_id, token_pos);
|
| RecordSafepoint(locs);
|
| // Marks either the continuation point in unoptimized code or the
|
| @@ -1275,6 +1310,47 @@
|
| }
|
|
|
|
|
| +void FlowGraphCompiler::EmitUnoptimizedStaticCall(
|
| + const Function& target_function,
|
| + const Array& arguments_descriptor,
|
| + intptr_t argument_count,
|
| + intptr_t deopt_id,
|
| + intptr_t token_pos,
|
| + LocationSummary* locs) {
|
| + // TODO(srdjan): Improve performance of function recognition.
|
| + MethodRecognizer::Kind recognized_kind =
|
| + MethodRecognizer::RecognizeKind(target_function);
|
| + int num_args_checked = 0;
|
| + if ((recognized_kind == MethodRecognizer::kMathMin) ||
|
| + (recognized_kind == MethodRecognizer::kMathMax)) {
|
| + num_args_checked = 2;
|
| + }
|
| + const ICData& ic_data = ICData::ZoneHandle(
|
| + ICData::New(parsed_function().function(), // Caller function.
|
| + String::Handle(target_function.name()),
|
| + arguments_descriptor,
|
| + deopt_id,
|
| + num_args_checked)); // No arguments checked.
|
| + ic_data.AddTarget(target_function);
|
| + uword label_address = 0;
|
| + if (ic_data.num_args_tested() == 0) {
|
| + label_address = StubCode::ZeroArgsUnoptimizedStaticCallEntryPoint();
|
| + } else if (ic_data.num_args_tested() == 2) {
|
| + label_address = StubCode::TwoArgsUnoptimizedStaticCallEntryPoint();
|
| + } else {
|
| + UNIMPLEMENTED();
|
| + }
|
| + ExternalLabel target_label("StaticCallICStub", label_address);
|
| + __ LoadObject(RBX, ic_data, PP);
|
| + GenerateDartCall(deopt_id,
|
| + token_pos,
|
| + &target_label,
|
| + PcDescriptors::kUnoptStaticCall,
|
| + locs);
|
| + __ Drop(argument_count);
|
| +}
|
| +
|
| +
|
| void FlowGraphCompiler::EmitOptimizedInstanceCall(
|
| ExternalLabel* target_label,
|
| const ICData& ic_data,
|
| @@ -1288,8 +1364,8 @@
|
| // top-level function (parsed_function().function()) which could be
|
| // reoptimized and which counter needs to be incremented.
|
| // Pass the function explicitly, it is used in IC stub.
|
| - __ LoadObject(RDI, parsed_function().function());
|
| - __ LoadObject(RBX, ic_data);
|
| + __ LoadObject(RDI, parsed_function().function(), PP);
|
| + __ LoadObject(RBX, ic_data, PP);
|
| GenerateDartCall(deopt_id,
|
| token_pos,
|
| target_label,
|
| @@ -1305,7 +1381,7 @@
|
| intptr_t deopt_id,
|
| intptr_t token_pos,
|
| LocationSummary* locs) {
|
| - __ LoadObject(RBX, ic_data);
|
| + __ LoadObject(RBX, ic_data, PP);
|
| GenerateDartCall(deopt_id,
|
| token_pos,
|
| target_label,
|
| @@ -1341,7 +1417,7 @@
|
|
|
| // RAX: class ID of the receiver (smi).
|
| __ Bind(&load_cache);
|
| - __ LoadObject(RBX, cache);
|
| + __ LoadObject(RBX, cache, PP);
|
| __ movq(RDI, FieldAddress(RBX, MegamorphicCache::buckets_offset()));
|
| __ movq(RBX, FieldAddress(RBX, MegamorphicCache::mask_offset()));
|
| // RDI: cache buckets array.
|
| @@ -1373,8 +1449,8 @@
|
| __ movq(RAX, FieldAddress(RDI, RCX, TIMES_8, base + kWordSize));
|
| __ movq(RAX, FieldAddress(RAX, Function::code_offset()));
|
| __ movq(RAX, FieldAddress(RAX, Code::instructions_offset()));
|
| - __ LoadObject(RBX, ic_data);
|
| - __ LoadObject(R10, arguments_descriptor);
|
| + __ LoadObject(RBX, ic_data, PP);
|
| + __ LoadObject(R10, arguments_descriptor, PP);
|
| __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
|
| __ call(RAX);
|
| AddCurrentDescriptor(PcDescriptors::kOther, Isolate::kNoDeoptId, token_pos);
|
| @@ -1391,7 +1467,7 @@
|
| intptr_t deopt_id,
|
| intptr_t token_pos,
|
| LocationSummary* locs) {
|
| - __ LoadObject(R10, arguments_descriptor);
|
| + __ LoadObject(R10, arguments_descriptor, PP);
|
| // 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,
|
| @@ -1424,9 +1500,9 @@
|
| __ pushq(reg);
|
| __ PushObject(obj);
|
| if (is_optimizing()) {
|
| - __ call(&StubCode::OptimizedIdenticalWithNumberCheckLabel());
|
| + __ CallPatchable(&StubCode::OptimizedIdenticalWithNumberCheckLabel());
|
| } else {
|
| - __ call(&StubCode::UnoptimizedIdenticalWithNumberCheckLabel());
|
| + __ CallPatchable(&StubCode::UnoptimizedIdenticalWithNumberCheckLabel());
|
| }
|
| AddCurrentDescriptor(PcDescriptors::kRuntimeCall,
|
| Isolate::kNoDeoptId,
|
| @@ -1448,9 +1524,9 @@
|
| __ pushq(left);
|
| __ pushq(right);
|
| if (is_optimizing()) {
|
| - __ call(&StubCode::OptimizedIdenticalWithNumberCheckLabel());
|
| + __ CallPatchable(&StubCode::OptimizedIdenticalWithNumberCheckLabel());
|
| } else {
|
| - __ call(&StubCode::UnoptimizedIdenticalWithNumberCheckLabel());
|
| + __ CallPatchable(&StubCode::UnoptimizedIdenticalWithNumberCheckLabel());
|
| }
|
| AddCurrentDescriptor(PcDescriptors::kRuntimeCall,
|
| Isolate::kNoDeoptId,
|
| @@ -1540,7 +1616,7 @@
|
| const Array& arguments_descriptor =
|
| Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
|
| argument_names));
|
| - __ LoadObject(R10, arguments_descriptor);
|
| + __ LoadObject(R10, arguments_descriptor, PP);
|
| for (intptr_t i = 0; i < len; i++) {
|
| const bool is_last_check = (i == (len - 1));
|
| Label next_test;
|
| @@ -1582,7 +1658,6 @@
|
| }
|
|
|
|
|
| -
|
| void FlowGraphCompiler::EmitDoubleCompareBool(Condition true_condition,
|
| FpuRegister left,
|
| FpuRegister right,
|
| @@ -1592,10 +1667,10 @@
|
| assembler()->j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN false;
|
| assembler()->j(true_condition, &is_true, Assembler::kNearJump);
|
| assembler()->Bind(&is_false);
|
| - assembler()->LoadObject(result, Bool::False());
|
| + assembler()->LoadObject(result, Bool::False(), PP);
|
| assembler()->jmp(&done);
|
| assembler()->Bind(&is_true);
|
| - assembler()->LoadObject(result, Bool::True());
|
| + assembler()->LoadObject(result, Bool::True(), PP);
|
| assembler()->Bind(&done);
|
| }
|
|
|
| @@ -1716,7 +1791,7 @@
|
| if (constant.IsSmi() && (Smi::Cast(constant).Value() == 0)) {
|
| __ xorq(destination.reg(), destination.reg());
|
| } else {
|
| - __ LoadObject(destination.reg(), constant);
|
| + __ LoadObject(destination.reg(), constant, PP);
|
| }
|
| } else {
|
| ASSERT(destination.IsStackSlot());
|
|
|