From 40e176056d9640635d3bbc9f4e63b50ccc9057bc Mon Sep 17 00:00:00 2001 From: jgruber <jgruber@chromium.org> Date: Wed, 7 Dec 2016 05:05:30 -0800 Subject: [PATCH] [regexp] Shrink results array in @@match and @@split Both @@match and @@split internally use dynamically growing fixed arrays. Shrink to fit when wrapping these in a JSArray to avoid excessive memory usage. BUG=chromium:670205,chromium:670708 Review-Url: https://codereview.chromium.org/2556773002 Cr-Commit-Position: refs/heads/master@{#41550} --- src/builtins/builtins-regexp.cc | 36 +++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/src/builtins/builtins-regexp.cc b/src/builtins/builtins-regexp.cc index 86871d24c1..6196f6d93a 100644 --- a/src/builtins/builtins-regexp.cc +++ b/src/builtins/builtins-regexp.cc @@ -1386,7 +1386,7 @@ class GrowableFixedArray { a->Bind(&grow); { Node* const new_capacity = NewCapacity(a, capacity); - Node* const new_array = GrowFixedArray(capacity, new_capacity, mode); + Node* const new_array = ResizeFixedArray(length, new_capacity, mode); var_capacity_.Bind(new_capacity); var_array_.Bind(new_array); @@ -1407,10 +1407,28 @@ class GrowableFixedArray { CodeStubAssembler* a = assembler_; const ElementsKind kind = FAST_ELEMENTS; + const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS; Node* const native_context = a->LoadNativeContext(context); Node* const array_map = a->LoadJSArrayElementsMap(kind, native_context); + // Shrink to fit if necessary. + { + Label next(a); + + Node* const length = var_length_.value(); + Node* const capacity = var_capacity_.value(); + + a->GotoIf(a->WordEqual(length, capacity), &next); + + Node* const array = ResizeFixedArray(length, length, mode); + var_array_.Bind(array); + var_capacity_.Bind(length); + a->Goto(&next); + + a->Bind(&next); + } + Node* const result_length = a->SmiTag(length()); Node* const result = a->AllocateUninitializedJSArrayWithoutElements( kind, array_map, result_length, nullptr); @@ -1454,14 +1472,17 @@ class GrowableFixedArray { return new_capacity; } - Node* GrowFixedArray(Node* const current_capacity, Node* const new_capacity, - ParameterMode mode) { + // Creates a new array with {new_capacity} and copies the first + // {element_count} elements from the current array. + Node* ResizeFixedArray(Node* const element_count, Node* const new_capacity, + ParameterMode mode) { DCHECK(mode == CodeStubAssembler::INTPTR_PARAMETERS); CodeStubAssembler* a = assembler_; - CSA_ASSERT(a, a->IntPtrGreaterThan(current_capacity, a->IntPtrConstant(0))); - CSA_ASSERT(a, a->IntPtrGreaterThan(new_capacity, current_capacity)); + CSA_ASSERT(a, a->IntPtrGreaterThan(element_count, a->IntPtrConstant(0))); + CSA_ASSERT(a, a->IntPtrGreaterThan(new_capacity, a->IntPtrConstant(0))); + CSA_ASSERT(a, a->IntPtrGreaterThanOrEqual(new_capacity, element_count)); const ElementsKind kind = FAST_ELEMENTS; const WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER; @@ -1471,9 +1492,8 @@ class GrowableFixedArray { Node* const from_array = var_array_.value(); Node* const to_array = a->AllocateFixedArray(kind, new_capacity, mode, flags); - a->CopyFixedArrayElements(kind, from_array, kind, to_array, - current_capacity, new_capacity, barrier_mode, - mode); + a->CopyFixedArrayElements(kind, from_array, kind, to_array, element_count, + new_capacity, barrier_mode, mode); return to_array; }