Chromium Code Reviews| Index: src/compiler/arm/code-generator-arm.cc |
| diff --git a/src/compiler/arm/code-generator-arm.cc b/src/compiler/arm/code-generator-arm.cc |
| index 5c94ccf7c3b2d07bb6ce1b379cf99d14135080db..a0b0f8efe0af8fff786a7a3b9be76f8c25ccc497 100644 |
| --- a/src/compiler/arm/code-generator-arm.cc |
| +++ b/src/compiler/arm/code-generator-arm.cc |
| @@ -405,6 +405,30 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { |
| frame_access_state()->SetFrameAccessToSP(); |
| } |
| +void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, |
| + Register scratch1, |
| + Register scratch2, |
| + Register scratch3) { |
| + DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3)); |
| + Label done; |
| + |
| + // Check if current frame is an arguments adaptor frame. |
| + __ ldr(scratch1, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| + __ cmp(scratch1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| + __ b(ne, &done); |
| + |
| + // Load arguments count from current arguments adaptor frame (note, it |
| + // does not include receiver). |
| + Register caller_args_count_reg = scratch1; |
| + __ ldr(caller_args_count_reg, |
| + MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| + __ SmiUntag(caller_args_count_reg); |
| + |
| + ParameterCount callee_args_count(args_reg); |
| + __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, |
| + scratch3); |
| + __ bind(&done); |
| +} |
| // Assembles an instruction after register allocation, producing machine code. |
| void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
| @@ -428,6 +452,24 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
| frame_access_state()->ClearSPDelta(); |
| break; |
| } |
| + case kArchTailCallCodeObjectFromJSFunction: { |
|
Michael Starzinger
2016/03/07 21:47:32
suggestion: I would slightly prefer the common cod
Igor Sheludko
2016/03/07 23:19:23
Good idea! Done.
|
| + int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
| + AssembleDeconstructActivationRecord(stack_param_delta); |
| + AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
| + i.TempRegister(0), i.TempRegister(1), |
| + i.TempRegister(2)); |
| + if (instr->InputAt(0)->IsImmediate()) { |
| + __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), |
| + RelocInfo::CODE_TARGET); |
| + } else { |
| + __ add(ip, i.InputRegister(0), |
| + Operand(Code::kHeaderSize - kHeapObjectTag)); |
| + __ Jump(ip); |
| + } |
| + DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| + frame_access_state()->ClearSPDelta(); |
| + break; |
| + } |
| case kArchTailCallCodeObject: { |
| int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
| AssembleDeconstructActivationRecord(stack_param_delta); |
| @@ -459,6 +501,25 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
| frame_access_state()->ClearSPDelta(); |
| break; |
| } |
| + case kArchTailCallJSFunctionFromJSFunction: { |
| + Register func = i.InputRegister(0); |
| + if (FLAG_debug_code) { |
| + // Check the function's context matches the context argument. |
| + __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); |
| + __ cmp(cp, kScratchReg); |
| + __ Assert(eq, kWrongFunctionContext); |
| + } |
| + int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
| + AssembleDeconstructActivationRecord(stack_param_delta); |
| + AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
| + i.TempRegister(0), i.TempRegister(1), |
| + i.TempRegister(2)); |
| + __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
| + __ Jump(ip); |
| + DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| + frame_access_state()->ClearSPDelta(); |
| + break; |
| + } |
| case kArchTailCallJSFunction: { |
| Register func = i.InputRegister(0); |
| if (FLAG_debug_code) { |