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 #include "src/code-stub-assembler.h" | 4 #include "src/code-stub-assembler.h" |
5 #include "src/code-factory.h" | 5 #include "src/code-factory.h" |
6 #include "src/frames-inl.h" | 6 #include "src/frames-inl.h" |
7 #include "src/frames.h" | 7 #include "src/frames.h" |
8 #include "src/ic/handler-configuration.h" | 8 #include "src/ic/handler-configuration.h" |
9 #include "src/ic/stub-cache.h" | 9 #include "src/ic/stub-cache.h" |
10 | 10 |
(...skipping 5686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5697 Bind(&slow); | 5697 Bind(&slow); |
5698 { | 5698 { |
5699 Comment("KeyedLoadGeneric_slow"); | 5699 Comment("KeyedLoadGeneric_slow"); |
5700 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_slow(), 1); | 5700 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_slow(), 1); |
5701 // TODO(jkummerow): Should we use the GetProperty TF stub instead? | 5701 // TODO(jkummerow): Should we use the GetProperty TF stub instead? |
5702 TailCallRuntime(Runtime::kKeyedGetProperty, p->context, p->receiver, | 5702 TailCallRuntime(Runtime::kKeyedGetProperty, p->context, p->receiver, |
5703 p->name); | 5703 p->name); |
5704 } | 5704 } |
5705 } | 5705 } |
5706 | 5706 |
| 5707 void CodeStubAssembler::HandleStoreFieldAndReturn( |
| 5708 Node* handler_word, Node* holder, Representation representation, |
| 5709 Node* value, bool transition_to_field, Label* miss) { |
| 5710 Node* prepared_value = PrepareValueForWrite(value, representation, miss); |
| 5711 |
| 5712 Node* offset = DecodeWord<StoreHandler::FieldOffsetBits>(handler_word); |
| 5713 Label if_inobject(this), if_out_of_object(this); |
| 5714 Branch(IsSetWord<StoreHandler::IsInobjectBits>(handler_word), &if_inobject, |
| 5715 &if_out_of_object); |
| 5716 |
| 5717 Bind(&if_inobject); |
| 5718 { |
| 5719 StoreNamedField(holder, offset, true, representation, prepared_value, |
| 5720 transition_to_field); |
| 5721 Return(value); |
| 5722 } |
| 5723 |
| 5724 Bind(&if_out_of_object); |
| 5725 { |
| 5726 StoreNamedField(holder, offset, false, representation, prepared_value, |
| 5727 transition_to_field); |
| 5728 Return(value); |
| 5729 } |
| 5730 } |
| 5731 |
| 5732 void CodeStubAssembler::HandleStoreICSmiHandlerCase(Node* handler_word, |
| 5733 Node* holder, Node* value, |
| 5734 bool transition_to_field, |
| 5735 Label* miss) { |
| 5736 Comment(transition_to_field ? "transitioning field store" : "field store"); |
| 5737 |
| 5738 Node* field_representation = |
| 5739 DecodeWord<StoreHandler::FieldRepresentationBits>(handler_word); |
| 5740 |
| 5741 Label if_smi_field(this), if_double_field(this), if_heap_object_field(this), |
| 5742 if_tagged_field(this); |
| 5743 |
| 5744 GotoIf(WordEqual(field_representation, IntPtrConstant(StoreHandler::kTagged)), |
| 5745 &if_tagged_field); |
| 5746 GotoIf(WordEqual(field_representation, |
| 5747 IntPtrConstant(StoreHandler::kHeapObject)), |
| 5748 &if_heap_object_field); |
| 5749 GotoIf(WordEqual(field_representation, IntPtrConstant(StoreHandler::kDouble)), |
| 5750 &if_double_field); |
| 5751 CSA_ASSERT( |
| 5752 WordEqual(field_representation, IntPtrConstant(StoreHandler::kSmi))); |
| 5753 Goto(&if_smi_field); |
| 5754 |
| 5755 Bind(&if_tagged_field); |
| 5756 { |
| 5757 Comment("store tagged field"); |
| 5758 HandleStoreFieldAndReturn(handler_word, holder, Representation::Tagged(), |
| 5759 value, transition_to_field, miss); |
| 5760 } |
| 5761 |
| 5762 Bind(&if_double_field); |
| 5763 { |
| 5764 Comment("store double field"); |
| 5765 HandleStoreFieldAndReturn(handler_word, holder, Representation::Double(), |
| 5766 value, transition_to_field, miss); |
| 5767 } |
| 5768 |
| 5769 Bind(&if_heap_object_field); |
| 5770 { |
| 5771 Comment("store heap object field"); |
| 5772 // Generate full field type check here and then store value as Tagged. |
| 5773 Node* prepared_value = |
| 5774 PrepareValueForWrite(value, Representation::HeapObject(), miss); |
| 5775 Node* value_index_in_descriptor = |
| 5776 DecodeWord<StoreHandler::DescriptorValueIndexBits>(handler_word); |
| 5777 Node* descriptors = LoadMapDescriptors(LoadMap(holder)); |
| 5778 Node* maybe_field_type = LoadFixedArrayElement( |
| 5779 descriptors, value_index_in_descriptor, 0, INTPTR_PARAMETERS); |
| 5780 Label do_store(this); |
| 5781 GotoIf(TaggedIsSmi(maybe_field_type), &do_store); |
| 5782 // Check that value type matches the field type. |
| 5783 { |
| 5784 Node* field_type = LoadWeakCellValue(maybe_field_type, miss); |
| 5785 Branch(WordEqual(LoadMap(prepared_value), field_type), &do_store, miss); |
| 5786 } |
| 5787 Bind(&do_store); |
| 5788 HandleStoreFieldAndReturn(handler_word, holder, Representation::Tagged(), |
| 5789 prepared_value, transition_to_field, miss); |
| 5790 } |
| 5791 |
| 5792 Bind(&if_smi_field); |
| 5793 { |
| 5794 Comment("store smi field"); |
| 5795 HandleStoreFieldAndReturn(handler_word, holder, Representation::Smi(), |
| 5796 value, transition_to_field, miss); |
| 5797 } |
| 5798 } |
| 5799 |
| 5800 void CodeStubAssembler::HandleStoreICHandlerCase(const StoreICParameters* p, |
| 5801 Node* handler, Label* miss) { |
| 5802 Label if_smi_handler(this), call_handler(this); |
| 5803 |
| 5804 Branch(TaggedIsSmi(handler), &if_smi_handler, &call_handler); |
| 5805 |
| 5806 // |handler| is a Smi, encoding what to do. See SmiHandler methods |
| 5807 // for the encoding format. |
| 5808 Bind(&if_smi_handler); |
| 5809 { |
| 5810 Node* holder = p->receiver; |
| 5811 Node* handler_word = SmiUntag(handler); |
| 5812 |
| 5813 // Handle non-transitioning stores. |
| 5814 HandleStoreICSmiHandlerCase(handler_word, holder, p->value, false, miss); |
| 5815 } |
| 5816 |
| 5817 // |handler| is a heap object. Must be code, call it. |
| 5818 Bind(&call_handler); |
| 5819 { |
| 5820 StoreWithVectorDescriptor descriptor(isolate()); |
| 5821 TailCallStub(descriptor, handler, p->context, p->receiver, p->name, |
| 5822 p->value, p->slot, p->vector); |
| 5823 } |
| 5824 } |
| 5825 |
5707 void CodeStubAssembler::StoreIC(const StoreICParameters* p) { | 5826 void CodeStubAssembler::StoreIC(const StoreICParameters* p) { |
5708 Variable var_handler(this, MachineRepresentation::kTagged); | 5827 Variable var_handler(this, MachineRepresentation::kTagged); |
5709 // TODO(ishell): defer blocks when it works. | 5828 // TODO(ishell): defer blocks when it works. |
5710 Label if_handler(this, &var_handler), try_polymorphic(this), | 5829 Label if_handler(this, &var_handler), try_polymorphic(this), |
5711 try_megamorphic(this /*, Label::kDeferred*/), | 5830 try_megamorphic(this /*, Label::kDeferred*/), |
5712 miss(this /*, Label::kDeferred*/); | 5831 miss(this /*, Label::kDeferred*/); |
5713 | 5832 |
5714 Node* receiver_map = LoadReceiverMap(p->receiver); | 5833 Node* receiver_map = LoadReceiverMap(p->receiver); |
5715 | 5834 |
5716 // Check monomorphic case. | 5835 // Check monomorphic case. |
5717 Node* feedback = | 5836 Node* feedback = |
5718 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, | 5837 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
5719 &var_handler, &try_polymorphic); | 5838 &var_handler, &try_polymorphic); |
5720 Bind(&if_handler); | 5839 Bind(&if_handler); |
5721 { | 5840 { |
5722 Comment("StoreIC_if_handler"); | 5841 Comment("StoreIC_if_handler"); |
5723 StoreWithVectorDescriptor descriptor(isolate()); | 5842 HandleStoreICHandlerCase(p, var_handler.value(), &miss); |
5724 TailCallStub(descriptor, var_handler.value(), p->context, p->receiver, | |
5725 p->name, p->value, p->slot, p->vector); | |
5726 } | 5843 } |
5727 | 5844 |
5728 Bind(&try_polymorphic); | 5845 Bind(&try_polymorphic); |
5729 { | 5846 { |
5730 // Check polymorphic case. | 5847 // Check polymorphic case. |
5731 Comment("StoreIC_try_polymorphic"); | 5848 Comment("StoreIC_try_polymorphic"); |
5732 GotoUnless( | 5849 GotoUnless( |
5733 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), | 5850 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), |
5734 &try_megamorphic); | 5851 &try_megamorphic); |
5735 HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, | 5852 HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, |
(...skipping 13 matching lines...) Expand all Loading... |
5749 Bind(&miss); | 5866 Bind(&miss); |
5750 { | 5867 { |
5751 TailCallRuntime(Runtime::kStoreIC_Miss, p->context, p->value, p->slot, | 5868 TailCallRuntime(Runtime::kStoreIC_Miss, p->context, p->value, p->slot, |
5752 p->vector, p->receiver, p->name); | 5869 p->vector, p->receiver, p->name); |
5753 } | 5870 } |
5754 } | 5871 } |
5755 | 5872 |
5756 void CodeStubAssembler::KeyedStoreIC(const StoreICParameters* p, | 5873 void CodeStubAssembler::KeyedStoreIC(const StoreICParameters* p, |
5757 LanguageMode language_mode) { | 5874 LanguageMode language_mode) { |
5758 Variable var_handler(this, MachineRepresentation::kTagged); | 5875 Variable var_handler(this, MachineRepresentation::kTagged); |
| 5876 // This is to make |miss| label see the var_handler bound on all paths. |
| 5877 var_handler.Bind(IntPtrConstant(0)); |
| 5878 |
5759 // TODO(ishell): defer blocks when it works. | 5879 // TODO(ishell): defer blocks when it works. |
5760 Label if_handler(this, &var_handler), try_polymorphic(this), | 5880 Label if_handler(this, &var_handler), try_polymorphic(this), |
5761 try_megamorphic(this /*, Label::kDeferred*/), | 5881 try_megamorphic(this /*, Label::kDeferred*/), |
5762 try_polymorphic_name(this /*, Label::kDeferred*/), | 5882 try_polymorphic_name(this /*, Label::kDeferred*/), |
5763 miss(this /*, Label::kDeferred*/); | 5883 miss(this /*, Label::kDeferred*/); |
5764 | 5884 |
5765 Node* receiver_map = LoadReceiverMap(p->receiver); | 5885 Node* receiver_map = LoadReceiverMap(p->receiver); |
5766 | 5886 |
5767 // Check monomorphic case. | 5887 // Check monomorphic case. |
5768 Node* feedback = | 5888 Node* feedback = |
5769 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, | 5889 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
5770 &var_handler, &try_polymorphic); | 5890 &var_handler, &try_polymorphic); |
5771 Bind(&if_handler); | 5891 Bind(&if_handler); |
5772 { | 5892 { |
5773 Comment("KeyedStoreIC_if_handler"); | 5893 Comment("KeyedStoreIC_if_handler"); |
5774 StoreWithVectorDescriptor descriptor(isolate()); | 5894 HandleStoreICHandlerCase(p, var_handler.value(), &miss); |
5775 TailCallStub(descriptor, var_handler.value(), p->context, p->receiver, | |
5776 p->name, p->value, p->slot, p->vector); | |
5777 } | 5895 } |
5778 | 5896 |
5779 Bind(&try_polymorphic); | 5897 Bind(&try_polymorphic); |
5780 { | 5898 { |
5781 // CheckPolymorphic case. | 5899 // CheckPolymorphic case. |
5782 Comment("KeyedStoreIC_try_polymorphic"); | 5900 Comment("KeyedStoreIC_try_polymorphic"); |
5783 GotoUnless( | 5901 GotoUnless( |
5784 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), | 5902 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), |
5785 &try_megamorphic); | 5903 &try_megamorphic); |
5786 Label if_transition_handler(this); | 5904 Label if_transition_handler(this); |
(...skipping 2546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8333 Node* buffer_bit_field = LoadObjectField( | 8451 Node* buffer_bit_field = LoadObjectField( |
8334 buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32()); | 8452 buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32()); |
8335 Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask); | 8453 Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask); |
8336 | 8454 |
8337 return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask), | 8455 return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask), |
8338 Int32Constant(0)); | 8456 Int32Constant(0)); |
8339 } | 8457 } |
8340 | 8458 |
8341 } // namespace internal | 8459 } // namespace internal |
8342 } // namespace v8 | 8460 } // namespace v8 |
OLD | NEW |