| Index: src/arm/lithium-codegen-arm.cc
|
| diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
|
| index dbcf4e4157d3f0399d88ddb80927ae6d527b625f..d918cc9337ee874cd8424ddb4ccf090df3642559 100644
|
| --- a/src/arm/lithium-codegen-arm.cc
|
| +++ b/src/arm/lithium-codegen-arm.cc
|
| @@ -150,11 +150,12 @@ bool LCodeGen::GeneratePrologue() {
|
|
|
| info()->set_prologue_offset(masm_->pc_offset());
|
| if (NeedsEagerFrame()) {
|
| + fp_sp_delta_ = 2 * kPointerSize;
|
| if (info()->IsStub()) {
|
| __ stm(db_w, sp, cp.bit() | fp.bit() | lr.bit());
|
| __ Push(Smi::FromInt(StackFrame::STUB));
|
| // Adjust FP to point to saved FP.
|
| - __ add(fp, sp, Operand(2 * kPointerSize));
|
| + __ add(fp, sp, Operand(fp_sp_delta_));
|
| } else {
|
| PredictableCodeSizeScope predictible_code_size_scope(
|
| masm_, kNoCodeAgeSequenceLength * Assembler::kInstrSize);
|
| @@ -166,7 +167,7 @@ bool LCodeGen::GeneratePrologue() {
|
| __ nop(ip.code());
|
| }
|
| // Adjust FP to point to saved FP.
|
| - __ add(fp, sp, Operand(2 * kPointerSize));
|
| + __ add(fp, sp, Operand(fp_sp_delta_));
|
| }
|
| frame_is_built_ = true;
|
| info_->AddNoFrameRange(0, masm_->pc_offset());
|
| @@ -175,11 +176,13 @@ bool LCodeGen::GeneratePrologue() {
|
| // Reserve space for the stack slots needed by the code.
|
| int slots = GetStackSlotCount();
|
| if (slots > 0) {
|
| + int slots_size = slots * kPointerSize;
|
| + fp_sp_delta_ += slots_size;
|
| if (FLAG_debug_code) {
|
| - __ sub(sp, sp, Operand(slots * kPointerSize));
|
| + __ sub(sp, sp, Operand(slots_size));
|
| __ push(r0);
|
| __ push(r1);
|
| - __ add(r0, sp, Operand(slots * kPointerSize));
|
| + __ add(r0, sp, Operand(slots_size));
|
| __ mov(r1, Operand(kSlotsZapValue));
|
| Label loop;
|
| __ bind(&loop);
|
| @@ -190,7 +193,7 @@ bool LCodeGen::GeneratePrologue() {
|
| __ pop(r1);
|
| __ pop(r0);
|
| } else {
|
| - __ sub(sp, sp, Operand(slots * kPointerSize));
|
| + __ sub(sp, sp, Operand(slots_size));
|
| }
|
| }
|
|
|
| @@ -210,6 +213,7 @@ bool LCodeGen::GeneratePrologue() {
|
| // Possibly allocate a local context.
|
| int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
|
| if (heap_slots > 0) {
|
| + ASSERT(frame_is_built_);
|
| Comment(";;; Allocate local context");
|
| // Argument to NewContext is the function, which is in r1.
|
| __ push(r1);
|
| @@ -222,16 +226,17 @@ bool LCodeGen::GeneratePrologue() {
|
| RecordSafepoint(Safepoint::kNoLazyDeopt);
|
| // Context is returned in both r0 and cp. It replaces the context
|
| // passed to us. It's saved in the stack and kept live in cp.
|
| - __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
| + int cp_offset = StandardFrameConstants::kContextOffset + fp_sp_delta_;
|
| + __ str(cp, MemOperand(sp, cp_offset));
|
| // Copy any necessary parameters into the context.
|
| int num_parameters = scope()->num_parameters();
|
| for (int i = 0; i < num_parameters; i++) {
|
| Variable* var = scope()->parameter(i);
|
| if (var->IsContextSlot()) {
|
| int parameter_offset = StandardFrameConstants::kCallerSPOffset +
|
| - (num_parameters - 1 - i) * kPointerSize;
|
| + (num_parameters - 1 - i) * kPointerSize + fp_sp_delta_;
|
| // Load parameter from stack.
|
| - __ ldr(r0, MemOperand(fp, parameter_offset));
|
| + __ ldr(r0, MemOperand(sp, parameter_offset));
|
| // Store it in the context.
|
| MemOperand target = ContextOperand(cp, var->index());
|
| __ str(r0, target);
|
| @@ -266,7 +271,15 @@ bool LCodeGen::GenerateBody() {
|
|
|
| // Don't emit code for basic blocks with a replacement.
|
| if (instr->IsLabel()) {
|
| - emit_instructions = !LLabel::cast(instr)->HasReplacement();
|
| + LLabel* label = LLabel::cast(instr);
|
| + emit_instructions = !label->HasReplacement();
|
| + if (emit_instructions) {
|
| + HBasicBlock* block = label->block();
|
| + int argument_count = block->HasPredecessor()
|
| + ? block->predecessors()->at(0)->argument_count()
|
| + : 0;
|
| + SetFpSpDelta(argument_count);
|
| + }
|
| }
|
| if (!emit_instructions) continue;
|
|
|
| @@ -307,10 +320,11 @@ bool LCodeGen::GenerateDeferredCode() {
|
| ASSERT(!frame_is_built_);
|
| ASSERT(info()->IsStub());
|
| frame_is_built_ = true;
|
| + fp_sp_delta_ = 2 * kPointerSize;
|
| __ stm(db_w, sp, cp.bit() | fp.bit() | lr.bit());
|
| __ mov(scratch0(), Operand(Smi::FromInt(StackFrame::STUB)));
|
| __ push(scratch0());
|
| - __ add(fp, sp, Operand(2 * kPointerSize));
|
| + __ add(fp, sp, Operand(fp_sp_delta_));
|
| Comment(";;; Deferred code");
|
| }
|
| code->Generate();
|
| @@ -320,6 +334,7 @@ bool LCodeGen::GenerateDeferredCode() {
|
| __ pop(ip);
|
| __ ldm(ia_w, sp, cp.bit() | fp.bit() | lr.bit());
|
| frame_is_built_ = false;
|
| + fp_sp_delta_ = -1;
|
| }
|
| __ jmp(code->exit());
|
| }
|
| @@ -375,7 +390,8 @@ bool LCodeGen::GenerateDeoptJumpTable() {
|
| ASSERT(info()->IsStub());
|
| __ mov(scratch0(), Operand(Smi::FromInt(StackFrame::STUB)));
|
| __ push(scratch0());
|
| - __ add(fp, sp, Operand(2 * kPointerSize));
|
| + fp_sp_delta_ = 2 * kPointerSize;
|
| + __ add(fp, sp, Operand(fp_sp_delta_));
|
| __ mov(lr, Operand(pc), LeaveCC, al);
|
| __ mov(pc, ip);
|
| }
|
| @@ -563,13 +579,14 @@ MemOperand LCodeGen::ToMemOperand(LOperand* op) const {
|
| ASSERT(!op->IsRegister());
|
| ASSERT(!op->IsDoubleRegister());
|
| ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot());
|
| - return MemOperand(fp, StackSlotOffset(op->index()));
|
| + return MemOperand(sp, StackSlotOffset(op->index(), fp_sp_delta_));
|
| }
|
|
|
|
|
| MemOperand LCodeGen::ToHighMemOperand(LOperand* op) const {
|
| ASSERT(op->IsDoubleStackSlot());
|
| - return MemOperand(fp, StackSlotOffset(op->index()) + kPointerSize);
|
| + int offset = StackSlotOffset(op->index(), fp_sp_delta_) + kPointerSize;
|
| + return MemOperand(sp, offset);
|
| }
|
|
|
|
|
| @@ -701,16 +718,67 @@ void LCodeGen::AddToTranslation(LEnvironment* environment,
|
| }
|
|
|
|
|
| +void LCodeGen::SetFpSpDelta(int argument_count) {
|
| + int slots_size = GetStackSlotCount() * kPointerSize;
|
| + int args_size = argument_count * kPointerSize;
|
| + int fixed_size = 2 * kPointerSize;
|
| + fp_sp_delta_ = slots_size + args_size + fixed_size;
|
| +}
|
| +
|
| +
|
| +void LCodeGen::Push(Register src1) {
|
| + fp_sp_delta_ += kPointerSize;
|
| + __ push(src1);
|
| +}
|
| +
|
| +
|
| +void LCodeGen::Push(Register src1, Register src2) {
|
| + fp_sp_delta_ += 2 * kPointerSize;
|
| + __ Push(src1, src2);
|
| +}
|
| +
|
| +
|
| +void LCodeGen::Push(Register src1, Register src2, Register src3) {
|
| + fp_sp_delta_ += 3 * kPointerSize;
|
| + __ Push(src1, src2, src3);
|
| +}
|
| +
|
| +
|
| +void LCodeGen::Push(Register src1,
|
| + Register src2,
|
| + Register src3,
|
| + Register src4) {
|
| + fp_sp_delta_ += 4 * kPointerSize;
|
| + __ Push(src1, src2, src3, src4);
|
| +}
|
| +
|
| +
|
| +#ifdef DEBUG
|
| +void LCodeGen::CheckFpSpDelta(LInstruction* instr) {
|
| + if (fp_sp_delta_ == -1 || !instr->HasEnvironment())
|
| + return;
|
| + int slots_size = GetStackSlotCount() * kPointerSize;
|
| + int args_size = instr->environment()->arguments_stack_height() * kPointerSize;
|
| + int fixed_size = 2 * kPointerSize;
|
| + int expected_delta = slots_size + args_size + fixed_size;
|
| + ASSERT_EQ(expected_delta, fp_sp_delta_);
|
| +}
|
| +#endif // DEBUG
|
| +
|
| +
|
| void LCodeGen::CallCode(Handle<Code> code,
|
| RelocInfo::Mode mode,
|
| + int num_arguments,
|
| LInstruction* instr,
|
| TargetAddressStorageMode storage_mode) {
|
| - CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT, storage_mode);
|
| + CallCodeGeneric(code, mode, num_arguments, instr, RECORD_SIMPLE_SAFEPOINT,
|
| + storage_mode);
|
| }
|
|
|
|
|
| void LCodeGen::CallCodeGeneric(Handle<Code> code,
|
| RelocInfo::Mode mode,
|
| + int num_arguments,
|
| LInstruction* instr,
|
| SafepointMode safepoint_mode,
|
| TargetAddressStorageMode storage_mode) {
|
| @@ -722,6 +790,7 @@ void LCodeGen::CallCodeGeneric(Handle<Code> code,
|
| LPointerMap* pointers = instr->pointer_map();
|
| RecordPosition(pointers->position());
|
| __ Call(code, mode, TypeFeedbackId::None(), al, storage_mode);
|
| + fp_sp_delta_ -= num_arguments * kPointerSize;
|
| RecordSafepointWithLazyDeopt(instr, safepoint_mode);
|
|
|
| // Signal that we don't inline smi code before these stubs in the
|
| @@ -742,6 +811,7 @@ void LCodeGen::CallRuntime(const Runtime::Function* function,
|
| RecordPosition(pointers->position());
|
|
|
| __ CallRuntime(function, num_arguments);
|
| + fp_sp_delta_ -= num_arguments * kPointerSize;
|
| RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
|
| }
|
|
|
| @@ -750,6 +820,7 @@ void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
|
| int argc,
|
| LInstruction* instr) {
|
| __ CallRuntimeSaveDoubles(id);
|
| + fp_sp_delta_ -= argc * kPointerSize;
|
| RecordSafepointWithRegisters(
|
| instr->pointer_map(), argc, Safepoint::kNoLazyDeopt);
|
| }
|
| @@ -1069,34 +1140,34 @@ void LCodeGen::DoCallStub(LCallStub* instr) {
|
| switch (instr->hydrogen()->major_key()) {
|
| case CodeStub::RegExpConstructResult: {
|
| RegExpConstructResultStub stub;
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| + CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 3, instr);
|
| break;
|
| }
|
| case CodeStub::RegExpExec: {
|
| RegExpExecStub stub;
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| + CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 4, instr);
|
| break;
|
| }
|
| case CodeStub::SubString: {
|
| SubStringStub stub;
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| + CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 3, instr);
|
| break;
|
| }
|
| case CodeStub::NumberToString: {
|
| NumberToStringStub stub;
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| + CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 1, instr);
|
| break;
|
| }
|
| case CodeStub::StringCompare: {
|
| StringCompareStub stub;
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| + CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 2, instr);
|
| break;
|
| }
|
| case CodeStub::TranscendentalCache: {
|
| __ ldr(r0, MemOperand(sp, 0));
|
| TranscendentalCacheStub stub(instr->transcendental_type(),
|
| TranscendentalCacheStub::TAGGED);
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| + CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 1, instr);
|
| break;
|
| }
|
| default:
|
| @@ -2002,7 +2073,7 @@ void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
|
|
|
| void LCodeGen::DoThrow(LThrow* instr) {
|
| Register input_reg = EmitLoadRegister(instr->value(), ip);
|
| - __ push(input_reg);
|
| + Push(input_reg);
|
| CallRuntime(Runtime::kThrow, 1, instr);
|
|
|
| if (FLAG_debug_code) {
|
| @@ -2119,7 +2190,7 @@ void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
|
| case Token::MOD: {
|
| // Save r0-r3 on the stack.
|
| __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit());
|
| -
|
| + fp_sp_delta_ += 4 * kPointerSize;
|
| __ PrepareCallCFunction(0, 2, scratch0());
|
| __ SetCallCDoubleArguments(left, right);
|
| __ CallCFunction(
|
| @@ -2130,6 +2201,7 @@ void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
|
|
|
| // Restore r0-r3.
|
| __ ldm(ia_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit());
|
| + fp_sp_delta_ -= 4 * kPointerSize;
|
| break;
|
| }
|
| default:
|
| @@ -2148,7 +2220,7 @@ void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
|
| // Block literal pool emission to ensure nop indicating no inlined smi code
|
| // is in the correct position.
|
| Assembler::BlockConstPoolScope block_const_pool(masm());
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| + CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 0, instr);
|
| __ nop(); // Signals no inlined code.
|
| }
|
|
|
| @@ -2573,7 +2645,7 @@ void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) {
|
| Token::Value op = instr->op();
|
|
|
| Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op);
|
| - CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
| + CallCode(ic, RelocInfo::CODE_TARGET, 0, instr);
|
| // This instruction also signals no smi code inlined.
|
| __ cmp(r0, Operand::Zero());
|
|
|
| @@ -2734,7 +2806,7 @@ void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
|
| ASSERT(ToRegister(instr->right()).is(r1)); // Function is in r1.
|
|
|
| InstanceofStub stub(InstanceofStub::kArgsInRegisters);
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| + CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 0, instr);
|
|
|
| __ cmp(r0, Operand::Zero());
|
| __ mov(r0, Operand(factory()->false_value()), LeaveCC, ne);
|
| @@ -2876,6 +2948,7 @@ void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
|
| __ StoreToSafepointRegisterSlot(temp, temp);
|
| CallCodeGeneric(stub.GetCode(isolate()),
|
| RelocInfo::CODE_TARGET,
|
| + 0,
|
| instr,
|
| RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
|
| LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment();
|
| @@ -2898,7 +2971,7 @@ void LCodeGen::DoCmpT(LCmpT* instr) {
|
| Token::Value op = instr->op();
|
|
|
| Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op);
|
| - CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
| + CallCode(ic, RelocInfo::CODE_TARGET, 0, instr);
|
| // This instruction also signals no smi code inlined.
|
| __ cmp(r0, Operand::Zero());
|
|
|
| @@ -2978,7 +3051,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
|
| RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET
|
| : RelocInfo::CODE_TARGET_CONTEXT;
|
| Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
| - CallCode(ic, mode, instr);
|
| + CallCode(ic, mode, 0, instr);
|
| }
|
|
|
|
|
| @@ -3015,7 +3088,7 @@ void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
|
| Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
|
| ? isolate()->builtins()->StoreIC_Initialize_Strict()
|
| : isolate()->builtins()->StoreIC_Initialize();
|
| - CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr);
|
| + CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, 0, instr);
|
| }
|
|
|
|
|
| @@ -3107,7 +3180,7 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
|
| // Name is always in r2.
|
| __ mov(r2, Operand(instr->name()));
|
| Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
| - CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
|
| + CallCode(ic, RelocInfo::CODE_TARGET, 0, instr, NEVER_INLINE_TARGET_ADDRESS);
|
| }
|
|
|
|
|
| @@ -3392,7 +3465,7 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
|
| ASSERT(ToRegister(instr->key()).is(r0));
|
|
|
| Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
|
| - CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
|
| + CallCode(ic, RelocInfo::CODE_TARGET, 0, instr, NEVER_INLINE_TARGET_ADDRESS);
|
| }
|
|
|
|
|
| @@ -3405,7 +3478,8 @@ void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
|
| } else {
|
| // Check if the calling frame is an arguments adaptor frame.
|
| Label done, adapted;
|
| - __ ldr(scratch, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
|
| + int fp_offset = StandardFrameConstants::kCallerFPOffset + fp_sp_delta_;
|
| + __ ldr(scratch, MemOperand(sp, fp_offset));
|
| __ ldr(result, MemOperand(scratch, StandardFrameConstants::kContextOffset));
|
| __ cmp(result, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
|
|
|
| @@ -3429,7 +3503,8 @@ void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
|
| __ b(eq, &done);
|
|
|
| // Arguments adaptor frame present. Get argument length from there.
|
| - __ ldr(result, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
|
| + int fp_offset = StandardFrameConstants::kCallerFPOffset + fp_sp_delta_;
|
| + __ ldr(result, MemOperand(sp, fp_offset));
|
| __ ldr(result,
|
| MemOperand(result, ArgumentsAdaptorFrameConstants::kLengthOffset));
|
| __ SmiUntag(result);
|
| @@ -3532,7 +3607,8 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
|
| ParameterCount actual(receiver);
|
| __ InvokeFunction(function, actual, CALL_FUNCTION,
|
| safepoint_generator, CALL_AS_METHOD);
|
| - __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
| + int cp_offset = StandardFrameConstants::kContextOffset + fp_sp_delta_;
|
| + __ ldr(cp, MemOperand(sp, cp_offset));
|
| }
|
|
|
|
|
| @@ -3542,19 +3618,21 @@ void LCodeGen::DoPushArgument(LPushArgument* instr) {
|
| Abort(kDoPushArgumentNotImplementedForDoubleType);
|
| } else {
|
| Register argument_reg = EmitLoadRegister(argument, ip);
|
| - __ push(argument_reg);
|
| + Push(argument_reg);
|
| }
|
| }
|
|
|
|
|
| void LCodeGen::DoDrop(LDrop* instr) {
|
| __ Drop(instr->count());
|
| + fp_sp_delta_ -= instr->count() * kPointerSize;
|
| }
|
|
|
|
|
| void LCodeGen::DoThisFunction(LThisFunction* instr) {
|
| Register result = ToRegister(instr->result());
|
| - __ ldr(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
|
| + int offset = JavaScriptFrameConstants::kFunctionOffset + fp_sp_delta_;
|
| + __ ldr(result, MemOperand(sp, offset));
|
| }
|
|
|
|
|
| @@ -3579,11 +3657,11 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) {
|
|
|
|
|
| void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) {
|
| - __ push(cp); // The context is the first argument.
|
| + Push(cp); // The context is the first argument.
|
| __ LoadHeapObject(scratch0(), instr->hydrogen()->pairs());
|
| - __ push(scratch0());
|
| + Push(scratch0());
|
| __ mov(scratch0(), Operand(Smi::FromInt(instr->hydrogen()->flags())));
|
| - __ push(scratch0());
|
| + Push(scratch0());
|
| CallRuntime(Runtime::kDeclareGlobals, 3, instr);
|
| }
|
|
|
| @@ -3643,9 +3721,11 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
|
| __ InvokeFunction(
|
| function, expected, count, CALL_FUNCTION, generator, call_kind);
|
| }
|
| + fp_sp_delta_ -= (arity + 1) * kPointerSize;
|
|
|
| // Restore context.
|
| - __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
| + int cp_offset = StandardFrameConstants::kContextOffset + fp_sp_delta_;
|
| + __ ldr(cp, MemOperand(sp, cp_offset));
|
| }
|
|
|
|
|
| @@ -3993,7 +4073,7 @@ void LCodeGen::DoMathLog(LMathLog* instr) {
|
| ASSERT(ToDoubleRegister(instr->result()).is(d2));
|
| TranscendentalCacheStub stub(TranscendentalCache::LOG,
|
| TranscendentalCacheStub::UNTAGGED);
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| + CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 0, instr);
|
| }
|
|
|
|
|
| @@ -4001,7 +4081,7 @@ void LCodeGen::DoMathTan(LMathTan* instr) {
|
| ASSERT(ToDoubleRegister(instr->result()).is(d2));
|
| TranscendentalCacheStub stub(TranscendentalCache::TAN,
|
| TranscendentalCacheStub::UNTAGGED);
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| + CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 0, instr);
|
| }
|
|
|
|
|
| @@ -4009,7 +4089,7 @@ void LCodeGen::DoMathCos(LMathCos* instr) {
|
| ASSERT(ToDoubleRegister(instr->result()).is(d2));
|
| TranscendentalCacheStub stub(TranscendentalCache::COS,
|
| TranscendentalCacheStub::UNTAGGED);
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| + CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 0, instr);
|
| }
|
|
|
|
|
| @@ -4017,7 +4097,7 @@ void LCodeGen::DoMathSin(LMathSin* instr) {
|
| ASSERT(ToDoubleRegister(instr->result()).is(d2));
|
| TranscendentalCacheStub stub(TranscendentalCache::SIN,
|
| TranscendentalCacheStub::UNTAGGED);
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| + CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 0, instr);
|
| }
|
|
|
|
|
| @@ -4032,7 +4112,9 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
|
| SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
|
| ParameterCount count(instr->arity());
|
| __ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
|
| - __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
| + fp_sp_delta_ -= (instr->arity() + 1) * kPointerSize;
|
| + int cp_offset = StandardFrameConstants::kContextOffset + fp_sp_delta_;
|
| + __ ldr(cp, MemOperand(sp, cp_offset));
|
| } else {
|
| CallKnownFunction(known_function,
|
| instr->hydrogen()->formal_parameter_count(),
|
| @@ -4050,8 +4132,10 @@ void LCodeGen::DoCallKeyed(LCallKeyed* instr) {
|
| int arity = instr->arity();
|
| Handle<Code> ic =
|
| isolate()->stub_cache()->ComputeKeyedCallInitialize(arity);
|
| - CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
|
| - __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
| + CallCode(ic, RelocInfo::CODE_TARGET, arity + 1, instr,
|
| + NEVER_INLINE_TARGET_ADDRESS);
|
| + int cp_offset = StandardFrameConstants::kContextOffset + fp_sp_delta_;
|
| + __ ldr(cp, MemOperand(sp, cp_offset));
|
| }
|
|
|
|
|
| @@ -4063,9 +4147,10 @@ void LCodeGen::DoCallNamed(LCallNamed* instr) {
|
| Handle<Code> ic =
|
| isolate()->stub_cache()->ComputeCallInitialize(arity, mode);
|
| __ mov(r2, Operand(instr->name()));
|
| - CallCode(ic, mode, instr, NEVER_INLINE_TARGET_ADDRESS);
|
| + CallCode(ic, mode, arity + 1, instr, NEVER_INLINE_TARGET_ADDRESS);
|
| // Restore context register.
|
| - __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
| + int cp_offset = StandardFrameConstants::kContextOffset + fp_sp_delta_;
|
| + __ ldr(cp, MemOperand(sp, cp_offset));
|
| }
|
|
|
|
|
| @@ -4075,8 +4160,9 @@ void LCodeGen::DoCallFunction(LCallFunction* instr) {
|
|
|
| int arity = instr->arity();
|
| CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS);
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| - __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
| + CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, arity + 1, instr);
|
| + int cp_offset = StandardFrameConstants::kContextOffset + fp_sp_delta_;
|
| + __ ldr(cp, MemOperand(sp, cp_offset));
|
| }
|
|
|
|
|
| @@ -4088,8 +4174,9 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
|
| Handle<Code> ic =
|
| isolate()->stub_cache()->ComputeCallInitialize(arity, mode);
|
| __ mov(r2, Operand(instr->name()));
|
| - CallCode(ic, mode, instr, NEVER_INLINE_TARGET_ADDRESS);
|
| - __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
| + CallCode(ic, mode, arity + 1, instr, NEVER_INLINE_TARGET_ADDRESS);
|
| + int cp_offset = StandardFrameConstants::kContextOffset + fp_sp_delta_;
|
| + __ ldr(cp, MemOperand(sp, cp_offset));
|
| }
|
|
|
|
|
| @@ -4113,7 +4200,8 @@ void LCodeGen::DoCallNew(LCallNew* instr) {
|
| Handle<Object> undefined_value(isolate()->factory()->undefined_value());
|
| __ mov(r2, Operand(undefined_value));
|
| CallConstructStub stub(NO_CALL_FUNCTION_FLAGS);
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
|
| + CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL,
|
| + instr->arity() + 1, instr);
|
| }
|
|
|
|
|
| @@ -4132,7 +4220,8 @@ void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
|
|
|
| if (instr->arity() == 0) {
|
| ArrayNoArgumentConstructorStub stub(kind, context_mode, override_mode);
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
|
| + CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL,
|
| + instr->arity() + 1, instr);
|
| } else if (instr->arity() == 1) {
|
| Label done;
|
| if (IsFastPackedElementsKind(kind)) {
|
| @@ -4146,17 +4235,21 @@ void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
|
| ElementsKind holey_kind = GetHoleyElementsKind(kind);
|
| ArraySingleArgumentConstructorStub stub(holey_kind, context_mode,
|
| override_mode);
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
|
| + CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL,
|
| + instr->arity() + 1, instr);
|
| __ jmp(&done);
|
| __ bind(&packed_case);
|
| + fp_sp_delta_ += (instr->arity() + 1) * kPointerSize;
|
| }
|
|
|
| ArraySingleArgumentConstructorStub stub(kind, context_mode, override_mode);
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
|
| + CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL,
|
| + instr->arity() + 1, instr);
|
| __ bind(&done);
|
| } else {
|
| ArrayNArgumentsConstructorStub stub(kind, context_mode, override_mode);
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
|
| + CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL,
|
| + instr->arity() + 1, instr);
|
| }
|
| }
|
|
|
| @@ -4268,7 +4361,7 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
|
| Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
|
| ? isolate()->builtins()->StoreIC_Initialize_Strict()
|
| : isolate()->builtins()->StoreIC_Initialize();
|
| - CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
|
| + CallCode(ic, RelocInfo::CODE_TARGET, 0, instr, NEVER_INLINE_TARGET_ADDRESS);
|
| }
|
|
|
|
|
| @@ -4484,7 +4577,7 @@ void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
|
| Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
|
| ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
|
| : isolate()->builtins()->KeyedStoreIC_Initialize();
|
| - CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
|
| + CallCode(ic, RelocInfo::CODE_TARGET, 0, instr, NEVER_INLINE_TARGET_ADDRESS);
|
| }
|
|
|
|
|
| @@ -4532,10 +4625,10 @@ void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
|
|
|
|
|
| void LCodeGen::DoStringAdd(LStringAdd* instr) {
|
| - __ push(ToRegister(instr->left()));
|
| - __ push(ToRegister(instr->right()));
|
| + Push(ToRegister(instr->left()));
|
| + Push(ToRegister(instr->right()));
|
| StringAddStub stub(instr->hydrogen()->flags());
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| + CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 2, instr);
|
| }
|
|
|
|
|
| @@ -4573,17 +4666,17 @@ void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
|
| __ mov(result, Operand::Zero());
|
|
|
| PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
|
| - __ push(string);
|
| + Push(string);
|
| // Push the index as a smi. This is safe because of the checks in
|
| // DoStringCharCodeAt above.
|
| if (instr->index()->IsConstantOperand()) {
|
| int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
|
| __ mov(scratch, Operand(Smi::FromInt(const_index)));
|
| - __ push(scratch);
|
| + Push(scratch);
|
| } else {
|
| Register index = ToRegister(instr->index());
|
| __ SmiTag(index);
|
| - __ push(index);
|
| + Push(index);
|
| }
|
| CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr);
|
| __ AssertSmi(r0);
|
| @@ -4634,7 +4727,7 @@ void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
|
|
|
| PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
|
| __ SmiTag(char_code);
|
| - __ push(char_code);
|
| + Push(char_code);
|
| CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr);
|
| __ StoreToSafepointRegisterSlot(r0, result);
|
| }
|
| @@ -5365,7 +5458,7 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
|
| Register size = ToRegister(instr->size());
|
| ASSERT(!size.is(result));
|
| __ SmiTag(size);
|
| - __ push(size);
|
| + Push(size);
|
| } else {
|
| int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
|
| __ Push(Smi::FromInt(size));
|
| @@ -5387,7 +5480,7 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
|
|
|
| void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
|
| ASSERT(ToRegister(instr->value()).is(r0));
|
| - __ push(r0);
|
| + Push(r0);
|
| CallRuntime(Runtime::kToFastProperties, 1, instr);
|
| }
|
|
|
| @@ -5412,7 +5505,7 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
|
| __ mov(r6, Operand(Smi::FromInt(instr->hydrogen()->literal_index())));
|
| __ mov(r5, Operand(instr->hydrogen()->pattern()));
|
| __ mov(r4, Operand(instr->hydrogen()->flags()));
|
| - __ Push(r7, r6, r5, r4);
|
| + Push(r7, r6, r5, r4);
|
| CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
|
| __ mov(r1, r0);
|
|
|
| @@ -5425,9 +5518,10 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
|
|
|
| __ bind(&runtime_allocate);
|
| __ mov(r0, Operand(Smi::FromInt(size)));
|
| - __ Push(r1, r0);
|
| + Push(r1, r0);
|
| CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
|
| __ pop(r1);
|
| + fp_sp_delta_ -= kPointerSize;
|
|
|
| __ bind(&allocated);
|
| // Copy the content into the newly allocated memory.
|
| @@ -5443,13 +5537,13 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
|
| FastNewClosureStub stub(instr->hydrogen()->language_mode(),
|
| instr->hydrogen()->is_generator());
|
| __ mov(r1, Operand(instr->hydrogen()->shared_info()));
|
| - __ push(r1);
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| + Push(r1);
|
| + CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 1, instr);
|
| } else {
|
| __ mov(r2, Operand(instr->hydrogen()->shared_info()));
|
| __ mov(r1, Operand(pretenure ? factory()->true_value()
|
| : factory()->false_value()));
|
| - __ Push(cp, r2, r1);
|
| + Push(cp, r2, r1);
|
| CallRuntime(Runtime::kNewClosure, 3, instr);
|
| }
|
| }
|
| @@ -5457,7 +5551,7 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
|
|
|
| void LCodeGen::DoTypeof(LTypeof* instr) {
|
| Register input = ToRegister(instr->value());
|
| - __ push(input);
|
| + Push(input);
|
| CallRuntime(Runtime::kTypeof, 1, instr);
|
| }
|
|
|
| @@ -5662,7 +5756,7 @@ void LCodeGen::DoStackCheck(LStackCheck* instr) {
|
| __ b(hs, &done);
|
| StackCheckStub stub;
|
| PredictableCodeSizeScope predictable(masm_, 2 * Assembler::kInstrSize);
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| + CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 0, instr);
|
| EnsureSpaceForLazyDeopt();
|
| last_lazy_deopt_pc_ = masm()->pc_offset();
|
| __ bind(&done);
|
| @@ -5730,7 +5824,7 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
|
|
|
| // Get the set of properties to enumerate.
|
| __ bind(&call_runtime);
|
| - __ push(r0);
|
| + Push(r0);
|
| CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
|
|
|
| __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
|
|
|