Revision: 3537 Author: [email protected] Date: Tue Jan 5 04:02:18 2010 Log: Use cmov instructions to avoid some conditional branches in stub code.
This change improves the ConstructStub and the ArgumentsAccessStub slightly by using the cmov instruction (if available) to eliminate a conditional branch. It only applies to the IA-32 and X64 platforms. Review URL: http://codereview.chromium.org/519035 http://code.google.com/p/v8/source/detail?r=3537 Modified: /branches/bleeding_edge/src/ia32/codegen-ia32.cc /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc /branches/bleeding_edge/src/x64/codegen-x64.cc /branches/bleeding_edge/src/x64/stub-cache-x64.cc ======================================= --- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Tue Jan 5 01:38:02 2010 +++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Tue Jan 5 04:02:18 2010 @@ -7733,20 +7733,24 @@ void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) { // Check if the calling frame is an arguments adaptor frame. - Label adaptor; __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); - __ j(equal, &adaptor); - - // Nothing to do: The formal number of parameters has already been - // passed in register eax by calling function. Just return it. - __ ret(0); // Arguments adaptor case: Read the arguments length from the // adaptor frame and return it. - __ bind(&adaptor); - __ mov(eax, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); + // Otherwise nothing to do: The number of formal parameters has already been + // passed in register eax by calling function. Just return it. + if (CpuFeatures::IsSupported(CMOV)) { + CpuFeatures::Scope use_cmov(CMOV); + __ cmov(equal, eax, + Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); + } else { + Label exit; + __ j(not_equal, &exit); + __ mov(eax, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); + __ bind(&exit); + } __ ret(0); } ======================================= --- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Sun Dec 20 00:40:13 2009 +++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Tue Jan 5 04:02:18 2010 @@ -1900,17 +1900,23 @@ // depending on the this.x = ...; assignment in the function. for (int i = 0; i < shared->this_property_assignments_count(); i++) { if (shared->IsThisPropertyAssignmentArgument(i)) { - Label not_passed; - // Set the property to undefined. - __ mov(Operand(edx, i * kPointerSize), edi); // Check if the argument assigned to the property is actually passed. + // If argument is not passed the property is set to undefined, + // otherwise find it on the stack. int arg_number = shared->GetThisPropertyAssignmentArgument(i); + __ mov(ebx, edi); __ cmp(eax, arg_number); - __ j(below_equal, ¬_passed); - // Argument passed - find it on the stack. - __ mov(ebx, Operand(ecx, arg_number * -kPointerSize)); + if (CpuFeatures::IsSupported(CMOV)) { + CpuFeatures::Scope use_cmov(CMOV); + __ cmov(above, ebx, Operand(ecx, arg_number * -kPointerSize)); + } else { + Label not_passed; + __ j(below_equal, ¬_passed); + __ mov(ebx, Operand(ecx, arg_number * -kPointerSize)); + __ bind(¬_passed); + } + // Store value in the property. __ mov(Operand(edx, i * kPointerSize), ebx); - __ bind(¬_passed); } else { // Set the property to the constant value. Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i)); ======================================= --- /branches/bleeding_edge/src/x64/codegen-x64.cc Tue Jan 5 01:38:02 2010 +++ /branches/bleeding_edge/src/x64/codegen-x64.cc Tue Jan 5 04:02:18 2010 @@ -6594,16 +6594,13 @@ __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); __ SmiCompare(Operand(rdx, StandardFrameConstants::kContextOffset), Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); - __ j(equal, &adaptor); - - // Nothing to do: The formal number of parameters has already been - // passed in register rax by calling function. Just return it. - __ ret(0); // Arguments adaptor case: Read the arguments length from the // adaptor frame and return it. - __ bind(&adaptor); - __ movq(rax, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); + // Otherwise nothing to do: The number of formal parameters has already been + // passed in register eax by calling function. Just return it. + __ cmovq(equal, rax, + Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); __ ret(0); } ======================================= --- /branches/bleeding_edge/src/x64/stub-cache-x64.cc Wed Dec 16 23:35:12 2009 +++ /branches/bleeding_edge/src/x64/stub-cache-x64.cc Tue Jan 5 04:02:18 2010 @@ -1827,17 +1827,15 @@ // depending on the this.x = ...; assignment in the function. for (int i = 0; i < shared->this_property_assignments_count(); i++) { if (shared->IsThisPropertyAssignmentArgument(i)) { - Label not_passed; - // Set the property to undefined. - __ movq(Operand(r9, i * kPointerSize), r8); // Check if the argument assigned to the property is actually passed. + // If argument is not passed the property is set to undefined, + // otherwise find it on the stack. int arg_number = shared->GetThisPropertyAssignmentArgument(i); + __ movq(rbx, r8); __ cmpq(rax, Immediate(arg_number)); - __ j(below_equal, ¬_passed); - // Argument passed - find it on the stack. - __ movq(rbx, Operand(rcx, arg_number * -kPointerSize)); + __ cmovq(above, rbx, Operand(rcx, arg_number * -kPointerSize)); + // Store value in the property. __ movq(Operand(r9, i * kPointerSize), rbx); - __ bind(¬_passed); } else { // Set the property to the constant value. Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i)); -- v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev
