Commit 307d2bdd authored by dcarney's avatar dcarney Committed by Commit bot

add transitions for global properties in ics

R=verwaest@chromium.org

BUG=

Review URL: https://codereview.chromium.org/911713003

Cr-Commit-Position: refs/heads/master@{#26569}
parent 85ed0097
...@@ -1676,6 +1676,19 @@ void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value, ...@@ -1676,6 +1676,19 @@ void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
} }
static Handle<Code> PropertyCellStoreHandler(
Isolate* isolate, Handle<JSObject> receiver, Handle<GlobalObject> holder,
Handle<Name> name, Handle<PropertyCell> cell, Handle<Object> value) {
auto union_type = PropertyCell::UpdatedType(cell, value);
StoreGlobalStub stub(isolate, union_type->IsConstant(),
receiver->IsJSGlobalProxy());
auto code = stub.GetCodeCopyFromTemplate(holder, cell);
// TODO(verwaest): Move caching of these NORMAL stubs outside as well.
HeapObject::UpdateMapCodeCache(receiver, name, code);
return code;
}
Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup, Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
Handle<Object> value, Handle<Object> value,
CacheHolderFlag cache_holder) { CacheHolderFlag cache_holder) {
...@@ -1688,6 +1701,13 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup, ...@@ -1688,6 +1701,13 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
switch (lookup->state()) { switch (lookup->state()) {
case LookupIterator::TRANSITION: { case LookupIterator::TRANSITION: {
auto store_target = lookup->GetStoreTarget();
if (store_target->IsGlobalObject()) {
auto cell = lookup->GetTransitionPropertyCell();
return PropertyCellStoreHandler(
isolate(), store_target, Handle<GlobalObject>::cast(store_target),
lookup->name(), cell, value);
}
Handle<Map> transition = lookup->transition_map(); Handle<Map> transition = lookup->transition_map();
// Currently not handled by CompileStoreTransition. // Currently not handled by CompileStoreTransition.
if (!holder->HasFastProperties()) { if (!holder->HasFastProperties()) {
...@@ -1754,17 +1774,12 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup, ...@@ -1754,17 +1774,12 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
case LookupIterator::DATA: { case LookupIterator::DATA: {
if (lookup->is_dictionary_holder()) { if (lookup->is_dictionary_holder()) {
if (holder->IsGlobalObject()) { if (holder->IsGlobalObject()) {
Handle<PropertyCell> cell = lookup->GetPropertyCell();
Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value);
DCHECK(holder.is_identical_to(receiver) || DCHECK(holder.is_identical_to(receiver) ||
receiver->map()->prototype() == *holder); receiver->map()->prototype() == *holder);
StoreGlobalStub stub(isolate(), union_type->IsConstant(), auto cell = lookup->GetPropertyCell();
receiver->IsJSGlobalProxy()); return PropertyCellStoreHandler(isolate(), receiver,
Handle<Code> code = stub.GetCodeCopyFromTemplate( Handle<GlobalObject>::cast(holder),
Handle<GlobalObject>::cast(holder), cell); lookup->name(), cell, value);
// TODO(verwaest): Move caching of these NORMAL stubs outside as well.
HeapObject::UpdateMapCodeCache(receiver, lookup->name(), code);
return code;
} }
DCHECK(holder.is_identical_to(receiver)); DCHECK(holder.is_identical_to(receiver));
return isolate()->builtins()->StoreIC_Normal(); return isolate()->builtins()->StoreIC_Normal();
......
...@@ -131,9 +131,22 @@ void LookupIterator::PrepareTransitionToDataProperty( ...@@ -131,9 +131,22 @@ void LookupIterator::PrepareTransitionToDataProperty(
return; return;
} }
transition_map_ = Map::TransitionToDataProperty( auto transition = Map::TransitionToDataProperty(
handle(receiver->map(), isolate_), name_, value, attributes, store_mode); handle(receiver->map(), isolate_), name_, value, attributes, store_mode);
state_ = TRANSITION; state_ = TRANSITION;
transition_ = transition;
if (receiver->IsGlobalObject()) {
// Install a property cell.
InternalizeName();
auto cell = GlobalObject::EnsurePropertyCell(
Handle<GlobalObject>::cast(receiver), name());
DCHECK(cell->value()->IsTheHole());
transition_ = cell;
} else if (transition->GetBackPointer()->IsMap()) {
property_details_ = transition->GetLastDescriptorDetails();
has_property_ = true;
}
} }
...@@ -141,8 +154,9 @@ void LookupIterator::ApplyTransitionToDataProperty() { ...@@ -141,8 +154,9 @@ void LookupIterator::ApplyTransitionToDataProperty() {
DCHECK_EQ(TRANSITION, state_); DCHECK_EQ(TRANSITION, state_);
Handle<JSObject> receiver = GetStoreTarget(); Handle<JSObject> receiver = GetStoreTarget();
if (receiver->IsGlobalObject()) return;
holder_ = receiver; holder_ = receiver;
holder_map_ = transition_map_; holder_map_ = transition_map();
JSObject::MigrateToMap(receiver, holder_map_); JSObject::MigrateToMap(receiver, holder_map_);
ReloadPropertyInformation(); ReloadPropertyInformation();
} }
......
...@@ -88,7 +88,7 @@ class LookupIterator FINAL BASE_EMBEDDED { ...@@ -88,7 +88,7 @@ class LookupIterator FINAL BASE_EMBEDDED {
bool is_dictionary_holder() const { return holder_map_->is_dictionary_map(); } bool is_dictionary_holder() const { return holder_map_->is_dictionary_map(); }
Handle<Map> transition_map() const { Handle<Map> transition_map() const {
DCHECK_EQ(TRANSITION, state_); DCHECK_EQ(TRANSITION, state_);
return transition_map_; return Handle<Map>::cast(transition_);
} }
template <class T> template <class T>
Handle<T> GetHolder() const { Handle<T> GetHolder() const {
...@@ -107,13 +107,9 @@ class LookupIterator FINAL BASE_EMBEDDED { ...@@ -107,13 +107,9 @@ class LookupIterator FINAL BASE_EMBEDDED {
PropertyAttributes attributes, PropertyAttributes attributes,
Object::StoreFromKeyed store_mode); Object::StoreFromKeyed store_mode);
bool IsCacheableTransition() { bool IsCacheableTransition() {
bool cacheable = if (state_ != TRANSITION) return false;
state_ == TRANSITION && transition_map()->GetBackPointer()->IsMap(); return transition_->IsPropertyCell() ||
if (cacheable) { transition_map()->GetBackPointer()->IsMap();
property_details_ = transition_map_->GetLastDescriptorDetails();
has_property_ = true;
}
return cacheable;
} }
void ApplyTransitionToDataProperty(); void ApplyTransitionToDataProperty();
void ReconfigureDataProperty(Handle<Object> value, void ReconfigureDataProperty(Handle<Object> value,
...@@ -135,6 +131,10 @@ class LookupIterator FINAL BASE_EMBEDDED { ...@@ -135,6 +131,10 @@ class LookupIterator FINAL BASE_EMBEDDED {
int GetAccessorIndex() const; int GetAccessorIndex() const;
int GetConstantIndex() const; int GetConstantIndex() const;
Handle<PropertyCell> GetPropertyCell() const; Handle<PropertyCell> GetPropertyCell() const;
Handle<PropertyCell> GetTransitionPropertyCell() const {
DCHECK_EQ(TRANSITION, state_);
return Handle<PropertyCell>::cast(transition_);
}
Handle<Object> GetAccessors() const; Handle<Object> GetAccessors() const;
Handle<Object> GetDataValue() const; Handle<Object> GetDataValue() const;
// Usually returns the value that was passed in, but may perform // Usually returns the value that was passed in, but may perform
...@@ -194,7 +194,7 @@ class LookupIterator FINAL BASE_EMBEDDED { ...@@ -194,7 +194,7 @@ class LookupIterator FINAL BASE_EMBEDDED {
Isolate* isolate_; Isolate* isolate_;
Handle<Name> name_; Handle<Name> name_;
Handle<Map> holder_map_; Handle<Map> holder_map_;
Handle<Map> transition_map_; Handle<Object> transition_;
Handle<Object> receiver_; Handle<Object> receiver_;
Handle<JSReceiver> holder_; Handle<JSReceiver> holder_;
......
...@@ -1752,9 +1752,7 @@ void JSObject::AddSlowProperty(Handle<JSObject> object, ...@@ -1752,9 +1752,7 @@ void JSObject::AddSlowProperty(Handle<JSObject> object,
dict->SetEntry(entry, name, cell, details); dict->SetEntry(entry, name, cell, details);
return; return;
} }
Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell(value); value = isolate->factory()->NewPropertyCell(value);
PropertyCell::SetValueInferType(cell, value);
value = cell;
} }
PropertyDetails details(attributes, DATA, 0); PropertyDetails details(attributes, DATA, 0);
Handle<NameDictionary> result = Handle<NameDictionary> result =
...@@ -3056,6 +3054,7 @@ MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it, ...@@ -3056,6 +3054,7 @@ MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it,
if (receiver->map()->is_dictionary_map()) { if (receiver->map()->is_dictionary_map()) {
// TODO(verwaest): Probably should ensure this is done beforehand. // TODO(verwaest): Probably should ensure this is done beforehand.
it->InternalizeName(); it->InternalizeName();
// TODO(dcarney): just populate TransitionPropertyCell here?
JSObject::AddSlowProperty(receiver, it->name(), value, attributes); JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
} else { } else {
// Write the property value. // Write the property value.
...@@ -15113,15 +15112,13 @@ void GlobalObject::InvalidatePropertyCell(Handle<GlobalObject> global, ...@@ -15113,15 +15112,13 @@ void GlobalObject::InvalidatePropertyCell(Handle<GlobalObject> global,
} }
Handle<PropertyCell> JSGlobalObject::EnsurePropertyCell( Handle<PropertyCell> GlobalObject::EnsurePropertyCell(
Handle<JSGlobalObject> global, Handle<GlobalObject> global, Handle<Name> name) {
Handle<Name> name) {
DCHECK(!global->HasFastProperties()); DCHECK(!global->HasFastProperties());
int entry = global->property_dictionary()->FindEntry(name); int entry = global->property_dictionary()->FindEntry(name);
if (entry == NameDictionary::kNotFound) { if (entry == NameDictionary::kNotFound) {
Isolate* isolate = global->GetIsolate(); Isolate* isolate = global->GetIsolate();
Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell( Handle<PropertyCell> cell = isolate->factory()->NewPropertyCellWithHole();
isolate->factory()->the_hole_value());
PropertyDetails details(NONE, DATA, 0); PropertyDetails details(NONE, DATA, 0);
details = details.AsDeleted(); details = details.AsDeleted();
Handle<NameDictionary> dictionary = NameDictionary::Add( Handle<NameDictionary> dictionary = NameDictionary::Add(
...@@ -16920,10 +16917,12 @@ Handle<Object> PropertyCell::SetValueInferType(Handle<PropertyCell> cell, ...@@ -16920,10 +16917,12 @@ Handle<Object> PropertyCell::SetValueInferType(Handle<PropertyCell> cell,
const int kMaxLengthForInternalization = 200; const int kMaxLengthForInternalization = 200;
if ((cell->type()->Is(HeapType::None()) || if ((cell->type()->Is(HeapType::None()) ||
cell->type()->Is(HeapType::Undefined())) && cell->type()->Is(HeapType::Undefined())) &&
value->IsString() && value->IsString()) {
Handle<String>::cast(value)->length() <= kMaxLengthForInternalization) { auto string = Handle<String>::cast(value);
value = cell->GetIsolate()->factory()->InternalizeString( if (string->length() <= kMaxLengthForInternalization &&
Handle<String>::cast(value)); !string->map()->is_undetectable()) {
value = cell->GetIsolate()->factory()->InternalizeString(string);
}
} }
cell->set_value(*value); cell->set_value(*value);
if (!HeapType::Any()->Is(cell->type())) { if (!HeapType::Any()->Is(cell->type())) {
......
...@@ -7643,6 +7643,9 @@ class GlobalObject: public JSObject { ...@@ -7643,6 +7643,9 @@ class GlobalObject: public JSObject {
static void InvalidatePropertyCell(Handle<GlobalObject> object, static void InvalidatePropertyCell(Handle<GlobalObject> object,
Handle<Name> name); Handle<Name> name);
// Ensure that the global object has a cell for the given property name.
static Handle<PropertyCell> EnsurePropertyCell(Handle<GlobalObject> global,
Handle<Name> name);
// Layout description. // Layout description.
static const int kBuiltinsOffset = JSObject::kHeaderSize; static const int kBuiltinsOffset = JSObject::kHeaderSize;
...@@ -7660,10 +7663,6 @@ class JSGlobalObject: public GlobalObject { ...@@ -7660,10 +7663,6 @@ class JSGlobalObject: public GlobalObject {
public: public:
DECLARE_CAST(JSGlobalObject) DECLARE_CAST(JSGlobalObject)
// Ensure that the global object has a cell for the given property name.
static Handle<PropertyCell> EnsurePropertyCell(Handle<JSGlobalObject> global,
Handle<Name> name);
inline bool IsDetached(); inline bool IsDetached();
// Dispatched behavior. // Dispatched behavior.
......
...@@ -407,6 +407,10 @@ TEST(HeapSnapshotSlicedString) { ...@@ -407,6 +407,10 @@ TEST(HeapSnapshotSlicedString) {
"parent_string = \"123456789.123456789.123456789.123456789.123456789." "parent_string = \"123456789.123456789.123456789.123456789.123456789."
"123456789.123456789.123456789.123456789.123456789." "123456789.123456789.123456789.123456789.123456789."
"123456789.123456789.123456789.123456789.123456789." "123456789.123456789.123456789.123456789.123456789."
"123456789.123456789.123456789.123456789.123456789."
"123456789.123456789.123456789.123456789.123456789."
"123456789.123456789.123456789.123456789.123456789."
"123456789.123456789.123456789.123456789.123456789."
"123456789.123456789.123456789.123456789.123456789.\";" "123456789.123456789.123456789.123456789.123456789.\";"
"child_string = parent_string.slice(100);"); "child_string = parent_string.slice(100);");
const v8::HeapSnapshot* snapshot = const v8::HeapSnapshot* snapshot =
......
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