From: hpayer@chromium.org Date: Thu, 29 Aug 2013 12:06:45 +0000 (+0000) Subject: Simplified BuildFastLiteral by eliminating manual allocation folding. X-Git-Tag: upstream/4.7.83~12750 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=95c7ae814942b320f36eed354e5d107bd2cc66e6;p=platform%2Fupstream%2Fv8.git Simplified BuildFastLiteral by eliminating manual allocation folding. BUG= R=mstarzinger@chromium.org Review URL: https://codereview.chromium.org/23030002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16422 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 237e807..ef0ab42 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -4097,9 +4097,7 @@ static bool LookupSetter(Handle map, // size of all objects that are part of the graph. static bool IsFastLiteral(Handle boilerplate, int max_depth, - int* max_properties, - int* data_size, - int* pointer_size) { + int* max_properties) { if (boilerplate->map()->is_deprecated()) { Handle result = JSObject::TryMigrateInstance(boilerplate); if (result->IsSmi()) return false; @@ -4112,9 +4110,7 @@ static bool IsFastLiteral(Handle boilerplate, Handle elements(boilerplate->elements()); if (elements->length() > 0 && elements->map() != isolate->heap()->fixed_cow_array_map()) { - if (boilerplate->HasFastDoubleElements()) { - *data_size += FixedDoubleArray::SizeFor(elements->length()); - } else if (boilerplate->HasFastObjectElements()) { + if (boilerplate->HasFastObjectElements()) { Handle fast_elements = Handle::cast(elements); int length = elements->length(); for (int i = 0; i < length; i++) { @@ -4124,15 +4120,12 @@ static bool IsFastLiteral(Handle boilerplate, Handle value_object = Handle::cast(value); if (!IsFastLiteral(value_object, max_depth - 1, - max_properties, - data_size, - pointer_size)) { + max_properties)) { return false; } } } - *pointer_size += FixedArray::SizeFor(length); - } else { + } else if (!boilerplate->HasFastDoubleElements()) { return false; } } @@ -4147,7 +4140,6 @@ static bool IsFastLiteral(Handle boilerplate, for (int i = 0; i < limit; i++) { PropertyDetails details = descriptors->GetDetails(i); if (details.type() != FIELD) continue; - Representation representation = details.representation(); int index = descriptors->GetFieldIndex(i); if ((*max_properties)-- == 0) return false; Handle value(boilerplate->InObjectPropertyAt(index), isolate); @@ -4155,18 +4147,12 @@ static bool IsFastLiteral(Handle boilerplate, Handle value_object = Handle::cast(value); if (!IsFastLiteral(value_object, max_depth - 1, - max_properties, - data_size, - pointer_size)) { + max_properties)) { return false; } - } else if (representation.IsDouble()) { - *data_size += HeapNumber::kSize; } } } - - *pointer_size += boilerplate->map()->instance_size(); return true; } @@ -4176,32 +4162,21 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { ASSERT(current_block() != NULL); ASSERT(current_block()->HasPredecessor()); Handle closure = function_state()->compilation_info()->closure(); - HValue* context = environment()->context(); HInstruction* literal; // Check whether to use fast or slow deep-copying for boilerplate. - int data_size = 0; - int pointer_size = 0; int max_properties = kMaxFastLiteralProperties; - Handle original_boilerplate(closure->literals()->get( + Handle boilerplate(closure->literals()->get( expr->literal_index()), isolate()); - if (original_boilerplate->IsJSObject() && - IsFastLiteral(Handle::cast(original_boilerplate), + if (boilerplate->IsJSObject() && + IsFastLiteral(Handle::cast(boilerplate), kMaxFastLiteralDepth, - &max_properties, - &data_size, - &pointer_size)) { - Handle original_boilerplate_object = - Handle::cast(original_boilerplate); + &max_properties)) { Handle boilerplate_object = - DeepCopy(original_boilerplate_object); + Handle::cast(boilerplate); - literal = BuildFastLiteral(context, - boilerplate_object, - original_boilerplate_object, + literal = BuildFastLiteral(boilerplate_object, Handle::null(), - data_size, - pointer_size, DONT_TRACK_ALLOCATION_SITE); } else { NoObservableSideEffectsScope no_effects(this); @@ -4303,7 +4278,6 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { ASSERT(current_block()->HasPredecessor()); ZoneList* subexprs = expr->values(); int length = subexprs->length(); - HValue* context = environment()->context(); HInstruction* literal; Handle site; @@ -4337,10 +4311,10 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { ASSERT(!raw_boilerplate.is_null()); ASSERT(site->IsLiteralSite()); - Handle original_boilerplate_object = + Handle boilerplate_object = Handle::cast(raw_boilerplate); ElementsKind boilerplate_elements_kind = - Handle::cast(original_boilerplate_object)->GetElementsKind(); + Handle::cast(boilerplate_object)->GetElementsKind(); // TODO(mvstanton): This heuristic is only a temporary solution. In the // end, we want to quit creating allocation site info after a certain number @@ -4349,25 +4323,12 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { boilerplate_elements_kind); // Check whether to use fast or slow deep-copying for boilerplate. - int data_size = 0; - int pointer_size = 0; int max_properties = kMaxFastLiteralProperties; - if (IsFastLiteral(original_boilerplate_object, + if (IsFastLiteral(boilerplate_object, kMaxFastLiteralDepth, - &max_properties, - &data_size, - &pointer_size)) { - if (mode == TRACK_ALLOCATION_SITE) { - pointer_size += AllocationMemento::kSize; - } - - Handle boilerplate_object = DeepCopy(original_boilerplate_object); - literal = BuildFastLiteral(context, - boilerplate_object, - original_boilerplate_object, + &max_properties)) { + literal = BuildFastLiteral(boilerplate_object, site, - data_size, - pointer_size, mode); } else { NoObservableSideEffectsScope no_effects(this); @@ -4387,8 +4348,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { 3); // De-opt if elements kind changed from boilerplate_elements_kind. - Handle map = Handle(original_boilerplate_object->map(), - isolate()); + Handle map = Handle(boilerplate_object->map(), isolate()); literal = Add(literal, map, top_info()); } @@ -8274,59 +8234,15 @@ HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( - HValue* context, Handle boilerplate_object, - Handle original_boilerplate_object, - Handle allocation_site, - int data_size, - int pointer_size, + Handle allocation_site_object, AllocationSiteMode mode) { NoObservableSideEffectsScope no_effects(this); - HInstruction* target = NULL; - HInstruction* data_target = NULL; - - if (isolate()->heap()->GetPretenureMode() == TENURED) { - if (data_size != 0) { - HValue* size_in_bytes = Add(data_size); - data_target = Add(size_in_bytes, HType::JSObject(), TENURED, - FIXED_DOUBLE_ARRAY_TYPE); - Handle free_space_map = isolate()->factory()->free_space_map(); - AddStoreMapConstant(data_target, free_space_map); - HObjectAccess access = - HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset); - Add(data_target, access, size_in_bytes); - } - if (pointer_size != 0) { - HValue* size_in_bytes = Add(pointer_size); - target = Add(size_in_bytes, HType::JSObject(), TENURED, - JS_OBJECT_TYPE); - } - } else { - InstanceType instance_type = boilerplate_object->map()->instance_type(); - HValue* size_in_bytes = Add(data_size + pointer_size); - target = Add(size_in_bytes, HType::JSObject(), NOT_TENURED, - instance_type); - } - - int offset = 0; - int data_offset = 0; - BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object, - allocation_site, target, &offset, data_target, - &data_offset, mode); - return target; -} - + Handle elements(boilerplate_object->elements()); + int object_size = boilerplate_object->map()->instance_size(); + int object_offset = object_size; -void HOptimizedGraphBuilder::BuildEmitDeepCopy( - Handle boilerplate_object, - Handle original_boilerplate_object, - Handle allocation_site_object, - HInstruction* target, - int* offset, - HInstruction* data_target, - int* data_offset, - AllocationSiteMode mode) { bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE && AllocationSite::CanTrack(boilerplate_object->map()->instance_type()); @@ -8335,99 +8251,67 @@ void HOptimizedGraphBuilder::BuildEmitDeepCopy( ASSERT(!create_allocation_site_info || AllocationSite::cast(*allocation_site_object)->IsLiteralSite()); - HInstruction* allocation_site = NULL; - if (create_allocation_site_info) { - allocation_site = Add(allocation_site_object); + object_size += AllocationMemento::kSize; } - // Only elements backing stores for non-COW arrays need to be copied. - Handle elements(boilerplate_object->elements()); - Handle original_elements( - original_boilerplate_object->elements()); - ElementsKind kind = boilerplate_object->map()->elements_kind(); + HValue* object_size_constant = Add(object_size); + HInstruction* object = Add(object_size_constant, HType::JSObject(), + isolate()->heap()->GetPretenureMode(), JS_OBJECT_TYPE); + + + BuildEmitObjectHeader(boilerplate_object, object); + + if (create_allocation_site_info) { + HInstruction* allocation_site = Add(allocation_site_object); + BuildCreateAllocationMemento(object, object_offset, allocation_site); + } - int object_offset = *offset; - int object_size = boilerplate_object->map()->instance_size(); int elements_size = (elements->length() > 0 && elements->map() != isolate()->heap()->fixed_cow_array_map()) ? elements->Size() : 0; - int elements_offset = 0; - if (data_target != NULL && boilerplate_object->HasFastDoubleElements()) { - elements_offset = *data_offset; - *data_offset += elements_size; - } else { - // Place elements right after this object. - elements_offset = *offset + object_size; - *offset += elements_size; + HInstruction* object_elements = NULL; + if (elements_size > 0) { + HValue* object_elements_size = Add(elements_size); + if (boilerplate_object->HasFastDoubleElements()) { + object_elements = Add(object_elements_size, HType::JSObject(), + isolate()->heap()->GetPretenureMode(), FIXED_DOUBLE_ARRAY_TYPE); + } else { + object_elements = Add(object_elements_size, HType::JSObject(), + isolate()->heap()->GetPretenureMode(), FIXED_ARRAY_TYPE); + } } - // Increase the offset so that subsequent objects end up right after this - // object (and it's elements if they are allocated in the same space). - *offset += object_size; + BuildInitElementsInObjectHeader(boilerplate_object, object, object_elements); + // Copy object elements if non-COW. - HValue* object_elements = BuildEmitObjectHeader(boilerplate_object, target, - data_target, object_offset, elements_offset, elements_size); if (object_elements != NULL) { - BuildEmitElements(elements, original_elements, kind, object_elements, - target, offset, data_target, data_offset); + BuildEmitElements(boilerplate_object, elements, object_elements); } // Copy in-object properties. if (boilerplate_object->map()->NumberOfFields() != 0) { - HValue* object_properties = - Add(target, object_offset); - BuildEmitInObjectProperties(boilerplate_object, original_boilerplate_object, - object_properties, target, offset, data_target, data_offset); - } - - // Create allocation site info. - if (mode == TRACK_ALLOCATION_SITE && - AllocationSite::CanTrack(boilerplate_object->map()->instance_type())) { - elements_offset += AllocationMemento::kSize; - *offset += AllocationMemento::kSize; - BuildCreateAllocationMemento(target, JSArray::kSize, allocation_site); + BuildEmitInObjectProperties(boilerplate_object, object); } + return object; } -HValue* HOptimizedGraphBuilder::BuildEmitObjectHeader( +void HOptimizedGraphBuilder::BuildEmitObjectHeader( Handle boilerplate_object, - HInstruction* target, - HInstruction* data_target, - int object_offset, - int elements_offset, - int elements_size) { + HInstruction* object) { ASSERT(boilerplate_object->properties()->length() == 0); - HValue* result = NULL; - HValue* object_header = Add(target, object_offset); Handle boilerplate_object_map(boilerplate_object->map()); - AddStoreMapConstant(object_header, boilerplate_object_map); - - HInstruction* elements; - if (elements_size == 0) { - Handle elements_field = - Handle(boilerplate_object->elements(), isolate()); - elements = Add(elements_field); - } else { - if (data_target != NULL && boilerplate_object->HasFastDoubleElements()) { - elements = Add(data_target, elements_offset); - } else { - elements = Add(target, elements_offset); - } - result = elements; - } - Add(object_header, HObjectAccess::ForElementsPointer(), - elements); + AddStoreMapConstant(object, boilerplate_object_map); Handle properties_field = Handle(boilerplate_object->properties(), isolate()); ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); HInstruction* properties = Add(properties_field); HObjectAccess access = HObjectAccess::ForPropertiesPointer(); - Add(object_header, access, properties); + Add(object, access, properties); if (boilerplate_object->IsJSArray()) { Handle boilerplate_array = @@ -8437,22 +8321,30 @@ HValue* HOptimizedGraphBuilder::BuildEmitObjectHeader( HInstruction* length = Add(length_field); ASSERT(boilerplate_array->length()->IsSmi()); - Add(object_header, HObjectAccess::ForArrayLength( + Add(object, HObjectAccess::ForArrayLength( boilerplate_array->GetElementsKind()), length); } +} - return result; + +void HOptimizedGraphBuilder::BuildInitElementsInObjectHeader( + Handle boilerplate_object, + HInstruction* object, + HInstruction* object_elements) { + ASSERT(boilerplate_object->properties()->length() == 0); + if (object_elements == NULL) { + Handle elements_field = + Handle(boilerplate_object->elements(), isolate()); + object_elements = Add(elements_field); + } + Add(object, HObjectAccess::ForElementsPointer(), + object_elements); } void HOptimizedGraphBuilder::BuildEmitInObjectProperties( Handle boilerplate_object, - Handle original_boilerplate_object, - HValue* object_properties, - HInstruction* target, - int* offset, - HInstruction* data_target, - int* data_offset) { + HInstruction* object) { Handle descriptors( boilerplate_object->map()->instance_descriptors()); int limit = boilerplate_object->map()->NumberOfOwnDescriptors(); @@ -8476,31 +8368,20 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties( if (value->IsJSObject()) { Handle value_object = Handle::cast(value); - Handle original_value_object = Handle::cast( - Handle(original_boilerplate_object->InObjectPropertyAt(index), - isolate())); - HInstruction* value_instruction = Add(target, - *offset); - - Add(object_properties, access, value_instruction); - BuildEmitDeepCopy(value_object, original_value_object, - Handle::null(), target, - offset, data_target, data_offset, - DONT_TRACK_ALLOCATION_SITE); + HInstruction* result = + BuildFastLiteral(value_object, + Handle::null(), DONT_TRACK_ALLOCATION_SITE); + Add(object, access, result); } else { Representation representation = details.representation(); HInstruction* value_instruction = Add(value); if (representation.IsDouble()) { // Allocate a HeapNumber box and store the value into it. - HInstruction* double_box; - if (data_target != NULL) { - double_box = Add(data_target, *data_offset); - *data_offset += HeapNumber::kSize; - } else { - double_box = Add(target, *offset); - *offset += HeapNumber::kSize; - } + HValue* heap_number_constant = Add(HeapNumber::kSize); + HInstruction* double_box = + Add(heap_number_constant, HType::HeapNumber(), + isolate()->heap()->GetPretenureMode(), HEAP_NUMBER_TYPE); AddStoreMapConstant(double_box, isolate()->factory()->heap_number_map()); Add(double_box, HObjectAccess::ForHeapNumberValue(), @@ -8508,7 +8389,7 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties( value_instruction = double_box; } - Add(object_properties, access, value_instruction); + Add(object, access, value_instruction); } } @@ -8519,31 +8400,25 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties( ASSERT(boilerplate_object->IsJSObject()); int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); - Add(object_properties, access, value_instruction); + Add(object, access, value_instruction); } } void HOptimizedGraphBuilder::BuildEmitElements( + Handle boilerplate_object, Handle elements, - Handle original_elements, - ElementsKind kind, - HValue* object_elements, - HInstruction* target, - int* offset, - HInstruction* data_target, - int* data_offset) { + HValue* object_elements) { + ElementsKind kind = boilerplate_object->map()->elements_kind(); int elements_length = elements->length(); HValue* object_elements_length = Add(elements_length); - BuildInitializeElementsHeader(object_elements, kind, object_elements_length); // Copy elements backing store content. if (elements->IsFixedDoubleArray()) { BuildEmitFixedDoubleArray(elements, kind, object_elements); } else if (elements->IsFixedArray()) { - BuildEmitFixedArray(elements, original_elements, kind, object_elements, - target, offset, data_target, data_offset); + BuildEmitFixedArray(elements, kind, object_elements); } else { UNREACHABLE(); } @@ -8571,32 +8446,20 @@ void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray( void HOptimizedGraphBuilder::BuildEmitFixedArray( Handle elements, - Handle original_elements, ElementsKind kind, - HValue* object_elements, - HInstruction* target, - int* offset, - HInstruction* data_target, - int* data_offset) { + HValue* object_elements) { HInstruction* boilerplate_elements = Add(elements); int elements_length = elements->length(); Handle fast_elements = Handle::cast(elements); - Handle original_fast_elements = - Handle::cast(original_elements); for (int i = 0; i < elements_length; i++) { Handle value(fast_elements->get(i), isolate()); HValue* key_constant = Add(i); if (value->IsJSObject()) { Handle value_object = Handle::cast(value); - Handle original_value_object = Handle::cast( - Handle(original_fast_elements->get(i), isolate())); - HInstruction* value_instruction = Add(target, - *offset); - Add(object_elements, key_constant, value_instruction, kind); - BuildEmitDeepCopy(value_object, original_value_object, - Handle::null(), target, - offset, data_target, data_offset, - DONT_TRACK_ALLOCATION_SITE); + HInstruction* result = + BuildFastLiteral(value_object, + Handle::null(), DONT_TRACK_ALLOCATION_SITE); + Add(object_elements, key_constant, result, kind); } else { HInstruction* value_instruction = Add(boilerplate_elements, key_constant, diff --git a/src/hydrogen.h b/src/hydrogen.h index 369e092..cdca1bd 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -2063,60 +2063,31 @@ class HOptimizedGraphBuilder V8_FINAL HInstruction* BuildThisFunction(); - HInstruction* BuildFastLiteral(HValue* context, - Handle boilerplate_object, - Handle original_boilerplate_object, + HInstruction* BuildFastLiteral(Handle boilerplate_object, Handle allocation_site, - int data_size, - int pointer_size, AllocationSiteMode mode); - void BuildEmitDeepCopy(Handle boilerplat_object, - Handle object, - Handle allocation_site, - HInstruction* target, - int* offset, - HInstruction* data_target, - int* data_offset, - AllocationSiteMode mode); - - MUST_USE_RESULT HValue* BuildEmitObjectHeader( - Handle boilerplat_object, - HInstruction* target, - HInstruction* data_target, - int object_offset, - int elements_offset, - int elements_size); + void BuildEmitObjectHeader(Handle boilerplate_object, + HInstruction* object); + + void BuildInitElementsInObjectHeader(Handle boilerplate_object, + HInstruction* object, + HInstruction* object_elements); void BuildEmitInObjectProperties(Handle boilerplate_object, - Handle original_boilerplate_object, - HValue* object_properties, - HInstruction* target, - int* offset, - HInstruction* data_target, - int* data_offset); - - void BuildEmitElements(Handle elements, - Handle original_elements, - ElementsKind kind, - HValue* object_elements, - HInstruction* target, - int* offset, - HInstruction* data_target, - int* data_offset); + HInstruction* object); + + void BuildEmitElements(Handle boilerplate_object, + Handle elements, + HValue* object_elements); void BuildEmitFixedDoubleArray(Handle elements, ElementsKind kind, HValue* object_elements); void BuildEmitFixedArray(Handle elements, - Handle original_elements, ElementsKind kind, - HValue* object_elements, - HInstruction* target, - int* offset, - HInstruction* data_target, - int* data_offset); + HValue* object_elements); void AddCheckPrototypeMaps(Handle holder, Handle receiver_map); diff --git a/test/mjsunit/fast-literal.js b/test/mjsunit/fast-literal.js new file mode 100644 index 0000000..822d906 --- /dev/null +++ b/test/mjsunit/fast-literal.js @@ -0,0 +1,42 @@ +// Copyright 2012 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. + +// Flags: --allow-natives-syntax --no-inline-new --nouse-allocation-folding + +%SetAllocationTimeout(10, 0); +function f() { + return [[1, 2, 3], [1.1, 1.2, 1.3], [[], [], []]]; +} + +f(); f(); f(); +%OptimizeFunctionOnNextCall(f); +for (var i=0; i<1000; i++) { + f(); +} + + +