| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 937f5b086b41029a1e4c70130ae3953cca3d1fe8..6d07c7e4415209f52a10be1cc8ac046ccfec8245 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -1300,6 +1300,20 @@ 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,
|
| @@ -1323,17 +1337,27 @@ 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()) {
|
| + HValue* new_elements = BuildCheckAndGrowElementsCapacity(
|
| + object, elements, kind, length, current_capacity, key);
|
| + environment()->Push(new_elements);
|
| + } else {
|
| + GrowArrayElementsStub stub(isolate(), is_js_array, kind);
|
| + GrowArrayElementsDescriptor descriptor(isolate());
|
| + HConstant* target = Add<HConstant>(stub.GetCode());
|
| + HValue* op_vals[] = {context(), object, key, current_capacity};
|
| + HValue* new_elements = Add<HCallWithDescriptor>(
|
| + target, 0, descriptor, Vector<HValue*>(op_vals, 4));
|
| + // 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);
|
|
|