Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(578)

Side by Side Diff: src/x64/codegen-x64.cc

Issue 1703019: Add inline floating point comparisons for comparison operators to x64 platfor... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 5690 matching lines...) Expand 10 before | Expand all | Expand 10 after
5701 __ cmpb(temp.reg(), 5701 __ cmpb(temp.reg(),
5702 Immediate(kStringTag | kSeqStringTag | kAsciiStringTag)); 5702 Immediate(kStringTag | kSeqStringTag | kAsciiStringTag));
5703 temp.Unuse(); 5703 temp.Unuse();
5704 is_string.Branch(equal, &left_side); 5704 is_string.Branch(equal, &left_side);
5705 5705
5706 // Setup and call the compare stub. 5706 // Setup and call the compare stub.
5707 is_not_string.Bind(&left_side); 5707 is_not_string.Bind(&left_side);
5708 CompareStub stub(cc, strict, kCantBothBeNaN); 5708 CompareStub stub(cc, strict, kCantBothBeNaN);
5709 Result result = frame_->CallStub(&stub, &left_side, &right_side); 5709 Result result = frame_->CallStub(&stub, &left_side, &right_side);
5710 result.ToRegister(); 5710 result.ToRegister();
5711 __ SmiCompare(result.reg(), Smi::FromInt(0)); 5711 __ testq(result.reg(), result.reg());
5712 result.Unuse(); 5712 result.Unuse();
5713 dest->true_target()->Branch(cc); 5713 dest->true_target()->Branch(cc);
5714 dest->false_target()->Jump(); 5714 dest->false_target()->Jump();
5715 5715
5716 is_string.Bind(&left_side); 5716 is_string.Bind(&left_side);
5717 // left_side is a sequential ASCII string. 5717 // left_side is a sequential ASCII string.
5718 ASSERT(left_side.reg().is(left_reg)); 5718 ASSERT(left_side.reg().is(left_reg));
5719 right_side = Result(right_val); 5719 right_side = Result(right_val);
5720 Result temp2 = allocator_->Allocate(); 5720 Result temp2 = allocator_->Allocate();
5721 ASSERT(temp2.is_valid()); 5721 ASSERT(temp2.is_valid());
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
5798 if (nan_info == kCantBothBeNaN && cc == equal) { 5798 if (nan_info == kCantBothBeNaN && cc == equal) {
5799 __ cmpq(left_side.reg(), right_side.reg()); 5799 __ cmpq(left_side.reg(), right_side.reg());
5800 dest->true_target()->Branch(equal); 5800 dest->true_target()->Branch(equal);
5801 } 5801 }
5802 5802
5803 // Inlined number comparison: 5803 // Inlined number comparison:
5804 if (inline_number_compare) { 5804 if (inline_number_compare) {
5805 GenerateInlineNumberComparison(&left_side, &right_side, cc, dest); 5805 GenerateInlineNumberComparison(&left_side, &right_side, cc, dest);
5806 } 5806 }
5807 5807
5808 // Call the compare stub. 5808 CompareStub stub(cc, strict, nan_info, !inline_number_compare);
5809 // TODO(whesse@chromium.org): Enable the inlining flag once
5810 // GenerateInlineNumberComparison is implemented.
5811 CompareStub stub(cc, strict, nan_info, true || !inline_number_compare);
5812 Result answer = frame_->CallStub(&stub, &left_side, &right_side); 5809 Result answer = frame_->CallStub(&stub, &left_side, &right_side);
5813 // The result is a Smi, which is negative, zero, or positive. 5810 __ testq(answer.reg(), answer.reg()); // Sets both zero and sign flag.
5814 __ SmiTest(answer.reg()); // Sets both zero and sign flag.
5815 answer.Unuse(); 5811 answer.Unuse();
5816 dest->Split(cc); 5812 dest->Split(cc);
5817 } else { 5813 } else {
5818 // Here we split control flow to the stub call and inlined cases 5814 // Here we split control flow to the stub call and inlined cases
5819 // before finally splitting it to the control destination. We use 5815 // before finally splitting it to the control destination. We use
5820 // a jump target and branching to duplicate the virtual frame at 5816 // a jump target and branching to duplicate the virtual frame at
5821 // the first split. We manually handle the off-frame references 5817 // the first split. We manually handle the off-frame references
5822 // by reconstituting them on the non-fall-through path. 5818 // by reconstituting them on the non-fall-through path.
5823 JumpTarget is_smi; 5819 JumpTarget is_smi;
5824 Register left_reg = left_side.reg(); 5820 Register left_reg = left_side.reg();
5825 Register right_reg = right_side.reg(); 5821 Register right_reg = right_side.reg();
5826 5822
5827 Condition both_smi = masm_->CheckBothSmi(left_reg, right_reg); 5823 Condition both_smi = masm_->CheckBothSmi(left_reg, right_reg);
5828 is_smi.Branch(both_smi); 5824 is_smi.Branch(both_smi);
5829 5825
5830 // Inline the equality check if both operands can't be a NaN. If both 5826 // Inline the equality check if both operands can't be a NaN. If both
5831 // objects are the same they are equal. 5827 // objects are the same they are equal.
5832 if (nan_info == kCantBothBeNaN && cc == equal) { 5828 if (nan_info == kCantBothBeNaN && cc == equal) {
5833 __ cmpq(left_side.reg(), right_side.reg()); 5829 __ cmpq(left_side.reg(), right_side.reg());
5834 dest->true_target()->Branch(equal); 5830 dest->true_target()->Branch(equal);
5835 } 5831 }
5836 5832
5837 // Inlined number comparison: 5833 // Inlined number comparison:
5838 if (inline_number_compare) { 5834 if (inline_number_compare) {
5839 GenerateInlineNumberComparison(&left_side, &right_side, cc, dest); 5835 GenerateInlineNumberComparison(&left_side, &right_side, cc, dest);
5840 } 5836 }
5841 5837
5842 // Call the compare stub. 5838 CompareStub stub(cc, strict, nan_info, !inline_number_compare);
5843 // TODO(whesse@chromium.org): Enable the inlining flag once
5844 // GenerateInlineNumberComparison is implemented.
5845 CompareStub stub(cc, strict, nan_info, true || !inline_number_compare);
5846 Result answer = frame_->CallStub(&stub, &left_side, &right_side); 5839 Result answer = frame_->CallStub(&stub, &left_side, &right_side);
5847 __ SmiTest(answer.reg()); // Sets both zero and sign flags. 5840 __ testq(answer.reg(), answer.reg()); // Sets both zero and sign flags.
5848 answer.Unuse(); 5841 answer.Unuse();
5849 dest->true_target()->Branch(cc); 5842 dest->true_target()->Branch(cc);
5850 dest->false_target()->Jump(); 5843 dest->false_target()->Jump();
5851 5844
5852 is_smi.Bind(); 5845 is_smi.Bind();
5853 left_side = Result(left_reg); 5846 left_side = Result(left_reg);
5854 right_side = Result(right_reg); 5847 right_side = Result(right_reg);
5855 __ SmiCompare(left_side.reg(), right_side.reg()); 5848 __ SmiCompare(left_side.reg(), right_side.reg());
5856 right_side.Unuse(); 5849 right_side.Unuse();
5857 left_side.Unuse(); 5850 left_side.Unuse();
5858 dest->Split(cc); 5851 dest->Split(cc);
5859 } 5852 }
5860 } 5853 }
5861 } 5854 }
5862 5855
5863 5856
5857 // Load a comparison operand into into a XMM register. Jump to not_numbers jump
5858 // target passing the left and right result if the operand is not a number.
5859 static void LoadComparisonOperand(MacroAssembler* masm_,
5860 Result* operand,
5861 XMMRegister xmm_reg,
5862 Result* left_side,
5863 Result* right_side,
5864 JumpTarget* not_numbers) {
5865 Label done;
5866 if (operand->type_info().IsDouble()) {
5867 // Operand is known to be a heap number, just load it.
5868 __ movsd(xmm_reg, FieldOperand(operand->reg(), HeapNumber::kValueOffset));
5869 } else if (operand->type_info().IsSmi()) {
5870 // Operand is known to be a smi. Convert it to double and keep the original
5871 // smi.
5872 __ SmiToInteger32(kScratchRegister, operand->reg());
5873 __ cvtlsi2sd(xmm_reg, kScratchRegister);
5874 } else {
5875 // Operand type not known, check for smi or heap number.
5876 Label smi;
5877 __ JumpIfSmi(operand->reg(), &smi);
5878 if (!operand->type_info().IsNumber()) {
5879 __ LoadRoot(kScratchRegister, Heap::kHeapNumberMapRootIndex);
5880 __ cmpq(FieldOperand(operand->reg(), HeapObject::kMapOffset),
5881 kScratchRegister);
5882 not_numbers->Branch(not_equal, left_side, right_side, taken);
5883 }
5884 __ movsd(xmm_reg, FieldOperand(operand->reg(), HeapNumber::kValueOffset));
5885 __ jmp(&done);
5886
5887 __ bind(&smi);
5888 // Comvert smi to float and keep the original smi.
5889 __ SmiToInteger32(kScratchRegister, operand->reg());
5890 __ cvtlsi2sd(xmm_reg, kScratchRegister);
5891 __ jmp(&done);
5892 }
5893 __ bind(&done);
5894 }
5895
5896
5864 void CodeGenerator::GenerateInlineNumberComparison(Result* left_side, 5897 void CodeGenerator::GenerateInlineNumberComparison(Result* left_side,
5865 Result* right_side, 5898 Result* right_side,
5866 Condition cc, 5899 Condition cc,
5867 ControlDestination* dest) { 5900 ControlDestination* dest) {
5868 ASSERT(left_side->is_register()); 5901 ASSERT(left_side->is_register());
5869 ASSERT(right_side->is_register()); 5902 ASSERT(right_side->is_register());
5870 // TODO(whesse@chromium.org): Implement this function, and enable the 5903
5871 // corresponding flags in the CompareStub. 5904 JumpTarget not_numbers;
5905 // Load left and right operand into registers xmm0 and xmm1 and compare.
5906 LoadComparisonOperand(masm_, left_side, xmm0, left_side, right_side,
5907 &not_numbers);
5908 LoadComparisonOperand(masm_, right_side, xmm1, left_side, right_side,
5909 &not_numbers);
5910 __ comisd(xmm0, xmm1);
5911 // Bail out if a NaN is involved.
5912 not_numbers.Branch(parity_even, left_side, right_side);
5913
5914 // Split to destination targets based on comparison.
5915 left_side->Unuse();
5916 right_side->Unuse();
5917 dest->true_target()->Branch(DoubleCondition(cc));
5918 dest->false_target()->Jump();
5919
5920 not_numbers.Bind(left_side, right_side);
5872 } 5921 }
5873 5922
5874 5923
5875 class DeferredInlineBinaryOperation: public DeferredCode { 5924 class DeferredInlineBinaryOperation: public DeferredCode {
5876 public: 5925 public:
5877 DeferredInlineBinaryOperation(Token::Value op, 5926 DeferredInlineBinaryOperation(Token::Value op,
5878 Register dst, 5927 Register dst,
5879 Register left, 5928 Register left,
5880 Register right, 5929 Register right,
5881 OverwriteMode mode) 5930 OverwriteMode mode)
(...skipping 2102 matching lines...) Expand 10 before | Expand all | Expand 10 after
7984 8033
7985 static int NegativeComparisonResult(Condition cc) { 8034 static int NegativeComparisonResult(Condition cc) {
7986 ASSERT(cc != equal); 8035 ASSERT(cc != equal);
7987 ASSERT((cc == less) || (cc == less_equal) 8036 ASSERT((cc == less) || (cc == less_equal)
7988 || (cc == greater) || (cc == greater_equal)); 8037 || (cc == greater) || (cc == greater_equal));
7989 return (cc == greater || cc == greater_equal) ? LESS : GREATER; 8038 return (cc == greater || cc == greater_equal) ? LESS : GREATER;
7990 } 8039 }
7991 8040
7992 void CompareStub::Generate(MacroAssembler* masm) { 8041 void CompareStub::Generate(MacroAssembler* masm) {
7993 Label call_builtin, done; 8042 Label call_builtin, done;
7994 8043 // The compare stub returns a positive, negative, or zero 64-bit
8044 // integer value in rax, corresponding to the relation of the two objects.
7995 // NOTICE! This code is only reached after a smi-fast-case check, so 8045 // NOTICE! This code is only reached after a smi-fast-case check, so
7996 // it is certain that at least one operand isn't a smi. 8046 // it is certain that at least one operand isn't a smi.
7997 8047
7998 // Identical objects can be compared fast, but there are some tricky cases 8048 // Two identical objects are equal unless they are both NaN or undefined.
7999 // for NaN and undefined.
8000 { 8049 {
8001 Label not_identical; 8050 Label not_identical;
8002 __ cmpq(rax, rdx); 8051 __ cmpq(rax, rdx);
8003 __ j(not_equal, &not_identical); 8052 __ j(not_equal, &not_identical);
8004 8053
8005 if (cc_ != equal) { 8054 if (cc_ != equal) {
8006 // Check for undefined. undefined OP undefined is false even though 8055 // Check for undefined. undefined OP undefined is false even though
8007 // undefined == undefined. 8056 // undefined == undefined.
8008 Label check_for_nan; 8057 Label check_for_nan;
8009 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); 8058 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex);
(...skipping 2867 matching lines...) Expand 10 before | Expand all | Expand 10 after
10877 // Call the function from C++. 10926 // Call the function from C++.
10878 return FUNCTION_CAST<ModuloFunction>(buffer); 10927 return FUNCTION_CAST<ModuloFunction>(buffer);
10879 } 10928 }
10880 10929
10881 #endif 10930 #endif
10882 10931
10883 10932
10884 #undef __ 10933 #undef __
10885 10934
10886 } } // namespace v8::internal 10935 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698