Chromium Code Reviews| 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 |