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