OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
612 // from |scratch|, it will contain that int32 value. | 612 // from |scratch|, it will contain that int32 value. |
613 static void CheckSSE2OperandIsInt32(MacroAssembler* masm, | 613 static void CheckSSE2OperandIsInt32(MacroAssembler* masm, |
614 Label* non_int32, | 614 Label* non_int32, |
615 XMMRegister operand, | 615 XMMRegister operand, |
616 Register int32_result, | 616 Register int32_result, |
617 Register scratch, | 617 Register scratch, |
618 XMMRegister xmm_scratch); | 618 XMMRegister xmm_scratch); |
619 }; | 619 }; |
620 | 620 |
621 | 621 |
622 // Get the integer part of a heap number. Surprisingly, all this bit twiddling | 622 void DoubleToIStub::Generate(MacroAssembler* masm) { |
623 // is faster than using the built-in instructions on floating point registers. | 623 Register input_reg = this->source(); |
624 // Trashes edi and ebx. Dest is ecx. Source cannot be ecx or one of the | 624 Register final_result_reg = this->destination(); |
625 // trashed registers. | 625 ASSERT(is_truncating()); |
626 static void IntegerConvert(MacroAssembler* masm, | 626 |
627 Register source, | 627 Label check_negative, process_64_bits, done, done_no_stash; |
628 bool use_sse3, | 628 |
629 Label* conversion_failure) { | 629 int double_offset = offset(); |
630 ASSERT(!source.is(ecx) && !source.is(edi) && !source.is(ebx)); | 630 |
631 Label done, right_exponent, normal_exponent; | 631 // Account for return address and saved regs if input is esp. |
632 Register scratch = ebx; | 632 if (input_reg.is(esp)) double_offset += 3 * kPointerSize; |
633 Register scratch2 = edi; | 633 |
634 // Get exponent word. | 634 MemOperand mantissa_operand(MemOperand(input_reg, double_offset)); |
635 __ mov(scratch, FieldOperand(source, HeapNumber::kExponentOffset)); | 635 MemOperand exponent_operand(MemOperand(input_reg, |
636 // Get exponent alone in scratch2. | 636 double_offset + kPointerSize)); |
637 __ mov(scratch2, scratch); | 637 |
638 __ and_(scratch2, HeapNumber::kExponentMask); | 638 Register scratch1 = ebx; |
639 __ shr(scratch2, HeapNumber::kExponentShift); | 639 if (final_result_reg.is(ebx)) { |
640 __ sub(scratch2, Immediate(HeapNumber::kExponentBias)); | 640 scratch1 = input_reg.is(edx) ? edi : edx; |
641 // Load ecx with zero. We use this either for the final shift or | 641 } else if (final_result_reg.is(edx)) { |
642 // for the answer. | 642 scratch1 = input_reg.is(ebx) ? edi : ebx; |
643 __ xor_(ecx, ecx); | 643 } else if (input_reg.is(ebx)) { |
644 // If the exponent is above 83, the number contains no significant | 644 scratch1 = edx; |
645 // bits in the range 0..2^31, so the result is zero. | 645 } |
Yang
2013/07/11 12:00:27
Seems easy to introduce bugs in here.
How about s
danno
2013/07/11 16:00:23
Done.
| |
646 static const uint32_t kResultIsZeroExponent = 83; | 646 Register result_reg = final_result_reg.is(ecx) ? eax : final_result_reg; |
647 __ cmp(scratch2, Immediate(kResultIsZeroExponent)); | 647 Register save_reg = final_result_reg.is(ecx) ? eax : ecx; |
Yang
2013/07/11 12:00:27
why do we need to spill eax if the result is expec
danno
2013/07/11 16:00:23
No, it's because we use eax above to calculate the
| |
648 __ push(scratch1); | |
649 __ push(save_reg); | |
650 | |
651 bool stash_exponent_copy = !input_reg.is(esp); | |
652 if (!input_reg.is(ecx)) { | |
653 __ mov(ecx, exponent_operand); | |
654 if (stash_exponent_copy) __ push(ecx); | |
655 } | |
656 __ mov(scratch1, mantissa_operand); | |
657 if (CpuFeatures::IsSupported(SSE3)) { | |
658 CpuFeatureScope scope(masm, SSE3); | |
659 // Load x87 register with heap number. | |
660 __ fld_d(mantissa_operand); | |
661 } | |
662 if (input_reg.is(ecx)) { | |
663 __ mov(ecx, exponent_operand); | |
664 if (stash_exponent_copy) __ push(ecx); | |
665 } | |
Yang
2013/07/11 12:00:27
At this point, we have overwritten ecx regardless
danno
2013/07/11 16:00:23
Done.
| |
666 __ shr(ecx, HeapNumber::kExponentShift); | |
667 __ and_(ecx, | |
668 Immediate(HeapNumber::kExponentMask >> HeapNumber::kExponentShift)); | |
Yang
2013/07/11 12:00:27
Looks like we could first mask and then shift, lik
danno
2013/07/11 16:00:23
Done.
| |
669 __ lea(result_reg, MemOperand(ecx, -HeapNumber::kExponentBias)); | |
Yang
2013/07/11 12:00:27
As far as I can see the value in result_reg is not
danno
2013/07/11 16:00:23
This is actually a different test. The cmp and bel
| |
670 __ cmp(result_reg, Immediate(HeapNumber::kMantissaBits)); | |
671 __ j(below, &process_64_bits); | |
672 | |
673 // Result is entirely in lower 32-bits of mantissa | |
674 int delta = HeapNumber::kExponentBias + Double::kPhysicalSignificandSize; | |
675 if (CpuFeatures::IsSupported(SSE3)) { | |
676 __ fstp(0); | |
677 } | |
678 __ sub(ecx, Immediate(delta)); | |
679 __ mov(result_reg, Immediate(0)); | |
Yang
2013/07/11 12:00:27
Use Set instead of mov to use xor, which is shorte
danno
2013/07/11 16:00:23
Done.
| |
680 __ cmp(ecx, Immediate(31)); | |
648 __ j(above, &done); | 681 __ j(above, &done); |
649 if (use_sse3) { | 682 __ shl_cl(scratch1); |
683 __ jmp(&check_negative); | |
684 | |
685 __ bind(&process_64_bits); | |
686 if (CpuFeatures::IsSupported(SSE3)) { | |
650 CpuFeatureScope scope(masm, SSE3); | 687 CpuFeatureScope scope(masm, SSE3); |
651 // Check whether the exponent is too big for a 64 bit signed integer. | 688 if (stash_exponent_copy) { |
652 static const uint32_t kTooBigExponent = 63; | 689 // Already a copy of the mantissa on the stack, overwrite it. |
Yang
2013/07/11 12:00:27
Comment seems wrong. We pushed a copy of the expon
danno
2013/07/11 16:00:23
Done.
| |
653 __ cmp(scratch2, Immediate(kTooBigExponent)); | 690 __ sub(esp, Immediate(kDoubleSize / 2)); |
654 __ j(greater_equal, conversion_failure); | 691 } else { |
655 // Load x87 register with heap number. | 692 // Reserve space for 64 bit answer. |
656 __ fld_d(FieldOperand(source, HeapNumber::kValueOffset)); | 693 __ sub(esp, Immediate(kDoubleSize)); // Nolint. |
657 // Reserve space for 64 bit answer. | 694 } |
658 __ sub(esp, Immediate(sizeof(uint64_t))); // Nolint. | |
659 // Do conversion, which cannot fail because we checked the exponent. | 695 // Do conversion, which cannot fail because we checked the exponent. |
660 __ fisttp_d(Operand(esp, 0)); | 696 __ fisttp_d(Operand(esp, 0)); |
661 __ mov(ecx, Operand(esp, 0)); // Load low word of answer into ecx. | 697 __ mov(result_reg, Operand(esp, 0)); // Load low word of answer as result |
662 __ add(esp, Immediate(sizeof(uint64_t))); // Nolint. | 698 __ add(esp, Immediate(sizeof(uint64_t))); // Nolint. |
Yang
2013/07/11 12:00:27
We should use kDoubleSize for consistency. Also, d
danno
2013/07/11 16:00:23
Done.
| |
699 __ jmp(&done_no_stash); | |
663 } else { | 700 } else { |
664 // Check whether the exponent matches a 32 bit signed int that cannot be | 701 // Result must be extracted from shifted 32-bit mantissa |
665 // represented by a Smi. A non-smi 32 bit integer is 1.xxx * 2^30 so the | 702 __ mov(result_reg, Immediate(delta)); |
666 // exponent is 30 (biased). This is the exponent that we are fastest at and | 703 __ sub(result_reg, ecx); |
667 // also the highest exponent we can handle here. | 704 __ mov(ecx, result_reg); |
Yang
2013/07/11 12:00:27
sub(ecx, Immediate(delta));
neg(ecx);
should do t
danno
2013/07/11 16:00:23
Done.
| |
668 const uint32_t non_smi_exponent = 30; | 705 if (stash_exponent_copy) { |
669 __ cmp(scratch2, Immediate(non_smi_exponent)); | 706 __ mov(result_reg, MemOperand(esp, 0)); |
670 // If we have a match of the int32-but-not-Smi exponent then skip some | 707 } else { |
671 // logic. | 708 __ mov(result_reg, exponent_operand); |
672 __ j(equal, &right_exponent, Label::kNear); | 709 } |
673 // If the exponent is higher than that then go to slow case. This catches | 710 __ and_(result_reg, |
674 // numbers that don't fit in a signed int32, infinities and NaNs. | 711 Immediate(static_cast<uint32_t>(Double::kSignificandMask >> 32))); |
675 __ j(less, &normal_exponent, Label::kNear); | 712 __ add(result_reg, |
713 Immediate(static_cast<uint32_t>(Double::kHiddenBit >> 32))); | |
714 __ shrd(result_reg, scratch1); | |
715 __ shr_cl(result_reg); | |
716 __ test(ecx, Immediate(32)); | |
717 if (CpuFeatures::IsSupported(CMOV)) { | |
718 CpuFeatureScope use_cmov(masm, CMOV); | |
719 __ cmov(not_equal, scratch1, result_reg); | |
720 } else { | |
721 Label skip_mov; | |
722 __ j(equal, &skip_mov); | |
Yang
2013/07/11 12:00:27
mark as near jump.
danno
2013/07/11 16:00:23
Done.
| |
723 __ mov(scratch1, result_reg); | |
724 __ bind(&skip_mov); | |
725 } | |
726 } | |
676 | 727 |
677 { | 728 // If the double was negative, negate the integer result. |
678 // Handle a big exponent. The only reason we have this code is that the | 729 __ bind(&check_negative); |
679 // >>> operator has a tendency to generate numbers with an exponent of 31. | 730 __ mov(result_reg, scratch1); |
680 const uint32_t big_non_smi_exponent = 31; | 731 __ neg(result_reg); |
681 __ cmp(scratch2, Immediate(big_non_smi_exponent)); | 732 if (stash_exponent_copy) { |
682 __ j(not_equal, conversion_failure); | 733 __ cmp(MemOperand(esp, 0), Immediate(0)); |
683 // We have the big exponent, typically from >>>. This means the number is | 734 } else { |
684 // in the range 2^31 to 2^32 - 1. Get the top bits of the mantissa. | 735 __ cmp(exponent_operand, Immediate(0)); |
685 __ mov(scratch2, scratch); | 736 } |
686 __ and_(scratch2, HeapNumber::kMantissaMask); | 737 if (CpuFeatures::IsSupported(CMOV)) { |
687 // Put back the implicit 1. | 738 CpuFeatureScope use_cmov(masm, CMOV); |
688 __ or_(scratch2, 1 << HeapNumber::kExponentShift); | 739 __ cmov(greater, result_reg, scratch1); |
689 // Shift up the mantissa bits to take up the space the exponent used to | 740 } else { |
690 // take. We just orred in the implicit bit so that took care of one and | 741 Label skip_mov; |
691 // we want to use the full unsigned range so we subtract 1 bit from the | 742 __ j(less_equal, &skip_mov); |
Yang
2013/07/11 12:00:27
mark as near jump
danno
2013/07/11 16:00:23
Done.
| |
692 // shift distance. | 743 __ mov(result_reg, scratch1); |
693 const int big_shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 1; | 744 __ bind(&skip_mov); |
694 __ shl(scratch2, big_shift_distance); | 745 } |
695 // Get the second half of the double. | |
696 __ mov(ecx, FieldOperand(source, HeapNumber::kMantissaOffset)); | |
697 // Shift down 21 bits to get the most significant 11 bits or the low | |
698 // mantissa word. | |
699 __ shr(ecx, 32 - big_shift_distance); | |
700 __ or_(ecx, scratch2); | |
701 // We have the answer in ecx, but we may need to negate it. | |
702 __ test(scratch, scratch); | |
703 __ j(positive, &done, Label::kNear); | |
704 __ neg(ecx); | |
705 __ jmp(&done, Label::kNear); | |
706 } | |
707 | 746 |
708 __ bind(&normal_exponent); | 747 // Restore registers |
709 // Exponent word in scratch, exponent in scratch2. Zero in ecx. | 748 __ bind(&done); |
710 // We know that 0 <= exponent < 30. | 749 if (stash_exponent_copy) { |
711 __ mov(ecx, Immediate(30)); | 750 __ add(esp, Immediate(kDoubleSize / 2)); |
712 __ sub(ecx, scratch2); | |
713 | |
714 __ bind(&right_exponent); | |
715 // Here ecx is the shift, scratch is the exponent word. | |
716 // Get the top bits of the mantissa. | |
717 __ and_(scratch, HeapNumber::kMantissaMask); | |
718 // Put back the implicit 1. | |
719 __ or_(scratch, 1 << HeapNumber::kExponentShift); | |
720 // Shift up the mantissa bits to take up the space the exponent used to | |
721 // take. We have kExponentShift + 1 significant bits int he low end of the | |
722 // word. Shift them to the top bits. | |
723 const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2; | |
724 __ shl(scratch, shift_distance); | |
725 // Get the second half of the double. For some exponents we don't | |
726 // actually need this because the bits get shifted out again, but | |
727 // it's probably slower to test than just to do it. | |
728 __ mov(scratch2, FieldOperand(source, HeapNumber::kMantissaOffset)); | |
729 // Shift down 22 bits to get the most significant 10 bits or the low | |
730 // mantissa word. | |
731 __ shr(scratch2, 32 - shift_distance); | |
732 __ or_(scratch2, scratch); | |
733 // Move down according to the exponent. | |
734 __ shr_cl(scratch2); | |
735 // Now the unsigned answer is in scratch2. We need to move it to ecx and | |
736 // we may need to fix the sign. | |
737 Label negative; | |
738 __ xor_(ecx, ecx); | |
739 __ cmp(ecx, FieldOperand(source, HeapNumber::kExponentOffset)); | |
740 __ j(greater, &negative, Label::kNear); | |
741 __ mov(ecx, scratch2); | |
742 __ jmp(&done, Label::kNear); | |
743 __ bind(&negative); | |
744 __ sub(ecx, scratch2); | |
745 } | 751 } |
746 __ bind(&done); | 752 __ bind(&done_no_stash); |
753 if (final_result_reg.is(ecx)) __ mov(ecx, save_reg); | |
Yang
2013/07/11 12:00:27
I think something like
if (!final_result_reg.is(r
danno
2013/07/11 16:00:23
Done.
| |
754 __ pop(save_reg); | |
755 __ pop(scratch1); | |
756 __ ret(0); | |
747 } | 757 } |
748 | 758 |
749 | 759 |
750 // Uses SSE2 to convert the heap number in |source| to an integer. Jumps to | 760 // Uses SSE2 to convert the heap number in |source| to an integer. Jumps to |
751 // |conversion_failure| if the heap number did not contain an int32 value. | 761 // |conversion_failure| if the heap number did not contain an int32 value. |
752 // Result is in ecx. Trashes ebx, xmm0, and xmm1. | 762 // Result is in ecx. Trashes ebx, xmm0, and xmm1. |
753 static void ConvertHeapNumberToInt32(MacroAssembler* masm, | 763 static void ConvertHeapNumberToInt32(MacroAssembler* masm, |
754 Register source, | 764 Register source, |
755 Label* conversion_failure) { | 765 Label* conversion_failure) { |
756 __ movdbl(xmm0, FieldOperand(source, HeapNumber::kValueOffset)); | 766 __ movdbl(xmm0, FieldOperand(source, HeapNumber::kValueOffset)); |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
963 } | 973 } |
964 | 974 |
965 | 975 |
966 void UnaryOpStub::GenerateHeapNumberCodeBitNot(MacroAssembler* masm, | 976 void UnaryOpStub::GenerateHeapNumberCodeBitNot(MacroAssembler* masm, |
967 Label* slow) { | 977 Label* slow) { |
968 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); | 978 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); |
969 __ cmp(edx, masm->isolate()->factory()->heap_number_map()); | 979 __ cmp(edx, masm->isolate()->factory()->heap_number_map()); |
970 __ j(not_equal, slow); | 980 __ j(not_equal, slow); |
971 | 981 |
972 // Convert the heap number in eax to an untagged integer in ecx. | 982 // Convert the heap number in eax to an untagged integer in ecx. |
973 IntegerConvert(masm, eax, CpuFeatures::IsSupported(SSE3), slow); | 983 DoubleToIStub stub(eax, ecx, HeapNumber::kValueOffset - kSmiTagSize, true); |
Yang
2013/07/11 12:00:27
I think you want to use (HeapNumber::kValueOffset
danno
2013/07/11 16:00:23
Done.
| |
984 __ call(stub.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); | |
974 | 985 |
975 // Do the bitwise operation and check if the result fits in a smi. | 986 // Do the bitwise operation and check if the result fits in a smi. |
976 Label try_float; | 987 Label try_float; |
977 __ not_(ecx); | 988 __ not_(ecx); |
978 __ cmp(ecx, 0xc0000000); | 989 __ cmp(ecx, 0xc0000000); |
979 __ j(sign, &try_float, Label::kNear); | 990 __ j(sign, &try_float, Label::kNear); |
980 | 991 |
981 // Tag the result as a smi and we're done. | 992 // Tag the result as a smi and we're done. |
982 STATIC_ASSERT(kSmiTagSize == 1); | 993 STATIC_ASSERT(kSmiTagSize == 1); |
983 __ lea(eax, Operand(ecx, times_2, kSmiTag)); | 994 __ lea(eax, Operand(ecx, times_2, kSmiTag)); |
(...skipping 11 matching lines...) Expand all Loading... | |
995 { | 1006 { |
996 FrameScope scope(masm, StackFrame::INTERNAL); | 1007 FrameScope scope(masm, StackFrame::INTERNAL); |
997 // Push the original HeapNumber on the stack. The integer value can't | 1008 // Push the original HeapNumber on the stack. The integer value can't |
998 // be stored since it's untagged and not in the smi range (so we can't | 1009 // be stored since it's untagged and not in the smi range (so we can't |
999 // smi-tag it). We'll recalculate the value after the GC instead. | 1010 // smi-tag it). We'll recalculate the value after the GC instead. |
1000 __ push(ebx); | 1011 __ push(ebx); |
1001 __ CallRuntime(Runtime::kNumberAlloc, 0); | 1012 __ CallRuntime(Runtime::kNumberAlloc, 0); |
1002 // New HeapNumber is in eax. | 1013 // New HeapNumber is in eax. |
1003 __ pop(edx); | 1014 __ pop(edx); |
1004 } | 1015 } |
1005 // IntegerConvert uses ebx and edi as scratch registers. | 1016 DoubleToIStub stub(edx, ecx, HeapNumber::kValueOffset - kSmiTagSize, true); |
Yang
2013/07/11 12:00:27
Ditto.
danno
2013/07/11 16:00:23
Done.
| |
1006 // This conversion won't go slow-case. | 1017 __ call(stub.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); |
1007 IntegerConvert(masm, edx, CpuFeatures::IsSupported(SSE3), slow); | 1018 |
1008 __ not_(ecx); | 1019 __ not_(ecx); |
1009 | 1020 |
1010 __ bind(&heapnumber_allocated); | 1021 __ bind(&heapnumber_allocated); |
1011 } | 1022 } |
1012 if (CpuFeatures::IsSupported(SSE2)) { | 1023 if (CpuFeatures::IsSupported(SSE2)) { |
1013 CpuFeatureScope use_sse2(masm, SSE2); | 1024 CpuFeatureScope use_sse2(masm, SSE2); |
1014 __ cvtsi2sd(xmm0, ecx); | 1025 __ cvtsi2sd(xmm0, ecx); |
1015 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 1026 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
1016 } else { | 1027 } else { |
1017 __ push(ecx); | 1028 __ push(ecx); |
(...skipping 1658 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2676 __ bind(&arg1_is_object); | 2687 __ bind(&arg1_is_object); |
2677 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); | 2688 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); |
2678 __ cmp(ebx, factory->heap_number_map()); | 2689 __ cmp(ebx, factory->heap_number_map()); |
2679 __ j(not_equal, &check_undefined_arg1); | 2690 __ j(not_equal, &check_undefined_arg1); |
2680 | 2691 |
2681 // Get the untagged integer version of the edx heap number in ecx. | 2692 // Get the untagged integer version of the edx heap number in ecx. |
2682 if (left_type == BinaryOpIC::INT32 && CpuFeatures::IsSupported(SSE2)) { | 2693 if (left_type == BinaryOpIC::INT32 && CpuFeatures::IsSupported(SSE2)) { |
2683 CpuFeatureScope use_sse2(masm, SSE2); | 2694 CpuFeatureScope use_sse2(masm, SSE2); |
2684 ConvertHeapNumberToInt32(masm, edx, conversion_failure); | 2695 ConvertHeapNumberToInt32(masm, edx, conversion_failure); |
2685 } else { | 2696 } else { |
2686 IntegerConvert(masm, edx, use_sse3, conversion_failure); | 2697 DoubleToIStub stub(edx, ecx, HeapNumber::kValueOffset - kSmiTagSize, true); |
Yang
2013/07/11 12:00:27
Ditto.
danno
2013/07/11 16:00:23
Done.
| |
2698 __ call(stub.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); | |
2687 } | 2699 } |
2688 __ mov(edx, ecx); | 2700 __ mov(edx, ecx); |
2689 | 2701 |
2690 // Here edx has the untagged integer, eax has a Smi or a heap number. | 2702 // Here edx has the untagged integer, eax has a Smi or a heap number. |
2691 __ bind(&load_arg2); | 2703 __ bind(&load_arg2); |
2692 | 2704 |
2693 // Test if arg2 is a Smi. | 2705 // Test if arg2 is a Smi. |
2694 if (right_type == BinaryOpIC::SMI) { | 2706 if (right_type == BinaryOpIC::SMI) { |
2695 __ JumpIfNotSmi(eax, conversion_failure); | 2707 __ JumpIfNotSmi(eax, conversion_failure); |
2696 } else { | 2708 } else { |
(...skipping 14 matching lines...) Expand all Loading... | |
2711 __ bind(&arg2_is_object); | 2723 __ bind(&arg2_is_object); |
2712 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 2724 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
2713 __ cmp(ebx, factory->heap_number_map()); | 2725 __ cmp(ebx, factory->heap_number_map()); |
2714 __ j(not_equal, &check_undefined_arg2); | 2726 __ j(not_equal, &check_undefined_arg2); |
2715 // Get the untagged integer version of the eax heap number in ecx. | 2727 // Get the untagged integer version of the eax heap number in ecx. |
2716 | 2728 |
2717 if (right_type == BinaryOpIC::INT32 && CpuFeatures::IsSupported(SSE2)) { | 2729 if (right_type == BinaryOpIC::INT32 && CpuFeatures::IsSupported(SSE2)) { |
2718 CpuFeatureScope use_sse2(masm, SSE2); | 2730 CpuFeatureScope use_sse2(masm, SSE2); |
2719 ConvertHeapNumberToInt32(masm, eax, conversion_failure); | 2731 ConvertHeapNumberToInt32(masm, eax, conversion_failure); |
2720 } else { | 2732 } else { |
2721 IntegerConvert(masm, eax, use_sse3, conversion_failure); | 2733 DoubleToIStub stub(eax, ecx, HeapNumber::kValueOffset - kSmiTagSize, true); |
Yang
2013/07/11 12:00:27
Ditto.
danno
2013/07/11 16:00:23
Done.
| |
2734 __ call(stub.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); | |
2722 } | 2735 } |
2723 | 2736 |
2724 __ bind(&done); | 2737 __ bind(&done); |
2725 __ mov(eax, edx); | 2738 __ mov(eax, edx); |
2726 } | 2739 } |
2727 | 2740 |
2728 | 2741 |
2729 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, | 2742 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, |
2730 Register number) { | 2743 Register number) { |
2731 Label load_smi, done; | 2744 Label load_smi, done; |
(...skipping 5287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8019 __ bind(&fast_elements_case); | 8032 __ bind(&fast_elements_case); |
8020 GenerateCase(masm, FAST_ELEMENTS); | 8033 GenerateCase(masm, FAST_ELEMENTS); |
8021 } | 8034 } |
8022 | 8035 |
8023 | 8036 |
8024 #undef __ | 8037 #undef __ |
8025 | 8038 |
8026 } } // namespace v8::internal | 8039 } } // namespace v8::internal |
8027 | 8040 |
8028 #endif // V8_TARGET_ARCH_IA32 | 8041 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |