| Index: src/compiler/arm64/code-generator-arm64.cc | 
| diff --git a/src/compiler/arm64/code-generator-arm64.cc b/src/compiler/arm64/code-generator-arm64.cc | 
| index da4fb8f7e9940084741ecc36156a0c5b1cb8fd61..456e7e76080be17551f644b38f834679ee8afd30 100644 | 
| --- a/src/compiler/arm64/code-generator-arm64.cc | 
| +++ b/src/compiler/arm64/code-generator-arm64.cc | 
| @@ -279,7 +279,8 @@ class OutOfLineRecordWrite final : public OutOfLineCode { | 
| value_(value), | 
| scratch0_(scratch0), | 
| scratch1_(scratch1), | 
| -        mode_(mode) {} | 
| +        mode_(mode), | 
| +        must_save_lr_(!gen->frame_access_state()->has_frame()) {} | 
|  | 
| void Generate() final { | 
| if (mode_ > RecordWriteMode::kValueIsPointer) { | 
| @@ -293,7 +294,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode { | 
| : OMIT_REMEMBERED_SET; | 
| SaveFPRegsMode const save_fp_mode = | 
| frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; | 
| -    if (!frame()->needs_frame()) { | 
| +    if (must_save_lr_) { | 
| // We need to save and restore lr if the frame was elided. | 
| __ Push(lr); | 
| } | 
| @@ -301,7 +302,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode { | 
| remembered_set_action, save_fp_mode); | 
| __ Add(scratch1_, object_, index_); | 
| __ CallStub(&stub); | 
| -    if (!frame()->needs_frame()) { | 
| +    if (must_save_lr_) { | 
| __ Pop(lr); | 
| } | 
| } | 
| @@ -313,6 +314,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode { | 
| Register const scratch0_; | 
| Register const scratch1_; | 
| RecordWriteMode const mode_; | 
| +  bool must_save_lr_; | 
| }; | 
|  | 
|  | 
| @@ -466,6 +468,15 @@ Condition FlagsConditionToCondition(FlagsCondition condition) { | 
| }                                                                       \ | 
| } while (0) | 
|  | 
| +void CodeGenerator::AssembleDeconstructFrame() { | 
| +  const CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 
| +  if (descriptor->IsCFunctionCall() || descriptor->UseNativeStack()) { | 
| +    __ Mov(csp, fp); | 
| +  } else { | 
| +    __ Mov(jssp, fp); | 
| +  } | 
| +  __ Pop(fp, lr); | 
| +} | 
|  | 
| void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { | 
| int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); | 
| @@ -482,7 +493,7 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { | 
| __ Claim(-sp_slot_delta); | 
| frame_access_state()->IncreaseSPDelta(-sp_slot_delta); | 
| } | 
| -  if (frame()->needs_frame()) { | 
| +  if (frame_access_state()->has_frame()) { | 
| __ Ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); | 
| __ Ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 
| } | 
| @@ -672,7 +683,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { | 
| __ mov(i.OutputRegister(), fp); | 
| break; | 
| case kArchParentFramePointer: | 
| -      if (frame_access_state()->frame()->needs_frame()) { | 
| +      if (frame_access_state()->has_frame()) { | 
| __ ldr(i.OutputRegister(), MemOperand(fp, 0)); | 
| } else { | 
| __ mov(i.OutputRegister(), fp); | 
| @@ -1492,6 +1503,14 @@ void CodeGenerator::AssembleDeoptimizerCall( | 
| __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); | 
| } | 
|  | 
| +void CodeGenerator::AssembleSetupStackPointer() { | 
| +  const CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 
| +  if (descriptor->UseNativeStack() || descriptor->IsCFunctionCall()) { | 
| +    __ SetStackPointer(csp); | 
| +  } else { | 
| +    __ SetStackPointer(jssp); | 
| +  } | 
| +} | 
|  | 
| void CodeGenerator::AssemblePrologue() { | 
| CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 
| @@ -1499,19 +1518,12 @@ void CodeGenerator::AssemblePrologue() { | 
| __ AssertCspAligned(); | 
| } | 
|  | 
| -  frame()->AlignFrame(16); | 
| int stack_shrink_slots = frame()->GetSpillSlotCount(); | 
| -  if (frame()->needs_frame()) { | 
| +  if (frame_access_state()->has_frame()) { | 
| if (descriptor->IsJSFunctionCall()) { | 
| DCHECK(!descriptor->UseNativeStack()); | 
| -      __ SetStackPointer(jssp); | 
| __ Prologue(this->info()->GeneratePreagedPrologue()); | 
| } else { | 
| -      if (descriptor->UseNativeStack() || descriptor->IsCFunctionCall()) { | 
| -        __ SetStackPointer(csp); | 
| -      } else { | 
| -        __ SetStackPointer(jssp); | 
| -      } | 
| if (descriptor->IsCFunctionCall()) { | 
| __ Push(lr, fp); | 
| __ Mov(fp, masm_.StackPointer()); | 
| @@ -1521,15 +1533,8 @@ void CodeGenerator::AssemblePrologue() { | 
| frame()->GetTotalFrameSlotCount()); | 
| } | 
| } | 
| -  } else { | 
| -    if (descriptor->UseNativeStack()) { | 
| -      __ SetStackPointer(csp); | 
| -    } else { | 
| -      __ SetStackPointer(jssp); | 
| -    } | 
| -    frame()->SetElidedFrameSizeInSlots(0); | 
| } | 
| -  frame_access_state()->SetFrameAccessToDefault(); | 
| + | 
| if (info()->is_osr()) { | 
| // TurboFan OSR-compiled functions cannot be entered directly. | 
| __ Abort(kShouldNotDirectlyEnterOsrFunction); | 
| @@ -1590,22 +1595,18 @@ void CodeGenerator::AssembleReturn() { | 
|  | 
| int pop_count = static_cast<int>(descriptor->StackParameterCount()); | 
| if (descriptor->IsCFunctionCall()) { | 
| -    __ Mov(csp, fp); | 
| -    __ Pop(fp, lr); | 
| -  } else if (frame()->needs_frame()) { | 
| +    AssembleDeconstructFrame(); | 
| +  } else if (frame_access_state()->has_frame()) { | 
| // Canonicalize JSFunction return sites for now. | 
| if (return_label_.is_bound()) { | 
| __ B(&return_label_); | 
| return; | 
| } else { | 
| __ Bind(&return_label_); | 
| +      AssembleDeconstructFrame(); | 
| if (descriptor->UseNativeStack()) { | 
| -        __ Mov(csp, fp); | 
| pop_count += (pop_count & 1);  // align | 
| -      } else { | 
| -        __ Mov(jssp, fp); | 
| } | 
| -      __ Pop(fp, lr); | 
| } | 
| } else if (descriptor->UseNativeStack()) { | 
| pop_count += (pop_count & 1);  // align | 
|  |