| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 0651e71a081873c57e8399cd2681853415368804..faed77533c5c7eb67842ee7ec7ce00dc618b3ceb 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -1277,6 +1277,24 @@ HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) {
|
| }
|
|
|
|
|
| +HValue* HGraphBuilder::BuildCheckAndGrowElementsCapacity(HValue* object,
|
| + HValue* elements,
|
| + ElementsKind kind,
|
| + HValue* length,
|
| + HValue* capacity,
|
| + HValue* key) {
|
| + HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap));
|
| + HValue* max_capacity = AddUncasted<HAdd>(capacity, max_gap);
|
| + Add<HBoundsCheck>(key, max_capacity);
|
| +
|
| + HValue* new_capacity = BuildNewElementsCapacity(key);
|
| + HValue* new_elements = BuildGrowElementsCapacity(object, elements,
|
| + kind, kind, length,
|
| + new_capacity);
|
| + return new_elements;
|
| +}
|
| +
|
| +
|
| HValue* HGraphBuilder::BuildCheckForCapacityGrow(
|
| HValue* object,
|
| HValue* elements,
|
| @@ -1300,19 +1318,29 @@ HValue* HGraphBuilder::BuildCheckForCapacityGrow(
|
| Token::GTE);
|
| capacity_checker.Then();
|
|
|
| - HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap));
|
| - HValue* max_capacity = AddUncasted<HAdd>(current_capacity, max_gap);
|
| -
|
| - Add<HBoundsCheck>(key, max_capacity);
|
| -
|
| - HValue* new_capacity = BuildNewElementsCapacity(key);
|
| - HValue* new_elements = BuildGrowElementsCapacity(object, elements,
|
| - kind, kind, length,
|
| - new_capacity);
|
| + // BuildCheckAndGrowElementsCapacity could de-opt without profitable feedback,
|
| + // therefore we defer calling it to a stub in optimized functions. It is
|
| + // okay to call directly in a code stub though, because a bailout to the
|
| + // runtime is tolerable in the corner cases.
|
| + if (top_info()->IsStub()) {
|
| + environment()->Push(
|
| + BuildCheckAndGrowElementsCapacity(object, elements, kind, length,
|
| + current_capacity, key));
|
| + } else {
|
| + GrowArrayElementsStub stub(isolate(), is_js_array, kind);
|
| + CodeStubInterfaceDescriptor* descriptor =
|
| + isolate()->code_stub_interface_descriptor(CodeStub::GrowArrayElements);
|
| + HConstant* target = Add<HConstant>(stub.GetCode());
|
| + HValue* op_vals[] = { object, key, current_capacity };
|
| + HValue* new_elements = Add<HCallWithDescriptor>(
|
| + target, 0, descriptor, Vector<HValue*>(op_vals, 3));
|
| + // If the object changed to a dictionary, GrowArrayElements will return a
|
| + // smi to signal that deopt is required.
|
| + Add<HCheckHeapObject>(new_elements);
|
| + environment()->Push(new_elements);
|
| + }
|
|
|
| - environment()->Push(new_elements);
|
| capacity_checker.Else();
|
| -
|
| environment()->Push(elements);
|
| capacity_checker.End();
|
|
|
| @@ -2683,7 +2711,7 @@ HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
|
| HValue* new_capacity) {
|
| Add<HBoundsCheck>(new_capacity, Add<HConstant>(
|
| (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) >>
|
| - ElementsKindToShiftSize(kind)));
|
| + ElementsKindToShiftSize(new_kind)));
|
|
|
| HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader(
|
| new_kind, new_capacity);
|
|
|