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 | |
5826 void CodeStubAssembler::StoreIC(const StoreICParameters* p) { | 5707 void CodeStubAssembler::StoreIC(const StoreICParameters* p) { |
5827 Variable var_handler(this, MachineRepresentation::kTagged); | 5708 Variable var_handler(this, MachineRepresentation::kTagged); |
5828 // TODO(ishell): defer blocks when it works. | 5709 // TODO(ishell): defer blocks when it works. |
5829 Label if_handler(this, &var_handler), try_polymorphic(this), | 5710 Label if_handler(this, &var_handler), try_polymorphic(this), |
5830 try_megamorphic(this /*, Label::kDeferred*/), | 5711 try_megamorphic(this /*, Label::kDeferred*/), |
5831 miss(this /*, Label::kDeferred*/); | 5712 miss(this /*, Label::kDeferred*/); |
5832 | 5713 |
5833 Node* receiver_map = LoadReceiverMap(p->receiver); | 5714 Node* receiver_map = LoadReceiverMap(p->receiver); |
5834 | 5715 |
5835 // Check monomorphic case. | 5716 // Check monomorphic case. |
5836 Node* feedback = | 5717 Node* feedback = |
5837 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, | 5718 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
5838 &var_handler, &try_polymorphic); | 5719 &var_handler, &try_polymorphic); |
5839 Bind(&if_handler); | 5720 Bind(&if_handler); |
5840 { | 5721 { |
5841 Comment("StoreIC_if_handler"); | 5722 Comment("StoreIC_if_handler"); |
5842 HandleStoreICHandlerCase(p, var_handler.value(), &miss); | 5723 StoreWithVectorDescriptor descriptor(isolate()); |
| 5724 TailCallStub(descriptor, var_handler.value(), p->context, p->receiver, |
| 5725 p->name, p->value, p->slot, p->vector); |
5843 } | 5726 } |
5844 | 5727 |
5845 Bind(&try_polymorphic); | 5728 Bind(&try_polymorphic); |
5846 { | 5729 { |
5847 // Check polymorphic case. | 5730 // Check polymorphic case. |
5848 Comment("StoreIC_try_polymorphic"); | 5731 Comment("StoreIC_try_polymorphic"); |
5849 GotoUnless( | 5732 GotoUnless( |
5850 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), | 5733 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), |
5851 &try_megamorphic); | 5734 &try_megamorphic); |
5852 HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, | 5735 HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, |
(...skipping 13 matching lines...) Expand all Loading... |
5866 Bind(&miss); | 5749 Bind(&miss); |
5867 { | 5750 { |
5868 TailCallRuntime(Runtime::kStoreIC_Miss, p->context, p->value, p->slot, | 5751 TailCallRuntime(Runtime::kStoreIC_Miss, p->context, p->value, p->slot, |
5869 p->vector, p->receiver, p->name); | 5752 p->vector, p->receiver, p->name); |
5870 } | 5753 } |
5871 } | 5754 } |
5872 | 5755 |
5873 void CodeStubAssembler::KeyedStoreIC(const StoreICParameters* p, | 5756 void CodeStubAssembler::KeyedStoreIC(const StoreICParameters* p, |
5874 LanguageMode language_mode) { | 5757 LanguageMode language_mode) { |
5875 Variable var_handler(this, MachineRepresentation::kTagged); | 5758 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 | |
5879 // TODO(ishell): defer blocks when it works. | 5759 // TODO(ishell): defer blocks when it works. |
5880 Label if_handler(this, &var_handler), try_polymorphic(this), | 5760 Label if_handler(this, &var_handler), try_polymorphic(this), |
5881 try_megamorphic(this /*, Label::kDeferred*/), | 5761 try_megamorphic(this /*, Label::kDeferred*/), |
5882 try_polymorphic_name(this /*, Label::kDeferred*/), | 5762 try_polymorphic_name(this /*, Label::kDeferred*/), |
5883 miss(this /*, Label::kDeferred*/); | 5763 miss(this /*, Label::kDeferred*/); |
5884 | 5764 |
5885 Node* receiver_map = LoadReceiverMap(p->receiver); | 5765 Node* receiver_map = LoadReceiverMap(p->receiver); |
5886 | 5766 |
5887 // Check monomorphic case. | 5767 // Check monomorphic case. |
5888 Node* feedback = | 5768 Node* feedback = |
5889 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, | 5769 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
5890 &var_handler, &try_polymorphic); | 5770 &var_handler, &try_polymorphic); |
5891 Bind(&if_handler); | 5771 Bind(&if_handler); |
5892 { | 5772 { |
5893 Comment("KeyedStoreIC_if_handler"); | 5773 Comment("KeyedStoreIC_if_handler"); |
5894 HandleStoreICHandlerCase(p, var_handler.value(), &miss); | 5774 StoreWithVectorDescriptor descriptor(isolate()); |
| 5775 TailCallStub(descriptor, var_handler.value(), p->context, p->receiver, |
| 5776 p->name, p->value, p->slot, p->vector); |
5895 } | 5777 } |
5896 | 5778 |
5897 Bind(&try_polymorphic); | 5779 Bind(&try_polymorphic); |
5898 { | 5780 { |
5899 // CheckPolymorphic case. | 5781 // CheckPolymorphic case. |
5900 Comment("KeyedStoreIC_try_polymorphic"); | 5782 Comment("KeyedStoreIC_try_polymorphic"); |
5901 GotoUnless( | 5783 GotoUnless( |
5902 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), | 5784 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), |
5903 &try_megamorphic); | 5785 &try_megamorphic); |
5904 Label if_transition_handler(this); | 5786 Label if_transition_handler(this); |
(...skipping 2546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8451 Node* buffer_bit_field = LoadObjectField( | 8333 Node* buffer_bit_field = LoadObjectField( |
8452 buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32()); | 8334 buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32()); |
8453 Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask); | 8335 Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask); |
8454 | 8336 |
8455 return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask), | 8337 return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask), |
8456 Int32Constant(0)); | 8338 Int32Constant(0)); |
8457 } | 8339 } |
8458 | 8340 |
8459 } // namespace internal | 8341 } // namespace internal |
8460 } // namespace v8 | 8342 } // namespace v8 |
OLD | NEW |