Reviewers: Michael Starzinger,

Message:
Feel free to tell me this SparseMove() is getting too hacky. This is mostly an
attempt to see what it would take to be spec-compliant.

Description:
Correctly handle Array unshift/splices that move elements past the max length of
an Array

BUG=v8:2615
LOG=n

Please review this at https://codereview.chromium.org/679113003/

Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files (+17, -41 lines):
  M src/array.js
  D test/mjsunit/bugs/bug-2615.js
  A + test/mjsunit/regress/regress-splice-large-index.js


Index: test/mjsunit/bugs/bug-2615.js
diff --git a/test/mjsunit/bugs/bug-2615.js b/test/mjsunit/bugs/bug-2615.js
deleted file mode 100644
index 5da17eecf1fa57699af86521adefc3fbe62a262f..0000000000000000000000000000000000000000
--- a/test/mjsunit/bugs/bug-2615.js
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2013 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-var a = [];
-a[0xfffffffe] = 10;
-assertThrows("a.unshift(1);", RangeError);
-assertEquals(0xffffffff, a.length);
-assertEquals(10, a[0xffffffff]);
-assertEquals(undefined, a[0xfffffffe]);
-
-a = [1,2,3];
-a[0xfffffffe] = 10;
-assertThrows("a.splice(1,1,7,7,7,7,7);", RangeError);
-assertEquals([1,7,7,7,7,7,3], a.slice(0, 7));
-assertEquals(0xffffffff, a.length);
-assertEquals(10, a[0xfffffffe + 5 - 1]);
Index: src/array.js
diff --git a/src/array.js b/src/array.js
index 29fa8318e2bfee8c8cfa4ba95af4da5bd777590e..ff14b3583f2ba5ee08b2f37015eff889a642a53e 100644
--- a/src/array.js
+++ b/src/array.js
@@ -238,7 +238,10 @@ function SparseMove(array, start_i, del_count, len, num_additional_args) {
   // Bail out if no moving is necessary.
   if (num_additional_args === del_count) return;
   // Move data to new array.
-  var new_array = new InternalArray(len - del_count + num_additional_args);
+  var new_array = new InternalArray(
+      // Clamp array length to 2^32-1 to avoid early RangeError.
+      MathMin(len - del_count + num_additional_args, 0xffffffff));
+  var big_indices;
   var indices = %GetArrayKeys(array, len);
   if (IS_NUMBER(indices)) {
     var limit = indices;
@@ -267,7 +270,12 @@ function SparseMove(array, start_i, del_count, len, num_additional_args) {
         } else if (key >= start_i + del_count) {
           var current = array[key];
           if (!IS_UNDEFINED(current) || key in array) {
-            new_array[key - del_count + num_additional_args] = current;
+            var new_key = key - del_count + num_additional_args;
+            new_array[new_key] = current;
+            if (new_key > 0xffffffff) {
+              big_indices = big_indices || new InternalArray();
+              big_indices.push(new_key);
+            }
           }
         }
       }
@@ -275,6 +283,14 @@ function SparseMove(array, start_i, del_count, len, num_additional_args) {
   }
   // Move contents of new_array into this array
   %MoveArrayContents(new_array, array);
+  // Add any moved values that aren't elements anymore.
+  if (!IS_UNDEFINED(big_indices)) {
+    var length = big_indices.length;
+    for (var i = 0; i < length; ++i) {
+      var key = big_indices[i];
+      array[key] = new_array[key];
+    }
+  }
 }


Index: test/mjsunit/regress/regress-splice-large-index.js
diff --git a/test/mjsunit/bugs/bug-2615.js b/test/mjsunit/regress/regress-splice-large-index.js
similarity index 100%
rename from test/mjsunit/bugs/bug-2615.js
rename to test/mjsunit/regress/regress-splice-large-index.js


--
--
v8-dev mailing list
v8-dev@googlegroups.com
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to v8-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to