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 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 // bit test is enough. | 267 // bit test is enough. |
268 STATIC_ASSERT(kNotInternalizedTag != 0); | 268 STATIC_ASSERT(kNotInternalizedTag != 0); |
269 __ testb(FieldOperand(map, Map::kInstanceTypeOffset), | 269 __ testb(FieldOperand(map, Map::kInstanceTypeOffset), |
270 Immediate(kIsNotInternalizedMask)); | 270 Immediate(kIsNotInternalizedMask)); |
271 __ j(not_zero, not_unique); | 271 __ j(not_zero, not_unique); |
272 | 272 |
273 __ bind(&unique); | 273 __ bind(&unique); |
274 } | 274 } |
275 | 275 |
276 | 276 |
277 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 277 void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
278 // The return address is on the stack. | 278 // The return address is on the stack. |
279 Label slow, check_name, index_smi, index_name, property_array_property; | 279 Label slow, check_name, index_smi, index_name, property_array_property; |
280 Label probe_dictionary, check_number_dictionary; | 280 Label probe_dictionary, check_number_dictionary; |
281 | 281 |
282 Register receiver = LoadDescriptor::ReceiverRegister(); | 282 Register receiver = LoadDescriptor::ReceiverRegister(); |
283 Register key = LoadDescriptor::NameRegister(); | 283 Register key = LoadDescriptor::NameRegister(); |
284 DCHECK(receiver.is(rdx)); | 284 DCHECK(receiver.is(rdx)); |
285 DCHECK(key.is(rcx)); | 285 DCHECK(key.is(rcx)); |
286 | 286 |
287 // Check that the key is a smi. | 287 // Check that the key is a smi. |
(...skipping 30 matching lines...) Expand all Loading... |
318 // Slow case: Jump to runtime. | 318 // Slow case: Jump to runtime. |
319 __ IncrementCounter(counters->keyed_load_generic_slow(), 1); | 319 __ IncrementCounter(counters->keyed_load_generic_slow(), 1); |
320 GenerateRuntimeGetProperty(masm); | 320 GenerateRuntimeGetProperty(masm); |
321 | 321 |
322 __ bind(&check_name); | 322 __ bind(&check_name); |
323 GenerateKeyNameCheck(masm, key, rax, rbx, &index_name, &slow); | 323 GenerateKeyNameCheck(masm, key, rax, rbx, &index_name, &slow); |
324 | 324 |
325 GenerateKeyedLoadReceiverCheck(masm, receiver, rax, Map::kHasNamedInterceptor, | 325 GenerateKeyedLoadReceiverCheck(masm, receiver, rax, Map::kHasNamedInterceptor, |
326 &slow); | 326 &slow); |
327 | 327 |
328 // If the receiver is a fast-case object, check the keyed lookup | 328 // If the receiver is a fast-case object, check the stub cache. Otherwise |
329 // cache. Otherwise probe the dictionary leaving result in key. | 329 // probe the dictionary. |
330 __ movp(rbx, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 330 __ movp(rbx, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
331 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), | 331 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), |
332 Heap::kHashTableMapRootIndex); | 332 Heap::kHashTableMapRootIndex); |
333 __ j(equal, &probe_dictionary); | 333 __ j(equal, &probe_dictionary); |
334 | 334 |
335 // Load the map of the receiver, compute the keyed lookup cache hash | 335 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( |
336 // based on 32 bits of the map pointer and the string hash. | 336 Code::ComputeHandlerFlags(Code::LOAD_IC)); |
337 __ movp(rbx, FieldOperand(receiver, HeapObject::kMapOffset)); | 337 masm->isolate()->stub_cache()->GenerateProbe( |
338 __ movl(rax, rbx); | 338 masm, Code::LOAD_IC, flags, false, receiver, key, rbx, no_reg); |
339 __ shrl(rax, Immediate(KeyedLookupCache::kMapHashShift)); | 339 // Cache miss. |
340 __ movl(rdi, FieldOperand(key, String::kHashFieldOffset)); | 340 GenerateMiss(masm); |
341 __ shrl(rdi, Immediate(String::kHashShift)); | |
342 __ xorp(rax, rdi); | |
343 int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask); | |
344 __ andp(rax, Immediate(mask)); | |
345 | |
346 // Load the key (consisting of map and internalized string) from the cache and | |
347 // check for match. | |
348 Label load_in_object_property; | |
349 static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket; | |
350 Label hit_on_nth_entry[kEntriesPerBucket]; | |
351 ExternalReference cache_keys = | |
352 ExternalReference::keyed_lookup_cache_keys(masm->isolate()); | |
353 | |
354 for (int i = 0; i < kEntriesPerBucket - 1; i++) { | |
355 Label try_next_entry; | |
356 __ movp(rdi, rax); | |
357 __ shlp(rdi, Immediate(kPointerSizeLog2 + 1)); | |
358 __ LoadAddress(kScratchRegister, cache_keys); | |
359 int off = kPointerSize * i * 2; | |
360 __ cmpp(rbx, Operand(kScratchRegister, rdi, times_1, off)); | |
361 __ j(not_equal, &try_next_entry); | |
362 __ cmpp(key, Operand(kScratchRegister, rdi, times_1, off + kPointerSize)); | |
363 __ j(equal, &hit_on_nth_entry[i]); | |
364 __ bind(&try_next_entry); | |
365 } | |
366 | |
367 int off = kPointerSize * (kEntriesPerBucket - 1) * 2; | |
368 __ cmpp(rbx, Operand(kScratchRegister, rdi, times_1, off)); | |
369 __ j(not_equal, &slow); | |
370 __ cmpp(key, Operand(kScratchRegister, rdi, times_1, off + kPointerSize)); | |
371 __ j(not_equal, &slow); | |
372 | |
373 // Get field offset, which is a 32-bit integer. | |
374 ExternalReference cache_field_offsets = | |
375 ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate()); | |
376 | |
377 // Hit on nth entry. | |
378 for (int i = kEntriesPerBucket - 1; i >= 0; i--) { | |
379 __ bind(&hit_on_nth_entry[i]); | |
380 if (i != 0) { | |
381 __ addl(rax, Immediate(i)); | |
382 } | |
383 __ LoadAddress(kScratchRegister, cache_field_offsets); | |
384 __ movl(rdi, Operand(kScratchRegister, rax, times_4, 0)); | |
385 __ movzxbp(rax, FieldOperand(rbx, Map::kInObjectPropertiesOffset)); | |
386 __ subp(rdi, rax); | |
387 __ j(above_equal, &property_array_property); | |
388 if (i != 0) { | |
389 __ jmp(&load_in_object_property); | |
390 } | |
391 } | |
392 | |
393 // Load in-object property. | |
394 __ bind(&load_in_object_property); | |
395 __ movzxbp(rax, FieldOperand(rbx, Map::kInstanceSizeOffset)); | |
396 __ addp(rax, rdi); | |
397 __ movp(rax, FieldOperand(receiver, rax, times_pointer_size, 0)); | |
398 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1); | |
399 __ ret(0); | |
400 | |
401 // Load property array property. | |
402 __ bind(&property_array_property); | |
403 __ movp(rax, FieldOperand(receiver, JSObject::kPropertiesOffset)); | |
404 __ movp(rax, | |
405 FieldOperand(rax, rdi, times_pointer_size, FixedArray::kHeaderSize)); | |
406 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1); | |
407 __ ret(0); | |
408 | 341 |
409 // Do a quick inline probe of the receiver's dictionary, if it | 342 // Do a quick inline probe of the receiver's dictionary, if it |
410 // exists. | 343 // exists. |
411 __ bind(&probe_dictionary); | 344 __ bind(&probe_dictionary); |
412 // rbx: elements | 345 // rbx: elements |
413 | 346 |
414 __ movp(rax, FieldOperand(receiver, JSObject::kMapOffset)); | 347 __ movp(rax, FieldOperand(receiver, JSObject::kMapOffset)); |
415 __ movb(rax, FieldOperand(rax, Map::kInstanceTypeOffset)); | 348 __ movb(rax, FieldOperand(rax, Map::kInstanceTypeOffset)); |
416 GenerateGlobalInstanceTypeCheck(masm, rax, &slow); | 349 GenerateGlobalInstanceTypeCheck(masm, rax, &slow); |
417 | 350 |
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1013 Condition cc = | 946 Condition cc = |
1014 (check == ENABLE_INLINED_SMI_CHECK) | 947 (check == ENABLE_INLINED_SMI_CHECK) |
1015 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 948 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
1016 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 949 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
1017 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 950 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
1018 } | 951 } |
1019 } | 952 } |
1020 } // namespace v8::internal | 953 } // namespace v8::internal |
1021 | 954 |
1022 #endif // V8_TARGET_ARCH_X64 | 955 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |