OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_IA32 | 7 #if V8_TARGET_ARCH_IA32 |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/base/division-by-constant.h" | 10 #include "src/base/division-by-constant.h" |
(...skipping 1717 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1728 mov(FieldOperand(result, HeapObject::kMapOffset), | 1728 mov(FieldOperand(result, HeapObject::kMapOffset), |
1729 Immediate(isolate()->factory()->string_map())); | 1729 Immediate(isolate()->factory()->string_map())); |
1730 mov(scratch1, length); | 1730 mov(scratch1, length); |
1731 SmiTag(scratch1); | 1731 SmiTag(scratch1); |
1732 mov(FieldOperand(result, String::kLengthOffset), scratch1); | 1732 mov(FieldOperand(result, String::kLengthOffset), scratch1); |
1733 mov(FieldOperand(result, String::kHashFieldOffset), | 1733 mov(FieldOperand(result, String::kHashFieldOffset), |
1734 Immediate(String::kEmptyHashField)); | 1734 Immediate(String::kEmptyHashField)); |
1735 } | 1735 } |
1736 | 1736 |
1737 | 1737 |
1738 void MacroAssembler::AllocateAsciiString(Register result, | 1738 void MacroAssembler::AllocateOneByteString(Register result, Register length, |
1739 Register length, | 1739 Register scratch1, Register scratch2, |
1740 Register scratch1, | 1740 Register scratch3, |
1741 Register scratch2, | 1741 Label* gc_required) { |
1742 Register scratch3, | |
1743 Label* gc_required) { | |
1744 // Calculate the number of bytes needed for the characters in the string while | 1742 // Calculate the number of bytes needed for the characters in the string while |
1745 // observing object alignment. | 1743 // observing object alignment. |
1746 DCHECK((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); | 1744 DCHECK((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); |
1747 mov(scratch1, length); | 1745 mov(scratch1, length); |
1748 DCHECK(kCharSize == 1); | 1746 DCHECK(kCharSize == 1); |
1749 add(scratch1, Immediate(kObjectAlignmentMask)); | 1747 add(scratch1, Immediate(kObjectAlignmentMask)); |
1750 and_(scratch1, Immediate(~kObjectAlignmentMask)); | 1748 and_(scratch1, Immediate(~kObjectAlignmentMask)); |
1751 | 1749 |
1752 // Allocate ASCII string in new space. | 1750 // Allocate one-byte string in new space. |
1753 Allocate(SeqOneByteString::kHeaderSize, | 1751 Allocate(SeqOneByteString::kHeaderSize, |
1754 times_1, | 1752 times_1, |
1755 scratch1, | 1753 scratch1, |
1756 REGISTER_VALUE_IS_INT32, | 1754 REGISTER_VALUE_IS_INT32, |
1757 result, | 1755 result, |
1758 scratch2, | 1756 scratch2, |
1759 scratch3, | 1757 scratch3, |
1760 gc_required, | 1758 gc_required, |
1761 TAG_OBJECT); | 1759 TAG_OBJECT); |
1762 | 1760 |
1763 // Set the map, length and hash field. | 1761 // Set the map, length and hash field. |
1764 mov(FieldOperand(result, HeapObject::kMapOffset), | 1762 mov(FieldOperand(result, HeapObject::kMapOffset), |
1765 Immediate(isolate()->factory()->ascii_string_map())); | 1763 Immediate(isolate()->factory()->one_byte_string_map())); |
1766 mov(scratch1, length); | 1764 mov(scratch1, length); |
1767 SmiTag(scratch1); | 1765 SmiTag(scratch1); |
1768 mov(FieldOperand(result, String::kLengthOffset), scratch1); | 1766 mov(FieldOperand(result, String::kLengthOffset), scratch1); |
1769 mov(FieldOperand(result, String::kHashFieldOffset), | 1767 mov(FieldOperand(result, String::kHashFieldOffset), |
1770 Immediate(String::kEmptyHashField)); | 1768 Immediate(String::kEmptyHashField)); |
1771 } | 1769 } |
1772 | 1770 |
1773 | 1771 |
1774 void MacroAssembler::AllocateAsciiString(Register result, | 1772 void MacroAssembler::AllocateOneByteString(Register result, int length, |
1775 int length, | 1773 Register scratch1, Register scratch2, |
1776 Register scratch1, | 1774 Label* gc_required) { |
1777 Register scratch2, | |
1778 Label* gc_required) { | |
1779 DCHECK(length > 0); | 1775 DCHECK(length > 0); |
1780 | 1776 |
1781 // Allocate ASCII string in new space. | 1777 // Allocate one-byte string in new space. |
1782 Allocate(SeqOneByteString::SizeFor(length), result, scratch1, scratch2, | 1778 Allocate(SeqOneByteString::SizeFor(length), result, scratch1, scratch2, |
1783 gc_required, TAG_OBJECT); | 1779 gc_required, TAG_OBJECT); |
1784 | 1780 |
1785 // Set the map, length and hash field. | 1781 // Set the map, length and hash field. |
1786 mov(FieldOperand(result, HeapObject::kMapOffset), | 1782 mov(FieldOperand(result, HeapObject::kMapOffset), |
1787 Immediate(isolate()->factory()->ascii_string_map())); | 1783 Immediate(isolate()->factory()->one_byte_string_map())); |
1788 mov(FieldOperand(result, String::kLengthOffset), | 1784 mov(FieldOperand(result, String::kLengthOffset), |
1789 Immediate(Smi::FromInt(length))); | 1785 Immediate(Smi::FromInt(length))); |
1790 mov(FieldOperand(result, String::kHashFieldOffset), | 1786 mov(FieldOperand(result, String::kHashFieldOffset), |
1791 Immediate(String::kEmptyHashField)); | 1787 Immediate(String::kEmptyHashField)); |
1792 } | 1788 } |
1793 | 1789 |
1794 | 1790 |
1795 void MacroAssembler::AllocateTwoByteConsString(Register result, | 1791 void MacroAssembler::AllocateTwoByteConsString(Register result, |
1796 Register scratch1, | 1792 Register scratch1, |
1797 Register scratch2, | 1793 Register scratch2, |
1798 Label* gc_required) { | 1794 Label* gc_required) { |
1799 // Allocate heap number in new space. | 1795 // Allocate heap number in new space. |
1800 Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required, | 1796 Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required, |
1801 TAG_OBJECT); | 1797 TAG_OBJECT); |
1802 | 1798 |
1803 // Set the map. The other fields are left uninitialized. | 1799 // Set the map. The other fields are left uninitialized. |
1804 mov(FieldOperand(result, HeapObject::kMapOffset), | 1800 mov(FieldOperand(result, HeapObject::kMapOffset), |
1805 Immediate(isolate()->factory()->cons_string_map())); | 1801 Immediate(isolate()->factory()->cons_string_map())); |
1806 } | 1802 } |
1807 | 1803 |
1808 | 1804 |
1809 void MacroAssembler::AllocateAsciiConsString(Register result, | 1805 void MacroAssembler::AllocateOneByteConsString(Register result, |
1810 Register scratch1, | 1806 Register scratch1, |
1811 Register scratch2, | 1807 Register scratch2, |
1812 Label* gc_required) { | 1808 Label* gc_required) { |
1813 Allocate(ConsString::kSize, | 1809 Allocate(ConsString::kSize, |
1814 result, | 1810 result, |
1815 scratch1, | 1811 scratch1, |
1816 scratch2, | 1812 scratch2, |
1817 gc_required, | 1813 gc_required, |
1818 TAG_OBJECT); | 1814 TAG_OBJECT); |
1819 | 1815 |
1820 // Set the map. The other fields are left uninitialized. | 1816 // Set the map. The other fields are left uninitialized. |
1821 mov(FieldOperand(result, HeapObject::kMapOffset), | 1817 mov(FieldOperand(result, HeapObject::kMapOffset), |
1822 Immediate(isolate()->factory()->cons_ascii_string_map())); | 1818 Immediate(isolate()->factory()->cons_one_byte_string_map())); |
1823 } | 1819 } |
1824 | 1820 |
1825 | 1821 |
1826 void MacroAssembler::AllocateTwoByteSlicedString(Register result, | 1822 void MacroAssembler::AllocateTwoByteSlicedString(Register result, |
1827 Register scratch1, | 1823 Register scratch1, |
1828 Register scratch2, | 1824 Register scratch2, |
1829 Label* gc_required) { | 1825 Label* gc_required) { |
1830 // Allocate heap number in new space. | 1826 // Allocate heap number in new space. |
1831 Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required, | 1827 Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required, |
1832 TAG_OBJECT); | 1828 TAG_OBJECT); |
1833 | 1829 |
1834 // Set the map. The other fields are left uninitialized. | 1830 // Set the map. The other fields are left uninitialized. |
1835 mov(FieldOperand(result, HeapObject::kMapOffset), | 1831 mov(FieldOperand(result, HeapObject::kMapOffset), |
1836 Immediate(isolate()->factory()->sliced_string_map())); | 1832 Immediate(isolate()->factory()->sliced_string_map())); |
1837 } | 1833 } |
1838 | 1834 |
1839 | 1835 |
1840 void MacroAssembler::AllocateAsciiSlicedString(Register result, | 1836 void MacroAssembler::AllocateOneByteSlicedString(Register result, |
1841 Register scratch1, | 1837 Register scratch1, |
1842 Register scratch2, | 1838 Register scratch2, |
1843 Label* gc_required) { | 1839 Label* gc_required) { |
1844 // Allocate heap number in new space. | 1840 // Allocate heap number in new space. |
1845 Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required, | 1841 Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required, |
1846 TAG_OBJECT); | 1842 TAG_OBJECT); |
1847 | 1843 |
1848 // Set the map. The other fields are left uninitialized. | 1844 // Set the map. The other fields are left uninitialized. |
1849 mov(FieldOperand(result, HeapObject::kMapOffset), | 1845 mov(FieldOperand(result, HeapObject::kMapOffset), |
1850 Immediate(isolate()->factory()->sliced_ascii_string_map())); | 1846 Immediate(isolate()->factory()->sliced_one_byte_string_map())); |
1851 } | 1847 } |
1852 | 1848 |
1853 | 1849 |
1854 // Copy memory, byte-by-byte, from source to destination. Not optimized for | 1850 // Copy memory, byte-by-byte, from source to destination. Not optimized for |
1855 // long or aligned copies. The contents of scratch and length are destroyed. | 1851 // long or aligned copies. The contents of scratch and length are destroyed. |
1856 // Source and destination are incremented by length. | 1852 // Source and destination are incremented by length. |
1857 // Many variants of movsb, loop unrolling, word moves, and indexed operands | 1853 // Many variants of movsb, loop unrolling, word moves, and indexed operands |
1858 // have been tried here already, and this is fastest. | 1854 // have been tried here already, and this is fastest. |
1859 // A simpler loop is faster on small copies, but 30% slower on large ones. | 1855 // A simpler loop is faster on small copies, but 30% slower on large ones. |
1860 // The cld() instruction must have been emitted, to set the direction flag(), | 1856 // The cld() instruction must have been emitted, to set the direction flag(), |
(...skipping 1043 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2904 bind(&load_result_from_cache); | 2900 bind(&load_result_from_cache); |
2905 mov(result, | 2901 mov(result, |
2906 FieldOperand(number_string_cache, | 2902 FieldOperand(number_string_cache, |
2907 index, | 2903 index, |
2908 times_twice_pointer_size, | 2904 times_twice_pointer_size, |
2909 FixedArray::kHeaderSize + kPointerSize)); | 2905 FixedArray::kHeaderSize + kPointerSize)); |
2910 IncrementCounter(isolate()->counters()->number_to_string_native(), 1); | 2906 IncrementCounter(isolate()->counters()->number_to_string_native(), 1); |
2911 } | 2907 } |
2912 | 2908 |
2913 | 2909 |
2914 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii( | 2910 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialOneByte( |
2915 Register instance_type, | 2911 Register instance_type, Register scratch, Label* failure) { |
2916 Register scratch, | |
2917 Label* failure) { | |
2918 if (!scratch.is(instance_type)) { | 2912 if (!scratch.is(instance_type)) { |
2919 mov(scratch, instance_type); | 2913 mov(scratch, instance_type); |
2920 } | 2914 } |
2921 and_(scratch, | 2915 and_(scratch, |
2922 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask); | 2916 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask); |
2923 cmp(scratch, kStringTag | kSeqStringTag | kOneByteStringTag); | 2917 cmp(scratch, kStringTag | kSeqStringTag | kOneByteStringTag); |
2924 j(not_equal, failure); | 2918 j(not_equal, failure); |
2925 } | 2919 } |
2926 | 2920 |
2927 | 2921 |
2928 void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register object1, | 2922 void MacroAssembler::JumpIfNotBothSequentialOneByteStrings(Register object1, |
2929 Register object2, | 2923 Register object2, |
2930 Register scratch1, | 2924 Register scratch1, |
2931 Register scratch2, | 2925 Register scratch2, |
2932 Label* failure) { | 2926 Label* failure) { |
2933 // Check that both objects are not smis. | 2927 // Check that both objects are not smis. |
2934 STATIC_ASSERT(kSmiTag == 0); | 2928 STATIC_ASSERT(kSmiTag == 0); |
2935 mov(scratch1, object1); | 2929 mov(scratch1, object1); |
2936 and_(scratch1, object2); | 2930 and_(scratch1, object2); |
2937 JumpIfSmi(scratch1, failure); | 2931 JumpIfSmi(scratch1, failure); |
2938 | 2932 |
2939 // Load instance type for both strings. | 2933 // Load instance type for both strings. |
2940 mov(scratch1, FieldOperand(object1, HeapObject::kMapOffset)); | 2934 mov(scratch1, FieldOperand(object1, HeapObject::kMapOffset)); |
2941 mov(scratch2, FieldOperand(object2, HeapObject::kMapOffset)); | 2935 mov(scratch2, FieldOperand(object2, HeapObject::kMapOffset)); |
2942 movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset)); | 2936 movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset)); |
2943 movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset)); | 2937 movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset)); |
2944 | 2938 |
2945 // Check that both are flat ASCII strings. | 2939 // Check that both are flat one-byte strings. |
2946 const int kFlatAsciiStringMask = | 2940 const int kFlatOneByteStringMask = |
2947 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; | 2941 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; |
2948 const int kFlatAsciiStringTag = | 2942 const int kFlatOneByteStringTag = |
2949 kStringTag | kOneByteStringTag | kSeqStringTag; | 2943 kStringTag | kOneByteStringTag | kSeqStringTag; |
2950 // Interleave bits from both instance types and compare them in one check. | 2944 // Interleave bits from both instance types and compare them in one check. |
2951 DCHECK_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3)); | 2945 DCHECK_EQ(0, kFlatOneByteStringMask & (kFlatOneByteStringMask << 3)); |
2952 and_(scratch1, kFlatAsciiStringMask); | 2946 and_(scratch1, kFlatOneByteStringMask); |
2953 and_(scratch2, kFlatAsciiStringMask); | 2947 and_(scratch2, kFlatOneByteStringMask); |
2954 lea(scratch1, Operand(scratch1, scratch2, times_8, 0)); | 2948 lea(scratch1, Operand(scratch1, scratch2, times_8, 0)); |
2955 cmp(scratch1, kFlatAsciiStringTag | (kFlatAsciiStringTag << 3)); | 2949 cmp(scratch1, kFlatOneByteStringTag | (kFlatOneByteStringTag << 3)); |
2956 j(not_equal, failure); | 2950 j(not_equal, failure); |
2957 } | 2951 } |
2958 | 2952 |
2959 | 2953 |
2960 void MacroAssembler::JumpIfNotUniqueName(Operand operand, | 2954 void MacroAssembler::JumpIfNotUniqueName(Operand operand, |
2961 Label* not_unique_name, | 2955 Label* not_unique_name, |
2962 Label::Distance distance) { | 2956 Label::Distance distance) { |
2963 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); | 2957 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); |
2964 Label succeed; | 2958 Label succeed; |
2965 test(operand, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); | 2959 test(operand, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3284 // External strings are the only ones with the kExternalStringTag bit | 3278 // External strings are the only ones with the kExternalStringTag bit |
3285 // set. | 3279 // set. |
3286 DCHECK_EQ(0, kSeqStringTag & kExternalStringTag); | 3280 DCHECK_EQ(0, kSeqStringTag & kExternalStringTag); |
3287 DCHECK_EQ(0, kConsStringTag & kExternalStringTag); | 3281 DCHECK_EQ(0, kConsStringTag & kExternalStringTag); |
3288 test_b(instance_type, kExternalStringTag); | 3282 test_b(instance_type, kExternalStringTag); |
3289 j(zero, ¬_external, Label::kNear); | 3283 j(zero, ¬_external, Label::kNear); |
3290 mov(length, Immediate(ExternalString::kSize)); | 3284 mov(length, Immediate(ExternalString::kSize)); |
3291 jmp(&is_data_object, Label::kNear); | 3285 jmp(&is_data_object, Label::kNear); |
3292 | 3286 |
3293 bind(¬_external); | 3287 bind(¬_external); |
3294 // Sequential string, either ASCII or UC16. | 3288 // Sequential string, either Latin1 or UC16. |
3295 DCHECK(kOneByteStringTag == 0x04); | 3289 DCHECK(kOneByteStringTag == 0x04); |
3296 and_(length, Immediate(kStringEncodingMask)); | 3290 and_(length, Immediate(kStringEncodingMask)); |
3297 xor_(length, Immediate(kStringEncodingMask)); | 3291 xor_(length, Immediate(kStringEncodingMask)); |
3298 add(length, Immediate(0x04)); | 3292 add(length, Immediate(0x04)); |
3299 // Value now either 4 (if ASCII) or 8 (if UC16), i.e., char-size shifted | 3293 // Value now either 4 (if Latin1) or 8 (if UC16), i.e., char-size shifted |
3300 // by 2. If we multiply the string length as smi by this, it still | 3294 // by 2. If we multiply the string length as smi by this, it still |
3301 // won't overflow a 32-bit value. | 3295 // won't overflow a 32-bit value. |
3302 DCHECK_EQ(SeqOneByteString::kMaxSize, SeqTwoByteString::kMaxSize); | 3296 DCHECK_EQ(SeqOneByteString::kMaxSize, SeqTwoByteString::kMaxSize); |
3303 DCHECK(SeqOneByteString::kMaxSize <= | 3297 DCHECK(SeqOneByteString::kMaxSize <= |
3304 static_cast<int>(0xffffffffu >> (2 + kSmiTagSize))); | 3298 static_cast<int>(0xffffffffu >> (2 + kSmiTagSize))); |
3305 imul(length, FieldOperand(value, String::kLengthOffset)); | 3299 imul(length, FieldOperand(value, String::kLengthOffset)); |
3306 shr(length, 2 + kSmiTagSize + kSmiShiftSize); | 3300 shr(length, 2 + kSmiTagSize + kSmiShiftSize); |
3307 add(length, Immediate(SeqString::kHeaderSize + kObjectAlignmentMask)); | 3301 add(length, Immediate(SeqString::kHeaderSize + kObjectAlignmentMask)); |
3308 and_(length, Immediate(~kObjectAlignmentMask)); | 3302 and_(length, Immediate(~kObjectAlignmentMask)); |
3309 | 3303 |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3434 if (mag.shift > 0) sar(edx, mag.shift); | 3428 if (mag.shift > 0) sar(edx, mag.shift); |
3435 mov(eax, dividend); | 3429 mov(eax, dividend); |
3436 shr(eax, 31); | 3430 shr(eax, 31); |
3437 add(edx, eax); | 3431 add(edx, eax); |
3438 } | 3432 } |
3439 | 3433 |
3440 | 3434 |
3441 } } // namespace v8::internal | 3435 } } // namespace v8::internal |
3442 | 3436 |
3443 #endif // V8_TARGET_ARCH_IA32 | 3437 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |