| 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 | 5 |
| 6 #include "src/v8.h" | 6 #include "src/v8.h" |
| 7 | 7 |
| 8 #if V8_TARGET_ARCH_MIPS | 8 #if V8_TARGET_ARCH_MIPS |
| 9 | 9 |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 468 | 468 |
| 469 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | 469 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
| 470 // The return address is in ra. | 470 // The return address is in ra. |
| 471 | 471 |
| 472 __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister()); | 472 __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister()); |
| 473 | 473 |
| 474 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | 474 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
| 475 } | 475 } |
| 476 | 476 |
| 477 | 477 |
| 478 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 478 void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 479 // The return address is in ra. | 479 // The return address is in ra. |
| 480 Label slow, check_name, index_smi, index_name, property_array_property; | 480 Label slow, check_name, index_smi, index_name, property_array_property; |
| 481 Label probe_dictionary, check_number_dictionary; | 481 Label probe_dictionary, check_number_dictionary; |
| 482 | 482 |
| 483 Register key = LoadDescriptor::NameRegister(); | 483 Register key = LoadDescriptor::NameRegister(); |
| 484 Register receiver = LoadDescriptor::ReceiverRegister(); | 484 Register receiver = LoadDescriptor::ReceiverRegister(); |
| 485 DCHECK(key.is(a2)); | 485 DCHECK(key.is(a2)); |
| 486 DCHECK(receiver.is(a1)); | 486 DCHECK(receiver.is(a1)); |
| 487 | 487 |
| 488 Isolate* isolate = masm->isolate(); | 488 Isolate* isolate = masm->isolate(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 522 a3); | 522 a3); |
| 523 GenerateRuntimeGetProperty(masm); | 523 GenerateRuntimeGetProperty(masm); |
| 524 | 524 |
| 525 __ bind(&check_name); | 525 __ bind(&check_name); |
| 526 GenerateKeyNameCheck(masm, key, a0, a3, &index_name, &slow); | 526 GenerateKeyNameCheck(masm, key, a0, a3, &index_name, &slow); |
| 527 | 527 |
| 528 GenerateKeyedLoadReceiverCheck(masm, receiver, a0, a3, | 528 GenerateKeyedLoadReceiverCheck(masm, receiver, a0, a3, |
| 529 Map::kHasNamedInterceptor, &slow); | 529 Map::kHasNamedInterceptor, &slow); |
| 530 | 530 |
| 531 | 531 |
| 532 // If the receiver is a fast-case object, check the keyed lookup | 532 // If the receiver is a fast-case object, check the stub cache. Otherwise |
| 533 // cache. Otherwise probe the dictionary. | 533 // probe the dictionary. |
| 534 __ lw(a3, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 534 __ lw(a3, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
| 535 __ lw(t0, FieldMemOperand(a3, HeapObject::kMapOffset)); | 535 __ lw(t0, FieldMemOperand(a3, HeapObject::kMapOffset)); |
| 536 __ LoadRoot(at, Heap::kHashTableMapRootIndex); | 536 __ LoadRoot(at, Heap::kHashTableMapRootIndex); |
| 537 __ Branch(&probe_dictionary, eq, t0, Operand(at)); | 537 __ Branch(&probe_dictionary, eq, t0, Operand(at)); |
| 538 | 538 |
| 539 // Load the map of the receiver, compute the keyed lookup cache hash | 539 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( |
| 540 // based on 32 bits of the map pointer and the name hash. | 540 Code::ComputeHandlerFlags(Code::LOAD_IC)); |
| 541 __ lw(a0, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 541 masm->isolate()->stub_cache()->GenerateProbe( |
| 542 __ sra(a3, a0, KeyedLookupCache::kMapHashShift); | 542 masm, Code::LOAD_IC, flags, false, receiver, key, a3, t0, t1, t2); |
| 543 __ lw(t0, FieldMemOperand(key, Name::kHashFieldOffset)); | 543 // Cache miss. |
| 544 __ sra(at, t0, Name::kHashShift); | 544 GenerateMiss(masm); |
| 545 __ xor_(a3, a3, at); | |
| 546 int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask; | |
| 547 __ And(a3, a3, Operand(mask)); | |
| 548 | |
| 549 // Load the key (consisting of map and unique name) from the cache and | |
| 550 // check for match. | |
| 551 Label load_in_object_property; | |
| 552 static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket; | |
| 553 Label hit_on_nth_entry[kEntriesPerBucket]; | |
| 554 ExternalReference cache_keys = | |
| 555 ExternalReference::keyed_lookup_cache_keys(isolate); | |
| 556 __ li(t0, Operand(cache_keys)); | |
| 557 __ sll(at, a3, kPointerSizeLog2 + 1); | |
| 558 __ addu(t0, t0, at); | |
| 559 | |
| 560 for (int i = 0; i < kEntriesPerBucket - 1; i++) { | |
| 561 Label try_next_entry; | |
| 562 __ lw(t1, MemOperand(t0, kPointerSize * i * 2)); | |
| 563 __ Branch(&try_next_entry, ne, a0, Operand(t1)); | |
| 564 __ lw(t1, MemOperand(t0, kPointerSize * (i * 2 + 1))); | |
| 565 __ Branch(&hit_on_nth_entry[i], eq, key, Operand(t1)); | |
| 566 __ bind(&try_next_entry); | |
| 567 } | |
| 568 | |
| 569 __ lw(t1, MemOperand(t0, kPointerSize * (kEntriesPerBucket - 1) * 2)); | |
| 570 __ Branch(&slow, ne, a0, Operand(t1)); | |
| 571 __ lw(t1, MemOperand(t0, kPointerSize * ((kEntriesPerBucket - 1) * 2 + 1))); | |
| 572 __ Branch(&slow, ne, key, Operand(t1)); | |
| 573 | |
| 574 // Get field offset. | |
| 575 // a0 : receiver's map | |
| 576 // a3 : lookup cache index | |
| 577 ExternalReference cache_field_offsets = | |
| 578 ExternalReference::keyed_lookup_cache_field_offsets(isolate); | |
| 579 | |
| 580 // Hit on nth entry. | |
| 581 for (int i = kEntriesPerBucket - 1; i >= 0; i--) { | |
| 582 __ bind(&hit_on_nth_entry[i]); | |
| 583 __ li(t0, Operand(cache_field_offsets)); | |
| 584 __ sll(at, a3, kPointerSizeLog2); | |
| 585 __ addu(at, t0, at); | |
| 586 __ lw(t1, MemOperand(at, kPointerSize * i)); | |
| 587 __ lbu(t2, FieldMemOperand(a0, Map::kInObjectPropertiesOffset)); | |
| 588 __ Subu(t1, t1, t2); | |
| 589 __ Branch(&property_array_property, ge, t1, Operand(zero_reg)); | |
| 590 if (i != 0) { | |
| 591 __ Branch(&load_in_object_property); | |
| 592 } | |
| 593 } | |
| 594 | |
| 595 // Load in-object property. | |
| 596 __ bind(&load_in_object_property); | |
| 597 __ lbu(t2, FieldMemOperand(a0, Map::kInstanceSizeOffset)); | |
| 598 __ addu(t2, t2, t1); // Index from start of object. | |
| 599 __ Subu(receiver, receiver, Operand(kHeapObjectTag)); // Remove the heap tag. | |
| 600 __ sll(at, t2, kPointerSizeLog2); | |
| 601 __ addu(at, receiver, at); | |
| 602 __ lw(v0, MemOperand(at)); | |
| 603 __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(), 1, | |
| 604 t0, a3); | |
| 605 __ Ret(); | |
| 606 | |
| 607 // Load property array property. | |
| 608 __ bind(&property_array_property); | |
| 609 __ lw(receiver, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | |
| 610 __ Addu(receiver, receiver, FixedArray::kHeaderSize - kHeapObjectTag); | |
| 611 __ sll(v0, t1, kPointerSizeLog2); | |
| 612 __ Addu(v0, v0, receiver); | |
| 613 __ lw(v0, MemOperand(v0)); | |
| 614 __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(), 1, | |
| 615 t0, a3); | |
| 616 __ Ret(); | |
| 617 | |
| 618 | 545 |
| 619 // Do a quick inline probe of the receiver's dictionary, if it | 546 // Do a quick inline probe of the receiver's dictionary, if it |
| 620 // exists. | 547 // exists. |
| 621 __ bind(&probe_dictionary); | 548 __ bind(&probe_dictionary); |
| 622 // a3: elements | 549 // a3: elements |
| 623 __ lw(a0, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 550 __ lw(a0, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 624 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); | 551 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); |
| 625 GenerateGlobalInstanceTypeCheck(masm, a0, &slow); | 552 GenerateGlobalInstanceTypeCheck(masm, a0, &slow); |
| 626 // Load the property to v0. | 553 // Load the property to v0. |
| 627 GenerateDictionaryLoad(masm, &slow, a3, key, v0, t1, t0); | 554 GenerateDictionaryLoad(masm, &slow, a3, key, v0, t1, t0); |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1046 patcher.ChangeBranchCondition(ne); | 973 patcher.ChangeBranchCondition(ne); |
| 1047 } else { | 974 } else { |
| 1048 DCHECK(Assembler::IsBne(branch_instr)); | 975 DCHECK(Assembler::IsBne(branch_instr)); |
| 1049 patcher.ChangeBranchCondition(eq); | 976 patcher.ChangeBranchCondition(eq); |
| 1050 } | 977 } |
| 1051 } | 978 } |
| 1052 } | 979 } |
| 1053 } // namespace v8::internal | 980 } // namespace v8::internal |
| 1054 | 981 |
| 1055 #endif // V8_TARGET_ARCH_MIPS | 982 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |