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-inl.h" | 10 #include "src/ic-inl.h" |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
320 __ testb(FieldOperand(map, Map::kInstanceTypeOffset), | 320 __ testb(FieldOperand(map, Map::kInstanceTypeOffset), |
321 Immediate(kIsNotInternalizedMask)); | 321 Immediate(kIsNotInternalizedMask)); |
322 __ j(not_zero, not_unique); | 322 __ j(not_zero, not_unique); |
323 | 323 |
324 __ bind(&unique); | 324 __ bind(&unique); |
325 } | 325 } |
326 | 326 |
327 | 327 |
328 | 328 |
329 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 329 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
330 // ----------- S t a t e ------------- | 330 // The return address is on the stack. |
331 // -- rax : key | |
332 // -- rdx : receiver | |
333 // -- rsp[0] : return address | |
334 // ----------------------------------- | |
335 ASSERT(rdx.is(ReceiverRegister())); | |
336 ASSERT(rax.is(NameRegister())); | |
337 Label slow, check_name, index_smi, index_name, property_array_property; | 331 Label slow, check_name, index_smi, index_name, property_array_property; |
338 Label probe_dictionary, check_number_dictionary; | 332 Label probe_dictionary, check_number_dictionary; |
339 | 333 |
334 Register receiver = ReceiverRegister(); | |
335 Register key = NameRegister(); | |
336 ASSERT(receiver.is(rdx)); | |
337 ASSERT(key.is(rcx)); | |
338 | |
340 // Check that the key is a smi. | 339 // Check that the key is a smi. |
341 __ JumpIfNotSmi(rax, &check_name); | 340 __ JumpIfNotSmi(key, &check_name); |
342 __ bind(&index_smi); | 341 __ bind(&index_smi); |
343 // Now the key is known to be a smi. This place is also jumped to from below | 342 // Now the key is known to be a smi. This place is also jumped to from below |
344 // where a numeric string is converted to a smi. | 343 // where a numeric string is converted to a smi. |
345 | 344 |
346 GenerateKeyedLoadReceiverCheck( | 345 GenerateKeyedLoadReceiverCheck( |
347 masm, rdx, rcx, Map::kHasIndexedInterceptor, &slow); | 346 masm, receiver, rax, Map::kHasIndexedInterceptor, &slow); |
348 | 347 |
349 // Check the receiver's map to see if it has fast elements. | 348 // Check the receiver's map to see if it has fast elements. |
350 __ CheckFastElements(rcx, &check_number_dictionary); | 349 __ CheckFastElements(rax, &check_number_dictionary); |
351 | 350 |
352 GenerateFastArrayLoad(masm, | 351 GenerateFastArrayLoad(masm, |
353 rdx, | 352 receiver, |
353 key, | |
354 rax, | 354 rax, |
355 rcx, | |
356 rbx, | 355 rbx, |
357 rax, | 356 rax, |
358 NULL, | 357 NULL, |
359 &slow); | 358 &slow); |
360 Counters* counters = masm->isolate()->counters(); | 359 Counters* counters = masm->isolate()->counters(); |
361 __ IncrementCounter(counters->keyed_load_generic_smi(), 1); | 360 __ IncrementCounter(counters->keyed_load_generic_smi(), 1); |
362 __ ret(0); | 361 __ ret(0); |
363 | 362 |
364 __ bind(&check_number_dictionary); | 363 __ bind(&check_number_dictionary); |
365 __ SmiToInteger32(rbx, rax); | 364 __ SmiToInteger32(rbx, key); |
366 __ movp(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); | 365 __ movp(rax, FieldOperand(receiver, JSObject::kElementsOffset)); |
367 | 366 |
368 // Check whether the elements is a number dictionary. | 367 // Check whether the elements is a number dictionary. |
369 // rdx: receiver | 368 // receiver: receiver |
Jakob Kummerow
2014/06/26 16:17:10
Yay for high-entropy comments! :-P
AFAICS, the |r
mvstanton
2014/06/30 13:19:09
Will do, thanks.
| |
370 // rax: key | 369 // key: key |
371 // rbx: key as untagged int32 | 370 // rbx: key as untagged int32 |
372 // rcx: elements | 371 // rax: elements |
373 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), | 372 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), |
374 Heap::kHashTableMapRootIndex); | 373 Heap::kHashTableMapRootIndex); |
375 __ j(not_equal, &slow); | 374 __ j(not_equal, &slow); |
376 __ LoadFromNumberDictionary(&slow, rcx, rax, rbx, r9, rdi, rax); | 375 __ LoadFromNumberDictionary(&slow, rax, key, rbx, r9, rdi, rax); |
377 __ ret(0); | 376 __ ret(0); |
378 | 377 |
379 __ bind(&slow); | 378 __ bind(&slow); |
380 // Slow case: Jump to runtime. | 379 // Slow case: Jump to runtime. |
381 // rdx: receiver | 380 // receiver: receiver |
382 // rax: key | 381 // key: key |
383 __ IncrementCounter(counters->keyed_load_generic_slow(), 1); | 382 __ IncrementCounter(counters->keyed_load_generic_slow(), 1); |
384 GenerateRuntimeGetProperty(masm); | 383 GenerateRuntimeGetProperty(masm); |
385 | 384 |
386 __ bind(&check_name); | 385 __ bind(&check_name); |
387 GenerateKeyNameCheck(masm, rax, rcx, rbx, &index_name, &slow); | 386 GenerateKeyNameCheck(masm, key, rax, rbx, &index_name, &slow); |
388 | 387 |
389 GenerateKeyedLoadReceiverCheck( | 388 GenerateKeyedLoadReceiverCheck( |
390 masm, rdx, rcx, Map::kHasNamedInterceptor, &slow); | 389 masm, receiver, rax, Map::kHasNamedInterceptor, &slow); |
391 | 390 |
392 // If the receiver is a fast-case object, check the keyed lookup | 391 // If the receiver is a fast-case object, check the keyed lookup |
393 // cache. Otherwise probe the dictionary leaving result in rcx. | 392 // cache. Otherwise probe the dictionary leaving result in key. |
394 __ movp(rbx, FieldOperand(rdx, JSObject::kPropertiesOffset)); | 393 __ movp(rbx, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
395 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), | 394 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), |
396 Heap::kHashTableMapRootIndex); | 395 Heap::kHashTableMapRootIndex); |
397 __ j(equal, &probe_dictionary); | 396 __ j(equal, &probe_dictionary); |
398 | 397 |
399 // Load the map of the receiver, compute the keyed lookup cache hash | 398 // Load the map of the receiver, compute the keyed lookup cache hash |
400 // based on 32 bits of the map pointer and the string hash. | 399 // based on 32 bits of the map pointer and the string hash. |
401 __ movp(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); | 400 __ movp(rbx, FieldOperand(receiver, HeapObject::kMapOffset)); |
402 __ movl(rcx, rbx); | 401 __ movl(rax, rbx); |
403 __ shrl(rcx, Immediate(KeyedLookupCache::kMapHashShift)); | 402 __ shrl(rax, Immediate(KeyedLookupCache::kMapHashShift)); |
404 __ movl(rdi, FieldOperand(rax, String::kHashFieldOffset)); | 403 __ movl(rdi, FieldOperand(key, String::kHashFieldOffset)); |
405 __ shrl(rdi, Immediate(String::kHashShift)); | 404 __ shrl(rdi, Immediate(String::kHashShift)); |
406 __ xorp(rcx, rdi); | 405 __ xorp(rax, rdi); |
407 int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask); | 406 int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask); |
408 __ andp(rcx, Immediate(mask)); | 407 __ andp(rax, Immediate(mask)); |
409 | 408 |
410 // Load the key (consisting of map and internalized string) from the cache and | 409 // Load the key (consisting of map and internalized string) from the cache and |
411 // check for match. | 410 // check for match. |
412 Label load_in_object_property; | 411 Label load_in_object_property; |
413 static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket; | 412 static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket; |
414 Label hit_on_nth_entry[kEntriesPerBucket]; | 413 Label hit_on_nth_entry[kEntriesPerBucket]; |
415 ExternalReference cache_keys | 414 ExternalReference cache_keys |
416 = ExternalReference::keyed_lookup_cache_keys(masm->isolate()); | 415 = ExternalReference::keyed_lookup_cache_keys(masm->isolate()); |
417 | 416 |
418 for (int i = 0; i < kEntriesPerBucket - 1; i++) { | 417 for (int i = 0; i < kEntriesPerBucket - 1; i++) { |
419 Label try_next_entry; | 418 Label try_next_entry; |
420 __ movp(rdi, rcx); | 419 __ movp(rdi, rax); |
421 __ shlp(rdi, Immediate(kPointerSizeLog2 + 1)); | 420 __ shlp(rdi, Immediate(kPointerSizeLog2 + 1)); |
422 __ LoadAddress(kScratchRegister, cache_keys); | 421 __ LoadAddress(kScratchRegister, cache_keys); |
423 int off = kPointerSize * i * 2; | 422 int off = kPointerSize * i * 2; |
424 __ cmpp(rbx, Operand(kScratchRegister, rdi, times_1, off)); | 423 __ cmpp(rbx, Operand(kScratchRegister, rdi, times_1, off)); |
425 __ j(not_equal, &try_next_entry); | 424 __ j(not_equal, &try_next_entry); |
426 __ cmpp(rax, Operand(kScratchRegister, rdi, times_1, off + kPointerSize)); | 425 __ cmpp(key, Operand(kScratchRegister, rdi, times_1, off + kPointerSize)); |
427 __ j(equal, &hit_on_nth_entry[i]); | 426 __ j(equal, &hit_on_nth_entry[i]); |
428 __ bind(&try_next_entry); | 427 __ bind(&try_next_entry); |
429 } | 428 } |
430 | 429 |
431 int off = kPointerSize * (kEntriesPerBucket - 1) * 2; | 430 int off = kPointerSize * (kEntriesPerBucket - 1) * 2; |
432 __ cmpp(rbx, Operand(kScratchRegister, rdi, times_1, off)); | 431 __ cmpp(rbx, Operand(kScratchRegister, rdi, times_1, off)); |
433 __ j(not_equal, &slow); | 432 __ j(not_equal, &slow); |
434 __ cmpp(rax, Operand(kScratchRegister, rdi, times_1, off + kPointerSize)); | 433 __ cmpp(key, Operand(kScratchRegister, rdi, times_1, off + kPointerSize)); |
435 __ j(not_equal, &slow); | 434 __ j(not_equal, &slow); |
436 | 435 |
437 // Get field offset, which is a 32-bit integer. | 436 // Get field offset, which is a 32-bit integer. |
438 ExternalReference cache_field_offsets | 437 ExternalReference cache_field_offsets |
439 = ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate()); | 438 = ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate()); |
440 | 439 |
441 // Hit on nth entry. | 440 // Hit on nth entry. |
442 for (int i = kEntriesPerBucket - 1; i >= 0; i--) { | 441 for (int i = kEntriesPerBucket - 1; i >= 0; i--) { |
443 __ bind(&hit_on_nth_entry[i]); | 442 __ bind(&hit_on_nth_entry[i]); |
444 if (i != 0) { | 443 if (i != 0) { |
445 __ addl(rcx, Immediate(i)); | 444 __ addl(rax, Immediate(i)); |
446 } | 445 } |
447 __ LoadAddress(kScratchRegister, cache_field_offsets); | 446 __ LoadAddress(kScratchRegister, cache_field_offsets); |
448 __ movl(rdi, Operand(kScratchRegister, rcx, times_4, 0)); | 447 __ movl(rdi, Operand(kScratchRegister, rax, times_4, 0)); |
449 __ movzxbp(rcx, FieldOperand(rbx, Map::kInObjectPropertiesOffset)); | 448 __ movzxbp(rax, FieldOperand(rbx, Map::kInObjectPropertiesOffset)); |
450 __ subp(rdi, rcx); | 449 __ subp(rdi, rax); |
451 __ j(above_equal, &property_array_property); | 450 __ j(above_equal, &property_array_property); |
452 if (i != 0) { | 451 if (i != 0) { |
453 __ jmp(&load_in_object_property); | 452 __ jmp(&load_in_object_property); |
454 } | 453 } |
455 } | 454 } |
456 | 455 |
457 // Load in-object property. | 456 // Load in-object property. |
458 __ bind(&load_in_object_property); | 457 __ bind(&load_in_object_property); |
459 __ movzxbp(rcx, FieldOperand(rbx, Map::kInstanceSizeOffset)); | 458 __ movzxbp(rax, FieldOperand(rbx, Map::kInstanceSizeOffset)); |
460 __ addp(rcx, rdi); | 459 __ addp(rax, rdi); |
461 __ movp(rax, FieldOperand(rdx, rcx, times_pointer_size, 0)); | 460 __ movp(rax, FieldOperand(receiver, rax, times_pointer_size, 0)); |
462 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1); | 461 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1); |
463 __ ret(0); | 462 __ ret(0); |
464 | 463 |
465 // Load property array property. | 464 // Load property array property. |
466 __ bind(&property_array_property); | 465 __ bind(&property_array_property); |
467 __ movp(rax, FieldOperand(rdx, JSObject::kPropertiesOffset)); | 466 __ movp(rax, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
468 __ movp(rax, FieldOperand(rax, rdi, times_pointer_size, | 467 __ movp(rax, FieldOperand(rax, rdi, times_pointer_size, |
469 FixedArray::kHeaderSize)); | 468 FixedArray::kHeaderSize)); |
470 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1); | 469 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1); |
471 __ ret(0); | 470 __ ret(0); |
472 | 471 |
473 // Do a quick inline probe of the receiver's dictionary, if it | 472 // Do a quick inline probe of the receiver's dictionary, if it |
474 // exists. | 473 // exists. |
475 __ bind(&probe_dictionary); | 474 __ bind(&probe_dictionary); |
476 // rdx: receiver | 475 // receiver: receiver |
477 // rax: key | 476 // key: key |
478 // rbx: elements | 477 // rbx: elements |
479 | 478 |
480 __ movp(rcx, FieldOperand(rdx, JSObject::kMapOffset)); | 479 __ movp(rax, FieldOperand(receiver, JSObject::kMapOffset)); |
481 __ movb(rcx, FieldOperand(rcx, Map::kInstanceTypeOffset)); | 480 __ movb(rax, FieldOperand(rax, Map::kInstanceTypeOffset)); |
482 GenerateGlobalInstanceTypeCheck(masm, rcx, &slow); | 481 GenerateGlobalInstanceTypeCheck(masm, rax, &slow); |
483 | 482 |
484 GenerateDictionaryLoad(masm, &slow, rbx, rax, rcx, rdi, rax); | 483 GenerateDictionaryLoad(masm, &slow, rbx, key, rax, rdi, rax); |
485 __ IncrementCounter(counters->keyed_load_generic_symbol(), 1); | 484 __ IncrementCounter(counters->keyed_load_generic_symbol(), 1); |
486 __ ret(0); | 485 __ ret(0); |
487 | 486 |
488 __ bind(&index_name); | 487 __ bind(&index_name); |
489 __ IndexFromHash(rbx, rax); | 488 __ IndexFromHash(rbx, key); |
490 __ jmp(&index_smi); | 489 __ jmp(&index_smi); |
491 } | 490 } |
492 | 491 |
493 | 492 |
494 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 493 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
495 // Return address is on the stack. | 494 // Return address is on the stack. |
496 Label miss; | 495 Label miss; |
497 | 496 |
498 Register receiver = ReceiverRegister(); | 497 Register receiver = ReceiverRegister(); |
499 Register index = NameRegister(); | 498 Register index = NameRegister(); |
500 Register scratch = rcx; | 499 Register scratch = rbx; |
501 Register result = rax; | 500 Register result = rax; |
502 ASSERT(!scratch.is(receiver) && !scratch.is(index)); | 501 ASSERT(!scratch.is(receiver) && !scratch.is(index)); |
503 | 502 |
504 StringCharAtGenerator char_at_generator(receiver, | 503 StringCharAtGenerator char_at_generator(receiver, |
505 index, | 504 index, |
506 scratch, | 505 scratch, |
507 result, | 506 result, |
508 &miss, // When not a string. | 507 &miss, // When not a string. |
509 &miss, // When not a number. | 508 &miss, // When not a number. |
510 &miss, // When index out of range. | 509 &miss, // When index out of range. |
511 STRING_INDEX_IS_ARRAY_INDEX); | 510 STRING_INDEX_IS_ARRAY_INDEX); |
512 char_at_generator.GenerateFast(masm); | 511 char_at_generator.GenerateFast(masm); |
513 __ ret(0); | 512 __ ret(0); |
514 | 513 |
515 StubRuntimeCallHelper call_helper; | 514 StubRuntimeCallHelper call_helper; |
516 char_at_generator.GenerateSlow(masm, call_helper); | 515 char_at_generator.GenerateSlow(masm, call_helper); |
517 | 516 |
518 __ bind(&miss); | 517 __ bind(&miss); |
519 GenerateMiss(masm); | 518 GenerateMiss(masm); |
520 } | 519 } |
521 | 520 |
522 | 521 |
523 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { | 522 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { |
524 // Return address is on the stack. | 523 // Return address is on the stack. |
525 Label slow; | 524 Label slow; |
526 | 525 |
527 Register receiver = ReceiverRegister(); | 526 Register receiver = ReceiverRegister(); |
528 Register key = NameRegister(); | 527 Register key = NameRegister(); |
529 Register scratch = rcx; | 528 Register scratch = rax; |
530 ASSERT(!scratch.is(receiver) && !scratch.is(key)); | 529 ASSERT(!scratch.is(receiver) && !scratch.is(key)); |
531 | 530 |
532 // Check that the receiver isn't a smi. | 531 // Check that the receiver isn't a smi. |
533 __ JumpIfSmi(receiver, &slow); | 532 __ JumpIfSmi(receiver, &slow); |
534 | 533 |
535 // Check that the key is an array index, that is Uint32. | 534 // Check that the key is an array index, that is Uint32. |
536 STATIC_ASSERT(kSmiValueSize <= 32); | 535 STATIC_ASSERT(kSmiValueSize <= 32); |
537 __ JumpUnlessNonNegativeSmi(key, &slow); | 536 __ JumpUnlessNonNegativeSmi(key, &slow); |
538 | 537 |
539 // Get the map of the receiver. | 538 // Get the map of the receiver. |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
880 __ j(greater_equal, slow_case); | 879 __ j(greater_equal, slow_case); |
881 __ SmiToInteger64(scratch, key); | 880 __ SmiToInteger64(scratch, key); |
882 return FieldOperand(backing_store, | 881 return FieldOperand(backing_store, |
883 scratch, | 882 scratch, |
884 times_pointer_size, | 883 times_pointer_size, |
885 FixedArray::kHeaderSize); | 884 FixedArray::kHeaderSize); |
886 } | 885 } |
887 | 886 |
888 | 887 |
889 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { | 888 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { |
890 // ----------- S t a t e ------------- | 889 // The return address is on the stack. |
891 // -- rax : key | 890 Register receiver = ReceiverRegister(); |
892 // -- rdx : receiver | 891 Register key = NameRegister(); |
893 // -- rsp[0] : return address | 892 ASSERT(receiver.is(rdx)); |
894 // ----------------------------------- | 893 ASSERT(key.is(rcx)); |
895 ASSERT(rdx.is(ReceiverRegister())); | 894 |
896 ASSERT(rax.is(NameRegister())); | |
897 Label slow, notin; | 895 Label slow, notin; |
898 Operand mapped_location = | 896 Operand mapped_location = |
899 GenerateMappedArgumentsLookup( | 897 GenerateMappedArgumentsLookup( |
900 masm, rdx, rax, rbx, rcx, rdi, ¬in, &slow); | 898 masm, receiver, key, rbx, rax, rdi, ¬in, &slow); |
901 __ movp(rax, mapped_location); | 899 __ movp(rax, mapped_location); |
902 __ Ret(); | 900 __ Ret(); |
903 __ bind(¬in); | 901 __ bind(¬in); |
904 // The unmapped lookup expects that the parameter map is in rbx. | 902 // The unmapped lookup expects that the parameter map is in rbx. |
905 Operand unmapped_location = | 903 Operand unmapped_location = |
906 GenerateUnmappedArgumentsLookup(masm, rax, rbx, rcx, &slow); | 904 GenerateUnmappedArgumentsLookup(masm, key, rbx, rax, &slow); |
907 __ CompareRoot(unmapped_location, Heap::kTheHoleValueRootIndex); | 905 __ CompareRoot(unmapped_location, Heap::kTheHoleValueRootIndex); |
908 __ j(equal, &slow); | 906 __ j(equal, &slow); |
909 __ movp(rax, unmapped_location); | 907 __ movp(rax, unmapped_location); |
910 __ Ret(); | 908 __ Ret(); |
911 __ bind(&slow); | 909 __ bind(&slow); |
912 GenerateMiss(masm); | 910 GenerateMiss(masm); |
913 } | 911 } |
914 | 912 |
915 | 913 |
916 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { | 914 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { |
(...skipping 30 matching lines...) Expand all Loading... | |
947 EMIT_REMEMBERED_SET, | 945 EMIT_REMEMBERED_SET, |
948 INLINE_SMI_CHECK); | 946 INLINE_SMI_CHECK); |
949 __ Ret(); | 947 __ Ret(); |
950 __ bind(&slow); | 948 __ bind(&slow); |
951 GenerateMiss(masm); | 949 GenerateMiss(masm); |
952 } | 950 } |
953 | 951 |
954 | 952 |
955 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { | 953 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
956 // ----------- S t a t e ------------- | 954 // ----------- S t a t e ------------- |
957 // -- rax : receiver | 955 // -- rdx : receiver |
958 // -- rcx : name | 956 // -- rcx : name |
959 // -- rsp[0] : return address | 957 // -- rsp[0] : return address |
960 // ----------------------------------- | 958 // ----------------------------------- |
961 ASSERT(rax.is(ReceiverRegister())); | 959 ASSERT(rdx.is(ReceiverRegister())); |
962 ASSERT(rcx.is(NameRegister())); | 960 ASSERT(rcx.is(NameRegister())); |
963 | 961 |
964 // Probe the stub cache. | 962 // Probe the stub cache. |
965 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); | 963 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); |
966 masm->isolate()->stub_cache()->GenerateProbe( | 964 masm->isolate()->stub_cache()->GenerateProbe( |
967 masm, flags, rax, rcx, rbx, rdx); | 965 masm, flags, rdx, rcx, rbx, rax); |
968 | 966 |
969 GenerateMiss(masm); | 967 GenerateMiss(masm); |
970 } | 968 } |
971 | 969 |
972 | 970 |
973 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 971 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
974 // ----------- S t a t e ------------- | 972 // ----------- S t a t e ------------- |
975 // -- rax : receiver | 973 // -- rdx : receiver |
976 // -- rcx : name | 974 // -- rcx : name |
977 // -- rsp[0] : return address | 975 // -- rsp[0] : return address |
978 // ----------------------------------- | 976 // ----------------------------------- |
979 ASSERT(rax.is(ReceiverRegister())); | 977 ASSERT(rdx.is(ReceiverRegister())); |
980 ASSERT(rcx.is(NameRegister())); | 978 ASSERT(rcx.is(NameRegister())); |
981 Label miss, slow; | 979 Label miss, slow; |
982 | 980 |
983 GenerateNameDictionaryReceiverCheck(masm, rax, rdx, rbx, &miss); | 981 GenerateNameDictionaryReceiverCheck(masm, rdx, rax, rbx, &miss); |
984 | 982 |
985 // rdx: elements | 983 // rax: elements |
986 // Search the dictionary placing the result in rax. | 984 // Search the dictionary placing the result in rax. |
987 GenerateDictionaryLoad(masm, &slow, rdx, rcx, rbx, rdi, rax); | 985 GenerateDictionaryLoad(masm, &slow, rax, rcx, rbx, rdi, rax); |
988 __ ret(0); | 986 __ ret(0); |
989 | 987 |
990 // Dictionary load failed, go slow (but don't miss). | 988 // Dictionary load failed, go slow (but don't miss). |
991 __ bind(&slow); | 989 __ bind(&slow); |
992 GenerateRuntimeGetProperty(masm); | 990 GenerateRuntimeGetProperty(masm); |
993 | 991 |
994 // Cache miss: Jump to runtime. | 992 // Cache miss: Jump to runtime. |
995 __ bind(&miss); | 993 __ bind(&miss); |
996 GenerateMiss(masm); | 994 GenerateMiss(masm); |
997 } | 995 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1048 __ PushReturnAddressFrom(KeyedLoadIC_TempRegister()); | 1046 __ PushReturnAddressFrom(KeyedLoadIC_TempRegister()); |
1049 | 1047 |
1050 // Perform tail call to the entry. | 1048 // Perform tail call to the entry. |
1051 ExternalReference ref = | 1049 ExternalReference ref = |
1052 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate()); | 1050 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate()); |
1053 __ TailCallExternalReference(ref, 2, 1); | 1051 __ TailCallExternalReference(ref, 2, 1); |
1054 } | 1052 } |
1055 | 1053 |
1056 | 1054 |
1057 // IC register specifications | 1055 // IC register specifications |
1058 const Register LoadIC::ReceiverRegister() { return rax; } | 1056 const Register LoadIC::ReceiverRegister() { return rdx; } |
1059 const Register LoadIC::NameRegister() { return rcx; } | 1057 const Register LoadIC::NameRegister() { return rcx; } |
1060 const Register KeyedLoadIC::ReceiverRegister() { return rdx; } | |
1061 const Register KeyedLoadIC::NameRegister() { return rax; } | |
1062 | 1058 |
1063 | 1059 |
1064 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | 1060 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
1065 // The return address is on the stack. | 1061 // The return address is on the stack. |
1066 | 1062 |
1067 __ PopReturnAddressTo(KeyedLoadIC_TempRegister()); | 1063 __ PopReturnAddressTo(KeyedLoadIC_TempRegister()); |
1068 __ Push(ReceiverRegister()); // receiver | 1064 __ Push(ReceiverRegister()); // receiver |
1069 __ Push(NameRegister()); // name | 1065 __ Push(NameRegister()); // name |
1070 __ PushReturnAddressFrom(KeyedLoadIC_TempRegister()); | 1066 __ PushReturnAddressFrom(KeyedLoadIC_TempRegister()); |
1071 | 1067 |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1307 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) | 1303 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) |
1308 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 1304 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
1309 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 1305 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
1310 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1306 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
1311 } | 1307 } |
1312 | 1308 |
1313 | 1309 |
1314 } } // namespace v8::internal | 1310 } } // namespace v8::internal |
1315 | 1311 |
1316 #endif // V8_TARGET_ARCH_X64 | 1312 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |