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

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

Issue 545007: Introduce number type information in the virtual frame. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: merged with latest rev. Created 10 years, 10 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 | « src/ia32/codegen-ia32.h ('k') | src/ia32/macro-assembler-ia32.h » ('j') | 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 704 matching lines...) Expand 10 before | Expand all | Expand 10 after
715 715
716 // ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and 716 // ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and
717 // convert it to a boolean in the condition code register or jump to 717 // convert it to a boolean in the condition code register or jump to
718 // 'false_target'/'true_target' as appropriate. 718 // 'false_target'/'true_target' as appropriate.
719 void CodeGenerator::ToBoolean(ControlDestination* dest) { 719 void CodeGenerator::ToBoolean(ControlDestination* dest) {
720 Comment cmnt(masm_, "[ ToBoolean"); 720 Comment cmnt(masm_, "[ ToBoolean");
721 721
722 // The value to convert should be popped from the frame. 722 // The value to convert should be popped from the frame.
723 Result value = frame_->Pop(); 723 Result value = frame_->Pop();
724 value.ToRegister(); 724 value.ToRegister();
725 // Fast case checks.
726 725
727 // 'false' => false. 726 if (value.is_number()) {
728 __ cmp(value.reg(), Factory::false_value()); 727 Comment cmnt(masm_, "ONLY_NUMBER");
729 dest->false_target()->Branch(equal); 728 // Fast case if NumberInfo indicates only numbers.
729 if (FLAG_debug_code) {
730 __ AbortIfNotNumber(value.reg(), "ToBoolean operand is not a number.");
731 }
732 // Smi => false iff zero.
733 ASSERT(kSmiTag == 0);
734 __ test(value.reg(), Operand(value.reg()));
735 dest->false_target()->Branch(zero);
736 __ test(value.reg(), Immediate(kSmiTagMask));
737 dest->true_target()->Branch(zero);
738 __ fldz();
739 __ fld_d(FieldOperand(value.reg(), HeapNumber::kValueOffset));
740 __ FCmp();
741 value.Unuse();
742 dest->Split(not_zero);
743 } else {
744 // Fast case checks.
745 // 'false' => false.
746 __ cmp(value.reg(), Factory::false_value());
747 dest->false_target()->Branch(equal);
730 748
731 // 'true' => true. 749 // 'true' => true.
732 __ cmp(value.reg(), Factory::true_value()); 750 __ cmp(value.reg(), Factory::true_value());
733 dest->true_target()->Branch(equal); 751 dest->true_target()->Branch(equal);
734 752
735 // 'undefined' => false. 753 // 'undefined' => false.
736 __ cmp(value.reg(), Factory::undefined_value()); 754 __ cmp(value.reg(), Factory::undefined_value());
737 dest->false_target()->Branch(equal); 755 dest->false_target()->Branch(equal);
738 756
739 // Smi => false iff zero. 757 // Smi => false iff zero.
740 ASSERT(kSmiTag == 0); 758 ASSERT(kSmiTag == 0);
741 __ test(value.reg(), Operand(value.reg())); 759 __ test(value.reg(), Operand(value.reg()));
742 dest->false_target()->Branch(zero); 760 dest->false_target()->Branch(zero);
743 __ test(value.reg(), Immediate(kSmiTagMask)); 761 __ test(value.reg(), Immediate(kSmiTagMask));
744 dest->true_target()->Branch(zero); 762 dest->true_target()->Branch(zero);
745 763
746 // Call the stub for all other cases. 764 // Call the stub for all other cases.
747 frame_->Push(&value); // Undo the Pop() from above. 765 frame_->Push(&value); // Undo the Pop() from above.
748 ToBooleanStub stub; 766 ToBooleanStub stub;
749 Result temp = frame_->CallStub(&stub, 1); 767 Result temp = frame_->CallStub(&stub, 1);
750 // Convert the result to a condition code. 768 // Convert the result to a condition code.
751 __ test(temp.reg(), Operand(temp.reg())); 769 __ test(temp.reg(), Operand(temp.reg()));
752 temp.Unuse(); 770 temp.Unuse();
753 dest->Split(not_equal); 771 dest->Split(not_equal);
772 }
754 } 773 }
755 774
756 775
757 class FloatingPointHelper : public AllStatic { 776 class FloatingPointHelper : public AllStatic {
758 public: 777 public:
759 778
760 enum ArgLocation { 779 enum ArgLocation {
761 ARGS_ON_STACK, 780 ARGS_ON_STACK,
762 ARGS_IN_REGISTERS 781 ARGS_IN_REGISTERS
763 }; 782 };
(...skipping 19 matching lines...) Expand all
783 // operand_1 in eax, operand_2 in edx; falls through on float 802 // operand_1 in eax, operand_2 in edx; falls through on float
784 // operands, jumps to the non_float label otherwise. 803 // operands, jumps to the non_float label otherwise.
785 static void CheckFloatOperands(MacroAssembler* masm, 804 static void CheckFloatOperands(MacroAssembler* masm,
786 Label* non_float, 805 Label* non_float,
787 Register scratch); 806 Register scratch);
788 // Takes the operands in edx and eax and loads them as integers in eax 807 // Takes the operands in edx and eax and loads them as integers in eax
789 // and ecx. 808 // and ecx.
790 static void LoadAsIntegers(MacroAssembler* masm, 809 static void LoadAsIntegers(MacroAssembler* masm,
791 bool use_sse3, 810 bool use_sse3,
792 Label* operand_conversion_failure); 811 Label* operand_conversion_failure);
812 // Test if operands are smis or heap numbers and load them
813 // into xmm0 and xmm1 if they are. Operands are in edx and eax.
814 // Leaves operands unchanged.
815 static void LoadSSE2Operands(MacroAssembler* masm);
793 // Test if operands are numbers (smi or HeapNumber objects), and load 816 // Test if operands are numbers (smi or HeapNumber objects), and load
794 // them into xmm0 and xmm1 if they are. Jump to label not_numbers if 817 // them into xmm0 and xmm1 if they are. Jump to label not_numbers if
795 // either operand is not a number. Operands are in edx and eax. 818 // either operand is not a number. Operands are in edx and eax.
796 // Leaves operands unchanged. 819 // Leaves operands unchanged.
797 static void LoadSSE2Operands(MacroAssembler* masm, Label* not_numbers); 820 static void LoadSSE2Operands(MacroAssembler* masm, Label* not_numbers);
798 821
799 // Similar to LoadSSE2Operands but assumes that both operands are smis. 822 // Similar to LoadSSE2Operands but assumes that both operands are smis.
800 // Expects operands in edx, eax. 823 // Expects operands in edx, eax.
801 static void LoadSSE2Smis(MacroAssembler* masm, Register scratch); 824 static void LoadSSE2Smis(MacroAssembler* masm, Register scratch);
802 }; 825 };
803 826
804 827
805 const char* GenericBinaryOpStub::GetName() { 828 const char* GenericBinaryOpStub::GetName() {
806 if (name_ != NULL) return name_; 829 if (name_ != NULL) return name_;
807 const int kMaxNameLength = 100; 830 const int kMaxNameLength = 100;
808 name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength); 831 name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength);
809 if (name_ == NULL) return "OOM"; 832 if (name_ == NULL) return "OOM";
810 const char* op_name = Token::Name(op_); 833 const char* op_name = Token::Name(op_);
811 const char* overwrite_name; 834 const char* overwrite_name;
812 switch (mode_) { 835 switch (mode_) {
813 case NO_OVERWRITE: overwrite_name = "Alloc"; break; 836 case NO_OVERWRITE: overwrite_name = "Alloc"; break;
814 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; 837 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break;
815 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break; 838 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break;
816 default: overwrite_name = "UnknownOverwrite"; break; 839 default: overwrite_name = "UnknownOverwrite"; break;
817 } 840 }
818 841
819 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), 842 OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
820 "GenericBinaryOpStub_%s_%s%s_%s%s", 843 "GenericBinaryOpStub_%s_%s%s_%s%s%s",
821 op_name, 844 op_name,
822 overwrite_name, 845 overwrite_name,
823 (flags_ & NO_SMI_CODE_IN_STUB) ? "_NoSmiInStub" : "", 846 (flags_ & NO_SMI_CODE_IN_STUB) ? "_NoSmiInStub" : "",
824 args_in_registers_ ? "RegArgs" : "StackArgs", 847 args_in_registers_ ? "RegArgs" : "StackArgs",
825 args_reversed_ ? "_R" : ""); 848 args_reversed_ ? "_R" : "",
849 only_numbers_in_stub_ ? "_OnlyNumbers" : "");
826 return name_; 850 return name_;
827 } 851 }
828 852
829 853
830 // Call the specialized stub for a binary operation. 854 // Call the specialized stub for a binary operation.
831 class DeferredInlineBinaryOperation: public DeferredCode { 855 class DeferredInlineBinaryOperation: public DeferredCode {
832 public: 856 public:
833 DeferredInlineBinaryOperation(Token::Value op, 857 DeferredInlineBinaryOperation(Token::Value op,
834 Register dst, 858 Register dst,
835 Register left, 859 Register left,
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
965 } else if (right_is_string) { 989 } else if (right_is_string) {
966 answer = 990 answer =
967 frame_->InvokeBuiltin(Builtins::STRING_ADD_RIGHT, CALL_FUNCTION, 2); 991 frame_->InvokeBuiltin(Builtins::STRING_ADD_RIGHT, CALL_FUNCTION, 2);
968 } 992 }
969 frame_->Push(&answer); 993 frame_->Push(&answer);
970 return; 994 return;
971 } 995 }
972 // Neither operand is known to be a string. 996 // Neither operand is known to be a string.
973 } 997 }
974 998
975 bool left_is_smi = left.is_constant() && left.handle()->IsSmi(); 999 bool left_is_smi_constant = left.is_constant() && left.handle()->IsSmi();
976 bool left_is_non_smi = left.is_constant() && !left.handle()->IsSmi(); 1000 bool left_is_non_smi_constant = left.is_constant() && !left.handle()->IsSmi();
977 bool right_is_smi = right.is_constant() && right.handle()->IsSmi(); 1001 bool right_is_smi_constant = right.is_constant() && right.handle()->IsSmi();
978 bool right_is_non_smi = right.is_constant() && !right.handle()->IsSmi(); 1002 bool right_is_non_smi_constant =
1003 right.is_constant() && !right.handle()->IsSmi();
979 1004
980 if (left_is_smi && right_is_smi) { 1005 if (left_is_smi_constant && right_is_smi_constant) {
981 // Compute the constant result at compile time, and leave it on the frame. 1006 // Compute the constant result at compile time, and leave it on the frame.
982 int left_int = Smi::cast(*left.handle())->value(); 1007 int left_int = Smi::cast(*left.handle())->value();
983 int right_int = Smi::cast(*right.handle())->value(); 1008 int right_int = Smi::cast(*right.handle())->value();
984 if (FoldConstantSmis(op, left_int, right_int)) return; 1009 if (FoldConstantSmis(op, left_int, right_int)) return;
985 } 1010 }
986 1011
1012 // Get number type of left and right sub-expressions.
1013 bool only_numbers = left.is_number() && right.is_number();
1014 bool only_smis = left.is_smi() && right.is_smi();
1015
987 Result answer; 1016 Result answer;
988 if (left_is_non_smi || right_is_non_smi) { 1017 if (left_is_non_smi_constant || right_is_non_smi_constant) {
989 // Go straight to the slow case, with no smi code. 1018 // Go straight to the slow case, with no smi code.
990 GenericBinaryOpStub stub(op, overwrite_mode, NO_SMI_CODE_IN_STUB); 1019 GenericBinaryOpStub stub(op,
1020 overwrite_mode,
1021 NO_SMI_CODE_IN_STUB,
1022 only_numbers);
991 answer = stub.GenerateCall(masm_, frame_, &left, &right); 1023 answer = stub.GenerateCall(masm_, frame_, &left, &right);
992 } else if (right_is_smi) { 1024 } else if (right_is_smi_constant) {
993 answer = ConstantSmiBinaryOperation(op, &left, right.handle(), 1025 answer = ConstantSmiBinaryOperation(op, &left, right.handle(),
994 type, false, overwrite_mode); 1026 type, false, overwrite_mode);
995 } else if (left_is_smi) { 1027 } else if (left_is_smi_constant) {
996 answer = ConstantSmiBinaryOperation(op, &right, left.handle(), 1028 answer = ConstantSmiBinaryOperation(op, &right, left.handle(),
997 type, true, overwrite_mode); 1029 type, true, overwrite_mode);
998 } else { 1030 } else {
999 // Set the flags based on the operation, type and loop nesting level. 1031 // Set the flags based on the operation, type and loop nesting level.
1000 // Bit operations always assume they likely operate on Smis. Still only 1032 // Bit operations always assume they likely operate on Smis. Still only
1001 // generate the inline Smi check code if this operation is part of a loop. 1033 // generate the inline Smi check code if this operation is part of a loop.
1002 // For all other operations only inline the Smi check code for likely smis 1034 // For all other operations only inline the Smi check code for likely smis
1003 // if the operation is part of a loop. 1035 // if the operation is part of a loop.
1004 if (loop_nesting() > 0 && (Token::IsBitOp(op) || type->IsLikelySmi())) { 1036 if (loop_nesting() > 0 && (Token::IsBitOp(op) || type->IsLikelySmi())) {
1005 answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode); 1037 answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode);
1006 } else { 1038 } else {
1007 GenericBinaryOpStub stub(op, overwrite_mode, NO_GENERIC_BINARY_FLAGS); 1039 GenericBinaryOpStub stub(op,
1040 overwrite_mode,
1041 NO_GENERIC_BINARY_FLAGS,
1042 only_numbers);
1008 answer = stub.GenerateCall(masm_, frame_, &left, &right); 1043 answer = stub.GenerateCall(masm_, frame_, &left, &right);
1009 } 1044 }
1010 } 1045 }
1046
1047 // Set NumberInfo of result according to the operation performed.
1048 NumberInfo::Type info = NumberInfo::kUnknown;
1049 switch (op) {
1050 case Token::COMMA:
1051 info = right.number_info();
1052 case Token::OR:
1053 case Token::AND:
1054 // Could be anything. Check inputs.
1055 if (only_numbers)
1056 info = NumberInfo::kNumber;
1057 break;
1058 case Token::BIT_OR:
1059 case Token::BIT_XOR:
1060 case Token::BIT_AND:
1061 case Token::SAR:
1062 case Token::SHR:
1063 info = only_smis ? NumberInfo::kSmi : NumberInfo::kNumber;
1064 break;
1065 case Token::SHL:
1066 info = NumberInfo::kNumber;
1067 break;
1068 case Token::ADD:
1069 // Could be strings or numbers. Check types of inputs.
1070 if (only_numbers) info = NumberInfo::kNumber;
1071 break;
1072 case Token::SUB:
1073 case Token::MUL:
1074 case Token::DIV:
1075 case Token::MOD:
1076 info = NumberInfo::kNumber;
1077 break;
1078 default:
1079 UNREACHABLE();
1080 }
1081 answer.set_number_info(info);
1011 frame_->Push(&answer); 1082 frame_->Push(&answer);
1012 } 1083 }
1013 1084
1014 1085
1015 bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) { 1086 bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) {
1016 Object* answer_object = Heap::undefined_value(); 1087 Object* answer_object = Heap::undefined_value();
1017 switch (op) { 1088 switch (op) {
1018 case Token::ADD: 1089 case Token::ADD:
1019 if (Smi::IsValid(left + right)) { 1090 if (Smi::IsValid(left + right)) {
1020 answer_object = Smi::FromInt(left + right); 1091 answer_object = Smi::FromInt(left + right);
(...skipping 6517 matching lines...) Expand 10 before | Expand all | Expand 10 after
7538 } 7609 }
7539 7610
7540 // Floating point case. 7611 // Floating point case.
7541 switch (op_) { 7612 switch (op_) {
7542 case Token::ADD: 7613 case Token::ADD:
7543 case Token::SUB: 7614 case Token::SUB:
7544 case Token::MUL: 7615 case Token::MUL:
7545 case Token::DIV: { 7616 case Token::DIV: {
7546 if (CpuFeatures::IsSupported(SSE2)) { 7617 if (CpuFeatures::IsSupported(SSE2)) {
7547 CpuFeatures::Scope use_sse2(SSE2); 7618 CpuFeatures::Scope use_sse2(SSE2);
7548 FloatingPointHelper::LoadSSE2Operands(masm, &call_runtime); 7619 if (only_numbers_in_stub_) {
7620 if (FLAG_debug_code) {
7621 // Assert at runtime that inputs are only numbers.
7622 __ AbortIfNotNumber(edx,
7623 "GenericBinaryOpStub operand not a number.");
7624 __ AbortIfNotNumber(eax,
7625 "GenericBinaryOpStub operand not a number.");
7626 }
7627 FloatingPointHelper::LoadSSE2Operands(masm);
7628 } else {
7629 FloatingPointHelper::LoadSSE2Operands(masm, &call_runtime);
7630 }
7549 7631
7550 switch (op_) { 7632 switch (op_) {
7551 case Token::ADD: __ addsd(xmm0, xmm1); break; 7633 case Token::ADD: __ addsd(xmm0, xmm1); break;
7552 case Token::SUB: __ subsd(xmm0, xmm1); break; 7634 case Token::SUB: __ subsd(xmm0, xmm1); break;
7553 case Token::MUL: __ mulsd(xmm0, xmm1); break; 7635 case Token::MUL: __ mulsd(xmm0, xmm1); break;
7554 case Token::DIV: __ divsd(xmm0, xmm1); break; 7636 case Token::DIV: __ divsd(xmm0, xmm1); break;
7555 default: UNREACHABLE(); 7637 default: UNREACHABLE();
7556 } 7638 }
7557 GenerateHeapResultAllocation(masm, &call_runtime); 7639 GenerateHeapResultAllocation(masm, &call_runtime);
7558 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); 7640 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
7559 GenerateReturn(masm); 7641 GenerateReturn(masm);
7560 } else { // SSE2 not available, use FPU. 7642 } else { // SSE2 not available, use FPU.
7561 FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx); 7643 if (only_numbers_in_stub_) {
7644 if (FLAG_debug_code) {
7645 // Assert at runtime that inputs are only numbers.
7646 __ AbortIfNotNumber(edx,
7647 "GenericBinaryOpStub operand not a number.");
7648 __ AbortIfNotNumber(eax,
7649 "GenericBinaryOpStub operand not a number.");
7650 }
7651 } else {
7652 FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx);
7653 }
7562 FloatingPointHelper::LoadFloatOperands( 7654 FloatingPointHelper::LoadFloatOperands(
7563 masm, 7655 masm,
7564 ecx, 7656 ecx,
7565 FloatingPointHelper::ARGS_IN_REGISTERS); 7657 FloatingPointHelper::ARGS_IN_REGISTERS);
7566 switch (op_) { 7658 switch (op_) {
7567 case Token::ADD: __ faddp(1); break; 7659 case Token::ADD: __ faddp(1); break;
7568 case Token::SUB: __ fsubp(1); break; 7660 case Token::SUB: __ fsubp(1); break;
7569 case Token::MUL: __ fmulp(1); break; 7661 case Token::MUL: __ fmulp(1); break;
7570 case Token::DIV: __ fdivp(1); break; 7662 case Token::DIV: __ fdivp(1); break;
7571 default: UNREACHABLE(); 7663 default: UNREACHABLE();
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after
8063 __ bind(&load_smi); 8155 __ bind(&load_smi);
8064 __ SmiUntag(number); 8156 __ SmiUntag(number);
8065 __ push(number); 8157 __ push(number);
8066 __ fild_s(Operand(esp, 0)); 8158 __ fild_s(Operand(esp, 0));
8067 __ pop(number); 8159 __ pop(number);
8068 8160
8069 __ bind(&done); 8161 __ bind(&done);
8070 } 8162 }
8071 8163
8072 8164
8165 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm) {
8166 Label load_smi_edx, load_eax, load_smi_eax, done;
8167 // Load operand in edx into xmm0.
8168 __ test(edx, Immediate(kSmiTagMask));
8169 __ j(zero, &load_smi_edx, not_taken); // Argument in edx is a smi.
8170 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
8171
8172 __ bind(&load_eax);
8173 // Load operand in eax into xmm1.
8174 __ test(eax, Immediate(kSmiTagMask));
8175 __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi.
8176 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
8177 __ jmp(&done);
8178
8179 __ bind(&load_smi_edx);
8180 __ SmiUntag(edx); // Untag smi before converting to float.
8181 __ cvtsi2sd(xmm0, Operand(edx));
8182 __ SmiTag(edx); // Retag smi for heap number overwriting test.
8183 __ jmp(&load_eax);
8184
8185 __ bind(&load_smi_eax);
8186 __ SmiUntag(eax); // Untag smi before converting to float.
8187 __ cvtsi2sd(xmm1, Operand(eax));
8188 __ SmiTag(eax); // Retag smi for heap number overwriting test.
8189
8190 __ bind(&done);
8191 }
8192
8193
8073 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm, 8194 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm,
8074 Label* not_numbers) { 8195 Label* not_numbers) {
8075 Label load_smi_edx, load_eax, load_smi_eax, load_float_eax, done; 8196 Label load_smi_edx, load_eax, load_smi_eax, load_float_eax, done;
8076 // Load operand in edx into xmm0, or branch to not_numbers. 8197 // Load operand in edx into xmm0, or branch to not_numbers.
8077 __ test(edx, Immediate(kSmiTagMask)); 8198 __ test(edx, Immediate(kSmiTagMask));
8078 __ j(zero, &load_smi_edx, not_taken); // Argument in edx is a smi. 8199 __ j(zero, &load_smi_edx, not_taken); // Argument in edx is a smi.
8079 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), Factory::heap_number_map()); 8200 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), Factory::heap_number_map());
8080 __ j(not_equal, not_numbers); // Argument in edx is not a number. 8201 __ j(not_equal, not_numbers); // Argument in edx is not a number.
8081 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); 8202 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
8082 __ bind(&load_eax); 8203 __ bind(&load_eax);
(...skipping 2342 matching lines...) Expand 10 before | Expand all | Expand 10 after
10425 10546
10426 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 10547 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
10427 // tagged as a small integer. 10548 // tagged as a small integer.
10428 __ bind(&runtime); 10549 __ bind(&runtime);
10429 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); 10550 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1);
10430 } 10551 }
10431 10552
10432 #undef __ 10553 #undef __
10433 10554
10434 } } // namespace v8::internal 10555 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/ia32/macro-assembler-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698