| Index: src/compiler/x64/code-generator-x64.cc | 
| diff --git a/src/compiler/x64/code-generator-x64.cc b/src/compiler/x64/code-generator-x64.cc | 
| index 0c2412fc5cfeaf7863f3dbe4491c50386afdf66c..8bd9e89b0525a893812aa69659288dbd1f4eb6a5 100644 | 
| --- a/src/compiler/x64/code-generator-x64.cc | 
| +++ b/src/compiler/x64/code-generator-x64.cc | 
| @@ -4,6 +4,8 @@ | 
|  | 
| #include "src/compiler/code-generator.h" | 
|  | 
| +#include <limits> | 
| + | 
| #include "src/compilation-info.h" | 
| #include "src/compiler/code-generator-impl.h" | 
| #include "src/compiler/gap-resolver.h" | 
| @@ -918,7 +920,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( | 
| break; | 
| } | 
| case kArchRet: | 
| -      AssembleReturn(); | 
| +      AssembleReturn(instr->InputAt(0)); | 
| break; | 
| case kArchStackPointer: | 
| __ movq(i.OutputRegister(), rsp); | 
| @@ -2447,8 +2449,7 @@ void CodeGenerator::AssembleConstructFrame() { | 
| } | 
| } | 
|  | 
| - | 
| -void CodeGenerator::AssembleReturn() { | 
| +void CodeGenerator::AssembleReturn(InstructionOperand* pop) { | 
| CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 
|  | 
| // Restore registers. | 
| @@ -2477,22 +2478,41 @@ void CodeGenerator::AssembleReturn() { | 
|  | 
| unwinding_info_writer_.MarkBlockWillExit(); | 
|  | 
| +  // Might need rcx for scratch if pop_size is too big or if there is a variable | 
| +  // pop count. | 
| +  DCHECK_EQ(0u, descriptor->CalleeSavedRegisters() & rcx.bit()); | 
| +  DCHECK_EQ(0u, descriptor->CalleeSavedRegisters() & rdx.bit()); | 
| +  size_t pop_size = descriptor->StackParameterCount() * kPointerSize; | 
| +  X64OperandConverter g(this, nullptr); | 
| if (descriptor->IsCFunctionCall()) { | 
| AssembleDeconstructFrame(); | 
| } else if (frame_access_state()->has_frame()) { | 
| -    // Canonicalize JSFunction return sites for now. | 
| -    if (return_label_.is_bound()) { | 
| -      __ jmp(&return_label_); | 
| -      return; | 
| +    if (pop->IsImmediate() && g.ToConstant(pop).ToInt32() == 0) { | 
| +      // Canonicalize JSFunction return sites for now. | 
| +      if (return_label_.is_bound()) { | 
| +        __ jmp(&return_label_); | 
| +        return; | 
| +      } else { | 
| +        __ bind(&return_label_); | 
| +        AssembleDeconstructFrame(); | 
| +      } | 
| } else { | 
| -      __ bind(&return_label_); | 
| AssembleDeconstructFrame(); | 
| } | 
| } | 
| -  size_t pop_size = descriptor->StackParameterCount() * kPointerSize; | 
| -  // Might need rcx for scratch if pop_size is too big. | 
| -  DCHECK_EQ(0u, descriptor->CalleeSavedRegisters() & rcx.bit()); | 
| -  __ Ret(static_cast<int>(pop_size), rcx); | 
| + | 
| +  if (pop->IsImmediate()) { | 
| +    DCHECK_EQ(Constant::kInt32, g.ToConstant(pop).type()); | 
| +    pop_size += g.ToConstant(pop).ToInt32() * kPointerSize; | 
| +    CHECK_LT(pop_size, std::numeric_limits<int>::max()); | 
| +    __ Ret(static_cast<int>(pop_size), rcx); | 
| +  } else { | 
| +    Register pop_reg = g.ToRegister(pop); | 
| +    Register scratch_reg = pop_reg.is(rcx) ? rdx : rcx; | 
| +    __ popq(scratch_reg); | 
| +    __ leaq(rsp, Operand(rsp, pop_reg, times_8, static_cast<int>(pop_size))); | 
| +    __ jmp(scratch_reg); | 
| +  } | 
| } | 
|  | 
|  | 
|  |