[ic] Don't use slow stub handler for fresh transitioning stores.

Given that we got a store transition handler for free (because it's just
a transition map) there's no need to wait for a second "use" of that
transition in order to install a normal store transition handler.

Bug: v8:5988
Change-Id: Iecdcfdd096a8efffdd0662f1b1d604943e57d85a
Reviewed-on: https://chromium-review.googlesource.com/997553
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52442}
This commit is contained in:
Igor Sheludko 2018-04-05 11:35:08 +02:00 committed by Commit Bot
parent 1f7d80cd97
commit d1532a1aef
7 changed files with 19 additions and 37 deletions

View File

@ -1300,8 +1300,8 @@ bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value,
if (it->HolderIsReceiverOrHiddenPrototype()) return false;
if (it->ExtendingNonExtensible(receiver)) return false;
created_new_transition_ = it->PrepareTransitionToDataProperty(
receiver, value, NONE, store_mode);
it->PrepareTransitionToDataProperty(receiver, value, NONE,
store_mode);
return it->IsCacheableTransition();
}
}
@ -1310,8 +1310,7 @@ bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value,
receiver = it->GetStoreTarget<JSObject>();
if (it->ExtendingNonExtensible(receiver)) return false;
created_new_transition_ =
it->PrepareTransitionToDataProperty(receiver, value, NONE, store_mode);
it->PrepareTransitionToDataProperty(receiver, value, NONE, store_mode);
return it->IsCacheableTransition();
}
@ -1435,13 +1434,6 @@ void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
return;
}
}
if (created_new_transition_) {
// The first time a transition is performed, there's a good chance that
// it won't be taken again, so don't bother creating a handler.
set_slow_stub_reason("new transition");
TraceIC("StoreIC", lookup->name());
return;
}
handler = ComputeHandler(lookup);
} else {
set_slow_stub_reason("LookupForWrite said 'false'");

View File

@ -329,8 +329,6 @@ class StoreIC : public IC {
Handle<Object> ComputeHandler(LookupIterator* lookup);
friend class IC;
bool created_new_transition_ = false;
};
class StoreGlobalIC : public StoreIC {

View File

@ -495,14 +495,12 @@ void LookupIterator::ReconfigureDataProperty(Handle<Object> value,
// Can only be called when the receiver is a JSObject. JSProxy has to be handled
// via a trap. Adding properties to primitive values is not observable.
// Returns true if a new transition has been created, or false if an existing
// transition was followed.
bool LookupIterator::PrepareTransitionToDataProperty(
void LookupIterator::PrepareTransitionToDataProperty(
Handle<JSReceiver> receiver, Handle<Object> value,
PropertyAttributes attributes, Object::StoreFromKeyed store_mode) {
DCHECK_IMPLIES(receiver->IsJSProxy(), name()->IsPrivate());
DCHECK(receiver.is_identical_to(GetStoreTarget<JSReceiver>()));
if (state_ == TRANSITION) return false;
if (state_ == TRANSITION) return;
if (!IsElement() && name()->IsPrivate()) {
attributes = static_cast<PropertyAttributes>(attributes | DONT_ENUM);
@ -548,13 +546,11 @@ bool LookupIterator::PrepareTransitionToDataProperty(
PropertyDetails(kData, attributes, PropertyCellType::kNoCell);
transition_ = map;
}
return false;
return;
}
bool created_new_map;
Handle<Map> transition = Map::TransitionToDataProperty(
map, name_, value, attributes, kDefaultFieldConstness, store_mode,
&created_new_map);
map, name_, value, attributes, kDefaultFieldConstness, store_mode);
state_ = TRANSITION;
transition_ = transition;
@ -566,7 +562,6 @@ bool LookupIterator::PrepareTransitionToDataProperty(
property_details_ = transition->GetLastDescriptorDetails();
has_property_ = true;
}
return created_new_map;
}
void LookupIterator::ApplyTransitionToDataProperty(

View File

@ -216,7 +216,7 @@ class V8_EXPORT_PRIVATE LookupIterator final BASE_EMBEDDED {
(IsElement() || !name_->IsPrivate());
}
void PrepareForDataProperty(Handle<Object> value);
bool PrepareTransitionToDataProperty(Handle<JSReceiver> receiver,
void PrepareTransitionToDataProperty(Handle<JSReceiver> receiver,
Handle<Object> value,
PropertyAttributes attributes,
Object::StoreFromKeyed store_mode);

View File

@ -9744,8 +9744,7 @@ Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
Handle<Object> value,
PropertyAttributes attributes,
PropertyConstness constness,
StoreFromKeyed store_mode,
bool* created_new_map) {
StoreFromKeyed store_mode) {
RuntimeCallTimerScope stats_scope(
*map, map->is_prototype_map()
? RuntimeCallCounterId::kPrototypeMap_TransitionToDataProperty
@ -9760,7 +9759,6 @@ Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
Map* maybe_transition =
TransitionsAccessor(map).SearchTransition(*name, kData, attributes);
if (maybe_transition != nullptr) {
*created_new_map = false;
Handle<Map> transition(maybe_transition);
int descriptor = transition->LastAdded();
@ -9771,7 +9769,6 @@ Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
return UpdateDescriptorForValue(transition, descriptor, constness, value);
}
*created_new_map = true;
TransitionFlag flag = INSERT_TRANSITION;
MaybeHandle<Map> maybe_map;
if (!FLAG_track_constant_fields && value->IsJSFunction()) {

View File

@ -681,10 +681,12 @@ class Map : public HeapObject {
// transitions to avoid an explosion in the number of maps for objects used as
// dictionaries.
inline bool TooManyFastProperties(StoreFromKeyed store_mode) const;
static Handle<Map> TransitionToDataProperty(
Handle<Map> map, Handle<Name> name, Handle<Object> value,
PropertyAttributes attributes, PropertyConstness constness,
StoreFromKeyed store_mode, bool* created_new_map);
static Handle<Map> TransitionToDataProperty(Handle<Map> map,
Handle<Name> name,
Handle<Object> value,
PropertyAttributes attributes,
PropertyConstness constness,
StoreFromKeyed store_mode);
static Handle<Map> TransitionToAccessorProperty(
Isolate* isolate, Handle<Map> map, Handle<Name> name, int descriptor,
Handle<Object> getter, Handle<Object> setter,

View File

@ -368,10 +368,9 @@ class Expectations {
heap_type);
Handle<String> name = MakeName("prop", property_index);
bool created_new_map;
return Map::TransitionToDataProperty(
map, name, value, attributes, constness,
Object::CERTAINLY_NOT_STORE_FROM_KEYED, &created_new_map);
Object::CERTAINLY_NOT_STORE_FROM_KEYED);
}
Handle<Map> TransitionToDataConstant(Handle<Map> map,
@ -382,10 +381,9 @@ class Expectations {
SetDataConstant(property_index, attributes, value);
Handle<String> name = MakeName("prop", property_index);
bool created_new_map;
return Map::TransitionToDataProperty(map, name, value, attributes, kConst,
Object::CERTAINLY_NOT_STORE_FROM_KEYED,
&created_new_map);
return Map::TransitionToDataProperty(
map, name, value, attributes, kConst,
Object::CERTAINLY_NOT_STORE_FROM_KEYED);
}
Handle<Map> FollowDataTransition(Handle<Map> map,