Chromium Code Reviews| Index: src/builtins.cc |
| diff --git a/src/builtins.cc b/src/builtins.cc |
| index f40b5c27741787d5869fd3e0a61e92bb917d3bf1..5fbe000f87f7d7745390880d3ae61fc1a9f338e1 100644 |
| --- a/src/builtins.cc |
| +++ b/src/builtins.cc |
| @@ -336,6 +336,7 @@ static FixedArray* LeftTrimFixedArray(FixedArray* elms, int to_trim) { |
| // In old space we do not use this trick to avoid dealing with |
| // remembered sets. |
| ASSERT(Heap::new_space()->Contains(elms)); |
| + ASSERT(to_trim > 0); |
| STATIC_ASSERT(FixedArray::kMapOffset == 0); |
| STATIC_ASSERT(FixedArray::kLengthOffset == kPointerSize); |
| @@ -718,97 +719,138 @@ BUILTIN(ArraySplice) { |
| } |
| int actual_delete_count = Min(Max(delete_count, 0), len - actual_start); |
| + int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0; |
| + |
| + int new_length = len - actual_delete_count + item_count; |
| + |
| JSArray* result_array = NULL; |
| - if (actual_delete_count == 0) { |
| - Object* result = AllocateEmptyJSArray(); |
| - if (result->IsFailure()) return result; |
| - result_array = JSArray::cast(result); |
| - } else { |
| - // Allocate result array. |
| + if (Heap::new_space()->Contains(elms) && |
| + (2 * actual_delete_count >= len + item_count)) { |
|
antonm
2010/04/05 12:21:13
looks like you're trying to keep the number of wri
iegorov
2010/04/05 13:01:49
My counts differ:
- when making inplace (terminolo
antonm
2010/04/05 14:34:30
Sorry, I should have been explicit but I didn't ac
|
| + // Allocate array for receiver's array. |
| Object* result = AllocateJSArray(); |
| if (result->IsFailure()) return result; |
| result_array = JSArray::cast(result); |
| - result = Heap::AllocateUninitializedFixedArray(actual_delete_count); |
| + result = Heap::AllocateUninitializedFixedArray(new_length); |
| if (result->IsFailure()) return result; |
| - FixedArray* result_elms = FixedArray::cast(result); |
| + FixedArray* receiver_elms = FixedArray::cast(result); |
| - AssertNoAllocation no_gc; |
| - // Fill newly created array. |
| - CopyElements(&no_gc, |
| - result_elms, 0, |
| - elms, actual_start, |
| - actual_delete_count); |
| + int tail_length = len - actual_start - actual_delete_count; |
| + ASSERT(tail_length >= 0); |
| - // Set elements. |
| - result_array->set_elements(result_elms); |
| + AssertNoAllocation no_gc; |
| + // Fill with receiver elements. |
| + if (actual_start > 0) { |
| + CopyElements(&no_gc, |
| + receiver_elms, 0, |
| + elms, 0, |
| + actual_start); |
| + } |
| + if (tail_length > 0) { |
| + CopyElements(&no_gc, |
| + receiver_elms, actual_start + item_count, |
| + elms, actual_start + actual_delete_count, |
| + tail_length); |
| + } |
| + array->set_elements(receiver_elms); |
| + array->set_length(Smi::FromInt(new_length)); |
| - // Set the length. |
| + if (actual_start > 0) { |
| + elms = LeftTrimFixedArray(elms, actual_start); |
|
antonm
2010/04/05 12:21:13
good you noticed that---was going to bring your at
iegorov
2010/04/05 13:01:49
Yeah, testing rocks :)
On 2010/04/05 12:21:13, ant
|
| + } |
| + result_array->set_elements(elms, SKIP_WRITE_BARRIER); |
| result_array->set_length(Smi::FromInt(actual_delete_count)); |
| - } |
| + FillWithHoles(elms, actual_delete_count, len - actual_start); |
| - int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0; |
| - |
| - int new_length = len - actual_delete_count + item_count; |
| + elms = receiver_elms; |
| + } else { |
| + if (actual_delete_count == 0) { |
| + Object* result = AllocateEmptyJSArray(); |
| + if (result->IsFailure()) return result; |
| + result_array = JSArray::cast(result); |
| + } else { |
| + // Allocate result array. |
| + Object* result = AllocateJSArray(); |
| + if (result->IsFailure()) return result; |
| + result_array = JSArray::cast(result); |
| - if (item_count < actual_delete_count) { |
| - // Shrink the array. |
| - const bool trim_array = Heap::new_space()->Contains(elms) && |
| - ((actual_start + item_count) < |
| - (len - actual_delete_count - actual_start)); |
| - if (trim_array) { |
| - const int delta = actual_delete_count - item_count; |
| - |
| - if (actual_start > 0) { |
| - Object** start = elms->data_start(); |
| - memmove(start + delta, start, actual_start * kPointerSize); |
| - } |
| + result = Heap::AllocateUninitializedFixedArray(actual_delete_count); |
| + if (result->IsFailure()) return result; |
| + FixedArray* result_elms = FixedArray::cast(result); |
| - elms = LeftTrimFixedArray(elms, delta); |
| - array->set_elements(elms, SKIP_WRITE_BARRIER); |
| - } else { |
| AssertNoAllocation no_gc; |
| - MoveElements(&no_gc, |
| - elms, actual_start + item_count, |
| - elms, actual_start + actual_delete_count, |
| - (len - actual_delete_count - actual_start)); |
| - FillWithHoles(elms, new_length, len); |
| + // Fill newly created array. |
| + CopyElements(&no_gc, |
| + result_elms, 0, |
| + elms, actual_start, |
| + actual_delete_count); |
| + |
| + // Set elements. |
| + result_array->set_elements(result_elms); |
| + |
| + // Set the length. |
| + result_array->set_length(Smi::FromInt(actual_delete_count)); |
| } |
| - } else if (item_count > actual_delete_count) { |
| - // Currently fixed arrays cannot grow too big, so |
| - // we should never hit this case. |
| - ASSERT((item_count - actual_delete_count) <= (Smi::kMaxValue - len)); |
| - |
| - // Check if array need to grow. |
| - if (new_length > elms->length()) { |
| - // New backing storage is needed. |
| - int capacity = new_length + (new_length >> 1) + 16; |
| - Object* obj = Heap::AllocateUninitializedFixedArray(capacity); |
| - if (obj->IsFailure()) return obj; |
| - FixedArray* new_elms = FixedArray::cast(obj); |
| - AssertNoAllocation no_gc; |
| - // Copy the part before actual_start as is. |
| - if (actual_start > 0) { |
| - CopyElements(&no_gc, new_elms, 0, elms, 0, actual_start); |
| - } |
| - const int to_copy = len - actual_delete_count - actual_start; |
| - if (to_copy > 0) { |
| - CopyElements(&no_gc, |
| - new_elms, actual_start + item_count, |
| + if (item_count < actual_delete_count) { |
| + // Shrink the array. |
| + const bool trim_array = Heap::new_space()->Contains(elms) && |
| + ((actual_start + item_count) < |
| + (len - actual_delete_count - actual_start)); |
| + if (trim_array) { |
| + const int delta = actual_delete_count - item_count; |
| + |
| + if (actual_start > 0) { |
| + Object** start = elms->data_start(); |
| + memmove(start + delta, start, actual_start * kPointerSize); |
| + } |
| + |
| + elms = LeftTrimFixedArray(elms, delta); |
| + array->set_elements(elms, SKIP_WRITE_BARRIER); |
| + } else { |
| + AssertNoAllocation no_gc; |
| + MoveElements(&no_gc, |
| + elms, actual_start + item_count, |
| elms, actual_start + actual_delete_count, |
| - to_copy); |
| + (len - actual_delete_count - actual_start)); |
| + FillWithHoles(elms, new_length, len); |
| } |
| - FillWithHoles(new_elms, new_length, capacity); |
| + } else if (item_count > actual_delete_count) { |
| + // Currently fixed arrays cannot grow too big, so |
| + // we should never hit this case. |
| + ASSERT((item_count - actual_delete_count) <= (Smi::kMaxValue - len)); |
| + |
| + // Check if array need to grow. |
| + if (new_length > elms->length()) { |
| + // New backing storage is needed. |
| + int capacity = new_length + (new_length >> 1) + 16; |
| + Object* obj = Heap::AllocateUninitializedFixedArray(capacity); |
| + if (obj->IsFailure()) return obj; |
| + FixedArray* new_elms = FixedArray::cast(obj); |
| - elms = new_elms; |
| - array->set_elements(elms); |
| - } else { |
| - AssertNoAllocation no_gc; |
| - MoveElements(&no_gc, |
| - elms, actual_start + item_count, |
| - elms, actual_start + actual_delete_count, |
| - (len - actual_delete_count - actual_start)); |
| + AssertNoAllocation no_gc; |
| + // Copy the part before actual_start as is. |
| + if (actual_start > 0) { |
| + CopyElements(&no_gc, new_elms, 0, elms, 0, actual_start); |
| + } |
| + const int to_copy = len - actual_delete_count - actual_start; |
| + if (to_copy > 0) { |
| + CopyElements(&no_gc, |
| + new_elms, actual_start + item_count, |
| + elms, actual_start + actual_delete_count, |
| + to_copy); |
| + } |
| + FillWithHoles(new_elms, new_length, capacity); |
| + |
| + elms = new_elms; |
| + array->set_elements(elms); |
| + } else { |
| + AssertNoAllocation no_gc; |
| + MoveElements(&no_gc, |
| + elms, actual_start + item_count, |
| + elms, actual_start + actual_delete_count, |
| + (len - actual_delete_count - actual_start)); |
| + } |
| } |
| } |