OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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/code-stub-assembler.h" | 5 #include "src/code-stub-assembler.h" |
6 #include "src/code-factory.h" | 6 #include "src/code-factory.h" |
7 #include "src/frames-inl.h" | 7 #include "src/frames-inl.h" |
8 #include "src/frames.h" | 8 #include "src/frames.h" |
9 #include "src/ic/handler-configuration.h" | 9 #include "src/ic/handler-configuration.h" |
10 #include "src/ic/stub-cache.h" | 10 #include "src/ic/stub-cache.h" |
(...skipping 4710 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4721 LoadFixedArrayElement(feedback, index, kPointerSize, INTPTR_PARAMETERS); | 4721 LoadFixedArrayElement(feedback, index, kPointerSize, INTPTR_PARAMETERS); |
4722 var_handler->Bind(handler); | 4722 var_handler->Bind(handler); |
4723 Goto(if_handler); | 4723 Goto(if_handler); |
4724 | 4724 |
4725 Bind(&next_entry); | 4725 Bind(&next_entry); |
4726 var_index.Bind(IntPtrAdd(index, IntPtrConstant(kEntrySize))); | 4726 var_index.Bind(IntPtrAdd(index, IntPtrConstant(kEntrySize))); |
4727 Goto(&loop); | 4727 Goto(&loop); |
4728 } | 4728 } |
4729 } | 4729 } |
4730 | 4730 |
| 4731 void CodeStubAssembler::HandleKeyedStorePolymorphicCase( |
| 4732 compiler::Node* receiver_map, compiler::Node* feedback, Label* if_handler, |
| 4733 Variable* var_handler, Label* if_transition_handler, |
| 4734 Variable* var_transition_map_cell, Label* if_miss) { |
| 4735 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); |
| 4736 DCHECK_EQ(MachineRepresentation::kTagged, var_transition_map_cell->rep()); |
| 4737 |
| 4738 const int kEntrySize = 3; |
| 4739 |
| 4740 Variable var_index(this, MachineType::PointerRepresentation()); |
| 4741 Label loop(this, &var_index); |
| 4742 var_index.Bind(IntPtrConstant(0)); |
| 4743 Node* length = LoadAndUntagFixedArrayBaseLength(feedback); |
| 4744 Goto(&loop); |
| 4745 Bind(&loop); |
| 4746 { |
| 4747 Node* index = var_index.value(); |
| 4748 GotoIf(UintPtrGreaterThanOrEqual(index, length), if_miss); |
| 4749 |
| 4750 Node* cached_map = LoadWeakCellValue( |
| 4751 LoadFixedArrayElement(feedback, index, 0, INTPTR_PARAMETERS)); |
| 4752 |
| 4753 Label next_entry(this); |
| 4754 GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); |
| 4755 |
| 4756 Node* maybe_transition_map_cell = |
| 4757 LoadFixedArrayElement(feedback, index, kPointerSize, INTPTR_PARAMETERS); |
| 4758 |
| 4759 var_handler->Bind(LoadFixedArrayElement(feedback, index, 2 * kPointerSize, |
| 4760 INTPTR_PARAMETERS)); |
| 4761 GotoIf(WordEqual(maybe_transition_map_cell, |
| 4762 LoadRoot(Heap::kUndefinedValueRootIndex)), |
| 4763 if_handler); |
| 4764 var_transition_map_cell->Bind(maybe_transition_map_cell); |
| 4765 Goto(if_transition_handler); |
| 4766 |
| 4767 Bind(&next_entry); |
| 4768 var_index.Bind(IntPtrAdd(index, IntPtrConstant(kEntrySize))); |
| 4769 Goto(&loop); |
| 4770 } |
| 4771 } |
| 4772 |
4731 compiler::Node* CodeStubAssembler::StubCachePrimaryOffset(compiler::Node* name, | 4773 compiler::Node* CodeStubAssembler::StubCachePrimaryOffset(compiler::Node* name, |
4732 compiler::Node* map) { | 4774 compiler::Node* map) { |
4733 // See v8::internal::StubCache::PrimaryOffset(). | 4775 // See v8::internal::StubCache::PrimaryOffset(). |
4734 STATIC_ASSERT(StubCache::kCacheIndexShift == Name::kHashShift); | 4776 STATIC_ASSERT(StubCache::kCacheIndexShift == Name::kHashShift); |
4735 // Compute the hash of the name (use entire hash field). | 4777 // Compute the hash of the name (use entire hash field). |
4736 Node* hash_field = LoadNameHashField(name); | 4778 Node* hash_field = LoadNameHashField(name); |
4737 CSA_ASSERT(Word32Equal( | 4779 CSA_ASSERT(Word32Equal( |
4738 Word32And(hash_field, Int32Constant(Name::kHashNotComputedMask)), | 4780 Word32And(hash_field, Int32Constant(Name::kHashNotComputedMask)), |
4739 Int32Constant(0))); | 4781 Int32Constant(0))); |
4740 | 4782 |
(...skipping 821 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5562 TryProbeStubCache(isolate()->store_stub_cache(), p->receiver, p->name, | 5604 TryProbeStubCache(isolate()->store_stub_cache(), p->receiver, p->name, |
5563 &if_handler, &var_handler, &miss); | 5605 &if_handler, &var_handler, &miss); |
5564 } | 5606 } |
5565 Bind(&miss); | 5607 Bind(&miss); |
5566 { | 5608 { |
5567 TailCallRuntime(Runtime::kStoreIC_Miss, p->context, p->value, p->slot, | 5609 TailCallRuntime(Runtime::kStoreIC_Miss, p->context, p->value, p->slot, |
5568 p->vector, p->receiver, p->name); | 5610 p->vector, p->receiver, p->name); |
5569 } | 5611 } |
5570 } | 5612 } |
5571 | 5613 |
| 5614 void CodeStubAssembler::KeyedStoreIC(const StoreICParameters* p, |
| 5615 LanguageMode language_mode) { |
| 5616 Variable var_handler(this, MachineRepresentation::kTagged); |
| 5617 // TODO(ishell): defer blocks when it works. |
| 5618 Label if_handler(this, &var_handler), try_polymorphic(this), |
| 5619 try_megamorphic(this /*, Label::kDeferred*/), |
| 5620 try_polymorphic_name(this /*, Label::kDeferred*/), |
| 5621 miss(this /*, Label::kDeferred*/); |
| 5622 |
| 5623 Node* receiver_map = LoadReceiverMap(p->receiver); |
| 5624 |
| 5625 // Check monomorphic case. |
| 5626 Node* feedback = |
| 5627 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
| 5628 &var_handler, &try_polymorphic); |
| 5629 Bind(&if_handler); |
| 5630 { |
| 5631 Comment("KeyedStoreIC_if_handler"); |
| 5632 StoreWithVectorDescriptor descriptor(isolate()); |
| 5633 TailCallStub(descriptor, var_handler.value(), p->context, p->receiver, |
| 5634 p->name, p->value, p->slot, p->vector); |
| 5635 } |
| 5636 |
| 5637 Bind(&try_polymorphic); |
| 5638 { |
| 5639 // CheckPolymorphic case. |
| 5640 Comment("KeyedStoreIC_try_polymorphic"); |
| 5641 GotoUnless( |
| 5642 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), |
| 5643 &try_megamorphic); |
| 5644 Label if_transition_handler(this); |
| 5645 Variable var_transition_map_cell(this, MachineRepresentation::kTagged); |
| 5646 HandleKeyedStorePolymorphicCase(receiver_map, feedback, &if_handler, |
| 5647 &var_handler, &if_transition_handler, |
| 5648 &var_transition_map_cell, &miss); |
| 5649 Bind(&if_transition_handler); |
| 5650 Comment("KeyedStoreIC_polymorphic_transition"); |
| 5651 Node* transition_map = |
| 5652 LoadWeakCellValue(var_transition_map_cell.value(), &miss); |
| 5653 StoreTransitionDescriptor descriptor(isolate()); |
| 5654 TailCallStub(descriptor, var_handler.value(), p->context, p->receiver, |
| 5655 p->name, transition_map, p->value, p->slot, p->vector); |
| 5656 } |
| 5657 |
| 5658 Bind(&try_megamorphic); |
| 5659 { |
| 5660 // Check megamorphic case. |
| 5661 Comment("KeyedStoreIC_try_megamorphic"); |
| 5662 GotoUnless( |
| 5663 WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), |
| 5664 &try_polymorphic_name); |
| 5665 TailCallStub( |
| 5666 CodeFactory::KeyedStoreIC_Megamorphic(isolate(), language_mode), |
| 5667 p->context, p->receiver, p->name, p->value, p->slot, p->vector); |
| 5668 } |
| 5669 |
| 5670 Bind(&try_polymorphic_name); |
| 5671 { |
| 5672 // We might have a name in feedback, and a fixed array in the next slot. |
| 5673 Comment("KeyedStoreIC_try_polymorphic_name"); |
| 5674 GotoUnless(WordEqual(feedback, p->name), &miss); |
| 5675 // If the name comparison succeeded, we know we have a FixedArray with |
| 5676 // at least one map/handler pair. |
| 5677 Node* offset = ElementOffsetFromIndex( |
| 5678 p->slot, FAST_HOLEY_ELEMENTS, SMI_PARAMETERS, |
| 5679 FixedArray::kHeaderSize + kPointerSize - kHeapObjectTag); |
| 5680 Node* array = Load(MachineType::AnyTagged(), p->vector, offset); |
| 5681 HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler, &miss, |
| 5682 1); |
| 5683 } |
| 5684 |
| 5685 Bind(&miss); |
| 5686 { |
| 5687 Comment("KeyedStoreIC_miss"); |
| 5688 TailCallRuntime(Runtime::kKeyedStoreIC_Miss, p->context, p->value, p->slot, |
| 5689 p->vector, p->receiver, p->name); |
| 5690 } |
| 5691 } |
| 5692 |
5572 void CodeStubAssembler::LoadGlobalIC(const LoadICParameters* p) { | 5693 void CodeStubAssembler::LoadGlobalIC(const LoadICParameters* p) { |
5573 Label try_handler(this), miss(this); | 5694 Label try_handler(this), miss(this); |
5574 Node* weak_cell = | 5695 Node* weak_cell = |
5575 LoadFixedArrayElement(p->vector, p->slot, 0, SMI_PARAMETERS); | 5696 LoadFixedArrayElement(p->vector, p->slot, 0, SMI_PARAMETERS); |
5576 AssertInstanceType(weak_cell, WEAK_CELL_TYPE); | 5697 AssertInstanceType(weak_cell, WEAK_CELL_TYPE); |
5577 | 5698 |
5578 // Load value or try handler case if the {weak_cell} is cleared. | 5699 // Load value or try handler case if the {weak_cell} is cleared. |
5579 Node* property_cell = LoadWeakCellValue(weak_cell, &try_handler); | 5700 Node* property_cell = LoadWeakCellValue(weak_cell, &try_handler); |
5580 AssertInstanceType(property_cell, PROPERTY_CELL_TYPE); | 5701 AssertInstanceType(property_cell, PROPERTY_CELL_TYPE); |
5581 | 5702 |
(...skipping 2486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8068 Node* buffer_bit_field = LoadObjectField( | 8189 Node* buffer_bit_field = LoadObjectField( |
8069 buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32()); | 8190 buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32()); |
8070 Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask); | 8191 Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask); |
8071 | 8192 |
8072 return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask), | 8193 return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask), |
8073 Int32Constant(0)); | 8194 Int32Constant(0)); |
8074 } | 8195 } |
8075 | 8196 |
8076 } // namespace internal | 8197 } // namespace internal |
8077 } // namespace v8 | 8198 } // namespace v8 |
OLD | NEW |