Commit 61d2ebde authored by antonm@chromium.org's avatar antonm@chromium.org

Fix invalid fast return in splice when returned array is empty.

TBR=vitalyr@chromium.org

Review URL: http://codereview.chromium.org/669101

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4027 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 56eb46e0
...@@ -616,30 +616,34 @@ BUILTIN(ArraySplice) { ...@@ -616,30 +616,34 @@ BUILTIN(ArraySplice) {
} }
} }
int actualDeleteCount = Min(Max(deleteCount, 0), len - actualStart); int actualDeleteCount = Min(Max(deleteCount, 0), len - actualStart);
if (actualDeleteCount == 0) {
return AllocateEmptyJSArray();
}
// Allocate result array. FixedArray* elms = FixedArray::cast(array->elements());
Object* result = AllocateJSArray();
if (result->IsFailure()) return result;
JSArray* result_array = JSArray::cast(result);
result = Heap::AllocateUninitializedFixedArray(actualDeleteCount); JSArray* result_array = NULL;
if (result->IsFailure()) return result; if (actualDeleteCount == 0) {
FixedArray* result_elms = FixedArray::cast(result); 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);
FixedArray* elms = FixedArray::cast(array->elements()); result = Heap::AllocateUninitializedFixedArray(actualDeleteCount);
if (result->IsFailure()) return result;
FixedArray* result_elms = FixedArray::cast(result);
AssertNoAllocation no_gc; AssertNoAllocation no_gc;
// Fill newly created array. // Fill newly created array.
CopyElements(&no_gc, result_elms, 0, elms, actualStart, actualDeleteCount); CopyElements(&no_gc, result_elms, 0, elms, actualStart, actualDeleteCount);
// Set elements. // Set elements.
result_array->set_elements(result_elms); result_array->set_elements(result_elms);
// Set the length. // Set the length.
result_array->set_length(Smi::FromInt(actualDeleteCount)); result_array->set_length(Smi::FromInt(actualDeleteCount));
}
int itemCount = (n_arguments > 1) ? (n_arguments - 2) : 0; int itemCount = (n_arguments > 1) ? (n_arguments - 2) : 0;
...@@ -647,6 +651,7 @@ BUILTIN(ArraySplice) { ...@@ -647,6 +651,7 @@ BUILTIN(ArraySplice) {
if (itemCount < actualDeleteCount) { if (itemCount < actualDeleteCount) {
// Shrink the array. // Shrink the array.
AssertNoAllocation no_gc;
MoveElements(&no_gc, MoveElements(&no_gc,
elms, actualStart + itemCount, elms, actualStart + itemCount,
elms, actualStart + actualDeleteCount, elms, actualStart + actualDeleteCount,
...@@ -667,6 +672,7 @@ BUILTIN(ArraySplice) { ...@@ -667,6 +672,7 @@ BUILTIN(ArraySplice) {
if (obj->IsFailure()) return obj; if (obj->IsFailure()) return obj;
FixedArray* new_elms = FixedArray::cast(obj); FixedArray* new_elms = FixedArray::cast(obj);
AssertNoAllocation no_gc;
// Copy the part before actualStart as is. // Copy the part before actualStart as is.
CopyElements(&no_gc, new_elms, 0, elms, 0, actualStart); CopyElements(&no_gc, new_elms, 0, elms, 0, actualStart);
FillWithHoles(new_elms, new_length, capacity); FillWithHoles(new_elms, new_length, capacity);
...@@ -676,12 +682,14 @@ BUILTIN(ArraySplice) { ...@@ -676,12 +682,14 @@ BUILTIN(ArraySplice) {
array->set_elements(elms); array->set_elements(elms);
} }
AssertNoAllocation no_gc;
MoveElements(&no_gc, MoveElements(&no_gc,
elms, actualStart + itemCount, elms, actualStart + itemCount,
source_elms, actualStart + actualDeleteCount, source_elms, actualStart + actualDeleteCount,
(len - actualDeleteCount - actualStart)); (len - actualDeleteCount - actualStart));
} }
AssertNoAllocation no_gc;
WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
for (int k = actualStart; k < actualStart + itemCount; k++) { for (int k = actualStart; k < actualStart + itemCount; k++) {
elms->set(k, args[3 + k - actualStart], mode); elms->set(k, args[3 + k - actualStart], mode);
......
...@@ -53,6 +53,16 @@ ...@@ -53,6 +53,16 @@
})(); })();
// Check that even if result array is empty, receiver gets sliced.
(function() {
for (var i = 0; i < 7; i++) {
var a = [1, 2, 3];
assertEquals([], a.splice(1, 0, 'a', 'b', 'c'));
assertEquals([1, 'a', 'b', 'c', 2, 3], a);
}
})();
// Check various forms of arguments omission. // Check various forms of arguments omission.
(function() { (function() {
var array; var array;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment