OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 | 85 |
86 // Helper function used to check that the dictionary doesn't contain | 86 // Helper function used to check that the dictionary doesn't contain |
87 // the property. This function may return false negatives, so miss_label | 87 // the property. This function may return false negatives, so miss_label |
88 // must always call a backup property check that is complete. | 88 // must always call a backup property check that is complete. |
89 // This function is safe to call if the receiver has fast properties. | 89 // This function is safe to call if the receiver has fast properties. |
90 // Name must be a symbol and receiver must be a heap object. | 90 // Name must be a symbol and receiver must be a heap object. |
91 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, | 91 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, |
92 Label* miss_label, | 92 Label* miss_label, |
93 Register receiver, | 93 Register receiver, |
94 String* name, | 94 String* name, |
95 Register r0, | 95 Register scratch0, |
96 Register extra) { | 96 Register scratch1) { |
97 ASSERT(name->IsSymbol()); | 97 ASSERT(name->IsSymbol()); |
98 if (!extra.is(no_reg)) { | 98 __ IncrementCounter(&Counters::negative_lookups, 1, scratch0, scratch1); |
99 __ IncrementCounter(&Counters::negative_lookups, 1, r0, extra); | 99 __ IncrementCounter(&Counters::negative_lookups_miss, 1, scratch0, scratch1); |
100 __ IncrementCounter(&Counters::negative_lookups_miss, 1, r0, extra); | |
101 } | |
102 | 100 |
103 Label done; | 101 Label done; |
104 | 102 |
105 const int kInterceptorOrAccessCheckNeededMask = | 103 const int kInterceptorOrAccessCheckNeededMask = |
106 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 104 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
107 | 105 |
108 // Bail out if the receiver has a named interceptor or requires access checks. | 106 // Bail out if the receiver has a named interceptor or requires access checks. |
109 Register map = extra.is(no_reg) ? r0 : extra; | 107 Register map = scratch1; |
110 __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 108 __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
111 __ ldrb(r0, FieldMemOperand(map, Map::kBitFieldOffset)); | 109 __ ldrb(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); |
112 __ tst(r0, Operand(kInterceptorOrAccessCheckNeededMask)); | 110 __ tst(scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); |
113 __ b(ne, miss_label); | 111 __ b(ne, miss_label); |
114 | 112 |
115 // Check that receiver is a JSObject. | 113 // Check that receiver is a JSObject. |
116 if (extra.is(no_reg)) { | 114 __ ldrb(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
117 __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 115 __ cmp(scratch0, Operand(FIRST_JS_OBJECT_TYPE)); |
118 } | |
119 __ ldrb(r0, FieldMemOperand(map, Map::kInstanceTypeOffset)); | |
120 __ cmp(r0, Operand(FIRST_JS_OBJECT_TYPE)); | |
121 __ b(lt, miss_label); | 116 __ b(lt, miss_label); |
122 | 117 |
123 // Load properties array. | 118 // Load properties array. |
124 Register properties = r0; | 119 Register properties = scratch0; |
125 __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 120 __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
126 // Check that the properties array is a dictionary. | 121 // Check that the properties array is a dictionary. |
127 if (!extra.is(no_reg)) { | 122 __ ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset)); |
128 __ ldr(extra, FieldMemOperand(properties, HeapObject::kMapOffset)); | 123 Register tmp = properties; |
129 Register tmp = properties; | 124 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); |
130 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); | 125 __ cmp(map, tmp); |
131 __ cmp(extra, tmp); | |
132 } else { | |
133 Register tmp1 = receiver; | |
134 Register tmp2 = properties; | |
135 __ push(tmp1); | |
136 __ ldr(tmp1, FieldMemOperand(properties, HeapObject::kMapOffset)); | |
137 __ LoadRoot(tmp2, Heap::kHashTableMapRootIndex); | |
138 __ cmp(tmp1, tmp2); | |
139 __ pop(tmp1); | |
140 } | |
141 __ b(ne, miss_label); | 126 __ b(ne, miss_label); |
142 | 127 |
143 // Restore the temporarily used register. | 128 // Restore the temporarily used register. |
144 __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 129 __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
145 | 130 |
146 // Compute the capacity mask. | 131 // Compute the capacity mask. |
147 const int kCapacityOffset = | 132 const int kCapacityOffset = |
148 StringDictionary::kHeaderSize + | 133 StringDictionary::kHeaderSize + |
149 StringDictionary::kCapacityIndex * kPointerSize; | 134 StringDictionary::kCapacityIndex * kPointerSize; |
150 | 135 |
151 // Generate an unrolled loop that performs a few probes before | 136 // Generate an unrolled loop that performs a few probes before |
152 // giving up. | 137 // giving up. |
153 static const int kProbes = 4; | 138 static const int kProbes = 4; |
154 const int kElementsStartOffset = | 139 const int kElementsStartOffset = |
155 StringDictionary::kHeaderSize + | 140 StringDictionary::kHeaderSize + |
156 StringDictionary::kElementsStartIndex * kPointerSize; | 141 StringDictionary::kElementsStartIndex * kPointerSize; |
157 | 142 |
158 // If names of slots in range from 1 to kProbes - 1 for the hash value are | 143 // If names of slots in range from 1 to kProbes - 1 for the hash value are |
159 // not equal to the name and kProbes-th slot is not used (its name is the | 144 // not equal to the name and kProbes-th slot is not used (its name is the |
160 // undefined value), it guarantees the hash table doesn't contain the | 145 // undefined value), it guarantees the hash table doesn't contain the |
161 // property. It's true even if some slots represent deleted properties | 146 // property. It's true even if some slots represent deleted properties |
162 // (their names are the null value). | 147 // (their names are the null value). |
163 for (int i = 0; i < kProbes; i++) { | 148 for (int i = 0; i < kProbes; i++) { |
164 // r0 points to properties hash. | 149 // scratch0 points to properties hash. |
165 // Compute the masked index: (hash + i + i * i) & mask. | 150 // Compute the masked index: (hash + i + i * i) & mask. |
166 if (extra.is(no_reg)) { | 151 Register index = scratch1; |
167 __ push(receiver); | |
168 } | |
169 Register index = extra.is(no_reg) ? receiver : extra; | |
170 // Capacity is smi 2^n. | 152 // Capacity is smi 2^n. |
171 __ ldr(index, FieldMemOperand(properties, kCapacityOffset)); | 153 __ ldr(index, FieldMemOperand(properties, kCapacityOffset)); |
172 __ sub(index, index, Operand(1)); | 154 __ sub(index, index, Operand(1)); |
173 __ and_(index, index, Operand( | 155 __ and_(index, index, Operand( |
174 Smi::FromInt(name->Hash() + StringDictionary::GetProbeOffset(i)))); | 156 Smi::FromInt(name->Hash() + StringDictionary::GetProbeOffset(i)))); |
175 | 157 |
176 // Scale the index by multiplying by the entry size. | 158 // Scale the index by multiplying by the entry size. |
177 ASSERT(StringDictionary::kEntrySize == 3); | 159 ASSERT(StringDictionary::kEntrySize == 3); |
178 __ add(index, index, Operand(index, LSL, 1)); // index *= 3. | 160 __ add(index, index, Operand(index, LSL, 1)); // index *= 3. |
179 | 161 |
180 Register entity_name = extra.is(no_reg) ? properties : extra; | 162 Register entity_name = scratch1; |
181 // Having undefined at this place means the name is not contained. | 163 // Having undefined at this place means the name is not contained. |
182 ASSERT_EQ(kSmiTagSize, 1); | 164 ASSERT_EQ(kSmiTagSize, 1); |
183 Register tmp = extra.is(no_reg) ? receiver : properties; | 165 Register tmp = properties; |
184 __ add(tmp, properties, Operand(index, LSL, 1)); | 166 __ add(tmp, properties, Operand(index, LSL, 1)); |
185 __ ldr(entity_name, FieldMemOperand(tmp, kElementsStartOffset)); | 167 __ ldr(entity_name, FieldMemOperand(tmp, kElementsStartOffset)); |
186 | 168 |
187 ASSERT(!tmp.is(entity_name)); | 169 ASSERT(!tmp.is(entity_name)); |
188 __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex); | 170 __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex); |
189 __ cmp(entity_name, tmp); | 171 __ cmp(entity_name, tmp); |
190 if (extra.is(no_reg)) { | |
191 // 'receiver' shares a register with 'entity_name'. | |
192 __ pop(receiver); | |
193 } | |
194 if (i != kProbes - 1) { | 172 if (i != kProbes - 1) { |
195 __ b(eq, &done); | 173 __ b(eq, &done); |
196 | 174 |
197 // Stop if found the property. | 175 // Stop if found the property. |
198 __ cmp(entity_name, Operand(Handle<String>(name))); | 176 __ cmp(entity_name, Operand(Handle<String>(name))); |
199 __ b(eq, miss_label); | 177 __ b(eq, miss_label); |
200 | 178 |
201 // Restore the properties. | 179 // Restore the properties. |
202 __ ldr(properties, | 180 __ ldr(properties, |
203 FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 181 FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
204 } else { | 182 } else { |
205 // Give up probing if still not found the undefined value. | 183 // Give up probing if still not found the undefined value. |
206 __ b(ne, miss_label); | 184 __ b(ne, miss_label); |
207 } | 185 } |
208 } | 186 } |
209 __ bind(&done); | 187 __ bind(&done); |
210 if (!extra.is(no_reg)) { | 188 __ DecrementCounter(&Counters::negative_lookups_miss, 1, scratch0, scratch1); |
211 __ DecrementCounter(&Counters::negative_lookups_miss, 1, r0, extra); | |
212 } | |
213 } | 189 } |
214 | 190 |
215 | 191 |
216 void StubCache::GenerateProbe(MacroAssembler* masm, | 192 void StubCache::GenerateProbe(MacroAssembler* masm, |
217 Code::Flags flags, | 193 Code::Flags flags, |
218 Register receiver, | 194 Register receiver, |
219 Register name, | 195 Register name, |
220 Register scratch, | 196 Register scratch, |
221 Register extra) { | 197 Register extra) { |
222 Label miss; | 198 Label miss; |
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
640 name_(name) {} | 616 name_(name) {} |
641 | 617 |
642 void Compile(MacroAssembler* masm, | 618 void Compile(MacroAssembler* masm, |
643 JSObject* object, | 619 JSObject* object, |
644 JSObject* holder, | 620 JSObject* holder, |
645 String* name, | 621 String* name, |
646 LookupResult* lookup, | 622 LookupResult* lookup, |
647 Register receiver, | 623 Register receiver, |
648 Register scratch1, | 624 Register scratch1, |
649 Register scratch2, | 625 Register scratch2, |
| 626 Register scratch3, |
650 Label* miss) { | 627 Label* miss) { |
651 ASSERT(holder->HasNamedInterceptor()); | 628 ASSERT(holder->HasNamedInterceptor()); |
652 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 629 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
653 | 630 |
654 // Check that the receiver isn't a smi. | 631 // Check that the receiver isn't a smi. |
655 __ BranchOnSmi(receiver, miss); | 632 __ BranchOnSmi(receiver, miss); |
656 | 633 |
657 CallOptimization optimization(lookup); | 634 CallOptimization optimization(lookup); |
658 | 635 |
659 if (optimization.is_constant_call()) { | 636 if (optimization.is_constant_call()) { |
660 CompileCacheable(masm, | 637 CompileCacheable(masm, |
661 object, | 638 object, |
662 receiver, | 639 receiver, |
663 scratch1, | 640 scratch1, |
664 scratch2, | 641 scratch2, |
| 642 scratch3, |
665 holder, | 643 holder, |
666 lookup, | 644 lookup, |
667 name, | 645 name, |
668 optimization, | 646 optimization, |
669 miss); | 647 miss); |
670 } else { | 648 } else { |
671 CompileRegular(masm, | 649 CompileRegular(masm, |
672 object, | 650 object, |
673 receiver, | 651 receiver, |
674 scratch1, | 652 scratch1, |
675 scratch2, | 653 scratch2, |
| 654 scratch3, |
676 name, | 655 name, |
677 holder, | 656 holder, |
678 miss); | 657 miss); |
679 } | 658 } |
680 } | 659 } |
681 | 660 |
682 private: | 661 private: |
683 void CompileCacheable(MacroAssembler* masm, | 662 void CompileCacheable(MacroAssembler* masm, |
684 JSObject* object, | 663 JSObject* object, |
685 Register receiver, | 664 Register receiver, |
686 Register scratch1, | 665 Register scratch1, |
687 Register scratch2, | 666 Register scratch2, |
| 667 Register scratch3, |
688 JSObject* interceptor_holder, | 668 JSObject* interceptor_holder, |
689 LookupResult* lookup, | 669 LookupResult* lookup, |
690 String* name, | 670 String* name, |
691 const CallOptimization& optimization, | 671 const CallOptimization& optimization, |
692 Label* miss_label) { | 672 Label* miss_label) { |
693 ASSERT(optimization.is_constant_call()); | 673 ASSERT(optimization.is_constant_call()); |
694 ASSERT(!lookup->holder()->IsGlobalObject()); | 674 ASSERT(!lookup->holder()->IsGlobalObject()); |
695 | 675 |
696 int depth1 = kInvalidProtoDepth; | 676 int depth1 = kInvalidProtoDepth; |
697 int depth2 = kInvalidProtoDepth; | 677 int depth2 = kInvalidProtoDepth; |
(...skipping 21 matching lines...) Expand all Loading... |
719 ReserveSpaceForFastApiCall(masm, scratch1); | 699 ReserveSpaceForFastApiCall(masm, scratch1); |
720 } | 700 } |
721 | 701 |
722 // Check that the maps from receiver to interceptor's holder | 702 // Check that the maps from receiver to interceptor's holder |
723 // haven't changed and thus we can invoke interceptor. | 703 // haven't changed and thus we can invoke interceptor. |
724 Label miss_cleanup; | 704 Label miss_cleanup; |
725 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; | 705 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; |
726 Register holder = | 706 Register holder = |
727 stub_compiler_->CheckPrototypes(object, receiver, | 707 stub_compiler_->CheckPrototypes(object, receiver, |
728 interceptor_holder, scratch1, | 708 interceptor_holder, scratch1, |
729 scratch2, name, depth1, miss); | 709 scratch2, scratch3, name, depth1, miss); |
730 | 710 |
731 // Invoke an interceptor and if it provides a value, | 711 // Invoke an interceptor and if it provides a value, |
732 // branch to |regular_invoke|. | 712 // branch to |regular_invoke|. |
733 Label regular_invoke; | 713 Label regular_invoke; |
734 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2, | 714 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2, |
735 ®ular_invoke); | 715 ®ular_invoke); |
736 | 716 |
737 // Interceptor returned nothing for this property. Try to use cached | 717 // Interceptor returned nothing for this property. Try to use cached |
738 // constant function. | 718 // constant function. |
739 | 719 |
740 // Check that the maps from interceptor's holder to constant function's | 720 // Check that the maps from interceptor's holder to constant function's |
741 // holder haven't changed and thus we can use cached constant function. | 721 // holder haven't changed and thus we can use cached constant function. |
742 if (interceptor_holder != lookup->holder()) { | 722 if (interceptor_holder != lookup->holder()) { |
743 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, | 723 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, |
744 lookup->holder(), scratch1, | 724 lookup->holder(), scratch1, |
745 scratch2, name, depth2, miss); | 725 scratch2, scratch3, name, depth2, miss); |
746 } else { | 726 } else { |
747 // CheckPrototypes has a side effect of fetching a 'holder' | 727 // CheckPrototypes has a side effect of fetching a 'holder' |
748 // for API (object which is instanceof for the signature). It's | 728 // for API (object which is instanceof for the signature). It's |
749 // safe to omit it here, as if present, it should be fetched | 729 // safe to omit it here, as if present, it should be fetched |
750 // by the previous CheckPrototypes. | 730 // by the previous CheckPrototypes. |
751 ASSERT(depth2 == kInvalidProtoDepth); | 731 ASSERT(depth2 == kInvalidProtoDepth); |
752 } | 732 } |
753 | 733 |
754 // Invoke function. | 734 // Invoke function. |
755 if (can_do_fast_api_call) { | 735 if (can_do_fast_api_call) { |
(...skipping 15 matching lines...) Expand all Loading... |
771 if (can_do_fast_api_call) { | 751 if (can_do_fast_api_call) { |
772 FreeSpaceForFastApiCall(masm); | 752 FreeSpaceForFastApiCall(masm); |
773 } | 753 } |
774 } | 754 } |
775 | 755 |
776 void CompileRegular(MacroAssembler* masm, | 756 void CompileRegular(MacroAssembler* masm, |
777 JSObject* object, | 757 JSObject* object, |
778 Register receiver, | 758 Register receiver, |
779 Register scratch1, | 759 Register scratch1, |
780 Register scratch2, | 760 Register scratch2, |
| 761 Register scratch3, |
781 String* name, | 762 String* name, |
782 JSObject* interceptor_holder, | 763 JSObject* interceptor_holder, |
783 Label* miss_label) { | 764 Label* miss_label) { |
784 Register holder = | 765 Register holder = |
785 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 766 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, |
786 scratch1, scratch2, name, | 767 scratch1, scratch2, scratch3, name, |
787 miss_label); | 768 miss_label); |
788 | 769 |
789 // Call a runtime function to load the interceptor property. | 770 // Call a runtime function to load the interceptor property. |
790 __ EnterInternalFrame(); | 771 __ EnterInternalFrame(); |
791 // Save the name_ register across the call. | 772 // Save the name_ register across the call. |
792 __ push(name_); | 773 __ push(name_); |
793 | 774 |
794 PushInterceptorArguments(masm, | 775 PushInterceptorArguments(masm, |
795 receiver, | 776 receiver, |
796 holder, | 777 holder, |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
861 | 842 |
862 | 843 |
863 #undef __ | 844 #undef __ |
864 #define __ ACCESS_MASM(masm()) | 845 #define __ ACCESS_MASM(masm()) |
865 | 846 |
866 | 847 |
867 Register StubCompiler::CheckPrototypes(JSObject* object, | 848 Register StubCompiler::CheckPrototypes(JSObject* object, |
868 Register object_reg, | 849 Register object_reg, |
869 JSObject* holder, | 850 JSObject* holder, |
870 Register holder_reg, | 851 Register holder_reg, |
871 Register scratch, | 852 Register scratch1, |
| 853 Register scratch2, |
872 String* name, | 854 String* name, |
873 int save_at_depth, | 855 int save_at_depth, |
874 Label* miss, | 856 Label* miss) { |
875 Register extra) { | 857 // Make sure there's no overlap between holder and object registers. |
876 // Make sure there's no overlap between scratch and the other | 858 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
877 // registers. | 859 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
878 ASSERT(!scratch.is(object_reg) && !scratch.is(holder_reg)); | 860 && !scratch2.is(scratch1)); |
879 | 861 |
880 // Keep track of the current object in register reg. | 862 // Keep track of the current object in register reg. |
881 Register reg = object_reg; | 863 Register reg = object_reg; |
882 int depth = 0; | 864 int depth = 0; |
883 | 865 |
884 if (save_at_depth == depth) { | 866 if (save_at_depth == depth) { |
885 __ str(reg, MemOperand(sp)); | 867 __ str(reg, MemOperand(sp)); |
886 } | 868 } |
887 | 869 |
888 // Check the maps in the prototype chain. | 870 // Check the maps in the prototype chain. |
(...skipping 19 matching lines...) Expand all Loading... |
908 name = String::cast(lookup_result); | 890 name = String::cast(lookup_result); |
909 } | 891 } |
910 } | 892 } |
911 ASSERT(current->property_dictionary()->FindEntry(name) == | 893 ASSERT(current->property_dictionary()->FindEntry(name) == |
912 StringDictionary::kNotFound); | 894 StringDictionary::kNotFound); |
913 | 895 |
914 GenerateDictionaryNegativeLookup(masm(), | 896 GenerateDictionaryNegativeLookup(masm(), |
915 miss, | 897 miss, |
916 reg, | 898 reg, |
917 name, | 899 name, |
918 scratch, | 900 scratch1, |
919 extra); | 901 scratch2); |
920 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); | 902 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
921 reg = holder_reg; // from now the object is in holder_reg | 903 reg = holder_reg; // from now the object is in holder_reg |
922 __ ldr(reg, FieldMemOperand(scratch, Map::kPrototypeOffset)); | 904 __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
923 } else { | 905 } else { |
924 // Get the map of the current object. | 906 // Get the map of the current object. |
925 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); | 907 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
926 __ cmp(scratch, Operand(Handle<Map>(current->map()))); | 908 __ cmp(scratch1, Operand(Handle<Map>(current->map()))); |
927 | 909 |
928 // Branch on the result of the map check. | 910 // Branch on the result of the map check. |
929 __ b(ne, miss); | 911 __ b(ne, miss); |
930 | 912 |
931 // Check access rights to the global object. This has to happen | 913 // Check access rights to the global object. This has to happen |
932 // after the map check so that we know that the object is | 914 // after the map check so that we know that the object is |
933 // actually a global object. | 915 // actually a global object. |
934 if (current->IsJSGlobalProxy()) { | 916 if (current->IsJSGlobalProxy()) { |
935 __ CheckAccessGlobalProxy(reg, scratch, miss); | 917 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
936 // Restore scratch register to be the map of the object. In the | 918 // Restore scratch register to be the map of the object. In the |
937 // new space case below, we load the prototype from the map in | 919 // new space case below, we load the prototype from the map in |
938 // the scratch register. | 920 // the scratch register. |
939 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); | 921 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
940 } | 922 } |
941 | 923 |
942 reg = holder_reg; // from now the object is in holder_reg | 924 reg = holder_reg; // from now the object is in holder_reg |
943 if (Heap::InNewSpace(prototype)) { | 925 if (Heap::InNewSpace(prototype)) { |
944 // The prototype is in new space; we cannot store a reference | 926 // The prototype is in new space; we cannot store a reference |
945 // to it in the code. Load it from the map. | 927 // to it in the code. Load it from the map. |
946 __ ldr(reg, FieldMemOperand(scratch, Map::kPrototypeOffset)); | 928 __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
947 } else { | 929 } else { |
948 // The prototype is in old space; load it directly. | 930 // The prototype is in old space; load it directly. |
949 __ mov(reg, Operand(Handle<JSObject>(prototype))); | 931 __ mov(reg, Operand(Handle<JSObject>(prototype))); |
950 } | 932 } |
951 } | 933 } |
952 | 934 |
953 if (save_at_depth == depth) { | 935 if (save_at_depth == depth) { |
954 __ str(reg, MemOperand(sp)); | 936 __ str(reg, MemOperand(sp)); |
955 } | 937 } |
956 | 938 |
957 // Go to the next object in the prototype chain. | 939 // Go to the next object in the prototype chain. |
958 current = prototype; | 940 current = prototype; |
959 } | 941 } |
960 | 942 |
961 // Check the holder map. | 943 // Check the holder map. |
962 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); | 944 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
963 __ cmp(scratch, Operand(Handle<Map>(current->map()))); | 945 __ cmp(scratch1, Operand(Handle<Map>(current->map()))); |
964 __ b(ne, miss); | 946 __ b(ne, miss); |
965 | 947 |
966 // Log the check depth. | 948 // Log the check depth. |
967 LOG(IntEvent("check-maps-depth", depth + 1)); | 949 LOG(IntEvent("check-maps-depth", depth + 1)); |
968 | 950 |
969 // Perform security check for access to the global object and return | 951 // Perform security check for access to the global object and return |
970 // the holder register. | 952 // the holder register. |
971 ASSERT(current == holder); | 953 ASSERT(current == holder); |
972 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | 954 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); |
973 if (current->IsJSGlobalProxy()) { | 955 if (current->IsJSGlobalProxy()) { |
974 __ CheckAccessGlobalProxy(reg, scratch, miss); | 956 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
975 } | 957 } |
976 | 958 |
977 // If we've skipped any global objects, it's not enough to verify | 959 // If we've skipped any global objects, it's not enough to verify |
978 // that their maps haven't changed. We also need to check that the | 960 // that their maps haven't changed. We also need to check that the |
979 // property cell for the property is still empty. | 961 // property cell for the property is still empty. |
980 current = object; | 962 current = object; |
981 while (current != holder) { | 963 while (current != holder) { |
982 if (current->IsGlobalObject()) { | 964 if (current->IsGlobalObject()) { |
983 Object* cell = GenerateCheckPropertyCell(masm(), | 965 Object* cell = GenerateCheckPropertyCell(masm(), |
984 GlobalObject::cast(current), | 966 GlobalObject::cast(current), |
985 name, | 967 name, |
986 scratch, | 968 scratch1, |
987 miss); | 969 miss); |
988 if (cell->IsFailure()) { | 970 if (cell->IsFailure()) { |
989 set_failure(Failure::cast(cell)); | 971 set_failure(Failure::cast(cell)); |
990 return reg; | 972 return reg; |
991 } | 973 } |
992 } | 974 } |
993 current = JSObject::cast(current->GetPrototype()); | 975 current = JSObject::cast(current->GetPrototype()); |
994 } | 976 } |
995 | 977 |
996 // Return the register containing the holder. | 978 // Return the register containing the holder. |
997 return reg; | 979 return reg; |
998 } | 980 } |
999 | 981 |
1000 | 982 |
1001 void StubCompiler::GenerateLoadField(JSObject* object, | 983 void StubCompiler::GenerateLoadField(JSObject* object, |
1002 JSObject* holder, | 984 JSObject* holder, |
1003 Register receiver, | 985 Register receiver, |
1004 Register scratch1, | 986 Register scratch1, |
1005 Register scratch2, | 987 Register scratch2, |
| 988 Register scratch3, |
1006 int index, | 989 int index, |
1007 String* name, | 990 String* name, |
1008 Label* miss) { | 991 Label* miss) { |
1009 // Check that the receiver isn't a smi. | 992 // Check that the receiver isn't a smi. |
1010 __ tst(receiver, Operand(kSmiTagMask)); | 993 __ tst(receiver, Operand(kSmiTagMask)); |
1011 __ b(eq, miss); | 994 __ b(eq, miss); |
1012 | 995 |
1013 // Check that the maps haven't changed. | 996 // Check that the maps haven't changed. |
1014 Register reg = | 997 Register reg = |
1015 CheckPrototypes(object, receiver, holder, scratch1, scratch2, name, miss); | 998 CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, |
| 999 name, miss); |
1016 GenerateFastPropertyLoad(masm(), r0, reg, holder, index); | 1000 GenerateFastPropertyLoad(masm(), r0, reg, holder, index); |
1017 __ Ret(); | 1001 __ Ret(); |
1018 } | 1002 } |
1019 | 1003 |
1020 | 1004 |
1021 void StubCompiler::GenerateLoadConstant(JSObject* object, | 1005 void StubCompiler::GenerateLoadConstant(JSObject* object, |
1022 JSObject* holder, | 1006 JSObject* holder, |
1023 Register receiver, | 1007 Register receiver, |
1024 Register scratch1, | 1008 Register scratch1, |
1025 Register scratch2, | 1009 Register scratch2, |
| 1010 Register scratch3, |
1026 Object* value, | 1011 Object* value, |
1027 String* name, | 1012 String* name, |
1028 Label* miss) { | 1013 Label* miss) { |
1029 // Check that the receiver isn't a smi. | 1014 // Check that the receiver isn't a smi. |
1030 __ tst(receiver, Operand(kSmiTagMask)); | 1015 __ tst(receiver, Operand(kSmiTagMask)); |
1031 __ b(eq, miss); | 1016 __ b(eq, miss); |
1032 | 1017 |
1033 // Check that the maps haven't changed. | 1018 // Check that the maps haven't changed. |
1034 Register reg = | 1019 Register reg = |
1035 CheckPrototypes(object, receiver, holder, scratch1, scratch2, name, miss); | 1020 CheckPrototypes(object, receiver, holder, |
| 1021 scratch1, scratch2, scratch3, name, miss); |
1036 | 1022 |
1037 // Return the constant value. | 1023 // Return the constant value. |
1038 __ mov(r0, Operand(Handle<Object>(value))); | 1024 __ mov(r0, Operand(Handle<Object>(value))); |
1039 __ Ret(); | 1025 __ Ret(); |
1040 } | 1026 } |
1041 | 1027 |
1042 | 1028 |
1043 bool StubCompiler::GenerateLoadCallback(JSObject* object, | 1029 bool StubCompiler::GenerateLoadCallback(JSObject* object, |
1044 JSObject* holder, | 1030 JSObject* holder, |
1045 Register receiver, | 1031 Register receiver, |
1046 Register name_reg, | 1032 Register name_reg, |
1047 Register scratch1, | 1033 Register scratch1, |
1048 Register scratch2, | 1034 Register scratch2, |
| 1035 Register scratch3, |
1049 AccessorInfo* callback, | 1036 AccessorInfo* callback, |
1050 String* name, | 1037 String* name, |
1051 Label* miss, | 1038 Label* miss, |
1052 Failure** failure) { | 1039 Failure** failure) { |
1053 // Check that the receiver isn't a smi. | 1040 // Check that the receiver isn't a smi. |
1054 __ tst(receiver, Operand(kSmiTagMask)); | 1041 __ tst(receiver, Operand(kSmiTagMask)); |
1055 __ b(eq, miss); | 1042 __ b(eq, miss); |
1056 | 1043 |
1057 // Check that the maps haven't changed. | 1044 // Check that the maps haven't changed. |
1058 Register reg = | 1045 Register reg = |
1059 CheckPrototypes(object, receiver, holder, scratch1, scratch2, name, miss); | 1046 CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, |
| 1047 name, miss); |
1060 | 1048 |
1061 // Push the arguments on the JS stack of the caller. | 1049 // Push the arguments on the JS stack of the caller. |
1062 __ push(receiver); // Receiver. | 1050 __ push(receiver); // Receiver. |
1063 __ push(reg); // Holder. | 1051 __ push(reg); // Holder. |
1064 __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback data | 1052 __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback data |
1065 __ ldr(reg, FieldMemOperand(ip, AccessorInfo::kDataOffset)); | 1053 __ ldr(reg, FieldMemOperand(ip, AccessorInfo::kDataOffset)); |
1066 __ Push(ip, reg, name_reg); | 1054 __ Push(ip, reg, name_reg); |
1067 | 1055 |
1068 // Do tail-call to the runtime system. | 1056 // Do tail-call to the runtime system. |
1069 ExternalReference load_callback_property = | 1057 ExternalReference load_callback_property = |
1070 ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); | 1058 ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); |
1071 __ TailCallExternalReference(load_callback_property, 5, 1); | 1059 __ TailCallExternalReference(load_callback_property, 5, 1); |
1072 | 1060 |
1073 return true; | 1061 return true; |
1074 } | 1062 } |
1075 | 1063 |
1076 | 1064 |
1077 void StubCompiler::GenerateLoadInterceptor(JSObject* object, | 1065 void StubCompiler::GenerateLoadInterceptor(JSObject* object, |
1078 JSObject* interceptor_holder, | 1066 JSObject* interceptor_holder, |
1079 LookupResult* lookup, | 1067 LookupResult* lookup, |
1080 Register receiver, | 1068 Register receiver, |
1081 Register name_reg, | 1069 Register name_reg, |
1082 Register scratch1, | 1070 Register scratch1, |
1083 Register scratch2, | 1071 Register scratch2, |
| 1072 Register scratch3, |
1084 String* name, | 1073 String* name, |
1085 Label* miss) { | 1074 Label* miss) { |
1086 ASSERT(interceptor_holder->HasNamedInterceptor()); | 1075 ASSERT(interceptor_holder->HasNamedInterceptor()); |
1087 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 1076 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
1088 | 1077 |
1089 // Check that the receiver isn't a smi. | 1078 // Check that the receiver isn't a smi. |
1090 __ BranchOnSmi(receiver, miss); | 1079 __ BranchOnSmi(receiver, miss); |
1091 | 1080 |
1092 // So far the most popular follow ups for interceptor loads are FIELD | 1081 // So far the most popular follow ups for interceptor loads are FIELD |
1093 // and CALLBACKS, so inline only them, other cases may be added | 1082 // and CALLBACKS, so inline only them, other cases may be added |
1094 // later. | 1083 // later. |
1095 bool compile_followup_inline = false; | 1084 bool compile_followup_inline = false; |
1096 if (lookup->IsProperty() && lookup->IsCacheable()) { | 1085 if (lookup->IsProperty() && lookup->IsCacheable()) { |
1097 if (lookup->type() == FIELD) { | 1086 if (lookup->type() == FIELD) { |
1098 compile_followup_inline = true; | 1087 compile_followup_inline = true; |
1099 } else if (lookup->type() == CALLBACKS && | 1088 } else if (lookup->type() == CALLBACKS && |
1100 lookup->GetCallbackObject()->IsAccessorInfo() && | 1089 lookup->GetCallbackObject()->IsAccessorInfo() && |
1101 AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL) { | 1090 AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL) { |
1102 compile_followup_inline = true; | 1091 compile_followup_inline = true; |
1103 } | 1092 } |
1104 } | 1093 } |
1105 | 1094 |
1106 if (compile_followup_inline) { | 1095 if (compile_followup_inline) { |
1107 // Compile the interceptor call, followed by inline code to load the | 1096 // Compile the interceptor call, followed by inline code to load the |
1108 // property from further up the prototype chain if the call fails. | 1097 // property from further up the prototype chain if the call fails. |
1109 // Check that the maps haven't changed. | 1098 // Check that the maps haven't changed. |
1110 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, | 1099 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, |
1111 scratch1, scratch2, name, miss); | 1100 scratch1, scratch2, scratch3, |
| 1101 name, miss); |
1112 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); | 1102 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); |
1113 | 1103 |
1114 // Save necessary data before invoking an interceptor. | 1104 // Save necessary data before invoking an interceptor. |
1115 // Requires a frame to make GC aware of pushed pointers. | 1105 // Requires a frame to make GC aware of pushed pointers. |
1116 __ EnterInternalFrame(); | 1106 __ EnterInternalFrame(); |
1117 | 1107 |
1118 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { | 1108 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { |
1119 // CALLBACKS case needs a receiver to be passed into C++ callback. | 1109 // CALLBACKS case needs a receiver to be passed into C++ callback. |
1120 __ Push(receiver, holder_reg, name_reg); | 1110 __ Push(receiver, holder_reg, name_reg); |
1121 } else { | 1111 } else { |
(...skipping 28 matching lines...) Expand all Loading... |
1150 __ LeaveInternalFrame(); | 1140 __ LeaveInternalFrame(); |
1151 | 1141 |
1152 // Check that the maps from interceptor's holder to lookup's holder | 1142 // Check that the maps from interceptor's holder to lookup's holder |
1153 // haven't changed. And load lookup's holder into |holder| register. | 1143 // haven't changed. And load lookup's holder into |holder| register. |
1154 if (interceptor_holder != lookup->holder()) { | 1144 if (interceptor_holder != lookup->holder()) { |
1155 holder_reg = CheckPrototypes(interceptor_holder, | 1145 holder_reg = CheckPrototypes(interceptor_holder, |
1156 holder_reg, | 1146 holder_reg, |
1157 lookup->holder(), | 1147 lookup->holder(), |
1158 scratch1, | 1148 scratch1, |
1159 scratch2, | 1149 scratch2, |
| 1150 scratch3, |
1160 name, | 1151 name, |
1161 miss); | 1152 miss); |
1162 } | 1153 } |
1163 | 1154 |
1164 if (lookup->type() == FIELD) { | 1155 if (lookup->type() == FIELD) { |
1165 // We found FIELD property in prototype chain of interceptor's holder. | 1156 // We found FIELD property in prototype chain of interceptor's holder. |
1166 // Retrieve a field from field's holder. | 1157 // Retrieve a field from field's holder. |
1167 GenerateFastPropertyLoad(masm(), r0, holder_reg, | 1158 GenerateFastPropertyLoad(masm(), r0, holder_reg, |
1168 lookup->holder(), lookup->GetFieldIndex()); | 1159 lookup->holder(), lookup->GetFieldIndex()); |
1169 __ Ret(); | 1160 __ Ret(); |
(...skipping 25 matching lines...) Expand all Loading... |
1195 } | 1186 } |
1196 | 1187 |
1197 ExternalReference ref = | 1188 ExternalReference ref = |
1198 ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); | 1189 ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); |
1199 __ TailCallExternalReference(ref, 5, 1); | 1190 __ TailCallExternalReference(ref, 5, 1); |
1200 } | 1191 } |
1201 } else { // !compile_followup_inline | 1192 } else { // !compile_followup_inline |
1202 // Call the runtime system to load the interceptor. | 1193 // Call the runtime system to load the interceptor. |
1203 // Check that the maps haven't changed. | 1194 // Check that the maps haven't changed. |
1204 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, | 1195 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, |
1205 scratch1, scratch2, name, miss); | 1196 scratch1, scratch2, scratch3, |
| 1197 name, miss); |
1206 PushInterceptorArguments(masm(), receiver, holder_reg, | 1198 PushInterceptorArguments(masm(), receiver, holder_reg, |
1207 name_reg, interceptor_holder); | 1199 name_reg, interceptor_holder); |
1208 | 1200 |
1209 ExternalReference ref = ExternalReference( | 1201 ExternalReference ref = ExternalReference( |
1210 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); | 1202 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); |
1211 __ TailCallExternalReference(ref, 5, 1); | 1203 __ TailCallExternalReference(ref, 5, 1); |
1212 } | 1204 } |
1213 } | 1205 } |
1214 | 1206 |
1215 | 1207 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1273 | 1265 |
1274 const int argc = arguments().immediate(); | 1266 const int argc = arguments().immediate(); |
1275 | 1267 |
1276 // Get the receiver of the function from the stack into r0. | 1268 // Get the receiver of the function from the stack into r0. |
1277 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | 1269 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
1278 // Check that the receiver isn't a smi. | 1270 // Check that the receiver isn't a smi. |
1279 __ tst(r0, Operand(kSmiTagMask)); | 1271 __ tst(r0, Operand(kSmiTagMask)); |
1280 __ b(eq, &miss); | 1272 __ b(eq, &miss); |
1281 | 1273 |
1282 // Do the right check and compute the holder register. | 1274 // Do the right check and compute the holder register. |
1283 Register reg = CheckPrototypes(object, r0, holder, r1, r3, name, &miss, r4); | 1275 Register reg = CheckPrototypes(object, r0, holder, r1, r3, r4, name, &miss); |
1284 GenerateFastPropertyLoad(masm(), r1, reg, holder, index); | 1276 GenerateFastPropertyLoad(masm(), r1, reg, holder, index); |
1285 | 1277 |
1286 GenerateCallFunction(masm(), object, arguments(), &miss); | 1278 GenerateCallFunction(masm(), object, arguments(), &miss); |
1287 | 1279 |
1288 // Handle call cache miss. | 1280 // Handle call cache miss. |
1289 __ bind(&miss); | 1281 __ bind(&miss); |
1290 GenerateMissBranch(); | 1282 GenerateMissBranch(); |
1291 | 1283 |
1292 // Return the generated code. | 1284 // Return the generated code. |
1293 return GetCode(FIELD, name); | 1285 return GetCode(FIELD, name); |
(...skipping 24 matching lines...) Expand all Loading... |
1318 | 1310 |
1319 // Get the receiver from the stack | 1311 // Get the receiver from the stack |
1320 const int argc = arguments().immediate(); | 1312 const int argc = arguments().immediate(); |
1321 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 1313 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
1322 | 1314 |
1323 // Check that the receiver isn't a smi. | 1315 // Check that the receiver isn't a smi. |
1324 __ tst(r1, Operand(kSmiTagMask)); | 1316 __ tst(r1, Operand(kSmiTagMask)); |
1325 __ b(eq, &miss); | 1317 __ b(eq, &miss); |
1326 | 1318 |
1327 // Check that the maps haven't changed. | 1319 // Check that the maps haven't changed. |
1328 CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, name, &miss, r4); | 1320 CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, r4, name, &miss); |
1329 | 1321 |
1330 if (object->IsGlobalObject()) { | 1322 if (object->IsGlobalObject()) { |
1331 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | 1323 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
1332 __ str(r3, MemOperand(sp, argc * kPointerSize)); | 1324 __ str(r3, MemOperand(sp, argc * kPointerSize)); |
1333 } | 1325 } |
1334 | 1326 |
1335 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush), | 1327 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush), |
1336 argc + 1, | 1328 argc + 1, |
1337 1); | 1329 1); |
1338 | 1330 |
(...skipping 30 matching lines...) Expand all Loading... |
1369 | 1361 |
1370 // Get the receiver from the stack | 1362 // Get the receiver from the stack |
1371 const int argc = arguments().immediate(); | 1363 const int argc = arguments().immediate(); |
1372 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 1364 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
1373 | 1365 |
1374 // Check that the receiver isn't a smi. | 1366 // Check that the receiver isn't a smi. |
1375 __ tst(r1, Operand(kSmiTagMask)); | 1367 __ tst(r1, Operand(kSmiTagMask)); |
1376 __ b(eq, &miss); | 1368 __ b(eq, &miss); |
1377 | 1369 |
1378 // Check that the maps haven't changed. | 1370 // Check that the maps haven't changed. |
1379 CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, name, &miss, r4); | 1371 CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, r4, name, &miss); |
1380 | 1372 |
1381 if (object->IsGlobalObject()) { | 1373 if (object->IsGlobalObject()) { |
1382 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | 1374 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
1383 __ str(r3, MemOperand(sp, argc * kPointerSize)); | 1375 __ str(r3, MemOperand(sp, argc * kPointerSize)); |
1384 } | 1376 } |
1385 | 1377 |
1386 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop), | 1378 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop), |
1387 argc + 1, | 1379 argc + 1, |
1388 1); | 1380 1); |
1389 | 1381 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1466 depth = optimization.GetPrototypeDepthOfExpectedType( | 1458 depth = optimization.GetPrototypeDepthOfExpectedType( |
1467 JSObject::cast(object), holder); | 1459 JSObject::cast(object), holder); |
1468 } | 1460 } |
1469 | 1461 |
1470 if (depth != kInvalidProtoDepth) { | 1462 if (depth != kInvalidProtoDepth) { |
1471 __ IncrementCounter(&Counters::call_const_fast_api, 1, r0, r3); | 1463 __ IncrementCounter(&Counters::call_const_fast_api, 1, r0, r3); |
1472 ReserveSpaceForFastApiCall(masm(), r0); | 1464 ReserveSpaceForFastApiCall(masm(), r0); |
1473 } | 1465 } |
1474 | 1466 |
1475 // Check that the maps haven't changed. | 1467 // Check that the maps haven't changed. |
1476 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, name, | 1468 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, |
1477 depth, &miss, r4); | 1469 depth, &miss); |
1478 | 1470 |
1479 // Patch the receiver on the stack with the global proxy if | 1471 // Patch the receiver on the stack with the global proxy if |
1480 // necessary. | 1472 // necessary. |
1481 if (object->IsGlobalObject()) { | 1473 if (object->IsGlobalObject()) { |
1482 ASSERT(depth == kInvalidProtoDepth); | 1474 ASSERT(depth == kInvalidProtoDepth); |
1483 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | 1475 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
1484 __ str(r3, MemOperand(sp, argc * kPointerSize)); | 1476 __ str(r3, MemOperand(sp, argc * kPointerSize)); |
1485 } | 1477 } |
1486 break; | 1478 break; |
1487 | 1479 |
1488 case STRING_CHECK: | 1480 case STRING_CHECK: |
1489 if (!function->IsBuiltin()) { | 1481 if (!function->IsBuiltin()) { |
1490 // Calling non-builtins with a value as receiver requires boxing. | 1482 // Calling non-builtins with a value as receiver requires boxing. |
1491 __ jmp(&miss); | 1483 __ jmp(&miss); |
1492 } else { | 1484 } else { |
1493 // Check that the object is a two-byte string or a symbol. | 1485 // Check that the object is a two-byte string or a symbol. |
1494 __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE); | 1486 __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE); |
1495 __ b(hs, &miss); | 1487 __ b(hs, &miss); |
1496 // Check that the maps starting from the prototype haven't changed. | 1488 // Check that the maps starting from the prototype haven't changed. |
1497 GenerateDirectLoadGlobalFunctionPrototype( | 1489 GenerateDirectLoadGlobalFunctionPrototype( |
1498 masm(), Context::STRING_FUNCTION_INDEX, r0); | 1490 masm(), Context::STRING_FUNCTION_INDEX, r0); |
1499 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, | 1491 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, |
1500 r1, name, &miss, r4); | 1492 r1, r4, name, &miss); |
1501 } | 1493 } |
1502 break; | 1494 break; |
1503 | 1495 |
1504 case NUMBER_CHECK: { | 1496 case NUMBER_CHECK: { |
1505 if (!function->IsBuiltin()) { | 1497 if (!function->IsBuiltin()) { |
1506 // Calling non-builtins with a value as receiver requires boxing. | 1498 // Calling non-builtins with a value as receiver requires boxing. |
1507 __ jmp(&miss); | 1499 __ jmp(&miss); |
1508 } else { | 1500 } else { |
1509 Label fast; | 1501 Label fast; |
1510 // Check that the object is a smi or a heap number. | 1502 // Check that the object is a smi or a heap number. |
1511 __ tst(r1, Operand(kSmiTagMask)); | 1503 __ tst(r1, Operand(kSmiTagMask)); |
1512 __ b(eq, &fast); | 1504 __ b(eq, &fast); |
1513 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE); | 1505 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE); |
1514 __ b(ne, &miss); | 1506 __ b(ne, &miss); |
1515 __ bind(&fast); | 1507 __ bind(&fast); |
1516 // Check that the maps starting from the prototype haven't changed. | 1508 // Check that the maps starting from the prototype haven't changed. |
1517 GenerateDirectLoadGlobalFunctionPrototype( | 1509 GenerateDirectLoadGlobalFunctionPrototype( |
1518 masm(), Context::NUMBER_FUNCTION_INDEX, r0); | 1510 masm(), Context::NUMBER_FUNCTION_INDEX, r0); |
1519 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, | 1511 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, |
1520 r1, name, &miss, r4); | 1512 r1, r4, name, &miss); |
1521 } | 1513 } |
1522 break; | 1514 break; |
1523 } | 1515 } |
1524 | 1516 |
1525 case BOOLEAN_CHECK: { | 1517 case BOOLEAN_CHECK: { |
1526 if (!function->IsBuiltin()) { | 1518 if (!function->IsBuiltin()) { |
1527 // Calling non-builtins with a value as receiver requires boxing. | 1519 // Calling non-builtins with a value as receiver requires boxing. |
1528 __ jmp(&miss); | 1520 __ jmp(&miss); |
1529 } else { | 1521 } else { |
1530 Label fast; | 1522 Label fast; |
1531 // Check that the object is a boolean. | 1523 // Check that the object is a boolean. |
1532 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 1524 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
1533 __ cmp(r1, ip); | 1525 __ cmp(r1, ip); |
1534 __ b(eq, &fast); | 1526 __ b(eq, &fast); |
1535 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 1527 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
1536 __ cmp(r1, ip); | 1528 __ cmp(r1, ip); |
1537 __ b(ne, &miss); | 1529 __ b(ne, &miss); |
1538 __ bind(&fast); | 1530 __ bind(&fast); |
1539 // Check that the maps starting from the prototype haven't changed. | 1531 // Check that the maps starting from the prototype haven't changed. |
1540 GenerateDirectLoadGlobalFunctionPrototype( | 1532 GenerateDirectLoadGlobalFunctionPrototype( |
1541 masm(), Context::BOOLEAN_FUNCTION_INDEX, r0); | 1533 masm(), Context::BOOLEAN_FUNCTION_INDEX, r0); |
1542 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, | 1534 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, |
1543 r1, name, &miss, r4); | 1535 r1, r4, name, &miss); |
1544 } | 1536 } |
1545 break; | 1537 break; |
1546 } | 1538 } |
1547 | 1539 |
1548 default: | 1540 default: |
1549 UNREACHABLE(); | 1541 UNREACHABLE(); |
1550 } | 1542 } |
1551 | 1543 |
1552 if (depth != kInvalidProtoDepth) { | 1544 if (depth != kInvalidProtoDepth) { |
1553 GenerateFastApiCall(masm(), optimization, argc); | 1545 GenerateFastApiCall(masm(), optimization, argc); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1592 | 1584 |
1593 CallInterceptorCompiler compiler(this, arguments(), r2); | 1585 CallInterceptorCompiler compiler(this, arguments(), r2); |
1594 compiler.Compile(masm(), | 1586 compiler.Compile(masm(), |
1595 object, | 1587 object, |
1596 holder, | 1588 holder, |
1597 name, | 1589 name, |
1598 &lookup, | 1590 &lookup, |
1599 r1, | 1591 r1, |
1600 r3, | 1592 r3, |
1601 r4, | 1593 r4, |
| 1594 r0, |
1602 &miss); | 1595 &miss); |
1603 | 1596 |
1604 // Move returned value, the function to call, to r1. | 1597 // Move returned value, the function to call, to r1. |
1605 __ mov(r1, r0); | 1598 __ mov(r1, r0); |
1606 // Restore receiver. | 1599 // Restore receiver. |
1607 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | 1600 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
1608 | 1601 |
1609 GenerateCallFunction(masm(), object, arguments(), &miss); | 1602 GenerateCallFunction(masm(), object, arguments(), &miss); |
1610 | 1603 |
1611 // Handle call cache miss. | 1604 // Handle call cache miss. |
(...skipping 26 matching lines...) Expand all Loading... |
1638 | 1631 |
1639 // If the object is the holder then we know that it's a global | 1632 // If the object is the holder then we know that it's a global |
1640 // object which can only happen for contextual calls. In this case, | 1633 // object which can only happen for contextual calls. In this case, |
1641 // the receiver cannot be a smi. | 1634 // the receiver cannot be a smi. |
1642 if (object != holder) { | 1635 if (object != holder) { |
1643 __ tst(r0, Operand(kSmiTagMask)); | 1636 __ tst(r0, Operand(kSmiTagMask)); |
1644 __ b(eq, &miss); | 1637 __ b(eq, &miss); |
1645 } | 1638 } |
1646 | 1639 |
1647 // Check that the maps haven't changed. | 1640 // Check that the maps haven't changed. |
1648 CheckPrototypes(object, r0, holder, r3, r1, name, &miss, r4); | 1641 CheckPrototypes(object, r0, holder, r3, r1, r4, name, &miss); |
1649 | 1642 |
1650 // Get the value from the cell. | 1643 // Get the value from the cell. |
1651 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); | 1644 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); |
1652 __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); | 1645 __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); |
1653 | 1646 |
1654 // Check that the cell contains the same function. | 1647 // Check that the cell contains the same function. |
1655 if (Heap::InNewSpace(function)) { | 1648 if (Heap::InNewSpace(function)) { |
1656 // We can't embed a pointer to a function in new space so we have | 1649 // We can't embed a pointer to a function in new space so we have |
1657 // to verify that the shared function info is unchanged. This has | 1650 // to verify that the shared function info is unchanged. This has |
1658 // the nice side effect that multiple closures based on the same | 1651 // the nice side effect that multiple closures based on the same |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1862 // -- r0 : receiver | 1855 // -- r0 : receiver |
1863 // -- lr : return address | 1856 // -- lr : return address |
1864 // ----------------------------------- | 1857 // ----------------------------------- |
1865 Label miss; | 1858 Label miss; |
1866 | 1859 |
1867 // Check that receiver is not a smi. | 1860 // Check that receiver is not a smi. |
1868 __ tst(r0, Operand(kSmiTagMask)); | 1861 __ tst(r0, Operand(kSmiTagMask)); |
1869 __ b(eq, &miss); | 1862 __ b(eq, &miss); |
1870 | 1863 |
1871 // Check the maps of the full prototype chain. | 1864 // Check the maps of the full prototype chain. |
1872 CheckPrototypes(object, r0, last, r3, r1, name, &miss, r4); | 1865 CheckPrototypes(object, r0, last, r3, r1, r4, name, &miss); |
1873 | 1866 |
1874 // If the last object in the prototype chain is a global object, | 1867 // If the last object in the prototype chain is a global object, |
1875 // check that the global property cell is empty. | 1868 // check that the global property cell is empty. |
1876 if (last->IsGlobalObject()) { | 1869 if (last->IsGlobalObject()) { |
1877 Object* cell = GenerateCheckPropertyCell(masm(), | 1870 Object* cell = GenerateCheckPropertyCell(masm(), |
1878 GlobalObject::cast(last), | 1871 GlobalObject::cast(last), |
1879 name, | 1872 name, |
1880 r1, | 1873 r1, |
1881 &miss); | 1874 &miss); |
1882 if (cell->IsFailure()) return cell; | 1875 if (cell->IsFailure()) return cell; |
(...skipping 16 matching lines...) Expand all Loading... |
1899 JSObject* holder, | 1892 JSObject* holder, |
1900 int index, | 1893 int index, |
1901 String* name) { | 1894 String* name) { |
1902 // ----------- S t a t e ------------- | 1895 // ----------- S t a t e ------------- |
1903 // -- r0 : receiver | 1896 // -- r0 : receiver |
1904 // -- r2 : name | 1897 // -- r2 : name |
1905 // -- lr : return address | 1898 // -- lr : return address |
1906 // ----------------------------------- | 1899 // ----------------------------------- |
1907 Label miss; | 1900 Label miss; |
1908 | 1901 |
1909 GenerateLoadField(object, holder, r0, r3, r1, index, name, &miss); | 1902 GenerateLoadField(object, holder, r0, r3, r1, r4, index, name, &miss); |
1910 __ bind(&miss); | 1903 __ bind(&miss); |
1911 GenerateLoadMiss(masm(), Code::LOAD_IC); | 1904 GenerateLoadMiss(masm(), Code::LOAD_IC); |
1912 | 1905 |
1913 // Return the generated code. | 1906 // Return the generated code. |
1914 return GetCode(FIELD, name); | 1907 return GetCode(FIELD, name); |
1915 } | 1908 } |
1916 | 1909 |
1917 | 1910 |
1918 Object* LoadStubCompiler::CompileLoadCallback(String* name, | 1911 Object* LoadStubCompiler::CompileLoadCallback(String* name, |
1919 JSObject* object, | 1912 JSObject* object, |
1920 JSObject* holder, | 1913 JSObject* holder, |
1921 AccessorInfo* callback) { | 1914 AccessorInfo* callback) { |
1922 // ----------- S t a t e ------------- | 1915 // ----------- S t a t e ------------- |
1923 // -- r0 : receiver | 1916 // -- r0 : receiver |
1924 // -- r2 : name | 1917 // -- r2 : name |
1925 // -- lr : return address | 1918 // -- lr : return address |
1926 // ----------------------------------- | 1919 // ----------------------------------- |
1927 Label miss; | 1920 Label miss; |
1928 | 1921 |
1929 Failure* failure = Failure::InternalError(); | 1922 Failure* failure = Failure::InternalError(); |
1930 bool success = GenerateLoadCallback(object, holder, r0, r2, r3, r1, | 1923 bool success = GenerateLoadCallback(object, holder, r0, r2, r3, r1, r4, |
1931 callback, name, &miss, &failure); | 1924 callback, name, &miss, &failure); |
1932 if (!success) return failure; | 1925 if (!success) return failure; |
1933 | 1926 |
1934 __ bind(&miss); | 1927 __ bind(&miss); |
1935 GenerateLoadMiss(masm(), Code::LOAD_IC); | 1928 GenerateLoadMiss(masm(), Code::LOAD_IC); |
1936 | 1929 |
1937 // Return the generated code. | 1930 // Return the generated code. |
1938 return GetCode(CALLBACKS, name); | 1931 return GetCode(CALLBACKS, name); |
1939 } | 1932 } |
1940 | 1933 |
1941 | 1934 |
1942 Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, | 1935 Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, |
1943 JSObject* holder, | 1936 JSObject* holder, |
1944 Object* value, | 1937 Object* value, |
1945 String* name) { | 1938 String* name) { |
1946 // ----------- S t a t e ------------- | 1939 // ----------- S t a t e ------------- |
1947 // -- r0 : receiver | 1940 // -- r0 : receiver |
1948 // -- r2 : name | 1941 // -- r2 : name |
1949 // -- lr : return address | 1942 // -- lr : return address |
1950 // ----------------------------------- | 1943 // ----------------------------------- |
1951 Label miss; | 1944 Label miss; |
1952 | 1945 |
1953 GenerateLoadConstant(object, holder, r0, r3, r1, value, name, &miss); | 1946 GenerateLoadConstant(object, holder, r0, r3, r1, r4, value, name, &miss); |
1954 __ bind(&miss); | 1947 __ bind(&miss); |
1955 GenerateLoadMiss(masm(), Code::LOAD_IC); | 1948 GenerateLoadMiss(masm(), Code::LOAD_IC); |
1956 | 1949 |
1957 // Return the generated code. | 1950 // Return the generated code. |
1958 return GetCode(CONSTANT_FUNCTION, name); | 1951 return GetCode(CONSTANT_FUNCTION, name); |
1959 } | 1952 } |
1960 | 1953 |
1961 | 1954 |
1962 Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object, | 1955 Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object, |
1963 JSObject* holder, | 1956 JSObject* holder, |
1964 String* name) { | 1957 String* name) { |
1965 // ----------- S t a t e ------------- | 1958 // ----------- S t a t e ------------- |
1966 // -- r0 : receiver | 1959 // -- r0 : receiver |
1967 // -- r2 : name | 1960 // -- r2 : name |
1968 // -- lr : return address | 1961 // -- lr : return address |
1969 // ----------------------------------- | 1962 // ----------------------------------- |
1970 Label miss; | 1963 Label miss; |
1971 | 1964 |
1972 LookupResult lookup; | 1965 LookupResult lookup; |
1973 LookupPostInterceptor(holder, name, &lookup); | 1966 LookupPostInterceptor(holder, name, &lookup); |
1974 GenerateLoadInterceptor(object, | 1967 GenerateLoadInterceptor(object, |
1975 holder, | 1968 holder, |
1976 &lookup, | 1969 &lookup, |
1977 r0, | 1970 r0, |
1978 r2, | 1971 r2, |
1979 r3, | 1972 r3, |
1980 r1, | 1973 r1, |
| 1974 r4, |
1981 name, | 1975 name, |
1982 &miss); | 1976 &miss); |
1983 __ bind(&miss); | 1977 __ bind(&miss); |
1984 GenerateLoadMiss(masm(), Code::LOAD_IC); | 1978 GenerateLoadMiss(masm(), Code::LOAD_IC); |
1985 | 1979 |
1986 // Return the generated code. | 1980 // Return the generated code. |
1987 return GetCode(INTERCEPTOR, name); | 1981 return GetCode(INTERCEPTOR, name); |
1988 } | 1982 } |
1989 | 1983 |
1990 | 1984 |
(...skipping 11 matching lines...) Expand all Loading... |
2002 | 1996 |
2003 // If the object is the holder then we know that it's a global | 1997 // If the object is the holder then we know that it's a global |
2004 // object which can only happen for contextual calls. In this case, | 1998 // object which can only happen for contextual calls. In this case, |
2005 // the receiver cannot be a smi. | 1999 // the receiver cannot be a smi. |
2006 if (object != holder) { | 2000 if (object != holder) { |
2007 __ tst(r0, Operand(kSmiTagMask)); | 2001 __ tst(r0, Operand(kSmiTagMask)); |
2008 __ b(eq, &miss); | 2002 __ b(eq, &miss); |
2009 } | 2003 } |
2010 | 2004 |
2011 // Check that the map of the global has not changed. | 2005 // Check that the map of the global has not changed. |
2012 CheckPrototypes(object, r0, holder, r3, r4, name, &miss, r1); | 2006 CheckPrototypes(object, r0, holder, r3, r4, r1, name, &miss); |
2013 | 2007 |
2014 // Get the value from the cell. | 2008 // Get the value from the cell. |
2015 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); | 2009 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); |
2016 __ ldr(r4, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); | 2010 __ ldr(r4, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); |
2017 | 2011 |
2018 // Check for deleted property if property can actually be deleted. | 2012 // Check for deleted property if property can actually be deleted. |
2019 if (!is_dont_delete) { | 2013 if (!is_dont_delete) { |
2020 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 2014 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
2021 __ cmp(r4, ip); | 2015 __ cmp(r4, ip); |
2022 __ b(eq, &miss); | 2016 __ b(eq, &miss); |
(...skipping 20 matching lines...) Expand all Loading... |
2043 // -- lr : return address | 2037 // -- lr : return address |
2044 // -- r0 : key | 2038 // -- r0 : key |
2045 // -- r1 : receiver | 2039 // -- r1 : receiver |
2046 // ----------------------------------- | 2040 // ----------------------------------- |
2047 Label miss; | 2041 Label miss; |
2048 | 2042 |
2049 // Check the key is the cached one. | 2043 // Check the key is the cached one. |
2050 __ cmp(r0, Operand(Handle<String>(name))); | 2044 __ cmp(r0, Operand(Handle<String>(name))); |
2051 __ b(ne, &miss); | 2045 __ b(ne, &miss); |
2052 | 2046 |
2053 GenerateLoadField(receiver, holder, r1, r2, r3, index, name, &miss); | 2047 GenerateLoadField(receiver, holder, r1, r2, r3, r4, index, name, &miss); |
2054 __ bind(&miss); | 2048 __ bind(&miss); |
2055 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2049 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
2056 | 2050 |
2057 return GetCode(FIELD, name); | 2051 return GetCode(FIELD, name); |
2058 } | 2052 } |
2059 | 2053 |
2060 | 2054 |
2061 Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name, | 2055 Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name, |
2062 JSObject* receiver, | 2056 JSObject* receiver, |
2063 JSObject* holder, | 2057 JSObject* holder, |
2064 AccessorInfo* callback) { | 2058 AccessorInfo* callback) { |
2065 // ----------- S t a t e ------------- | 2059 // ----------- S t a t e ------------- |
2066 // -- lr : return address | 2060 // -- lr : return address |
2067 // -- r0 : key | 2061 // -- r0 : key |
2068 // -- r1 : receiver | 2062 // -- r1 : receiver |
2069 // ----------------------------------- | 2063 // ----------------------------------- |
2070 Label miss; | 2064 Label miss; |
2071 | 2065 |
2072 // Check the key is the cached one. | 2066 // Check the key is the cached one. |
2073 __ cmp(r0, Operand(Handle<String>(name))); | 2067 __ cmp(r0, Operand(Handle<String>(name))); |
2074 __ b(ne, &miss); | 2068 __ b(ne, &miss); |
2075 | 2069 |
2076 Failure* failure = Failure::InternalError(); | 2070 Failure* failure = Failure::InternalError(); |
2077 bool success = GenerateLoadCallback(receiver, holder, r1, r0, r2, r3, | 2071 bool success = GenerateLoadCallback(receiver, holder, r1, r0, r2, r3, r4, |
2078 callback, name, &miss, &failure); | 2072 callback, name, &miss, &failure); |
2079 if (!success) return failure; | 2073 if (!success) return failure; |
2080 | 2074 |
2081 __ bind(&miss); | 2075 __ bind(&miss); |
2082 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2076 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
2083 | 2077 |
2084 return GetCode(CALLBACKS, name); | 2078 return GetCode(CALLBACKS, name); |
2085 } | 2079 } |
2086 | 2080 |
2087 | 2081 |
2088 Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name, | 2082 Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name, |
2089 JSObject* receiver, | 2083 JSObject* receiver, |
2090 JSObject* holder, | 2084 JSObject* holder, |
2091 Object* value) { | 2085 Object* value) { |
2092 // ----------- S t a t e ------------- | 2086 // ----------- S t a t e ------------- |
2093 // -- lr : return address | 2087 // -- lr : return address |
2094 // -- r0 : key | 2088 // -- r0 : key |
2095 // -- r1 : receiver | 2089 // -- r1 : receiver |
2096 // ----------------------------------- | 2090 // ----------------------------------- |
2097 Label miss; | 2091 Label miss; |
2098 | 2092 |
2099 // Check the key is the cached one. | 2093 // Check the key is the cached one. |
2100 __ cmp(r0, Operand(Handle<String>(name))); | 2094 __ cmp(r0, Operand(Handle<String>(name))); |
2101 __ b(ne, &miss); | 2095 __ b(ne, &miss); |
2102 | 2096 |
2103 GenerateLoadConstant(receiver, holder, r1, r2, r3, value, name, &miss); | 2097 GenerateLoadConstant(receiver, holder, r1, r2, r3, r4, value, name, &miss); |
2104 __ bind(&miss); | 2098 __ bind(&miss); |
2105 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2099 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
2106 | 2100 |
2107 // Return the generated code. | 2101 // Return the generated code. |
2108 return GetCode(CONSTANT_FUNCTION, name); | 2102 return GetCode(CONSTANT_FUNCTION, name); |
2109 } | 2103 } |
2110 | 2104 |
2111 | 2105 |
2112 Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 2106 Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, |
2113 JSObject* holder, | 2107 JSObject* holder, |
(...skipping 11 matching lines...) Expand all Loading... |
2125 | 2119 |
2126 LookupResult lookup; | 2120 LookupResult lookup; |
2127 LookupPostInterceptor(holder, name, &lookup); | 2121 LookupPostInterceptor(holder, name, &lookup); |
2128 GenerateLoadInterceptor(receiver, | 2122 GenerateLoadInterceptor(receiver, |
2129 holder, | 2123 holder, |
2130 &lookup, | 2124 &lookup, |
2131 r1, | 2125 r1, |
2132 r0, | 2126 r0, |
2133 r2, | 2127 r2, |
2134 r3, | 2128 r3, |
| 2129 r4, |
2135 name, | 2130 name, |
2136 &miss); | 2131 &miss); |
2137 __ bind(&miss); | 2132 __ bind(&miss); |
2138 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2133 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
2139 | 2134 |
2140 return GetCode(INTERCEPTOR, name); | 2135 return GetCode(INTERCEPTOR, name); |
2141 } | 2136 } |
2142 | 2137 |
2143 | 2138 |
2144 Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { | 2139 Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2376 // Return the generated code. | 2371 // Return the generated code. |
2377 return GetCode(); | 2372 return GetCode(); |
2378 } | 2373 } |
2379 | 2374 |
2380 | 2375 |
2381 #undef __ | 2376 #undef __ |
2382 | 2377 |
2383 } } // namespace v8::internal | 2378 } } // namespace v8::internal |
2384 | 2379 |
2385 #endif // V8_TARGET_ARCH_ARM | 2380 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |