| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 0e9b95e690b8fcc2d72757452c50d490467e3bc4..ee233c23b94ee6d05074a7f0ee258c8d160084e8 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -1296,6 +1296,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,
|
| @@ -1319,17 +1337,28 @@ 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[] = { 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);
|
|
|