| Index: runtime/vm/stub_code_x64.cc | 
| =================================================================== | 
| --- runtime/vm/stub_code_x64.cc	(revision 27291) | 
| +++ 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); | 
| +  __ LoadObject(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); | 
| +  __ LoadObject(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); | 
| +  __ LoadObject(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())); | 
| - | 
| +  __ LoadObject(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); | 
| +  __ 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,21 @@ | 
| __ movq(RBX, Address(RBP, saved_result_slot_from_fp * kWordSize)); | 
| } | 
|  | 
| +  // There is a Dart Frame on the stack. We just need the PP. | 
| +  __ movq(PP, Address(RBP, -2 * kWordSize)); | 
| __ LeaveFrame(); | 
| + | 
| __ 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); | 
| +  __ pushq(Immediate(0)); | 
| +  __ pushq(PP); | 
| + | 
| if (preserve_result) { | 
| __ pushq(RBX);  // Preserve result as first local. | 
| } | 
| @@ -441,6 +444,8 @@ | 
| __ movq(RBX, Address(RBP, kFirstLocalSlotFromFp * kWordSize)); | 
| } | 
| // Code above cannot cause GC. | 
| +  // There is a Dart Frame on the stack. We just need the PP. | 
| +  __ movq(PP, Address(RBP, -2 * kWordSize)); | 
| __ LeaveFrame(); | 
|  | 
| // Frame is fully rewritten at this point and it is safe to perform a GC. | 
| @@ -486,20 +491,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 +516,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 +537,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 +625,14 @@ | 
| __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); | 
| // RBX: iterator which initially points to the start of the variable | 
| // data area to be initialized. | 
| +    __ LoadObject(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 +649,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 +668,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. | 
|  | 
| +  __ LoadObject(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 +686,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 +698,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 +737,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 +765,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 +796,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 +808,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 +885,7 @@ | 
| // Output: | 
| // RAX: new allocated RawContext object. | 
| void StubCode::GenerateAllocateContextStub(Assembler* assembler) { | 
| -  const Immediate& raw_null = | 
| -      Immediate(reinterpret_cast<intptr_t>(Object::null())); | 
| +  __ LoadObject(R12, Object::Handle(), PP); | 
| if (FLAG_inline_alloc) { | 
| const Class& context_class = Class::ZoneHandle(Object::context_class()); | 
| Label slow_case; | 
| @@ -957,12 +960,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 +975,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 +989,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 +1073,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 +1084,7 @@ | 
| const intptr_t instance_size = cls.instance_size(); | 
| ASSERT(instance_size > 0); | 
| const intptr_t type_args_size = InstantiatedTypeArguments::InstanceSize(); | 
| +  __ LoadObject(R12, Object::Handle(), PP); | 
| if (FLAG_inline_alloc && | 
| Heap::IsAllocatableInNewSpace(instance_size + type_args_size)) { | 
| Label slow_case; | 
| @@ -1168,9 +1168,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 +1178,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 +1192,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 +1214,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 +1231,7 @@ | 
| __ popq(RAX);  // Pop result (newly allocated object). | 
| // RAX: new object | 
| // Restore the frame pointer. | 
| -  __ LeaveFrame(); | 
| +  __ LeaveFrameWithPP(); | 
| __ ret(); | 
| } | 
|  | 
| @@ -1246,16 +1243,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. | 
| +  __ LoadObject(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 +1296,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. | 
| +    __ LoadObject(R10, func, PP); | 
| __ movq(Address(RAX, Closure::function_offset()), R10); | 
|  | 
| // Setup the context for this closure. | 
| @@ -1320,7 +1319,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 +1339,7 @@ | 
| // Done allocating and initializing the instance. | 
| // RAX: new object. | 
| __ addq(RAX, Immediate(kHeapObjectTag)); | 
| +    __ LeaveFrameWithPP(); | 
| __ ret(); | 
|  | 
| __ Bind(&slow_case); | 
| @@ -1350,9 +1350,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 +1359,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 +1374,7 @@ | 
| __ popq(RAX);  // Pop the result. | 
| // RAX: New closure object. | 
| // Restore the calling frame. | 
| -  __ LeaveFrame(); | 
| +  __ LeaveFrameWithPP(); | 
| __ ret(); | 
| } | 
|  | 
| @@ -1395,9 +1394,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. | 
| +  __ LoadObject(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 +1543,7 @@ | 
| __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 
|  | 
| // IC miss. | 
| -  const Immediate& raw_null = | 
| -      Immediate(reinterpret_cast<intptr_t>(Object::null())); | 
| +  __ LoadObject(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 +1551,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 +1568,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 +1734,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); | 
| +  __ LoadObject(R12, Object::Handle(), PP); | 
| +  __ cmpq(RAX, R12); | 
| __ j(NOT_EQUAL, &target_is_compiled, Assembler::kNearJump); | 
|  | 
| __ EnterStubFrame(); | 
| @@ -1783,9 +1779,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. | 
| +  __ LoadObject(R12, Object::Handle(), PP); | 
| +  __ pushq(R12);  // Room for result. | 
| __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); | 
| __ popq(RAX);  // Address of original. | 
| __ popq(R10);  // Restore arguments. | 
| @@ -1798,11 +1793,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(); | 
| +  __ LoadObject(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 +1821,7 @@ | 
| __ LeaveFrame(); | 
|  | 
| __ popq(R11);  // discard return address of call to this stub. | 
| -  __ LeaveFrame(); | 
| +  __ LeaveFrameWithPP(); | 
| __ ret(); | 
| } | 
|  | 
| @@ -1868,17 +1862,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)); | 
| +  __ LoadObject(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 +1893,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 +1920,7 @@ | 
| __ jmp(&loop, Assembler::kNearJump); | 
| // Fall through to not found. | 
| __ Bind(¬_found); | 
| -  __ movq(RCX, raw_null); | 
| +  __ movq(RCX, R12); | 
| __ ret(); | 
|  | 
| __ Bind(&found); | 
| @@ -2060,10 +2053,10 @@ | 
| __ movq(RAX, Address(RSP, 1 * kWordSize)); | 
| __ cmpq(RAX, Address(RSP, 2 * kWordSize)); | 
| __ j(EQUAL, &true_label, Assembler::kNearJump); | 
| -  __ LoadObject(RAX, Bool::False()); | 
| +  __ LoadObject(RAX, Bool::False(), PP); | 
| __ ret(); | 
| __ Bind(&true_label); | 
| -  __ LoadObject(RAX, Bool::True()); | 
| +  __ LoadObject(RAX, Bool::True(), PP); | 
| __ ret(); | 
|  | 
| __ Bind(&get_class_id_as_smi); | 
| @@ -2081,7 +2074,7 @@ | 
|  | 
| __ Bind(&update_ic_data); | 
|  | 
| -  // RCX: ICData | 
| +  // RBX: ICData | 
| __ movq(RAX, Address(RSP, 1 * kWordSize)); | 
| __ movq(R13, Address(RSP, 2 * kWordSize)); | 
| __ EnterStubFrame(); | 
| @@ -2100,11 +2093,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(); | 
| +  __ LoadObject(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 +2104,7 @@ | 
| __ popq(R10);  // Restore argument descriptor. | 
| __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); | 
| __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 
| -  __ LeaveFrame(); | 
| +  __ LeaveFrameWithPP(); | 
| __ jmp(RAX); | 
| __ int3(); | 
| } | 
|  |