OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 __ b(eq, global_object); | 57 __ b(eq, global_object); |
58 __ cmp(type, Operand(JS_BUILTINS_OBJECT_TYPE)); | 58 __ cmp(type, Operand(JS_BUILTINS_OBJECT_TYPE)); |
59 __ b(eq, global_object); | 59 __ b(eq, global_object); |
60 __ cmp(type, Operand(JS_GLOBAL_PROXY_TYPE)); | 60 __ cmp(type, Operand(JS_GLOBAL_PROXY_TYPE)); |
61 __ b(eq, global_object); | 61 __ b(eq, global_object); |
62 } | 62 } |
63 | 63 |
64 | 64 |
65 // Generated code falls through if the receiver is a regular non-global | 65 // Generated code falls through if the receiver is a regular non-global |
66 // JS object with slow properties and no interceptors. | 66 // JS object with slow properties and no interceptors. |
67 static void GenerateDictionaryLoadReceiverCheck(MacroAssembler* masm, | 67 static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm, |
68 Register receiver, | 68 Register receiver, |
69 Register elements, | 69 Register elements, |
70 Register t0, | 70 Register t0, |
71 Register t1, | 71 Register t1, |
72 Label* miss) { | 72 Label* miss) { |
73 // Register usage: | 73 // Register usage: |
74 // receiver: holds the receiver on entry and is unchanged. | 74 // receiver: holds the receiver on entry and is unchanged. |
75 // elements: holds the property dictionary on fall through. | 75 // elements: holds the property dictionary on fall through. |
76 // Scratch registers: | 76 // Scratch registers: |
77 // t0: used to holds the receiver map. | 77 // t0: used to holds the receiver map. |
78 // t1: used to holds the receiver instance type, receiver bit mask and | 78 // t1: used to holds the receiver instance type, receiver bit mask and |
79 // elements map. | 79 // elements map. |
80 | 80 |
81 // Check that the receiver isn't a smi. | 81 // Check that the receiver isn't a smi. |
82 __ tst(receiver, Operand(kSmiTagMask)); | 82 __ tst(receiver, Operand(kSmiTagMask)); |
(...skipping 15 matching lines...) Expand all Loading... |
98 __ b(nz, miss); | 98 __ b(nz, miss); |
99 | 99 |
100 __ ldr(elements, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 100 __ ldr(elements, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
101 __ ldr(t1, FieldMemOperand(elements, HeapObject::kMapOffset)); | 101 __ ldr(t1, FieldMemOperand(elements, HeapObject::kMapOffset)); |
102 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); | 102 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); |
103 __ cmp(t1, ip); | 103 __ cmp(t1, ip); |
104 __ b(nz, miss); | 104 __ b(nz, miss); |
105 } | 105 } |
106 | 106 |
107 | 107 |
108 // Helper function used from LoadIC/CallIC GenerateNormal. | 108 // Probe the string dictionary in the |elements| register. Jump to the |
109 // | 109 // |done| label if a property with the given name is found. Jump to |
110 // elements: Property dictionary. It is not clobbered if a jump to the miss | 110 // the |miss| label otherwise. |
111 // label is done. | 111 static void GenerateStringDictionaryProbes(MacroAssembler* masm, |
112 // name: Property name. It is not clobbered if a jump to the miss label is | 112 Label* miss, |
113 // done | 113 Label* done, |
114 // result: Register for the result. It is only updated if a jump to the miss | 114 Register elements, |
115 // label is not done. Can be the same as elements or name clobbering | 115 Register name, |
116 // one of these in the case of not jumping to the miss label. | 116 Register scratch1, |
117 // The two scratch registers need to be different from elements, name and | 117 Register scratch2) { |
118 // result. | |
119 // The generated code assumes that the receiver has slow properties, | |
120 // is not a global object and does not have interceptors. | |
121 static void GenerateDictionaryLoad(MacroAssembler* masm, | |
122 Label* miss, | |
123 Register elements, | |
124 Register name, | |
125 Register result, | |
126 Register scratch1, | |
127 Register scratch2) { | |
128 // Main use of the scratch registers. | |
129 // scratch1: Used as temporary and to hold the capacity of the property | |
130 // dictionary. | |
131 // scratch2: Used as temporary. | |
132 | |
133 Label done; | |
134 | |
135 // Compute the capacity mask. | 118 // Compute the capacity mask. |
136 const int kCapacityOffset = StringDictionary::kHeaderSize + | 119 const int kCapacityOffset = StringDictionary::kHeaderSize + |
137 StringDictionary::kCapacityIndex * kPointerSize; | 120 StringDictionary::kCapacityIndex * kPointerSize; |
138 __ ldr(scratch1, FieldMemOperand(elements, kCapacityOffset)); | 121 __ ldr(scratch1, FieldMemOperand(elements, kCapacityOffset)); |
139 __ mov(scratch1, Operand(scratch1, ASR, kSmiTagSize)); // convert smi to int | 122 __ mov(scratch1, Operand(scratch1, ASR, kSmiTagSize)); // convert smi to int |
140 __ sub(scratch1, scratch1, Operand(1)); | 123 __ sub(scratch1, scratch1, Operand(1)); |
141 | 124 |
142 const int kElementsStartOffset = StringDictionary::kHeaderSize + | 125 const int kElementsStartOffset = StringDictionary::kHeaderSize + |
143 StringDictionary::kElementsStartIndex * kPointerSize; | 126 StringDictionary::kElementsStartIndex * kPointerSize; |
144 | 127 |
(...skipping 18 matching lines...) Expand all Loading... |
163 // Scale the index by multiplying by the element size. | 146 // Scale the index by multiplying by the element size. |
164 ASSERT(StringDictionary::kEntrySize == 3); | 147 ASSERT(StringDictionary::kEntrySize == 3); |
165 // scratch2 = scratch2 * 3. | 148 // scratch2 = scratch2 * 3. |
166 __ add(scratch2, scratch2, Operand(scratch2, LSL, 1)); | 149 __ add(scratch2, scratch2, Operand(scratch2, LSL, 1)); |
167 | 150 |
168 // Check if the key is identical to the name. | 151 // Check if the key is identical to the name. |
169 __ add(scratch2, elements, Operand(scratch2, LSL, 2)); | 152 __ add(scratch2, elements, Operand(scratch2, LSL, 2)); |
170 __ ldr(ip, FieldMemOperand(scratch2, kElementsStartOffset)); | 153 __ ldr(ip, FieldMemOperand(scratch2, kElementsStartOffset)); |
171 __ cmp(name, Operand(ip)); | 154 __ cmp(name, Operand(ip)); |
172 if (i != kProbes - 1) { | 155 if (i != kProbes - 1) { |
173 __ b(eq, &done); | 156 __ b(eq, done); |
174 } else { | 157 } else { |
175 __ b(ne, miss); | 158 __ b(ne, miss); |
176 } | 159 } |
177 } | 160 } |
| 161 } |
178 | 162 |
179 // Check that the value is a normal property. | 163 |
| 164 // Helper function used from LoadIC/CallIC GenerateNormal. |
| 165 // |
| 166 // elements: Property dictionary. It is not clobbered if a jump to the miss |
| 167 // label is done. |
| 168 // name: Property name. It is not clobbered if a jump to the miss label is |
| 169 // done |
| 170 // result: Register for the result. It is only updated if a jump to the miss |
| 171 // label is not done. Can be the same as elements or name clobbering |
| 172 // one of these in the case of not jumping to the miss label. |
| 173 // The two scratch registers need to be different from elements, name and |
| 174 // result. |
| 175 // The generated code assumes that the receiver has slow properties, |
| 176 // is not a global object and does not have interceptors. |
| 177 static void GenerateDictionaryLoad(MacroAssembler* masm, |
| 178 Label* miss, |
| 179 Register elements, |
| 180 Register name, |
| 181 Register result, |
| 182 Register scratch1, |
| 183 Register scratch2) { |
| 184 // Main use of the scratch registers. |
| 185 // scratch1: Used as temporary and to hold the capacity of the property |
| 186 // dictionary. |
| 187 // scratch2: Used as temporary. |
| 188 Label done; |
| 189 |
| 190 // Probe the dictionary. |
| 191 GenerateStringDictionaryProbes(masm, |
| 192 miss, |
| 193 &done, |
| 194 elements, |
| 195 name, |
| 196 scratch1, |
| 197 scratch2); |
| 198 |
| 199 // If probing finds an entry check that the value is a normal |
| 200 // property. |
180 __ bind(&done); // scratch2 == elements + 4 * index | 201 __ bind(&done); // scratch2 == elements + 4 * index |
181 __ ldr(scratch1, | 202 const int kElementsStartOffset = StringDictionary::kHeaderSize + |
182 FieldMemOperand(scratch2, kElementsStartOffset + 2 * kPointerSize)); | 203 StringDictionary::kElementsStartIndex * kPointerSize; |
| 204 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; |
| 205 __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); |
183 __ tst(scratch1, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize)); | 206 __ tst(scratch1, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize)); |
184 __ b(ne, miss); | 207 __ b(ne, miss); |
185 | 208 |
186 // Get the value at the masked, scaled index and return. | 209 // Get the value at the masked, scaled index and return. |
187 __ ldr(result, | 210 __ ldr(result, |
188 FieldMemOperand(scratch2, kElementsStartOffset + 1 * kPointerSize)); | 211 FieldMemOperand(scratch2, kElementsStartOffset + 1 * kPointerSize)); |
189 } | 212 } |
190 | 213 |
191 | 214 |
| 215 // Helper function used from StoreIC::GenerateNormal. |
| 216 // |
| 217 // elements: Property dictionary. It is not clobbered if a jump to the miss |
| 218 // label is done. |
| 219 // name: Property name. It is not clobbered if a jump to the miss label is |
| 220 // done |
| 221 // value: The value to store. |
| 222 // The two scratch registers need to be different from elements, name and |
| 223 // result. |
| 224 // The generated code assumes that the receiver has slow properties, |
| 225 // is not a global object and does not have interceptors. |
| 226 static void GenerateDictionaryStore(MacroAssembler* masm, |
| 227 Label* miss, |
| 228 Register elements, |
| 229 Register name, |
| 230 Register value, |
| 231 Register scratch1, |
| 232 Register scratch2) { |
| 233 // Main use of the scratch registers. |
| 234 // scratch1: Used as temporary and to hold the capacity of the property |
| 235 // dictionary. |
| 236 // scratch2: Used as temporary. |
| 237 Label done; |
| 238 |
| 239 // Probe the dictionary. |
| 240 GenerateStringDictionaryProbes(masm, |
| 241 miss, |
| 242 &done, |
| 243 elements, |
| 244 name, |
| 245 scratch1, |
| 246 scratch2); |
| 247 |
| 248 // If probing finds an entry in the dictionary check that the value |
| 249 // is a normal property that is not read only. |
| 250 __ bind(&done); // scratch2 == elements + 4 * index |
| 251 const int kElementsStartOffset = StringDictionary::kHeaderSize + |
| 252 StringDictionary::kElementsStartIndex * kPointerSize; |
| 253 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; |
| 254 const int kTypeAndReadOnlyMask |
| 255 = (PropertyDetails::TypeField::mask() | |
| 256 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize; |
| 257 __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); |
| 258 __ tst(scratch1, Operand(kTypeAndReadOnlyMask)); |
| 259 __ b(ne, miss); |
| 260 |
| 261 // Store the value at the masked, scaled index and return. |
| 262 const int kValueOffset = kElementsStartOffset + kPointerSize; |
| 263 __ add(scratch2, scratch2, Operand(kValueOffset - kHeapObjectTag)); |
| 264 __ str(value, MemOperand(scratch2)); |
| 265 |
| 266 // Update the write barrier. Make sure not to clobber the value. |
| 267 __ mov(scratch1, value); |
| 268 __ RecordWrite(elements, scratch2, scratch1); |
| 269 } |
| 270 |
| 271 |
192 static void GenerateNumberDictionaryLoad(MacroAssembler* masm, | 272 static void GenerateNumberDictionaryLoad(MacroAssembler* masm, |
193 Label* miss, | 273 Label* miss, |
194 Register elements, | 274 Register elements, |
195 Register key, | 275 Register key, |
196 Register result, | 276 Register result, |
197 Register t0, | 277 Register t0, |
198 Register t1, | 278 Register t1, |
199 Register t2) { | 279 Register t2) { |
200 // Register use: | 280 // Register use: |
201 // | 281 // |
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
553 static void GenerateCallNormal(MacroAssembler* masm, int argc) { | 633 static void GenerateCallNormal(MacroAssembler* masm, int argc) { |
554 // ----------- S t a t e ------------- | 634 // ----------- S t a t e ------------- |
555 // -- r2 : name | 635 // -- r2 : name |
556 // -- lr : return address | 636 // -- lr : return address |
557 // ----------------------------------- | 637 // ----------------------------------- |
558 Label miss; | 638 Label miss; |
559 | 639 |
560 // Get the receiver of the function from the stack into r1. | 640 // Get the receiver of the function from the stack into r1. |
561 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 641 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
562 | 642 |
563 GenerateDictionaryLoadReceiverCheck(masm, r1, r0, r3, r4, &miss); | 643 GenerateStringDictionaryReceiverCheck(masm, r1, r0, r3, r4, &miss); |
564 | 644 |
565 // r0: elements | 645 // r0: elements |
566 // Search the dictionary - put result in register r1. | 646 // Search the dictionary - put result in register r1. |
567 GenerateDictionaryLoad(masm, &miss, r0, r2, r1, r3, r4); | 647 GenerateDictionaryLoad(masm, &miss, r0, r2, r1, r3, r4); |
568 | 648 |
569 GenerateFunctionTailCall(masm, argc, &miss, r4); | 649 GenerateFunctionTailCall(masm, argc, &miss, r4); |
570 | 650 |
571 __ bind(&miss); | 651 __ bind(&miss); |
572 } | 652 } |
573 | 653 |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
808 | 888 |
809 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 889 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
810 // ----------- S t a t e ------------- | 890 // ----------- S t a t e ------------- |
811 // -- r2 : name | 891 // -- r2 : name |
812 // -- lr : return address | 892 // -- lr : return address |
813 // -- r0 : receiver | 893 // -- r0 : receiver |
814 // -- sp[0] : receiver | 894 // -- sp[0] : receiver |
815 // ----------------------------------- | 895 // ----------------------------------- |
816 Label miss; | 896 Label miss; |
817 | 897 |
818 GenerateDictionaryLoadReceiverCheck(masm, r0, r1, r3, r4, &miss); | 898 GenerateStringDictionaryReceiverCheck(masm, r0, r1, r3, r4, &miss); |
819 | 899 |
820 // r1: elements | 900 // r1: elements |
821 GenerateDictionaryLoad(masm, &miss, r1, r2, r0, r3, r4); | 901 GenerateDictionaryLoad(masm, &miss, r1, r2, r0, r3, r4); |
822 __ Ret(); | 902 __ Ret(); |
823 | 903 |
824 // Cache miss: Jump to runtime. | 904 // Cache miss: Jump to runtime. |
825 __ bind(&miss); | 905 __ bind(&miss); |
826 GenerateMiss(masm); | 906 GenerateMiss(masm); |
827 } | 907 } |
828 | 908 |
(...skipping 1302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2131 | 2211 |
2132 ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_ArrayLength)); | 2212 ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_ArrayLength)); |
2133 __ TailCallExternalReference(ref, 2, 1); | 2213 __ TailCallExternalReference(ref, 2, 1); |
2134 | 2214 |
2135 __ bind(&miss); | 2215 __ bind(&miss); |
2136 | 2216 |
2137 GenerateMiss(masm); | 2217 GenerateMiss(masm); |
2138 } | 2218 } |
2139 | 2219 |
2140 | 2220 |
| 2221 void StoreIC::GenerateNormal(MacroAssembler* masm) { |
| 2222 // ----------- S t a t e ------------- |
| 2223 // -- r0 : value |
| 2224 // -- r1 : receiver |
| 2225 // -- r2 : name |
| 2226 // -- lr : return address |
| 2227 // ----------------------------------- |
| 2228 Label miss; |
| 2229 |
| 2230 GenerateStringDictionaryReceiverCheck(masm, r1, r3, r4, r5, &miss); |
| 2231 |
| 2232 GenerateDictionaryStore(masm, &miss, r3, r2, r0, r4, r5); |
| 2233 __ IncrementCounter(&Counters::store_normal_hit, 1, r4, r5); |
| 2234 __ Ret(); |
| 2235 |
| 2236 __ bind(&miss); |
| 2237 __ IncrementCounter(&Counters::store_normal_miss, 1, r4, r5); |
| 2238 GenerateMiss(masm); |
| 2239 } |
| 2240 |
| 2241 |
2141 #undef __ | 2242 #undef __ |
2142 | 2243 |
2143 | 2244 |
2144 } } // namespace v8::internal | 2245 } } // namespace v8::internal |
2145 | 2246 |
2146 #endif // V8_TARGET_ARCH_ARM | 2247 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |