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