OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
745 Context::SECURITY_TOKEN_INDEX * kPointerSize; | 745 Context::SECURITY_TOKEN_INDEX * kPointerSize; |
746 mov(scratch, FieldOperand(scratch, token_offset)); | 746 mov(scratch, FieldOperand(scratch, token_offset)); |
747 cmp(scratch, FieldOperand(holder_reg, token_offset)); | 747 cmp(scratch, FieldOperand(holder_reg, token_offset)); |
748 pop(holder_reg); | 748 pop(holder_reg); |
749 j(not_equal, miss); | 749 j(not_equal, miss); |
750 | 750 |
751 bind(&same_contexts); | 751 bind(&same_contexts); |
752 } | 752 } |
753 | 753 |
754 | 754 |
| 755 // Compute the hash code from the untagged key. This must be kept in sync |
| 756 // with ComputeIntegerHash in utils.h. |
| 757 // |
| 758 // Note: r0 will contain hash code |
| 759 void MacroAssembler::GetNumberHash(Register r0, Register scratch) { |
| 760 // Xor original key with a seed. |
| 761 if (Serializer::enabled()) { |
| 762 ExternalReference roots_address = |
| 763 ExternalReference::roots_address(isolate()); |
| 764 mov(scratch, Immediate(Heap::kHashSeedRootIndex)); |
| 765 mov(scratch, Operand::StaticArray(scratch, |
| 766 times_pointer_size, |
| 767 roots_address)); |
| 768 SmiUntag(scratch); |
| 769 xor_(r0, Operand(scratch)); |
| 770 } else { |
| 771 int32_t seed = isolate()->heap()->HashSeed(); |
| 772 xor_(r0, seed); |
| 773 } |
| 774 |
| 775 // hash = ~hash + (hash << 15); |
| 776 mov(scratch, r0); |
| 777 not_(r0); |
| 778 shl(scratch, 15); |
| 779 add(r0, Operand(scratch)); |
| 780 // hash = hash ^ (hash >> 12); |
| 781 mov(scratch, r0); |
| 782 shr(scratch, 12); |
| 783 xor_(r0, Operand(scratch)); |
| 784 // hash = hash + (hash << 2); |
| 785 lea(r0, Operand(r0, r0, times_4, 0)); |
| 786 // hash = hash ^ (hash >> 4); |
| 787 mov(scratch, r0); |
| 788 shr(scratch, 4); |
| 789 xor_(r0, Operand(scratch)); |
| 790 // hash = hash * 2057; |
| 791 imul(r0, r0, 2057); |
| 792 // hash = hash ^ (hash >> 16); |
| 793 mov(scratch, r0); |
| 794 shr(scratch, 16); |
| 795 xor_(r0, Operand(scratch)); |
| 796 } |
| 797 |
| 798 |
| 799 |
755 void MacroAssembler::LoadFromNumberDictionary(Label* miss, | 800 void MacroAssembler::LoadFromNumberDictionary(Label* miss, |
756 Register elements, | 801 Register elements, |
757 Register key, | 802 Register key, |
758 Register r0, | 803 Register r0, |
759 Register r1, | 804 Register r1, |
760 Register r2, | 805 Register r2, |
761 Register result) { | 806 Register result) { |
762 // Register use: | 807 // Register use: |
763 // | 808 // |
764 // elements - holds the slow-case elements of the receiver and is unchanged. | 809 // elements - holds the slow-case elements of the receiver and is unchanged. |
765 // | 810 // |
766 // key - holds the smi key on entry and is unchanged. | 811 // key - holds the smi key on entry and is unchanged. |
767 // | 812 // |
768 // Scratch registers: | 813 // Scratch registers: |
769 // | 814 // |
770 // r0 - holds the untagged key on entry and holds the hash once computed. | 815 // r0 - holds the untagged key on entry and holds the hash once computed. |
771 // | 816 // |
772 // r1 - used to hold the capacity mask of the dictionary | 817 // r1 - used to hold the capacity mask of the dictionary |
773 // | 818 // |
774 // r2 - used for the index into the dictionary. | 819 // r2 - used for the index into the dictionary. |
775 // | 820 // |
776 // result - holds the result on exit if the load succeeds and we fall through. | 821 // result - holds the result on exit if the load succeeds and we fall through. |
777 | 822 |
778 Label done; | 823 Label done; |
779 | 824 |
780 // Compute the hash code from the untagged key. This must be kept in sync | 825 GetNumberHash(r0, r1); |
781 // with ComputeIntegerHash in utils.h. | |
782 // | |
783 // hash = ~hash + (hash << 15); | |
784 mov(r1, r0); | |
785 not_(r0); | |
786 shl(r1, 15); | |
787 add(r0, Operand(r1)); | |
788 // hash = hash ^ (hash >> 12); | |
789 mov(r1, r0); | |
790 shr(r1, 12); | |
791 xor_(r0, Operand(r1)); | |
792 // hash = hash + (hash << 2); | |
793 lea(r0, Operand(r0, r0, times_4, 0)); | |
794 // hash = hash ^ (hash >> 4); | |
795 mov(r1, r0); | |
796 shr(r1, 4); | |
797 xor_(r0, Operand(r1)); | |
798 // hash = hash * 2057; | |
799 imul(r0, r0, 2057); | |
800 // hash = hash ^ (hash >> 16); | |
801 mov(r1, r0); | |
802 shr(r1, 16); | |
803 xor_(r0, Operand(r1)); | |
804 | 826 |
805 // Compute capacity mask. | 827 // Compute capacity mask. |
806 mov(r1, FieldOperand(elements, NumberDictionary::kCapacityOffset)); | 828 mov(r1, FieldOperand(elements, SeededNumberDictionary::kCapacityOffset)); |
807 shr(r1, kSmiTagSize); // convert smi to int | 829 shr(r1, kSmiTagSize); // convert smi to int |
808 dec(r1); | 830 dec(r1); |
809 | 831 |
810 // Generate an unrolled loop that performs a few probes before giving up. | 832 // Generate an unrolled loop that performs a few probes before giving up. |
811 const int kProbes = 4; | 833 const int kProbes = 4; |
812 for (int i = 0; i < kProbes; i++) { | 834 for (int i = 0; i < kProbes; i++) { |
813 // Use r2 for index calculations and keep the hash intact in r0. | 835 // Use r2 for index calculations and keep the hash intact in r0. |
814 mov(r2, r0); | 836 mov(r2, r0); |
815 // Compute the masked index: (hash + i + i * i) & mask. | 837 // Compute the masked index: (hash + i + i * i) & mask. |
816 if (i > 0) { | 838 if (i > 0) { |
817 add(Operand(r2), Immediate(NumberDictionary::GetProbeOffset(i))); | 839 add(Operand(r2), Immediate(SeededNumberDictionary::GetProbeOffset(i))); |
818 } | 840 } |
819 and_(r2, Operand(r1)); | 841 and_(r2, Operand(r1)); |
820 | 842 |
821 // Scale the index by multiplying by the entry size. | 843 // Scale the index by multiplying by the entry size. |
822 ASSERT(NumberDictionary::kEntrySize == 3); | 844 ASSERT(SeededNumberDictionary::kEntrySize == 3); |
823 lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 | 845 lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 |
824 | 846 |
825 // Check if the key matches. | 847 // Check if the key matches. |
826 cmp(key, FieldOperand(elements, | 848 cmp(key, FieldOperand(elements, |
827 r2, | 849 r2, |
828 times_pointer_size, | 850 times_pointer_size, |
829 NumberDictionary::kElementsStartOffset)); | 851 SeededNumberDictionary::kElementsStartOffset)); |
830 if (i != (kProbes - 1)) { | 852 if (i != (kProbes - 1)) { |
831 j(equal, &done); | 853 j(equal, &done); |
832 } else { | 854 } else { |
833 j(not_equal, miss); | 855 j(not_equal, miss); |
834 } | 856 } |
835 } | 857 } |
836 | 858 |
837 bind(&done); | 859 bind(&done); |
838 // Check that the value is a normal propety. | 860 // Check that the value is a normal propety. |
839 const int kDetailsOffset = | 861 const int kDetailsOffset = |
840 NumberDictionary::kElementsStartOffset + 2 * kPointerSize; | 862 SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize; |
841 ASSERT_EQ(NORMAL, 0); | 863 ASSERT_EQ(NORMAL, 0); |
842 test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), | 864 test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), |
843 Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize)); | 865 Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize)); |
844 j(not_zero, miss); | 866 j(not_zero, miss); |
845 | 867 |
846 // Get the value at the masked, scaled index. | 868 // Get the value at the masked, scaled index. |
847 const int kValueOffset = | 869 const int kValueOffset = |
848 NumberDictionary::kElementsStartOffset + kPointerSize; | 870 SeededNumberDictionary::kElementsStartOffset + kPointerSize; |
849 mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); | 871 mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); |
850 } | 872 } |
851 | 873 |
852 | 874 |
853 void MacroAssembler::LoadAllocationTopHelper(Register result, | 875 void MacroAssembler::LoadAllocationTopHelper(Register result, |
854 Register scratch, | 876 Register scratch, |
855 AllocationFlags flags) { | 877 AllocationFlags flags) { |
856 ExternalReference new_space_allocation_top = | 878 ExternalReference new_space_allocation_top = |
857 ExternalReference::new_space_allocation_top_address(isolate()); | 879 ExternalReference::new_space_allocation_top_address(isolate()); |
858 | 880 |
(...skipping 1423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2282 | 2304 |
2283 // Check that the code was patched as expected. | 2305 // Check that the code was patched as expected. |
2284 ASSERT(masm_.pc_ == address_ + size_); | 2306 ASSERT(masm_.pc_ == address_ + size_); |
2285 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 2307 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
2286 } | 2308 } |
2287 | 2309 |
2288 | 2310 |
2289 } } // namespace v8::internal | 2311 } } // namespace v8::internal |
2290 | 2312 |
2291 #endif // V8_TARGET_ARCH_IA32 | 2313 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |