From 307d2bdd8145b2aa1207ed846f49dfa6c90d93c4 Mon Sep 17 00:00:00 2001 From: dcarney Date: Wed, 11 Feb 2015 01:15:19 -0800 Subject: [PATCH] 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} --- src/ic/ic.cc | 33 ++++++++++++++++++++++++--------- src/lookup.cc | 18 ++++++++++++++++-- src/lookup.h | 18 +++++++++--------- src/objects.cc | 23 +++++++++++------------ src/objects.h | 7 +++---- test/cctest/test-heap-profiler.cc | 4 ++++ 6 files changed, 67 insertions(+), 36 deletions(-) diff --git a/src/ic/ic.cc b/src/ic/ic.cc index e8b2dbf..60e03b7 100644 --- a/src/ic/ic.cc +++ b/src/ic/ic.cc @@ -1676,6 +1676,19 @@ void StoreIC::UpdateCaches(LookupIterator* lookup, Handle value, } +static Handle PropertyCellStoreHandler( + Isolate* isolate, Handle receiver, Handle holder, + Handle name, Handle cell, Handle 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 StoreIC::CompileHandler(LookupIterator* lookup, Handle value, CacheHolderFlag cache_holder) { @@ -1688,6 +1701,13 @@ Handle 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::cast(store_target), + lookup->name(), cell, value); + } Handle transition = lookup->transition_map(); // Currently not handled by CompileStoreTransition. if (!holder->HasFastProperties()) { @@ -1754,17 +1774,12 @@ Handle StoreIC::CompileHandler(LookupIterator* lookup, case LookupIterator::DATA: { if (lookup->is_dictionary_holder()) { if (holder->IsGlobalObject()) { - Handle cell = lookup->GetPropertyCell(); - Handle 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 = stub.GetCodeCopyFromTemplate( - Handle::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::cast(holder), + lookup->name(), cell, value); } DCHECK(holder.is_identical_to(receiver)); return isolate()->builtins()->StoreIC_Normal(); diff --git a/src/lookup.cc b/src/lookup.cc index a2ae54d..22da70c 100644 --- a/src/lookup.cc +++ b/src/lookup.cc @@ -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::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 receiver = GetStoreTarget(); + if (receiver->IsGlobalObject()) return; holder_ = receiver; - holder_map_ = transition_map_; + holder_map_ = transition_map(); JSObject::MigrateToMap(receiver, holder_map_); ReloadPropertyInformation(); } diff --git a/src/lookup.h b/src/lookup.h index 01fa766..5a5466e 100644 --- a/src/lookup.h +++ b/src/lookup.h @@ -88,7 +88,7 @@ class LookupIterator FINAL BASE_EMBEDDED { bool is_dictionary_holder() const { return holder_map_->is_dictionary_map(); } Handle transition_map() const { DCHECK_EQ(TRANSITION, state_); - return transition_map_; + return Handle::cast(transition_); } template Handle 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 value, @@ -135,6 +131,10 @@ class LookupIterator FINAL BASE_EMBEDDED { int GetAccessorIndex() const; int GetConstantIndex() const; Handle GetPropertyCell() const; + Handle GetTransitionPropertyCell() const { + DCHECK_EQ(TRANSITION, state_); + return Handle::cast(transition_); + } Handle GetAccessors() const; Handle 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_; Handle holder_map_; - Handle transition_map_; + Handle transition_; Handle receiver_; Handle holder_; diff --git a/src/objects.cc b/src/objects.cc index 7e85e59..bc4fb1b 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -1752,9 +1752,7 @@ void JSObject::AddSlowProperty(Handle object, dict->SetEntry(entry, name, cell, details); return; } - Handle cell = isolate->factory()->NewPropertyCell(value); - PropertyCell::SetValueInferType(cell, value); - value = cell; + value = isolate->factory()->NewPropertyCell(value); } PropertyDetails details(attributes, DATA, 0); Handle result = @@ -3056,6 +3054,7 @@ MaybeHandle 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 global, } -Handle JSGlobalObject::EnsurePropertyCell( - Handle global, - Handle name) { +Handle GlobalObject::EnsurePropertyCell( + Handle global, Handle name) { DCHECK(!global->HasFastProperties()); int entry = global->property_dictionary()->FindEntry(name); if (entry == NameDictionary::kNotFound) { Isolate* isolate = global->GetIsolate(); - Handle cell = isolate->factory()->NewPropertyCell( - isolate->factory()->the_hole_value()); + Handle cell = isolate->factory()->NewPropertyCellWithHole(); PropertyDetails details(NONE, DATA, 0); details = details.AsDeleted(); Handle dictionary = NameDictionary::Add( @@ -16920,10 +16917,12 @@ Handle PropertyCell::SetValueInferType(Handle cell, const int kMaxLengthForInternalization = 200; if ((cell->type()->Is(HeapType::None()) || cell->type()->Is(HeapType::Undefined())) && - value->IsString() && - Handle::cast(value)->length() <= kMaxLengthForInternalization) { - value = cell->GetIsolate()->factory()->InternalizeString( - Handle::cast(value)); + value->IsString()) { + auto string = Handle::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())) { diff --git a/src/objects.h b/src/objects.h index ef8416a..5fa64cb 100644 --- a/src/objects.h +++ b/src/objects.h @@ -7643,6 +7643,9 @@ class GlobalObject: public JSObject { static void InvalidatePropertyCell(Handle object, Handle name); + // Ensure that the global object has a cell for the given property name. + static Handle EnsurePropertyCell(Handle global, + Handle 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 EnsurePropertyCell(Handle global, - Handle name); - inline bool IsDetached(); // Dispatched behavior. diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc index 815d27d..5c9d2e6 100644 --- a/test/cctest/test-heap-profiler.cc +++ b/test/cctest/test-heap-profiler.cc @@ -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 = -- 2.7.4