Revision: 4027
Author: [email protected]
Date: Thu Mar 4 14:16:58 2010
Log: Fix invalid fast return in splice when returned array is empty.
[email protected]
Review URL: http://codereview.chromium.org/669101
http://code.google.com/p/v8/source/detail?r=4027
Modified:
/branches/bleeding_edge/src/builtins.cc
/branches/bleeding_edge/test/mjsunit/array-splice.js
=======================================
--- /branches/bleeding_edge/src/builtins.cc Thu Mar 4 13:29:33 2010
+++ /branches/bleeding_edge/src/builtins.cc Thu Mar 4 14:16:58 2010
@@ -616,30 +616,34 @@
}
}
int actualDeleteCount = Min(Max(deleteCount, 0), len - actualStart);
- if (actualDeleteCount == 0) {
- return AllocateEmptyJSArray();
- }
-
- // Allocate result array.
- Object* result = AllocateJSArray();
- if (result->IsFailure()) return result;
- JSArray* result_array = JSArray::cast(result);
-
- result = Heap::AllocateUninitializedFixedArray(actualDeleteCount);
- if (result->IsFailure()) return result;
- FixedArray* result_elms = FixedArray::cast(result);
-
- FixedArray* elms = FixedArray::cast(array->elements());
-
- AssertNoAllocation no_gc;
- // Fill newly created array.
- CopyElements(&no_gc, result_elms, 0, elms, actualStart,
actualDeleteCount);
-
- // Set elements.
- result_array->set_elements(result_elms);
-
- // Set the length.
- result_array->set_length(Smi::FromInt(actualDeleteCount));
+
+ FixedArray* elms = FixedArray::cast(array->elements());
+
+ JSArray* result_array = NULL;
+ if (actualDeleteCount == 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);
+
+ result = Heap::AllocateUninitializedFixedArray(actualDeleteCount);
+ if (result->IsFailure()) return result;
+ FixedArray* result_elms = FixedArray::cast(result);
+
+ AssertNoAllocation no_gc;
+ // Fill newly created array.
+ CopyElements(&no_gc, result_elms, 0, elms, actualStart,
actualDeleteCount);
+
+ // Set elements.
+ result_array->set_elements(result_elms);
+
+ // Set the length.
+ result_array->set_length(Smi::FromInt(actualDeleteCount));
+ }
int itemCount = (n_arguments > 1) ? (n_arguments - 2) : 0;
@@ -647,6 +651,7 @@
if (itemCount < actualDeleteCount) {
// Shrink the array.
+ AssertNoAllocation no_gc;
MoveElements(&no_gc,
elms, actualStart + itemCount,
elms, actualStart + actualDeleteCount,
@@ -667,6 +672,7 @@
if (obj->IsFailure()) return obj;
FixedArray* new_elms = FixedArray::cast(obj);
+ AssertNoAllocation no_gc;
// Copy the part before actualStart as is.
CopyElements(&no_gc, new_elms, 0, elms, 0, actualStart);
FillWithHoles(new_elms, new_length, capacity);
@@ -676,12 +682,14 @@
array->set_elements(elms);
}
+ AssertNoAllocation no_gc;
MoveElements(&no_gc,
elms, actualStart + itemCount,
source_elms, actualStart + actualDeleteCount,
(len - actualDeleteCount - actualStart));
}
+ AssertNoAllocation no_gc;
WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
for (int k = actualStart; k < actualStart + itemCount; k++) {
elms->set(k, args[3 + k - actualStart], mode);
=======================================
--- /branches/bleeding_edge/test/mjsunit/array-splice.js Thu Mar 4
13:29:33 2010
+++ /branches/bleeding_edge/test/mjsunit/array-splice.js Thu Mar 4
14:16:58 2010
@@ -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.
(function() {
var array;
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev