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_X87 | 7 #if V8_TARGET_ARCH_X87 |
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 1610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1621 mov(FieldOperand(result, HeapObject::kMapOffset), | 1621 mov(FieldOperand(result, HeapObject::kMapOffset), |
1622 Immediate(isolate()->factory()->string_map())); | 1622 Immediate(isolate()->factory()->string_map())); |
1623 mov(scratch1, length); | 1623 mov(scratch1, length); |
1624 SmiTag(scratch1); | 1624 SmiTag(scratch1); |
1625 mov(FieldOperand(result, String::kLengthOffset), scratch1); | 1625 mov(FieldOperand(result, String::kLengthOffset), scratch1); |
1626 mov(FieldOperand(result, String::kHashFieldOffset), | 1626 mov(FieldOperand(result, String::kHashFieldOffset), |
1627 Immediate(String::kEmptyHashField)); | 1627 Immediate(String::kEmptyHashField)); |
1628 } | 1628 } |
1629 | 1629 |
1630 | 1630 |
1631 void MacroAssembler::AllocateAsciiString(Register result, | 1631 void MacroAssembler::AllocateOneByteString(Register result, Register length, |
1632 Register length, | 1632 Register scratch1, Register scratch2, |
1633 Register scratch1, | 1633 Register scratch3, |
1634 Register scratch2, | 1634 Label* gc_required) { |
1635 Register scratch3, | |
1636 Label* gc_required) { | |
1637 // Calculate the number of bytes needed for the characters in the string while | 1635 // Calculate the number of bytes needed for the characters in the string while |
1638 // observing object alignment. | 1636 // observing object alignment. |
1639 DCHECK((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); | 1637 DCHECK((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); |
1640 mov(scratch1, length); | 1638 mov(scratch1, length); |
1641 DCHECK(kCharSize == 1); | 1639 DCHECK(kCharSize == 1); |
1642 add(scratch1, Immediate(kObjectAlignmentMask)); | 1640 add(scratch1, Immediate(kObjectAlignmentMask)); |
1643 and_(scratch1, Immediate(~kObjectAlignmentMask)); | 1641 and_(scratch1, Immediate(~kObjectAlignmentMask)); |
1644 | 1642 |
1645 // Allocate ASCII string in new space. | 1643 // Allocate one-byte string in new space. |
1646 Allocate(SeqOneByteString::kHeaderSize, | 1644 Allocate(SeqOneByteString::kHeaderSize, |
1647 times_1, | 1645 times_1, |
1648 scratch1, | 1646 scratch1, |
1649 REGISTER_VALUE_IS_INT32, | 1647 REGISTER_VALUE_IS_INT32, |
1650 result, | 1648 result, |
1651 scratch2, | 1649 scratch2, |
1652 scratch3, | 1650 scratch3, |
1653 gc_required, | 1651 gc_required, |
1654 TAG_OBJECT); | 1652 TAG_OBJECT); |
1655 | 1653 |
1656 // Set the map, length and hash field. | 1654 // Set the map, length and hash field. |
1657 mov(FieldOperand(result, HeapObject::kMapOffset), | 1655 mov(FieldOperand(result, HeapObject::kMapOffset), |
1658 Immediate(isolate()->factory()->ascii_string_map())); | 1656 Immediate(isolate()->factory()->one_byte_string_map())); |
1659 mov(scratch1, length); | 1657 mov(scratch1, length); |
1660 SmiTag(scratch1); | 1658 SmiTag(scratch1); |
1661 mov(FieldOperand(result, String::kLengthOffset), scratch1); | 1659 mov(FieldOperand(result, String::kLengthOffset), scratch1); |
1662 mov(FieldOperand(result, String::kHashFieldOffset), | 1660 mov(FieldOperand(result, String::kHashFieldOffset), |
1663 Immediate(String::kEmptyHashField)); | 1661 Immediate(String::kEmptyHashField)); |
1664 } | 1662 } |
1665 | 1663 |
1666 | 1664 |
1667 void MacroAssembler::AllocateAsciiString(Register result, | 1665 void MacroAssembler::AllocateOneByteString(Register result, int length, |
1668 int length, | 1666 Register scratch1, Register scratch2, |
1669 Register scratch1, | 1667 Label* gc_required) { |
1670 Register scratch2, | |
1671 Label* gc_required) { | |
1672 DCHECK(length > 0); | 1668 DCHECK(length > 0); |
1673 | 1669 |
1674 // Allocate ASCII string in new space. | 1670 // Allocate one-byte string in new space. |
1675 Allocate(SeqOneByteString::SizeFor(length), result, scratch1, scratch2, | 1671 Allocate(SeqOneByteString::SizeFor(length), result, scratch1, scratch2, |
1676 gc_required, TAG_OBJECT); | 1672 gc_required, TAG_OBJECT); |
1677 | 1673 |
1678 // Set the map, length and hash field. | 1674 // Set the map, length and hash field. |
1679 mov(FieldOperand(result, HeapObject::kMapOffset), | 1675 mov(FieldOperand(result, HeapObject::kMapOffset), |
1680 Immediate(isolate()->factory()->ascii_string_map())); | 1676 Immediate(isolate()->factory()->one_byte_string_map())); |
1681 mov(FieldOperand(result, String::kLengthOffset), | 1677 mov(FieldOperand(result, String::kLengthOffset), |
1682 Immediate(Smi::FromInt(length))); | 1678 Immediate(Smi::FromInt(length))); |
1683 mov(FieldOperand(result, String::kHashFieldOffset), | 1679 mov(FieldOperand(result, String::kHashFieldOffset), |
1684 Immediate(String::kEmptyHashField)); | 1680 Immediate(String::kEmptyHashField)); |
1685 } | 1681 } |
1686 | 1682 |
1687 | 1683 |
1688 void MacroAssembler::AllocateTwoByteConsString(Register result, | 1684 void MacroAssembler::AllocateTwoByteConsString(Register result, |
1689 Register scratch1, | 1685 Register scratch1, |
1690 Register scratch2, | 1686 Register scratch2, |
1691 Label* gc_required) { | 1687 Label* gc_required) { |
1692 // Allocate heap number in new space. | 1688 // Allocate heap number in new space. |
1693 Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required, | 1689 Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required, |
1694 TAG_OBJECT); | 1690 TAG_OBJECT); |
1695 | 1691 |
1696 // Set the map. The other fields are left uninitialized. | 1692 // Set the map. The other fields are left uninitialized. |
1697 mov(FieldOperand(result, HeapObject::kMapOffset), | 1693 mov(FieldOperand(result, HeapObject::kMapOffset), |
1698 Immediate(isolate()->factory()->cons_string_map())); | 1694 Immediate(isolate()->factory()->cons_string_map())); |
1699 } | 1695 } |
1700 | 1696 |
1701 | 1697 |
1702 void MacroAssembler::AllocateAsciiConsString(Register result, | 1698 void MacroAssembler::AllocateOneByteConsString(Register result, |
1703 Register scratch1, | 1699 Register scratch1, |
1704 Register scratch2, | 1700 Register scratch2, |
1705 Label* gc_required) { | 1701 Label* gc_required) { |
1706 Allocate(ConsString::kSize, | 1702 Allocate(ConsString::kSize, |
1707 result, | 1703 result, |
1708 scratch1, | 1704 scratch1, |
1709 scratch2, | 1705 scratch2, |
1710 gc_required, | 1706 gc_required, |
1711 TAG_OBJECT); | 1707 TAG_OBJECT); |
1712 | 1708 |
1713 // Set the map. The other fields are left uninitialized. | 1709 // Set the map. The other fields are left uninitialized. |
1714 mov(FieldOperand(result, HeapObject::kMapOffset), | 1710 mov(FieldOperand(result, HeapObject::kMapOffset), |
1715 Immediate(isolate()->factory()->cons_ascii_string_map())); | 1711 Immediate(isolate()->factory()->cons_one_byte_string_map())); |
1716 } | 1712 } |
1717 | 1713 |
1718 | 1714 |
1719 void MacroAssembler::AllocateTwoByteSlicedString(Register result, | 1715 void MacroAssembler::AllocateTwoByteSlicedString(Register result, |
1720 Register scratch1, | 1716 Register scratch1, |
1721 Register scratch2, | 1717 Register scratch2, |
1722 Label* gc_required) { | 1718 Label* gc_required) { |
1723 // Allocate heap number in new space. | 1719 // Allocate heap number in new space. |
1724 Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required, | 1720 Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required, |
1725 TAG_OBJECT); | 1721 TAG_OBJECT); |
1726 | 1722 |
1727 // Set the map. The other fields are left uninitialized. | 1723 // Set the map. The other fields are left uninitialized. |
1728 mov(FieldOperand(result, HeapObject::kMapOffset), | 1724 mov(FieldOperand(result, HeapObject::kMapOffset), |
1729 Immediate(isolate()->factory()->sliced_string_map())); | 1725 Immediate(isolate()->factory()->sliced_string_map())); |
1730 } | 1726 } |
1731 | 1727 |
1732 | 1728 |
1733 void MacroAssembler::AllocateAsciiSlicedString(Register result, | 1729 void MacroAssembler::AllocateOneByteSlicedString(Register result, |
1734 Register scratch1, | 1730 Register scratch1, |
1735 Register scratch2, | 1731 Register scratch2, |
1736 Label* gc_required) { | 1732 Label* gc_required) { |
1737 // Allocate heap number in new space. | 1733 // Allocate heap number in new space. |
1738 Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required, | 1734 Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required, |
1739 TAG_OBJECT); | 1735 TAG_OBJECT); |
1740 | 1736 |
1741 // Set the map. The other fields are left uninitialized. | 1737 // Set the map. The other fields are left uninitialized. |
1742 mov(FieldOperand(result, HeapObject::kMapOffset), | 1738 mov(FieldOperand(result, HeapObject::kMapOffset), |
1743 Immediate(isolate()->factory()->sliced_ascii_string_map())); | 1739 Immediate(isolate()->factory()->sliced_one_byte_string_map())); |
1744 } | 1740 } |
1745 | 1741 |
1746 | 1742 |
1747 // Copy memory, byte-by-byte, from source to destination. Not optimized for | 1743 // Copy memory, byte-by-byte, from source to destination. Not optimized for |
1748 // long or aligned copies. The contents of scratch and length are destroyed. | 1744 // long or aligned copies. The contents of scratch and length are destroyed. |
1749 // Source and destination are incremented by length. | 1745 // Source and destination are incremented by length. |
1750 // Many variants of movsb, loop unrolling, word moves, and indexed operands | 1746 // Many variants of movsb, loop unrolling, word moves, and indexed operands |
1751 // have been tried here already, and this is fastest. | 1747 // have been tried here already, and this is fastest. |
1752 // A simpler loop is faster on small copies, but 30% slower on large ones. | 1748 // A simpler loop is faster on small copies, but 30% slower on large ones. |
1753 // The cld() instruction must have been emitted, to set the direction flag(), | 1749 // The cld() instruction must have been emitted, to set the direction flag(), |
(...skipping 1037 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2791 bind(&load_result_from_cache); | 2787 bind(&load_result_from_cache); |
2792 mov(result, | 2788 mov(result, |
2793 FieldOperand(number_string_cache, | 2789 FieldOperand(number_string_cache, |
2794 index, | 2790 index, |
2795 times_twice_pointer_size, | 2791 times_twice_pointer_size, |
2796 FixedArray::kHeaderSize + kPointerSize)); | 2792 FixedArray::kHeaderSize + kPointerSize)); |
2797 IncrementCounter(isolate()->counters()->number_to_string_native(), 1); | 2793 IncrementCounter(isolate()->counters()->number_to_string_native(), 1); |
2798 } | 2794 } |
2799 | 2795 |
2800 | 2796 |
2801 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii( | 2797 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialOneByte( |
2802 Register instance_type, | 2798 Register instance_type, Register scratch, Label* failure) { |
2803 Register scratch, | |
2804 Label* failure) { | |
2805 if (!scratch.is(instance_type)) { | 2799 if (!scratch.is(instance_type)) { |
2806 mov(scratch, instance_type); | 2800 mov(scratch, instance_type); |
2807 } | 2801 } |
2808 and_(scratch, | 2802 and_(scratch, |
2809 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask); | 2803 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask); |
2810 cmp(scratch, kStringTag | kSeqStringTag | kOneByteStringTag); | 2804 cmp(scratch, kStringTag | kSeqStringTag | kOneByteStringTag); |
2811 j(not_equal, failure); | 2805 j(not_equal, failure); |
2812 } | 2806 } |
2813 | 2807 |
2814 | 2808 |
2815 void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register object1, | 2809 void MacroAssembler::JumpIfNotBothSequentialOneByteStrings(Register object1, |
2816 Register object2, | 2810 Register object2, |
2817 Register scratch1, | 2811 Register scratch1, |
2818 Register scratch2, | 2812 Register scratch2, |
2819 Label* failure) { | 2813 Label* failure) { |
2820 // Check that both objects are not smis. | 2814 // Check that both objects are not smis. |
2821 STATIC_ASSERT(kSmiTag == 0); | 2815 STATIC_ASSERT(kSmiTag == 0); |
2822 mov(scratch1, object1); | 2816 mov(scratch1, object1); |
2823 and_(scratch1, object2); | 2817 and_(scratch1, object2); |
2824 JumpIfSmi(scratch1, failure); | 2818 JumpIfSmi(scratch1, failure); |
2825 | 2819 |
2826 // Load instance type for both strings. | 2820 // Load instance type for both strings. |
2827 mov(scratch1, FieldOperand(object1, HeapObject::kMapOffset)); | 2821 mov(scratch1, FieldOperand(object1, HeapObject::kMapOffset)); |
2828 mov(scratch2, FieldOperand(object2, HeapObject::kMapOffset)); | 2822 mov(scratch2, FieldOperand(object2, HeapObject::kMapOffset)); |
2829 movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset)); | 2823 movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset)); |
2830 movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset)); | 2824 movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset)); |
2831 | 2825 |
2832 // Check that both are flat ASCII strings. | 2826 // Check that both are flat one-byte strings. |
2833 const int kFlatAsciiStringMask = | 2827 const int kFlatOneByteStringMask = |
2834 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; | 2828 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; |
2835 const int kFlatAsciiStringTag = | 2829 const int kFlatOneByteStringTag = |
2836 kStringTag | kOneByteStringTag | kSeqStringTag; | 2830 kStringTag | kOneByteStringTag | kSeqStringTag; |
2837 // Interleave bits from both instance types and compare them in one check. | 2831 // Interleave bits from both instance types and compare them in one check. |
2838 DCHECK_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3)); | 2832 DCHECK_EQ(0, kFlatOneByteStringMask & (kFlatOneByteStringMask << 3)); |
2839 and_(scratch1, kFlatAsciiStringMask); | 2833 and_(scratch1, kFlatOneByteStringMask); |
2840 and_(scratch2, kFlatAsciiStringMask); | 2834 and_(scratch2, kFlatOneByteStringMask); |
2841 lea(scratch1, Operand(scratch1, scratch2, times_8, 0)); | 2835 lea(scratch1, Operand(scratch1, scratch2, times_8, 0)); |
2842 cmp(scratch1, kFlatAsciiStringTag | (kFlatAsciiStringTag << 3)); | 2836 cmp(scratch1, kFlatOneByteStringTag | (kFlatOneByteStringTag << 3)); |
2843 j(not_equal, failure); | 2837 j(not_equal, failure); |
2844 } | 2838 } |
2845 | 2839 |
2846 | 2840 |
2847 void MacroAssembler::JumpIfNotUniqueName(Operand operand, | 2841 void MacroAssembler::JumpIfNotUniqueName(Operand operand, |
2848 Label* not_unique_name, | 2842 Label* not_unique_name, |
2849 Label::Distance distance) { | 2843 Label::Distance distance) { |
2850 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); | 2844 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); |
2851 Label succeed; | 2845 Label succeed; |
2852 test(operand, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); | 2846 test(operand, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3171 // External strings are the only ones with the kExternalStringTag bit | 3165 // External strings are the only ones with the kExternalStringTag bit |
3172 // set. | 3166 // set. |
3173 DCHECK_EQ(0, kSeqStringTag & kExternalStringTag); | 3167 DCHECK_EQ(0, kSeqStringTag & kExternalStringTag); |
3174 DCHECK_EQ(0, kConsStringTag & kExternalStringTag); | 3168 DCHECK_EQ(0, kConsStringTag & kExternalStringTag); |
3175 test_b(instance_type, kExternalStringTag); | 3169 test_b(instance_type, kExternalStringTag); |
3176 j(zero, ¬_external, Label::kNear); | 3170 j(zero, ¬_external, Label::kNear); |
3177 mov(length, Immediate(ExternalString::kSize)); | 3171 mov(length, Immediate(ExternalString::kSize)); |
3178 jmp(&is_data_object, Label::kNear); | 3172 jmp(&is_data_object, Label::kNear); |
3179 | 3173 |
3180 bind(¬_external); | 3174 bind(¬_external); |
3181 // Sequential string, either ASCII or UC16. | 3175 // Sequential string, either Latin1 or UC16. |
3182 DCHECK(kOneByteStringTag == 0x04); | 3176 DCHECK(kOneByteStringTag == 0x04); |
3183 and_(length, Immediate(kStringEncodingMask)); | 3177 and_(length, Immediate(kStringEncodingMask)); |
3184 xor_(length, Immediate(kStringEncodingMask)); | 3178 xor_(length, Immediate(kStringEncodingMask)); |
3185 add(length, Immediate(0x04)); | 3179 add(length, Immediate(0x04)); |
3186 // Value now either 4 (if ASCII) or 8 (if UC16), i.e., char-size shifted | 3180 // Value now either 4 (if Latin1) or 8 (if UC16), i.e., char-size shifted |
3187 // by 2. If we multiply the string length as smi by this, it still | 3181 // by 2. If we multiply the string length as smi by this, it still |
3188 // won't overflow a 32-bit value. | 3182 // won't overflow a 32-bit value. |
3189 DCHECK_EQ(SeqOneByteString::kMaxSize, SeqTwoByteString::kMaxSize); | 3183 DCHECK_EQ(SeqOneByteString::kMaxSize, SeqTwoByteString::kMaxSize); |
3190 DCHECK(SeqOneByteString::kMaxSize <= | 3184 DCHECK(SeqOneByteString::kMaxSize <= |
3191 static_cast<int>(0xffffffffu >> (2 + kSmiTagSize))); | 3185 static_cast<int>(0xffffffffu >> (2 + kSmiTagSize))); |
3192 imul(length, FieldOperand(value, String::kLengthOffset)); | 3186 imul(length, FieldOperand(value, String::kLengthOffset)); |
3193 shr(length, 2 + kSmiTagSize + kSmiShiftSize); | 3187 shr(length, 2 + kSmiTagSize + kSmiShiftSize); |
3194 add(length, Immediate(SeqString::kHeaderSize + kObjectAlignmentMask)); | 3188 add(length, Immediate(SeqString::kHeaderSize + kObjectAlignmentMask)); |
3195 and_(length, Immediate(~kObjectAlignmentMask)); | 3189 and_(length, Immediate(~kObjectAlignmentMask)); |
3196 | 3190 |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3321 if (mag.shift > 0) sar(edx, mag.shift); | 3315 if (mag.shift > 0) sar(edx, mag.shift); |
3322 mov(eax, dividend); | 3316 mov(eax, dividend); |
3323 shr(eax, 31); | 3317 shr(eax, 31); |
3324 add(edx, eax); | 3318 add(edx, eax); |
3325 } | 3319 } |
3326 | 3320 |
3327 | 3321 |
3328 } } // namespace v8::internal | 3322 } } // namespace v8::internal |
3329 | 3323 |
3330 #endif // V8_TARGET_ARCH_X87 | 3324 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |