Index: src/x64/codegen-x64.cc |
=================================================================== |
--- src/x64/codegen-x64.cc (revision 4543) |
+++ src/x64/codegen-x64.cc (working copy) |
@@ -5708,7 +5708,7 @@ |
CompareStub stub(cc, strict, kCantBothBeNaN); |
Result result = frame_->CallStub(&stub, &left_side, &right_side); |
result.ToRegister(); |
- __ SmiCompare(result.reg(), Smi::FromInt(0)); |
+ __ testq(result.reg(), result.reg()); |
result.Unuse(); |
dest->true_target()->Branch(cc); |
dest->false_target()->Jump(); |
@@ -5805,13 +5805,9 @@ |
GenerateInlineNumberComparison(&left_side, &right_side, cc, dest); |
} |
- // Call the compare stub. |
- // TODO(whesse@chromium.org): Enable the inlining flag once |
- // GenerateInlineNumberComparison is implemented. |
- CompareStub stub(cc, strict, nan_info, true || !inline_number_compare); |
+ CompareStub stub(cc, strict, nan_info, !inline_number_compare); |
Result answer = frame_->CallStub(&stub, &left_side, &right_side); |
- // The result is a Smi, which is negative, zero, or positive. |
- __ SmiTest(answer.reg()); // Sets both zero and sign flag. |
+ __ testq(answer.reg(), answer.reg()); // Sets both zero and sign flag. |
answer.Unuse(); |
dest->Split(cc); |
} else { |
@@ -5839,12 +5835,9 @@ |
GenerateInlineNumberComparison(&left_side, &right_side, cc, dest); |
} |
- // Call the compare stub. |
- // TODO(whesse@chromium.org): Enable the inlining flag once |
- // GenerateInlineNumberComparison is implemented. |
- CompareStub stub(cc, strict, nan_info, true || !inline_number_compare); |
+ CompareStub stub(cc, strict, nan_info, !inline_number_compare); |
Result answer = frame_->CallStub(&stub, &left_side, &right_side); |
- __ SmiTest(answer.reg()); // Sets both zero and sign flags. |
+ __ testq(answer.reg(), answer.reg()); // Sets both zero and sign flags. |
answer.Unuse(); |
dest->true_target()->Branch(cc); |
dest->false_target()->Jump(); |
@@ -5861,14 +5854,70 @@ |
} |
+// 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_, |
+ Result* operand, |
+ XMMRegister xmm_reg, |
+ Result* left_side, |
+ Result* right_side, |
+ JumpTarget* not_numbers) { |
+ Label done; |
+ if (operand->type_info().IsDouble()) { |
+ // Operand is known to be a heap number, just load it. |
+ __ movsd(xmm_reg, FieldOperand(operand->reg(), HeapNumber::kValueOffset)); |
+ } else if (operand->type_info().IsSmi()) { |
+ // Operand is known to be a smi. Convert it to double and keep the original |
+ // smi. |
+ __ SmiToInteger32(kScratchRegister, operand->reg()); |
+ __ cvtlsi2sd(xmm_reg, kScratchRegister); |
+ } else { |
+ // Operand type not known, check for smi or heap number. |
+ Label smi; |
+ __ JumpIfSmi(operand->reg(), &smi); |
+ if (!operand->type_info().IsNumber()) { |
+ __ LoadRoot(kScratchRegister, Heap::kHeapNumberMapRootIndex); |
+ __ cmpq(FieldOperand(operand->reg(), HeapObject::kMapOffset), |
+ kScratchRegister); |
+ not_numbers->Branch(not_equal, left_side, right_side, taken); |
+ } |
+ __ movsd(xmm_reg, FieldOperand(operand->reg(), HeapNumber::kValueOffset)); |
+ __ jmp(&done); |
+ |
+ __ bind(&smi); |
+ // Comvert smi to float and keep the original smi. |
+ __ SmiToInteger32(kScratchRegister, operand->reg()); |
+ __ cvtlsi2sd(xmm_reg, kScratchRegister); |
+ __ jmp(&done); |
+ } |
+ __ bind(&done); |
+} |
+ |
+ |
void CodeGenerator::GenerateInlineNumberComparison(Result* left_side, |
Result* right_side, |
Condition cc, |
ControlDestination* dest) { |
ASSERT(left_side->is_register()); |
ASSERT(right_side->is_register()); |
- // TODO(whesse@chromium.org): Implement this function, and enable the |
- // corresponding flags in the CompareStub. |
+ |
+ JumpTarget not_numbers; |
+ // Load left and right operand into registers xmm0 and xmm1 and compare. |
+ LoadComparisonOperand(masm_, left_side, xmm0, left_side, right_side, |
+ ¬_numbers); |
+ LoadComparisonOperand(masm_, right_side, xmm1, left_side, right_side, |
+ ¬_numbers); |
+ __ comisd(xmm0, xmm1); |
+ // Bail out if a NaN is involved. |
+ not_numbers.Branch(parity_even, left_side, right_side); |
+ |
+ // Split to destination targets based on comparison. |
+ left_side->Unuse(); |
+ right_side->Unuse(); |
+ dest->true_target()->Branch(DoubleCondition(cc)); |
+ dest->false_target()->Jump(); |
+ |
+ not_numbers.Bind(left_side, right_side); |
} |
@@ -7991,12 +8040,12 @@ |
void CompareStub::Generate(MacroAssembler* masm) { |
Label call_builtin, done; |
- |
+ // The compare stub returns a positive, negative, or zero 64-bit |
+ // integer value in rax, corresponding to the relation of the two objects. |
// NOTICE! This code is only reached after a smi-fast-case check, so |
// it is certain that at least one operand isn't a smi. |
- // Identical objects can be compared fast, but there are some tricky cases |
- // for NaN and undefined. |
+ // Two identical objects are equal unless they are both NaN or undefined. |
{ |
Label not_identical; |
__ cmpq(rax, rdx); |