Index: src/hydrogen.cc |
diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
index 41854088d31283f6bfa367e8a9eaa2b49b2c54de..c5bf280ce47ab31f26535f142aea6bf2c52a422d 100644 |
--- a/src/hydrogen.cc |
+++ b/src/hydrogen.cc |
@@ -2174,17 +2174,19 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
} |
- |
HValue* HGraphBuilder::BuildAllocateArrayFromLength( |
JSArrayBuilder* array_builder, |
HValue* length_argument) { |
if (length_argument->IsConstant() && |
HConstant::cast(length_argument)->HasSmiValue()) { |
int array_length = HConstant::cast(length_argument)->Integer32Value(); |
- HValue* new_object = array_length == 0 |
- ? array_builder->AllocateEmptyArray() |
- : array_builder->AllocateArray(length_argument, length_argument); |
- return new_object; |
+ if (array_length == 0) { |
+ return array_builder->AllocateEmptyArray(); |
+ } else { |
+ return array_builder->AllocateArray(length_argument, |
+ array_length, |
+ length_argument); |
+ } |
} |
HValue* constant_zero = graph()->GetConstant0(); |
@@ -2214,32 +2216,61 @@ HValue* HGraphBuilder::BuildAllocateArrayFromLength( |
// Figure out total size |
HValue* length = Pop(); |
HValue* capacity = Pop(); |
- return array_builder->AllocateArray(capacity, length); |
+ return array_builder->AllocateArray(capacity, max_alloc_length, length); |
} |
-HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind, |
- HValue* capacity) { |
- int elements_size; |
- InstanceType instance_type; |
- |
- if (IsFastDoubleElementsKind(kind)) { |
- elements_size = kDoubleSize; |
- instance_type = FIXED_DOUBLE_ARRAY_TYPE; |
- } else { |
- elements_size = kPointerSize; |
- instance_type = FIXED_ARRAY_TYPE; |
- } |
+HValue* HGraphBuilder::BuildCalculateElementsSize(ElementsKind kind, |
+ HValue* capacity) { |
+ int elements_size = IsFastDoubleElementsKind(kind) |
+ ? kDoubleSize |
+ : kPointerSize; |
HConstant* elements_size_value = Add<HConstant>(elements_size); |
- HValue* mul = AddUncasted<HMul>(capacity, elements_size_value); |
+ HInstruction* mul = HMul::NewImul(zone(), context(), |
+ capacity->ActualValue(), |
+ elements_size_value); |
+ AddInstruction(mul); |
mul->ClearFlag(HValue::kCanOverflow); |
+ STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize); |
+ |
HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize); |
HValue* total_size = AddUncasted<HAdd>(mul, header_size); |
total_size->ClearFlag(HValue::kCanOverflow); |
+ return total_size; |
+} |
+ |
+ |
+HConstant* HGraphBuilder::EstablishHeaderAllocationSize( |
+ AllocationSiteMode mode) { |
+ int base_size = JSArray::kSize; |
+ if (mode == TRACK_ALLOCATION_SITE) { |
+ base_size += AllocationMemento::kSize; |
+ } |
+ return Add<HConstant>(base_size); |
+} |
- return Add<HAllocate>(total_size, HType::JSArray(), |
- isolate()->heap()->GetPretenureMode(), instance_type); |
+ |
+HConstant* HGraphBuilder::EstablishElementsAllocationSize( |
+ ElementsKind kind, |
+ int capacity) { |
+ int base_size = IsFastDoubleElementsKind(kind) |
+ ? FixedDoubleArray::SizeFor(capacity) |
+ : FixedArray::SizeFor(capacity); |
+ |
+ return Add<HConstant>(base_size); |
+} |
+ |
+ |
+HAllocate* HGraphBuilder::BuildAllocateElements(ElementsKind kind, |
+ HValue* size_in_bytes, |
+ PretenureFlag pretenure) { |
+ InstanceType instance_type = IsFastDoubleElementsKind(kind) |
+ ? FIXED_DOUBLE_ARRAY_TYPE |
+ : FIXED_ARRAY_TYPE; |
+ |
+ return Add<HAllocate>(size_in_bytes, HType::JSArray(), |
+ pretenure, instance_type); |
} |
@@ -2263,43 +2294,38 @@ HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader( |
// The HForceRepresentation is to prevent possible deopt on int-smi |
// conversion after allocation but before the new object fields are set. |
capacity = AddUncasted<HForceRepresentation>(capacity, Representation::Smi()); |
- HValue* new_elements = BuildAllocateElements(kind, capacity); |
+ HValue* size_in_bytes = BuildCalculateElementsSize(kind, capacity); |
+ HValue* new_elements = BuildAllocateElements( |
+ kind, size_in_bytes, isolate()->heap()->GetPretenureMode()); |
BuildInitializeElementsHeader(new_elements, kind, capacity); |
return new_elements; |
} |
-HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, |
- HValue* array_map, |
- AllocationSiteMode mode, |
- ElementsKind elements_kind, |
- HValue* allocation_site_payload, |
- HValue* length_field) { |
- |
+void HGraphBuilder::BuildJSArrayHeader(HValue* array, |
+ HValue* array_map, |
+ AllocationSiteMode mode, |
+ ElementsKind elements_kind, |
+ HValue* allocation_site_payload, |
+ HValue* length_field) { |
Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map); |
HConstant* empty_fixed_array = |
Add<HConstant>(isolate()->factory()->empty_fixed_array()); |
- HObjectAccess access = HObjectAccess::ForPropertiesPointer(); |
- Add<HStoreNamedField>(array, access, empty_fixed_array); |
- Add<HStoreNamedField>(array, HObjectAccess::ForArrayLength(elements_kind), |
- length_field); |
+ Add<HStoreNamedField>( |
+ array, HObjectAccess::ForPropertiesPointer(), empty_fixed_array); |
+ |
+ Add<HStoreNamedField>( |
+ array, HObjectAccess::ForElementsPointer(), empty_fixed_array); |
+ |
+ Add<HStoreNamedField>( |
+ array, HObjectAccess::ForArrayLength(elements_kind), length_field); |
if (mode == TRACK_ALLOCATION_SITE) { |
BuildCreateAllocationMemento( |
array, Add<HConstant>(JSArray::kSize), allocation_site_payload); |
} |
- |
- int elements_location = JSArray::kSize; |
- if (mode == TRACK_ALLOCATION_SITE) { |
- elements_location += AllocationMemento::kSize; |
- } |
- |
- HInnerAllocatedObject* elements = Add<HInnerAllocatedObject>( |
- array, Add<HConstant>(elements_location)); |
- Add<HStoreNamedField>(array, HObjectAccess::ForElementsPointer(), elements); |
- return elements; |
} |
@@ -2510,12 +2536,7 @@ HValue* HGraphBuilder::BuildCloneShallowArray(HValue* boilerplate, |
NoObservableSideEffectsScope no_effects(this); |
// All sizes here are multiples of kPointerSize. |
- int size = JSArray::kSize; |
- if (mode == TRACK_ALLOCATION_SITE) { |
- size += AllocationMemento::kSize; |
- } |
- |
- HValue* size_in_bytes = Add<HConstant>(size); |
+ HConstant* size_in_bytes = EstablishHeaderAllocationSize(mode); |
HInstruction* object = Add<HAllocate>(size_in_bytes, |
HType::JSObject(), |
NOT_TENURED, |
@@ -2538,16 +2559,10 @@ HValue* HGraphBuilder::BuildCloneShallowArray(HValue* boilerplate, |
if (length > 0) { |
HValue* boilerplate_elements = AddLoadElements(boilerplate); |
- HValue* object_elements; |
- if (IsFastDoubleElementsKind(kind)) { |
- HValue* elems_size = Add<HConstant>(FixedDoubleArray::SizeFor(length)); |
- object_elements = Add<HAllocate>(elems_size, HType::JSArray(), |
- NOT_TENURED, FIXED_DOUBLE_ARRAY_TYPE); |
- } else { |
- HValue* elems_size = Add<HConstant>(FixedArray::SizeFor(length)); |
- object_elements = Add<HAllocate>(elems_size, HType::JSArray(), |
- NOT_TENURED, FIXED_ARRAY_TYPE); |
- } |
+ HConstant* elements_size = EstablishElementsAllocationSize(kind, length); |
+ HValue* object_elements = |
+ BuildAllocateElements(kind, elements_size, NOT_TENURED); |
+ |
Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
object_elements); |
@@ -2754,67 +2769,47 @@ HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { |
} |
-HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( |
- HValue* length_node) { |
- ASSERT(length_node != NULL); |
- |
- int base_size = JSArray::kSize; |
- if (mode_ == TRACK_ALLOCATION_SITE) { |
- base_size += AllocationMemento::kSize; |
- } |
- |
- STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize); |
- base_size += FixedArray::kHeaderSize; |
- |
- HInstruction* elements_size_value = |
- builder()->Add<HConstant>(elements_size()); |
- HInstruction* mul = HMul::NewImul(builder()->zone(), builder()->context(), |
- length_node, elements_size_value); |
- builder()->AddInstruction(mul); |
- HInstruction* base = builder()->Add<HConstant>(base_size); |
- HInstruction* total_size = HAdd::New(builder()->zone(), builder()->context(), |
- base, mul); |
- total_size->ClearFlag(HValue::kCanOverflow); |
- builder()->AddInstruction(total_size); |
- return total_size; |
+HAllocate* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() { |
+ HConstant* capacity = builder()->Add<HConstant>(initial_capacity()); |
+ return AllocateArray(capacity, |
+ builder()->graph()->GetConstant0()); |
} |
-HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() { |
- int base_size = JSArray::kSize; |
- if (mode_ == TRACK_ALLOCATION_SITE) { |
- base_size += AllocationMemento::kSize; |
- } |
- |
- base_size += IsFastDoubleElementsKind(kind_) |
- ? FixedDoubleArray::SizeFor(initial_capacity()) |
- : FixedArray::SizeFor(initial_capacity()); |
- |
- return builder()->Add<HConstant>(base_size); |
+HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray( |
+ HValue* capacity, |
+ HConstant* capacity_upper_bound, |
+ HValue* length_field, |
+ FillMode fill_mode) { |
+ return AllocateArray(capacity, |
+ capacity_upper_bound->GetInteger32Constant(), |
+ length_field, |
+ fill_mode); |
} |
-HValue* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() { |
- HValue* size_in_bytes = EstablishEmptyArrayAllocationSize(); |
- HConstant* capacity = builder()->Add<HConstant>(initial_capacity()); |
- return AllocateArray(size_in_bytes, |
- capacity, |
- builder()->graph()->GetConstant0()); |
-} |
- |
+HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray( |
+ HValue* capacity, |
+ int capacity_upper_bound, |
+ HValue* length_field, |
+ FillMode fill_mode) { |
+ HConstant* elememts_size_upper_bound = capacity->IsInteger32Constant() |
+ ? HConstant::cast(capacity) |
+ : builder()->EstablishElementsAllocationSize(kind_, capacity_upper_bound); |
-HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* capacity, |
- HValue* length_field, |
- FillMode fill_mode) { |
- HValue* size_in_bytes = EstablishAllocationSize(capacity); |
- return AllocateArray(size_in_bytes, capacity, length_field, fill_mode); |
+ HAllocate* array = AllocateArray(capacity, length_field, fill_mode); |
+ if (!capacity->IsInteger32Constant()) { |
+ // For constant sizes the size upper bound is set automatically. |
+ elements_location_->set_size_upper_bound(elememts_size_upper_bound); |
+ } |
+ return array; |
} |
-HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes, |
- HValue* capacity, |
- HValue* length_field, |
- FillMode fill_mode) { |
+HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray( |
+ HValue* capacity, |
+ HValue* length_field, |
+ FillMode fill_mode) { |
// These HForceRepresentations are because we store these as fields in the |
// objects we construct, and an int32-to-smi HChange could deopt. Accept |
// the deopt possibility now, before allocation occurs. |
@@ -2824,15 +2819,18 @@ HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes, |
length_field = |
builder()->AddUncasted<HForceRepresentation>(length_field, |
Representation::Smi()); |
+ |
+ // Generate size calculation code here in order to make it dominate |
+ // the JSArray allocation. |
+ HValue* elements_size = |
+ builder()->BuildCalculateElementsSize(kind_, capacity); |
+ |
// Allocate (dealing with failure appropriately) |
- HAllocate* new_object = builder()->Add<HAllocate>(size_in_bytes, |
+ HConstant* array_object_size = |
+ builder()->EstablishHeaderAllocationSize(mode_); |
+ HAllocate* array_object = builder()->Add<HAllocate>(array_object_size, |
HType::JSArray(), NOT_TENURED, JS_ARRAY_TYPE); |
- // Folded array allocation should be aligned if it has fast double elements. |
- if (IsFastDoubleElementsKind(kind_)) { |
- new_object->MakeDoubleAligned(); |
- } |
- |
// Fill in the fields: map, properties, length |
HValue* map; |
if (allocation_site_payload_ == NULL) { |
@@ -2840,22 +2838,30 @@ HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes, |
} else { |
map = EmitMapCode(); |
} |
- elements_location_ = builder()->BuildJSArrayHeader(new_object, |
- map, |
- mode_, |
- kind_, |
- allocation_site_payload_, |
- length_field); |
- // Initialize the elements |
+ builder()->BuildJSArrayHeader(array_object, |
+ map, |
+ mode_, |
+ kind_, |
+ allocation_site_payload_, |
+ length_field); |
+ |
+ // Allocate and initialize the elements |
+ elements_location_ = |
+ builder()->BuildAllocateElements(kind_, elements_size, NOT_TENURED); |
+ |
builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity); |
+ // Set the elements |
+ builder()->Add<HStoreNamedField>( |
+ array_object, HObjectAccess::ForElementsPointer(), elements_location_); |
+ |
if (fill_mode == FILL_WITH_HOLE) { |
builder()->BuildFillElementsWithHole(elements_location_, kind_, |
graph()->GetConstant0(), capacity); |
} |
- return new_object; |
+ return array_object; |
} |