CallFunctionStub stub(isolate(), arity, flags);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
}
+ RecordPushedArgumentsDelta(instr->hydrogen()->argument_delta());
}
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));
}
ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode);
CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
}
+ RecordPushedArgumentsDelta(instr->hydrogen()->argument_delta());
DCHECK(ToRegister(instr->result()).is(x0));
}
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));
}
-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.
}
generator.AfterCall();
}
+
+ RecordPushedArgumentsDelta(instr->hydrogen()->argument_delta());
}
__ 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());
}
default:
UNREACHABLE();
}
+ RecordPushedArgumentsDelta(instr->hydrogen()->argument_delta());
}
instr->hydrogen()->formal_parameter_count(),
instr->arity(), instr);
}
+ RecordPushedArgumentsDelta(instr->hydrogen()->argument_delta());
}
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);
// The preamble was done by LPreparePushArguments.
args.PushQueued(MacroAssembler::PushPopQueue::SKIP_PREAMBLE);
+
+ RecordPushedArgumentsDelta(instr->ArgumentCount());
}
frame_is_built_(false),
safepoints_(info->zone()),
resolver_(this),
- expected_safepoint_kind_(Safepoint::kSimple) {
+ expected_safepoint_kind_(Safepoint::kSimple),
+ pushed_arguments_(0) {
PopulateDeoptimizationLiteralsWithInlinedFunctions();
}
Register ToRegister32(LOperand* op) const;
Operand ToOperand(LOperand* op);
Operand ToOperand32(LOperand* op);
- MemOperand ToMemOperand(LOperand* op) const;
+ enum StackMode { kMustUseFramePointer, kCanUseStackPointer };
+ MemOperand ToMemOperand(LOperand* op,
+ StackMode stack_mode = kCanUseStackPointer) const;
Handle<Object> ToHandle(LConstantOperand* op) const;
template <class LI>
Safepoint::Kind expected_safepoint_kind_;
+ // The number of arguments pushed onto the stack, either by this block or by a
+ // predecessor.
+ int pushed_arguments_;
+
+ void RecordPushedArgumentsDelta(int delta) {
+ pushed_arguments_ += delta;
+ DCHECK(pushed_arguments_ >= 0);
+ }
+
int old_position_;
class PushSafepointRegistersScope BASE_EMBEDDED {