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

Side by Side Diff: src/ia32/code-stubs-ia32.cc

Issue 148153010: Synchronize with r15701. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 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/assembler-ia32.cc ('k') | src/ia32/deoptimizer-ia32.cc » ('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 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 633 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 // from |scratch|, it will contain that int32 value. 644 // from |scratch|, it will contain that int32 value.
645 static void CheckSSE2OperandIsInt32(MacroAssembler* masm, 645 static void CheckSSE2OperandIsInt32(MacroAssembler* masm,
646 Label* non_int32, 646 Label* non_int32,
647 XMMRegister operand, 647 XMMRegister operand,
648 Register int32_result, 648 Register int32_result,
649 Register scratch, 649 Register scratch,
650 XMMRegister xmm_scratch); 650 XMMRegister xmm_scratch);
651 }; 651 };
652 652
653 653
654 // Get the integer part of a heap number. Surprisingly, all this bit twiddling 654 void DoubleToIStub::Generate(MacroAssembler* masm) {
655 // is faster than using the built-in instructions on floating point registers. 655 Register input_reg = this->source();
656 // Trashes edi and ebx. Dest is ecx. Source cannot be ecx or one of the 656 Register final_result_reg = this->destination();
657 // trashed registers. 657 ASSERT(is_truncating());
658 static void IntegerConvert(MacroAssembler* masm, 658
659 Register source, 659 Label check_negative, process_64_bits, done, done_no_stash;
660 bool use_sse3, 660
661 Label* conversion_failure) { 661 int double_offset = offset();
662 ASSERT(!source.is(ecx) && !source.is(edi) && !source.is(ebx)); 662
663 Label done, right_exponent, normal_exponent; 663 // Account for return address and saved regs if input is esp.
664 Register scratch = ebx; 664 if (input_reg.is(esp)) double_offset += 3 * kPointerSize;
665 Register scratch2 = edi; 665
666 // Get exponent word. 666 MemOperand mantissa_operand(MemOperand(input_reg, double_offset));
667 __ mov(scratch, FieldOperand(source, HeapNumber::kExponentOffset)); 667 MemOperand exponent_operand(MemOperand(input_reg,
668 // Get exponent alone in scratch2. 668 double_offset + kPointerSize));
669 __ mov(scratch2, scratch); 669
670 __ and_(scratch2, HeapNumber::kExponentMask); 670 Register scratch1;
671 __ shr(scratch2, HeapNumber::kExponentShift); 671 {
672 __ sub(scratch2, Immediate(HeapNumber::kExponentBias)); 672 Register scratch_candidates[3] = { ebx, edx, edi };
673 // Load ecx with zero. We use this either for the final shift or 673 for (int i = 0; i < 3; i++) {
674 // for the answer. 674 scratch1 = scratch_candidates[i];
675 __ xor_(ecx, ecx); 675 if (!final_result_reg.is(scratch1) && !input_reg.is(scratch1)) break;
676 // If the exponent is above 83, the number contains no significant 676 }
677 // bits in the range 0..2^31, so the result is zero. 677 }
678 static const uint32_t kResultIsZeroExponent = 83; 678 // Since we must use ecx for shifts below, use some other register (eax)
679 __ cmp(scratch2, Immediate(kResultIsZeroExponent)); 679 // to calculate the result if ecx is the requested return register.
680 Register result_reg = final_result_reg.is(ecx) ? eax : final_result_reg;
681 // Save ecx if it isn't the return register and therefore volatile, or if it
682 // is the return register, then save the temp register we use in its stead for
683 // the result.
684 Register save_reg = final_result_reg.is(ecx) ? eax : ecx;
685 __ push(scratch1);
686 __ push(save_reg);
687
688 bool stash_exponent_copy = !input_reg.is(esp);
689 __ mov(scratch1, mantissa_operand);
690 if (CpuFeatures::IsSupported(SSE3)) {
691 CpuFeatureScope scope(masm, SSE3);
692 // Load x87 register with heap number.
693 __ fld_d(mantissa_operand);
694 }
695 __ mov(ecx, exponent_operand);
696 if (stash_exponent_copy) __ push(ecx);
697
698 __ and_(ecx, HeapNumber::kExponentMask);
699 __ shr(ecx, HeapNumber::kExponentShift);
700 __ lea(result_reg, MemOperand(ecx, -HeapNumber::kExponentBias));
701 __ cmp(result_reg, Immediate(HeapNumber::kMantissaBits));
702 __ j(below, &process_64_bits);
703
704 // Result is entirely in lower 32-bits of mantissa
705 int delta = HeapNumber::kExponentBias + Double::kPhysicalSignificandSize;
706 if (CpuFeatures::IsSupported(SSE3)) {
707 __ fstp(0);
708 }
709 __ sub(ecx, Immediate(delta));
710 __ xor_(result_reg, result_reg);
711 __ cmp(ecx, Immediate(31));
680 __ j(above, &done); 712 __ j(above, &done);
681 if (use_sse3) { 713 __ shl_cl(scratch1);
714 __ jmp(&check_negative);
715
716 __ bind(&process_64_bits);
717 if (CpuFeatures::IsSupported(SSE3)) {
682 CpuFeatureScope scope(masm, SSE3); 718 CpuFeatureScope scope(masm, SSE3);
683 // Check whether the exponent is too big for a 64 bit signed integer. 719 if (stash_exponent_copy) {
684 static const uint32_t kTooBigExponent = 63; 720 // Already a copy of the exponent on the stack, overwrite it.
685 __ cmp(scratch2, Immediate(kTooBigExponent)); 721 STATIC_ASSERT(kDoubleSize == 2 * kPointerSize);
686 __ j(greater_equal, conversion_failure); 722 __ sub(esp, Immediate(kDoubleSize / 2));
687 // Load x87 register with heap number. 723 } else {
688 __ fld_d(FieldOperand(source, HeapNumber::kValueOffset)); 724 // Reserve space for 64 bit answer.
689 // Reserve space for 64 bit answer. 725 __ sub(esp, Immediate(kDoubleSize)); // Nolint.
690 __ sub(esp, Immediate(sizeof(uint64_t))); // Nolint. 726 }
691 // Do conversion, which cannot fail because we checked the exponent. 727 // Do conversion, which cannot fail because we checked the exponent.
692 __ fisttp_d(Operand(esp, 0)); 728 __ fisttp_d(Operand(esp, 0));
693 __ mov(ecx, Operand(esp, 0)); // Load low word of answer into ecx. 729 __ mov(result_reg, Operand(esp, 0)); // Load low word of answer as result
694 __ add(esp, Immediate(sizeof(uint64_t))); // Nolint. 730 __ add(esp, Immediate(kDoubleSize));
731 __ jmp(&done_no_stash);
695 } else { 732 } else {
696 // Check whether the exponent matches a 32 bit signed int that cannot be 733 // Result must be extracted from shifted 32-bit mantissa
697 // represented by a Smi. A non-smi 32 bit integer is 1.xxx * 2^30 so the 734 __ sub(ecx, Immediate(delta));
698 // exponent is 30 (biased). This is the exponent that we are fastest at and 735 __ neg(ecx);
699 // also the highest exponent we can handle here. 736 if (stash_exponent_copy) {
700 const uint32_t non_smi_exponent = 30; 737 __ mov(result_reg, MemOperand(esp, 0));
701 __ cmp(scratch2, Immediate(non_smi_exponent)); 738 } else {
702 // If we have a match of the int32-but-not-Smi exponent then skip some 739 __ mov(result_reg, exponent_operand);
703 // logic. 740 }
704 __ j(equal, &right_exponent, Label::kNear); 741 __ and_(result_reg,
705 // If the exponent is higher than that then go to slow case. This catches 742 Immediate(static_cast<uint32_t>(Double::kSignificandMask >> 32)));
706 // numbers that don't fit in a signed int32, infinities and NaNs. 743 __ add(result_reg,
707 __ j(less, &normal_exponent, Label::kNear); 744 Immediate(static_cast<uint32_t>(Double::kHiddenBit >> 32)));
745 __ shrd(result_reg, scratch1);
746 __ shr_cl(result_reg);
747 __ test(ecx, Immediate(32));
748 if (CpuFeatures::IsSupported(CMOV)) {
749 CpuFeatureScope use_cmov(masm, CMOV);
750 __ cmov(not_equal, scratch1, result_reg);
751 } else {
752 Label skip_mov;
753 __ j(equal, &skip_mov, Label::kNear);
754 __ mov(scratch1, result_reg);
755 __ bind(&skip_mov);
756 }
757 }
708 758
709 { 759 // If the double was negative, negate the integer result.
710 // Handle a big exponent. The only reason we have this code is that the 760 __ bind(&check_negative);
711 // >>> operator has a tendency to generate numbers with an exponent of 31. 761 __ mov(result_reg, scratch1);
712 const uint32_t big_non_smi_exponent = 31; 762 __ neg(result_reg);
713 __ cmp(scratch2, Immediate(big_non_smi_exponent)); 763 if (stash_exponent_copy) {
714 __ j(not_equal, conversion_failure); 764 __ cmp(MemOperand(esp, 0), Immediate(0));
715 // We have the big exponent, typically from >>>. This means the number is 765 } else {
716 // in the range 2^31 to 2^32 - 1. Get the top bits of the mantissa. 766 __ cmp(exponent_operand, Immediate(0));
717 __ mov(scratch2, scratch); 767 }
718 __ and_(scratch2, HeapNumber::kMantissaMask); 768 if (CpuFeatures::IsSupported(CMOV)) {
719 // Put back the implicit 1. 769 CpuFeatureScope use_cmov(masm, CMOV);
720 __ or_(scratch2, 1 << HeapNumber::kExponentShift); 770 __ cmov(greater, result_reg, scratch1);
721 // Shift up the mantissa bits to take up the space the exponent used to 771 } else {
722 // take. We just orred in the implicit bit so that took care of one and 772 Label skip_mov;
723 // we want to use the full unsigned range so we subtract 1 bit from the 773 __ j(less_equal, &skip_mov, Label::kNear);
724 // shift distance. 774 __ mov(result_reg, scratch1);
725 const int big_shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 1; 775 __ bind(&skip_mov);
726 __ shl(scratch2, big_shift_distance); 776 }
727 // Get the second half of the double.
728 __ mov(ecx, FieldOperand(source, HeapNumber::kMantissaOffset));
729 // Shift down 21 bits to get the most significant 11 bits or the low
730 // mantissa word.
731 __ shr(ecx, 32 - big_shift_distance);
732 __ or_(ecx, scratch2);
733 // We have the answer in ecx, but we may need to negate it.
734 __ test(scratch, scratch);
735 __ j(positive, &done, Label::kNear);
736 __ neg(ecx);
737 __ jmp(&done, Label::kNear);
738 }
739 777
740 __ bind(&normal_exponent); 778 // Restore registers
741 // Exponent word in scratch, exponent in scratch2. Zero in ecx. 779 __ bind(&done);
742 // We know that 0 <= exponent < 30. 780 if (stash_exponent_copy) {
743 __ mov(ecx, Immediate(30)); 781 __ add(esp, Immediate(kDoubleSize / 2));
744 __ sub(ecx, scratch2);
745
746 __ bind(&right_exponent);
747 // Here ecx is the shift, scratch is the exponent word.
748 // Get the top bits of the mantissa.
749 __ and_(scratch, HeapNumber::kMantissaMask);
750 // Put back the implicit 1.
751 __ or_(scratch, 1 << HeapNumber::kExponentShift);
752 // Shift up the mantissa bits to take up the space the exponent used to
753 // take. We have kExponentShift + 1 significant bits int he low end of the
754 // word. Shift them to the top bits.
755 const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2;
756 __ shl(scratch, shift_distance);
757 // Get the second half of the double. For some exponents we don't
758 // actually need this because the bits get shifted out again, but
759 // it's probably slower to test than just to do it.
760 __ mov(scratch2, FieldOperand(source, HeapNumber::kMantissaOffset));
761 // Shift down 22 bits to get the most significant 10 bits or the low
762 // mantissa word.
763 __ shr(scratch2, 32 - shift_distance);
764 __ or_(scratch2, scratch);
765 // Move down according to the exponent.
766 __ shr_cl(scratch2);
767 // Now the unsigned answer is in scratch2. We need to move it to ecx and
768 // we may need to fix the sign.
769 Label negative;
770 __ xor_(ecx, ecx);
771 __ cmp(ecx, FieldOperand(source, HeapNumber::kExponentOffset));
772 __ j(greater, &negative, Label::kNear);
773 __ mov(ecx, scratch2);
774 __ jmp(&done, Label::kNear);
775 __ bind(&negative);
776 __ sub(ecx, scratch2);
777 } 782 }
778 __ bind(&done); 783 __ bind(&done_no_stash);
784 if (!final_result_reg.is(result_reg)) {
785 ASSERT(final_result_reg.is(ecx));
786 __ mov(final_result_reg, result_reg);
787 }
788 __ pop(save_reg);
789 __ pop(scratch1);
790 __ ret(0);
779 } 791 }
780 792
781 793
782 // Uses SSE2 to convert the heap number in |source| to an integer. Jumps to 794 // Uses SSE2 to convert the heap number in |source| to an integer. Jumps to
783 // |conversion_failure| if the heap number did not contain an int32 value. 795 // |conversion_failure| if the heap number did not contain an int32 value.
784 // Result is in ecx. Trashes ebx, xmm0, and xmm1. 796 // Result is in ecx. Trashes ebx, xmm0, and xmm1.
785 static void ConvertHeapNumberToInt32(MacroAssembler* masm, 797 static void ConvertHeapNumberToInt32(MacroAssembler* masm,
786 Register source, 798 Register source,
787 Label* conversion_failure) { 799 Label* conversion_failure) {
788 __ movdbl(xmm0, FieldOperand(source, HeapNumber::kValueOffset)); 800 __ movdbl(xmm0, FieldOperand(source, HeapNumber::kValueOffset));
(...skipping 1600 matching lines...) Expand 10 before | Expand all | Expand 10 after
2389 __ bind(&arg1_is_object); 2401 __ bind(&arg1_is_object);
2390 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 2402 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
2391 __ cmp(ebx, factory->heap_number_map()); 2403 __ cmp(ebx, factory->heap_number_map());
2392 __ j(not_equal, &check_undefined_arg1); 2404 __ j(not_equal, &check_undefined_arg1);
2393 2405
2394 // Get the untagged integer version of the edx heap number in ecx. 2406 // Get the untagged integer version of the edx heap number in ecx.
2395 if (left_type == BinaryOpIC::INT32 && CpuFeatures::IsSupported(SSE2)) { 2407 if (left_type == BinaryOpIC::INT32 && CpuFeatures::IsSupported(SSE2)) {
2396 CpuFeatureScope use_sse2(masm, SSE2); 2408 CpuFeatureScope use_sse2(masm, SSE2);
2397 ConvertHeapNumberToInt32(masm, edx, conversion_failure); 2409 ConvertHeapNumberToInt32(masm, edx, conversion_failure);
2398 } else { 2410 } else {
2399 IntegerConvert(masm, edx, use_sse3, conversion_failure); 2411 DoubleToIStub stub(edx, ecx, HeapNumber::kValueOffset - kHeapObjectTag,
2412 true);
2413 __ call(stub.GetCode(masm->isolate()), RelocInfo::CODE_TARGET);
2400 } 2414 }
2401 __ mov(edx, ecx); 2415 __ mov(edx, ecx);
2402 2416
2403 // Here edx has the untagged integer, eax has a Smi or a heap number. 2417 // Here edx has the untagged integer, eax has a Smi or a heap number.
2404 __ bind(&load_arg2); 2418 __ bind(&load_arg2);
2405 2419
2406 // Test if arg2 is a Smi. 2420 // Test if arg2 is a Smi.
2407 if (right_type == BinaryOpIC::SMI) { 2421 if (right_type == BinaryOpIC::SMI) {
2408 __ JumpIfNotSmi(eax, conversion_failure); 2422 __ JumpIfNotSmi(eax, conversion_failure);
2409 } else { 2423 } else {
(...skipping 14 matching lines...) Expand all
2424 __ bind(&arg2_is_object); 2438 __ bind(&arg2_is_object);
2425 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 2439 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
2426 __ cmp(ebx, factory->heap_number_map()); 2440 __ cmp(ebx, factory->heap_number_map());
2427 __ j(not_equal, &check_undefined_arg2); 2441 __ j(not_equal, &check_undefined_arg2);
2428 // Get the untagged integer version of the eax heap number in ecx. 2442 // Get the untagged integer version of the eax heap number in ecx.
2429 2443
2430 if (right_type == BinaryOpIC::INT32 && CpuFeatures::IsSupported(SSE2)) { 2444 if (right_type == BinaryOpIC::INT32 && CpuFeatures::IsSupported(SSE2)) {
2431 CpuFeatureScope use_sse2(masm, SSE2); 2445 CpuFeatureScope use_sse2(masm, SSE2);
2432 ConvertHeapNumberToInt32(masm, eax, conversion_failure); 2446 ConvertHeapNumberToInt32(masm, eax, conversion_failure);
2433 } else { 2447 } else {
2434 IntegerConvert(masm, eax, use_sse3, conversion_failure); 2448 DoubleToIStub stub(eax, ecx, HeapNumber::kValueOffset - kHeapObjectTag,
2449 true);
2450 __ call(stub.GetCode(masm->isolate()), RelocInfo::CODE_TARGET);
2435 } 2451 }
2436 2452
2437 __ bind(&done); 2453 __ bind(&done);
2438 __ mov(eax, edx); 2454 __ mov(eax, edx);
2439 } 2455 }
2440 2456
2441 2457
2442 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, 2458 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm,
2443 Register number) { 2459 Register number) {
2444 Label load_smi, done; 2460 Label load_smi, done;
(...skipping 5309 matching lines...) Expand 10 before | Expand all | Expand 10 after
7754 __ bind(&fast_elements_case); 7770 __ bind(&fast_elements_case);
7755 GenerateCase(masm, FAST_ELEMENTS); 7771 GenerateCase(masm, FAST_ELEMENTS);
7756 } 7772 }
7757 7773
7758 7774
7759 #undef __ 7775 #undef __
7760 7776
7761 } } // namespace v8::internal 7777 } } // namespace v8::internal
7762 7778
7763 #endif // V8_TARGET_ARCH_IA32 7779 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/assembler-ia32.cc ('k') | src/ia32/deoptimizer-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698