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_X64 | 7 #if V8_TARGET_ARCH_X64 |
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 2593 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2604 Register object_map, | 2604 Register object_map, |
2605 Label* not_string, | 2605 Label* not_string, |
2606 Label::Distance near_jump) { | 2606 Label::Distance near_jump) { |
2607 Condition is_smi = CheckSmi(object); | 2607 Condition is_smi = CheckSmi(object); |
2608 j(is_smi, not_string, near_jump); | 2608 j(is_smi, not_string, near_jump); |
2609 CmpObjectType(object, FIRST_NONSTRING_TYPE, object_map); | 2609 CmpObjectType(object, FIRST_NONSTRING_TYPE, object_map); |
2610 j(above_equal, not_string, near_jump); | 2610 j(above_equal, not_string, near_jump); |
2611 } | 2611 } |
2612 | 2612 |
2613 | 2613 |
2614 void MacroAssembler::JumpIfNotBothSequentialAsciiStrings( | 2614 void MacroAssembler::JumpIfNotBothSequentialOneByteStrings( |
2615 Register first_object, | 2615 Register first_object, Register second_object, Register scratch1, |
2616 Register second_object, | 2616 Register scratch2, Label* on_fail, Label::Distance near_jump) { |
2617 Register scratch1, | |
2618 Register scratch2, | |
2619 Label* on_fail, | |
2620 Label::Distance near_jump) { | |
2621 // Check that both objects are not smis. | 2617 // Check that both objects are not smis. |
2622 Condition either_smi = CheckEitherSmi(first_object, second_object); | 2618 Condition either_smi = CheckEitherSmi(first_object, second_object); |
2623 j(either_smi, on_fail, near_jump); | 2619 j(either_smi, on_fail, near_jump); |
2624 | 2620 |
2625 // Load instance type for both strings. | 2621 // Load instance type for both strings. |
2626 movp(scratch1, FieldOperand(first_object, HeapObject::kMapOffset)); | 2622 movp(scratch1, FieldOperand(first_object, HeapObject::kMapOffset)); |
2627 movp(scratch2, FieldOperand(second_object, HeapObject::kMapOffset)); | 2623 movp(scratch2, FieldOperand(second_object, HeapObject::kMapOffset)); |
2628 movzxbl(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset)); | 2624 movzxbl(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset)); |
2629 movzxbl(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset)); | 2625 movzxbl(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset)); |
2630 | 2626 |
2631 // Check that both are flat ASCII strings. | 2627 // Check that both are flat one-byte strings. |
2632 DCHECK(kNotStringTag != 0); | 2628 DCHECK(kNotStringTag != 0); |
2633 const int kFlatAsciiStringMask = | 2629 const int kFlatOneByteStringMask = |
2634 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; | 2630 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; |
2635 const int kFlatAsciiStringTag = | 2631 const int kFlatOneByteStringTag = |
2636 kStringTag | kOneByteStringTag | kSeqStringTag; | 2632 kStringTag | kOneByteStringTag | kSeqStringTag; |
2637 | 2633 |
2638 andl(scratch1, Immediate(kFlatAsciiStringMask)); | 2634 andl(scratch1, Immediate(kFlatOneByteStringMask)); |
2639 andl(scratch2, Immediate(kFlatAsciiStringMask)); | 2635 andl(scratch2, Immediate(kFlatOneByteStringMask)); |
2640 // Interleave the bits to check both scratch1 and scratch2 in one test. | 2636 // Interleave the bits to check both scratch1 and scratch2 in one test. |
2641 DCHECK_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3)); | 2637 DCHECK_EQ(0, kFlatOneByteStringMask & (kFlatOneByteStringMask << 3)); |
2642 leap(scratch1, Operand(scratch1, scratch2, times_8, 0)); | 2638 leap(scratch1, Operand(scratch1, scratch2, times_8, 0)); |
2643 cmpl(scratch1, | 2639 cmpl(scratch1, |
2644 Immediate(kFlatAsciiStringTag + (kFlatAsciiStringTag << 3))); | 2640 Immediate(kFlatOneByteStringTag + (kFlatOneByteStringTag << 3))); |
2645 j(not_equal, on_fail, near_jump); | 2641 j(not_equal, on_fail, near_jump); |
2646 } | 2642 } |
2647 | 2643 |
2648 | 2644 |
2649 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii( | 2645 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialOneByte( |
2650 Register instance_type, | 2646 Register instance_type, Register scratch, Label* failure, |
2651 Register scratch, | |
2652 Label* failure, | |
2653 Label::Distance near_jump) { | 2647 Label::Distance near_jump) { |
2654 if (!scratch.is(instance_type)) { | 2648 if (!scratch.is(instance_type)) { |
2655 movl(scratch, instance_type); | 2649 movl(scratch, instance_type); |
2656 } | 2650 } |
2657 | 2651 |
2658 const int kFlatAsciiStringMask = | 2652 const int kFlatOneByteStringMask = |
2659 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; | 2653 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; |
2660 | 2654 |
2661 andl(scratch, Immediate(kFlatAsciiStringMask)); | 2655 andl(scratch, Immediate(kFlatOneByteStringMask)); |
2662 cmpl(scratch, Immediate(kStringTag | kSeqStringTag | kOneByteStringTag)); | 2656 cmpl(scratch, Immediate(kStringTag | kSeqStringTag | kOneByteStringTag)); |
2663 j(not_equal, failure, near_jump); | 2657 j(not_equal, failure, near_jump); |
2664 } | 2658 } |
2665 | 2659 |
2666 | 2660 |
2667 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii( | 2661 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialOneByte( |
2668 Register first_object_instance_type, | 2662 Register first_object_instance_type, Register second_object_instance_type, |
2669 Register second_object_instance_type, | 2663 Register scratch1, Register scratch2, Label* on_fail, |
2670 Register scratch1, | |
2671 Register scratch2, | |
2672 Label* on_fail, | |
2673 Label::Distance near_jump) { | 2664 Label::Distance near_jump) { |
2674 // Load instance type for both strings. | 2665 // Load instance type for both strings. |
2675 movp(scratch1, first_object_instance_type); | 2666 movp(scratch1, first_object_instance_type); |
2676 movp(scratch2, second_object_instance_type); | 2667 movp(scratch2, second_object_instance_type); |
2677 | 2668 |
2678 // Check that both are flat ASCII strings. | 2669 // Check that both are flat one-byte strings. |
2679 DCHECK(kNotStringTag != 0); | 2670 DCHECK(kNotStringTag != 0); |
2680 const int kFlatAsciiStringMask = | 2671 const int kFlatOneByteStringMask = |
2681 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; | 2672 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; |
2682 const int kFlatAsciiStringTag = | 2673 const int kFlatOneByteStringTag = |
2683 kStringTag | kOneByteStringTag | kSeqStringTag; | 2674 kStringTag | kOneByteStringTag | kSeqStringTag; |
2684 | 2675 |
2685 andl(scratch1, Immediate(kFlatAsciiStringMask)); | 2676 andl(scratch1, Immediate(kFlatOneByteStringMask)); |
2686 andl(scratch2, Immediate(kFlatAsciiStringMask)); | 2677 andl(scratch2, Immediate(kFlatOneByteStringMask)); |
2687 // Interleave the bits to check both scratch1 and scratch2 in one test. | 2678 // Interleave the bits to check both scratch1 and scratch2 in one test. |
2688 DCHECK_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3)); | 2679 DCHECK_EQ(0, kFlatOneByteStringMask & (kFlatOneByteStringMask << 3)); |
2689 leap(scratch1, Operand(scratch1, scratch2, times_8, 0)); | 2680 leap(scratch1, Operand(scratch1, scratch2, times_8, 0)); |
2690 cmpl(scratch1, | 2681 cmpl(scratch1, |
2691 Immediate(kFlatAsciiStringTag + (kFlatAsciiStringTag << 3))); | 2682 Immediate(kFlatOneByteStringTag + (kFlatOneByteStringTag << 3))); |
2692 j(not_equal, on_fail, near_jump); | 2683 j(not_equal, on_fail, near_jump); |
2693 } | 2684 } |
2694 | 2685 |
2695 | 2686 |
2696 template<class T> | 2687 template<class T> |
2697 static void JumpIfNotUniqueNameHelper(MacroAssembler* masm, | 2688 static void JumpIfNotUniqueNameHelper(MacroAssembler* masm, |
2698 T operand_or_register, | 2689 T operand_or_register, |
2699 Label* not_unique_name, | 2690 Label* not_unique_name, |
2700 Label::Distance distance) { | 2691 Label::Distance distance) { |
2701 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); | 2692 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); |
(...skipping 1943 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4645 // Set the map, length and hash field. | 4636 // Set the map, length and hash field. |
4646 LoadRoot(kScratchRegister, Heap::kStringMapRootIndex); | 4637 LoadRoot(kScratchRegister, Heap::kStringMapRootIndex); |
4647 movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); | 4638 movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); |
4648 Integer32ToSmi(scratch1, length); | 4639 Integer32ToSmi(scratch1, length); |
4649 movp(FieldOperand(result, String::kLengthOffset), scratch1); | 4640 movp(FieldOperand(result, String::kLengthOffset), scratch1); |
4650 movp(FieldOperand(result, String::kHashFieldOffset), | 4641 movp(FieldOperand(result, String::kHashFieldOffset), |
4651 Immediate(String::kEmptyHashField)); | 4642 Immediate(String::kEmptyHashField)); |
4652 } | 4643 } |
4653 | 4644 |
4654 | 4645 |
4655 void MacroAssembler::AllocateAsciiString(Register result, | 4646 void MacroAssembler::AllocateOneByteString(Register result, Register length, |
4656 Register length, | 4647 Register scratch1, Register scratch2, |
4657 Register scratch1, | 4648 Register scratch3, |
4658 Register scratch2, | 4649 Label* gc_required) { |
4659 Register scratch3, | |
4660 Label* gc_required) { | |
4661 // Calculate the number of bytes needed for the characters in the string while | 4650 // Calculate the number of bytes needed for the characters in the string while |
4662 // observing object alignment. | 4651 // observing object alignment. |
4663 const int kHeaderAlignment = SeqOneByteString::kHeaderSize & | 4652 const int kHeaderAlignment = SeqOneByteString::kHeaderSize & |
4664 kObjectAlignmentMask; | 4653 kObjectAlignmentMask; |
4665 movl(scratch1, length); | 4654 movl(scratch1, length); |
4666 DCHECK(kCharSize == 1); | 4655 DCHECK(kCharSize == 1); |
4667 addp(scratch1, Immediate(kObjectAlignmentMask + kHeaderAlignment)); | 4656 addp(scratch1, Immediate(kObjectAlignmentMask + kHeaderAlignment)); |
4668 andp(scratch1, Immediate(~kObjectAlignmentMask)); | 4657 andp(scratch1, Immediate(~kObjectAlignmentMask)); |
4669 if (kHeaderAlignment > 0) { | 4658 if (kHeaderAlignment > 0) { |
4670 subp(scratch1, Immediate(kHeaderAlignment)); | 4659 subp(scratch1, Immediate(kHeaderAlignment)); |
4671 } | 4660 } |
4672 | 4661 |
4673 // Allocate ASCII string in new space. | 4662 // Allocate one-byte string in new space. |
4674 Allocate(SeqOneByteString::kHeaderSize, | 4663 Allocate(SeqOneByteString::kHeaderSize, |
4675 times_1, | 4664 times_1, |
4676 scratch1, | 4665 scratch1, |
4677 result, | 4666 result, |
4678 scratch2, | 4667 scratch2, |
4679 scratch3, | 4668 scratch3, |
4680 gc_required, | 4669 gc_required, |
4681 TAG_OBJECT); | 4670 TAG_OBJECT); |
4682 | 4671 |
4683 // Set the map, length and hash field. | 4672 // Set the map, length and hash field. |
4684 LoadRoot(kScratchRegister, Heap::kAsciiStringMapRootIndex); | 4673 LoadRoot(kScratchRegister, Heap::kOneByteStringMapRootIndex); |
4685 movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); | 4674 movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); |
4686 Integer32ToSmi(scratch1, length); | 4675 Integer32ToSmi(scratch1, length); |
4687 movp(FieldOperand(result, String::kLengthOffset), scratch1); | 4676 movp(FieldOperand(result, String::kLengthOffset), scratch1); |
4688 movp(FieldOperand(result, String::kHashFieldOffset), | 4677 movp(FieldOperand(result, String::kHashFieldOffset), |
4689 Immediate(String::kEmptyHashField)); | 4678 Immediate(String::kEmptyHashField)); |
4690 } | 4679 } |
4691 | 4680 |
4692 | 4681 |
4693 void MacroAssembler::AllocateTwoByteConsString(Register result, | 4682 void MacroAssembler::AllocateTwoByteConsString(Register result, |
4694 Register scratch1, | 4683 Register scratch1, |
4695 Register scratch2, | 4684 Register scratch2, |
4696 Label* gc_required) { | 4685 Label* gc_required) { |
4697 // Allocate heap number in new space. | 4686 // Allocate heap number in new space. |
4698 Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required, | 4687 Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required, |
4699 TAG_OBJECT); | 4688 TAG_OBJECT); |
4700 | 4689 |
4701 // Set the map. The other fields are left uninitialized. | 4690 // Set the map. The other fields are left uninitialized. |
4702 LoadRoot(kScratchRegister, Heap::kConsStringMapRootIndex); | 4691 LoadRoot(kScratchRegister, Heap::kConsStringMapRootIndex); |
4703 movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); | 4692 movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); |
4704 } | 4693 } |
4705 | 4694 |
4706 | 4695 |
4707 void MacroAssembler::AllocateAsciiConsString(Register result, | 4696 void MacroAssembler::AllocateOneByteConsString(Register result, |
4708 Register scratch1, | 4697 Register scratch1, |
4709 Register scratch2, | 4698 Register scratch2, |
4710 Label* gc_required) { | 4699 Label* gc_required) { |
4711 Allocate(ConsString::kSize, | 4700 Allocate(ConsString::kSize, |
4712 result, | 4701 result, |
4713 scratch1, | 4702 scratch1, |
4714 scratch2, | 4703 scratch2, |
4715 gc_required, | 4704 gc_required, |
4716 TAG_OBJECT); | 4705 TAG_OBJECT); |
4717 | 4706 |
4718 // Set the map. The other fields are left uninitialized. | 4707 // Set the map. The other fields are left uninitialized. |
4719 LoadRoot(kScratchRegister, Heap::kConsAsciiStringMapRootIndex); | 4708 LoadRoot(kScratchRegister, Heap::kConsOneByteStringMapRootIndex); |
4720 movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); | 4709 movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); |
4721 } | 4710 } |
4722 | 4711 |
4723 | 4712 |
4724 void MacroAssembler::AllocateTwoByteSlicedString(Register result, | 4713 void MacroAssembler::AllocateTwoByteSlicedString(Register result, |
4725 Register scratch1, | 4714 Register scratch1, |
4726 Register scratch2, | 4715 Register scratch2, |
4727 Label* gc_required) { | 4716 Label* gc_required) { |
4728 // Allocate heap number in new space. | 4717 // Allocate heap number in new space. |
4729 Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required, | 4718 Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required, |
4730 TAG_OBJECT); | 4719 TAG_OBJECT); |
4731 | 4720 |
4732 // Set the map. The other fields are left uninitialized. | 4721 // Set the map. The other fields are left uninitialized. |
4733 LoadRoot(kScratchRegister, Heap::kSlicedStringMapRootIndex); | 4722 LoadRoot(kScratchRegister, Heap::kSlicedStringMapRootIndex); |
4734 movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); | 4723 movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); |
4735 } | 4724 } |
4736 | 4725 |
4737 | 4726 |
4738 void MacroAssembler::AllocateAsciiSlicedString(Register result, | 4727 void MacroAssembler::AllocateOneByteSlicedString(Register result, |
4739 Register scratch1, | 4728 Register scratch1, |
4740 Register scratch2, | 4729 Register scratch2, |
4741 Label* gc_required) { | 4730 Label* gc_required) { |
4742 // Allocate heap number in new space. | 4731 // Allocate heap number in new space. |
4743 Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required, | 4732 Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required, |
4744 TAG_OBJECT); | 4733 TAG_OBJECT); |
4745 | 4734 |
4746 // Set the map. The other fields are left uninitialized. | 4735 // Set the map. The other fields are left uninitialized. |
4747 LoadRoot(kScratchRegister, Heap::kSlicedAsciiStringMapRootIndex); | 4736 LoadRoot(kScratchRegister, Heap::kSlicedOneByteStringMapRootIndex); |
4748 movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); | 4737 movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); |
4749 } | 4738 } |
4750 | 4739 |
4751 | 4740 |
4752 // Copy memory, byte-by-byte, from source to destination. Not optimized for | 4741 // Copy memory, byte-by-byte, from source to destination. Not optimized for |
4753 // long or aligned copies. The contents of scratch and length are destroyed. | 4742 // long or aligned copies. The contents of scratch and length are destroyed. |
4754 // Destination is incremented by length, source, length and scratch are | 4743 // Destination is incremented by length, source, length and scratch are |
4755 // clobbered. | 4744 // clobbered. |
4756 // A simpler loop is faster on small copies, but slower on large ones. | 4745 // A simpler loop is faster on small copies, but slower on large ones. |
4757 // The cld() instruction must have been emitted, to set the direction flag(), | 4746 // The cld() instruction must have been emitted, to set the direction flag(), |
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5246 // External strings are the only ones with the kExternalStringTag bit | 5235 // External strings are the only ones with the kExternalStringTag bit |
5247 // set. | 5236 // set. |
5248 DCHECK_EQ(0, kSeqStringTag & kExternalStringTag); | 5237 DCHECK_EQ(0, kSeqStringTag & kExternalStringTag); |
5249 DCHECK_EQ(0, kConsStringTag & kExternalStringTag); | 5238 DCHECK_EQ(0, kConsStringTag & kExternalStringTag); |
5250 testb(instance_type, Immediate(kExternalStringTag)); | 5239 testb(instance_type, Immediate(kExternalStringTag)); |
5251 j(zero, ¬_external, Label::kNear); | 5240 j(zero, ¬_external, Label::kNear); |
5252 movp(length, Immediate(ExternalString::kSize)); | 5241 movp(length, Immediate(ExternalString::kSize)); |
5253 jmp(&is_data_object, Label::kNear); | 5242 jmp(&is_data_object, Label::kNear); |
5254 | 5243 |
5255 bind(¬_external); | 5244 bind(¬_external); |
5256 // Sequential string, either ASCII or UC16. | 5245 // Sequential string, either Latin1 or UC16. |
5257 DCHECK(kOneByteStringTag == 0x04); | 5246 DCHECK(kOneByteStringTag == 0x04); |
5258 andp(length, Immediate(kStringEncodingMask)); | 5247 andp(length, Immediate(kStringEncodingMask)); |
5259 xorp(length, Immediate(kStringEncodingMask)); | 5248 xorp(length, Immediate(kStringEncodingMask)); |
5260 addp(length, Immediate(0x04)); | 5249 addp(length, Immediate(0x04)); |
5261 // Value now either 4 (if ASCII) or 8 (if UC16), i.e. char-size shifted by 2. | 5250 // Value now either 4 (if Latin1) or 8 (if UC16), i.e. char-size shifted by 2. |
5262 imulp(length, FieldOperand(value, String::kLengthOffset)); | 5251 imulp(length, FieldOperand(value, String::kLengthOffset)); |
5263 shrp(length, Immediate(2 + kSmiTagSize + kSmiShiftSize)); | 5252 shrp(length, Immediate(2 + kSmiTagSize + kSmiShiftSize)); |
5264 addp(length, Immediate(SeqString::kHeaderSize + kObjectAlignmentMask)); | 5253 addp(length, Immediate(SeqString::kHeaderSize + kObjectAlignmentMask)); |
5265 andp(length, Immediate(~kObjectAlignmentMask)); | 5254 andp(length, Immediate(~kObjectAlignmentMask)); |
5266 | 5255 |
5267 bind(&is_data_object); | 5256 bind(&is_data_object); |
5268 // Value is a data object, and it is white. Mark it black. Since we know | 5257 // Value is a data object, and it is white. Mark it black. Since we know |
5269 // that the object is white we can make it black by flipping one bit. | 5258 // that the object is white we can make it black by flipping one bit. |
5270 orp(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch); | 5259 orp(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch); |
5271 | 5260 |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5380 if (mag.shift > 0) sarl(rdx, Immediate(mag.shift)); | 5369 if (mag.shift > 0) sarl(rdx, Immediate(mag.shift)); |
5381 movl(rax, dividend); | 5370 movl(rax, dividend); |
5382 shrl(rax, Immediate(31)); | 5371 shrl(rax, Immediate(31)); |
5383 addl(rdx, rax); | 5372 addl(rdx, rax); |
5384 } | 5373 } |
5385 | 5374 |
5386 | 5375 |
5387 } } // namespace v8::internal | 5376 } } // namespace v8::internal |
5388 | 5377 |
5389 #endif // V8_TARGET_ARCH_X64 | 5378 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |