| 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_ARM | 7 #if V8_TARGET_ARCH_ARM |
| 8 | 8 |
| 9 #include "src/arm/assembler-arm.h" | 9 #include "src/arm/assembler-arm.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 304 __ ldrb(hash, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 304 __ ldrb(hash, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
| 305 STATIC_ASSERT(kInternalizedTag == 0); | 305 STATIC_ASSERT(kInternalizedTag == 0); |
| 306 __ tst(hash, Operand(kIsNotInternalizedMask)); | 306 __ tst(hash, Operand(kIsNotInternalizedMask)); |
| 307 __ b(ne, not_unique); | 307 __ b(ne, not_unique); |
| 308 | 308 |
| 309 __ bind(&unique); | 309 __ bind(&unique); |
| 310 } | 310 } |
| 311 | 311 |
| 312 | 312 |
| 313 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { | 313 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 314 // ----------- S t a t e ------------- | 314 // The return address is in lr. |
| 315 // -- r2 : name | 315 Register receiver = ReceiverRegister(); |
| 316 // -- lr : return address | 316 Register name = NameRegister(); |
| 317 // -- r0 : receiver | 317 ASSERT(receiver.is(r1)); |
| 318 // ----------------------------------- | 318 ASSERT(name.is(r2)); |
| 319 ASSERT(r0.is(ReceiverRegister())); | |
| 320 ASSERT(r2.is(NameRegister())); | |
| 321 | 319 |
| 322 // Probe the stub cache. | 320 // Probe the stub cache. |
| 323 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); | 321 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); |
| 324 masm->isolate()->stub_cache()->GenerateProbe( | 322 masm->isolate()->stub_cache()->GenerateProbe( |
| 325 masm, flags, r0, r2, r3, r4, r5, r6); | 323 masm, flags, receiver, name, r3, r4, r5, r6); |
| 326 | 324 |
| 327 // Cache miss: Jump to runtime. | 325 // Cache miss: Jump to runtime. |
| 328 GenerateMiss(masm); | 326 GenerateMiss(masm); |
| 329 } | 327 } |
| 330 | 328 |
| 331 | 329 |
| 332 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 330 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
| 333 // ----------- S t a t e ------------- | 331 // ----------- S t a t e ------------- |
| 334 // -- r2 : name | 332 // -- r2 : name |
| 335 // -- lr : return address | 333 // -- lr : return address |
| 336 // -- r0 : receiver | 334 // -- r1 : receiver |
| 337 // ----------------------------------- | 335 // ----------------------------------- |
| 338 ASSERT(r0.is(ReceiverRegister())); | 336 ASSERT(r1.is(ReceiverRegister())); |
| 339 ASSERT(r2.is(NameRegister())); | 337 ASSERT(r2.is(NameRegister())); |
| 340 | 338 |
| 341 Label miss, slow; | 339 Label miss, slow; |
| 342 | 340 |
| 343 GenerateNameDictionaryReceiverCheck(masm, r0, r1, r3, r4, &miss); | 341 GenerateNameDictionaryReceiverCheck(masm, r1, r0, r3, r4, &miss); |
| 344 | 342 |
| 345 // r1: elements | 343 // r0: elements |
| 346 GenerateDictionaryLoad(masm, &slow, r1, r2, r0, r3, r4); | 344 GenerateDictionaryLoad(masm, &slow, r0, r2, r0, r3, r4); |
| 347 __ Ret(); | 345 __ Ret(); |
| 348 | 346 |
| 349 // Dictionary load failed, go slow (but don't miss). | 347 // Dictionary load failed, go slow (but don't miss). |
| 350 __ bind(&slow); | 348 __ bind(&slow); |
| 351 GenerateRuntimeGetProperty(masm); | 349 GenerateRuntimeGetProperty(masm); |
| 352 | 350 |
| 353 // Cache miss: Jump to runtime. | 351 // Cache miss: Jump to runtime. |
| 354 __ bind(&miss); | 352 __ bind(&miss); |
| 355 GenerateMiss(masm); | 353 GenerateMiss(masm); |
| 356 } | 354 } |
| 357 | 355 |
| 358 | 356 |
| 359 // A register that isn't one of the parameters to the load ic. | 357 // A register that isn't one of the parameters to the load ic. |
| 360 static const Register LoadIC_TempRegister() { return r3; } | 358 static const Register LoadIC_TempRegister() { return r3; } |
| 361 | 359 |
| 362 | 360 |
| 363 void LoadIC::GenerateMiss(MacroAssembler* masm) { | 361 void LoadIC::GenerateMiss(MacroAssembler* masm) { |
| 364 // The return address is on the stack. | 362 // The return address is in lr. |
| 365 Isolate* isolate = masm->isolate(); | 363 Isolate* isolate = masm->isolate(); |
| 366 | 364 |
| 367 __ IncrementCounter(isolate->counters()->load_miss(), 1, r3, r4); | 365 __ IncrementCounter(isolate->counters()->load_miss(), 1, r3, r4); |
| 368 | 366 |
| 369 __ mov(LoadIC_TempRegister(), ReceiverRegister()); | 367 __ mov(LoadIC_TempRegister(), ReceiverRegister()); |
| 370 __ Push(LoadIC_TempRegister(), NameRegister()); | 368 __ Push(LoadIC_TempRegister(), NameRegister()); |
| 371 | 369 |
| 372 // Perform tail call to the entry. | 370 // Perform tail call to the entry. |
| 373 ExternalReference ref = | 371 ExternalReference ref = |
| 374 ExternalReference(IC_Utility(kLoadIC_Miss), isolate); | 372 ExternalReference(IC_Utility(kLoadIC_Miss), isolate); |
| 375 __ TailCallExternalReference(ref, 2, 1); | 373 __ TailCallExternalReference(ref, 2, 1); |
| 376 } | 374 } |
| 377 | 375 |
| 378 | 376 |
| 379 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | 377 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
| 380 // The return address is on the stack. | 378 // The return address is in lr. |
| 381 | 379 |
| 382 __ mov(LoadIC_TempRegister(), ReceiverRegister()); | 380 __ mov(LoadIC_TempRegister(), ReceiverRegister()); |
| 383 __ Push(LoadIC_TempRegister(), NameRegister()); | 381 __ Push(LoadIC_TempRegister(), NameRegister()); |
| 384 | 382 |
| 385 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); | 383 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); |
| 386 } | 384 } |
| 387 | 385 |
| 388 | 386 |
| 389 static MemOperand GenerateMappedArgumentsLookup(MacroAssembler* masm, | 387 static MemOperand GenerateMappedArgumentsLookup(MacroAssembler* masm, |
| 390 Register object, | 388 Register object, |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 __ mov(scratch, Operand(kPointerSize >> 1)); | 463 __ mov(scratch, Operand(kPointerSize >> 1)); |
| 466 __ mul(scratch, key, scratch); | 464 __ mul(scratch, key, scratch); |
| 467 __ add(scratch, | 465 __ add(scratch, |
| 468 scratch, | 466 scratch, |
| 469 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 467 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 470 return MemOperand(backing_store, scratch); | 468 return MemOperand(backing_store, scratch); |
| 471 } | 469 } |
| 472 | 470 |
| 473 | 471 |
| 474 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { | 472 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { |
| 475 // ---------- S t a t e -------------- | 473 // The return address is in lr. |
| 476 // -- lr : return address | 474 Register receiver = ReceiverRegister(); |
| 477 // -- r0 : key | 475 Register key = NameRegister(); |
| 478 // -- r1 : receiver | 476 ASSERT(receiver.is(r1)); |
| 479 // ----------------------------------- | 477 ASSERT(key.is(r2)); |
| 480 ASSERT(r1.is(ReceiverRegister())); | 478 |
| 481 ASSERT(r0.is(NameRegister())); | |
| 482 Label slow, notin; | 479 Label slow, notin; |
| 483 MemOperand mapped_location = | 480 MemOperand mapped_location = |
| 484 GenerateMappedArgumentsLookup(masm, r1, r0, r2, r3, r4, ¬in, &slow); | 481 GenerateMappedArgumentsLookup( |
| 482 masm, receiver, key, r0, r3, r4, ¬in, &slow); |
| 485 __ ldr(r0, mapped_location); | 483 __ ldr(r0, mapped_location); |
| 486 __ Ret(); | 484 __ Ret(); |
| 487 __ bind(¬in); | 485 __ bind(¬in); |
| 488 // The unmapped lookup expects that the parameter map is in r2. | 486 // The unmapped lookup expects that the parameter map is in r0. |
| 489 MemOperand unmapped_location = | 487 MemOperand unmapped_location = |
| 490 GenerateUnmappedArgumentsLookup(masm, r0, r2, r3, &slow); | 488 GenerateUnmappedArgumentsLookup(masm, key, r0, r3, &slow); |
| 491 __ ldr(r2, unmapped_location); | 489 __ ldr(r0, unmapped_location); |
| 492 __ LoadRoot(r3, Heap::kTheHoleValueRootIndex); | 490 __ LoadRoot(r3, Heap::kTheHoleValueRootIndex); |
| 493 __ cmp(r2, r3); | 491 __ cmp(r0, r3); |
| 494 __ b(eq, &slow); | 492 __ b(eq, &slow); |
| 495 __ mov(r0, r2); | |
| 496 __ Ret(); | 493 __ Ret(); |
| 497 __ bind(&slow); | 494 __ bind(&slow); |
| 498 GenerateMiss(masm); | 495 GenerateMiss(masm); |
| 499 } | 496 } |
| 500 | 497 |
| 501 | 498 |
| 502 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { | 499 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { |
| 503 // ---------- S t a t e -------------- | 500 // ---------- S t a t e -------------- |
| 504 // -- r0 : value | 501 // -- r0 : value |
| 505 // -- r1 : key | 502 // -- r1 : key |
| (...skipping 16 matching lines...) Expand all Loading... |
| 522 __ add(r6, r3, r4); | 519 __ add(r6, r3, r4); |
| 523 __ mov(r9, r0); | 520 __ mov(r9, r0); |
| 524 __ RecordWrite(r3, r6, r9, kLRHasNotBeenSaved, kDontSaveFPRegs); | 521 __ RecordWrite(r3, r6, r9, kLRHasNotBeenSaved, kDontSaveFPRegs); |
| 525 __ Ret(); | 522 __ Ret(); |
| 526 __ bind(&slow); | 523 __ bind(&slow); |
| 527 GenerateMiss(masm); | 524 GenerateMiss(masm); |
| 528 } | 525 } |
| 529 | 526 |
| 530 | 527 |
| 531 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { | 528 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { |
| 532 // The return address is on the stack. | 529 // The return address is in lr. |
| 533 Isolate* isolate = masm->isolate(); | 530 Isolate* isolate = masm->isolate(); |
| 534 | 531 |
| 535 __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, r3, r4); | 532 __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, r3, r4); |
| 536 | 533 |
| 537 __ Push(ReceiverRegister(), NameRegister()); | 534 __ Push(ReceiverRegister(), NameRegister()); |
| 538 | 535 |
| 539 // Perform tail call to the entry. | 536 // Perform tail call to the entry. |
| 540 ExternalReference ref = | 537 ExternalReference ref = |
| 541 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate); | 538 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate); |
| 542 | 539 |
| 543 __ TailCallExternalReference(ref, 2, 1); | 540 __ TailCallExternalReference(ref, 2, 1); |
| 544 } | 541 } |
| 545 | 542 |
| 546 | 543 |
| 547 // IC register specifications | 544 // IC register specifications |
| 548 const Register LoadIC::ReceiverRegister() { return r0; } | 545 const Register LoadIC::ReceiverRegister() { return r1; } |
| 549 const Register LoadIC::NameRegister() { return r2; } | 546 const Register LoadIC::NameRegister() { return r2; } |
| 550 const Register KeyedLoadIC::ReceiverRegister() { return r1; } | |
| 551 const Register KeyedLoadIC::NameRegister() { return r0; } | |
| 552 | 547 |
| 553 | 548 |
| 554 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | 549 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
| 555 // The return address is on the stack. | 550 // The return address is in lr. |
| 556 | 551 |
| 557 __ Push(ReceiverRegister(), NameRegister()); | 552 __ Push(ReceiverRegister(), NameRegister()); |
| 558 | 553 |
| 559 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | 554 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
| 560 } | 555 } |
| 561 | 556 |
| 562 | 557 |
| 563 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 558 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
| 564 // ---------- S t a t e -------------- | 559 // The return address is in lr. |
| 565 // -- lr : return address | |
| 566 // -- r0 : key | |
| 567 // -- r1 : receiver | |
| 568 // ----------------------------------- | |
| 569 Label slow, check_name, index_smi, index_name, property_array_property; | 560 Label slow, check_name, index_smi, index_name, property_array_property; |
| 570 Label probe_dictionary, check_number_dictionary; | 561 Label probe_dictionary, check_number_dictionary; |
| 571 | 562 |
| 572 Register key = NameRegister(); | 563 Register key = NameRegister(); |
| 573 Register receiver = ReceiverRegister(); | 564 Register receiver = ReceiverRegister(); |
| 574 ASSERT(key.is(r0)); | 565 ASSERT(key.is(r2)); |
| 575 ASSERT(receiver.is(r1)); | 566 ASSERT(receiver.is(r1)); |
| 576 | 567 |
| 577 Isolate* isolate = masm->isolate(); | 568 Isolate* isolate = masm->isolate(); |
| 578 | 569 |
| 579 // Check that the key is a smi. | 570 // Check that the key is a smi. |
| 580 __ JumpIfNotSmi(key, &check_name); | 571 __ JumpIfNotSmi(key, &check_name); |
| 581 __ bind(&index_smi); | 572 __ bind(&index_smi); |
| 582 // Now the key is known to be a smi. This place is also jumped to from below | 573 // Now the key is known to be a smi. This place is also jumped to from below |
| 583 // where a numeric string is converted to a smi. | 574 // where a numeric string is converted to a smi. |
| 584 | 575 |
| 585 GenerateKeyedLoadReceiverCheck( | 576 GenerateKeyedLoadReceiverCheck( |
| 586 masm, receiver, r2, r3, Map::kHasIndexedInterceptor, &slow); | 577 masm, receiver, r0, r3, Map::kHasIndexedInterceptor, &slow); |
| 587 | 578 |
| 588 // Check the receiver's map to see if it has fast elements. | 579 // Check the receiver's map to see if it has fast elements. |
| 589 __ CheckFastElements(r2, r3, &check_number_dictionary); | 580 __ CheckFastElements(r0, r3, &check_number_dictionary); |
| 590 | 581 |
| 591 GenerateFastArrayLoad( | 582 GenerateFastArrayLoad( |
| 592 masm, receiver, key, r4, r3, r2, r0, NULL, &slow); | 583 masm, receiver, key, r0, r3, r4, r0, NULL, &slow); |
| 593 __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r2, r3); | 584 __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r4, r3); |
| 594 __ Ret(); | 585 __ Ret(); |
| 595 | 586 |
| 596 __ bind(&check_number_dictionary); | 587 __ bind(&check_number_dictionary); |
| 597 __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 588 __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| 598 __ ldr(r3, FieldMemOperand(r4, JSObject::kMapOffset)); | 589 __ ldr(r3, FieldMemOperand(r4, JSObject::kMapOffset)); |
| 599 | 590 |
| 600 // Check whether the elements is a number dictionary. | 591 // Check whether the elements is a number dictionary. |
| 601 // r0: key | |
| 602 // r3: elements map | 592 // r3: elements map |
| 603 // r4: elements | 593 // r4: elements |
| 604 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); | 594 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); |
| 605 __ cmp(r3, ip); | 595 __ cmp(r3, ip); |
| 606 __ b(ne, &slow); | 596 __ b(ne, &slow); |
| 607 __ SmiUntag(r2, r0); | 597 __ SmiUntag(r0, key); |
| 608 __ LoadFromNumberDictionary(&slow, r4, r0, r0, r2, r3, r5); | 598 __ LoadFromNumberDictionary(&slow, r4, key, r0, r0, r3, r5); |
| 609 __ Ret(); | 599 __ Ret(); |
| 610 | 600 |
| 611 // Slow case, key and receiver still in r0 and r1. | 601 // Slow case, key and receiver still in r2 and r1. |
| 612 __ bind(&slow); | 602 __ bind(&slow); |
| 613 __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), | 603 __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), |
| 614 1, r2, r3); | 604 1, r4, r3); |
| 615 GenerateRuntimeGetProperty(masm); | 605 GenerateRuntimeGetProperty(masm); |
| 616 | 606 |
| 617 __ bind(&check_name); | 607 __ bind(&check_name); |
| 618 GenerateKeyNameCheck(masm, key, r2, r3, &index_name, &slow); | 608 GenerateKeyNameCheck(masm, key, r0, r3, &index_name, &slow); |
| 619 | 609 |
| 620 GenerateKeyedLoadReceiverCheck( | 610 GenerateKeyedLoadReceiverCheck( |
| 621 masm, receiver, r2, r3, Map::kHasNamedInterceptor, &slow); | 611 masm, receiver, r0, r3, Map::kHasNamedInterceptor, &slow); |
| 622 | 612 |
| 623 // If the receiver is a fast-case object, check the keyed lookup | 613 // If the receiver is a fast-case object, check the keyed lookup |
| 624 // cache. Otherwise probe the dictionary. | 614 // cache. Otherwise probe the dictionary. |
| 625 __ ldr(r3, FieldMemOperand(r1, JSObject::kPropertiesOffset)); | 615 __ ldr(r3, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
| 626 __ ldr(r4, FieldMemOperand(r3, HeapObject::kMapOffset)); | 616 __ ldr(r4, FieldMemOperand(r3, HeapObject::kMapOffset)); |
| 627 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); | 617 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); |
| 628 __ cmp(r4, ip); | 618 __ cmp(r4, ip); |
| 629 __ b(eq, &probe_dictionary); | 619 __ b(eq, &probe_dictionary); |
| 630 | 620 |
| 631 // Load the map of the receiver, compute the keyed lookup cache hash | 621 // Load the map of the receiver, compute the keyed lookup cache hash |
| 632 // based on 32 bits of the map pointer and the name hash. | 622 // based on 32 bits of the map pointer and the name hash. |
| 633 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); | 623 __ ldr(r0, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 634 __ mov(r3, Operand(r2, ASR, KeyedLookupCache::kMapHashShift)); | 624 __ mov(r3, Operand(r0, ASR, KeyedLookupCache::kMapHashShift)); |
| 635 __ ldr(r4, FieldMemOperand(r0, Name::kHashFieldOffset)); | 625 __ ldr(r4, FieldMemOperand(key, Name::kHashFieldOffset)); |
| 636 __ eor(r3, r3, Operand(r4, ASR, Name::kHashShift)); | 626 __ eor(r3, r3, Operand(r4, ASR, Name::kHashShift)); |
| 637 int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask; | 627 int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask; |
| 638 __ And(r3, r3, Operand(mask)); | 628 __ And(r3, r3, Operand(mask)); |
| 639 | 629 |
| 640 // Load the key (consisting of map and unique name) from the cache and | 630 // Load the key (consisting of map and unique name) from the cache and |
| 641 // check for match. | 631 // check for match. |
| 642 Label load_in_object_property; | 632 Label load_in_object_property; |
| 643 static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket; | 633 static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket; |
| 644 Label hit_on_nth_entry[kEntriesPerBucket]; | 634 Label hit_on_nth_entry[kEntriesPerBucket]; |
| 645 ExternalReference cache_keys = | 635 ExternalReference cache_keys = |
| 646 ExternalReference::keyed_lookup_cache_keys(isolate); | 636 ExternalReference::keyed_lookup_cache_keys(isolate); |
| 647 | 637 |
| 648 __ mov(r4, Operand(cache_keys)); | 638 __ mov(r4, Operand(cache_keys)); |
| 649 __ add(r4, r4, Operand(r3, LSL, kPointerSizeLog2 + 1)); | 639 __ add(r4, r4, Operand(r3, LSL, kPointerSizeLog2 + 1)); |
| 650 | 640 |
| 651 for (int i = 0; i < kEntriesPerBucket - 1; i++) { | 641 for (int i = 0; i < kEntriesPerBucket - 1; i++) { |
| 652 Label try_next_entry; | 642 Label try_next_entry; |
| 653 // Load map and move r4 to next entry. | 643 // Load map and move r4 to next entry. |
| 654 __ ldr(r5, MemOperand(r4, kPointerSize * 2, PostIndex)); | 644 __ ldr(r5, MemOperand(r4, kPointerSize * 2, PostIndex)); |
| 655 __ cmp(r2, r5); | 645 __ cmp(r0, r5); |
| 656 __ b(ne, &try_next_entry); | 646 __ b(ne, &try_next_entry); |
| 657 __ ldr(r5, MemOperand(r4, -kPointerSize)); // Load name | 647 __ ldr(r5, MemOperand(r4, -kPointerSize)); // Load name |
| 658 __ cmp(r0, r5); | 648 __ cmp(key, r5); |
| 659 __ b(eq, &hit_on_nth_entry[i]); | 649 __ b(eq, &hit_on_nth_entry[i]); |
| 660 __ bind(&try_next_entry); | 650 __ bind(&try_next_entry); |
| 661 } | 651 } |
| 662 | 652 |
| 663 // Last entry: Load map and move r4 to name. | 653 // Last entry: Load map and move r4 to name. |
| 664 __ ldr(r5, MemOperand(r4, kPointerSize, PostIndex)); | 654 __ ldr(r5, MemOperand(r4, kPointerSize, PostIndex)); |
| 665 __ cmp(r2, r5); | 655 __ cmp(r0, r5); |
| 666 __ b(ne, &slow); | 656 __ b(ne, &slow); |
| 667 __ ldr(r5, MemOperand(r4)); | 657 __ ldr(r5, MemOperand(r4)); |
| 668 __ cmp(r0, r5); | 658 __ cmp(key, r5); |
| 669 __ b(ne, &slow); | 659 __ b(ne, &slow); |
| 670 | 660 |
| 671 // Get field offset. | 661 // Get field offset. |
| 672 // r0 : key | 662 // r0 : receiver's map |
| 673 // r1 : receiver | |
| 674 // r2 : receiver's map | |
| 675 // r3 : lookup cache index | 663 // r3 : lookup cache index |
| 676 ExternalReference cache_field_offsets = | 664 ExternalReference cache_field_offsets = |
| 677 ExternalReference::keyed_lookup_cache_field_offsets(isolate); | 665 ExternalReference::keyed_lookup_cache_field_offsets(isolate); |
| 678 | 666 |
| 679 // Hit on nth entry. | 667 // Hit on nth entry. |
| 680 for (int i = kEntriesPerBucket - 1; i >= 0; i--) { | 668 for (int i = kEntriesPerBucket - 1; i >= 0; i--) { |
| 681 __ bind(&hit_on_nth_entry[i]); | 669 __ bind(&hit_on_nth_entry[i]); |
| 682 __ mov(r4, Operand(cache_field_offsets)); | 670 __ mov(r4, Operand(cache_field_offsets)); |
| 683 if (i != 0) { | 671 if (i != 0) { |
| 684 __ add(r3, r3, Operand(i)); | 672 __ add(r3, r3, Operand(i)); |
| 685 } | 673 } |
| 686 __ ldr(r5, MemOperand(r4, r3, LSL, kPointerSizeLog2)); | 674 __ ldr(r5, MemOperand(r4, r3, LSL, kPointerSizeLog2)); |
| 687 __ ldrb(r6, FieldMemOperand(r2, Map::kInObjectPropertiesOffset)); | 675 __ ldrb(r6, FieldMemOperand(r0, Map::kInObjectPropertiesOffset)); |
| 688 __ sub(r5, r5, r6, SetCC); | 676 __ sub(r5, r5, r6, SetCC); |
| 689 __ b(ge, &property_array_property); | 677 __ b(ge, &property_array_property); |
| 690 if (i != 0) { | 678 if (i != 0) { |
| 691 __ jmp(&load_in_object_property); | 679 __ jmp(&load_in_object_property); |
| 692 } | 680 } |
| 693 } | 681 } |
| 694 | 682 |
| 695 // Load in-object property. | 683 // Load in-object property. |
| 696 __ bind(&load_in_object_property); | 684 __ bind(&load_in_object_property); |
| 697 __ ldrb(r6, FieldMemOperand(r2, Map::kInstanceSizeOffset)); | 685 __ ldrb(r6, FieldMemOperand(r0, Map::kInstanceSizeOffset)); |
| 698 __ add(r6, r6, r5); // Index from start of object. | 686 __ add(r6, r6, r5); // Index from start of object. |
| 699 __ sub(r1, r1, Operand(kHeapObjectTag)); // Remove the heap tag. | 687 __ sub(receiver, receiver, Operand(kHeapObjectTag)); // Remove the heap tag. |
| 700 __ ldr(r0, MemOperand(r1, r6, LSL, kPointerSizeLog2)); | 688 __ ldr(r0, MemOperand(receiver, r6, LSL, kPointerSizeLog2)); |
| 701 __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(), | 689 __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(), |
| 702 1, r2, r3); | 690 1, r4, r3); |
| 703 __ Ret(); | 691 __ Ret(); |
| 704 | 692 |
| 705 // Load property array property. | 693 // Load property array property. |
| 706 __ bind(&property_array_property); | 694 __ bind(&property_array_property); |
| 707 __ ldr(r1, FieldMemOperand(r1, JSObject::kPropertiesOffset)); | 695 __ ldr(receiver, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
| 708 __ add(r1, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 696 __ add(receiver, receiver, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 709 __ ldr(r0, MemOperand(r1, r5, LSL, kPointerSizeLog2)); | 697 __ ldr(r0, MemOperand(receiver, r5, LSL, kPointerSizeLog2)); |
| 710 __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(), | 698 __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(), |
| 711 1, r2, r3); | 699 1, r4, r3); |
| 712 __ Ret(); | 700 __ Ret(); |
| 713 | 701 |
| 714 // Do a quick inline probe of the receiver's dictionary, if it | 702 // Do a quick inline probe of the receiver's dictionary, if it |
| 715 // exists. | 703 // exists. |
| 716 __ bind(&probe_dictionary); | 704 __ bind(&probe_dictionary); |
| 717 // r1: receiver | |
| 718 // r0: key | |
| 719 // r3: elements | 705 // r3: elements |
| 720 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); | 706 __ ldr(r0, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 721 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); | 707 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); |
| 722 GenerateGlobalInstanceTypeCheck(masm, r2, &slow); | 708 GenerateGlobalInstanceTypeCheck(masm, r0, &slow); |
| 723 // Load the property to r0. | 709 // Load the property to r0. |
| 724 GenerateDictionaryLoad(masm, &slow, r3, r0, r0, r2, r4); | 710 GenerateDictionaryLoad(masm, &slow, r3, key, r0, r5, r4); |
| 725 __ IncrementCounter( | 711 __ IncrementCounter( |
| 726 isolate->counters()->keyed_load_generic_symbol(), 1, r2, r3); | 712 isolate->counters()->keyed_load_generic_symbol(), 1, r4, r3); |
| 727 __ Ret(); | 713 __ Ret(); |
| 728 | 714 |
| 729 __ bind(&index_name); | 715 __ bind(&index_name); |
| 730 __ IndexFromHash(r3, key); | 716 __ IndexFromHash(r3, key); |
| 731 // Now jump to the place where smi keys are handled. | 717 // Now jump to the place where smi keys are handled. |
| 732 __ jmp(&index_smi); | 718 __ jmp(&index_smi); |
| 733 } | 719 } |
| 734 | 720 |
| 735 | 721 |
| 736 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 722 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
| 737 // Return address is on the stack. | 723 // Return address is in lr. |
| 738 Label miss; | 724 Label miss; |
| 739 | 725 |
| 740 Register receiver = ReceiverRegister(); | 726 Register receiver = ReceiverRegister(); |
| 741 Register index = NameRegister(); | 727 Register index = NameRegister(); |
| 742 Register scratch = r3; | 728 Register scratch = r3; |
| 743 Register result = r0; | 729 Register result = r0; |
| 744 ASSERT(!scratch.is(receiver) && !scratch.is(index)); | 730 ASSERT(!scratch.is(receiver) && !scratch.is(index)); |
| 745 | 731 |
| 746 StringCharAtGenerator char_at_generator(receiver, | 732 StringCharAtGenerator char_at_generator(receiver, |
| 747 index, | 733 index, |
| 748 scratch, | 734 scratch, |
| 749 result, | 735 result, |
| 750 &miss, // When not a string. | 736 &miss, // When not a string. |
| 751 &miss, // When not a number. | 737 &miss, // When not a number. |
| 752 &miss, // When index out of range. | 738 &miss, // When index out of range. |
| 753 STRING_INDEX_IS_ARRAY_INDEX); | 739 STRING_INDEX_IS_ARRAY_INDEX); |
| 754 char_at_generator.GenerateFast(masm); | 740 char_at_generator.GenerateFast(masm); |
| 755 __ Ret(); | 741 __ Ret(); |
| 756 | 742 |
| 757 StubRuntimeCallHelper call_helper; | 743 StubRuntimeCallHelper call_helper; |
| 758 char_at_generator.GenerateSlow(masm, call_helper); | 744 char_at_generator.GenerateSlow(masm, call_helper); |
| 759 | 745 |
| 760 __ bind(&miss); | 746 __ bind(&miss); |
| 761 GenerateMiss(masm); | 747 GenerateMiss(masm); |
| 762 } | 748 } |
| 763 | 749 |
| 764 | 750 |
| 765 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { | 751 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { |
| 766 // Return address is on the stack. | 752 // Return address is in lr. |
| 767 Label slow; | 753 Label slow; |
| 768 | 754 |
| 769 Register receiver = ReceiverRegister(); | 755 Register receiver = ReceiverRegister(); |
| 770 Register key = NameRegister(); | 756 Register key = NameRegister(); |
| 771 Register scratch1 = r2; | 757 Register scratch1 = r3; |
| 772 Register scratch2 = r3; | 758 Register scratch2 = r4; |
| 773 ASSERT(!scratch1.is(receiver) && !scratch1.is(key)); | 759 ASSERT(!scratch1.is(receiver) && !scratch1.is(key)); |
| 774 ASSERT(!scratch2.is(receiver) && !scratch2.is(key)); | 760 ASSERT(!scratch2.is(receiver) && !scratch2.is(key)); |
| 775 | 761 |
| 776 // Check that the receiver isn't a smi. | 762 // Check that the receiver isn't a smi. |
| 777 __ JumpIfSmi(receiver, &slow); | 763 __ JumpIfSmi(receiver, &slow); |
| 778 | 764 |
| 779 // Check that the key is an array index, that is Uint32. | 765 // Check that the key is an array index, that is Uint32. |
| 780 __ NonNegativeSmiTst(key); | 766 __ NonNegativeSmiTst(key); |
| 781 __ b(ne, &slow); | 767 __ b(ne, &slow); |
| 782 | 768 |
| (...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1316 } else { | 1302 } else { |
| 1317 ASSERT(Assembler::GetCondition(branch_instr) == ne); | 1303 ASSERT(Assembler::GetCondition(branch_instr) == ne); |
| 1318 patcher.EmitCondition(eq); | 1304 patcher.EmitCondition(eq); |
| 1319 } | 1305 } |
| 1320 } | 1306 } |
| 1321 | 1307 |
| 1322 | 1308 |
| 1323 } } // namespace v8::internal | 1309 } } // namespace v8::internal |
| 1324 | 1310 |
| 1325 #endif // V8_TARGET_ARCH_ARM | 1311 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |