Chromium Code Reviews| Index: runtime/vm/stub_code_x64.cc |
| =================================================================== |
| --- runtime/vm/stub_code_x64.cc (revision 27135) |
| +++ runtime/vm/stub_code_x64.cc (working copy) |
| @@ -83,9 +83,8 @@ |
| __ movq(RBX, Address(CTX, Isolate::top_context_offset())); |
| // Reset Context pointer in Isolate structure. |
| - const Immediate& raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| - __ movq(Address(CTX, Isolate::top_context_offset()), raw_null); |
| + __ LoadObjectFromPool(R12, Object::Handle(), PP); |
| + __ movq(Address(CTX, Isolate::top_context_offset()), R12); |
| // Cache Context pointer into CTX while executing Dart code. |
| __ movq(CTX, RBX); |
| @@ -172,9 +171,8 @@ |
| __ movq(R8, Address(CTX, Isolate::top_context_offset())); |
| // Reset Context pointer in Isolate structure. |
| - const Immediate& raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| - __ movq(Address(CTX, Isolate::top_context_offset()), raw_null); |
| + __ LoadObjectFromPool(R12, Object::Handle(), PP); |
| + __ movq(Address(CTX, Isolate::top_context_offset()), R12); |
| // Cache Context pointer into CTX while executing Dart code. |
| __ movq(CTX, R8); |
| @@ -240,9 +238,8 @@ |
| __ movq(R8, Address(CTX, Isolate::top_context_offset())); |
| // Reset Context pointer in Isolate structure. |
| - const Immediate& raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| - __ movq(Address(CTX, Isolate::top_context_offset()), raw_null); |
| + __ LoadObjectFromPool(R12, Object::Handle(), PP); |
| + __ movq(Address(CTX, Isolate::top_context_offset()), R12); |
| // Cache Context pointer into CTX while executing Dart code. |
| __ movq(CTX, R8); |
| @@ -255,11 +252,10 @@ |
| // Input parameters: |
| // R10: arguments descriptor array. |
| void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { |
| - const Immediate& raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| __ EnterStubFrame(); |
| __ pushq(R10); // Preserve arguments descriptor array. |
| - __ pushq(raw_null); // Setup space on stack for return value. |
| + // Setup space on stack for return value. |
| + __ PushObject(Object::Handle()); |
| __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); |
| __ popq(RAX); // Get Code object result. |
| __ popq(R10); // Restore arguments descriptor array. |
| @@ -276,11 +272,10 @@ |
| // (invalid because its function was optimized or deoptimized). |
| // R10: arguments descriptor array. |
| void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { |
| - const Immediate& raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| __ EnterStubFrame(); |
| __ pushq(R10); // Preserve arguments descriptor array. |
| - __ pushq(raw_null); // Setup space on stack for return value. |
| + // Setup space on stack for return value. |
| + __ PushObject(Object::Handle()); |
| __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); |
| __ popq(RAX); // Get Code object. |
| __ popq(R10); // Restore arguments descriptor array. |
| @@ -296,11 +291,9 @@ |
| // R10: smi-tagged argument count, may be zero. |
| // RBP[kParamEndSlotFromFp + 1]: last argument. |
| static void PushArgumentsArray(Assembler* assembler) { |
| - const Immediate& raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| - |
| + __ LoadObjectFromPool(R12, Object::Handle(), PP); |
| // Allocate array to store arguments of caller. |
| - __ movq(RBX, raw_null); // Null element type for raw Array. |
| + __ movq(RBX, R12); // Null element type for raw Array. |
| __ call(&StubCode::AllocateArrayLabel()); |
| __ SmiUntag(R10); |
| // RAX: newly allocated array. |
| @@ -330,18 +323,15 @@ |
| // called, the stub accesses the receiver from this location directly |
| // when trying to resolve the call. |
| void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { |
| - __ EnterStubFrame(); |
| + __ EnterStubFrameWithPP(); |
| + __ PushObject(Object::Handle()); // Space for the return value. |
| - const Immediate& raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| - __ pushq(raw_null); // Space for the return value. |
| - |
| // Push the receiver as an argument. Load the smi-tagged argument |
| // count into R13 to index the receiver in the stack. There are |
| - // three words (null, stub's pc marker, saved fp) above the return |
| + // four words (null, stub's pc marker, saved pp, saved fp) above the return |
| // address. |
| __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
| - __ pushq(Address(RSP, R13, TIMES_4, (3 * kWordSize))); |
| + __ pushq(Address(RSP, R13, TIMES_4, (4 * kWordSize))); |
| __ pushq(RBX); // Pass IC data object. |
| __ pushq(R10); // Pass arguments descriptor array. |
| @@ -355,7 +345,7 @@ |
| // Remove arguments. |
| __ Drop(4); |
| __ popq(RAX); // Get result into RAX. |
| - __ LeaveFrame(); |
| + __ LeaveFrameWithPP(); |
| __ ret(); |
| } |
| @@ -378,8 +368,10 @@ |
| // - Fill the unoptimized frame. |
| // - Materialize objects that require allocation (e.g. Double instances). |
| // GC can occur only after frame is fully rewritten. |
| -// Stack after EnterDartFrame(0) below: |
| +// Stack after EnterDartFrame(0, PP, kNoRegister) below: |
| // +------------------+ |
| +// | Saved PP | <- PP |
| +// +------------------+ |
| // | PC marker | <- TOS |
| // +------------------+ |
| // | Saved FP | <- FP of stub |
| @@ -391,8 +383,12 @@ |
| // Parts of the code cannot GC, part of the code can GC. |
| static void GenerateDeoptimizationSequence(Assembler* assembler, |
| bool preserve_result) { |
| - // Leaf runtime function DeoptimizeCopyFrame expects a Dart frame. |
| - __ EnterDartFrame(0); |
| + // DeoptimizeCopyFrame expects a Dart frame, i.e. EnterDartFrame(0), but there |
| + // is no need to set the correct PC marker or load PP, since they get patched. |
| + __ EnterFrame(0); |
|
Florian Schneider
2013/09/05 10:57:45
It is very confusing to start with EnterFrame here
zra
2013/09/05 20:29:26
Inlined LeaveFrameWithPP (which ends with LeaveFra
|
| + __ pushq(Immediate(0)); |
| + __ pushq(PP); |
| + |
| // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry |
| // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. |
| const intptr_t saved_result_slot_from_fp = |
| @@ -422,14 +418,18 @@ |
| __ movq(RBX, Address(RBP, saved_result_slot_from_fp * kWordSize)); |
| } |
| - __ LeaveFrame(); |
| + __ LeaveFrameWithPP(); |
| __ popq(RCX); // Preserve return address. |
| __ movq(RSP, RBP); // Discard optimized frame. |
| __ subq(RSP, RAX); // Reserve space for deoptimized frame. |
| __ pushq(RCX); // Restore return address. |
| - // Leaf runtime function DeoptimizeFillFrame expects a Dart frame. |
| - __ EnterDartFrame(0); |
| + // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there |
| + // is no need to set the correct PC marker or load PP, since they get patched. |
| + __ EnterFrame(0); |
|
Florian Schneider
2013/09/05 10:57:45
It is very confusing to start with EnterFrame here
zra
2013/09/05 20:29:26
Inlined LeaveFrameWithPP (which ends with LeaveFra
|
| + __ pushq(Immediate(0)); |
| + __ pushq(PP); |
| + |
| if (preserve_result) { |
| __ pushq(RBX); // Preserve result as first local. |
| } |
| @@ -441,7 +441,7 @@ |
| __ movq(RBX, Address(RBP, kFirstLocalSlotFromFp * kWordSize)); |
| } |
| // Code above cannot cause GC. |
| - __ LeaveFrame(); |
| + __ LeaveFrameWithPP(); |
| // Frame is fully rewritten at this point and it is safe to perform a GC. |
| // Materialize any objects that were deferred by FillFrame because they |
| @@ -486,20 +486,20 @@ |
| void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { |
| - __ EnterStubFrame(); |
| + __ EnterStubFrameWithPP(); |
| // Load the receiver into RAX. The argument count in the arguments |
| // descriptor in R10 is a smi. |
| __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
| - // Two words (saved fp, stub's pc marker) in the stack above the return |
| - // address. |
| - __ movq(RAX, Address(RSP, RAX, TIMES_4, 2 * kWordSize)); |
| + // Three words (saved pp, saved fp, stub's pc marker) |
| + // in the stack above the return address. |
| + __ movq(RAX, Address(RSP, RAX, TIMES_4, |
| + kSavedAboveReturnAddress * kWordSize)); |
| // Preserve IC data and arguments descriptor. |
| __ pushq(RBX); |
| __ pushq(R10); |
| - const Immediate& raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Instructions::null())); |
| - __ pushq(raw_null); // Space for the result of the runtime call. |
| + // Space for the result of the runtime call. |
| + __ PushObject(Object::Handle()); |
| __ pushq(RAX); // Receiver. |
| __ pushq(RBX); // IC data. |
| __ pushq(R10); // Arguments descriptor. |
| @@ -511,10 +511,10 @@ |
| __ popq(RAX); // Return value from the runtime call (instructions). |
| __ popq(R10); // Restore arguments descriptor. |
| __ popq(RBX); // Restore IC data. |
| - __ LeaveFrame(); |
| + __ LeaveFrameWithPP(); |
| Label lookup; |
| - __ cmpq(RAX, raw_null); |
| + __ CompareObject(RAX, Object::Handle()); |
| __ j(EQUAL, &lookup, Assembler::kNearJump); |
| __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| __ jmp(RAX); |
| @@ -532,8 +532,6 @@ |
| // The newly allocated object is returned in RAX. |
| void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
| Label slow_case; |
| - const Immediate& raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| if (FLAG_inline_alloc) { |
| // Compute the size to be allocated, it is based on the array length |
| @@ -622,13 +620,14 @@ |
| __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); |
| // RBX: iterator which initially points to the start of the variable |
| // data area to be initialized. |
| + __ LoadObjectFromPool(R13, Object::Handle(), PP); |
| Label done; |
| Label init_loop; |
| __ Bind(&init_loop); |
| __ cmpq(RBX, R12); |
| __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
| // TODO(cshapiro): StoreIntoObjectNoBarrier |
| - __ movq(Address(RBX, 0), raw_null); |
| + __ movq(Address(RBX, 0), R13); |
| __ addq(RBX, Immediate(kWordSize)); |
| __ jmp(&init_loop, Assembler::kNearJump); |
| __ Bind(&done); |
| @@ -645,7 +644,8 @@ |
| // Create a stub frame as we are pushing some objects on the stack before |
| // calling into the runtime. |
| __ EnterStubFrame(); |
| - __ pushq(raw_null); // Setup space on stack for return value. |
| + // Setup space on stack for return value. |
| + __ PushObject(Object::Handle()); |
| __ pushq(R10); // Array length as Smi. |
| __ pushq(RBX); // Element type. |
| __ CallRuntime(kAllocateArrayRuntimeEntry, 2); |
| @@ -663,17 +663,16 @@ |
| // called, the stub accesses the closure from this location directly |
| // when trying to resolve the call. |
| void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { |
| - const Immediate& raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| - |
| // Load num_args. |
| __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
| // Load closure object in R13. |
| __ movq(R13, Address(RSP, RAX, TIMES_4, 0)); // RAX is a Smi. |
| + __ LoadObjectFromPool(R12, Object::Handle(), PP); |
| + |
| // Verify that R13 is a closure by checking its class. |
| Label not_closure; |
| - __ cmpq(R13, raw_null); |
| + __ cmpq(R13, R12); |
| // Not a closure, but null object. |
| __ j(EQUAL, ¬_closure); |
| __ testq(R13, Immediate(kSmiTagMask)); |
| @@ -682,7 +681,7 @@ |
| // class.signature_function() is not null. |
| __ LoadClass(RAX, R13); |
| __ movq(RAX, FieldAddress(RAX, Class::signature_function_offset())); |
| - __ cmpq(RAX, raw_null); |
| + __ cmpq(RAX, R12); |
| // Actual class is not a closure class. |
| __ j(EQUAL, ¬_closure, Assembler::kNearJump); |
| @@ -694,7 +693,7 @@ |
| // Load closure function code in RAX. |
| __ movq(RAX, FieldAddress(RBX, Function::code_offset())); |
| - __ cmpq(RAX, raw_null); |
| + __ cmpq(RAX, R12); |
| Label function_compiled; |
| __ j(NOT_EQUAL, &function_compiled, Assembler::kNearJump); |
| @@ -733,8 +732,8 @@ |
| // Create a stub frame as we are pushing some objects on the stack before |
| // calling into the runtime. |
| __ EnterStubFrame(); |
| - |
| - __ pushq(raw_null); // Setup space on stack for result from call. |
| + // Setup space on stack for result from call. |
| + __ pushq(R12); |
| __ pushq(R10); // Arguments descriptor. |
| // Load smi-tagged arguments array length, including the non-closure. |
| __ movq(R10, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
| @@ -761,12 +760,12 @@ |
| // RCX : new context containing the current isolate pointer. |
| void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { |
| // Save frame pointer coming in. |
| - __ EnterFrame(0); |
| + __ EnterStubFrame(); |
| // Save arguments descriptor array and new context. |
| - const intptr_t kArgumentsDescOffset = -1 * kWordSize; |
| + const intptr_t kArgumentsDescOffset = -2 * kWordSize; |
| __ pushq(RSI); |
| - const intptr_t kNewContextOffset = -2 * kWordSize; |
| + const intptr_t kNewContextOffset = -3 * kWordSize; |
| __ pushq(RCX); |
| // Save C++ ABI callee-saved registers. |
| @@ -792,7 +791,7 @@ |
| // StackFrameIterator reads the top exit frame info saved in this frame. |
| // The constant kExitLinkSlotFromEntryFp must be kept in sync with the |
| // code below. |
| - ASSERT(kExitLinkSlotFromEntryFp == -8); |
| + ASSERT(kExitLinkSlotFromEntryFp == -9); |
| __ movq(RAX, Address(R8, Isolate::top_exit_frame_info_offset())); |
| __ pushq(RAX); |
| __ movq(Address(R8, Isolate::top_exit_frame_info_offset()), Immediate(0)); |
| @@ -804,7 +803,7 @@ |
| // EntryFrame::SavedContext reads the context saved in this frame. |
| // The constant kSavedContextSlotFromEntryFp must be kept in sync with |
| // the code below. |
| - ASSERT(kSavedContextSlotFromEntryFp == -9); |
| + ASSERT(kSavedContextSlotFromEntryFp == -10); |
| __ movq(RAX, Address(R8, Isolate::top_context_offset())); |
| __ pushq(RAX); |
| @@ -881,8 +880,7 @@ |
| // Output: |
| // RAX: new allocated RawContext object. |
| void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
| - const Immediate& raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| + __ LoadObjectFromPool(R12, Object::Handle(), PP); |
| if (FLAG_inline_alloc) { |
| const Class& context_class = Class::ZoneHandle(Object::context_class()); |
| Label slow_case; |
| @@ -957,12 +955,10 @@ |
| // R13: Isolate, not an object. |
| __ movq(FieldAddress(RAX, Context::isolate_offset()), R13); |
| - const Immediate& raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| // Setup the parent field. |
| // RAX: new object. |
| // R10: number of context variables. |
| - __ movq(FieldAddress(RAX, Context::parent_offset()), raw_null); |
| + __ movq(FieldAddress(RAX, Context::parent_offset()), R12); |
| // Initialize the context variables. |
| // RAX: new object. |
| @@ -974,7 +970,7 @@ |
| __ jmp(&entry, Assembler::kNearJump); |
| __ Bind(&loop); |
| __ decq(R10); |
| - __ movq(Address(R13, R10, TIMES_8, 0), raw_null); |
| + __ movq(Address(R13, R10, TIMES_8, 0), R12); |
| __ Bind(&entry); |
| __ cmpq(R10, Immediate(0)); |
| __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| @@ -988,7 +984,7 @@ |
| } |
| // Create a stub frame. |
| __ EnterStubFrame(); |
| - __ pushq(raw_null); // Setup space on stack for the return value. |
| + __ pushq(R12); // Setup space on stack for the return value. |
| __ SmiTag(R10); |
| __ pushq(R10); // Push number of context variables. |
| __ CallRuntime(kAllocateContextRuntimeEntry, 1); // Allocate context. |
| @@ -1072,8 +1068,6 @@ |
| const Class& cls) { |
| const intptr_t kObjectTypeArgumentsOffset = 2 * kWordSize; |
| const intptr_t kInstantiatorTypeArgumentsOffset = 1 * kWordSize; |
| - const Immediate& raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| // The generated code is different if the class is parameterized. |
| const bool is_cls_parameterized = cls.HasTypeArguments(); |
| ASSERT(!cls.HasTypeArguments() || |
| @@ -1085,6 +1079,7 @@ |
| const intptr_t instance_size = cls.instance_size(); |
| ASSERT(instance_size > 0); |
| const intptr_t type_args_size = InstantiatedTypeArguments::InstanceSize(); |
| + __ LoadObjectFromPool(R12, Object::Handle(), PP); |
| if (FLAG_inline_alloc && |
| Heap::IsAllocatableInNewSpace(instance_size + type_args_size)) { |
| Label slow_case; |
| @@ -1168,9 +1163,6 @@ |
| __ movq(Address(RAX, Instance::tags_offset()), Immediate(tags)); |
| // Initialize the remaining words of the object. |
| - const Immediate& raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| - |
| // RAX: new object start. |
| // RBX: next object start. |
| // RDI: new object type arguments (if is_cls_parameterized). |
| @@ -1181,7 +1173,7 @@ |
| for (intptr_t current_offset = sizeof(RawObject); |
| current_offset < instance_size; |
| current_offset += kWordSize) { |
| - __ movq(Address(RAX, current_offset), raw_null); |
| + __ movq(Address(RAX, current_offset), R12); |
| } |
| } else { |
| __ leaq(RCX, Address(RAX, sizeof(RawObject))); |
| @@ -1195,7 +1187,7 @@ |
| __ Bind(&init_loop); |
| __ cmpq(RCX, RBX); |
| __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
| - __ movq(Address(RCX, 0), raw_null); |
| + __ movq(Address(RCX, 0), R12); |
| __ addq(RCX, Immediate(kWordSize)); |
| __ jmp(&init_loop, Assembler::kNearJump); |
| __ Bind(&done); |
| @@ -1217,14 +1209,14 @@ |
| __ movq(RDX, Address(RSP, kInstantiatorTypeArgumentsOffset)); |
| } |
| // Create a stub frame. |
| - __ EnterStubFrame(); |
| - __ pushq(raw_null); // Setup space on stack for return value. |
| + __ EnterStubFrameWithPP(); |
| + __ pushq(R12); // Setup space on stack for return value. |
| __ PushObject(cls); // Push class of object to be allocated. |
| if (is_cls_parameterized) { |
| __ pushq(RAX); // Push type arguments of object to be allocated. |
| __ pushq(RDX); // Push type arguments of instantiator. |
| } else { |
| - __ pushq(raw_null); // Push null type arguments. |
| + __ pushq(R12); // Push null type arguments. |
| __ pushq(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| } |
| __ CallRuntime(kAllocateObjectRuntimeEntry, 3); // Allocate object. |
| @@ -1234,7 +1226,7 @@ |
| __ popq(RAX); // Pop result (newly allocated object). |
| // RAX: new object |
| // Restore the frame pointer. |
| - __ LeaveFrame(); |
| + __ LeaveFrameWithPP(); |
| __ ret(); |
| } |
| @@ -1246,16 +1238,17 @@ |
| // RSP : points to return address. |
| void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, |
| const Function& func) { |
| - const Immediate& raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| ASSERT(func.IsClosureFunction()); |
| ASSERT(!func.IsImplicitStaticClosureFunction()); |
| const bool is_implicit_instance_closure = |
| func.IsImplicitInstanceClosureFunction(); |
| const Class& cls = Class::ZoneHandle(func.signature_class()); |
| const bool has_type_arguments = cls.HasTypeArguments(); |
| - const intptr_t kTypeArgumentsOffset = 1 * kWordSize; |
| - const intptr_t kReceiverOffset = 2 * kWordSize; |
| + |
| + __ EnterStubFrameWithPP(); // Uses pool pointer to refer to function. |
| + __ LoadObjectFromPool(R12, Object::Handle(), PP); |
| + const intptr_t kTypeArgumentsOffset = 4 * kWordSize; |
| + const intptr_t kReceiverOffset = 5 * kWordSize; |
| const intptr_t closure_size = Closure::InstanceSize(); |
| const intptr_t context_size = Context::InstanceSize(1); // Captured receiver. |
| if (FLAG_inline_alloc && |
| @@ -1298,7 +1291,8 @@ |
| // RAX: new closure object. |
| // RBX: new context object (only if is_implicit_closure). |
| // R13: next object start. |
| - __ LoadObject(R10, func); // Load function of closure to be allocated. |
| + // Load function of closure to be allocated. |
| + __ LoadObjectFromPool(R10, func, PP); |
| __ movq(Address(RAX, Closure::function_offset()), R10); |
| // Setup the context for this closure. |
| @@ -1320,7 +1314,7 @@ |
| __ movq(Address(RBX, Context::isolate_offset()), R10); |
| // Set the parent to null. |
| - __ movq(Address(RBX, Context::parent_offset()), raw_null); |
| + __ movq(Address(RBX, Context::parent_offset()), R12); |
| // Initialize the context variable to the receiver. |
| __ movq(R10, Address(RSP, kReceiverOffset)); |
| @@ -1340,6 +1334,7 @@ |
| // Done allocating and initializing the instance. |
| // RAX: new object. |
| __ addq(RAX, Immediate(kHeapObjectTag)); |
| + __ LeaveFrameWithPP(); |
| __ ret(); |
| __ Bind(&slow_case); |
| @@ -1350,9 +1345,8 @@ |
| if (is_implicit_instance_closure) { |
| __ movq(RAX, Address(RSP, kReceiverOffset)); |
| } |
| - // Create the stub frame. |
| - __ EnterStubFrame(); |
| - __ pushq(raw_null); // Setup space on stack for the return value. |
| + |
| + __ pushq(R12); // Setup space on stack for the return value. |
| __ PushObject(func); |
| if (is_implicit_instance_closure) { |
| __ pushq(RAX); // Receiver. |
| @@ -1360,7 +1354,7 @@ |
| if (has_type_arguments) { |
| __ pushq(RCX); // Push type arguments of closure to be allocated. |
| } else { |
| - __ pushq(raw_null); // Push null type arguments. |
| + __ pushq(R12); // Push null type arguments. |
| } |
| if (is_implicit_instance_closure) { |
| __ CallRuntime(kAllocateImplicitInstanceClosureRuntimeEntry, 3); |
| @@ -1375,7 +1369,7 @@ |
| __ popq(RAX); // Pop the result. |
| // RAX: New closure object. |
| // Restore the calling frame. |
| - __ LeaveFrame(); |
| + __ LeaveFrameWithPP(); |
| __ ret(); |
| } |
| @@ -1395,9 +1389,8 @@ |
| __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
| __ movq(RAX, Address(RBP, R13, TIMES_4, kParamEndSlotFromFp * kWordSize)); |
| - const Immediate& raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| - __ pushq(raw_null); // Setup space on stack for result from noSuchMethod. |
| + __ LoadObjectFromPool(R12, Object::Handle(), PP); |
| + __ pushq(R12); // Setup space on stack for result from noSuchMethod. |
| __ pushq(RAX); // Receiver. |
| __ pushq(RBX); // IC data array. |
| __ pushq(R10); // Arguments descriptor array. |
| @@ -1545,8 +1538,7 @@ |
| __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| // IC miss. |
| - const Immediate& raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| + __ LoadObjectFromPool(R12, Object::Handle(), PP); |
| // Compute address of arguments (first read number of arguments from |
| // arguments descriptor array and then compute address on the stack). |
| __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
| @@ -1554,7 +1546,7 @@ |
| __ EnterStubFrame(); |
| __ pushq(R10); // Preserve arguments descriptor array. |
| __ pushq(RBX); // Preserve IC data object. |
| - __ pushq(raw_null); // Setup space on stack for result (target code object). |
| + __ pushq(R12); // Setup space on stack for result (target code object). |
| // Push call arguments. |
| for (intptr_t i = 0; i < num_args; i++) { |
| __ movq(RCX, Address(RAX, -kWordSize * i)); |
| @@ -1571,7 +1563,7 @@ |
| __ popq(R10); // Restore arguments descriptor array. |
| __ LeaveFrame(); |
| Label call_target_function; |
| - __ cmpq(RAX, raw_null); |
| + __ cmpq(RAX, R12); |
| __ j(NOT_EQUAL, &call_target_function, Assembler::kNearJump); |
| // NoSuchMethod or closure. |
| // Mark IC call that it may be a closure call that does not collect |
| @@ -1737,13 +1729,12 @@ |
| Immediate(Smi::RawValue(Smi::kMaxValue))); |
| __ Bind(&increment_done); |
| - const Immediate& raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| Label target_is_compiled; |
| // Get function and call it, if possible. |
| __ movq(R13, Address(R12, target_offset)); |
| __ movq(RAX, FieldAddress(R13, Function::code_offset())); |
| - __ cmpq(RAX, raw_null); |
| + __ LoadObjectFromPool(R12, Object::Handle(), PP); |
| + __ cmpq(RAX, R12); |
| __ j(NOT_EQUAL, &target_is_compiled, Assembler::kNearJump); |
| __ EnterStubFrame(); |
| @@ -1783,9 +1774,8 @@ |
| __ pushq(R10); |
| // Room for result. Debugger stub returns address of the |
| // unpatched runtime stub. |
| - const Immediate& raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| - __ pushq(raw_null); // Room for result. |
| + __ LoadObjectFromPool(R12, Object::Handle(), PP); |
| + __ pushq(R12); // Room for result. |
| __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); |
| __ popq(RAX); // Address of original. |
| __ popq(R10); // Restore arguments. |
| @@ -1798,11 +1788,10 @@ |
| // RBX: ICData (unoptimized static call) |
| // TOS(0): return address (Dart code). |
| void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { |
| - const Immediate& raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| __ EnterStubFrame(); |
| + __ LoadObjectFromPool(R12, Object::Handle(), PP); |
| __ pushq(RBX); // Preserve IC data for unoptimized call. |
| - __ pushq(raw_null); // Room for result. |
| + __ pushq(R12); // Room for result. |
| __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry, 0); |
| __ popq(RAX); // Code object. |
| __ popq(RBX); // Restore IC data. |
| @@ -1827,7 +1816,7 @@ |
| __ LeaveFrame(); |
| __ popq(R11); // discard return address of call to this stub. |
| - __ LeaveFrame(); |
| + __ LeaveFrameWithPP(); |
| __ ret(); |
| } |
| @@ -1868,17 +1857,16 @@ |
| // Result in RCX: null -> not found, otherwise result (true or false). |
| static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { |
| ASSERT((1 <= n) && (n <= 3)); |
| - const Immediate& raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; |
| const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; |
| const intptr_t kCacheOffsetInBytes = 3 * kWordSize; |
| __ movq(RAX, Address(RSP, kInstanceOffsetInBytes)); |
| + __ LoadObjectFromPool(R12, Object::Handle(), PP); |
| if (n > 1) { |
| __ LoadClass(R10, RAX); |
| // Compute instance type arguments into R13. |
| Label has_no_type_arguments; |
| - __ movq(R13, raw_null); |
| + __ movq(R13, R12); |
| __ movq(RDI, FieldAddress(R10, |
| Class::type_arguments_field_offset_in_words_offset())); |
| __ cmpq(RDI, Immediate(Class::kNoTypeArguments)); |
| @@ -1900,7 +1888,7 @@ |
| __ SmiTag(R10); |
| __ Bind(&loop); |
| __ movq(RDI, Address(RDX, kWordSize * SubtypeTestCache::kInstanceClassId)); |
| - __ cmpq(RDI, raw_null); |
| + __ cmpq(RDI, R12); |
| __ j(EQUAL, ¬_found, Assembler::kNearJump); |
| __ cmpq(RDI, R10); |
| if (n == 1) { |
| @@ -1927,7 +1915,7 @@ |
| __ jmp(&loop, Assembler::kNearJump); |
| // Fall through to not found. |
| __ Bind(¬_found); |
| - __ movq(RCX, raw_null); |
| + __ movq(RCX, R12); |
| __ ret(); |
| __ Bind(&found); |
| @@ -2060,10 +2048,10 @@ |
| __ movq(RAX, Address(RSP, 1 * kWordSize)); |
| __ cmpq(RAX, Address(RSP, 2 * kWordSize)); |
| __ j(EQUAL, &true_label, Assembler::kNearJump); |
| - __ LoadObject(RAX, Bool::False()); |
| + __ LoadObjectFromPool(RAX, Bool::False(), PP); |
| __ ret(); |
| __ Bind(&true_label); |
| - __ LoadObject(RAX, Bool::True()); |
| + __ LoadObjectFromPool(RAX, Bool::True(), PP); |
| __ ret(); |
| __ Bind(&get_class_id_as_smi); |
| @@ -2081,7 +2069,7 @@ |
| __ Bind(&update_ic_data); |
| - // RCX: ICData |
| + // RBX: ICData |
| __ movq(RAX, Address(RSP, 1 * kWordSize)); |
| __ movq(R13, Address(RSP, 2 * kWordSize)); |
| __ EnterStubFrame(); |
| @@ -2100,11 +2088,10 @@ |
| // RDI: function to be reoptimized. |
| // R10: argument descriptor (preserved). |
| void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { |
| - const Immediate& raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| - __ EnterStubFrame(); |
| + __ EnterStubFrameWithPP(); |
| + __ LoadObjectFromPool(R12, Object::Handle(), PP); |
| __ pushq(R10); |
| - __ pushq(raw_null); // Setup space on stack for return value. |
| + __ pushq(R12); // Setup space on stack for return value. |
| __ pushq(RDI); |
| __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); |
| __ popq(RAX); // Disard argument. |
| @@ -2112,7 +2099,7 @@ |
| __ popq(R10); // Restore argument descriptor. |
| __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); |
| __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| - __ LeaveFrame(); |
| + __ LeaveFrameWithPP(); |
| __ jmp(RAX); |
| __ int3(); |
| } |