Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Side by Side Diff: src/code-stub-assembler.cc

Issue 2488673004: [ic] Support data handlers that represent transitioning stores. (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 5581 matching lines...) Expand 10 before | Expand all | Expand 10 after
5592 CSA_ASSERT(UintPtrLessThan( 5592 CSA_ASSERT(UintPtrLessThan(
5593 descriptor, LoadAndUntagFixedArrayBaseLength(descriptors))); 5593 descriptor, LoadAndUntagFixedArrayBaseLength(descriptors)));
5594 #endif 5594 #endif
5595 Return( 5595 Return(
5596 LoadFixedArrayElement(descriptors, descriptor, 0, INTPTR_PARAMETERS)); 5596 LoadFixedArrayElement(descriptors, descriptor, 0, INTPTR_PARAMETERS));
5597 } 5597 }
5598 } 5598 }
5599 5599
5600 Bind(&try_proto_handler); 5600 Bind(&try_proto_handler);
5601 { 5601 {
5602 GotoIf(WordEqual(LoadMap(handler), LoadRoot(Heap::kCodeMapRootIndex)), 5602 GotoIf(IsCodeMap(LoadMap(handler)), &call_handler);
5603 &call_handler);
5604 HandleLoadICProtoHandler(p, handler, &var_holder, &var_smi_handler, 5603 HandleLoadICProtoHandler(p, handler, &var_holder, &var_smi_handler,
5605 &if_smi_handler, miss); 5604 &if_smi_handler, miss);
5606 } 5605 }
5607 5606
5608 Bind(&call_handler); 5607 Bind(&call_handler);
5609 { 5608 {
5610 typedef LoadWithVectorDescriptor Descriptor; 5609 typedef LoadWithVectorDescriptor Descriptor;
5611 TailCallStub(Descriptor(isolate()), handler, p->context, 5610 TailCallStub(Descriptor(isolate()), handler, p->context,
5612 Arg(Descriptor::kReceiver, p->receiver), 5611 Arg(Descriptor::kReceiver, p->receiver),
5613 Arg(Descriptor::kName, p->name), 5612 Arg(Descriptor::kName, p->name),
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after
6009 Bind(&slow); 6008 Bind(&slow);
6010 { 6009 {
6011 Comment("KeyedLoadGeneric_slow"); 6010 Comment("KeyedLoadGeneric_slow");
6012 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_slow(), 1); 6011 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_slow(), 1);
6013 // TODO(jkummerow): Should we use the GetProperty TF stub instead? 6012 // TODO(jkummerow): Should we use the GetProperty TF stub instead?
6014 TailCallRuntime(Runtime::kKeyedGetProperty, p->context, p->receiver, 6013 TailCallRuntime(Runtime::kKeyedGetProperty, p->context, p->receiver,
6015 p->name); 6014 p->name);
6016 } 6015 }
6017 } 6016 }
6018 6017
6019 void CodeStubAssembler::HandleStoreFieldAndReturn( 6018 void CodeStubAssembler::HandleStoreFieldAndReturn(Node* handler_word,
6020 Node* handler_word, Node* holder, Representation representation, 6019 Node* holder,
6021 Node* value, bool transition_to_field, Label* miss) { 6020 Representation representation,
6021 Node* value, Node* transition,
6022 Label* miss) {
6023 bool transition_to_field = transition != nullptr;
6022 Node* prepared_value = PrepareValueForWrite(value, representation, miss); 6024 Node* prepared_value = PrepareValueForWrite(value, representation, miss);
6023 6025
6026 if (transition_to_field) {
6027 Label storage_extended(this);
6028 GotoUnless(IsSetWord<StoreHandler::ExtendStorageBits>(handler_word),
6029 &storage_extended);
6030 Comment("[ Extend storage");
6031 ExtendPropertiesBackingStore(holder);
6032 Comment("] Extend storage");
6033 Goto(&storage_extended);
6034
6035 Bind(&storage_extended);
6036 }
6037
6024 Node* offset = DecodeWord<StoreHandler::FieldOffsetBits>(handler_word); 6038 Node* offset = DecodeWord<StoreHandler::FieldOffsetBits>(handler_word);
6025 Label if_inobject(this), if_out_of_object(this); 6039 Label if_inobject(this), if_out_of_object(this);
6026 Branch(IsSetWord<StoreHandler::IsInobjectBits>(handler_word), &if_inobject, 6040 Branch(IsSetWord<StoreHandler::IsInobjectBits>(handler_word), &if_inobject,
6027 &if_out_of_object); 6041 &if_out_of_object);
6028 6042
6029 Bind(&if_inobject); 6043 Bind(&if_inobject);
6030 { 6044 {
6031 StoreNamedField(holder, offset, true, representation, prepared_value, 6045 StoreNamedField(holder, offset, true, representation, prepared_value,
6032 transition_to_field); 6046 transition_to_field);
6047 if (transition_to_field) {
6048 StoreObjectField(holder, JSObject::kMapOffset, transition);
6049 }
6033 Return(value); 6050 Return(value);
6034 } 6051 }
6035 6052
6036 Bind(&if_out_of_object); 6053 Bind(&if_out_of_object);
6037 { 6054 {
6038 StoreNamedField(holder, offset, false, representation, prepared_value, 6055 StoreNamedField(holder, offset, false, representation, prepared_value,
6039 transition_to_field); 6056 transition_to_field);
6057 if (transition_to_field) {
6058 StoreObjectField(holder, JSObject::kMapOffset, transition);
6059 }
6040 Return(value); 6060 Return(value);
6041 } 6061 }
6042 } 6062 }
6043 6063
6044 void CodeStubAssembler::HandleStoreICSmiHandlerCase(Node* handler_word, 6064 void CodeStubAssembler::HandleStoreICSmiHandlerCase(Node* handler_word,
6045 Node* holder, Node* value, 6065 Node* holder, Node* value,
6046 bool transition_to_field, 6066 Node* transition,
6047 Label* miss) { 6067 Label* miss) {
6048 Comment(transition_to_field ? "transitioning field store" : "field store"); 6068 Comment(transition ? "transitioning field store" : "field store");
6069
6070 #ifdef DEBUG
6071 Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word);
6072 if (transition) {
6073 CSA_ASSERT(
6074 WordOr(WordEqual(handler_kind,
6075 IntPtrConstant(StoreHandler::kTransitionToField)),
6076 WordEqual(handler_kind,
6077 IntPtrConstant(StoreHandler::kTransitionToConstant))));
6078 } else {
6079 CSA_ASSERT(
6080 WordEqual(handler_kind, IntPtrConstant(StoreHandler::kStoreField)));
6081 }
6082 #endif
6049 6083
6050 Node* field_representation = 6084 Node* field_representation =
6051 DecodeWord<StoreHandler::FieldRepresentationBits>(handler_word); 6085 DecodeWord<StoreHandler::FieldRepresentationBits>(handler_word);
6052 6086
6053 Label if_smi_field(this), if_double_field(this), if_heap_object_field(this), 6087 Label if_smi_field(this), if_double_field(this), if_heap_object_field(this),
6054 if_tagged_field(this); 6088 if_tagged_field(this);
6055 6089
6056 GotoIf(WordEqual(field_representation, IntPtrConstant(StoreHandler::kTagged)), 6090 GotoIf(WordEqual(field_representation, IntPtrConstant(StoreHandler::kTagged)),
6057 &if_tagged_field); 6091 &if_tagged_field);
6058 GotoIf(WordEqual(field_representation, 6092 GotoIf(WordEqual(field_representation,
6059 IntPtrConstant(StoreHandler::kHeapObject)), 6093 IntPtrConstant(StoreHandler::kHeapObject)),
6060 &if_heap_object_field); 6094 &if_heap_object_field);
6061 GotoIf(WordEqual(field_representation, IntPtrConstant(StoreHandler::kDouble)), 6095 GotoIf(WordEqual(field_representation, IntPtrConstant(StoreHandler::kDouble)),
6062 &if_double_field); 6096 &if_double_field);
6063 CSA_ASSERT( 6097 CSA_ASSERT(
6064 WordEqual(field_representation, IntPtrConstant(StoreHandler::kSmi))); 6098 WordEqual(field_representation, IntPtrConstant(StoreHandler::kSmi)));
6065 Goto(&if_smi_field); 6099 Goto(&if_smi_field);
6066 6100
6067 Bind(&if_tagged_field); 6101 Bind(&if_tagged_field);
6068 { 6102 {
6069 Comment("store tagged field"); 6103 Comment("store tagged field");
6070 HandleStoreFieldAndReturn(handler_word, holder, Representation::Tagged(), 6104 HandleStoreFieldAndReturn(handler_word, holder, Representation::Tagged(),
6071 value, transition_to_field, miss); 6105 value, transition, miss);
6072 } 6106 }
6073 6107
6074 Bind(&if_double_field); 6108 Bind(&if_double_field);
6075 { 6109 {
6076 Comment("store double field"); 6110 Comment("store double field");
6077 HandleStoreFieldAndReturn(handler_word, holder, Representation::Double(), 6111 HandleStoreFieldAndReturn(handler_word, holder, Representation::Double(),
6078 value, transition_to_field, miss); 6112 value, transition, miss);
6079 } 6113 }
6080 6114
6081 Bind(&if_heap_object_field); 6115 Bind(&if_heap_object_field);
6082 { 6116 {
6083 Comment("store heap object field"); 6117 Comment("store heap object field");
6084 // Generate full field type check here and then store value as Tagged. 6118 // Generate full field type check here and then store value as Tagged.
6085 Node* prepared_value = 6119 Node* prepared_value =
6086 PrepareValueForWrite(value, Representation::HeapObject(), miss); 6120 PrepareValueForWrite(value, Representation::HeapObject(), miss);
6087 Node* value_index_in_descriptor = 6121 Node* value_index_in_descriptor =
6088 DecodeWord<StoreHandler::DescriptorValueIndexBits>(handler_word); 6122 DecodeWord<StoreHandler::DescriptorValueIndexBits>(handler_word);
6089 Node* descriptors = LoadMapDescriptors(LoadMap(holder)); 6123 Node* descriptors =
6124 LoadMapDescriptors(transition ? transition : LoadMap(holder));
6090 Node* maybe_field_type = LoadFixedArrayElement( 6125 Node* maybe_field_type = LoadFixedArrayElement(
6091 descriptors, value_index_in_descriptor, 0, INTPTR_PARAMETERS); 6126 descriptors, value_index_in_descriptor, 0, INTPTR_PARAMETERS);
6092 Label do_store(this); 6127 Label do_store(this);
6093 GotoIf(TaggedIsSmi(maybe_field_type), &do_store); 6128 GotoIf(TaggedIsSmi(maybe_field_type), &do_store);
6094 // Check that value type matches the field type. 6129 // Check that value type matches the field type.
6095 { 6130 {
6096 Node* field_type = LoadWeakCellValue(maybe_field_type, miss); 6131 Node* field_type = LoadWeakCellValue(maybe_field_type, miss);
6097 Branch(WordEqual(LoadMap(prepared_value), field_type), &do_store, miss); 6132 Branch(WordEqual(LoadMap(prepared_value), field_type), &do_store, miss);
6098 } 6133 }
6099 Bind(&do_store); 6134 Bind(&do_store);
6100 HandleStoreFieldAndReturn(handler_word, holder, Representation::Tagged(), 6135 HandleStoreFieldAndReturn(handler_word, holder, Representation::Tagged(),
6101 prepared_value, transition_to_field, miss); 6136 prepared_value, transition, miss);
6102 } 6137 }
6103 6138
6104 Bind(&if_smi_field); 6139 Bind(&if_smi_field);
6105 { 6140 {
6106 Comment("store smi field"); 6141 Comment("store smi field");
6107 HandleStoreFieldAndReturn(handler_word, holder, Representation::Smi(), 6142 HandleStoreFieldAndReturn(handler_word, holder, Representation::Smi(),
6108 value, transition_to_field, miss); 6143 value, transition, miss);
6109 } 6144 }
6110 } 6145 }
6111 6146
6112 void CodeStubAssembler::HandleStoreICHandlerCase(const StoreICParameters* p, 6147 void CodeStubAssembler::HandleStoreICHandlerCase(const StoreICParameters* p,
6113 Node* handler, Label* miss) { 6148 Node* handler, Label* miss) {
6114 Label if_smi_handler(this), call_handler(this); 6149 Label if_smi_handler(this);
6150 Label try_proto_handler(this), call_handler(this);
6115 6151
6116 Branch(TaggedIsSmi(handler), &if_smi_handler, &call_handler); 6152 Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_handler);
6117 6153
6118 // |handler| is a Smi, encoding what to do. See SmiHandler methods 6154 // |handler| is a Smi, encoding what to do. See SmiHandler methods
6119 // for the encoding format. 6155 // for the encoding format.
6120 Bind(&if_smi_handler); 6156 Bind(&if_smi_handler);
6121 { 6157 {
6122 Node* holder = p->receiver; 6158 Node* holder = p->receiver;
6123 Node* handler_word = SmiUntag(handler); 6159 Node* handler_word = SmiUntag(handler);
6124 6160
6125 // Handle non-transitioning stores. 6161 // Handle non-transitioning field stores.
6126 HandleStoreICSmiHandlerCase(handler_word, holder, p->value, false, miss); 6162 HandleStoreICSmiHandlerCase(handler_word, holder, p->value, nullptr, miss);
6163 }
6164
6165 Bind(&try_proto_handler);
6166 {
6167 GotoIf(IsCodeMap(LoadMap(handler)), &call_handler);
6168 HandleStoreICProtoHandler(p, handler, miss);
6127 } 6169 }
6128 6170
6129 // |handler| is a heap object. Must be code, call it. 6171 // |handler| is a heap object. Must be code, call it.
6130 Bind(&call_handler); 6172 Bind(&call_handler);
6131 { 6173 {
6132 StoreWithVectorDescriptor descriptor(isolate()); 6174 StoreWithVectorDescriptor descriptor(isolate());
6133 TailCallStub(descriptor, handler, p->context, p->receiver, p->name, 6175 TailCallStub(descriptor, handler, p->context, p->receiver, p->name,
6134 p->value, p->slot, p->vector); 6176 p->value, p->slot, p->vector);
6135 } 6177 }
6136 } 6178 }
6137 6179
6180 void CodeStubAssembler::HandleStoreICProtoHandler(const StoreICParameters* p,
6181 Node* handler, Label* miss) {
6182 // IC dispatchers rely on these assumptions to be held.
6183 STATIC_ASSERT(FixedArray::kLengthOffset ==
6184 StoreHandler::kTransitionCellOffset);
6185 DCHECK_EQ(FixedArray::OffsetOfElementAt(StoreHandler::kSmiHandlerIndex),
6186 StoreHandler::kSmiHandlerOffset);
6187 DCHECK_EQ(FixedArray::OffsetOfElementAt(StoreHandler::kValidityCellIndex),
6188 StoreHandler::kValidityCellOffset);
6189
6190 // Both FixedArray and Tuple3 handlers have validity cell at the same offset.
6191 Label validity_cell_check_done(this);
6192 Node* validity_cell =
6193 LoadObjectField(handler, StoreHandler::kValidityCellOffset);
6194 GotoIf(WordEqual(validity_cell, IntPtrConstant(0)),
6195 &validity_cell_check_done);
6196 Node* cell_value = LoadObjectField(validity_cell, Cell::kValueOffset);
6197 GotoIf(WordNotEqual(cell_value,
6198 SmiConstant(Smi::FromInt(Map::kPrototypeChainValid))),
6199 miss);
6200 Goto(&validity_cell_check_done);
6201
6202 Bind(&validity_cell_check_done);
6203 Node* smi_handler = LoadObjectField(handler, StoreHandler::kSmiHandlerOffset);
6204 CSA_ASSERT(TaggedIsSmi(smi_handler));
6205
6206 Node* maybe_transition_cell =
6207 LoadObjectField(handler, StoreHandler::kTransitionCellOffset);
6208 Label array_handler(this), tuple_handler(this);
6209 Branch(TaggedIsSmi(maybe_transition_cell), &array_handler, &tuple_handler);
6210
6211 Variable var_transition(this, MachineRepresentation::kTagged);
6212 Label if_transition(this), if_transition_to_constant(this);
6213 Bind(&tuple_handler);
6214 {
6215 Node* transition = LoadWeakCellValue(maybe_transition_cell, miss);
6216 var_transition.Bind(transition);
6217 Goto(&if_transition);
6218 }
6219
6220 Bind(&array_handler);
6221 {
6222 Node* length = SmiUntag(maybe_transition_cell);
6223 BuildFastLoop(MachineType::PointerRepresentation(),
6224 IntPtrConstant(StoreHandler::kFirstPrototypeIndex), length,
6225 [this, p, handler, miss](CodeStubAssembler*, Node* current) {
6226 Node* prototype_cell = LoadFixedArrayElement(
6227 handler, current, 0, INTPTR_PARAMETERS);
6228 CheckPrototype(prototype_cell, p->name, miss);
6229 },
6230 1, IndexAdvanceMode::kPost);
6231
6232 Node* maybe_transition_cell = LoadFixedArrayElement(
6233 handler, IntPtrConstant(StoreHandler::kTransitionCellIndex), 0,
6234 INTPTR_PARAMETERS);
6235 Node* transition = LoadWeakCellValue(maybe_transition_cell, miss);
6236 var_transition.Bind(transition);
6237 Goto(&if_transition);
6238 }
6239
6240 Bind(&if_transition);
6241 {
6242 Node* holder = p->receiver;
6243 Node* transition = var_transition.value();
6244 Node* handler_word = SmiUntag(smi_handler);
6245
6246 GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(transition)), miss);
6247
6248 Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word);
6249 GotoIf(WordEqual(handler_kind,
6250 IntPtrConstant(StoreHandler::kTransitionToConstant)),
6251 &if_transition_to_constant);
6252
6253 // Handle transitioning field stores.
6254 HandleStoreICSmiHandlerCase(handler_word, holder, p->value, transition,
6255 miss);
6256
6257 Bind(&if_transition_to_constant);
6258 {
6259 // Check that constant matches value.
6260 Node* value_index_in_descriptor =
6261 DecodeWord<StoreHandler::DescriptorValueIndexBits>(handler_word);
6262 Node* descriptors = LoadMapDescriptors(transition);
6263 Node* constant = LoadFixedArrayElement(
6264 descriptors, value_index_in_descriptor, 0, INTPTR_PARAMETERS);
6265 GotoIf(WordNotEqual(p->value, constant), miss);
6266
6267 StoreObjectField(p->receiver, JSObject::kMapOffset, transition);
6268 Return(p->value);
6269 }
6270 }
6271 }
6272
6138 void CodeStubAssembler::StoreIC(const StoreICParameters* p) { 6273 void CodeStubAssembler::StoreIC(const StoreICParameters* p) {
6139 Variable var_handler(this, MachineRepresentation::kTagged); 6274 Variable var_handler(this, MachineRepresentation::kTagged);
6140 // TODO(ishell): defer blocks when it works. 6275 // TODO(ishell): defer blocks when it works.
6141 Label if_handler(this, &var_handler), try_polymorphic(this), 6276 Label if_handler(this, &var_handler), try_polymorphic(this),
6142 try_megamorphic(this /*, Label::kDeferred*/), 6277 try_megamorphic(this /*, Label::kDeferred*/),
6143 miss(this /*, Label::kDeferred*/); 6278 miss(this /*, Label::kDeferred*/);
6144 6279
6145 Node* receiver_map = LoadReceiverMap(p->receiver); 6280 Node* receiver_map = LoadReceiverMap(p->receiver);
6146 6281
6147 // Check monomorphic case. 6282 // Check monomorphic case.
(...skipping 2689 matching lines...) Expand 10 before | Expand all | Expand 10 after
8837 } 8972 }
8838 8973
8839 void CodeStubArguments::PopAndReturn(compiler::Node* value) { 8974 void CodeStubArguments::PopAndReturn(compiler::Node* value) {
8840 assembler_->PopAndReturn( 8975 assembler_->PopAndReturn(
8841 assembler_->IntPtrAddFoldConstants(argc_, assembler_->IntPtrConstant(1)), 8976 assembler_->IntPtrAddFoldConstants(argc_, assembler_->IntPtrConstant(1)),
8842 value); 8977 value);
8843 } 8978 }
8844 8979
8845 } // namespace internal 8980 } // namespace internal
8846 } // namespace v8 8981 } // namespace v8
OLDNEW
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/counters.h » ('j') | src/ic/ic.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698