Commit 40672966 authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[ic] Move the elements transition target out from the polymorphic array into the tuple3 handler

BUG=v8:5561

Change-Id: If8f166860b4d4f9f25b15badfda531cbef49db16
Reviewed-on: https://chromium-review.googlesource.com/457341Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#43985}
parent e3826bc7
......@@ -775,48 +775,16 @@ void KeyedStoreICNexus::ConfigurePolymorphic(Handle<Name> name,
}
void KeyedStoreICNexus::ConfigurePolymorphic(MapHandleList* maps,
MapHandleList* transitioned_maps,
List<Handle<Object>>* handlers) {
int receiver_count = maps->length();
DCHECK(receiver_count > 1);
Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 3);
Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 2);
SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(GetIsolate()),
SKIP_WRITE_BARRIER);
Handle<Oddball> undefined_value = GetIsolate()->factory()->undefined_value();
for (int i = 0; i < receiver_count; ++i) {
Handle<Map> map = maps->at(i);
Handle<WeakCell> cell = Map::WeakCellForMap(map);
array->set(i * 3, *cell);
if (!transitioned_maps->at(i).is_null()) {
Handle<Map> transitioned_map = transitioned_maps->at(i);
cell = Map::WeakCellForMap(transitioned_map);
array->set((i * 3) + 1, *cell);
} else {
array->set((i * 3) + 1, *undefined_value);
}
array->set((i * 3) + 2, *handlers->at(i));
}
}
namespace {
int GetStepSize(FixedArray* array, Isolate* isolate) {
// The array should be of the form
// [map, handler, map, handler, ...]
// or
// [map, map, handler, map, map, handler, ...]
// where "map" is either a WeakCell or |undefined|,
// and "handler" is either a Code object or a Smi.
DCHECK(array->length() >= 2);
Object* second = array->get(1);
if (second->IsWeakCell() || second->IsUndefined(isolate)) return 3;
DCHECK(IC::IsHandler(second));
return 2;
InstallHandlers(array, maps, handlers);
}
} // namespace
int FeedbackNexus::ExtractMaps(MapHandleList* maps) const {
Isolate* isolate = GetIsolate();
Object* feedback = GetFeedback();
......@@ -827,7 +795,7 @@ int FeedbackNexus::ExtractMaps(MapHandleList* maps) const {
feedback = GetFeedbackExtra();
}
FixedArray* array = FixedArray::cast(feedback);
int increment = GetStepSize(array, isolate);
const int increment = 2;
for (int i = 0; i < array->length(); i += increment) {
DCHECK(array->get(i)->IsWeakCell());
WeakCell* cell = WeakCell::cast(array->get(i));
......@@ -859,7 +827,7 @@ MaybeHandle<Object> FeedbackNexus::FindHandlerForMap(Handle<Map> map) const {
feedback = GetFeedbackExtra();
}
FixedArray* array = FixedArray::cast(feedback);
int increment = GetStepSize(array, isolate);
const int increment = 2;
for (int i = 0; i < array->length(); i += increment) {
DCHECK(array->get(i)->IsWeakCell());
WeakCell* cell = WeakCell::cast(array->get(i));
......@@ -898,7 +866,7 @@ bool FeedbackNexus::FindHandlers(List<Handle<Object>>* code_list,
feedback = GetFeedbackExtra();
}
FixedArray* array = FixedArray::cast(feedback);
int increment = GetStepSize(array, isolate);
const int increment = 2;
for (int i = 0; i < array->length(); i += increment) {
DCHECK(array->get(i)->IsWeakCell());
WeakCell* cell = WeakCell::cast(array->get(i));
......@@ -951,10 +919,16 @@ KeyedAccessStoreMode KeyedStoreICNexus::GetKeyedAccessStoreMode() const {
// The first handler that isn't the slow handler will have the bits we need.
Handle<Object> maybe_code_handler = handlers.at(i);
Handle<Code> handler;
if (maybe_code_handler->IsTuple2()) {
if (maybe_code_handler->IsTuple3()) {
// Elements transition.
Handle<Tuple3> data_handler = Handle<Tuple3>::cast(maybe_code_handler);
handler = handle(Code::cast(data_handler->value2()));
} else if (maybe_code_handler->IsTuple2()) {
// Element store with prototype chain check.
Handle<Tuple2> data_handler = Handle<Tuple2>::cast(maybe_code_handler);
handler = handle(Code::cast(data_handler->value2()));
} else {
// Element store without prototype chain check.
handler = Handle<Code>::cast(maybe_code_handler);
}
CodeStub::Major major_key = CodeStub::MajorKeyFromKey(handler->stub_key());
......
......@@ -666,7 +666,6 @@ class KeyedStoreICNexus : public FeedbackNexus {
void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps,
List<Handle<Object>>* handlers);
void ConfigurePolymorphic(MapHandleList* maps,
MapHandleList* transitioned_maps,
List<Handle<Object>>* handlers);
void ConfigureMegamorphicKeyed(IcCheckType property_type);
......
......@@ -126,35 +126,27 @@ void AccessorAssembler::HandlePolymorphicCase(Node* receiver_map,
Goto(if_miss);
}
void AccessorAssembler::HandleKeyedStorePolymorphicCase(
Node* receiver_map, Node* feedback, Label* if_handler,
Variable* var_handler, Label* if_transition_handler,
Variable* var_transition_map_cell, Label* if_miss) {
void AccessorAssembler::HandleKeyedStorePolymorphicCase(Node* receiver_map,
Node* feedback,
Label* if_handler,
Variable* var_handler,
Label* if_miss) {
DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep());
DCHECK_EQ(MachineRepresentation::kTagged, var_transition_map_cell->rep());
const int kEntrySize = 3;
const int kEntrySize = 2;
Node* init = IntPtrConstant(0);
Node* length = LoadAndUntagFixedArrayBaseLength(feedback);
BuildFastLoop(init, length,
[this, receiver_map, feedback, if_handler, var_handler,
if_transition_handler, var_transition_map_cell](Node* index) {
[=](Node* index) {
Node* cached_map =
LoadWeakCellValue(LoadFixedArrayElement(feedback, index));
Label next_entry(this);
GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry);
Node* maybe_transition_map_cell =
LoadFixedArrayElement(feedback, index, kPointerSize);
var_handler->Bind(
LoadFixedArrayElement(feedback, index, 2 * kPointerSize));
GotoIf(WordEqual(maybe_transition_map_cell,
LoadRoot(Heap::kUndefinedValueRootIndex)),
if_handler);
var_transition_map_cell->Bind(maybe_transition_map_cell);
Goto(if_transition_handler);
LoadFixedArrayElement(feedback, index, kPointerSize));
Goto(if_handler);
Bind(&next_entry);
},
......@@ -674,9 +666,7 @@ void AccessorAssembler::HandleStoreICHandlerCase(
}
Bind(&if_proto_handler);
{
HandleStoreICProtoHandler(p, handler, miss);
}
{ HandleStoreICProtoHandler(p, handler, miss, support_elements); }
// |handler| is a heap object. Must be code, call it.
Bind(&call_handler);
......@@ -704,8 +694,9 @@ void AccessorAssembler::HandleStoreICElementHandlerCase(
p->value, p->slot, p->vector);
}
void AccessorAssembler::HandleStoreICProtoHandler(const StoreICParameters* p,
Node* handler, Label* miss) {
void AccessorAssembler::HandleStoreICProtoHandler(
const StoreICParameters* p, Node* handler, Label* miss,
ElementSupport support_elements) {
// IC dispatchers rely on these assumptions to be held.
STATIC_ASSERT(FixedArray::kLengthOffset ==
StoreHandler::kTransitionCellOffset);
......@@ -727,8 +718,7 @@ void AccessorAssembler::HandleStoreICProtoHandler(const StoreICParameters* p,
Goto(&validity_cell_check_done);
Bind(&validity_cell_check_done);
Node* smi_handler = LoadObjectField(handler, StoreHandler::kSmiHandlerOffset);
CSA_ASSERT(this, TaggedIsSmi(smi_handler));
Node* smi_or_code = LoadObjectField(handler, StoreHandler::kSmiHandlerOffset);
Node* maybe_transition_cell =
LoadObjectField(handler, StoreHandler::kTransitionCellOffset);
......@@ -767,10 +757,26 @@ void AccessorAssembler::HandleStoreICProtoHandler(const StoreICParameters* p,
{
Node* holder = p->receiver;
Node* transition = var_transition.value();
Node* handler_word = SmiUntag(smi_handler);
GotoIf(IsDeprecatedMap(transition), miss);
if (support_elements == kSupportElements) {
Label if_smi_handler(this);
GotoIf(TaggedIsSmi(smi_or_code), &if_smi_handler);
Node* code_handler = smi_or_code;
CSA_ASSERT(this, IsCodeMap(LoadMap(code_handler)));
StoreTransitionDescriptor descriptor(isolate());
TailCallStub(descriptor, code_handler, p->context, p->receiver, p->name,
transition, p->value, p->slot, p->vector);
Bind(&if_smi_handler);
}
Node* smi_handler = smi_or_code;
Node* handler_word = SmiUntag(smi_handler);
Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word);
GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kStoreNormal)),
&if_store_normal);
......@@ -2172,47 +2178,8 @@ void AccessorAssembler::KeyedStoreIC(const StoreICParameters* p,
GotoIfNot(
WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)),
&try_megamorphic);
Label if_transition_handler(this);
Variable var_transition_map_cell(this, MachineRepresentation::kTagged);
HandleKeyedStorePolymorphicCase(receiver_map, feedback, &if_handler,
&var_handler, &if_transition_handler,
&var_transition_map_cell, &miss);
Bind(&if_transition_handler);
Comment("KeyedStoreIC_polymorphic_transition");
{
Node* handler = var_handler.value();
Label call_handler(this);
Variable var_code_handler(this, MachineRepresentation::kTagged);
var_code_handler.Bind(handler);
GotoIfNot(IsTuple2Map(LoadMap(handler)), &call_handler);
{
CSA_ASSERT(this, IsTuple2Map(LoadMap(handler)));
// Check validity cell.
Node* validity_cell = LoadObjectField(handler, Tuple2::kValue1Offset);
Node* cell_value = LoadObjectField(validity_cell, Cell::kValueOffset);
GotoIf(
WordNotEqual(cell_value, SmiConstant(Map::kPrototypeChainValid)),
&miss);
var_code_handler.Bind(
LoadObjectField(handler, Tuple2::kValue2Offset));
Goto(&call_handler);
}
Bind(&call_handler);
{
Node* code_handler = var_code_handler.value();
CSA_ASSERT(this, IsCodeMap(LoadMap(code_handler)));
Node* transition_map =
LoadWeakCellValue(var_transition_map_cell.value(), &miss);
StoreTransitionDescriptor descriptor(isolate());
TailCallStub(descriptor, code_handler, p->context, p->receiver,
p->name, transition_map, p->value, p->slot, p->vector);
}
}
&var_handler, &miss);
}
Bind(&try_megamorphic);
......
......@@ -126,8 +126,6 @@ class AccessorAssembler : public CodeStubAssembler {
Label* if_miss, int min_feedback_capacity);
void HandleKeyedStorePolymorphicCase(Node* receiver_map, Node* feedback,
Label* if_handler, Variable* var_handler,
Label* if_transition_handler,
Variable* var_transition_map_cell,
Label* if_miss);
// LoadIC implementation.
......@@ -169,7 +167,7 @@ class AccessorAssembler : public CodeStubAssembler {
Node* handler, Label* miss);
void HandleStoreICProtoHandler(const StoreICParameters* p, Node* handler,
Label* miss);
Label* miss, ElementSupport support_elements);
// If |transition| is nullptr then the normal field store is generated or
// transitioning store otherwise.
void HandleStoreICSmiHandlerCase(Node* handler_word, Node* holder,
......
......@@ -633,11 +633,10 @@ void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps,
}
void IC::ConfigureVectorState(MapHandleList* maps,
MapHandleList* transitioned_maps,
List<Handle<Object>>* handlers) {
DCHECK(IsKeyedStoreIC());
KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
nexus->ConfigurePolymorphic(maps, transitioned_maps, handlers);
nexus->ConfigurePolymorphic(maps, handlers);
vector_set_ = true;
OnFeedbackChanged(isolate(), GetHostFunction());
......@@ -2166,11 +2165,9 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
}
}
MapHandleList transitioned_maps(target_receiver_maps.length());
List<Handle<Object>> handlers(target_receiver_maps.length());
StoreElementPolymorphicHandlers(&target_receiver_maps, &transitioned_maps,
&handlers, store_mode);
ConfigureVectorState(&target_receiver_maps, &transitioned_maps, &handlers);
StoreElementPolymorphicHandlers(&target_receiver_maps, &handlers, store_mode);
ConfigureVectorState(&target_receiver_maps, &handlers);
}
......@@ -2230,15 +2227,13 @@ Handle<Object> KeyedStoreIC::StoreElementHandler(
}
Handle<Object> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
if (validity_cell.is_null()) {
return stub;
}
if (validity_cell.is_null()) return stub;
return isolate()->factory()->NewTuple2(validity_cell, stub);
}
void KeyedStoreIC::StoreElementPolymorphicHandlers(
MapHandleList* receiver_maps, MapHandleList* transitioned_maps,
List<Handle<Object>>* handlers, KeyedAccessStoreMode store_mode) {
MapHandleList* receiver_maps, List<Handle<Object>>* handlers,
KeyedAccessStoreMode store_mode) {
DCHECK(store_mode == STANDARD_STORE ||
store_mode == STORE_AND_GROW_NO_TRANSITION ||
store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
......@@ -2281,17 +2276,17 @@ void KeyedStoreIC::StoreElementPolymorphicHandlers(
Handle<Object> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
if (validity_cell.is_null()) {
handler = stub;
} else {
handler = isolate()->factory()->NewTuple2(validity_cell, stub);
validity_cell = handle(Smi::kZero, isolate());
}
Handle<WeakCell> transition = Map::WeakCellForMap(transitioned_map);
handler =
isolate()->factory()->NewTuple3(transition, stub, validity_cell);
} else {
handler = StoreElementHandler(receiver_map, store_mode);
}
}
DCHECK(!handler.is_null());
handlers->Add(handler);
transitioned_maps->Add(transitioned_map);
}
}
......
......@@ -100,7 +100,6 @@ class IC {
// Configure the vector for POLYMORPHIC with transitions (only for element
// keyed stores).
void ConfigureVectorState(MapHandleList* maps,
MapHandleList* transitioned_maps,
List<Handle<Object>>* handlers);
char TransitionMarkFromState(IC::State state);
......@@ -408,7 +407,6 @@ class KeyedStoreIC : public StoreIC {
KeyedAccessStoreMode store_mode);
void StoreElementPolymorphicHandlers(MapHandleList* receiver_maps,
MapHandleList* transitioned_maps,
List<Handle<Object>>* handlers,
KeyedAccessStoreMode store_mode);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment