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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/counters.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/code-stub-assembler.cc
diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc
index 2e73c89cb63fdc1eeb9a86e382dbc419a34453ed..323c05d17e737cbbfdc0e5acfb1dc6625743b867 100644
--- a/src/code-stub-assembler.cc
+++ b/src/code-stub-assembler.cc
@@ -5635,8 +5635,7 @@ void CodeStubAssembler::HandleLoadICHandlerCase(
Bind(&try_proto_handler);
{
- GotoIf(WordEqual(LoadMap(handler), LoadRoot(Heap::kCodeMapRootIndex)),
- &call_handler);
+ GotoIf(IsCodeMap(LoadMap(handler)), &call_handler);
HandleLoadICProtoHandler(p, handler, &var_holder, &var_smi_handler,
&if_smi_handler, miss);
}
@@ -6086,11 +6085,26 @@ void CodeStubAssembler::KeyedLoadICGeneric(const LoadICParameters* p) {
}
}
-void CodeStubAssembler::HandleStoreFieldAndReturn(
- Node* handler_word, Node* holder, Representation representation,
- Node* value, bool transition_to_field, Label* miss) {
+void CodeStubAssembler::HandleStoreFieldAndReturn(Node* handler_word,
+ Node* holder,
+ Representation representation,
+ Node* value, Node* transition,
+ Label* miss) {
+ bool transition_to_field = transition != nullptr;
Node* prepared_value = PrepareValueForWrite(value, representation, miss);
+ if (transition_to_field) {
+ Label storage_extended(this);
+ GotoUnless(IsSetWord<StoreHandler::ExtendStorageBits>(handler_word),
+ &storage_extended);
+ Comment("[ Extend storage");
+ ExtendPropertiesBackingStore(holder);
+ Comment("] Extend storage");
+ Goto(&storage_extended);
+
+ Bind(&storage_extended);
+ }
+
Node* offset = DecodeWord<StoreHandler::FieldOffsetBits>(handler_word);
Label if_inobject(this), if_out_of_object(this);
Branch(IsSetWord<StoreHandler::IsInobjectBits>(handler_word), &if_inobject,
@@ -6100,6 +6114,9 @@ void CodeStubAssembler::HandleStoreFieldAndReturn(
{
StoreNamedField(holder, offset, true, representation, prepared_value,
transition_to_field);
+ if (transition_to_field) {
+ StoreObjectField(holder, JSObject::kMapOffset, transition);
+ }
Return(value);
}
@@ -6107,15 +6124,33 @@ void CodeStubAssembler::HandleStoreFieldAndReturn(
{
StoreNamedField(holder, offset, false, representation, prepared_value,
transition_to_field);
+ if (transition_to_field) {
+ StoreObjectField(holder, JSObject::kMapOffset, transition);
+ }
Return(value);
}
}
void CodeStubAssembler::HandleStoreICSmiHandlerCase(Node* handler_word,
Node* holder, Node* value,
- bool transition_to_field,
+ Node* transition,
Label* miss) {
- Comment(transition_to_field ? "transitioning field store" : "field store");
+ Comment(transition ? "transitioning field store" : "field store");
+
+#ifdef DEBUG
+ Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word);
+ if (transition) {
+ CSA_ASSERT(
+ this,
+ WordOr(WordEqual(handler_kind,
+ IntPtrConstant(StoreHandler::kTransitionToField)),
+ WordEqual(handler_kind,
+ IntPtrConstant(StoreHandler::kTransitionToConstant))));
+ } else {
+ CSA_ASSERT(this, WordEqual(handler_kind,
+ IntPtrConstant(StoreHandler::kStoreField)));
+ }
+#endif
Node* field_representation =
DecodeWord<StoreHandler::FieldRepresentationBits>(handler_word);
@@ -6138,14 +6173,14 @@ void CodeStubAssembler::HandleStoreICSmiHandlerCase(Node* handler_word,
{
Comment("store tagged field");
HandleStoreFieldAndReturn(handler_word, holder, Representation::Tagged(),
- value, transition_to_field, miss);
+ value, transition, miss);
}
Bind(&if_double_field);
{
Comment("store double field");
HandleStoreFieldAndReturn(handler_word, holder, Representation::Double(),
- value, transition_to_field, miss);
+ value, transition, miss);
}
Bind(&if_heap_object_field);
@@ -6156,7 +6191,8 @@ void CodeStubAssembler::HandleStoreICSmiHandlerCase(Node* handler_word,
PrepareValueForWrite(value, Representation::HeapObject(), miss);
Node* value_index_in_descriptor =
DecodeWord<StoreHandler::DescriptorValueIndexBits>(handler_word);
- Node* descriptors = LoadMapDescriptors(LoadMap(holder));
+ Node* descriptors =
+ LoadMapDescriptors(transition ? transition : LoadMap(holder));
Node* maybe_field_type = LoadFixedArrayElement(
descriptors, value_index_in_descriptor, 0, INTPTR_PARAMETERS);
Label do_store(this);
@@ -6168,22 +6204,23 @@ void CodeStubAssembler::HandleStoreICSmiHandlerCase(Node* handler_word,
}
Bind(&do_store);
HandleStoreFieldAndReturn(handler_word, holder, Representation::Tagged(),
- prepared_value, transition_to_field, miss);
+ prepared_value, transition, miss);
}
Bind(&if_smi_field);
{
Comment("store smi field");
HandleStoreFieldAndReturn(handler_word, holder, Representation::Smi(),
- value, transition_to_field, miss);
+ value, transition, miss);
}
}
void CodeStubAssembler::HandleStoreICHandlerCase(const StoreICParameters* p,
Node* handler, Label* miss) {
- Label if_smi_handler(this), call_handler(this);
+ Label if_smi_handler(this);
+ Label try_proto_handler(this), call_handler(this);
- Branch(TaggedIsSmi(handler), &if_smi_handler, &call_handler);
+ Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_handler);
// |handler| is a Smi, encoding what to do. See SmiHandler methods
// for the encoding format.
@@ -6192,8 +6229,14 @@ void CodeStubAssembler::HandleStoreICHandlerCase(const StoreICParameters* p,
Node* holder = p->receiver;
Node* handler_word = SmiUntag(handler);
- // Handle non-transitioning stores.
- HandleStoreICSmiHandlerCase(handler_word, holder, p->value, false, miss);
+ // Handle non-transitioning field stores.
+ HandleStoreICSmiHandlerCase(handler_word, holder, p->value, nullptr, miss);
+ }
+
+ Bind(&try_proto_handler);
+ {
+ GotoIf(IsCodeMap(LoadMap(handler)), &call_handler);
+ HandleStoreICProtoHandler(p, handler, miss);
}
// |handler| is a heap object. Must be code, call it.
@@ -6205,6 +6248,99 @@ void CodeStubAssembler::HandleStoreICHandlerCase(const StoreICParameters* p,
}
}
+void CodeStubAssembler::HandleStoreICProtoHandler(const StoreICParameters* p,
+ Node* handler, Label* miss) {
+ // IC dispatchers rely on these assumptions to be held.
+ STATIC_ASSERT(FixedArray::kLengthOffset ==
+ StoreHandler::kTransitionCellOffset);
+ DCHECK_EQ(FixedArray::OffsetOfElementAt(StoreHandler::kSmiHandlerIndex),
+ StoreHandler::kSmiHandlerOffset);
+ DCHECK_EQ(FixedArray::OffsetOfElementAt(StoreHandler::kValidityCellIndex),
+ StoreHandler::kValidityCellOffset);
+
+ // Both FixedArray and Tuple3 handlers have validity cell at the same offset.
+ Label validity_cell_check_done(this);
+ Node* validity_cell =
+ LoadObjectField(handler, StoreHandler::kValidityCellOffset);
+ GotoIf(WordEqual(validity_cell, IntPtrConstant(0)),
+ &validity_cell_check_done);
+ Node* cell_value = LoadObjectField(validity_cell, Cell::kValueOffset);
+ GotoIf(WordNotEqual(cell_value,
+ SmiConstant(Smi::FromInt(Map::kPrototypeChainValid))),
+ miss);
+ Goto(&validity_cell_check_done);
+
+ Bind(&validity_cell_check_done);
+ Node* smi_handler = LoadObjectField(handler, StoreHandler::kSmiHandlerOffset);
+ CSA_ASSERT(this, TaggedIsSmi(smi_handler));
+
+ Node* maybe_transition_cell =
+ LoadObjectField(handler, StoreHandler::kTransitionCellOffset);
+ Label array_handler(this), tuple_handler(this);
+ Branch(TaggedIsSmi(maybe_transition_cell), &array_handler, &tuple_handler);
+
+ Variable var_transition(this, MachineRepresentation::kTagged);
+ Label if_transition(this), if_transition_to_constant(this);
+ Bind(&tuple_handler);
+ {
+ Node* transition = LoadWeakCellValue(maybe_transition_cell, miss);
+ var_transition.Bind(transition);
+ Goto(&if_transition);
+ }
+
+ Bind(&array_handler);
+ {
+ Node* length = SmiUntag(maybe_transition_cell);
+ BuildFastLoop(MachineType::PointerRepresentation(),
+ IntPtrConstant(StoreHandler::kFirstPrototypeIndex), length,
+ [this, p, handler, miss](CodeStubAssembler*, Node* current) {
+ Node* prototype_cell = LoadFixedArrayElement(
+ handler, current, 0, INTPTR_PARAMETERS);
+ CheckPrototype(prototype_cell, p->name, miss);
+ },
+ 1, IndexAdvanceMode::kPost);
+
+ Node* maybe_transition_cell = LoadFixedArrayElement(
+ handler, IntPtrConstant(StoreHandler::kTransitionCellIndex), 0,
+ INTPTR_PARAMETERS);
+ Node* transition = LoadWeakCellValue(maybe_transition_cell, miss);
+ var_transition.Bind(transition);
+ Goto(&if_transition);
+ }
+
+ Bind(&if_transition);
+ {
+ Node* holder = p->receiver;
+ Node* transition = var_transition.value();
+ Node* handler_word = SmiUntag(smi_handler);
+
+ GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(transition)), miss);
+
+ Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word);
+ GotoIf(WordEqual(handler_kind,
+ IntPtrConstant(StoreHandler::kTransitionToConstant)),
+ &if_transition_to_constant);
+
+ // Handle transitioning field stores.
+ HandleStoreICSmiHandlerCase(handler_word, holder, p->value, transition,
+ miss);
+
+ Bind(&if_transition_to_constant);
+ {
+ // Check that constant matches value.
+ Node* value_index_in_descriptor =
+ DecodeWord<StoreHandler::DescriptorValueIndexBits>(handler_word);
+ Node* descriptors = LoadMapDescriptors(transition);
+ Node* constant = LoadFixedArrayElement(
+ descriptors, value_index_in_descriptor, 0, INTPTR_PARAMETERS);
+ GotoIf(WordNotEqual(p->value, constant), miss);
+
+ StoreObjectField(p->receiver, JSObject::kMapOffset, transition);
+ Return(p->value);
+ }
+ }
+}
+
void CodeStubAssembler::StoreIC(const StoreICParameters* p) {
Variable var_handler(this, MachineRepresentation::kTagged);
// TODO(ishell): defer blocks when it works.
« 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