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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3537 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 9f0997f9
......@@ -7733,20 +7733,24 @@ void GenericUnaryOpStub::Generate(MacroAssembler* masm) {
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);
}
......
......@@ -1900,17 +1900,23 @@ Object* ConstructStubCompiler::CompileConstructStub(
// 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, &not_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, &not_passed);
__ mov(ebx, Operand(ecx, arg_number * -kPointerSize));
__ bind(&not_passed);
}
// Store value in the property.
__ mov(Operand(edx, i * kPointerSize), ebx);
__ bind(&not_passed);
} else {
// Set the property to the constant value.
Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i));
......
......@@ -6594,16 +6594,13 @@ void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) {
__ 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);
}
......
......@@ -1827,17 +1827,15 @@ Object* ConstructStubCompiler::CompileConstructStub(
// 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, &not_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(&not_passed);
} else {
// Set the property to the constant value.
Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment