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 4086 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4097 Bind(&load_receiver_map); | 4097 Bind(&load_receiver_map); |
4098 { | 4098 { |
4099 var_receiver_map.Bind(LoadMap(receiver)); | 4099 var_receiver_map.Bind(LoadMap(receiver)); |
4100 Goto(&if_result); | 4100 Goto(&if_result); |
4101 } | 4101 } |
4102 Bind(&if_result); | 4102 Bind(&if_result); |
4103 return var_receiver_map.value(); | 4103 return var_receiver_map.value(); |
4104 } | 4104 } |
4105 | 4105 |
4106 compiler::Node* CodeStubAssembler::TryMonomorphicCase( | 4106 compiler::Node* CodeStubAssembler::TryMonomorphicCase( |
4107 const LoadICParameters* p, compiler::Node* receiver_map, Label* if_handler, | 4107 compiler::Node* slot, compiler::Node* vector, compiler::Node* receiver_map, |
4108 Variable* var_handler, Label* if_miss) { | 4108 Label* if_handler, Variable* var_handler, Label* if_miss) { |
4109 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); | 4109 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); |
4110 | 4110 |
4111 // TODO(ishell): add helper class that hides offset computations for a series | 4111 // TODO(ishell): add helper class that hides offset computations for a series |
4112 // of loads. | 4112 // of loads. |
4113 int32_t header_size = FixedArray::kHeaderSize - kHeapObjectTag; | 4113 int32_t header_size = FixedArray::kHeaderSize - kHeapObjectTag; |
4114 Node* offset = ElementOffsetFromIndex(p->slot, FAST_HOLEY_ELEMENTS, | 4114 Node* offset = ElementOffsetFromIndex(slot, FAST_HOLEY_ELEMENTS, |
4115 SMI_PARAMETERS, header_size); | 4115 SMI_PARAMETERS, header_size); |
4116 Node* feedback = Load(MachineType::AnyTagged(), p->vector, offset); | 4116 Node* feedback = Load(MachineType::AnyTagged(), vector, offset); |
4117 | 4117 |
4118 // Try to quickly handle the monomorphic case without knowing for sure | 4118 // Try to quickly handle the monomorphic case without knowing for sure |
4119 // if we have a weak cell in feedback. We do know it's safe to look | 4119 // if we have a weak cell in feedback. We do know it's safe to look |
4120 // at WeakCell::kValueOffset. | 4120 // at WeakCell::kValueOffset. |
4121 GotoUnless(WordEqual(receiver_map, LoadWeakCellValue(feedback)), if_miss); | 4121 GotoUnless(WordEqual(receiver_map, LoadWeakCellValue(feedback)), if_miss); |
4122 | 4122 |
4123 Node* handler = Load(MachineType::AnyTagged(), p->vector, | 4123 Node* handler = Load(MachineType::AnyTagged(), vector, |
4124 IntPtrAdd(offset, IntPtrConstant(kPointerSize))); | 4124 IntPtrAdd(offset, IntPtrConstant(kPointerSize))); |
4125 | 4125 |
4126 var_handler->Bind(handler); | 4126 var_handler->Bind(handler); |
4127 Goto(if_handler); | 4127 Goto(if_handler); |
4128 return feedback; | 4128 return feedback; |
4129 } | 4129 } |
4130 | 4130 |
4131 void CodeStubAssembler::HandlePolymorphicCase( | 4131 void CodeStubAssembler::HandlePolymorphicCase( |
4132 const LoadICParameters* p, compiler::Node* receiver_map, | 4132 compiler::Node* receiver_map, compiler::Node* feedback, Label* if_handler, |
4133 compiler::Node* feedback, Label* if_handler, Variable* var_handler, | 4133 Variable* var_handler, Label* if_miss, int unroll_count) { |
4134 Label* if_miss, int unroll_count) { | |
4135 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); | 4134 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); |
4136 | 4135 |
4137 // Iterate {feedback} array. | 4136 // Iterate {feedback} array. |
4138 const int kEntrySize = 2; | 4137 const int kEntrySize = 2; |
4139 | 4138 |
4140 for (int i = 0; i < unroll_count; i++) { | 4139 for (int i = 0; i < unroll_count; i++) { |
4141 Label next_entry(this); | 4140 Label next_entry(this); |
4142 Node* cached_map = LoadWeakCellValue(LoadFixedArrayElement( | 4141 Node* cached_map = LoadWeakCellValue(LoadFixedArrayElement( |
4143 feedback, IntPtrConstant(i * kEntrySize), 0, INTPTR_PARAMETERS)); | 4142 feedback, IntPtrConstant(i * kEntrySize), 0, INTPTR_PARAMETERS)); |
4144 GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); | 4143 GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); |
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4657 void CodeStubAssembler::LoadIC(const LoadICParameters* p) { | 4656 void CodeStubAssembler::LoadIC(const LoadICParameters* p) { |
4658 Variable var_handler(this, MachineRepresentation::kTagged); | 4657 Variable var_handler(this, MachineRepresentation::kTagged); |
4659 // TODO(ishell): defer blocks when it works. | 4658 // TODO(ishell): defer blocks when it works. |
4660 Label if_handler(this, &var_handler), try_polymorphic(this), | 4659 Label if_handler(this, &var_handler), try_polymorphic(this), |
4661 try_megamorphic(this /*, Label::kDeferred*/), | 4660 try_megamorphic(this /*, Label::kDeferred*/), |
4662 miss(this /*, Label::kDeferred*/); | 4661 miss(this /*, Label::kDeferred*/); |
4663 | 4662 |
4664 Node* receiver_map = LoadReceiverMap(p->receiver); | 4663 Node* receiver_map = LoadReceiverMap(p->receiver); |
4665 | 4664 |
4666 // Check monomorphic case. | 4665 // Check monomorphic case. |
4667 Node* feedback = TryMonomorphicCase(p, receiver_map, &if_handler, | 4666 Node* feedback = |
4668 &var_handler, &try_polymorphic); | 4667 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
| 4668 &var_handler, &try_polymorphic); |
4669 Bind(&if_handler); | 4669 Bind(&if_handler); |
4670 { | 4670 { |
4671 HandleLoadICHandlerCase(p, var_handler.value(), &miss); | 4671 HandleLoadICHandlerCase(p, var_handler.value(), &miss); |
4672 } | 4672 } |
4673 | 4673 |
4674 Bind(&try_polymorphic); | 4674 Bind(&try_polymorphic); |
4675 { | 4675 { |
4676 // Check polymorphic case. | 4676 // Check polymorphic case. |
4677 Comment("LoadIC_try_polymorphic"); | 4677 Comment("LoadIC_try_polymorphic"); |
4678 GotoUnless(WordEqual(LoadMap(feedback), FixedArrayMapConstant()), | 4678 GotoUnless(WordEqual(LoadMap(feedback), FixedArrayMapConstant()), |
4679 &try_megamorphic); | 4679 &try_megamorphic); |
4680 HandlePolymorphicCase(p, receiver_map, feedback, &if_handler, &var_handler, | 4680 HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, |
4681 &miss, 2); | 4681 &miss, 2); |
4682 } | 4682 } |
4683 | 4683 |
4684 Bind(&try_megamorphic); | 4684 Bind(&try_megamorphic); |
4685 { | 4685 { |
4686 // Check megamorphic case. | 4686 // Check megamorphic case. |
4687 GotoUnless( | 4687 GotoUnless( |
4688 WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), | 4688 WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), |
4689 &miss); | 4689 &miss); |
4690 | 4690 |
(...skipping 11 matching lines...) Expand all Loading... |
4702 Variable var_handler(this, MachineRepresentation::kTagged); | 4702 Variable var_handler(this, MachineRepresentation::kTagged); |
4703 // TODO(ishell): defer blocks when it works. | 4703 // TODO(ishell): defer blocks when it works. |
4704 Label if_handler(this, &var_handler), try_polymorphic(this), | 4704 Label if_handler(this, &var_handler), try_polymorphic(this), |
4705 try_megamorphic(this /*, Label::kDeferred*/), | 4705 try_megamorphic(this /*, Label::kDeferred*/), |
4706 try_polymorphic_name(this /*, Label::kDeferred*/), | 4706 try_polymorphic_name(this /*, Label::kDeferred*/), |
4707 miss(this /*, Label::kDeferred*/); | 4707 miss(this /*, Label::kDeferred*/); |
4708 | 4708 |
4709 Node* receiver_map = LoadReceiverMap(p->receiver); | 4709 Node* receiver_map = LoadReceiverMap(p->receiver); |
4710 | 4710 |
4711 // Check monomorphic case. | 4711 // Check monomorphic case. |
4712 Node* feedback = TryMonomorphicCase(p, receiver_map, &if_handler, | 4712 Node* feedback = |
4713 &var_handler, &try_polymorphic); | 4713 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
| 4714 &var_handler, &try_polymorphic); |
4714 Bind(&if_handler); | 4715 Bind(&if_handler); |
4715 { | 4716 { |
4716 HandleLoadICHandlerCase(p, var_handler.value(), &miss, kSupportElements); | 4717 HandleLoadICHandlerCase(p, var_handler.value(), &miss, kSupportElements); |
4717 } | 4718 } |
4718 | 4719 |
4719 Bind(&try_polymorphic); | 4720 Bind(&try_polymorphic); |
4720 { | 4721 { |
4721 // Check polymorphic case. | 4722 // Check polymorphic case. |
4722 Comment("KeyedLoadIC_try_polymorphic"); | 4723 Comment("KeyedLoadIC_try_polymorphic"); |
4723 GotoUnless(WordEqual(LoadMap(feedback), FixedArrayMapConstant()), | 4724 GotoUnless(WordEqual(LoadMap(feedback), FixedArrayMapConstant()), |
4724 &try_megamorphic); | 4725 &try_megamorphic); |
4725 HandlePolymorphicCase(p, receiver_map, feedback, &if_handler, &var_handler, | 4726 HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, |
4726 &miss, 2); | 4727 &miss, 2); |
4727 } | 4728 } |
4728 | 4729 |
4729 Bind(&try_megamorphic); | 4730 Bind(&try_megamorphic); |
4730 { | 4731 { |
4731 // Check megamorphic case. | 4732 // Check megamorphic case. |
4732 Comment("KeyedLoadIC_try_megamorphic"); | 4733 Comment("KeyedLoadIC_try_megamorphic"); |
4733 GotoUnless( | 4734 GotoUnless( |
4734 WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), | 4735 WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), |
4735 &try_polymorphic_name); | 4736 &try_polymorphic_name); |
4736 // TODO(jkummerow): Inline this? Or some of it? | 4737 // TODO(jkummerow): Inline this? Or some of it? |
4737 TailCallStub(CodeFactory::KeyedLoadIC_Megamorphic(isolate()), p->context, | 4738 TailCallStub(CodeFactory::KeyedLoadIC_Megamorphic(isolate()), p->context, |
4738 p->receiver, p->name, p->slot, p->vector); | 4739 p->receiver, p->name, p->slot, p->vector); |
4739 } | 4740 } |
4740 Bind(&try_polymorphic_name); | 4741 Bind(&try_polymorphic_name); |
4741 { | 4742 { |
4742 // We might have a name in feedback, and a fixed array in the next slot. | 4743 // We might have a name in feedback, and a fixed array in the next slot. |
4743 Comment("KeyedLoadIC_try_polymorphic_name"); | 4744 Comment("KeyedLoadIC_try_polymorphic_name"); |
4744 GotoUnless(WordEqual(feedback, p->name), &miss); | 4745 GotoUnless(WordEqual(feedback, p->name), &miss); |
4745 // If the name comparison succeeded, we know we have a fixed array with | 4746 // If the name comparison succeeded, we know we have a fixed array with |
4746 // at least one map/handler pair. | 4747 // at least one map/handler pair. |
4747 Node* offset = ElementOffsetFromIndex( | 4748 Node* offset = ElementOffsetFromIndex( |
4748 p->slot, FAST_HOLEY_ELEMENTS, SMI_PARAMETERS, | 4749 p->slot, FAST_HOLEY_ELEMENTS, SMI_PARAMETERS, |
4749 FixedArray::kHeaderSize + kPointerSize - kHeapObjectTag); | 4750 FixedArray::kHeaderSize + kPointerSize - kHeapObjectTag); |
4750 Node* array = Load(MachineType::AnyTagged(), p->vector, offset); | 4751 Node* array = Load(MachineType::AnyTagged(), p->vector, offset); |
4751 HandlePolymorphicCase(p, receiver_map, array, &if_handler, &var_handler, | 4752 HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler, &miss, |
4752 &miss, 1); | 4753 1); |
4753 } | 4754 } |
4754 Bind(&miss); | 4755 Bind(&miss); |
4755 { | 4756 { |
4756 Comment("KeyedLoadIC_miss"); | 4757 Comment("KeyedLoadIC_miss"); |
4757 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, | 4758 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, |
4758 p->name, p->slot, p->vector); | 4759 p->name, p->slot, p->vector); |
4759 } | 4760 } |
4760 } | 4761 } |
4761 | 4762 |
4762 void CodeStubAssembler::KeyedLoadICGeneric(const LoadICParameters* p) { | 4763 void CodeStubAssembler::KeyedLoadICGeneric(const LoadICParameters* p) { |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4908 Bind(&slow); | 4909 Bind(&slow); |
4909 { | 4910 { |
4910 Comment("KeyedLoadGeneric_slow"); | 4911 Comment("KeyedLoadGeneric_slow"); |
4911 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_slow(), 1); | 4912 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_slow(), 1); |
4912 // TODO(jkummerow): Should we use the GetProperty TF stub instead? | 4913 // TODO(jkummerow): Should we use the GetProperty TF stub instead? |
4913 TailCallRuntime(Runtime::kKeyedGetProperty, p->context, p->receiver, | 4914 TailCallRuntime(Runtime::kKeyedGetProperty, p->context, p->receiver, |
4914 p->name); | 4915 p->name); |
4915 } | 4916 } |
4916 } | 4917 } |
4917 | 4918 |
| 4919 void CodeStubAssembler::StoreIC(const StoreICParameters* p) { |
| 4920 Variable var_handler(this, MachineRepresentation::kTagged); |
| 4921 // TODO(ishell): defer blocks when it works. |
| 4922 Label if_handler(this, &var_handler), try_polymorphic(this), |
| 4923 try_megamorphic(this /*, Label::kDeferred*/), |
| 4924 miss(this /*, Label::kDeferred*/); |
| 4925 |
| 4926 Node* receiver_map = LoadReceiverMap(p->receiver); |
| 4927 |
| 4928 // Check monomorphic case. |
| 4929 Node* feedback = |
| 4930 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
| 4931 &var_handler, &try_polymorphic); |
| 4932 Bind(&if_handler); |
| 4933 { |
| 4934 Comment("StoreIC_if_handler"); |
| 4935 StoreWithVectorDescriptor descriptor(isolate()); |
| 4936 TailCallStub(descriptor, var_handler.value(), p->context, p->receiver, |
| 4937 p->name, p->value, p->slot, p->vector); |
| 4938 } |
| 4939 |
| 4940 Bind(&try_polymorphic); |
| 4941 { |
| 4942 // Check polymorphic case. |
| 4943 Comment("StoreIC_try_polymorphic"); |
| 4944 GotoUnless( |
| 4945 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), |
| 4946 &try_megamorphic); |
| 4947 HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, |
| 4948 &miss, 2); |
| 4949 } |
| 4950 |
| 4951 Bind(&try_megamorphic); |
| 4952 { |
| 4953 // Check megamorphic case. |
| 4954 GotoUnless( |
| 4955 WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), |
| 4956 &miss); |
| 4957 |
| 4958 TryProbeStubCache(isolate()->store_stub_cache(), p->receiver, p->name, |
| 4959 &if_handler, &var_handler, &miss); |
| 4960 } |
| 4961 Bind(&miss); |
| 4962 { |
| 4963 TailCallRuntime(Runtime::kStoreIC_Miss, p->context, p->value, p->slot, |
| 4964 p->vector, p->receiver, p->name); |
| 4965 } |
| 4966 } |
| 4967 |
4918 void CodeStubAssembler::LoadGlobalIC(const LoadICParameters* p) { | 4968 void CodeStubAssembler::LoadGlobalIC(const LoadICParameters* p) { |
4919 Label try_handler(this), miss(this); | 4969 Label try_handler(this), miss(this); |
4920 Node* weak_cell = | 4970 Node* weak_cell = |
4921 LoadFixedArrayElement(p->vector, p->slot, 0, SMI_PARAMETERS); | 4971 LoadFixedArrayElement(p->vector, p->slot, 0, SMI_PARAMETERS); |
4922 AssertInstanceType(weak_cell, WEAK_CELL_TYPE); | 4972 AssertInstanceType(weak_cell, WEAK_CELL_TYPE); |
4923 | 4973 |
4924 // Load value or try handler case if the {weak_cell} is cleared. | 4974 // Load value or try handler case if the {weak_cell} is cleared. |
4925 Node* property_cell = LoadWeakCellValue(weak_cell, &try_handler); | 4975 Node* property_cell = LoadWeakCellValue(weak_cell, &try_handler); |
4926 AssertInstanceType(property_cell, PROPERTY_CELL_TYPE); | 4976 AssertInstanceType(property_cell, PROPERTY_CELL_TYPE); |
4927 | 4977 |
(...skipping 711 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5639 Heap::kTheHoleValueRootIndex); | 5689 Heap::kTheHoleValueRootIndex); |
5640 | 5690 |
5641 // Store the WeakCell in the feedback vector. | 5691 // Store the WeakCell in the feedback vector. |
5642 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, | 5692 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, |
5643 CodeStubAssembler::SMI_PARAMETERS); | 5693 CodeStubAssembler::SMI_PARAMETERS); |
5644 return cell; | 5694 return cell; |
5645 } | 5695 } |
5646 | 5696 |
5647 } // namespace internal | 5697 } // namespace internal |
5648 } // namespace v8 | 5698 } // namespace v8 |
OLD | NEW |