| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 3b77c73c0d0357e4e6d660ba03a3735326f284ad..b38211c97b3ab4eb3374e6e222708556400273a4 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -1535,25 +1535,18 @@ HValue* HGraphBuilder::BuildRegExpConstructResult(HValue* length,
|
| HValue* index,
|
| HValue* input) {
|
| NoObservableSideEffectsScope scope(this);
|
| + HConstant* max_length = Add<HConstant>(JSObject::kInitialMaxFastElementArray);
|
| + Add<HBoundsCheck>(length, max_length);
|
|
|
| - // Compute the size of the RegExpResult followed by FixedArray with length.
|
| - HValue* size = length;
|
| - // Make sure size does not exceed max regular heap object size.
|
| - const int kHeaderSize = JSRegExpResult::kSize + FixedArray::kHeaderSize;
|
| - const int kMaxLength =
|
| - (Page::kMaxRegularHeapObjectSize - kHeaderSize) >> kPointerSizeLog2;
|
| - Add<HBoundsCheck>(size, Add<HConstant>(kMaxLength));
|
| -
|
| - size = AddUncasted<HShl>(size, Add<HConstant>(kPointerSizeLog2));
|
| - size = AddUncasted<HAdd>(size, Add<HConstant>(kHeaderSize));
|
| + // Generate size calculation code here in order to make it dominate
|
| + // the JSRegExpResult allocation.
|
| + ElementsKind elements_kind = FAST_ELEMENTS;
|
| + HValue* size = BuildCalculateElementsSize(elements_kind, length);
|
|
|
| // Allocate the JSRegExpResult and the FixedArray in one step.
|
| HValue* result = Add<HAllocate>(
|
| - size, HType::JSArray(), NOT_TENURED, JS_ARRAY_TYPE);
|
| -
|
| - // Determine the elements FixedArray.
|
| - HValue* elements = Add<HInnerAllocatedObject>(
|
| - result, Add<HConstant>(JSRegExpResult::kSize), HType::HeapObject());
|
| + Add<HConstant>(JSRegExpResult::kSize), HType::JSArray(),
|
| + NOT_TENURED, JS_ARRAY_TYPE);
|
|
|
| // Initialize the JSRegExpResult header.
|
| HValue* global_object = Add<HLoadNamedField>(
|
| @@ -1567,12 +1560,14 @@ HValue* HGraphBuilder::BuildRegExpConstructResult(HValue* length,
|
| Add<HLoadNamedField>(
|
| native_context, static_cast<HValue*>(NULL),
|
| HObjectAccess::ForContextSlot(Context::REGEXP_RESULT_MAP_INDEX)));
|
| + HConstant* empty_fixed_array =
|
| + Add<HConstant>(isolate()->factory()->empty_fixed_array());
|
| Add<HStoreNamedField>(
|
| result, HObjectAccess::ForJSArrayOffset(JSArray::kPropertiesOffset),
|
| - Add<HConstant>(isolate()->factory()->empty_fixed_array()));
|
| + empty_fixed_array);
|
| Add<HStoreNamedField>(
|
| result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
|
| - elements);
|
| + empty_fixed_array);
|
| Add<HStoreNamedField>(
|
| result, HObjectAccess::ForJSArrayOffset(JSArray::kLengthOffset), length);
|
|
|
| @@ -1584,18 +1579,22 @@ HValue* HGraphBuilder::BuildRegExpConstructResult(HValue* length,
|
| result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kInputOffset),
|
| input);
|
|
|
| - // Initialize the elements header.
|
| - AddStoreMapConstant(elements, isolate()->factory()->fixed_array_map());
|
| - Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(), length);
|
| + // Allocate and initialize the elements header.
|
| + HAllocate* elements = BuildAllocateElements(elements_kind, size);
|
| + BuildInitializeElementsHeader(elements, elements_kind, length);
|
| +
|
| + HConstant* size_in_bytes_upper_bound = EstablishElementsAllocationSize(
|
| + elements_kind, max_length->Integer32Value());
|
| + elements->set_size_upper_bound(size_in_bytes_upper_bound);
|
| +
|
| + Add<HStoreNamedField>(
|
| + result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
|
| + elements);
|
|
|
| // Initialize the elements contents with undefined.
|
| - LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
|
| - index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT);
|
| - {
|
| - Add<HStoreKeyed>(elements, index, graph()->GetConstantUndefined(),
|
| - FAST_ELEMENTS);
|
| - }
|
| - loop.EndBody();
|
| + BuildFillElementsWithValue(
|
| + elements, elements_kind, graph()->GetConstant0(), length,
|
| + graph()->GetConstantUndefined());
|
|
|
| return result;
|
| }
|
| @@ -2228,17 +2227,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();
|
| @@ -2268,32 +2269,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;
|
| +}
|
| +
|
| +
|
| +HAllocate* HGraphBuilder::AllocateJSArrayObject(AllocationSiteMode mode) {
|
| + int base_size = JSArray::kSize;
|
| + if (mode == TRACK_ALLOCATION_SITE) {
|
| + base_size += AllocationMemento::kSize;
|
| + }
|
| + HConstant* size_in_bytes = Add<HConstant>(base_size);
|
| + return Add<HAllocate>(
|
| + size_in_bytes, HType::JSArray(), NOT_TENURED, JS_OBJECT_TYPE);
|
| +}
|
| +
|
| +
|
| +HConstant* HGraphBuilder::EstablishElementsAllocationSize(
|
| + ElementsKind kind,
|
| + int capacity) {
|
| + int base_size = IsFastDoubleElementsKind(kind)
|
| + ? FixedDoubleArray::SizeFor(capacity)
|
| + : FixedArray::SizeFor(capacity);
|
|
|
| - return Add<HAllocate>(total_size, HType::HeapObject(), NOT_TENURED,
|
| + return Add<HConstant>(base_size);
|
| +}
|
| +
|
| +
|
| +HAllocate* HGraphBuilder::BuildAllocateElements(ElementsKind kind,
|
| + HValue* size_in_bytes) {
|
| + InstanceType instance_type = IsFastDoubleElementsKind(kind)
|
| + ? FIXED_DOUBLE_ARRAY_TYPE
|
| + : FIXED_ARRAY_TYPE;
|
| +
|
| + return Add<HAllocate>(size_in_bytes, HType::HeapObject(), NOT_TENURED,
|
| instance_type);
|
| }
|
|
|
| @@ -2318,43 +2348,39 @@ 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);
|
| 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,
|
| + HValue* elements,
|
| + 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(),
|
| + elements != NULL ? elements : 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), HType::HeapObject());
|
| - Add<HStoreNamedField>(array, HObjectAccess::ForElementsPointer(), elements);
|
| - return elements;
|
| }
|
|
|
|
|
| @@ -2391,6 +2417,12 @@ HInstruction* HGraphBuilder::AddElementAccess(
|
| }
|
|
|
|
|
| +HLoadNamedField* HGraphBuilder::AddLoadMap(HValue* object,
|
| + HValue* dependency) {
|
| + return Add<HLoadNamedField>(object, dependency, HObjectAccess::ForMap());
|
| +}
|
| +
|
| +
|
| HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object,
|
| HValue* dependency) {
|
| return Add<HLoadNamedField>(
|
| @@ -2443,7 +2475,7 @@ HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
|
| HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader(
|
| new_kind, new_capacity);
|
|
|
| - BuildCopyElements(object, elements, kind, new_elements,
|
| + BuildCopyElements(elements, kind, new_elements,
|
| new_kind, length, new_capacity);
|
|
|
| Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
|
| @@ -2453,19 +2485,11 @@ HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
|
| }
|
|
|
|
|
| -void HGraphBuilder::BuildFillElementsWithHole(HValue* elements,
|
| - ElementsKind elements_kind,
|
| - HValue* from,
|
| - HValue* to) {
|
| - // Fast elements kinds need to be initialized in case statements below cause a
|
| - // garbage collection.
|
| - Factory* factory = isolate()->factory();
|
| -
|
| - double nan_double = FixedDoubleArray::hole_nan_as_double();
|
| - HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
|
| - ? Add<HConstant>(factory->the_hole_value())
|
| - : Add<HConstant>(nan_double);
|
| -
|
| +void HGraphBuilder::BuildFillElementsWithValue(HValue* elements,
|
| + ElementsKind elements_kind,
|
| + HValue* from,
|
| + HValue* to,
|
| + HValue* value) {
|
| if (to == NULL) {
|
| to = AddLoadFixedArrayLength(elements);
|
| }
|
| @@ -2492,7 +2516,7 @@ void HGraphBuilder::BuildFillElementsWithHole(HValue* elements,
|
| if (initial_capacity >= 0) {
|
| for (int i = 0; i < initial_capacity; i++) {
|
| HInstruction* key = Add<HConstant>(i);
|
| - Add<HStoreKeyed>(elements, key, hole, elements_kind);
|
| + Add<HStoreKeyed>(elements, key, value, elements_kind);
|
| }
|
| } else {
|
| // Carefully loop backwards so that the "from" remains live through the loop
|
| @@ -2506,15 +2530,31 @@ void HGraphBuilder::BuildFillElementsWithHole(HValue* elements,
|
| HValue* adjusted_key = AddUncasted<HSub>(key, graph()->GetConstant1());
|
| adjusted_key->ClearFlag(HValue::kCanOverflow);
|
|
|
| - Add<HStoreKeyed>(elements, adjusted_key, hole, elements_kind);
|
| + Add<HStoreKeyed>(elements, adjusted_key, value, elements_kind);
|
|
|
| builder.EndBody();
|
| }
|
| }
|
|
|
|
|
| -void HGraphBuilder::BuildCopyElements(HValue* array,
|
| - HValue* from_elements,
|
| +void HGraphBuilder::BuildFillElementsWithHole(HValue* elements,
|
| + ElementsKind elements_kind,
|
| + HValue* from,
|
| + HValue* to) {
|
| + // Fast elements kinds need to be initialized in case statements below cause a
|
| + // garbage collection.
|
| + Factory* factory = isolate()->factory();
|
| +
|
| + double nan_double = FixedDoubleArray::hole_nan_as_double();
|
| + HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
|
| + ? Add<HConstant>(factory->the_hole_value())
|
| + : Add<HConstant>(nan_double);
|
| +
|
| + BuildFillElementsWithValue(elements, elements_kind, from, to, hole);
|
| +}
|
| +
|
| +
|
| +void HGraphBuilder::BuildCopyElements(HValue* from_elements,
|
| ElementsKind from_elements_kind,
|
| HValue* to_elements,
|
| ElementsKind to_elements_kind,
|
| @@ -2601,88 +2641,43 @@ void HGraphBuilder::BuildCopyElements(HValue* array,
|
| AddIncrementCounter(counters->inlined_copied_elements());
|
| }
|
|
|
| -HValue* HGraphBuilder::BuildCloneShallowArrayCommon(
|
| - HValue* boilerplate,
|
| - HValue* allocation_site,
|
| - HValue* extra_size,
|
| - HValue** return_elements,
|
| - AllocationSiteMode mode) {
|
| - // All sizes here are multiples of kPointerSize.
|
| - int array_size = JSArray::kSize;
|
| - if (mode == TRACK_ALLOCATION_SITE) {
|
| - array_size += AllocationMemento::kSize;
|
| - }
|
| -
|
| - HValue* size_in_bytes = Add<HConstant>(array_size);
|
| - if (extra_size != NULL) {
|
| - size_in_bytes = AddUncasted<HAdd>(extra_size, size_in_bytes);
|
| - size_in_bytes->ClearFlag(HValue::kCanOverflow);
|
| - }
|
| -
|
| - HInstruction* object = Add<HAllocate>(size_in_bytes,
|
| - HType::JSObject(),
|
| - NOT_TENURED,
|
| - JS_OBJECT_TYPE);
|
| -
|
| - // Copy the JS array part.
|
| - HValue* map = Add<HLoadNamedField>(boilerplate,
|
| - static_cast<HValue*>(NULL), HObjectAccess::ForMap());
|
| - Add<HStoreNamedField>(object, HObjectAccess::ForPropertiesPointer(),
|
| - Add<HConstant>(isolate()->factory()->empty_fixed_array()),
|
| - INITIALIZING_STORE);
|
| - Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map,
|
| - INITIALIZING_STORE);
|
| -
|
| - // Create an allocation site info if requested.
|
| - if (mode == TRACK_ALLOCATION_SITE) {
|
| - BuildCreateAllocationMemento(
|
| - object, Add<HConstant>(JSArray::kSize), allocation_site);
|
| - }
|
| -
|
| - if (extra_size != NULL) {
|
| - HValue* elements = Add<HInnerAllocatedObject>(object,
|
| - Add<HConstant>(array_size), HType::HeapObject());
|
| - if (return_elements != NULL) *return_elements = elements;
|
| - }
|
| -
|
| - return object;
|
| -}
|
| -
|
|
|
| HValue* HGraphBuilder::BuildCloneShallowArrayCow(HValue* boilerplate,
|
| HValue* allocation_site,
|
| AllocationSiteMode mode,
|
| ElementsKind kind) {
|
| - HValue* result = BuildCloneShallowArrayCommon(boilerplate,
|
| - allocation_site, NULL, NULL, mode);
|
| + HAllocate* array = AllocateJSArrayObject(mode);
|
|
|
| + HValue* map = AddLoadMap(boilerplate);
|
| HValue* elements = AddLoadElements(boilerplate);
|
| - HObjectAccess access = HObjectAccess::ForElementsPointer();
|
| - Add<HStoreNamedField>(result, access, elements, INITIALIZING_STORE);
|
| -
|
| HValue* length = AddLoadArrayLength(boilerplate, kind);
|
| - access = HObjectAccess::ForArrayLength(kind);
|
| - Add<HStoreNamedField>(result, access, length, INITIALIZING_STORE);
|
|
|
| - return result;
|
| + BuildJSArrayHeader(array,
|
| + map,
|
| + elements,
|
| + mode,
|
| + FAST_ELEMENTS,
|
| + allocation_site,
|
| + length);
|
| + return array;
|
| }
|
|
|
|
|
| HValue* HGraphBuilder::BuildCloneShallowArrayEmpty(HValue* boilerplate,
|
| HValue* allocation_site,
|
| AllocationSiteMode mode) {
|
| - HValue* result = BuildCloneShallowArrayCommon(boilerplate,
|
| - allocation_site, NULL, NULL, mode);
|
| + HAllocate* array = AllocateJSArrayObject(mode);
|
|
|
| - HObjectAccess access = HObjectAccess::ForArrayLength(FAST_ELEMENTS);
|
| - Add<HStoreNamedField>(result, access, graph()->GetConstant0(),
|
| - INITIALIZING_STORE);
|
| - access = HObjectAccess::ForElementsPointer();
|
| - Add<HStoreNamedField>(result, access,
|
| - Add<HConstant>(isolate()->factory()->empty_fixed_array()),
|
| - INITIALIZING_STORE);
|
| + HValue* map = AddLoadMap(boilerplate);
|
|
|
| - return result;
|
| + BuildJSArrayHeader(array,
|
| + map,
|
| + NULL, // set elements to empty fixed array
|
| + mode,
|
| + FAST_ELEMENTS,
|
| + allocation_site,
|
| + graph()->GetConstant0());
|
| + return array;
|
| }
|
|
|
|
|
| @@ -2690,27 +2685,31 @@ HValue* HGraphBuilder::BuildCloneShallowArrayNonEmpty(HValue* boilerplate,
|
| HValue* allocation_site,
|
| AllocationSiteMode mode,
|
| ElementsKind kind) {
|
| - int elements_kind_size = IsFastDoubleElementsKind(kind)
|
| - ? kDoubleSize : kPointerSize;
|
| -
|
| HValue* boilerplate_elements = AddLoadElements(boilerplate);
|
| HValue* capacity = AddLoadFixedArrayLength(boilerplate_elements);
|
| - HValue* extra = AddUncasted<HMul>(capacity,
|
| - Add<HConstant>(elements_kind_size));
|
| - extra->ClearFlag(HValue::kCanOverflow);
|
| - extra = AddUncasted<HAdd>(extra, Add<HConstant>(FixedArray::kHeaderSize));
|
| - extra->ClearFlag(HValue::kCanOverflow);
|
| +
|
| + // Generate size calculation code here in order to make it dominate
|
| + // the JSArray allocation.
|
| + HValue* elements_size = BuildCalculateElementsSize(kind, capacity);
|
| +
|
| + // Create empty JSArray object for now, store elimination should remove
|
| + // redundant initialization of elements and length fields and at the same
|
| + // time the object will be fully prepared for GC if it happens during
|
| + // elements allocation.
|
| + HValue* result = BuildCloneShallowArrayEmpty(
|
| + boilerplate, allocation_site, mode);
|
| +
|
| + HAllocate* elements = BuildAllocateElements(kind, elements_size);
|
| +
|
| // This function implicitly relies on the fact that the
|
| // FastCloneShallowArrayStub is called only for literals shorter than
|
| - // JSObject::kInitialMaxFastElementArray and therefore the size of the
|
| - // resulting folded allocation will always be in allowed range.
|
| + // JSObject::kInitialMaxFastElementArray.
|
| // Can't add HBoundsCheck here because otherwise the stub will eager a frame.
|
| + HConstant* size_upper_bound = EstablishElementsAllocationSize(
|
| + kind, JSObject::kInitialMaxFastElementArray);
|
| + elements->set_size_upper_bound(size_upper_bound);
|
|
|
| - HValue* elements = NULL;
|
| - HValue* result = BuildCloneShallowArrayCommon(boilerplate,
|
| - allocation_site, extra, &elements, mode);
|
| - Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(),
|
| - elements, INITIALIZING_STORE);
|
| + Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(), elements);
|
|
|
| // The allocation for the cloned array above causes register pressure on
|
| // machines with low register counts. Force a reload of the boilerplate
|
| @@ -2724,19 +2723,15 @@ HValue* HGraphBuilder::BuildCloneShallowArrayNonEmpty(HValue* boilerplate,
|
| HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i);
|
| Add<HStoreNamedField>(elements, access,
|
| Add<HLoadNamedField>(boilerplate_elements,
|
| - static_cast<HValue*>(NULL), access),
|
| - INITIALIZING_STORE);
|
| + static_cast<HValue*>(NULL), access));
|
| }
|
|
|
| // And the result of the length
|
| - HValue* length = Add<HLoadNamedField>(boilerplate, static_cast<HValue*>(NULL),
|
| - HObjectAccess::ForArrayLength(kind));
|
| - Add<HStoreNamedField>(result, HObjectAccess::ForArrayLength(kind),
|
| - length, INITIALIZING_STORE);
|
| + HValue* length = AddLoadArrayLength(boilerplate, kind);
|
| + Add<HStoreNamedField>(result, HObjectAccess::ForArrayLength(kind), length);
|
|
|
| - BuildCopyElements(result, boilerplate_elements, kind, elements,
|
| + BuildCopyElements(boilerplate_elements, kind, elements,
|
| kind, length, NULL);
|
| -
|
| return result;
|
| }
|
|
|
| @@ -2931,67 +2926,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,
|
| + 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 (!elements_location_->has_size_upper_bound()) {
|
| + 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.
|
| @@ -3001,14 +2976,14 @@ HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes,
|
| length_field =
|
| builder()->AddUncasted<HForceRepresentation>(length_field,
|
| Representation::Smi());
|
| - // Allocate (dealing with failure appropriately)
|
| - HAllocate* new_object = builder()->Add<HAllocate>(size_in_bytes,
|
| - 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();
|
| - }
|
| + // 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* array_object = builder()->AllocateJSArrayObject(mode_);
|
|
|
| // Fill in the fields: map, properties, length
|
| HValue* map;
|
| @@ -3017,22 +2992,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,
|
| + NULL, // set elements to empty fixed array
|
| + mode_,
|
| + kind_,
|
| + allocation_site_payload_,
|
| + length_field);
|
| +
|
| + // Allocate and initialize the elements
|
| + elements_location_ = builder()->BuildAllocateElements(kind_, elements_size);
|
| +
|
| 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;
|
| }
|
|
|
|
|
| @@ -10247,7 +10230,7 @@ HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
|
| HConstant* empty_fixed_array = Add<HConstant>(
|
| isolate()->factory()->empty_fixed_array());
|
| Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
|
| - empty_fixed_array, INITIALIZING_STORE);
|
| + empty_fixed_array);
|
|
|
| BuildEmitObjectHeader(boilerplate_object, object);
|
|
|
|
|