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