| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 615 __ TailCallExternalReference(ref, 2, 1); | 615 __ TailCallExternalReference(ref, 2, 1); |
| 616 | 616 |
| 617 __ bind(&slow); | 617 __ bind(&slow); |
| 618 GenerateMiss(masm); | 618 GenerateMiss(masm); |
| 619 } | 619 } |
| 620 | 620 |
| 621 | 621 |
| 622 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { | 622 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { |
| 623 // ----------- S t a t e ------------- | 623 // ----------- S t a t e ------------- |
| 624 // -- eax : value | 624 // -- eax : value |
| 625 // -- ecx : key |
| 626 // -- edx : receiver |
| 625 // -- esp[0] : return address | 627 // -- esp[0] : return address |
| 626 // -- esp[4] : key | |
| 627 // -- esp[8] : receiver | |
| 628 // ----------------------------------- | 628 // ----------------------------------- |
| 629 Label slow, fast, array, extra, check_pixel_array; | 629 Label slow, fast, array, extra, check_pixel_array; |
| 630 | 630 |
| 631 // Get the receiver from the stack. | |
| 632 __ mov(edx, Operand(esp, 2 * kPointerSize)); // 2 ~ return address, key | |
| 633 // Check that the object isn't a smi. | 631 // Check that the object isn't a smi. |
| 634 __ test(edx, Immediate(kSmiTagMask)); | 632 __ test(edx, Immediate(kSmiTagMask)); |
| 635 __ j(zero, &slow, not_taken); | 633 __ j(zero, &slow, not_taken); |
| 636 // Get the map from the receiver. | 634 // Get the map from the receiver. |
| 637 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 635 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); |
| 638 // Check that the receiver does not require access checks. We need | 636 // Check that the receiver does not require access checks. We need |
| 639 // to do this because this generic stub does not perform map checks. | 637 // to do this because this generic stub does not perform map checks. |
| 640 __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset)); | 638 __ movzx_b(ebx, FieldOperand(edi, Map::kBitFieldOffset)); |
| 641 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); | 639 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); |
| 642 __ j(not_zero, &slow, not_taken); | 640 __ j(not_zero, &slow, not_taken); |
| 643 // Get the key from the stack. | |
| 644 __ mov(ebx, Operand(esp, 1 * kPointerSize)); // 1 ~ return address | |
| 645 // Check that the key is a smi. | 641 // Check that the key is a smi. |
| 646 __ test(ebx, Immediate(kSmiTagMask)); | 642 __ test(ecx, Immediate(kSmiTagMask)); |
| 647 __ j(not_zero, &slow, not_taken); | 643 __ j(not_zero, &slow, not_taken); |
| 648 // Get the instance type from the map of the receiver. | 644 __ CmpInstanceType(edi, JS_ARRAY_TYPE); |
| 649 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); | |
| 650 // Check if the object is a JS array or not. | |
| 651 __ cmp(ecx, JS_ARRAY_TYPE); | |
| 652 __ j(equal, &array); | 645 __ j(equal, &array); |
| 653 // Check that the object is some kind of JS object. | 646 // Check that the object is some kind of JS object. |
| 654 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); | 647 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); |
| 655 __ j(less, &slow, not_taken); | 648 __ j(below, &slow, not_taken); |
| 656 | 649 |
| 657 // Object case: Check key against length in the elements array. | 650 // Object case: Check key against length in the elements array. |
| 658 // eax: value | 651 // eax: value |
| 659 // edx: JSObject | 652 // edx: JSObject |
| 660 // ebx: index (as a smi) | 653 // ecx: key (a smi) |
| 661 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 654 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
| 662 // Check that the object is in fast mode (not dictionary). | 655 // Check that the object is in fast mode (not dictionary). |
| 663 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 656 __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); |
| 664 Immediate(Factory::fixed_array_map())); | 657 __ mov(ebx, Operand(ecx)); |
| 665 __ j(not_equal, &check_pixel_array, not_taken); | 658 __ SmiUntag(ebx); |
| 666 // Untag the key (for checking against untagged length in the fixed array). | 659 __ cmp(ebx, FieldOperand(edi, Array::kLengthOffset)); |
| 667 __ mov(edx, Operand(ebx)); | |
| 668 __ sar(edx, kSmiTagSize); // untag the index and use it for the comparison | |
| 669 __ cmp(edx, FieldOperand(ecx, Array::kLengthOffset)); | |
| 670 // eax: value | |
| 671 // ecx: FixedArray | |
| 672 // ebx: index (as a smi) | |
| 673 __ j(below, &fast, taken); | 660 __ j(below, &fast, taken); |
| 674 | 661 |
| 675 // Slow case: call runtime. | 662 // Slow case: call runtime. |
| 676 __ bind(&slow); | 663 __ bind(&slow); |
| 677 GenerateRuntimeSetProperty(masm); | 664 GenerateRuntimeSetProperty(masm); |
| 678 | 665 |
| 679 // Check whether the elements is a pixel array. | 666 // Check whether the elements is a pixel array. |
| 667 __ bind(&check_pixel_array); |
| 680 // eax: value | 668 // eax: value |
| 681 // ecx: elements array | 669 // ecx: key |
| 682 // ebx: index (as a smi) | 670 // edx: receiver |
| 683 __ bind(&check_pixel_array); | 671 // edi: elements array |
| 684 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 672 __ CheckMap(edi, Factory::pixel_array_map(), &slow, true); |
| 685 Immediate(Factory::pixel_array_map())); | |
| 686 __ j(not_equal, &slow); | |
| 687 // Check that the value is a smi. If a conversion is needed call into the | 673 // Check that the value is a smi. If a conversion is needed call into the |
| 688 // runtime to convert and clamp. | 674 // runtime to convert and clamp. |
| 689 __ test(eax, Immediate(kSmiTagMask)); | 675 __ test(eax, Immediate(kSmiTagMask)); |
| 690 __ j(not_zero, &slow); | 676 __ j(not_zero, &slow); |
| 691 __ sar(ebx, kSmiTagSize); // Untag the index. | 677 __ mov(ebx, ecx); |
| 692 __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset)); | 678 __ SmiUntag(ebx); |
| 679 __ cmp(ebx, FieldOperand(edi, PixelArray::kLengthOffset)); |
| 693 __ j(above_equal, &slow); | 680 __ j(above_equal, &slow); |
| 694 __ mov(edx, eax); // Save the value. | 681 __ mov(ecx, eax); // Save the value. Key is not longer needed. |
| 695 __ sar(eax, kSmiTagSize); // Untag the value. | 682 __ SmiUntag(ecx); |
| 696 { // Clamp the value to [0..255]. | 683 { // Clamp the value to [0..255]. |
| 697 Label done; | 684 Label done; |
| 698 __ test(eax, Immediate(0xFFFFFF00)); | 685 __ test(ecx, Immediate(0xFFFFFF00)); |
| 699 __ j(zero, &done); | 686 __ j(zero, &done); |
| 700 __ setcc(negative, eax); // 1 if negative, 0 if positive. | 687 __ setcc(negative, ecx); // 1 if negative, 0 if positive. |
| 701 __ dec_b(eax); // 0 if negative, 255 if positive. | 688 __ dec_b(ecx); // 0 if negative, 255 if positive. |
| 702 __ bind(&done); | 689 __ bind(&done); |
| 703 } | 690 } |
| 704 __ mov(ecx, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); | 691 __ mov(edi, FieldOperand(edi, PixelArray::kExternalPointerOffset)); |
| 705 __ mov_b(Operand(ecx, ebx, times_1, 0), eax); | 692 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
| 706 __ mov(eax, edx); // Return the original value. | 693 __ ret(0); // Return value in eax. |
| 707 __ ret(0); | |
| 708 | 694 |
| 709 // Extra capacity case: Check if there is extra capacity to | 695 // Extra capacity case: Check if there is extra capacity to |
| 710 // perform the store and update the length. Used for adding one | 696 // perform the store and update the length. Used for adding one |
| 711 // element to the array by writing to array[array.length]. | 697 // element to the array by writing to array[array.length]. |
| 712 __ bind(&extra); | 698 __ bind(&extra); |
| 713 // eax: value | 699 // eax: value |
| 714 // edx: JSArray | 700 // edx: receiver, a JSArray |
| 715 // ecx: FixedArray | 701 // ecx: key, a smi. |
| 716 // ebx: index (as a smi) | 702 // edi: receiver->elements, a FixedArray |
| 717 // flags: compare (ebx, edx.length()) | 703 // flags: compare (ecx, edx.length()) |
| 718 __ j(not_equal, &slow, not_taken); // do not leave holes in the array | 704 __ j(not_equal, &slow, not_taken); // do not leave holes in the array |
| 719 __ sar(ebx, kSmiTagSize); // untag | 705 __ mov(ebx, ecx); |
| 720 __ cmp(ebx, FieldOperand(ecx, Array::kLengthOffset)); | 706 __ SmiUntag(ebx); // untag |
| 707 __ cmp(ebx, FieldOperand(edi, Array::kLengthOffset)); |
| 721 __ j(above_equal, &slow, not_taken); | 708 __ j(above_equal, &slow, not_taken); |
| 722 // Restore tag and increment. | 709 // Add 1 to receiver->length, and go to fast array write. |
| 723 __ lea(ebx, Operand(ebx, times_2, 1 << kSmiTagSize)); | 710 __ add(FieldOperand(edx, JSArray::kLengthOffset), |
| 724 __ mov(FieldOperand(edx, JSArray::kLengthOffset), ebx); | 711 Immediate(1 << kSmiTagSize)); |
| 725 __ sub(Operand(ebx), Immediate(1 << kSmiTagSize)); // decrement ebx again | |
| 726 __ jmp(&fast); | 712 __ jmp(&fast); |
| 727 | 713 |
| 728 // Array case: Get the length and the elements array from the JS | 714 // Array case: Get the length and the elements array from the JS |
| 729 // array. Check that the array is in fast mode; if it is the | 715 // array. Check that the array is in fast mode; if it is the |
| 730 // length is always a smi. | 716 // length is always a smi. |
| 731 __ bind(&array); | 717 __ bind(&array); |
| 732 // eax: value | 718 // eax: value |
| 733 // edx: JSArray | 719 // edx: receiver, a JSArray |
| 734 // ebx: index (as a smi) | 720 // ecx: key, a smi. |
| 735 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 721 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
| 736 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 722 __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); |
| 737 Immediate(Factory::fixed_array_map())); | |
| 738 __ j(not_equal, &check_pixel_array); | |
| 739 | 723 |
| 740 // Check the key against the length in the array, compute the | 724 // Check the key against the length in the array, compute the |
| 741 // address to store into and fall through to fast case. | 725 // address to store into and fall through to fast case. |
| 742 __ cmp(ebx, FieldOperand(edx, JSArray::kLengthOffset)); | 726 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. |
| 743 __ j(above_equal, &extra, not_taken); | 727 __ j(above_equal, &extra, not_taken); |
| 744 | 728 |
| 745 // Fast case: Do the store. | 729 // Fast case: Do the store. |
| 746 __ bind(&fast); | 730 __ bind(&fast); |
| 747 // eax: value | 731 // eax: value |
| 748 // ecx: FixedArray | 732 // ecx: key (a smi) |
| 749 // ebx: index (as a smi) | 733 // edx: receiver |
| 750 __ mov(Operand(ecx, ebx, times_2, FixedArray::kHeaderSize - kHeapObjectTag), | 734 // edi: FixedArray receiver->elements |
| 751 eax); | 735 __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax); |
| 752 // Update write barrier for the elements array address. | 736 // Update write barrier for the elements array address. |
| 753 __ mov(edx, Operand(eax)); | 737 __ mov(edx, Operand(eax)); |
| 754 __ RecordWrite(ecx, 0, edx, ebx); | 738 __ RecordWrite(edi, 0, edx, ecx); |
| 755 __ ret(0); | 739 __ ret(0); |
| 756 } | 740 } |
| 757 | 741 |
| 758 | 742 |
| 759 void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm, | 743 void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm, |
| 760 ExternalArrayType array_type) { | 744 ExternalArrayType array_type) { |
| 761 // ----------- S t a t e ------------- | 745 // ----------- S t a t e ------------- |
| 762 // -- eax : value | 746 // -- eax : value |
| 747 // -- ecx : key |
| 748 // -- edx : receiver |
| 763 // -- esp[0] : return address | 749 // -- esp[0] : return address |
| 764 // -- esp[4] : key | |
| 765 // -- esp[8] : receiver | |
| 766 // ----------------------------------- | 750 // ----------------------------------- |
| 767 Label slow, check_heap_number; | 751 Label slow, check_heap_number; |
| 768 | 752 |
| 769 // Get the receiver from the stack. | |
| 770 __ mov(edx, Operand(esp, 2 * kPointerSize)); | |
| 771 // Check that the object isn't a smi. | 753 // Check that the object isn't a smi. |
| 772 __ test(edx, Immediate(kSmiTagMask)); | 754 __ test(edx, Immediate(kSmiTagMask)); |
| 773 __ j(zero, &slow); | 755 __ j(zero, &slow); |
| 774 // Get the map from the receiver. | 756 // Get the map from the receiver. |
| 775 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 757 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); |
| 776 // Check that the receiver does not require access checks. We need | 758 // Check that the receiver does not require access checks. We need |
| 777 // to do this because this generic stub does not perform map checks. | 759 // to do this because this generic stub does not perform map checks. |
| 778 __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset)); | 760 __ movzx_b(ebx, FieldOperand(edi, Map::kBitFieldOffset)); |
| 779 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); | 761 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); |
| 780 __ j(not_zero, &slow); | 762 __ j(not_zero, &slow); |
| 781 // Get the key from the stack. | |
| 782 __ mov(ebx, Operand(esp, 1 * kPointerSize)); // 1 ~ return address | |
| 783 // Check that the key is a smi. | 763 // Check that the key is a smi. |
| 784 __ test(ebx, Immediate(kSmiTagMask)); | 764 __ test(ecx, Immediate(kSmiTagMask)); |
| 785 __ j(not_zero, &slow); | 765 __ j(not_zero, &slow); |
| 786 // Get the instance type from the map of the receiver. | 766 // Get the instance type from the map of the receiver. |
| 787 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); | 767 __ CmpInstanceType(edi, JS_OBJECT_TYPE); |
| 788 // Check that the object is a JS object. | |
| 789 __ cmp(ecx, JS_OBJECT_TYPE); | |
| 790 __ j(not_equal, &slow); | 768 __ j(not_equal, &slow); |
| 791 | 769 |
| 792 // Check that the elements array is the appropriate type of | 770 // Check that the elements array is the appropriate type of |
| 793 // ExternalArray. | 771 // ExternalArray. |
| 794 // eax: value | 772 // eax: value |
| 795 // edx: JSObject | 773 // edx: receiver, a JSObject |
| 796 // ebx: index (as a smi) | 774 // ecx: key, a smi |
| 797 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 775 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
| 798 Handle<Map> map(Heap::MapForExternalArrayType(array_type)); | 776 __ CheckMap(edi, Handle<Map>(Heap::MapForExternalArrayType(array_type)), |
| 799 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 777 &slow, true); |
| 800 Immediate(map)); | |
| 801 __ j(not_equal, &slow); | |
| 802 | 778 |
| 803 // Check that the index is in range. | 779 // Check that the index is in range. |
| 804 __ sar(ebx, kSmiTagSize); // Untag the index. | 780 __ mov(ebx, ecx); |
| 805 __ cmp(ebx, FieldOperand(ecx, ExternalArray::kLengthOffset)); | 781 __ SmiUntag(ebx); |
| 782 __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset)); |
| 806 // Unsigned comparison catches both negative and too-large values. | 783 // Unsigned comparison catches both negative and too-large values. |
| 807 __ j(above_equal, &slow); | 784 __ j(above_equal, &slow); |
| 808 | 785 |
| 809 // Handle both smis and HeapNumbers in the fast path. Go to the | 786 // Handle both smis and HeapNumbers in the fast path. Go to the |
| 810 // runtime for all other kinds of values. | 787 // runtime for all other kinds of values. |
| 811 // eax: value | 788 // eax: value |
| 812 // ecx: elements array | 789 // edx: receiver |
| 790 // ecx: key |
| 791 // edi: elements array |
| 813 // ebx: untagged index | 792 // ebx: untagged index |
| 814 __ test(eax, Immediate(kSmiTagMask)); | 793 __ test(eax, Immediate(kSmiTagMask)); |
| 815 __ j(not_equal, &check_heap_number); | 794 __ j(not_equal, &check_heap_number); |
| 816 // smi case | 795 // smi case |
| 817 __ mov(edx, eax); // Save the value. | 796 __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed. |
| 818 __ sar(eax, kSmiTagSize); // Untag the value. | 797 __ SmiUntag(ecx); |
| 819 __ mov(ecx, FieldOperand(ecx, ExternalArray::kExternalPointerOffset)); | 798 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); |
| 820 // ecx: base pointer of external storage | 799 // ecx: base pointer of external storage |
| 821 switch (array_type) { | 800 switch (array_type) { |
| 822 case kExternalByteArray: | 801 case kExternalByteArray: |
| 823 case kExternalUnsignedByteArray: | 802 case kExternalUnsignedByteArray: |
| 824 __ mov_b(Operand(ecx, ebx, times_1, 0), eax); | 803 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
| 825 break; | 804 break; |
| 826 case kExternalShortArray: | 805 case kExternalShortArray: |
| 827 case kExternalUnsignedShortArray: | 806 case kExternalUnsignedShortArray: |
| 828 __ mov_w(Operand(ecx, ebx, times_2, 0), eax); | 807 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); |
| 829 break; | 808 break; |
| 830 case kExternalIntArray: | 809 case kExternalIntArray: |
| 831 case kExternalUnsignedIntArray: | 810 case kExternalUnsignedIntArray: |
| 832 __ mov(Operand(ecx, ebx, times_4, 0), eax); | 811 __ mov(Operand(edi, ebx, times_4, 0), ecx); |
| 833 break; | 812 break; |
| 834 case kExternalFloatArray: | 813 case kExternalFloatArray: |
| 835 // Need to perform int-to-float conversion. | 814 // Need to perform int-to-float conversion. |
| 836 __ push(eax); | 815 __ push(ecx); |
| 837 __ fild_s(Operand(esp, 0)); | 816 __ fild_s(Operand(esp, 0)); |
| 838 __ pop(eax); | 817 __ pop(ecx); |
| 839 __ fstp_s(Operand(ecx, ebx, times_4, 0)); | 818 __ fstp_s(Operand(edi, ebx, times_4, 0)); |
| 840 break; | 819 break; |
| 841 default: | 820 default: |
| 842 UNREACHABLE(); | 821 UNREACHABLE(); |
| 843 break; | 822 break; |
| 844 } | 823 } |
| 845 __ mov(eax, edx); // Return the original value. | 824 __ ret(0); // Return the original value. |
| 846 __ ret(0); | |
| 847 | 825 |
| 848 __ bind(&check_heap_number); | 826 __ bind(&check_heap_number); |
| 827 // eax: value |
| 828 // edx: receiver |
| 829 // ecx: key |
| 830 // edi: elements array |
| 831 // ebx: untagged index |
| 849 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 832 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
| 850 Immediate(Factory::heap_number_map())); | 833 Immediate(Factory::heap_number_map())); |
| 851 __ j(not_equal, &slow); | 834 __ j(not_equal, &slow); |
| 852 | 835 |
| 853 // The WebGL specification leaves the behavior of storing NaN and | 836 // The WebGL specification leaves the behavior of storing NaN and |
| 854 // +/-Infinity into integer arrays basically undefined. For more | 837 // +/-Infinity into integer arrays basically undefined. For more |
| 855 // reproducible behavior, convert these to zero. | 838 // reproducible behavior, convert these to zero. |
| 856 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 839 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 857 __ mov(edx, eax); // Save the value. | 840 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); |
| 858 __ mov(ecx, FieldOperand(ecx, ExternalArray::kExternalPointerOffset)); | |
| 859 // ebx: untagged index | 841 // ebx: untagged index |
| 860 // ecx: base pointer of external storage | 842 // edi: base pointer of external storage |
| 861 // top of FPU stack: value | 843 // top of FPU stack: value |
| 862 if (array_type == kExternalFloatArray) { | 844 if (array_type == kExternalFloatArray) { |
| 863 __ fstp_s(Operand(ecx, ebx, times_4, 0)); | 845 __ fstp_s(Operand(edi, ebx, times_4, 0)); |
| 864 __ mov(eax, edx); // Return the original value. | |
| 865 __ ret(0); | 846 __ ret(0); |
| 866 } else { | 847 } else { |
| 867 // Need to perform float-to-int conversion. | 848 // Need to perform float-to-int conversion. |
| 868 // Test the top of the FP stack for NaN. | 849 // Test the top of the FP stack for NaN. |
| 869 Label is_nan; | 850 Label is_nan; |
| 870 __ fucomi(0); | 851 __ fucomi(0); |
| 871 __ j(parity_even, &is_nan); | 852 __ j(parity_even, &is_nan); |
| 872 | 853 |
| 873 if (array_type != kExternalUnsignedIntArray) { | 854 if (array_type != kExternalUnsignedIntArray) { |
| 874 __ push(eax); // Make room on stack | 855 __ push(ecx); // Make room on stack |
| 875 __ fistp_s(Operand(esp, 0)); | 856 __ fistp_s(Operand(esp, 0)); |
| 876 __ pop(eax); | 857 __ pop(ecx); |
| 877 } else { | 858 } else { |
| 878 // fistp stores values as signed integers. | 859 // fistp stores values as signed integers. |
| 879 // To represent the entire range, we need to store as a 64-bit | 860 // To represent the entire range, we need to store as a 64-bit |
| 880 // int and discard the high 32 bits. | 861 // int and discard the high 32 bits. |
| 881 __ push(eax); // Make room on stack | 862 __ sub(Operand(esp), Immediate(2 * kPointerSize)); |
| 882 __ push(eax); // Make room on stack | |
| 883 __ fistp_d(Operand(esp, 0)); | 863 __ fistp_d(Operand(esp, 0)); |
| 884 __ pop(eax); | 864 __ pop(ecx); |
| 885 __ mov(Operand(esp, 0), eax); | 865 __ add(Operand(esp), Immediate(kPointerSize)); |
| 886 __ pop(eax); | |
| 887 } | 866 } |
| 888 // eax: untagged integer value | 867 // ecx: untagged integer value |
| 889 switch (array_type) { | 868 switch (array_type) { |
| 890 case kExternalByteArray: | 869 case kExternalByteArray: |
| 891 case kExternalUnsignedByteArray: | 870 case kExternalUnsignedByteArray: |
| 892 __ mov_b(Operand(ecx, ebx, times_1, 0), eax); | 871 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
| 893 break; | 872 break; |
| 894 case kExternalShortArray: | 873 case kExternalShortArray: |
| 895 case kExternalUnsignedShortArray: | 874 case kExternalUnsignedShortArray: |
| 896 __ mov_w(Operand(ecx, ebx, times_2, 0), eax); | 875 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); |
| 897 break; | 876 break; |
| 898 case kExternalIntArray: | 877 case kExternalIntArray: |
| 899 case kExternalUnsignedIntArray: { | 878 case kExternalUnsignedIntArray: { |
| 900 // We also need to explicitly check for +/-Infinity. These are | 879 // We also need to explicitly check for +/-Infinity. These are |
| 901 // converted to MIN_INT, but we need to be careful not to | 880 // converted to MIN_INT, but we need to be careful not to |
| 902 // confuse with legal uses of MIN_INT. | 881 // confuse with legal uses of MIN_INT. |
| 903 Label not_infinity; | 882 Label not_infinity; |
| 904 // This test would apparently detect both NaN and Infinity, | 883 // This test would apparently detect both NaN and Infinity, |
| 905 // but we've already checked for NaN using the FPU hardware | 884 // but we've already checked for NaN using the FPU hardware |
| 906 // above. | 885 // above. |
| 907 __ mov_w(edi, FieldOperand(edx, HeapNumber::kValueOffset + 6)); | 886 __ mov_w(edx, FieldOperand(eax, HeapNumber::kValueOffset + 6)); |
| 908 __ and_(edi, 0x7FF0); | 887 __ and_(edx, 0x7FF0); |
| 909 __ cmp(edi, 0x7FF0); | 888 __ cmp(edx, 0x7FF0); |
| 910 __ j(not_equal, ¬_infinity); | 889 __ j(not_equal, ¬_infinity); |
| 911 __ mov(eax, 0); | 890 __ mov(ecx, 0); |
| 912 __ bind(¬_infinity); | 891 __ bind(¬_infinity); |
| 913 __ mov(Operand(ecx, ebx, times_4, 0), eax); | 892 __ mov(Operand(edi, ebx, times_4, 0), ecx); |
| 914 break; | 893 break; |
| 915 } | 894 } |
| 916 default: | 895 default: |
| 917 UNREACHABLE(); | 896 UNREACHABLE(); |
| 918 break; | 897 break; |
| 919 } | 898 } |
| 920 __ mov(eax, edx); // Return the original value. | 899 __ ret(0); // Return original value. |
| 921 __ ret(0); | |
| 922 | 900 |
| 923 __ bind(&is_nan); | 901 __ bind(&is_nan); |
| 924 __ ffree(); | 902 __ ffree(); |
| 925 __ fincstp(); | 903 __ fincstp(); |
| 926 switch (array_type) { | 904 switch (array_type) { |
| 927 case kExternalByteArray: | 905 case kExternalByteArray: |
| 928 case kExternalUnsignedByteArray: | 906 case kExternalUnsignedByteArray: |
| 929 __ mov_b(Operand(ecx, ebx, times_1, 0), 0); | 907 __ mov_b(Operand(edi, ebx, times_1, 0), 0); |
| 930 break; | 908 break; |
| 931 case kExternalShortArray: | 909 case kExternalShortArray: |
| 932 case kExternalUnsignedShortArray: | 910 case kExternalUnsignedShortArray: |
| 933 __ mov(eax, 0); | 911 __ xor_(ecx, Operand(ecx)); |
| 934 __ mov_w(Operand(ecx, ebx, times_2, 0), eax); | 912 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); |
| 935 break; | 913 break; |
| 936 case kExternalIntArray: | 914 case kExternalIntArray: |
| 937 case kExternalUnsignedIntArray: | 915 case kExternalUnsignedIntArray: |
| 938 __ mov(Operand(ecx, ebx, times_4, 0), Immediate(0)); | 916 __ mov(Operand(edi, ebx, times_4, 0), Immediate(0)); |
| 939 break; | 917 break; |
| 940 default: | 918 default: |
| 941 UNREACHABLE(); | 919 UNREACHABLE(); |
| 942 break; | 920 break; |
| 943 } | 921 } |
| 944 __ mov(eax, edx); // Return the original value. | 922 __ ret(0); // Return the original value. |
| 945 __ ret(0); | |
| 946 } | 923 } |
| 947 | 924 |
| 948 // Slow case: call runtime. | 925 // Slow case: call runtime. |
| 949 __ bind(&slow); | 926 __ bind(&slow); |
| 950 GenerateRuntimeSetProperty(masm); | 927 GenerateRuntimeSetProperty(masm); |
| 951 } | 928 } |
| 952 | 929 |
| 953 | 930 |
| 954 // Defined in ic.cc. | 931 // Defined in ic.cc. |
| 955 Object* CallIC_Miss(Arguments args); | 932 Object* CallIC_Miss(Arguments args); |
| (...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1490 GenerateMiss(masm); | 1467 GenerateMiss(masm); |
| 1491 } | 1468 } |
| 1492 | 1469 |
| 1493 | 1470 |
| 1494 // Defined in ic.cc. | 1471 // Defined in ic.cc. |
| 1495 Object* KeyedStoreIC_Miss(Arguments args); | 1472 Object* KeyedStoreIC_Miss(Arguments args); |
| 1496 | 1473 |
| 1497 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { | 1474 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { |
| 1498 // ----------- S t a t e ------------- | 1475 // ----------- S t a t e ------------- |
| 1499 // -- eax : value | 1476 // -- eax : value |
| 1477 // -- ecx : key |
| 1478 // -- edx : receiver |
| 1500 // -- esp[0] : return address | 1479 // -- esp[0] : return address |
| 1501 // -- esp[4] : key | |
| 1502 // -- esp[8] : receiver | |
| 1503 // ----------------------------------- | 1480 // ----------------------------------- |
| 1504 | 1481 |
| 1505 __ pop(ecx); | 1482 __ pop(ebx); |
| 1506 __ push(Operand(esp, 1 * kPointerSize)); | 1483 __ push(edx); |
| 1507 __ push(Operand(esp, 1 * kPointerSize)); | 1484 __ push(ecx); |
| 1508 __ push(eax); | 1485 __ push(eax); |
| 1509 __ push(ecx); | 1486 __ push(ebx); |
| 1510 | 1487 |
| 1511 // Do tail-call to runtime routine. | 1488 // Do tail-call to runtime routine. |
| 1512 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); | 1489 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); |
| 1513 } | 1490 } |
| 1514 | 1491 |
| 1515 | 1492 |
| 1516 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { | 1493 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { |
| 1517 // ----------- S t a t e ------------- | 1494 // ----------- S t a t e ------------- |
| 1518 // -- eax : value | 1495 // -- eax : value |
| 1496 // -- ecx : key |
| 1497 // -- edx : receiver |
| 1519 // -- esp[0] : return address | 1498 // -- esp[0] : return address |
| 1520 // -- esp[4] : key | |
| 1521 // -- esp[8] : receiver | |
| 1522 // ----------------------------------- | 1499 // ----------------------------------- |
| 1523 | 1500 |
| 1524 __ pop(ecx); | 1501 __ pop(ebx); |
| 1525 __ push(Operand(esp, 1 * kPointerSize)); | 1502 __ push(edx); |
| 1526 __ push(Operand(esp, 1 * kPointerSize)); | 1503 __ push(ecx); |
| 1527 __ push(eax); | 1504 __ push(eax); |
| 1528 __ push(ecx); | 1505 __ push(ebx); |
| 1529 | 1506 |
| 1530 // Do tail-call to runtime routine. | 1507 // Do tail-call to runtime routine. |
| 1531 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); | 1508 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); |
| 1532 __ TailCallExternalReference(ref, 3, 1); | 1509 __ TailCallExternalReference(ref, 3, 1); |
| 1533 } | 1510 } |
| 1534 | 1511 |
| 1535 #undef __ | 1512 #undef __ |
| 1536 | 1513 |
| 1537 | 1514 |
| 1538 } } // namespace v8::internal | 1515 } } // namespace v8::internal |
| OLD | NEW |