[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:
parent
1f7d80cd97
commit
d1532a1aef
14
src/ic/ic.cc
14
src/ic/ic.cc
@ -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'");
|
||||
|
@ -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 {
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
|
@ -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()) {
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user