| Index: src/crankshaft/mips/lithium-codegen-mips.cc
 | 
| diff --git a/src/crankshaft/mips/lithium-codegen-mips.cc b/src/crankshaft/mips/lithium-codegen-mips.cc
 | 
| index dd908dea5ca3c9c15ee965c831148091bc1bfcfc..38d3eaff340194935e121df2e7ac0cdd78a8b2e0 100644
 | 
| --- a/src/crankshaft/mips/lithium-codegen-mips.cc
 | 
| +++ b/src/crankshaft/mips/lithium-codegen-mips.cc
 | 
| @@ -3130,15 +3130,24 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
 | 
|    __ sll(scratch, length, 2);
 | 
|  
 | 
|    __ bind(&invoke);
 | 
| +
 | 
| +  InvokeFlag flag = CALL_FUNCTION;
 | 
| +  if (instr->hydrogen()->tail_call_mode() == TailCallMode::kAllow) {
 | 
| +    // TODO(ishell): drop current frame before pushing arguments to the stack.
 | 
| +    flag = JUMP_FUNCTION;
 | 
| +    ParameterCount actual(a0);
 | 
| +    // It is safe to use t0, t1 and t2 as scratch registers here given that
 | 
| +    // we are not going to return to caller function anyway.
 | 
| +    PrepareForTailCall(actual, t0, t1, t2);
 | 
| +  }
 | 
| +
 | 
|    DCHECK(instr->HasPointerMap());
 | 
|    LPointerMap* pointers = instr->pointer_map();
 | 
| -  SafepointGenerator safepoint_generator(
 | 
| -      this, pointers, Safepoint::kLazyDeopt);
 | 
| +  SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt);
 | 
|    // The number of arguments is stored in receiver which is a0, as expected
 | 
|    // by InvokeFunction.
 | 
|    ParameterCount actual(receiver);
 | 
| -  __ InvokeFunction(function, no_reg, actual, CALL_FUNCTION,
 | 
| -                    safepoint_generator);
 | 
| +  __ InvokeFunction(function, no_reg, actual, flag, safepoint_generator);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -3184,10 +3193,9 @@ void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) {
 | 
|    CallRuntime(Runtime::kDeclareGlobals, instr);
 | 
|  }
 | 
|  
 | 
| -
 | 
|  void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
 | 
|                                   int formal_parameter_count, int arity,
 | 
| -                                 LInstruction* instr) {
 | 
| +                                 bool is_tail_call, LInstruction* instr) {
 | 
|    bool dont_adapt_arguments =
 | 
|        formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel;
 | 
|    bool can_invoke_directly =
 | 
| @@ -3204,17 +3212,35 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
 | 
|      __ LoadRoot(a3, Heap::kUndefinedValueRootIndex);
 | 
|      __ li(a0, Operand(arity));
 | 
|  
 | 
| +    bool is_self_call = function.is_identical_to(info()->closure());
 | 
| +
 | 
|      // Invoke function.
 | 
| -    __ lw(at, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset));
 | 
| -    __ Call(at);
 | 
| +    if (is_self_call) {
 | 
| +      Handle<Code> self(reinterpret_cast<Code**>(__ CodeObject().location()));
 | 
| +      if (is_tail_call) {
 | 
| +        __ Jump(self, RelocInfo::CODE_TARGET);
 | 
| +      } else {
 | 
| +        __ Call(self, RelocInfo::CODE_TARGET);
 | 
| +      }
 | 
| +    } else {
 | 
| +      __ lw(at, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset));
 | 
| +      if (is_tail_call) {
 | 
| +        __ Jump(at);
 | 
| +      } else {
 | 
| +        __ Call(at);
 | 
| +      }
 | 
| +    }
 | 
|  
 | 
| -    // Set up deoptimization.
 | 
| -    RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
 | 
| +    if (!is_tail_call) {
 | 
| +      // Set up deoptimization.
 | 
| +      RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
 | 
| +    }
 | 
|    } else {
 | 
|      SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
 | 
| -    ParameterCount count(arity);
 | 
| +    ParameterCount actual(arity);
 | 
|      ParameterCount expected(formal_parameter_count);
 | 
| -    __ InvokeFunction(function_reg, expected, count, CALL_FUNCTION, generator);
 | 
| +    InvokeFlag flag = is_tail_call ? JUMP_FUNCTION : CALL_FUNCTION;
 | 
| +    __ InvokeFunction(function_reg, expected, actual, flag, generator);
 | 
|    }
 | 
|  }
 | 
|  
 | 
