Chromium Code Reviews| Index: src/objects.cc |
| diff --git a/src/objects.cc b/src/objects.cc |
| index f39b760402e1f05a937dbaac7d278aa277ca2855..871e2bd4d8d76ac8a0b5e39e9a3bd88434e536e5 100644 |
| --- a/src/objects.cc |
| +++ b/src/objects.cc |
| @@ -28,6 +28,7 @@ |
| #include "v8.h" |
| #include "accessors.h" |
| +#include "allocation-site-scopes.h" |
| #include "api.h" |
| #include "arguments.h" |
| #include "bootstrapper.h" |
| @@ -5605,6 +5606,14 @@ MUST_USE_RESULT MaybeObject* JSObject::SetObserved(Isolate* isolate) { |
| } |
| +Handle<JSObject> JSObject::Copy(Handle<JSObject> object, |
| + Handle<AllocationSite> site) { |
| + Isolate* isolate = object->GetIsolate(); |
| + CALL_HEAP_FUNCTION(isolate, |
| + isolate->heap()->CopyJSObject(*object, *site), JSObject); |
| +} |
| + |
| + |
| Handle<JSObject> JSObject::Copy(Handle<JSObject> object) { |
| Isolate* isolate = object->GetIsolate(); |
| CALL_HEAP_FUNCTION(isolate, |
| @@ -5614,45 +5623,94 @@ Handle<JSObject> JSObject::Copy(Handle<JSObject> object) { |
| class JSObjectWalkVisitor { |
| public: |
| - explicit JSObjectWalkVisitor() {} |
| + explicit JSObjectWalkVisitor(AllocationSiteContext* site_context) : |
| + site_context_(site_context) {} |
| virtual ~JSObjectWalkVisitor() {} |
| Handle<JSObject> Visit(Handle<JSObject> object) { |
| return StructureWalk(object); |
| } |
| - // Returns true if the visitor is a copying visitor. |
| virtual bool is_copying() = 0; |
| protected: |
| Handle<JSObject> StructureWalk(Handle<JSObject> object); |
| - // The returned handle should point to a new object if the visitor is a |
| - // copying visitor, otherwise it should be the same as the input object. |
| + // The returned handle will be used for the object in all |
| + // subsequent usages. This allows VisitObject to make a copy |
| + // of the object if desired. |
|
Hannes Payer (out of office)
2013/10/15 13:53:20
take advantage of 80 chars
|
| virtual Handle<JSObject> VisitObject(Handle<JSObject> object) = 0; |
| - |
| - // The returned handle should point to a new value if the visitor is a |
| - // copying visitor, otherwise it should be the same as the input value. |
| virtual Handle<JSObject> VisitElementOrProperty(Handle<JSObject> object, |
| Handle<JSObject> value) = 0; |
| + |
| + AllocationSiteContext* site_context() { return site_context_; } |
| + |
| + private: |
| + AllocationSiteContext* site_context_; |
| }; |
| class JSObjectCopyVisitor: public JSObjectWalkVisitor { |
| public: |
| - explicit JSObjectCopyVisitor() {} |
| + explicit JSObjectCopyVisitor(AllocationSiteContext* site_context) |
| + : JSObjectWalkVisitor(site_context) {} |
| virtual bool is_copying() V8_OVERRIDE { return true; } |
| - protected: |
| + // The returned handle will be used for the object in all |
| + // subsequent usages. This allows VisitObject to make a copy |
| + // of the object if desired. |
| virtual Handle<JSObject> VisitObject(Handle<JSObject> object) V8_OVERRIDE { |
| - return JSObject::Copy(object); |
| + // Only create a memento if |
| + // 1) we have a JSArray, and |
| + // 2) the elements kind is palatable |
| + // 3) allow_mementos is true |
| + Handle<JSObject> copy; |
| + if (site_context()->activated() && |
| + AllocationSite::CanTrack(object->map()->instance_type()) && |
| + AllocationSite::GetMode(object->GetElementsKind()) == |
| + TRACK_ALLOCATION_SITE) { |
| + copy = JSObject::Copy(object, site_context()->current()); |
| + } else { |
| + copy = JSObject::Copy(object); |
| + } |
| + |
| + return copy; |
| } |
| virtual Handle<JSObject> VisitElementOrProperty( |
| Handle<JSObject> object, |
| Handle<JSObject> value) V8_OVERRIDE { |
| - return StructureWalk(value); |
| + Handle<AllocationSite> current_site = site_context()->EnterNewScope(); |
| + Handle<JSObject> copy_of_value = StructureWalk(value); |
| + site_context()->ExitScope(current_site, value); |
| + return copy_of_value; |
| + } |
| +}; |
| + |
| + |
| +class JSObjectCreateAllocationSitesVisitor: public JSObjectWalkVisitor { |
| + public: |
| + explicit JSObjectCreateAllocationSitesVisitor( |
| + AllocationSiteContext* site_context) |
| + : JSObjectWalkVisitor(site_context) {} |
| + |
| + virtual bool is_copying() V8_OVERRIDE { return false; } |
| + |
| + // The returned handle will be used for the object in all |
| + // subsequent usages. This allows VisitObject to make a copy |
| + // of the object if desired. |
| + virtual Handle<JSObject> VisitObject(Handle<JSObject> object) V8_OVERRIDE { |
| + return object; |
| + } |
| + |
| + virtual Handle<JSObject> VisitElementOrProperty( |
| + Handle<JSObject> object, |
| + Handle<JSObject> value) V8_OVERRIDE { |
| + Handle<AllocationSite> current_site = site_context()->EnterNewScope(); |
| + value = StructureWalk(value); |
| + site_context()->ExitScope(current_site, value); |
| + return value; |
| } |
| }; |
| @@ -5799,8 +5857,18 @@ Handle<JSObject> JSObjectWalkVisitor::StructureWalk(Handle<JSObject> object) { |
| } |
| -Handle<JSObject> JSObject::DeepCopy(Handle<JSObject> object) { |
| - JSObjectCopyVisitor v; |
| +Handle<JSObject> JSObject::DeepWalk(Handle<JSObject> object, |
| + AllocationSiteContext* site_context) { |
| + JSObjectCreateAllocationSitesVisitor v(site_context); |
| + Handle<JSObject> copy = v.Visit(object); |
| + ASSERT(!v.is_copying() && copy.is_identical_to(object)); |
| + return copy; |
| +} |
| + |
| + |
| +Handle<JSObject> JSObject::DeepCopy(Handle<JSObject> object, |
| + AllocationSiteContext* site_context) { |
| + JSObjectCopyVisitor v(site_context); |
| Handle<JSObject> copy = v.Visit(object); |
| ASSERT(v.is_copying() && !copy.is_identical_to(object)); |
| return copy; |
| @@ -12553,6 +12621,20 @@ void JSObject::TransitionElementsKind(Handle<JSObject> object, |
| } |
| +bool AllocationSite::IsNestedSite() { |
| + ASSERT(FLAG_trace_track_allocation_sites); |
| + Object* current = GetHeap()->allocation_sites_list(); |
| + while (current != NULL && current->IsAllocationSite()) { |
| + AllocationSite* current_site = AllocationSite::cast(current); |
| + if (current_site->nested_site() == this) { |
| + return true; |
| + } |
| + current = current_site->weak_next(); |
| + } |
| + return false; |
| +} |
| + |
| + |
| MaybeObject* JSObject::UpdateAllocationSite(ElementsKind to_kind) { |
| if (!FLAG_track_allocation_sites || !IsJSArray()) { |
| return this; |
| @@ -12565,7 +12647,8 @@ MaybeObject* JSObject::UpdateAllocationSite(ElementsKind to_kind) { |
| // Walk through to the Allocation Site |
| AllocationSite* site = memento->GetAllocationSite(); |
| - if (site->IsLiteralSite()) { |
| + if (site->SitePointsToLiteral() && |
| + site->transition_info()->IsJSArray()) { |
| JSArray* transition_info = JSArray::cast(site->transition_info()); |
| ElementsKind kind = transition_info->GetElementsKind(); |
| // if kind is holey ensure that to_kind is as well. |
| @@ -12579,9 +12662,11 @@ MaybeObject* JSObject::UpdateAllocationSite(ElementsKind to_kind) { |
| CHECK(transition_info->length()->ToArrayIndex(&length)); |
| if (length <= AllocationSite::kMaximumArrayBytesToPretransition) { |
| if (FLAG_trace_track_allocation_sites) { |
| + bool is_nested = site->IsNestedSite(); |
| PrintF( |
| - "AllocationSite: JSArray %p boilerplate updated %s->%s\n", |
| + "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n", |
| reinterpret_cast<void*>(this), |
| + is_nested ? "(nested)" : "", |
| ElementsKindToString(kind), |
| ElementsKindToString(to_kind)); |
| } |