Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(975)

Side by Side Diff: src/arm/stub-cache-arm.cc

Issue 2982001: Simplifying GenerateDictionaryNegativeLookup by making the 'extra' parameter ... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/ia32/stub-cache-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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 &regular_invoke); 715 &regular_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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | src/ia32/stub-cache-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698