| @@ -3548,22 +3574,77 @@ void LCodeGen::DoMathClz32(LMathClz32* instr) {
 | 
|    __ Clz(result, input);
 | 
|  }
 | 
|  
 | 
| +void LCodeGen::PrepareForTailCall(const ParameterCount& actual,
 | 
| +                                  Register scratch1, Register scratch2,
 | 
| +                                  Register scratch3) {
 | 
| +#if DEBUG
 | 
| +  if (actual.is_reg()) {
 | 
| +    DCHECK(!AreAliased(actual.reg(), scratch1, scratch2, scratch3));
 | 
| +  } else {
 | 
| +    DCHECK(!AreAliased(scratch1, scratch2, scratch3));
 | 
| +  }
 | 
| +#endif
 | 
| +  if (FLAG_code_comments) {
 | 
| +    if (actual.is_reg()) {
 | 
| +      Comment(";;; PrepareForTailCall, actual: %s {", actual.reg().ToString());
 | 
| +    } else {
 | 
| +      Comment(";;; PrepareForTailCall, actual: %d {", actual.immediate());
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  // Check if next frame is an arguments adaptor frame.
 | 
| +  Register caller_args_count_reg = scratch1;
 | 
| +  Label no_arguments_adaptor, formal_parameter_count_loaded;
 | 
| +  __ lw(scratch2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
 | 
| +  __ lw(scratch3, MemOperand(scratch2, StandardFrameConstants::kContextOffset));
 | 
| +  __ Branch(&no_arguments_adaptor, ne, scratch3,
 | 
| +            Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
 | 
| +
 | 
| +  // Drop current frame and load arguments count from arguments adaptor frame.
 | 
| +  __ mov(fp, scratch2);
 | 
| +  __ lw(caller_args_count_reg,
 | 
| +        MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset));
 | 
| +  __ SmiUntag(caller_args_count_reg);
 | 
| +  __ Branch(&formal_parameter_count_loaded);
 | 
| +
 | 
| +  __ bind(&no_arguments_adaptor);
 | 
| +  // Load caller's formal parameter count
 | 
| +  __ lw(scratch1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
 | 
| +  __ lw(scratch1,
 | 
| +        FieldMemOperand(scratch1, JSFunction::kSharedFunctionInfoOffset));
 | 
| +  __ li(caller_args_count_reg, Operand(info()->literal()->parameter_count()));
 | 
| +
 | 
| +  __ bind(&formal_parameter_count_loaded);
 | 
| +  __ PrepareForTailCall(actual, caller_args_count_reg, scratch2, scratch3);
 | 
| +
 | 
| +  Comment(";;; }");
 | 
| +}
 | 
|  
 | 
|  void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
 | 
| +  HInvokeFunction* hinstr = instr->hydrogen();
 | 
|    DCHECK(ToRegister(instr->context()).is(cp));
 | 
|    DCHECK(ToRegister(instr->function()).is(a1));
 | 
|    DCHECK(instr->HasPointerMap());
 | 
|  
 | 
| -  Handle<JSFunction> known_function = instr->hydrogen()->known_function();
 | 
| +  bool is_tail_call = hinstr->tail_call_mode() == TailCallMode::kAllow;
 | 
| +
 | 
| +  if (is_tail_call) {
 | 
| +    ParameterCount actual(instr->arity());
 | 
| +    // It is safe to use t0, t1 and t2 as scratch registers here given that
 | 
| +    // we are not going to return to caller function anyway.
 | 
| +    PrepareForTailCall(actual, t0, t1, t2);
 | 
| +  }
 | 
| +
 | 
| +  Handle<JSFunction> known_function = hinstr->known_function();
 | 
|    if (known_function.is_null()) {
 | 
|      LPointerMap* pointers = instr->pointer_map();
 | 
|      SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
 | 
| -    ParameterCount count(instr->arity());
 | 
| -    __ InvokeFunction(a1, no_reg, count, CALL_FUNCTION, generator);
 | 
| +    ParameterCount actual(instr->arity());
 | 
| +    InvokeFlag flag = is_tail_call ? JUMP_FUNCTION : CALL_FUNCTION;
 | 
| +    __ InvokeFunction(a1, no_reg, actual, flag, generator);
 | 
|    } else {
 | 
| -    CallKnownFunction(known_function,
 | 
| -                      instr->hydrogen()->formal_parameter_count(),
 | 
| -                      instr->arity(), instr);
 | 
| +    CallKnownFunction(known_function, hinstr->formal_parameter_count(),
 | 
| +                      instr->arity(), is_tail_call, instr);
 | 
|    }
 | 
|  }
 | 
|  
 | 
| 
 |