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