OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/ic/ic.h" | 10 #include "src/ic/ic.h" |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 | 161 |
162 // Check bit field. | 162 // Check bit field. |
163 __ testb( | 163 __ testb( |
164 FieldOperand(map, Map::kBitFieldOffset), | 164 FieldOperand(map, Map::kBitFieldOffset), |
165 Immediate((1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit))); | 165 Immediate((1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit))); |
166 __ j(not_zero, slow); | 166 __ j(not_zero, slow); |
167 } | 167 } |
168 | 168 |
169 | 169 |
170 // Loads an indexed element from a fast case array. | 170 // Loads an indexed element from a fast case array. |
171 // If not_fast_array is NULL, doesn't perform the elements map check. | |
172 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, | 171 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, |
173 Register key, Register elements, | 172 Register key, Register elements, |
174 Register scratch, Register result, | 173 Register scratch, Register result, |
175 Label* not_fast_array, Label* out_of_range) { | 174 Label* slow) { |
176 // Register use: | 175 // Register use: |
177 // | 176 // |
178 // receiver - holds the receiver on entry. | 177 // receiver - holds the receiver on entry. |
179 // Unchanged unless 'result' is the same register. | 178 // Unchanged unless 'result' is the same register. |
180 // | 179 // |
181 // key - holds the smi key on entry. | 180 // key - holds the smi key on entry. |
182 // Unchanged unless 'result' is the same register. | 181 // Unchanged unless 'result' is the same register. |
183 // | 182 // |
184 // elements - holds the elements of the receiver on exit. | |
185 // | |
186 // result - holds the result on exit if the load succeeded. | 183 // result - holds the result on exit if the load succeeded. |
187 // Allowed to be the the same as 'receiver' or 'key'. | 184 // Allowed to be the the same as 'receiver' or 'key'. |
188 // Unchanged on bailout so 'receiver' and 'key' can be safely | 185 // Unchanged on bailout so 'receiver' and 'key' can be safely |
189 // used by further computation. | 186 // used by further computation. |
190 // | 187 // |
191 // Scratch registers: | 188 // Scratch registers: |
192 // | 189 // |
193 // scratch - used to hold elements of the receiver and the loaded value. | 190 // elements - holds the elements of the receiver and its prototypes. |
| 191 // |
| 192 // scratch - used to hold maps, prototypes, and the loaded value. |
| 193 Label check_prototypes, check_next_prototype; |
| 194 Label done, in_bounds, return_undefined; |
194 | 195 |
195 __ movp(elements, FieldOperand(receiver, JSObject::kElementsOffset)); | 196 __ movp(elements, FieldOperand(receiver, JSObject::kElementsOffset)); |
196 if (not_fast_array != NULL) { | 197 __ AssertFastElements(elements); |
197 // Check that the object is in fast mode and writable. | |
198 __ CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), | |
199 Heap::kFixedArrayMapRootIndex); | |
200 __ j(not_equal, not_fast_array); | |
201 } else { | |
202 __ AssertFastElements(elements); | |
203 } | |
204 // Check that the key (index) is within bounds. | 198 // Check that the key (index) is within bounds. |
205 __ SmiCompare(key, FieldOperand(elements, FixedArray::kLengthOffset)); | 199 __ SmiCompare(key, FieldOperand(elements, FixedArray::kLengthOffset)); |
206 // Unsigned comparison rejects negative indices. | 200 // Unsigned comparison rejects negative indices. |
207 __ j(above_equal, out_of_range); | 201 __ j(below, &in_bounds); |
| 202 |
| 203 // Out-of-bounds. Check the prototype chain to see if we can just return |
| 204 // 'undefined'. |
| 205 __ SmiCompare(key, Smi::FromInt(0)); |
| 206 __ j(less, slow); // Negative keys can't take the fast OOB path. |
| 207 __ bind(&check_prototypes); |
| 208 __ movp(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 209 __ bind(&check_next_prototype); |
| 210 __ movp(scratch, FieldOperand(scratch, Map::kPrototypeOffset)); |
| 211 // scratch: current prototype |
| 212 __ CompareRoot(scratch, Heap::kNullValueRootIndex); |
| 213 __ j(equal, &return_undefined); |
| 214 __ movp(elements, FieldOperand(scratch, JSObject::kElementsOffset)); |
| 215 __ movp(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); |
| 216 // elements: elements of current prototype |
| 217 // scratch: map of current prototype |
| 218 __ CmpInstanceType(scratch, JS_OBJECT_TYPE); |
| 219 __ j(below, slow); |
| 220 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), |
| 221 Immediate((1 << Map::kIsAccessCheckNeeded) | |
| 222 (1 << Map::kHasIndexedInterceptor))); |
| 223 __ j(not_zero, slow); |
| 224 __ CompareRoot(elements, Heap::kEmptyFixedArrayRootIndex); |
| 225 __ j(not_equal, slow); |
| 226 __ jmp(&check_next_prototype); |
| 227 |
| 228 __ bind(&return_undefined); |
| 229 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); |
| 230 __ jmp(&done); |
| 231 |
| 232 __ bind(&in_bounds); |
208 // Fast case: Do the load. | 233 // Fast case: Do the load. |
209 SmiIndex index = masm->SmiToIndex(scratch, key, kPointerSizeLog2); | 234 SmiIndex index = masm->SmiToIndex(scratch, key, kPointerSizeLog2); |
210 __ movp(scratch, FieldOperand(elements, index.reg, index.scale, | 235 __ movp(scratch, FieldOperand(elements, index.reg, index.scale, |
211 FixedArray::kHeaderSize)); | 236 FixedArray::kHeaderSize)); |
212 __ CompareRoot(scratch, Heap::kTheHoleValueRootIndex); | 237 __ CompareRoot(scratch, Heap::kTheHoleValueRootIndex); |
213 // In case the loaded value is the_hole we have to consult GetProperty | 238 // In case the loaded value is the_hole we have to check the prototype chain. |
214 // to ensure the prototype chain is searched. | 239 __ j(equal, &check_prototypes); |
215 __ j(equal, out_of_range); | 240 __ Move(result, scratch); |
216 if (!result.is(scratch)) { | 241 __ bind(&done); |
217 __ movp(result, scratch); | |
218 } | |
219 } | 242 } |
220 | 243 |
221 | 244 |
222 // Checks whether a key is an array index string or a unique name. | 245 // Checks whether a key is an array index string or a unique name. |
223 // Falls through if the key is a unique name. | 246 // Falls through if the key is a unique name. |
224 static void GenerateKeyNameCheck(MacroAssembler* masm, Register key, | 247 static void GenerateKeyNameCheck(MacroAssembler* masm, Register key, |
225 Register map, Register hash, | 248 Register map, Register hash, |
226 Label* index_string, Label* not_unique) { | 249 Label* index_string, Label* not_unique) { |
227 // Register use: | 250 // Register use: |
228 // key - holds the key and is unchanged. Assumed to be non-smi. | 251 // key - holds the key and is unchanged. Assumed to be non-smi. |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 __ bind(&index_smi); | 289 __ bind(&index_smi); |
267 // Now the key is known to be a smi. This place is also jumped to from below | 290 // Now the key is known to be a smi. This place is also jumped to from below |
268 // where a numeric string is converted to a smi. | 291 // where a numeric string is converted to a smi. |
269 | 292 |
270 GenerateKeyedLoadReceiverCheck(masm, receiver, rax, | 293 GenerateKeyedLoadReceiverCheck(masm, receiver, rax, |
271 Map::kHasIndexedInterceptor, &slow); | 294 Map::kHasIndexedInterceptor, &slow); |
272 | 295 |
273 // Check the receiver's map to see if it has fast elements. | 296 // Check the receiver's map to see if it has fast elements. |
274 __ CheckFastElements(rax, &check_number_dictionary); | 297 __ CheckFastElements(rax, &check_number_dictionary); |
275 | 298 |
276 GenerateFastArrayLoad(masm, receiver, key, rax, rbx, rax, NULL, &slow); | 299 GenerateFastArrayLoad(masm, receiver, key, rax, rbx, rax, &slow); |
277 Counters* counters = masm->isolate()->counters(); | 300 Counters* counters = masm->isolate()->counters(); |
278 __ IncrementCounter(counters->keyed_load_generic_smi(), 1); | 301 __ IncrementCounter(counters->keyed_load_generic_smi(), 1); |
279 __ ret(0); | 302 __ ret(0); |
280 | 303 |
281 __ bind(&check_number_dictionary); | 304 __ bind(&check_number_dictionary); |
282 __ SmiToInteger32(rbx, key); | 305 __ SmiToInteger32(rbx, key); |
283 __ movp(rax, FieldOperand(receiver, JSObject::kElementsOffset)); | 306 __ movp(rax, FieldOperand(receiver, JSObject::kElementsOffset)); |
284 | 307 |
285 // Check whether the elements is a number dictionary. | 308 // Check whether the elements is a number dictionary. |
286 // rbx: key as untagged int32 | 309 // rbx: key as untagged int32 |
(...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
990 Condition cc = | 1013 Condition cc = |
991 (check == ENABLE_INLINED_SMI_CHECK) | 1014 (check == ENABLE_INLINED_SMI_CHECK) |
992 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 1015 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
993 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 1016 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
994 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1017 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
995 } | 1018 } |
996 } | 1019 } |
997 } // namespace v8::internal | 1020 } // namespace v8::internal |
998 | 1021 |
999 #endif // V8_TARGET_ARCH_X64 | 1022 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |