| 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 |