Index: src/arm64/lithium-codegen-arm64.cc |
diff --git a/src/arm64/lithium-codegen-arm64.cc b/src/arm64/lithium-codegen-arm64.cc |
index 3ecd2403ba3b6aa0848006d90439a11b746e0bc3..725d1f2e42a5fffc75fe30e2be57ff8f1ee52023 100644 |
--- a/src/arm64/lithium-codegen-arm64.cc |
+++ b/src/arm64/lithium-codegen-arm64.cc |
@@ -409,6 +409,7 @@ void LCodeGen::DoCallFunction(LCallFunction* instr) { |
int arity = instr->arity(); |
CallFunctionStub stub(isolate(), arity, instr->hydrogen()->function_flags()); |
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
+ after_push_argument_ = false; |
} |
@@ -423,6 +424,7 @@ void LCodeGen::DoCallNew(LCallNew* instr) { |
CallConstructStub stub(isolate(), NO_CALL_FUNCTION_FLAGS); |
CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); |
+ after_push_argument_ = false; |
ASSERT(ToRegister(instr->result()).is(x0)); |
} |
@@ -470,6 +472,7 @@ void LCodeGen::DoCallNewArray(LCallNewArray* instr) { |
ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode); |
CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); |
} |
+ after_push_argument_ = false; |
ASSERT(ToRegister(instr->result()).is(x0)); |
} |
@@ -491,7 +494,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)); |
@@ -1232,13 +1235,38 @@ static ptrdiff_t ArgumentsOffsetWithoutFrame(ptrdiff_t index) { |
} |
-MemOperand LCodeGen::ToMemOperand(LOperand* op) const { |
+MemOperand LCodeGen::ToMemOperand(LOperand* op, StackMode stack_mode) const { |
ASSERT(op != NULL); |
ASSERT(!op->IsRegister()); |
ASSERT(!op->IsDoubleRegister()); |
ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); |
if (NeedsEagerFrame()) { |
- return MemOperand(fp, StackSlotOffset(op->index())); |
+ int fp_offset = StackSlotOffset(op->index()); |
+ if (op->index() >= 0) { |
+ // Loads and stores have a bigger reach in positive offset than negative. |
+ // When the load or the store can't be done in one instruction via fp |
+ // (too big negative offset), we try to access via jssp (positive offset). |
+ // We can reference a stack slot from jssp only if jssp references the end |
+ // of the stack slots. It's not the case when: |
+ // - stack_mode != kCanUseStackPointer: this is the case when a deferred |
+ // code saved the registers. |
+ // - after_push_argument_: arguments has been pushed for a call. |
+ // - inlined_arguments_: inlined arguments have been pushed once. All the |
+ // remainder of the function cannot trust jssp any longer. |
+ // - 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. |
+ // Also, if the offset from fp is small enough to make a load/store in |
+ // one instruction, we use a fp access. |
+ if ((stack_mode == kCanUseStackPointer) && !after_push_argument_ && |
+ !inlined_arguments_ && !is_int9(fp_offset) && |
+ !info()->saves_caller_doubles()) { |
+ int jssp_offset = |
+ (GetStackSlotCount() - op->index() - 1) * kPointerSize; |
+ return MemOperand(masm()->StackPointer(), jssp_offset); |
+ } |
+ } |
+ return MemOperand(fp, fp_offset); |
} else { |
// Retrieve parameter without eager stack-frame relative to the |
// stack-pointer. |
@@ -1628,6 +1656,10 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
+ // We push some arguments and they will be pop in an other block. We can't |
+ // trust that jssp references the end of the stack slots until the end of |
+ // the function. |
+ inlined_arguments_ = true; |
Register result = ToRegister(instr->result()); |
if (instr->hydrogen()->from_inlined()) { |
@@ -1996,6 +2028,7 @@ void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { |
__ Call(target); |
} |
generator.AfterCall(); |
+ after_push_argument_ = false; |
} |
@@ -2015,11 +2048,13 @@ void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) { |
__ Call(x10); |
RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
+ after_push_argument_ = false; |
} |
void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
CallRuntime(instr->function(), instr->arity(), instr); |
+ after_push_argument_ = false; |
} |
@@ -2045,6 +2080,7 @@ void LCodeGen::DoCallStub(LCallStub* instr) { |
default: |
UNREACHABLE(); |
} |
+ after_push_argument_ = false; |
} |
@@ -3102,6 +3138,7 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
instr, |
x1); |
} |
+ after_push_argument_ = false; |
} |
@@ -4575,6 +4612,7 @@ void LCodeGen::DoPushArgument(LPushArgument* instr) { |
Abort(kDoPushArgumentNotImplementedForDoubleType); |
} else { |
__ Push(ToRegister(argument)); |
+ after_push_argument_ = true; |
} |
} |