OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |