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

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

Issue 2488673004: [ic] Support data handlers that represent transitioning stores. (Closed)
Patch Set: Rebasing again 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
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/counters.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 5617 matching lines...) Expand 10 before | Expand all | Expand 10 after
5628 Return(value); 5628 Return(value);
5629 5629
5630 Bind(&if_accessor_info); 5630 Bind(&if_accessor_info);
5631 Callable callable = CodeFactory::ApiGetter(isolate()); 5631 Callable callable = CodeFactory::ApiGetter(isolate());
5632 TailCallStub(callable, p->context, p->receiver, holder, value); 5632 TailCallStub(callable, p->context, p->receiver, holder, value);
5633 } 5633 }
5634 } 5634 }
5635 5635
5636 Bind(&try_proto_handler); 5636 Bind(&try_proto_handler);
5637 { 5637 {
5638 GotoIf(WordEqual(LoadMap(handler), LoadRoot(Heap::kCodeMapRootIndex)), 5638 GotoIf(IsCodeMap(LoadMap(handler)), &call_handler);
5639 &call_handler);
5640 HandleLoadICProtoHandler(p, handler, &var_holder, &var_smi_handler, 5639 HandleLoadICProtoHandler(p, handler, &var_holder, &var_smi_handler,
5641 &if_smi_handler, miss); 5640 &if_smi_handler, miss);
5642 } 5641 }
5643 5642
5644 Bind(&call_handler); 5643 Bind(&call_handler);
5645 { 5644 {
5646 typedef LoadWithVectorDescriptor Descriptor; 5645 typedef LoadWithVectorDescriptor Descriptor;
5647 TailCallStub(Descriptor(isolate()), handler, p->context, 5646 TailCallStub(Descriptor(isolate()), handler, p->context,
5648 Arg(Descriptor::kReceiver, p->receiver), 5647 Arg(Descriptor::kReceiver, p->receiver),
5649 Arg(Descriptor::kName, p->name), 5648 Arg(Descriptor::kName, p->name),
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after
6079 Bind(&slow); 6078 Bind(&slow);
6080 { 6079 {
6081 Comment("KeyedLoadGeneric_slow"); 6080 Comment("KeyedLoadGeneric_slow");
6082 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_slow(), 1); 6081 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_slow(), 1);
6083 // TODO(jkummerow): Should we use the GetProperty TF stub instead? 6082 // TODO(jkummerow): Should we use the GetProperty TF stub instead?
6084 TailCallRuntime(Runtime::kKeyedGetProperty, p->context, p->receiver, 6083 TailCallRuntime(Runtime::kKeyedGetProperty, p->context, p->receiver,
6085 p->name); 6084 p->name);
6086 } 6085 }
6087 } 6086 }
6088 6087
6089 void CodeStubAssembler::HandleStoreFieldAndReturn( 6088 void CodeStubAssembler::HandleStoreFieldAndReturn(Node* handler_word,
6090 Node* handler_word, Node* holder, Representation representation, 6089 Node* holder,
6091 Node* value, bool transition_to_field, Label* miss) { 6090 Representation representation,
6091 Node* value, Node* transition,
6092 Label* miss) {
6093 bool transition_to_field = transition != nullptr;
6092 Node* prepared_value = PrepareValueForWrite(value, representation, miss); 6094 Node* prepared_value = PrepareValueForWrite(value, representation, miss);
6093 6095
6096 if (transition_to_field) {
6097 Label storage_extended(this);
6098 GotoUnless(IsSetWord<StoreHandler::ExtendStorageBits>(handler_word),
6099 &storage_extended);
6100 Comment("[ Extend storage");
6101 ExtendPropertiesBackingStore(holder);
6102 Comment("] Extend storage");
6103 Goto(&storage_extended);
6104
6105 Bind(&storage_extended);
6106 }
6107
6094 Node* offset = DecodeWord<StoreHandler::FieldOffsetBits>(handler_word); 6108 Node* offset = DecodeWord<StoreHandler::FieldOffsetBits>(handler_word);
6095 Label if_inobject(this), if_out_of_object(this); 6109 Label if_inobject(this), if_out_of_object(this);
6096 Branch(IsSetWord<StoreHandler::IsInobjectBits>(handler_word), &if_inobject, 6110 Branch(IsSetWord<StoreHandler::IsInobjectBits>(handler_word), &if_inobject,
6097 &if_out_of_object); 6111 &if_out_of_object);
6098 6112
6099 Bind(&if_inobject); 6113 Bind(&if_inobject);
6100 { 6114 {
6101 StoreNamedField(holder, offset, true, representation, prepared_value, 6115 StoreNamedField(holder, offset, true, representation, prepared_value,
6102 transition_to_field); 6116 transition_to_field);
6117 if (transition_to_field) {
6118 StoreObjectField(holder, JSObject::kMapOffset, transition);
6119 }
6103 Return(value); 6120 Return(value);
6104 } 6121 }
6105 6122
6106 Bind(&if_out_of_object); 6123 Bind(&if_out_of_object);
6107 { 6124 {
6108 StoreNamedField(holder, offset, false, representation, prepared_value, 6125 StoreNamedField(holder, offset, false, representation, prepared_value,
6109 transition_to_field); 6126 transition_to_field);
6127 if (transition_to_field) {
6128 StoreObjectField(holder, JSObject::kMapOffset, transition);
6129 }
6110 Return(value); 6130 Return(value);
6111 } 6131 }
6112 } 6132 }
6113 6133
6114 void CodeStubAssembler::HandleStoreICSmiHandlerCase(Node* handler_word, 6134 void CodeStubAssembler::HandleStoreICSmiHandlerCase(Node* handler_word,
6115 Node* holder, Node* value, 6135 Node* holder, Node* value,
6116 bool transition_to_field, 6136 Node* transition,
6117 Label* miss) { 6137 Label* miss) {
6118 Comment(transition_to_field ? "transitioning field store" : "field store"); 6138 Comment(transition ? "transitioning field store" : "field store");
6139
6140 #ifdef DEBUG
6141 Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word);
6142 if (transition) {
6143 CSA_ASSERT(
6144 this,
6145 WordOr(WordEqual(handler_kind,
6146 IntPtrConstant(StoreHandler::kTransitionToField)),
6147 WordEqual(handler_kind,
6148 IntPtrConstant(StoreHandler::kTransitionToConstant))));
6149 } else {
6150 CSA_ASSERT(this, WordEqual(handler_kind,
6151 IntPtrConstant(StoreHandler::kStoreField)));
6152 }
6153 #endif
6119 6154
6120 Node* field_representation = 6155 Node* field_representation =
6121 DecodeWord<StoreHandler::FieldRepresentationBits>(handler_word); 6156 DecodeWord<StoreHandler::FieldRepresentationBits>(handler_word);
6122 6157
6123 Label if_smi_field(this), if_double_field(this), if_heap_object_field(this), 6158 Label if_smi_field(this), if_double_field(this), if_heap_object_field(this),
6124 if_tagged_field(this); 6159 if_tagged_field(this);
6125 6160
6126 GotoIf(WordEqual(field_representation, IntPtrConstant(StoreHandler::kTagged)), 6161 GotoIf(WordEqual(field_representation, IntPtrConstant(StoreHandler::kTagged)),
6127 &if_tagged_field); 6162 &if_tagged_field);
6128 GotoIf(WordEqual(field_representation, 6163 GotoIf(WordEqual(field_representation,
6129 IntPtrConstant(StoreHandler::kHeapObject)), 6164 IntPtrConstant(StoreHandler::kHeapObject)),
6130 &if_heap_object_field); 6165 &if_heap_object_field);
6131 GotoIf(WordEqual(field_representation, IntPtrConstant(StoreHandler::kDouble)), 6166 GotoIf(WordEqual(field_representation, IntPtrConstant(StoreHandler::kDouble)),
6132 &if_double_field); 6167 &if_double_field);
6133 CSA_ASSERT(this, WordEqual(field_representation, 6168 CSA_ASSERT(this, WordEqual(field_representation,
6134 IntPtrConstant(StoreHandler::kSmi))); 6169 IntPtrConstant(StoreHandler::kSmi)));
6135 Goto(&if_smi_field); 6170 Goto(&if_smi_field);
6136 6171
6137 Bind(&if_tagged_field); 6172 Bind(&if_tagged_field);
6138 { 6173 {
6139 Comment("store tagged field"); 6174 Comment("store tagged field");
6140 HandleStoreFieldAndReturn(handler_word, holder, Representation::Tagged(), 6175 HandleStoreFieldAndReturn(handler_word, holder, Representation::Tagged(),
6141 value, transition_to_field, miss); 6176 value, transition, miss);
6142 } 6177 }
6143 6178
6144 Bind(&if_double_field); 6179 Bind(&if_double_field);
6145 { 6180 {
6146 Comment("store double field"); 6181 Comment("store double field");
6147 HandleStoreFieldAndReturn(handler_word, holder, Representation::Double(), 6182 HandleStoreFieldAndReturn(handler_word, holder, Representation::Double(),
6148 value, transition_to_field, miss); 6183 value, transition, miss);
6149 } 6184 }
6150 6185
6151 Bind(&if_heap_object_field); 6186 Bind(&if_heap_object_field);
6152 { 6187 {
6153 Comment("store heap object field"); 6188 Comment("store heap object field");
6154 // Generate full field type check here and then store value as Tagged. 6189 // Generate full field type check here and then store value as Tagged.
6155 Node* prepared_value = 6190 Node* prepared_value =
6156 PrepareValueForWrite(value, Representation::HeapObject(), miss); 6191 PrepareValueForWrite(value, Representation::HeapObject(), miss);
6157 Node* value_index_in_descriptor = 6192 Node* value_index_in_descriptor =
6158 DecodeWord<StoreHandler::DescriptorValueIndexBits>(handler_word); 6193 DecodeWord<StoreHandler::DescriptorValueIndexBits>(handler_word);
6159 Node* descriptors = LoadMapDescriptors(LoadMap(holder)); 6194 Node* descriptors =
6195 LoadMapDescriptors(transition ? transition : LoadMap(holder));
6160 Node* maybe_field_type = LoadFixedArrayElement( 6196 Node* maybe_field_type = LoadFixedArrayElement(
6161 descriptors, value_index_in_descriptor, 0, INTPTR_PARAMETERS); 6197 descriptors, value_index_in_descriptor, 0, INTPTR_PARAMETERS);
6162 Label do_store(this); 6198 Label do_store(this);
6163 GotoIf(TaggedIsSmi(maybe_field_type), &do_store); 6199 GotoIf(TaggedIsSmi(maybe_field_type), &do_store);
6164 // Check that value type matches the field type. 6200 // Check that value type matches the field type.
6165 { 6201 {
6166 Node* field_type = LoadWeakCellValue(maybe_field_type, miss); 6202 Node* field_type = LoadWeakCellValue(maybe_field_type, miss);
6167 Branch(WordEqual(LoadMap(prepared_value), field_type), &do_store, miss); 6203 Branch(WordEqual(LoadMap(prepared_value), field_type), &do_store, miss);
6168 } 6204 }
6169 Bind(&do_store); 6205 Bind(&do_store);
6170 HandleStoreFieldAndReturn(handler_word, holder, Representation::Tagged(), 6206 HandleStoreFieldAndReturn(handler_word, holder, Representation::Tagged(),
6171 prepared_value, transition_to_field, miss); 6207 prepared_value, transition, miss);
6172 } 6208 }
6173 6209
6174 Bind(&if_smi_field); 6210 Bind(&if_smi_field);
6175 { 6211 {
6176 Comment("store smi field"); 6212 Comment("store smi field");
6177 HandleStoreFieldAndReturn(handler_word, holder, Representation::Smi(), 6213 HandleStoreFieldAndReturn(handler_word, holder, Representation::Smi(),
6178 value, transition_to_field, miss); 6214 value, transition, miss);
6179 } 6215 }
6180 } 6216 }
6181 6217
6182 void CodeStubAssembler::HandleStoreICHandlerCase(const StoreICParameters* p, 6218 void CodeStubAssembler::HandleStoreICHandlerCase(const StoreICParameters* p,
6183 Node* handler, Label* miss) { 6219 Node* handler, Label* miss) {
6184 Label if_smi_handler(this), call_handler(this); 6220 Label if_smi_handler(this);
6221 Label try_proto_handler(this), call_handler(this);
6185 6222
6186 Branch(TaggedIsSmi(handler), &if_smi_handler, &call_handler); 6223 Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_handler);
6187 6224
6188 // |handler| is a Smi, encoding what to do. See SmiHandler methods 6225 // |handler| is a Smi, encoding what to do. See SmiHandler methods
6189 // for the encoding format. 6226 // for the encoding format.
6190 Bind(&if_smi_handler); 6227 Bind(&if_smi_handler);
6191 { 6228 {
6192 Node* holder = p->receiver; 6229 Node* holder = p->receiver;
6193 Node* handler_word = SmiUntag(handler); 6230 Node* handler_word = SmiUntag(handler);
6194 6231
6195 // Handle non-transitioning stores. 6232 // Handle non-transitioning field stores.
6196 HandleStoreICSmiHandlerCase(handler_word, holder, p->value, false, miss); 6233 HandleStoreICSmiHandlerCase(handler_word, holder, p->value, nullptr, miss);
6234 }
6235
6236 Bind(&try_proto_handler);
6237 {
6238 GotoIf(IsCodeMap(LoadMap(handler)), &call_handler);
6239 HandleStoreICProtoHandler(p, handler, miss);
6197 } 6240 }
6198 6241
6199 // |handler| is a heap object. Must be code, call it. 6242 // |handler| is a heap object. Must be code, call it.
6200 Bind(&call_handler); 6243 Bind(&call_handler);
6201 { 6244 {
6202 StoreWithVectorDescriptor descriptor(isolate()); 6245 StoreWithVectorDescriptor descriptor(isolate());
6203 TailCallStub(descriptor, handler, p->context, p->receiver, p->name, 6246 TailCallStub(descriptor, handler, p->context, p->receiver, p->name,
6204 p->value, p->slot, p->vector); 6247 p->value, p->slot, p->vector);
6205 } 6248 }
6206 } 6249 }
6207 6250
6251 void CodeStubAssembler::HandleStoreICProtoHandler(const StoreICParameters* p,
6252 Node* handler, Label* miss) {
6253 // IC dispatchers rely on these assumptions to be held.
6254 STATIC_ASSERT(FixedArray::kLengthOffset ==
6255 StoreHandler::kTransitionCellOffset);
6256 DCHECK_EQ(FixedArray::OffsetOfElementAt(StoreHandler::kSmiHandlerIndex),
6257 StoreHandler::kSmiHandlerOffset);
6258 DCHECK_EQ(FixedArray::OffsetOfElementAt(StoreHandler::kValidityCellIndex),
6259 StoreHandler::kValidityCellOffset);
6260
6261 // Both FixedArray and Tuple3 handlers have validity cell at the same offset.
6262 Label validity_cell_check_done(this);
6263 Node* validity_cell =
6264 LoadObjectField(handler, StoreHandler::kValidityCellOffset);
6265 GotoIf(WordEqual(validity_cell, IntPtrConstant(0)),
6266 &validity_cell_check_done);
6267 Node* cell_value = LoadObjectField(validity_cell, Cell::kValueOffset);
6268 GotoIf(WordNotEqual(cell_value,
6269 SmiConstant(Smi::FromInt(Map::kPrototypeChainValid))),
6270 miss);
6271 Goto(&validity_cell_check_done);
6272
6273 Bind(&validity_cell_check_done);
6274 Node* smi_handler = LoadObjectField(handler, StoreHandler::kSmiHandlerOffset);
6275 CSA_ASSERT(this, TaggedIsSmi(smi_handler));
6276
6277 Node* maybe_transition_cell =
6278 LoadObjectField(handler, StoreHandler::kTransitionCellOffset);
6279 Label array_handler(this), tuple_handler(this);
6280 Branch(TaggedIsSmi(maybe_transition_cell), &array_handler, &tuple_handler);
6281
6282 Variable var_transition(this, MachineRepresentation::kTagged);
6283 Label if_transition(this), if_transition_to_constant(this);
6284 Bind(&tuple_handler);
6285 {
6286 Node* transition = LoadWeakCellValue(maybe_transition_cell, miss);
6287 var_transition.Bind(transition);
6288 Goto(&if_transition);
6289 }
6290
6291 Bind(&array_handler);
6292 {
6293 Node* length = SmiUntag(maybe_transition_cell);
6294 BuildFastLoop(MachineType::PointerRepresentation(),
6295 IntPtrConstant(StoreHandler::kFirstPrototypeIndex), length,
6296 [this, p, handler, miss](CodeStubAssembler*, Node* current) {
6297 Node* prototype_cell = LoadFixedArrayElement(
6298 handler, current, 0, INTPTR_PARAMETERS);
6299 CheckPrototype(prototype_cell, p->name, miss);
6300 },
6301 1, IndexAdvanceMode::kPost);
6302
6303 Node* maybe_transition_cell = LoadFixedArrayElement(
6304 handler, IntPtrConstant(StoreHandler::kTransitionCellIndex), 0,
6305 INTPTR_PARAMETERS);
6306 Node* transition = LoadWeakCellValue(maybe_transition_cell, miss);
6307 var_transition.Bind(transition);
6308 Goto(&if_transition);
6309 }
6310
6311 Bind(&if_transition);
6312 {
6313 Node* holder = p->receiver;
6314 Node* transition = var_transition.value();
6315 Node* handler_word = SmiUntag(smi_handler);
6316
6317 GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(transition)), miss);
6318
6319 Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word);
6320 GotoIf(WordEqual(handler_kind,
6321 IntPtrConstant(StoreHandler::kTransitionToConstant)),
6322 &if_transition_to_constant);
6323
6324 // Handle transitioning field stores.
6325 HandleStoreICSmiHandlerCase(handler_word, holder, p->value, transition,
6326 miss);
6327
6328 Bind(&if_transition_to_constant);
6329 {
6330 // Check that constant matches value.
6331 Node* value_index_in_descriptor =
6332 DecodeWord<StoreHandler::DescriptorValueIndexBits>(handler_word);
6333 Node* descriptors = LoadMapDescriptors(transition);
6334 Node* constant = LoadFixedArrayElement(
6335 descriptors, value_index_in_descriptor, 0, INTPTR_PARAMETERS);
6336 GotoIf(WordNotEqual(p->value, constant), miss);
6337
6338 StoreObjectField(p->receiver, JSObject::kMapOffset, transition);
6339 Return(p->value);
6340 }
6341 }
6342 }
6343
6208 void CodeStubAssembler::StoreIC(const StoreICParameters* p) { 6344 void CodeStubAssembler::StoreIC(const StoreICParameters* p) {
6209 Variable var_handler(this, MachineRepresentation::kTagged); 6345 Variable var_handler(this, MachineRepresentation::kTagged);
6210 // TODO(ishell): defer blocks when it works. 6346 // TODO(ishell): defer blocks when it works.
6211 Label if_handler(this, &var_handler), try_polymorphic(this), 6347 Label if_handler(this, &var_handler), try_polymorphic(this),
6212 try_megamorphic(this /*, Label::kDeferred*/), 6348 try_megamorphic(this /*, Label::kDeferred*/),
6213 miss(this /*, Label::kDeferred*/); 6349 miss(this /*, Label::kDeferred*/);
6214 6350
6215 Node* receiver_map = LoadReceiverMap(p->receiver); 6351 Node* receiver_map = LoadReceiverMap(p->receiver);
6216 6352
6217 // Check monomorphic case. 6353 // Check monomorphic case.
(...skipping 2692 matching lines...) Expand 10 before | Expand all | Expand 10 after
8910 } 9046 }
8911 9047
8912 void CodeStubArguments::PopAndReturn(compiler::Node* value) { 9048 void CodeStubArguments::PopAndReturn(compiler::Node* value) {
8913 assembler_->PopAndReturn( 9049 assembler_->PopAndReturn(
8914 assembler_->IntPtrAddFoldConstants(argc_, assembler_->IntPtrConstant(1)), 9050 assembler_->IntPtrAddFoldConstants(argc_, assembler_->IntPtrConstant(1)),
8915 value); 9051 value);
8916 } 9052 }
8917 9053
8918 } // namespace internal 9054 } // namespace internal
8919 } // namespace v8 9055 } // namespace v8
OLDNEW
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/counters.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698