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