Index: src/x64/codegen-x64.cc |
=================================================================== |
--- src/x64/codegen-x64.cc (revision 5072) |
+++ src/x64/codegen-x64.cc (working copy) |
@@ -2002,106 +2002,11 @@ |
} |
if (left_side_constant_smi || right_side_constant_smi) { |
- if (left_side_constant_smi && right_side_constant_smi) { |
- // Trivial case, comparing two constants. |
- int left_value = Smi::cast(*left_side.handle())->value(); |
- int right_value = Smi::cast(*right_side.handle())->value(); |
- switch (cc) { |
- case less: |
- dest->Goto(left_value < right_value); |
- break; |
- case equal: |
- dest->Goto(left_value == right_value); |
- break; |
- case greater_equal: |
- dest->Goto(left_value >= right_value); |
- break; |
- default: |
- UNREACHABLE(); |
- } |
- } else { |
- // Only one side is a constant Smi. |
- // If left side is a constant Smi, reverse the operands. |
- // Since one side is a constant Smi, conversion order does not matter. |
- if (left_side_constant_smi) { |
- Result temp = left_side; |
- left_side = right_side; |
- right_side = temp; |
- cc = ReverseCondition(cc); |
- // This may re-introduce greater or less_equal as the value of cc. |
- // CompareStub and the inline code both support all values of cc. |
- } |
- // Implement comparison against a constant Smi, inlining the case |
- // where both sides are Smis. |
- left_side.ToRegister(); |
- Register left_reg = left_side.reg(); |
- Handle<Object> right_val = right_side.handle(); |
- |
- // Here we split control flow to the stub call and inlined cases |
- // before finally splitting it to the control destination. We use |
- // a jump target and branching to duplicate the virtual frame at |
- // the first split. We manually handle the off-frame references |
- // by reconstituting them on the non-fall-through path. |
- JumpTarget is_smi; |
- |
- if (left_side.is_smi()) { |
- if (FLAG_debug_code) { |
- __ AbortIfNotSmi(left_side.reg()); |
- } |
- } else { |
- Condition left_is_smi = masm_->CheckSmi(left_side.reg()); |
- is_smi.Branch(left_is_smi); |
- |
- bool is_loop_condition = (node->AsExpression() != NULL) && |
- node->AsExpression()->is_loop_condition(); |
- if (!is_loop_condition && right_val->IsSmi()) { |
- // Right side is a constant smi and left side has been checked |
- // not to be a smi. |
- JumpTarget not_number; |
- __ Cmp(FieldOperand(left_reg, HeapObject::kMapOffset), |
- Factory::heap_number_map()); |
- not_number.Branch(not_equal, &left_side); |
- __ movsd(xmm1, |
- FieldOperand(left_reg, HeapNumber::kValueOffset)); |
- int value = Smi::cast(*right_val)->value(); |
- if (value == 0) { |
- __ xorpd(xmm0, xmm0); |
- } else { |
- Result temp = allocator()->Allocate(); |
- __ movl(temp.reg(), Immediate(value)); |
- __ cvtlsi2sd(xmm0, temp.reg()); |
- temp.Unuse(); |
- } |
- __ ucomisd(xmm1, xmm0); |
- // Jump to builtin for NaN. |
- not_number.Branch(parity_even, &left_side); |
- left_side.Unuse(); |
- dest->true_target()->Branch(DoubleCondition(cc)); |
- dest->false_target()->Jump(); |
- not_number.Bind(&left_side); |
- } |
- |
- // Setup and call the compare stub. |
- CompareStub stub(cc, strict, kCantBothBeNaN); |
- Result result = frame_->CallStub(&stub, &left_side, &right_side); |
- result.ToRegister(); |
- __ testq(result.reg(), result.reg()); |
- result.Unuse(); |
- dest->true_target()->Branch(cc); |
- dest->false_target()->Jump(); |
- |
- is_smi.Bind(); |
- } |
- |
- left_side = Result(left_reg); |
- right_side = Result(right_val); |
- // Test smi equality and comparison by signed int comparison. |
- // Both sides are smis, so we can use an Immediate. |
- __ SmiCompare(left_side.reg(), Smi::cast(*right_side.handle())); |
- left_side.Unuse(); |
- right_side.Unuse(); |
- dest->Split(cc); |
- } |
+ bool is_loop_condition = (node->AsExpression() != NULL) && |
+ node->AsExpression()->is_loop_condition(); |
+ ConstantSmiComparison(cc, strict, dest, &left_side, &right_side, |
+ left_side_constant_smi, right_side_constant_smi, |
+ is_loop_condition); |
} else if (cc == equal && |
(left_side_constant_null || right_side_constant_null)) { |
// To make null checks efficient, we check if either the left side or |
@@ -2366,6 +2271,128 @@ |
} |
+void CodeGenerator::ConstantSmiComparison(Condition cc, |
+ bool strict, |
+ ControlDestination* dest, |
+ Result* left_side, |
+ Result* right_side, |
+ bool left_side_constant_smi, |
+ bool right_side_constant_smi, |
+ bool is_loop_condition) { |
+ if (left_side_constant_smi && right_side_constant_smi) { |
+ // Trivial case, comparing two constants. |
+ int left_value = Smi::cast(*left_side->handle())->value(); |
+ int right_value = Smi::cast(*right_side->handle())->value(); |
+ switch (cc) { |
+ case less: |
+ dest->Goto(left_value < right_value); |
+ break; |
+ case equal: |
+ dest->Goto(left_value == right_value); |
+ break; |
+ case greater_equal: |
+ dest->Goto(left_value >= right_value); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+ } else { |
+ // Only one side is a constant Smi. |
+ // If left side is a constant Smi, reverse the operands. |
+ // Since one side is a constant Smi, conversion order does not matter. |
+ if (left_side_constant_smi) { |
+ Result* temp = left_side; |
+ left_side = right_side; |
+ right_side = temp; |
+ cc = ReverseCondition(cc); |
+ // This may re-introduce greater or less_equal as the value of cc. |
+ // CompareStub and the inline code both support all values of cc. |
+ } |
+ // Implement comparison against a constant Smi, inlining the case |
+ // where both sides are Smis. |
+ left_side->ToRegister(); |
+ Register left_reg = left_side->reg(); |
+ Smi* constant_smi = Smi::cast(*right_side->handle()); |
+ |
+ if (left_side->is_smi()) { |
+ if (FLAG_debug_code) { |
+ __ AbortIfNotSmi(left_reg); |
+ } |
+ // Test smi equality and comparison by signed int comparison. |
+ // Both sides are smis, so we can use an Immediate. |
+ __ SmiCompare(left_reg, constant_smi); |
+ left_side->Unuse(); |
+ right_side->Unuse(); |
+ dest->Split(cc); |
+ } else { |
+ // Only the case where the left side could possibly be a non-smi is left. |
+ JumpTarget is_smi; |
+ if (cc == equal) { |
+ // We can do the equality comparison before the smi check. |
+ __ SmiCompare(left_reg, constant_smi); |
+ dest->true_target()->Branch(equal); |
+ Condition left_is_smi = masm_->CheckSmi(left_reg); |
+ dest->false_target()->Branch(left_is_smi); |
+ } else { |
+ // Do the smi check, then the comparison. |
+ Condition left_is_smi = masm_->CheckSmi(left_reg); |
+ is_smi.Branch(left_is_smi, left_side, right_side); |
+ } |
+ |
+ // Jump or fall through to here if we are comparing a non-smi to a |
+ // constant smi. If the non-smi is a heap number and this is not |
+ // a loop condition, inline the floating point code. |
+ if (!is_loop_condition) { |
+ // Right side is a constant smi and left side has been checked |
+ // not to be a smi. |
+ JumpTarget not_number; |
+ __ Cmp(FieldOperand(left_reg, HeapObject::kMapOffset), |
+ Factory::heap_number_map()); |
+ not_number.Branch(not_equal, left_side); |
+ __ movsd(xmm1, |
+ FieldOperand(left_reg, HeapNumber::kValueOffset)); |
+ int value = constant_smi->value(); |
+ if (value == 0) { |
+ __ xorpd(xmm0, xmm0); |
+ } else { |
+ Result temp = allocator()->Allocate(); |
+ __ movl(temp.reg(), Immediate(value)); |
+ __ cvtlsi2sd(xmm0, temp.reg()); |
+ temp.Unuse(); |
+ } |
+ __ ucomisd(xmm1, xmm0); |
+ // Jump to builtin for NaN. |
+ not_number.Branch(parity_even, left_side); |
+ left_side->Unuse(); |
+ dest->true_target()->Branch(DoubleCondition(cc)); |
+ dest->false_target()->Jump(); |
+ not_number.Bind(left_side); |
+ } |
+ |
+ // Setup and call the compare stub. |
+ CompareStub stub(cc, strict, kCantBothBeNaN); |
+ Result result = frame_->CallStub(&stub, left_side, right_side); |
+ result.ToRegister(); |
+ __ testq(result.reg(), result.reg()); |
+ result.Unuse(); |
+ if (cc == equal) { |
+ dest->Split(cc); |
+ } else { |
+ dest->true_target()->Branch(cc); |
+ dest->false_target()->Jump(); |
+ |
+ // It is important for performance for this case to be at the end. |
+ is_smi.Bind(left_side, right_side); |
+ __ SmiCompare(left_reg, constant_smi); |
+ left_side->Unuse(); |
+ right_side->Unuse(); |
+ dest->Split(cc); |
+ } |
+ } |
+ } |
+} |
+ |
+ |
// Load a comparison operand into into a XMM register. Jump to not_numbers jump |
// target passing the left and right result if the operand is not a number. |
static void LoadComparisonOperand(MacroAssembler* masm_, |