Chromium Code Reviews| Index: src/hydrogen.cc |
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
| index 99687caf91e9963727301762e6ce2d2f61af1974..c059f3468df50bf4f8b1d8057289bc30690423a2 100644 |
| --- a/src/hydrogen.cc |
| +++ b/src/hydrogen.cc |
| @@ -30,6 +30,7 @@ |
| #include <algorithm> |
| #include "v8.h" |
| +#include "allocation-site-scopes.h" |
| #include "codegen.h" |
| #include "full-codegen.h" |
| #include "hashmap.h" |
| @@ -4335,15 +4336,26 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| // Check whether to use fast or slow deep-copying for boilerplate. |
| int max_properties = kMaxFastLiteralProperties; |
| - Handle<Object> boilerplate(closure->literals()->get( |
| - expr->literal_index()), isolate()); |
| - if (boilerplate->IsJSObject() && |
| + Handle<Object> literals_cell(closure->literals()->get(expr->literal_index()), |
| + isolate()); |
| + Handle<AllocationSite> site; |
| + Handle<Object> boilerplate; |
| + if (!literals_cell->IsUndefined()) { |
| + // Retrieve the boilerplate |
| + ASSERT(literals_cell->IsAllocationSite()); |
| + site = Handle<AllocationSite>::cast(literals_cell); |
| + boilerplate = Handle<Object>(site->transition_info(), isolate()); |
| + } |
| + |
| + if (!boilerplate.is_null() && |
| IsFastLiteral(Handle<JSObject>::cast(boilerplate), |
| kMaxFastLiteralDepth, |
| &max_properties)) { |
| Handle<JSObject> boilerplate_object = Handle<JSObject>::cast(boilerplate); |
| - |
| - literal = BuildFastLiteral(boilerplate_object); |
| + AllocationSiteContext site_context(isolate(), false); |
| + AllocationSiteUsageScope site_scope(&site_context, site, |
| + boilerplate_object); |
| + literal = BuildFastLiteral(boilerplate_object, &site_context); |
| } else { |
| NoObservableSideEffectsScope no_effects(this); |
| Handle<FixedArray> closure_literals(closure->literals(), isolate()); |
| @@ -4458,8 +4470,12 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
| return Bailout(kArrayBoilerplateCreationFailed); |
| } |
| - site = isolate()->factory()->NewAllocationSite(); |
| - site->set_transition_info(*raw_boilerplate); |
| + AllocationSiteContext site_context(isolate(), true); |
| + AllocationSiteCreationScope site_scope(&site_context); |
| + Handle<Object> same = JSObject::DeepWalk( |
| + Handle<JSObject>::cast(raw_boilerplate), &site_context); |
| + site = site_context.top(); |
| + site->set_transition_info(*same); |
| literals->set(expr->literal_index(), *site); |
| if (JSObject::cast(*raw_boilerplate)->elements()->map() == |
| @@ -4480,14 +4496,15 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
| ElementsKind boilerplate_elements_kind = |
| Handle<JSObject>::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)) { |
| - literal = BuildFastLiteral(boilerplate_object); |
| + AllocationSiteContext site_context(isolate(), false); |
| + AllocationSiteUsageScope site_scope(&site_context, site, |
| + boilerplate_object); |
| + literal = BuildFastLiteral(boilerplate_object, &site_context); |
| } else { |
| NoObservableSideEffectsScope no_effects(this); |
| // Boilerplate already exists and constant elements are never accessed, |
| @@ -8408,7 +8425,8 @@ HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { |
| HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( |
| - Handle<JSObject> boilerplate_object) { |
| + Handle<JSObject> boilerplate_object, |
| + AllocationSiteContext* site_context) { |
| NoObservableSideEffectsScope no_effects(this); |
| InstanceType instance_type = boilerplate_object->map()->instance_type(); |
| ASSERT(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE); |
| @@ -8440,15 +8458,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); |
| + BuildEmitElements(boilerplate_object, elements, object_elements, |
| + site_context); |
| } |
| // Copy in-object properties. |
| if (boilerplate_object->map()->NumberOfFields() != 0) { |
| - BuildEmitInObjectProperties(boilerplate_object, object); |
| + BuildEmitInObjectProperties(boilerplate_object, object, site_context); |
| } |
| return object; |
| } |
| @@ -8500,7 +8518,8 @@ void HOptimizedGraphBuilder::BuildInitElementsInObjectHeader( |
| void HOptimizedGraphBuilder::BuildEmitInObjectProperties( |
| Handle<JSObject> boilerplate_object, |
| - HInstruction* object) { |
| + HInstruction* object, |
| + AllocationSiteContext* site_context) { |
| Handle<DescriptorArray> descriptors( |
| boilerplate_object->map()->instance_descriptors()); |
| int limit = boilerplate_object->map()->NumberOfOwnDescriptors(); |
| @@ -8523,8 +8542,10 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties( |
| HObjectAccess::ForJSObjectOffset(property_offset); |
| if (value->IsJSObject()) { |
| + AllocationSiteUsageScope site_scope(site_context, value); |
| Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| - HInstruction* result = BuildFastLiteral(value_object); |
| + HInstruction* result = |
| + BuildFastLiteral(value_object, site_context); |
| Add<HStoreNamedField>(object, access, result); |
| } else { |
| Representation representation = details.representation(); |
| @@ -8533,6 +8554,12 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties( |
| if (representation.IsDouble()) { |
| // Allocate a HeapNumber box and store the value into it. |
| HValue* heap_number_constant = Add<HConstant>(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(). |
|
Hannes Payer (out of office)
2013/10/11 12:55:44
Cool!
mvstanton
2013/10/11 13:41:47
Yessir...velly nice.
|
| HInstruction* double_box = |
| Add<HAllocate>(heap_number_constant, HType::HeapNumber(), |
| isolate()->heap()->GetPretenureMode(), HEAP_NUMBER_TYPE); |
| @@ -8562,7 +8589,8 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties( |
| void HOptimizedGraphBuilder::BuildEmitElements( |
| Handle<JSObject> boilerplate_object, |
| Handle<FixedArrayBase> elements, |
| - HValue* object_elements) { |
| + HValue* object_elements, |
| + AllocationSiteContext* site_context) { |
| ElementsKind kind = boilerplate_object->map()->elements_kind(); |
| int elements_length = elements->length(); |
| HValue* object_elements_length = Add<HConstant>(elements_length); |
| @@ -8572,7 +8600,8 @@ void HOptimizedGraphBuilder::BuildEmitElements( |
| if (elements->IsFixedDoubleArray()) { |
| BuildEmitFixedDoubleArray(elements, kind, object_elements); |
| } else if (elements->IsFixedArray()) { |
| - BuildEmitFixedArray(elements, kind, object_elements); |
| + BuildEmitFixedArray(elements, kind, object_elements, |
| + site_context); |
| } else { |
| UNREACHABLE(); |
| } |
| @@ -8601,7 +8630,8 @@ void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray( |
| void HOptimizedGraphBuilder::BuildEmitFixedArray( |
| Handle<FixedArrayBase> elements, |
| ElementsKind kind, |
| - HValue* object_elements) { |
| + HValue* object_elements, |
| + AllocationSiteContext* site_context) { |
| HInstruction* boilerplate_elements = Add<HConstant>(elements); |
| int elements_length = elements->length(); |
| Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); |
| @@ -8609,8 +8639,10 @@ void HOptimizedGraphBuilder::BuildEmitFixedArray( |
| Handle<Object> value(fast_elements->get(i), isolate()); |
| HValue* key_constant = Add<HConstant>(i); |
| if (value->IsJSObject()) { |
| + AllocationSiteUsageScope site_scope(site_context, value); |
| Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| - HInstruction* result = BuildFastLiteral(value_object); |
| + HInstruction* result = |
| + BuildFastLiteral(value_object, site_context); |
| Add<HStoreKeyed>(object_elements, key_constant, result, kind); |
| } else { |
| HInstruction* value_instruction = |