From f4edc076d8d763169e3416cdba1fa8edfe8b6a1e Mon Sep 17 00:00:00 2001 From: "mvstanton@chromium.org" Date: Tue, 15 Oct 2013 15:35:23 +0000 Subject: [PATCH] Revert "AllocationSites for all literals" This reverts commit r17219 due to WebKit failures. R=mstarzinger@chromium.org TBR=mstarzinger@chromium.org Review URL: https://codereview.chromium.org/26539010 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17222 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/allocation-site-scopes.cc | 108 ------------------------- src/allocation-site-scopes.h | 115 --------------------------- src/flag-definitions.h | 3 - src/hydrogen.cc | 80 ++++++------------- src/hydrogen.h | 12 +-- src/objects.cc | 114 ++++---------------------- src/objects.h | 25 ++---- src/runtime.cc | 57 +++++-------- test/mjsunit/allocation-site-info.js | 110 ------------------------- tools/gyp/v8.gyp | 2 - 10 files changed, 72 insertions(+), 554 deletions(-) delete mode 100644 src/allocation-site-scopes.cc delete mode 100644 src/allocation-site-scopes.h diff --git a/src/allocation-site-scopes.cc b/src/allocation-site-scopes.cc deleted file mode 100644 index 1ca32eb862..0000000000 --- a/src/allocation-site-scopes.cc +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2013 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "allocation-site-scopes.h" - -namespace v8 { -namespace internal { - - -Handle AllocationSiteCreationContext::EnterNewScope() { - Handle scope_site; - if (top().is_null()) { - // We are creating the top level AllocationSite as opposed to a nested - // AllocationSite. - InitializeTraversal(isolate()->factory()->NewAllocationSite()); - scope_site = Handle(*top(), isolate()); - if (FLAG_trace_creation_allocation_sites) { - PrintF("*** Creating top level AllocationSite %p\n", - static_cast(*scope_site)); - } - } else { - ASSERT(!current().is_null()); - scope_site = isolate()->factory()->NewAllocationSite(); - if (FLAG_trace_creation_allocation_sites) { - PrintF("Creating nested site (top, current, new) (%p, %p, %p)\n", - static_cast(*top()), - static_cast(*current()), - static_cast(*scope_site)); - } - current()->set_nested_site(*scope_site); - update_current_site(*scope_site); - } - ASSERT(!scope_site.is_null()); - return scope_site; -} - - -void AllocationSiteCreationContext::ExitScope( - Handle scope_site, - Handle object) { - if (!object.is_null() && !object->IsFailure()) { - bool top_level = !scope_site.is_null() && - top().is_identical_to(scope_site); - - scope_site->set_transition_info(*object); - if (FLAG_trace_creation_allocation_sites) { - if (top_level) { - PrintF("*** Setting AllocationSite %p transition_info %p\n", - static_cast(*scope_site), - static_cast(*object)); - } else { - PrintF("Setting AllocationSite (%p, %p) transition_info %p\n", - static_cast(*top()), - static_cast(*scope_site), - static_cast(*object)); - } - } - } -} - - -Handle AllocationSiteUsageContext::EnterNewScope() { - if (top().is_null()) { - InitializeTraversal(top_site_); - } else { - // Advance current site - Object* nested_site = current()->nested_site(); - // Something is wrong if we advance to the end of the list here. - ASSERT(nested_site->IsAllocationSite()); - update_current_site(AllocationSite::cast(nested_site)); - } - return Handle(*current(), isolate()); -} - - -void AllocationSiteUsageContext::ExitScope( - Handle scope_site, - Handle object) { - // This assert ensures that we are pointing at the right sub-object in a - // recursive walk of a nested literal. - ASSERT(*object == scope_site->transition_info()); -} - -} } // namespace v8::internal diff --git a/src/allocation-site-scopes.h b/src/allocation-site-scopes.h deleted file mode 100644 index 1c3afdf369..0000000000 --- a/src/allocation-site-scopes.h +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2013 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef V8_ALLOCATION_SITE_SCOPES_H_ -#define V8_ALLOCATION_SITE_SCOPES_H_ - -#include "ast.h" -#include "handles.h" -#include "objects.h" -#include "zone.h" - -namespace v8 { -namespace internal { - - -// AllocationSiteContext is the base class for walking and copying a nested -// boilerplate with AllocationSite and AllocationMemento support. -class AllocationSiteContext { - public: - AllocationSiteContext(Isolate* isolate, bool activated) { - isolate_ = isolate; - activated_ = activated; - }; - virtual ~AllocationSiteContext() {} - - Handle top() { return top_; } - Handle current() { return current_; } - - // If activated, then recursively create mementos - bool activated() const { return activated_; } - - // Returns the AllocationSite that matches this scope. - virtual Handle EnterNewScope() = 0; - - // scope_site should be the handle returned by the matching EnterNewScope() - virtual void ExitScope(Handle scope_site, - Handle object) = 0; - - protected: - void update_current_site(AllocationSite* site) { - *(current_.location()) = site; - } - - Isolate* isolate() { return isolate_; } - void InitializeTraversal(Handle site) { - top_ = site; - current_ = Handle(*top_, isolate()); - } - - private: - Isolate* isolate_; - Handle top_; - Handle current_; - bool activated_; -}; - - -// AllocationSiteCreationContext aids in the creation of AllocationSites to -// accompany object literals. -class AllocationSiteCreationContext : public AllocationSiteContext { - public: - explicit AllocationSiteCreationContext(Isolate* isolate) - : AllocationSiteContext(isolate, true) { } - - virtual Handle EnterNewScope() V8_OVERRIDE; - virtual void ExitScope(Handle site, - Handle object) V8_OVERRIDE; -}; - - -// AllocationSiteUsageContext aids in the creation of AllocationMementos placed -// behind some/all components of a copied object literal. -class AllocationSiteUsageContext : public AllocationSiteContext { - public: - AllocationSiteUsageContext(Isolate* isolate, Handle site, - bool activated) - : AllocationSiteContext(isolate, activated), - top_site_(site) { } - - virtual Handle EnterNewScope() V8_OVERRIDE; - virtual void ExitScope(Handle site, - Handle object) V8_OVERRIDE; - - private: - Handle top_site_; -}; - - -} } // namespace v8::internal - -#endif // V8_ALLOCATION_SITE_SCOPES_H_ diff --git a/src/flag-definitions.h b/src/flag-definitions.h index cc317e58d6..63cf4a6aef 100644 --- a/src/flag-definitions.h +++ b/src/flag-definitions.h @@ -806,9 +806,6 @@ DEFINE_implication(log_internal_timer_events, prof) // elements.cc DEFINE_bool(trace_elements_transitions, false, "trace elements transitions") -DEFINE_bool(trace_creation_allocation_sites, false, - "trace the creation of allocation sites") - // code-stubs.cc DEFINE_bool(print_code_stubs, false, "print code stubs") DEFINE_bool(test_secondary_stub_cache, diff --git a/src/hydrogen.cc b/src/hydrogen.cc index b5e3a05de8..a41be5e6b4 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -30,7 +30,6 @@ #include #include "v8.h" -#include "allocation-site-scopes.h" #include "codegen.h" #include "full-codegen.h" #include "hashmap.h" @@ -4299,10 +4298,7 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { if (!boilerplate.is_null() && IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) { - AllocationSiteUsageContext usage_context(isolate(), site, false); - usage_context.EnterNewScope(); - literal = BuildFastLiteral(boilerplate, &usage_context); - usage_context.ExitScope(site, boilerplate); + literal = BuildFastLiteral(boilerplate); } else { NoObservableSideEffectsScope no_effects(this); Handle closure_literals(closure->literals(), isolate()); @@ -4318,9 +4314,6 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { Add(Add(constant_properties)); Add(Add(flags)); - // TODO(mvstanton): Add a flag to turn off creation of any - // AllocationMementos for this call: we are in crankshaft and should have - // learned enough about transition behavior to stop emitting mementos. Runtime::FunctionId function_id = Runtime::kCreateObjectLiteral; literal = Add(isolate()->factory()->empty_string(), Runtime::FunctionForId(function_id), @@ -4411,48 +4404,45 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { bool uninitialized = false; Handle literals_cell(literals->get(expr->literal_index()), isolate()); - Handle boilerplate_object; + Handle raw_boilerplate; if (literals_cell->IsUndefined()) { uninitialized = true; - Handle raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate( + raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate( isolate(), literals, expr->constant_elements()); if (raw_boilerplate.is_null()) { return Bailout(kArrayBoilerplateCreationFailed); } - boilerplate_object = Handle::cast(raw_boilerplate); - AllocationSiteCreationContext creation_context(isolate()); - site = creation_context.EnterNewScope(); - JSObject::DeepWalk(boilerplate_object, &creation_context); - creation_context.ExitScope(site, boilerplate_object); + site = isolate()->factory()->NewAllocationSite(); + site->set_transition_info(*raw_boilerplate); literals->set(expr->literal_index(), *site); - if (boilerplate_object->elements()->map() == + if (JSObject::cast(*raw_boilerplate)->elements()->map() == isolate()->heap()->fixed_cow_array_map()) { isolate()->counters()->cow_arrays_created_runtime()->Increment(); } } else { ASSERT(literals_cell->IsAllocationSite()); site = Handle::cast(literals_cell); - boilerplate_object = Handle( - JSObject::cast(site->transition_info()), isolate()); + raw_boilerplate = Handle(site->transition_info(), isolate()); } - ASSERT(!boilerplate_object.is_null()); - ASSERT(site->SitePointsToLiteral()); + ASSERT(!raw_boilerplate.is_null()); + ASSERT(site->IsLiteralSite()); + Handle boilerplate_object = + Handle::cast(raw_boilerplate); ElementsKind boilerplate_elements_kind = - boilerplate_object->GetElementsKind(); + Handle::cast(boilerplate_object)->GetElementsKind(); + + ASSERT(AllocationSite::CanTrack(boilerplate_object->map()->instance_type())); // Check whether to use fast or slow deep-copying for boilerplate. int max_properties = kMaxFastLiteralProperties; if (IsFastLiteral(boilerplate_object, kMaxFastLiteralDepth, &max_properties)) { - AllocationSiteUsageContext usage_context(isolate(), site, false); - usage_context.EnterNewScope(); - literal = BuildFastLiteral(boilerplate_object, &usage_context); - usage_context.ExitScope(site, boilerplate_object); + literal = BuildFastLiteral(boilerplate_object); } else { NoObservableSideEffectsScope no_effects(this); // Boilerplate already exists and constant elements are never accessed, @@ -4464,9 +4454,6 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { Add(Add(literal_index)); Add(Add(constants)); - // TODO(mvstanton): Consider a flag to turn off creation of any - // AllocationMementos for this call: we are in crankshaft and should have - // learned enough about transition behavior to stop emitting mementos. Runtime::FunctionId function_id = (expr->depth() > 1) ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; literal = Add(isolate()->factory()->empty_string(), @@ -8355,8 +8342,7 @@ HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( - Handle boilerplate_object, - AllocationSiteContext* site_context) { + Handle boilerplate_object) { NoObservableSideEffectsScope no_effects(this); InstanceType instance_type = boilerplate_object->map()->instance_type(); ASSERT(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE); @@ -8388,15 +8374,15 @@ HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( } BuildInitElementsInObjectHeader(boilerplate_object, object, object_elements); + // Copy object elements if non-COW. if (object_elements != NULL) { - BuildEmitElements(boilerplate_object, elements, object_elements, - site_context); + BuildEmitElements(boilerplate_object, elements, object_elements); } // Copy in-object properties. if (boilerplate_object->map()->NumberOfFields() != 0) { - BuildEmitInObjectProperties(boilerplate_object, object, site_context); + BuildEmitInObjectProperties(boilerplate_object, object); } return object; } @@ -8448,8 +8434,7 @@ void HOptimizedGraphBuilder::BuildInitElementsInObjectHeader( void HOptimizedGraphBuilder::BuildEmitInObjectProperties( Handle boilerplate_object, - HInstruction* object, - AllocationSiteContext* site_context) { + HInstruction* object) { Handle descriptors( boilerplate_object->map()->instance_descriptors()); int limit = boilerplate_object->map()->NumberOfOwnDescriptors(); @@ -8473,10 +8458,7 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties( if (value->IsJSObject()) { Handle value_object = Handle::cast(value); - Handle current_site = site_context->EnterNewScope(); - HInstruction* result = - BuildFastLiteral(value_object, site_context); - site_context->ExitScope(current_site, value_object); + HInstruction* result = BuildFastLiteral(value_object); Add(object, access, result); } else { Representation representation = details.representation(); @@ -8485,12 +8467,6 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties( if (representation.IsDouble()) { // Allocate a HeapNumber box and store the value into it. HValue* heap_number_constant = Add(HeapNumber::kSize); - // TODO(mvstanton): This heap number alloc does not have a corresponding - // AllocationSite. That is okay because - // 1) it's a child object of another object with a valid allocation site - // 2) we can just use the mode of the parent object for pretenuring - // The todo is replace GetPretenureMode() with - // site_context->top()->GetPretenureMode(). HInstruction* double_box = Add(heap_number_constant, HType::HeapNumber(), isolate()->heap()->GetPretenureMode(), HEAP_NUMBER_TYPE); @@ -8520,8 +8496,7 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties( void HOptimizedGraphBuilder::BuildEmitElements( Handle boilerplate_object, Handle elements, - HValue* object_elements, - AllocationSiteContext* site_context) { + HValue* object_elements) { ElementsKind kind = boilerplate_object->map()->elements_kind(); int elements_length = elements->length(); HValue* object_elements_length = Add(elements_length); @@ -8531,8 +8506,7 @@ void HOptimizedGraphBuilder::BuildEmitElements( if (elements->IsFixedDoubleArray()) { BuildEmitFixedDoubleArray(elements, kind, object_elements); } else if (elements->IsFixedArray()) { - BuildEmitFixedArray(elements, kind, object_elements, - site_context); + BuildEmitFixedArray(elements, kind, object_elements); } else { UNREACHABLE(); } @@ -8561,8 +8535,7 @@ void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray( void HOptimizedGraphBuilder::BuildEmitFixedArray( Handle elements, ElementsKind kind, - HValue* object_elements, - AllocationSiteContext* site_context) { + HValue* object_elements) { HInstruction* boilerplate_elements = Add(elements); int elements_length = elements->length(); Handle fast_elements = Handle::cast(elements); @@ -8571,10 +8544,7 @@ void HOptimizedGraphBuilder::BuildEmitFixedArray( HValue* key_constant = Add(i); if (value->IsJSObject()) { Handle value_object = Handle::cast(value); - Handle current_site = site_context->EnterNewScope(); - HInstruction* result = - BuildFastLiteral(value_object, site_context); - site_context->ExitScope(current_site, value_object); + HInstruction* result = BuildFastLiteral(value_object); Add(object_elements, key_constant, result, kind); } else { HInstruction* value_instruction = diff --git a/src/hydrogen.h b/src/hydrogen.h index bd28ba1b74..01f72869c3 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -2248,8 +2248,7 @@ class HOptimizedGraphBuilder V8_FINAL HInstruction* BuildThisFunction(); - HInstruction* BuildFastLiteral(Handle boilerplate_object, - AllocationSiteContext* site_context); + HInstruction* BuildFastLiteral(Handle boilerplate_object); void BuildEmitObjectHeader(Handle boilerplate_object, HInstruction* object); @@ -2259,13 +2258,11 @@ class HOptimizedGraphBuilder V8_FINAL HInstruction* object_elements); void BuildEmitInObjectProperties(Handle boilerplate_object, - HInstruction* object, - AllocationSiteContext* site_context); + HInstruction* object); void BuildEmitElements(Handle boilerplate_object, Handle elements, - HValue* object_elements, - AllocationSiteContext* site_context); + HValue* object_elements); void BuildEmitFixedDoubleArray(Handle elements, ElementsKind kind, @@ -2273,8 +2270,7 @@ class HOptimizedGraphBuilder V8_FINAL void BuildEmitFixedArray(Handle elements, ElementsKind kind, - HValue* object_elements, - AllocationSiteContext* site_context); + HValue* object_elements); void AddCheckPrototypeMaps(Handle holder, Handle receiver_map); diff --git a/src/objects.cc b/src/objects.cc index 0a8f57b9e2..26cb3c53dc 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -28,7 +28,6 @@ #include "v8.h" #include "accessors.h" -#include "allocation-site-scopes.h" #include "api.h" #include "arguments.h" #include "bootstrapper.h" @@ -5616,14 +5615,6 @@ MUST_USE_RESULT MaybeObject* JSObject::SetObserved(Isolate* isolate) { } -Handle JSObject::Copy(Handle object, - Handle site) { - Isolate* isolate = object->GetIsolate(); - CALL_HEAP_FUNCTION(isolate, - isolate->heap()->CopyJSObject(*object, *site), JSObject); -} - - Handle JSObject::Copy(Handle object) { Isolate* isolate = object->GetIsolate(); CALL_HEAP_FUNCTION(isolate, @@ -5633,93 +5624,45 @@ Handle JSObject::Copy(Handle object) { class JSObjectWalkVisitor { public: - explicit JSObjectWalkVisitor(AllocationSiteContext* site_context) : - site_context_(site_context) {} + explicit JSObjectWalkVisitor() {} virtual ~JSObjectWalkVisitor() {} Handle Visit(Handle object) { return StructureWalk(object); } + // Returns true if the visitor is a copying visitor. virtual bool is_copying() = 0; protected: Handle StructureWalk(Handle 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. + // 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. virtual Handle VisitObject(Handle 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 VisitElementOrProperty(Handle object, Handle value) = 0; - - AllocationSiteContext* site_context() { return site_context_; } - - private: - AllocationSiteContext* site_context_; }; class JSObjectCopyVisitor: public JSObjectWalkVisitor { public: - explicit JSObjectCopyVisitor(AllocationSiteContext* site_context) - : JSObjectWalkVisitor(site_context) {} + explicit JSObjectCopyVisitor() {} virtual bool is_copying() V8_OVERRIDE { return true; } - // 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. + protected: virtual Handle VisitObject(Handle object) V8_OVERRIDE { - // Only create a memento if - // 1) we have a JSArray, and - // 2) the elements kind is palatable - // 3) allow_mementos is true - Handle 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; + return JSObject::Copy(object); } virtual Handle VisitElementOrProperty( Handle object, Handle value) V8_OVERRIDE { - Handle current_site = site_context()->EnterNewScope(); - Handle 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 VisitObject(Handle object) V8_OVERRIDE { - return object; - } - - virtual Handle VisitElementOrProperty( - Handle object, - Handle value) V8_OVERRIDE { - Handle current_site = site_context()->EnterNewScope(); - value = StructureWalk(value); - site_context()->ExitScope(current_site, value); - return value; + return StructureWalk(value); } }; @@ -5866,18 +5809,8 @@ Handle JSObjectWalkVisitor::StructureWalk(Handle object) { } -Handle JSObject::DeepWalk(Handle object, - AllocationSiteContext* site_context) { - JSObjectCreateAllocationSitesVisitor v(site_context); - Handle copy = v.Visit(object); - ASSERT(!v.is_copying() && copy.is_identical_to(object)); - return copy; -} - - -Handle JSObject::DeepCopy(Handle object, - AllocationSiteContext* site_context) { - JSObjectCopyVisitor v(site_context); +Handle JSObject::DeepCopy(Handle object) { + JSObjectCopyVisitor v; Handle copy = v.Visit(object); ASSERT(v.is_copying() && !copy.is_identical_to(object)); return copy; @@ -12640,20 +12573,6 @@ void JSObject::TransitionElementsKind(Handle 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; @@ -12666,8 +12585,7 @@ MaybeObject* JSObject::UpdateAllocationSite(ElementsKind to_kind) { // Walk through to the Allocation Site AllocationSite* site = memento->GetAllocationSite(); - if (site->SitePointsToLiteral() && - site->transition_info()->IsJSArray()) { + if (site->IsLiteralSite()) { JSArray* transition_info = JSArray::cast(site->transition_info()); ElementsKind kind = transition_info->GetElementsKind(); // if kind is holey ensure that to_kind is as well. @@ -12681,11 +12599,9 @@ 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 %s updated %s->%s\n", + "AllocationSite: JSArray %p boilerplate updated %s->%s\n", reinterpret_cast(this), - is_nested ? "(nested)" : "", ElementsKindToString(kind), ElementsKindToString(to_kind)); } diff --git a/src/objects.h b/src/objects.h index 50c739cb9e..2925c54f18 100644 --- a/src/objects.h +++ b/src/objects.h @@ -865,9 +865,8 @@ enum CompareResult { inline void set_##name(type* value, \ WriteBarrierMode mode = UPDATE_WRITE_BARRIER); \ + class AccessorPair; -class AllocationSite; -class AllocationSiteContext; class DictionaryElementsAccessor; class ElementsAccessor; class Failure; @@ -2545,13 +2544,8 @@ class JSObject: public JSReceiver { MUST_USE_RESULT MaybeObject* SetObserved(Isolate* isolate); // Copy object. - static Handle Copy(Handle object, - Handle site); static Handle Copy(Handle object); - static Handle DeepCopy(Handle object, - AllocationSiteContext* site_context); - static Handle DeepWalk(Handle object, - AllocationSiteContext* site_context); + static Handle DeepCopy(Handle object); // Casting. static inline JSObject* cast(Object* obj); @@ -8011,15 +8005,8 @@ class AllocationSite: public Struct { inline void Initialize(); - bool HasNestedSites() { - return nested_site()->IsAllocationSite(); - } - - // This method is expensive, it should only be called for reporting. - bool IsNestedSite(); - ElementsKind GetElementsKind() { - ASSERT(!SitePointsToLiteral()); + ASSERT(!IsLiteralSite()); return static_cast(Smi::cast(transition_info())->value()); } @@ -8027,11 +8014,11 @@ class AllocationSite: public Struct { set_transition_info(Smi::FromInt(static_cast(kind))); } - bool SitePointsToLiteral() { + bool IsLiteralSite() { // If transition_info is a smi, then it represents an ElementsKind // for a constructed array. Otherwise, it must be a boilerplate - // for an object or array literal. - return transition_info()->IsJSArray() || transition_info()->IsJSObject(); + // for an array literal + return transition_info()->IsJSArray(); } DECLARE_PRINTER(AllocationSite) diff --git a/src/runtime.cc b/src/runtime.cc index fe4d089d79..be0281b846 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -31,7 +31,6 @@ #include "v8.h" #include "accessors.h" -#include "allocation-site-scopes.h" #include "api.h" #include "arguments.h" #include "bootstrapper.h" @@ -489,34 +488,25 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteral) { // Check if boilerplate exists. If not, create it first. Handle literal_site(literals->get(literals_index), isolate); Handle site; - Handle boilerplate; + Handle boilerplate; if (*literal_site == isolate->heap()->undefined_value()) { - Handle raw_boilerplate = CreateObjectLiteralBoilerplate( - isolate, - literals, - constant_properties, - should_have_fast_elements, - has_function_literal); - RETURN_IF_EMPTY_HANDLE(isolate, raw_boilerplate); - boilerplate = Handle::cast(raw_boilerplate); - - AllocationSiteCreationContext creation_context(isolate); - site = creation_context.EnterNewScope(); - JSObject::DeepWalk(boilerplate, &creation_context); - creation_context.ExitScope(site, boilerplate); + boilerplate = CreateObjectLiteralBoilerplate(isolate, + literals, + constant_properties, + should_have_fast_elements, + has_function_literal); + RETURN_IF_EMPTY_HANDLE(isolate, boilerplate); + site = isolate->factory()->NewAllocationSite(); + site->set_transition_info(*boilerplate); // Update the functions literal and return the boilerplate. literals->set(literals_index, *site); } else { site = Handle::cast(literal_site); - boilerplate = Handle(JSObject::cast(site->transition_info()), - isolate); + boilerplate = Handle(JSObject::cast(site->transition_info())); } - AllocationSiteUsageContext usage_context(isolate, site, true); - usage_context.EnterNewScope(); - Handle copy = JSObject::DeepCopy(boilerplate, &usage_context); - usage_context.ExitScope(site, boilerplate); + Handle copy = JSObject::DeepCopy(Handle::cast(boilerplate)); RETURN_IF_EMPTY_HANDLE(isolate, copy); return *copy; } @@ -534,13 +524,12 @@ static Handle GetLiteralAllocationSite( ASSERT(*elements != isolate->heap()->empty_fixed_array()); Handle boilerplate = Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements); - if (boilerplate.is_null()) return Handle::null(); - - AllocationSiteCreationContext creation_context(isolate); - site = creation_context.EnterNewScope(); - JSObject::DeepWalk(Handle::cast(boilerplate), &creation_context); - creation_context.ExitScope(site, Handle::cast(boilerplate)); - + if (boilerplate.is_null()) { + ASSERT(site.is_null()); + return site; + } + site = isolate->factory()->NewAllocationSite(); + site->set_transition_info(*boilerplate); literals->set(literals_index, *site); } else { site = Handle::cast(literal_site); @@ -562,10 +551,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteral) { RETURN_IF_EMPTY_HANDLE(isolate, site); Handle boilerplate(JSObject::cast(site->transition_info())); - AllocationSiteUsageContext usage_context(isolate, site, true); - usage_context.EnterNewScope(); - Handle copy = JSObject::DeepCopy(boilerplate, &usage_context); - usage_context.ExitScope(site, boilerplate); + Handle copy = JSObject::DeepCopy(boilerplate); RETURN_IF_EMPTY_HANDLE(isolate, copy); return *copy; } @@ -588,8 +574,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralShallow) { isolate->counters()->cow_arrays_created_runtime()->Increment(); } - if (AllocationSite::GetMode(boilerplate->GetElementsKind()) == - TRACK_ALLOCATION_SITE) { + AllocationSiteMode mode = AllocationSite::GetMode( + boilerplate->GetElementsKind()); + if (mode == TRACK_ALLOCATION_SITE) { return isolate->heap()->CopyJSObject(boilerplate, *site); } @@ -14698,7 +14685,7 @@ static MaybeObject* ArrayConstructorCommon(Isolate* isolate, Handle cell = Handle::cast(type_info); Handle site = Handle( AllocationSite::cast(cell->value()), isolate); - ASSERT(!site->SitePointsToLiteral()); + ASSERT(!site->IsLiteralSite()); ElementsKind to_kind = site->GetElementsKind(); if (holey && !IsFastHoleyElementsKind(to_kind)) { to_kind = GetHoleyElementsKind(to_kind); diff --git a/test/mjsunit/allocation-site-info.js b/test/mjsunit/allocation-site-info.js index 626696be15..9b1f4bd355 100644 --- a/test/mjsunit/allocation-site-info.js +++ b/test/mjsunit/allocation-site-info.js @@ -383,114 +383,4 @@ if (support_smi_only_arrays) { instanceof_check(realmBArray); assertUnoptimized(instanceof_check); - - // Case: make sure nested arrays benefit from allocation site feedback as - // well. - (function() { - // Make sure we handle nested arrays - function get_nested_literal() { - var literal = [[1,2,3,4], [2], [3]]; - return literal; - } - - obj = get_nested_literal(); - assertKind(elements_kind.fast, obj); - obj[0][0] = 3.5; - obj[2][0] = "hello"; - obj = get_nested_literal(); - assertKind(elements_kind.fast_double, obj[0]); - assertKind(elements_kind.fast_smi_only, obj[1]); - assertKind(elements_kind.fast, obj[2]); - - // A more complex nested literal case. - function get_deep_nested_literal() { - var literal = [[1], [[2], "hello"], 3, [4]]; - return literal; - } - - obj = get_deep_nested_literal(); - assertKind(elements_kind.fast_smi_only, obj[1][0]); - obj[0][0] = 3.5; - obj[1][0][0] = "goodbye"; - assertKind(elements_kind.fast_double, obj[0]); - assertKind(elements_kind.fast, obj[1][0]); - - obj = get_deep_nested_literal(); - assertKind(elements_kind.fast_double, obj[0]); - assertKind(elements_kind.fast, obj[1][0]); - })(); - - - // Make sure object literals with array fields benefit from the type feedback - // that allocation mementos provide. - (function() { - // A literal in an object - function get_object_literal() { - var literal = { - array: [1,2,3], - data: 3.5 - }; - return literal; - } - - obj = get_object_literal(); - assertKind(elements_kind.fast_smi_only, obj.array); - obj.array[1] = 3.5; - assertKind(elements_kind.fast_double, obj.array); - obj = get_object_literal(); - assertKind(elements_kind.fast_double, obj.array); - - function get_nested_object_literal() { - var literal = { - array: [[1],[2],[3]], - data: 3.5 - }; - return literal; - } - - obj = get_nested_object_literal(); - assertKind(elements_kind.fast, obj.array); - assertKind(elements_kind.fast_smi_only, obj.array[1]); - obj.array[1][0] = 3.5; - assertKind(elements_kind.fast_double, obj.array[1]); - obj = get_nested_object_literal(); - assertKind(elements_kind.fast_double, obj.array[1]); - - %OptimizeFunctionOnNextCall(get_nested_object_literal); - get_nested_object_literal(); - obj = get_nested_object_literal(); - assertKind(elements_kind.fast_double, obj.array[1]); - - // Make sure we handle nested arrays - function get_nested_literal() { - var literal = [[1,2,3,4], [2], [3]]; - return literal; - } - - obj = get_nested_literal(); - assertKind(elements_kind.fast, obj); - obj[0][0] = 3.5; - obj[2][0] = "hello"; - obj = get_nested_literal(); - assertKind(elements_kind.fast_double, obj[0]); - assertKind(elements_kind.fast_smi_only, obj[1]); - assertKind(elements_kind.fast, obj[2]); - - // A more complex nested literal case. - function get_deep_nested_literal() { - var literal = [[1], [[2], "hello"], 3, [4]]; - return literal; - } - - obj = get_deep_nested_literal(); - assertKind(elements_kind.fast_smi_only, obj[1][0]); - obj[0][0] = 3.5; - obj[1][0][0] = "goodbye"; - assertKind(elements_kind.fast_double, obj[0]); - assertKind(elements_kind.fast, obj[1][0]); - - obj = get_deep_nested_literal(); - assertKind(elements_kind.fast_double, obj[0]); - assertKind(elements_kind.fast, obj[1][0]); - })(); } diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp index 94b9bc00d0..5bda0cd900 100644 --- a/tools/gyp/v8.gyp +++ b/tools/gyp/v8.gyp @@ -209,8 +209,6 @@ '../../src/accessors.h', '../../src/allocation.cc', '../../src/allocation.h', - '../../src/allocation-site-scopes.cc', - '../../src/allocation-site-scopes.h', '../../src/api.cc', '../../src/api.h', '../../src/apiutils.h',