| 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;
|
| }
|
|
|
|
|
|
|