Index: src/arm64/lithium-codegen-arm64.cc |
diff --git a/src/arm64/lithium-codegen-arm64.cc b/src/arm64/lithium-codegen-arm64.cc |
index c2a2ff364cc5bc80b1e29c0645a1383bbd68b067..49014109dc5e2699c0c4b789fc358ca2de313115 100644 |
--- a/src/arm64/lithium-codegen-arm64.cc |
+++ b/src/arm64/lithium-codegen-arm64.cc |
@@ -435,6 +435,7 @@ void LCodeGen::DoCallFunction(LCallFunction* instr) { |
CallFunctionStub stub(isolate(), arity, flags); |
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
} |
+ RecordPushedArgumentsDelta(instr->hydrogen()->argument_delta()); |
} |
@@ -449,6 +450,7 @@ void LCodeGen::DoCallNew(LCallNew* instr) { |
CallConstructStub stub(isolate(), NO_CALL_CONSTRUCTOR_FLAGS); |
CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); |
+ RecordPushedArgumentsDelta(instr->hydrogen()->argument_delta()); |
DCHECK(ToRegister(instr->result()).is(x0)); |
} |
@@ -504,6 +506,7 @@ void LCodeGen::DoCallNewArray(LCallNewArray* instr) { |
ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode); |
CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); |
} |
+ RecordPushedArgumentsDelta(instr->hydrogen()->argument_delta()); |
DCHECK(ToRegister(instr->result()).is(x0)); |
} |
@@ -525,7 +528,7 @@ void LCodeGen::LoadContextFromDeferred(LOperand* context) { |
if (context->IsRegister()) { |
__ Mov(cp, ToRegister(context)); |
} else if (context->IsStackSlot()) { |
- __ Ldr(cp, ToMemOperand(context)); |
+ __ Ldr(cp, ToMemOperand(context, kMustUseFramePointer)); |
} else if (context->IsConstantOperand()) { |
HConstant* constant = |
chunk_->LookupConstant(LConstantOperand::cast(context)); |
@@ -1281,13 +1284,37 @@ static int64_t ArgumentsOffsetWithoutFrame(int index) { |
} |
-MemOperand LCodeGen::ToMemOperand(LOperand* op) const { |
+MemOperand LCodeGen::ToMemOperand(LOperand* op, StackMode stack_mode) const { |
DCHECK(op != NULL); |
DCHECK(!op->IsRegister()); |
DCHECK(!op->IsDoubleRegister()); |
DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); |
if (NeedsEagerFrame()) { |
- return MemOperand(fp, StackSlotOffset(op->index())); |
+ int fp_offset = StackSlotOffset(op->index()); |
+ // Loads and stores have a bigger reach in positive offset than negative. |
+ // We try to access using jssp (positive offset) first, then fall back to |
+ // fp (negative offset) if that fails. |
+ // |
+ // We can reference a stack slot from jssp only if we know how much we've |
+ // put on the stack. We don't know this in the following cases: |
+ // - stack_mode != kCanUseStackPointer: this is the case when deferred |
+ // code has saved the registers. |
+ // - saves_caller_doubles(): some double registers have been pushed, jssp |
+ // references the end of the double registers and not the end of the stack |
+ // slots. |
+ // In both of the cases above, we _could_ add the tracking information |
+ // required so that we can use jssp here, but in practice it isn't worth it. |
+ if ((stack_mode == kCanUseStackPointer) && |
+ !info()->saves_caller_doubles()) { |
+ int jssp_offset_to_fp = |
+ StandardFrameConstants::kFixedFrameSizeFromFp + |
+ (pushed_arguments_ + GetStackSlotCount()) * kPointerSize; |
+ int jssp_offset = fp_offset + jssp_offset_to_fp; |
+ if (masm()->IsImmLSScaled(jssp_offset, LSDoubleWord)) { |
+ return MemOperand(masm()->StackPointer(), jssp_offset); |
+ } |
+ } |
+ return MemOperand(fp, fp_offset); |
} else { |
// Retrieve parameter without eager stack-frame relative to the |
// stack-pointer. |
@@ -2085,6 +2112,8 @@ void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { |
} |
generator.AfterCall(); |
} |
+ |
+ RecordPushedArgumentsDelta(instr->hydrogen()->argument_delta()); |
} |
@@ -2104,11 +2133,13 @@ void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) { |
__ Call(x10); |
RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
+ RecordPushedArgumentsDelta(instr->hydrogen()->argument_delta()); |
} |
void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
CallRuntime(instr->function(), instr->arity(), instr); |
+ RecordPushedArgumentsDelta(instr->hydrogen()->argument_delta()); |
} |
@@ -2134,6 +2165,7 @@ void LCodeGen::DoCallStub(LCallStub* instr) { |
default: |
UNREACHABLE(); |
} |
+ RecordPushedArgumentsDelta(instr->hydrogen()->argument_delta()); |
} |
@@ -3196,6 +3228,7 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
instr->hydrogen()->formal_parameter_count(), |
instr->arity(), instr); |
} |
+ RecordPushedArgumentsDelta(instr->hydrogen()->argument_delta()); |
} |
@@ -3309,6 +3342,16 @@ void LCodeGen::DoLabel(LLabel* label) { |
label->block_id(), |
LabelType(label)); |
+ // Inherit pushed_arguments_ from the predecessor's argument count. |
+ if (label->block()->HasPredecessor()) { |
+ pushed_arguments_ = label->block()->predecessors()->at(0)->argument_count(); |
+#ifdef DEBUG |
+ for (auto p : *label->block()->predecessors()) { |
+ DCHECK_EQ(p->argument_count(), pushed_arguments_); |
+ } |
+#endif |
+ } |
+ |
__ Bind(label->label()); |
current_block_ = label->block_id(); |
DoGap(label); |
@@ -4754,6 +4797,8 @@ void LCodeGen::DoPushArguments(LPushArguments* instr) { |
// The preamble was done by LPreparePushArguments. |
args.PushQueued(MacroAssembler::PushPopQueue::SKIP_PREAMBLE); |
+ |
+ RecordPushedArgumentsDelta(instr->ArgumentCount()); |
} |