Chromium Code Reviews| Index: src/hydrogen.cc |
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
| index cccfa5b041ee7ee3cf12f747f69dea295f0fcd32..e009508d238be0365e87057973e3d63657c3a720 100644 |
| --- a/src/hydrogen.cc |
| +++ b/src/hydrogen.cc |
| @@ -2132,17 +2132,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(); |
| @@ -2172,32 +2174,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); |
| } |
| @@ -2221,43 +2252,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; |
| } |
| @@ -2468,12 +2494,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, |
| @@ -2496,16 +2517,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* elems_size = EstablishElementsAllocationSize(kind, length); |
| + HValue* object_elements = |
| + BuildAllocateElements(kind, elems_size, NOT_TENURED); |
| + |
| Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
| object_elements); |
| @@ -2695,67 +2710,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* elms_size_upper_bound = capacity->IsInteger32Constant() |
|
Hannes Payer (out of office)
2014/01/16 12:58:39
please use a full name elms -> elements
|
| + ? 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(elms_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. |
| @@ -2765,15 +2760,17 @@ 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* elms_size = builder()->BuildCalculateElementsSize(kind_, capacity); |
|
Hannes Payer (out of office)
2014/01/16 12:58:39
elms -> elements
|
| + |
| // 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) { |
| @@ -2781,22 +2778,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_, elms_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; |
| } |