1ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com// Copyright 2012 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
5c2e08d7d6b03e672e13fc3bf274a292009decce6machenbach@chromium.org"use strict";
6c2e08d7d6b03e672e13fc3bf274a292009decce6machenbach@chromium.org
743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// This file relies on the fact that the following declarations have been made
843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// in runtime.js:
9f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org// var $Array = global.Array;
1043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// -------------------------------------------------------------------
1243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Global list of arrays visited during toString, toLocaleString and
1443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// join invocations.
158f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.orgvar visited_arrays = new InternalArray();
1643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Gets a sorted array of array keys.  Useful for operations on sparse
1943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// arrays.  Dupes have not been removed.
20f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.orgfunction GetSortedArrayKeys(array, indices) {
21f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  var keys = new InternalArray();
22f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  if (IS_NUMBER(indices)) {
23f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    // It's an interval
24f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    var limit = indices;
25f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    for (var i = 0; i < limit; ++i) {
26f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      var e = array[i];
27f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      if (!IS_UNDEFINED(e) || i in array) {
28f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org        keys.push(i);
2943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
30f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    }
31f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  } else {
32f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    var length = indices.length;
33f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    for (var k = 0; k < length; ++k) {
34f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      var key = indices[k];
3543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      if (!IS_UNDEFINED(key)) {
3643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        var e = array[key];
3743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        if (!IS_UNDEFINED(e) || key in array) {
3843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          keys.push(key);
3943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
4043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
4143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
42f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    %_CallFunction(keys, function(a, b) { return a - b; }, ArraySort);
4343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
4443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return keys;
4543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
4643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
48aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.orgfunction SparseJoinWithSeparatorJS(array, len, convert, separator) {
498e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, len));
508e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  var totalLength = 0;
518e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  var elements = new InternalArray(keys.length * 2);
528e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  var previousKey = -1;
538e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  for (var i = 0; i < keys.length; i++) {
548e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org    var key = keys[i];
558e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org    if (key != previousKey) {  // keys may contain duplicates.
568e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org      var e = array[key];
578e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org      if (!IS_STRING(e)) e = convert(e);
588e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org      elements[i * 2] = key;
598e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org      elements[i * 2 + 1] = e;
608e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org      previousKey = key;
618e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org    }
628e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  }
638e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  return %SparseJoinWithSeparator(elements, len, separator);
648e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org}
658e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org
668e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org
6743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Optimized for sparse arrays if separator is ''.
6843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction SparseJoin(array, len, convert) {
6943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, len));
7043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  var last_key = -1;
7143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  var keys_length = keys.length;
720c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
738f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  var elements = new InternalArray(keys_length);
740c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  var elements_length = 0;
750c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
7643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  for (var i = 0; i < keys_length; i++) {
7743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    var key = keys[i];
7843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (key != last_key) {
7943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      var e = array[key];
800c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org      if (!IS_STRING(e)) e = convert(e);
810c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org      elements[elements_length++] = e;
8243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      last_key = key;
8343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
8443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
850c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  return %StringBuilderConcat(elements, elements_length, '');
8643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
8743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
8843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
892b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgfunction UseSparseVariant(array, length, is_array, touched) {
902b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org  // Only use the sparse variant on arrays that are likely to be sparse and the
912b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org  // number of elements touched in the operation is relatively small compared to
922b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org  // the overall size of the array.
932b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org  if (!is_array || length < 1000 || %IsObserved(array)) {
942b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    return false;
952b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org  }
962b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org  if (!%_IsSmi(length)) {
972b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    return true;
982b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org  }
992b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org  var elements_threshold = length >> 2;  // No more than 75% holes
1002b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org  var estimated_elements = %EstimateNumberOfElements(array);
1012b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org  return (estimated_elements < elements_threshold) &&
1022b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    (touched > estimated_elements * 4);
10343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
10443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
10543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
10643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction Join(array, length, separator, convert) {
10743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (length == 0) return '';
10843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
10943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  var is_array = IS_ARRAY(array);
11043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
11143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (is_array) {
11243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // If the array is cyclic, return the empty string for already
11343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // visited arrays.
1149258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org    if (!%PushIfAbsent(visited_arrays, array)) return '';
11543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
11643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
11743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Attempt to convert the elements.
11843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  try {
1192b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    if (UseSparseVariant(array, length, is_array, length)) {
1202b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org      %NormalizeElements(array);
1218e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org      if (separator.length == 0) {
1228e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org        return SparseJoin(array, length, convert);
1238e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org      } else {
124aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org        return SparseJoinWithSeparatorJS(array, length, convert, separator);
1258e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org      }
12643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
12743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1289258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org    // Fast case for one-element arrays.
1299258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org    if (length == 1) {
1309258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org      var e = array[0];
131c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org      if (IS_STRING(e)) return e;
132c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org      return convert(e);
1339258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org    }
1349258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org
1350c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    // Construct an array for the elements.
1368f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    var elements = new InternalArray(length);
13743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
138ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org    // We pull the empty separator check outside the loop for speed!
139ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org    if (separator.length == 0) {
140c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org      var elements_length = 0;
141ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org      for (var i = 0; i < length; i++) {
142ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org        var e = array[i];
1438e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org        if (!IS_STRING(e)) e = convert(e);
1448e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org        elements[elements_length++] = e;
145ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org      }
146d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      elements.length = elements_length;
1472c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      var result = %_FastOneByteArrayJoin(elements, '');
148d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      if (!IS_UNDEFINED(result)) return result;
149d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      return %StringBuilderConcat(elements, elements_length, '');
150d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    }
151c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    // Non-empty separator case.
1528f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    // If the first element is a number then use the heuristic that the
153c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    // remaining elements are also likely to be numbers.
154c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    if (!IS_NUMBER(array[0])) {
155c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org      for (var i = 0; i < length; i++) {
156c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org        var e = array[i];
157d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        if (!IS_STRING(e)) e = convert(e);
158d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        elements[i] = e;
15943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
1608f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    } else {
161c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org      for (var i = 0; i < length; i++) {
162c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org        var e = array[i];
163c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        if (IS_NUMBER(e)) {
164c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org          e = %_NumberToString(e);
165c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        } else if (!IS_STRING(e)) {
166c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org          e = convert(e);
167c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        }
168c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        elements[i] = e;
169c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org      }
1708f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    }
1712c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    var result = %_FastOneByteArrayJoin(elements, separator);
1728f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    if (!IS_UNDEFINED(result)) return result;
173d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org
17449edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org    return %StringBuilderJoin(elements, length, separator);
17543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } finally {
17631b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org    // Make sure to remove the last element of the visited array no
17731b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org    // matter what happens.
17831b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org    if (is_array) visited_arrays.length = visited_arrays.length - 1;
17943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
18041044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
18143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
18243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1835f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.orgfunction ConvertToString(x) {
1848f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  // Assumes x is a non-string.
1855f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  if (IS_NUMBER(x)) return %_NumberToString(x);
1865f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
1875f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  return (IS_NULL_OR_UNDEFINED(x)) ? '' : %ToString(%DefaultString(x));
18841044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
18943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
19043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
19143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction ConvertToLocaleString(e) {
192c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (IS_NULL_OR_UNDEFINED(e)) {
1930c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    return '';
1940c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  } else {
1952efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org    // According to ES5, section 15.4.4.3, the toLocaleString conversion
196c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // must throw a TypeError if ToObject(e).toLocaleString isn't
197c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // callable.
19843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    var e_obj = ToObject(e);
199c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    return %ToString(e_obj.toLocaleString());
20043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
20141044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
20243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
20343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
20443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// This function implements the optimized splice implementation that can use
20543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// special array operations to handle sparse arrays in a sensible fashion.
20643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction SmartSlice(array, start_i, del_count, len, deleted_elements) {
20743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Move deleted elements to a new array (the return value from splice).
208f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  var indices = %GetArrayKeys(array, start_i + del_count);
209f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  if (IS_NUMBER(indices)) {
210f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    var limit = indices;
211f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    for (var i = start_i; i < limit; ++i) {
212f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      var current = array[i];
213f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      if (!IS_UNDEFINED(current) || i in array) {
214f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org        deleted_elements[i - start_i] = current;
21543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
216f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    }
217f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  } else {
218f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    var length = indices.length;
219f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    for (var k = 0; k < length; ++k) {
220f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      var key = indices[k];
22143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      if (!IS_UNDEFINED(key)) {
22243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        if (key >= start_i) {
22343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          var current = array[key];
22443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          if (!IS_UNDEFINED(current) || key in array) {
22543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            deleted_elements[key - start_i] = current;
22643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          }
22743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
22843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
22943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
23043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
23141044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
23243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
23343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
23443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// This function implements the optimized splice implementation that can use
23543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// special array operations to handle sparse arrays in a sensible fashion.
23643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction SmartMove(array, start_i, del_count, len, num_additional_args) {
23743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Move data to new array.
2388f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  var new_array = new InternalArray(len - del_count + num_additional_args);
239f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  var indices = %GetArrayKeys(array, len);
240f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  if (IS_NUMBER(indices)) {
241f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    var limit = indices;
242f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    for (var i = 0; i < start_i && i < limit; ++i) {
243f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      var current = array[i];
244f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      if (!IS_UNDEFINED(current) || i in array) {
245f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org        new_array[i] = current;
24643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
247f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    }
248f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    for (var i = start_i + del_count; i < limit; ++i) {
249f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      var current = array[i];
250f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      if (!IS_UNDEFINED(current) || i in array) {
251f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org        new_array[i - del_count + num_additional_args] = current;
25243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
253f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    }
254f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  } else {
255f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    var length = indices.length;
256f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    for (var k = 0; k < length; ++k) {
257f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      var key = indices[k];
25843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      if (!IS_UNDEFINED(key)) {
25943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        if (key < start_i) {
26043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          var current = array[key];
2619258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org          if (!IS_UNDEFINED(current) || key in array) {
26243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            new_array[key] = current;
2639258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org          }
26443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        } else if (key >= start_i + del_count) {
26543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          var current = array[key];
2669258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org          if (!IS_UNDEFINED(current) || key in array) {
26743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            new_array[key - del_count + num_additional_args] = current;
2689258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org          }
26943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
27043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
27143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
27243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
27343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Move contents of new_array into this array
27443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  %MoveArrayContents(new_array, array);
27541044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
27643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
27743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
27843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// This is part of the old simple-minded splice.  We are using it either
27943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// because the receiver is not an array (so we have no choice) or because we
28043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// know we are not deleting or moving a lot of elements.
28143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction SimpleSlice(array, start_i, del_count, len, deleted_elements) {
28243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  for (var i = 0; i < del_count; i++) {
28343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    var index = start_i + i;
284fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org    // The spec could also be interpreted such that %HasOwnProperty
28543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // would be the appropriate test.  We follow KJS in consulting the
28643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // prototype.
28743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    var current = array[index];
2881b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    if (!IS_UNDEFINED(current) || index in array) {
28943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      deleted_elements[i] = current;
2901b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    }
29143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
29241044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
29343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
29443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
29543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction SimpleMove(array, start_i, del_count, len, num_additional_args) {
29643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (num_additional_args !== del_count) {
29743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // Move the existing elements after the elements to be deleted
29843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // to the right position in the resulting array.
29943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (num_additional_args > del_count) {
30043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      for (var i = len - del_count; i > start_i; i--) {
30143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        var from_index = i + del_count - 1;
30243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        var to_index = i + num_additional_args - 1;
30343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        // The spec could also be interpreted such that
304fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org        // %HasOwnProperty would be the appropriate test.  We follow
30543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        // KJS in consulting the prototype.
30643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        var current = array[from_index];
30743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        if (!IS_UNDEFINED(current) || from_index in array) {
30843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          array[to_index] = current;
30943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        } else {
31043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          delete array[to_index];
31143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
31243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
31343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    } else {
31443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      for (var i = start_i; i < len - del_count; i++) {
31543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        var from_index = i + del_count;
31643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        var to_index = i + num_additional_args;
31743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        // The spec could also be interpreted such that
318fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org        // %HasOwnProperty would be the appropriate test.  We follow
31943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        // KJS in consulting the prototype.
32043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        var current = array[from_index];
32143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        if (!IS_UNDEFINED(current) || from_index in array) {
32243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          array[to_index] = current;
32343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        } else {
32443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          delete array[to_index];
32543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
32643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
32743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      for (var i = len; i > len - del_count + num_additional_args; i--) {
32843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        delete array[i - 1];
32943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
33043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
33143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
33241044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
33343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
33443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
33543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// -------------------------------------------------------------------
33643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
33743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
33843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction ArrayToString() {
339c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  var array;
340c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  var func;
341c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (IS_ARRAY(this)) {
342c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    func = this.join;
343c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    if (func === ArrayJoin) {
344c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      return Join(this, this.length, ',', ConvertToString);
345c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
346c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    array = this;
347c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  } else {
348c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    array = ToObject(this);
349c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    func = array.join;
35043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
351c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (!IS_SPEC_FUNCTION(func)) {
352c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    return %_CallFunction(array, ObjectToString);
353c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
354c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  return %_CallFunction(array, func);
35541044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
35643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
35743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
35843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction ArrayToLocaleString() {
359c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  var array = ToObject(this);
360c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  var arrayLen = array.length;
361c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  var len = TO_UINT32(arrayLen);
362c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (len === 0) return "";
363c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  return Join(array, len, ',', ConvertToLocaleString);
36441044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
36543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
36643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
36743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction ArrayJoin(separator) {
36857a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.join");
3691c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
370a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  var array = TO_OBJECT_INLINE(this);
371a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  var length = TO_UINT32(array.length);
3720c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  if (IS_UNDEFINED(separator)) {
3730c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    separator = ',';
3740c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  } else if (!IS_STRING(separator)) {
3755f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org    separator = NonStringToString(separator);
3760c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  }
37721b5e95db1c650dfc2ba8e11d010bb01293f85c5vegorov@chromium.org
3782c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  var result = %_FastOneByteArrayJoin(array, separator);
379a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  if (!IS_UNDEFINED(result)) return result;
38021b5e95db1c650dfc2ba8e11d010bb01293f85c5vegorov@chromium.org
381a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  return Join(array, length, separator, ConvertToString);
38241044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
38343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
38443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
385b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.orgfunction ObservedArrayPop(n) {
386b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  n--;
387b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  var value = this[n];
388b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
389b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  try {
390b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    BeginPerformSplice(this);
391b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    delete this[n];
392b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    this.length = n;
393b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  } finally {
394b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    EndPerformSplice(this);
395528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    EnqueueSpliceRecord(this, n, [value], 0);
396b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  }
397b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
398b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  return value;
399b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org}
400b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
40143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Removes the last element from the array and returns it. See
40243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// ECMA-262, section 15.4.4.6.
40343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction ArrayPop() {
40457a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.pop");
4051c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
406b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org  var array = TO_OBJECT_INLINE(this);
407b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org  var n = TO_UINT32(array.length);
40843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (n == 0) {
409b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org    array.length = n;
41043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return;
41143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
412b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
413b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org  if (%IsObserved(array))
414b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org    return ObservedArrayPop.call(array, n);
415b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
41643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  n--;
417b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org  var value = array[n];
418b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org  Delete(array, ToName(n), true);
419b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org  array.length = n;
42043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return value;
42141044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
42243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
42343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4244e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.orgfunction ObservedArrayPush() {
4254e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  var n = TO_UINT32(this.length);
4264e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  var m = %_ArgumentsLength();
4274e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
4284e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  try {
4294e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    BeginPerformSplice(this);
4304e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    for (var i = 0; i < m; i++) {
4314e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      this[i+n] = %_Arguments(i);
4324e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    }
4335b080567cf135f6dbaf23973ba6b6fa1d6af83b3machenbach@chromium.org    var new_length = n + m;
4345b080567cf135f6dbaf23973ba6b6fa1d6af83b3machenbach@chromium.org    this.length = new_length;
4354e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  } finally {
4364e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    EndPerformSplice(this);
437528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    EnqueueSpliceRecord(this, n, [], m);
4384e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  }
4394e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
4405b080567cf135f6dbaf23973ba6b6fa1d6af83b3machenbach@chromium.org  return new_length;
4414e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org}
4424e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
44343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Appends the arguments to the end of the array and returns the new
44443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// length of the array. See ECMA-262, section 15.4.4.7.
44543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction ArrayPush() {
44657a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.push");
4471c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
4484e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  if (%IsObserved(this))
4494e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    return ObservedArrayPush.apply(this, arguments);
4504e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
451b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org  var array = TO_OBJECT_INLINE(this);
452b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org  var n = TO_UINT32(array.length);
453b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org  var m = %_ArgumentsLength();
454b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org
45543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  for (var i = 0; i < m; i++) {
4566fbe38f254bead420fb1c779e97dbeb71e92d23cyangguo@chromium.org    array[i+n] = %_Arguments(i);
45743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
4585b080567cf135f6dbaf23973ba6b6fa1d6af83b3machenbach@chromium.org
4595b080567cf135f6dbaf23973ba6b6fa1d6af83b3machenbach@chromium.org  var new_length = n + m;
460b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org  array.length = new_length;
4615b080567cf135f6dbaf23973ba6b6fa1d6af83b3machenbach@chromium.org  return new_length;
46241044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
46343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
46443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
465ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com// Returns an array containing the array elements of the object followed
466ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com// by the array elements of each argument in order. See ECMA-262,
467ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com// section 15.4.4.7.
468aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.orgfunction ArrayConcatJS(arg1) {  // length == 1
46957a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.concat");
4701c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
471ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  var array = ToObject(this);
4729bbf968a649030335309265ba2c98fcc36aeb762kasperl@chromium.org  var arg_count = %_ArgumentsLength();
4738f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  var arrays = new InternalArray(1 + arg_count);
474ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  arrays[0] = array;
4759bbf968a649030335309265ba2c98fcc36aeb762kasperl@chromium.org  for (var i = 0; i < arg_count; i++) {
4769bbf968a649030335309265ba2c98fcc36aeb762kasperl@chromium.org    arrays[i + 1] = %_Arguments(i);
47743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
47843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4799bbf968a649030335309265ba2c98fcc36aeb762kasperl@chromium.org  return %ArrayConcat(arrays);
48041044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
48143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
48243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
48343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// For implementing reverse() on large, sparse arrays.
48443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction SparseReverse(array, len) {
48543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, len));
48643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  var high_counter = keys.length - 1;
48743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  var low_counter = 0;
48843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  while (low_counter <= high_counter) {
48943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    var i = keys[low_counter];
49043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    var j = keys[high_counter];
49143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
49243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    var j_complement = len - j - 1;
49343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    var low, high;
49443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
49543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (j_complement <= i) {
49643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      high = j;
4971b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      while (keys[--high_counter] == j) { }
49843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      low = j_complement;
49943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
50043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (j_complement >= i) {
50143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      low = i;
5021b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      while (keys[++low_counter] == i) { }
50343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      high = len - i - 1;
50443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
50543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
50643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    var current_i = array[low];
50743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (!IS_UNDEFINED(current_i) || low in array) {
50843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      var current_j = array[high];
50943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      if (!IS_UNDEFINED(current_j) || high in array) {
51043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        array[low] = current_j;
51143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        array[high] = current_i;
51243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      } else {
51343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        array[high] = current_i;
51443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        delete array[low];
51543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
51643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    } else {
51743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      var current_j = array[high];
51843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      if (!IS_UNDEFINED(current_j) || high in array) {
51943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        array[low] = current_j;
52043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        delete array[high];
52143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
52243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
52343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
52443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
52543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
52643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
52743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction ArrayReverse() {
52857a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.reverse");
5291c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
530a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  var array = TO_OBJECT_INLINE(this);
5312b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org  var len = TO_UINT32(array.length);
53243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
5332b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org  if (UseSparseVariant(array, len, IS_ARRAY(array), len)) {
5342b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    %NormalizeElements(array);
5352b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    SparseReverse(array, len);
536a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org    return array;
53743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
53843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
5392b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org  var j = len - 1;
54043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  for (var i = 0; i < j; i++, j--) {
541a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org    var current_i = array[i];
542a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org    if (!IS_UNDEFINED(current_i) || i in array) {
543a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org      var current_j = array[j];
544a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org      if (!IS_UNDEFINED(current_j) || j in array) {
545a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org        array[i] = current_j;
546a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org        array[j] = current_i;
54743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      } else {
548a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org        array[j] = current_i;
549a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org        delete array[i];
55043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
55143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    } else {
552a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org      var current_j = array[j];
553a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org      if (!IS_UNDEFINED(current_j) || j in array) {
554a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org        array[i] = current_j;
555a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org        delete array[j];
55643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
55743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
55843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
559a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  return array;
56041044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
56143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
56243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
563b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.orgfunction ObservedArrayShift(len) {
564b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  var first = this[0];
565b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
566b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  try {
567b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    BeginPerformSplice(this);
568b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    SimpleMove(this, 0, 1, len, 0);
569b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    this.length = len - 1;
570b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  } finally {
571b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    EndPerformSplice(this);
572528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    EnqueueSpliceRecord(this, 0, [first], 0);
573b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  }
574b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
575b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  return first;
576b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org}
577b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
57843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction ArrayShift() {
57957a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.shift");
5801c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
581b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org  var array = TO_OBJECT_INLINE(this);
582b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org  var len = TO_UINT32(array.length);
58341044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
58443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (len === 0) {
585b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org    array.length = 0;
58643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return;
58743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
58841044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
589b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org  if (ObjectIsSealed(array)) {
5908a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org    throw MakeTypeError("array_functions_change_sealed",
5918a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org                        ["Array.prototype.shift"]);
5928a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  }
5938a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org
594b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org  if (%IsObserved(array))
595b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org    return ObservedArrayShift.call(array, len);
596b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
597b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org  var first = array[0];
59841044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
599b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org  if (IS_ARRAY(array)) {
600b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org    SmartMove(array, 0, 1, len, 0);
6011b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  } else {
602b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org    SimpleMove(array, 0, 1, len, 0);
6031b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  }
60441044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
605b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org  array.length = len - 1;
60641044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
60743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return first;
60841044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
60943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
610b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.orgfunction ObservedArrayUnshift() {
611b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  var len = TO_UINT32(this.length);
612b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  var num_arguments = %_ArgumentsLength();
613b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
614b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  try {
615b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    BeginPerformSplice(this);
616b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    SimpleMove(this, 0, 0, len, num_arguments);
617b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    for (var i = 0; i < num_arguments; i++) {
618b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org      this[i] = %_Arguments(i);
619b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    }
6205b080567cf135f6dbaf23973ba6b6fa1d6af83b3machenbach@chromium.org    var new_length = len + num_arguments;
6215b080567cf135f6dbaf23973ba6b6fa1d6af83b3machenbach@chromium.org    this.length = new_length;
622b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  } finally {
623b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    EndPerformSplice(this);
624528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    EnqueueSpliceRecord(this, 0, [], num_arguments);
625b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  }
626b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
6275b080567cf135f6dbaf23973ba6b6fa1d6af83b3machenbach@chromium.org  return new_length;
628b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org}
62943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
63043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction ArrayUnshift(arg1) {  // length == 1
63157a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.unshift");
6321c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
6338a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  if (%IsObserved(this))
6348a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org    return ObservedArrayUnshift.apply(this, arguments);
6358a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org
636b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org  var array = TO_OBJECT_INLINE(this);
637b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org  var len = TO_UINT32(array.length);
638b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org  var num_arguments = %_ArgumentsLength();
639b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org  var is_sealed = ObjectIsSealed(array);
640b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org
641fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org  if (IS_ARRAY(array) && !is_sealed && len > 0) {
642b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org    SmartMove(array, 0, 0, len, num_arguments);
6431b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  } else {
644b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org    SimpleMove(array, 0, 0, len, num_arguments);
6451b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  }
64641044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
64743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  for (var i = 0; i < num_arguments; i++) {
648b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org    array[i] = %_Arguments(i);
64943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
65041044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
6515b080567cf135f6dbaf23973ba6b6fa1d6af83b3machenbach@chromium.org  var new_length = len + num_arguments;
652b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org  array.length = new_length;
6535b080567cf135f6dbaf23973ba6b6fa1d6af83b3machenbach@chromium.org  return new_length;
65441044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
65543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
65643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
65743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction ArraySlice(start, end) {
65857a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.slice");
6591c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
660a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  var array = TO_OBJECT_INLINE(this);
661a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  var len = TO_UINT32(array.length);
66243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  var start_i = TO_INTEGER(start);
66343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  var end_i = len;
66441044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
665690083842e7c67a362017dae50909d4bb0b2a9c2mstarzinger@chromium.org  if (!IS_UNDEFINED(end)) end_i = TO_INTEGER(end);
66641044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
66743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (start_i < 0) {
66843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    start_i += len;
66943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (start_i < 0) start_i = 0;
67043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } else {
67143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (start_i > len) start_i = len;
67243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
67341044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
67443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (end_i < 0) {
67543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    end_i += len;
67643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (end_i < 0) end_i = 0;
67743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } else {
67843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (end_i > len) end_i = len;
67943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
68041044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
68143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  var result = [];
68241044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
68341044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org  if (end_i < start_i) return result;
68441044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
6852b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org  if (UseSparseVariant(array, len, IS_ARRAY(array), end_i - start_i)) {
6862b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    %NormalizeElements(array);
6872b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    %NormalizeElements(result);
688a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org    SmartSlice(array, start_i, end_i - start_i, len, result);
68941044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org  } else {
690a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org    SimpleSlice(array, start_i, end_i - start_i, len, result);
69141044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org  }
69241044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
69343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  result.length = end_i - start_i;
69441044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
69543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return result;
69641044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
69743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
69843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
699b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.orgfunction ComputeSpliceStartIndex(start_i, len) {
70043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (start_i < 0) {
70143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    start_i += len;
702b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    return start_i < 0 ? 0 : start_i;
70343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
70441044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
705b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  return start_i > len ? len : start_i;
706b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org}
707b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
708b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
709b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.orgfunction ComputeSpliceDeleteCount(delete_count, num_arguments, len, start_i) {
7105c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
71131b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org  // given as a request to delete all the elements from the start.
71231b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org  // And it differs from the case of undefined delete count.
71343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // This does not follow ECMA-262, but we do the same for
71443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // compatibility.
71543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  var del_count = 0;
716b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  if (num_arguments == 1)
717b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    return len - start_i;
718b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
719b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  del_count = TO_INTEGER(delete_count);
720b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  if (del_count < 0)
721b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    return 0;
722b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
723b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  if (del_count > len - start_i)
724b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    return len - start_i;
725b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
726b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  return del_count;
727b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org}
72841044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
729b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
730b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.orgfunction ObservedArraySplice(start, delete_count) {
731b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  var num_arguments = %_ArgumentsLength();
732b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  var len = TO_UINT32(this.length);
733b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  var start_i = ComputeSpliceStartIndex(TO_INTEGER(start), len);
734b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  var del_count = ComputeSpliceDeleteCount(delete_count, num_arguments, len,
735b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org                                           start_i);
73643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  var deleted_elements = [];
73743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  deleted_elements.length = del_count;
738b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  var num_elements_to_add = num_arguments > 2 ? num_arguments - 2 : 0;
739b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
740b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  try {
741b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    BeginPerformSplice(this);
74241044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
743b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    SimpleSlice(this, start_i, del_count, len, deleted_elements);
744b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    SimpleMove(this, start_i, del_count, len, num_elements_to_add);
745b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
746b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    // Insert the arguments into the resulting array in
747b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    // place of the deleted elements.
748b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    var i = start_i;
749b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    var arguments_index = 2;
750b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    var arguments_length = %_ArgumentsLength();
751b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    while (arguments_index < arguments_length) {
752b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org      this[i++] = %_Arguments(arguments_index++);
753b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    }
754b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    this.length = len - del_count + num_elements_to_add;
755b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
756b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  } finally {
757b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    EndPerformSplice(this);
758b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    if (deleted_elements.length || num_elements_to_add) {
759b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org       EnqueueSpliceRecord(this,
760b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org                           start_i,
761b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org                           deleted_elements.slice(),
762b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org                           num_elements_to_add);
763b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    }
76443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
76541044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
766b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  // Return the deleted elements.
767b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  return deleted_elements;
768b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org}
769b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
770b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
771b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.orgfunction ArraySplice(start, delete_count) {
77257a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.splice");
77341044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
774b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  if (%IsObserved(this))
775b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    return ObservedArraySplice.apply(this, arguments);
776b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
777b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  var num_arguments = %_ArgumentsLength();
778a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  var array = TO_OBJECT_INLINE(this);
779a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  var len = TO_UINT32(array.length);
780b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  var start_i = ComputeSpliceStartIndex(TO_INTEGER(start), len);
781b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  var del_count = ComputeSpliceDeleteCount(delete_count, num_arguments, len,
782b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org                                           start_i);
783b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  var deleted_elements = [];
784b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  deleted_elements.length = del_count;
785b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  var num_elements_to_add = num_arguments > 2 ? num_arguments - 2 : 0;
786b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
787a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  if (del_count != num_elements_to_add && ObjectIsSealed(array)) {
7888a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org    throw MakeTypeError("array_functions_change_sealed",
7898a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org                        ["Array.prototype.splice"]);
790a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  } else if (del_count > 0 && ObjectIsFrozen(array)) {
7918a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org    throw MakeTypeError("array_functions_on_frozen",
7928a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org                        ["Array.prototype.splice"]);
7938a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  }
7948a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org
7952b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org  var changed_elements = del_count;
7962b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org  if (num_elements_to_add != del_count) {
7972b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    // If the slice needs to do a actually move elements after the insertion
7982b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    // point, then include those in the estimate of changed elements.
7992b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    changed_elements += len - start_i - del_count;
80043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
8012b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org  if (UseSparseVariant(array, len, IS_ARRAY(array), changed_elements)) {
8022b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    %NormalizeElements(array);
8032b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    %NormalizeElements(deleted_elements);
804a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org    SmartSlice(array, start_i, del_count, len, deleted_elements);
805a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org    SmartMove(array, start_i, del_count, len, num_elements_to_add);
8062b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org  } else {
8072b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    SimpleSlice(array, start_i, del_count, len, deleted_elements);
8082b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    SimpleMove(array, start_i, del_count, len, num_elements_to_add);
80943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
81041044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
81143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Insert the arguments into the resulting array in
81243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // place of the deleted elements.
81343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  var i = start_i;
81443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  var arguments_index = 2;
81543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  var arguments_length = %_ArgumentsLength();
81643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  while (arguments_index < arguments_length) {
817a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org    array[i++] = %_Arguments(arguments_index++);
81843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
819a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  array.length = len - del_count + num_elements_to_add;
82041044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
82143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Return the deleted elements.
82243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return deleted_elements;
82341044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
82443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
82543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
82643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction ArraySort(comparefn) {
82757a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.sort");
8281c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
82941044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org  // In-place QuickSort algorithm.
83041044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org  // For short (length <= 22) arrays, insertion sort is used for efficiency.
83143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
83234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  if (!IS_SPEC_FUNCTION(comparefn)) {
833c34f5802a37a9fa2ce8f3929d1d5159ddcf04ff3lrn@chromium.org    comparefn = function (x, y) {
834c34f5802a37a9fa2ce8f3929d1d5159ddcf04ff3lrn@chromium.org      if (x === y) return 0;
835c34f5802a37a9fa2ce8f3929d1d5159ddcf04ff3lrn@chromium.org      if (%_IsSmi(x) && %_IsSmi(y)) {
836c34f5802a37a9fa2ce8f3929d1d5159ddcf04ff3lrn@chromium.org        return %SmiLexicographicCompare(x, y);
837357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org      }
838c34f5802a37a9fa2ce8f3929d1d5159ddcf04ff3lrn@chromium.org      x = ToString(x);
839c34f5802a37a9fa2ce8f3929d1d5159ddcf04ff3lrn@chromium.org      y = ToString(y);
840c34f5802a37a9fa2ce8f3929d1d5159ddcf04ff3lrn@chromium.org      if (x == y) return 0;
841c34f5802a37a9fa2ce8f3929d1d5159ddcf04ff3lrn@chromium.org      else return x < y ? -1 : 1;
842c34f5802a37a9fa2ce8f3929d1d5159ddcf04ff3lrn@chromium.org    };
843357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org  }
8444668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  var receiver = %GetDefaultReceiver(comparefn);
84543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
846f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  var InsertionSort = function InsertionSort(a, from, to) {
84741044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org    for (var i = from + 1; i < to; i++) {
84841044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org      var element = a[i];
849b6e43bb9b1cd7673592be9dfd0a036fe8dab4dcdwhesse@chromium.org      for (var j = i - 1; j >= from; j--) {
850b6e43bb9b1cd7673592be9dfd0a036fe8dab4dcdwhesse@chromium.org        var tmp = a[j];
8514f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org        var order = %_CallFunction(receiver, tmp, element, comparefn);
852b6e43bb9b1cd7673592be9dfd0a036fe8dab4dcdwhesse@chromium.org        if (order > 0) {
853b6e43bb9b1cd7673592be9dfd0a036fe8dab4dcdwhesse@chromium.org          a[j + 1] = tmp;
85441044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org        } else {
855b6e43bb9b1cd7673592be9dfd0a036fe8dab4dcdwhesse@chromium.org          break;
85641044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org        }
85741044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org      }
858b6e43bb9b1cd7673592be9dfd0a036fe8dab4dcdwhesse@chromium.org      a[j + 1] = element;
85941044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org    }
860f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  };
86141044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
8625a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  var GetThirdIndex = function(a, from, to) {
8635a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    var t_array = [];
8645a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    // Use both 'from' and 'to' to determine the pivot candidates.
8655a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    var increment = 200 + ((to - from) & 15);
866a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    for (var i = from + 1, j = 0; i < to - 1; i += increment, j++) {
867a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      t_array[j] = [i, a[i]];
86841044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org    }
869a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    %_CallFunction(t_array, function(a, b) {
870a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      return %_CallFunction(receiver, a[1], b[1], comparefn);
871a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    }, ArraySort);
8725a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    var third_index = t_array[t_array.length >> 1][0];
8735a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    return third_index;
8745a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  }
8755a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
8765a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  var QuickSort = function QuickSort(a, from, to) {
8775a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    var third_index = 0;
8785a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    while (true) {
8795a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      // Insertion sort is faster for short arrays.
8805a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      if (to - from <= 10) {
8815a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        InsertionSort(a, from, to);
8825a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        return;
883023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org      }
8845a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      if (to - from > 1000) {
8855a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        third_index = GetThirdIndex(a, from, to);
8865a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      } else {
8875a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        third_index = from + ((to - from) >> 1);
8885a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      }
8895a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      // Find a pivot as the median of first, last and middle element.
8905a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      var v0 = a[from];
8915a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      var v1 = a[to - 1];
8925a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      var v2 = a[third_index];
8935a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      var c01 = %_CallFunction(receiver, v0, v1, comparefn);
8945a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      if (c01 > 0) {
8955a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        // v1 < v0, so swap them.
8965a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        var tmp = v0;
8975a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        v0 = v1;
8985a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        v1 = tmp;
8995a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      } // v0 <= v1.
9005a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      var c02 = %_CallFunction(receiver, v0, v2, comparefn);
9015a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      if (c02 >= 0) {
9025a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        // v2 <= v0 <= v1.
9035a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        var tmp = v0;
9045a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        v0 = v2;
9055a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        v2 = v1;
9065a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        v1 = tmp;
9075a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      } else {
9085a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        // v0 <= v1 && v0 < v2
9095a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        var c12 = %_CallFunction(receiver, v1, v2, comparefn);
9105a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        if (c12 > 0) {
9115a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org          // v0 <= v2 < v1
9125a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org          var tmp = v1;
9135a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org          v1 = v2;
9145a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org          v2 = tmp;
9155a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        }
9165a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      }
9175a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      // v0 <= v1 <= v2
9185a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      a[from] = v0;
9195a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      a[to - 1] = v2;
9205a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      var pivot = v1;
9215a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      var low_end = from + 1;   // Upper bound of elements lower than pivot.
9225a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      var high_start = to - 1;  // Lower bound of elements greater than pivot.
9235a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      a[third_index] = a[low_end];
9245a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      a[low_end] = pivot;
9255a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
9265a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      // From low_end to i are elements equal to pivot.
9275a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      // From i to high_start are elements that haven't been compared yet.
9285a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      partition: for (var i = low_end + 1; i < high_start; i++) {
9295a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        var element = a[i];
9305a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        var order = %_CallFunction(receiver, element, pivot, comparefn);
931023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org        if (order < 0) {
932d6899c3545b051ec84363203d4235f883b4981bfulan@chromium.org          a[i] = a[low_end];
933d6899c3545b051ec84363203d4235f883b4981bfulan@chromium.org          a[low_end] = element;
934023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org          low_end++;
9355a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        } else if (order > 0) {
9365a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org          do {
9375a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org            high_start--;
9385a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org            if (high_start == i) break partition;
9395a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org            var top_elem = a[high_start];
9405a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org            order = %_CallFunction(receiver, top_elem, pivot, comparefn);
9415a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org          } while (order > 0);
9425a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org          a[i] = a[high_start];
9435a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org          a[high_start] = element;
9445a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org          if (order < 0) {
9455a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org            element = a[i];
9465a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org            a[i] = a[low_end];
9475a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org            a[low_end] = element;
9485a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org            low_end++;
9495a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org          }
950023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org        }
95141044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org      }
9525a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      if (to - high_start < low_end - from) {
9535a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        QuickSort(a, high_start, to);
9545a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        to = low_end;
9555a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      } else {
9565a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        QuickSort(a, from, low_end);
9575a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        from = high_start;
9585a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      }
95941044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org    }
960f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  };
96141044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
962023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  // Copy elements in the range 0..length from obj's prototype chain
963023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  // to obj itself, if obj has holes. Return one more than the maximal index
9645ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org  // of a prototype property.
965f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  var CopyFromPrototype = function CopyFromPrototype(obj, length) {
9665ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org    var max = 0;
967750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    for (var proto = %GetPrototype(obj); proto; proto = %GetPrototype(proto)) {
9685ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org      var indices = %GetArrayKeys(proto, length);
969f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      if (IS_NUMBER(indices)) {
970f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org        // It's an interval.
971f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org        var proto_length = indices;
972f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org        for (var i = 0; i < proto_length; i++) {
973a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org          if (!HAS_OWN_PROPERTY(obj, i) && HAS_OWN_PROPERTY(proto, i)) {
974f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org            obj[i] = proto[i];
975f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org            if (i >= max) { max = i + 1; }
9765ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org          }
977f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org        }
978f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      } else {
979f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org        for (var i = 0; i < indices.length; i++) {
980f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org          var index = indices[i];
981a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org          if (!IS_UNDEFINED(index) && !HAS_OWN_PROPERTY(obj, index)
982a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org              && HAS_OWN_PROPERTY(proto, index)) {
983f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org            obj[index] = proto[index];
984f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org            if (index >= max) { max = index + 1; }
9855ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org          }
9865ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org        }
9875ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org      }
9885ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org    }
9895ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org    return max;
990f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  };
9915ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org
9925ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org  // Set a value of "undefined" on all indices in the range from..to
9935ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org  // where a prototype of obj has an element. I.e., shadow all prototype
9945ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org  // elements in that range.
995f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  var ShadowPrototypeElements = function(obj, from, to) {
996750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    for (var proto = %GetPrototype(obj); proto; proto = %GetPrototype(proto)) {
9975ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org      var indices = %GetArrayKeys(proto, to);
998f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      if (IS_NUMBER(indices)) {
999f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org        // It's an interval.
1000f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org        var proto_length = indices;
1001f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org        for (var i = from; i < proto_length; i++) {
1002a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org          if (HAS_OWN_PROPERTY(proto, i)) {
1003690083842e7c67a362017dae50909d4bb0b2a9c2mstarzinger@chromium.org            obj[i] = UNDEFINED;
10045ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org          }
1005f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org        }
1006f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      } else {
1007f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org        for (var i = 0; i < indices.length; i++) {
1008f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org          var index = indices[i];
1009f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org          if (!IS_UNDEFINED(index) && from <= index &&
1010a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org              HAS_OWN_PROPERTY(proto, index)) {
1011690083842e7c67a362017dae50909d4bb0b2a9c2mstarzinger@chromium.org            obj[index] = UNDEFINED;
10125ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org          }
10135ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org        }
10145ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org      }
101543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
1016f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  };
101743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1018f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  var SafeRemoveArrayHoles = function SafeRemoveArrayHoles(obj) {
1019eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    // Copy defined elements from the end to fill in all holes and undefineds
1020eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    // in the beginning of the array.  Write undefineds and holes at the end
1021eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    // after loop is finished.
1022eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    var first_undefined = 0;
1023eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    var last_defined = length - 1;
1024eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    var num_holes = 0;
1025eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    while (first_undefined < last_defined) {
1026eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org      // Find first undefined element.
1027eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org      while (first_undefined < last_defined &&
1028eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org             !IS_UNDEFINED(obj[first_undefined])) {
1029eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org        first_undefined++;
1030eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org      }
1031eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org      // Maintain the invariant num_holes = the number of holes in the original
1032eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org      // array with indices <= first_undefined or > last_defined.
1033a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      if (!HAS_OWN_PROPERTY(obj, first_undefined)) {
1034eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org        num_holes++;
1035eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org      }
1036eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
1037eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org      // Find last defined element.
1038eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org      while (first_undefined < last_defined &&
1039eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org             IS_UNDEFINED(obj[last_defined])) {
1040a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org        if (!HAS_OWN_PROPERTY(obj, last_defined)) {
1041eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org          num_holes++;
1042eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org        }
1043eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org        last_defined--;
1044eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org      }
1045eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org      if (first_undefined < last_defined) {
1046eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org        // Fill in hole or undefined.
1047eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org        obj[first_undefined] = obj[last_defined];
1048690083842e7c67a362017dae50909d4bb0b2a9c2mstarzinger@chromium.org        obj[last_defined] = UNDEFINED;
1049eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org      }
1050eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    }
1051eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    // If there were any undefineds in the entire array, first_undefined
1052eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    // points to one past the last defined element.  Make this true if
1053eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    // there were no undefineds, as well, so that first_undefined == number
1054eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    // of defined elements.
1055eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    if (!IS_UNDEFINED(obj[first_undefined])) first_undefined++;
1056eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    // Fill in the undefineds and the holes.  There may be a hole where
1057eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    // an undefined should be and vice versa.
1058eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    var i;
1059eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    for (i = first_undefined; i < length - num_holes; i++) {
1060690083842e7c67a362017dae50909d4bb0b2a9c2mstarzinger@chromium.org      obj[i] = UNDEFINED;
1061eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    }
1062eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    for (i = length - num_holes; i < length; i++) {
1063eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org      // For compatability with Webkit, do not expose elements in the prototype.
1064750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org      if (i in %GetPrototype(obj)) {
1065690083842e7c67a362017dae50909d4bb0b2a9c2mstarzinger@chromium.org        obj[i] = UNDEFINED;
1066eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org      } else {
1067eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org        delete obj[i];
1068eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org      }
1069eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    }
1070eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
1071eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    // Return the number of defined elements.
1072eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    return first_undefined;
1073f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  };
1074eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
1075357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org  var length = TO_UINT32(this.length);
10765ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org  if (length < 2) return this;
10775ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org
10785ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org  var is_array = IS_ARRAY(this);
10795ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org  var max_prototype_element;
10805ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org  if (!is_array) {
10815ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org    // For compatibility with JSC, we also sort elements inherited from
10825ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org    // the prototype chain on non-Array objects.
10835ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org    // We do this by copying them to this object and sorting only
1084fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org    // own elements. This is not very efficient, but sorting with
10855ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org    // inherited elements happens very, very rarely, if at all.
10865ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org    // The specification allows "implementation dependent" behavior
10875ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org    // if an element on the prototype chain has an element that
10885ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org    // might interact with sorting.
10895ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org    max_prototype_element = CopyFromPrototype(this, length);
10905ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org  }
10915ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org
109297b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  // %RemoveArrayHoles returns -1 if fast removal is not supported.
109397b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  var num_non_undefined = %RemoveArrayHoles(this, length);
1094c118402c43ae44cf9255d36608a44886c98537c5jkummerow@chromium.org
1095eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  if (num_non_undefined == -1) {
1096c118402c43ae44cf9255d36608a44886c98537c5jkummerow@chromium.org    // The array is observed, or there were indexed accessors in the array.
1097c118402c43ae44cf9255d36608a44886c98537c5jkummerow@chromium.org    // Move array holes and undefineds to the end using a Javascript function
1098c118402c43ae44cf9255d36608a44886c98537c5jkummerow@chromium.org    // that is safe in the presence of accessors and is observable.
1099eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    num_non_undefined = SafeRemoveArrayHoles(this);
1100eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  }
11015ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org
1102c34f5802a37a9fa2ce8f3929d1d5159ddcf04ff3lrn@chromium.org  QuickSort(this, 0, num_non_undefined);
11035ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org
11045ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org  if (!is_array && (num_non_undefined + 1 < max_prototype_element)) {
11055ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org    // For compatibility with JSC, we shadow any elements in the prototype
11065ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org    // chain that has become exposed by sort moving a hole to its position.
11075ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org    ShadowPrototypeElements(this, num_non_undefined, max_prototype_element);
110843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
110943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
111043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return this;
111141044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
111243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
111343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
111443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// The following functions cannot be made efficient on sparse arrays while
111543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// preserving the semantics, since the calls to the receiver function can add
111643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// or delete elements from the array.
111743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction ArrayFilter(f, receiver) {
111857a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.filter");
11191c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
1120a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // Pull out the length so that modifications to the length in the
1121a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // loop will not affect the looping and side effects are visible.
1122a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  var array = ToObject(this);
1123a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  var length = ToUint32(array.length);
1124a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
112534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  if (!IS_SPEC_FUNCTION(f)) {
112643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    throw MakeTypeError('called_non_callable', [ f ]);
112743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
112880c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  if (IS_NULL_OR_UNDEFINED(receiver)) {
112980c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    receiver = %GetDefaultReceiver(f) || receiver;
1130486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  } else if (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(f)) {
1131394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    receiver = ToObject(receiver);
113280c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  }
1133a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
1134394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  var result = new $Array();
1135394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  var accumulator = new InternalArray();
1136394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  var accumulator_length = 0;
1137975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org  var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
1138f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org  for (var i = 0; i < length; i++) {
1139f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org    if (i in array) {
1140f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      var element = array[i];
1141f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      // Prepare break slots for debugger step in.
1142f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      if (stepping) %DebugPrepareStepInIfStepping(f);
1143f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      if (%_CallFunction(receiver, element, i, array, f)) {
1144f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org        accumulator[accumulator_length++] = element;
11458f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org      }
114643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
114743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
1148394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  %MoveArrayContents(accumulator, result);
114943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return result;
115041044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
115143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
115243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
115343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction ArrayForEach(f, receiver) {
115457a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.forEach");
11551c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
1156a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // Pull out the length so that modifications to the length in the
1157a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // loop will not affect the looping and side effects are visible.
1158a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  var array = ToObject(this);
1159a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  var length = TO_UINT32(array.length);
1160a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
116134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  if (!IS_SPEC_FUNCTION(f)) {
116243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    throw MakeTypeError('called_non_callable', [ f ]);
116343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
116480c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  if (IS_NULL_OR_UNDEFINED(receiver)) {
116580c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    receiver = %GetDefaultReceiver(f) || receiver;
1166486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  } else if (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(f)) {
1167394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    receiver = ToObject(receiver);
116880c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  }
1169e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
1170975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org  var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
1171f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org  for (var i = 0; i < length; i++) {
1172f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org    if (i in array) {
1173f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      var element = array[i];
1174f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      // Prepare break slots for debugger step in.
1175f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      if (stepping) %DebugPrepareStepInIfStepping(f);
1176f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      %_CallFunction(receiver, element, i, array, f);
117743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
117843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
117941044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
118043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
118143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
118243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Executes the function once for each element present in the
118343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// array until it finds one where callback returns true.
118443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction ArraySome(f, receiver) {
118557a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.some");
11861c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
1187a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // Pull out the length so that modifications to the length in the
1188a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // loop will not affect the looping and side effects are visible.
1189a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  var array = ToObject(this);
1190a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  var length = TO_UINT32(array.length);
1191a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
119234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  if (!IS_SPEC_FUNCTION(f)) {
119343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    throw MakeTypeError('called_non_callable', [ f ]);
119443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
119580c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  if (IS_NULL_OR_UNDEFINED(receiver)) {
119680c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    receiver = %GetDefaultReceiver(f) || receiver;
1197486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  } else if (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(f)) {
1198394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    receiver = ToObject(receiver);
119980c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  }
1200a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
1201975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org  var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
1202f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org  for (var i = 0; i < length; i++) {
1203f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org    if (i in array) {
1204f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      var element = array[i];
1205f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      // Prepare break slots for debugger step in.
1206f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      if (stepping) %DebugPrepareStepInIfStepping(f);
1207f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      if (%_CallFunction(receiver, element, i, array, f)) return true;
120888d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org    }
120943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
121043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return false;
121141044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
121243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
121343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
121443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction ArrayEvery(f, receiver) {
121557a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.every");
12161c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
1217a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // Pull out the length so that modifications to the length in the
1218a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // loop will not affect the looping and side effects are visible.
1219a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  var array = ToObject(this);
1220a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  var length = TO_UINT32(array.length);
1221a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
122234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  if (!IS_SPEC_FUNCTION(f)) {
122343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    throw MakeTypeError('called_non_callable', [ f ]);
122443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
122580c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  if (IS_NULL_OR_UNDEFINED(receiver)) {
122680c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    receiver = %GetDefaultReceiver(f) || receiver;
1227486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  } else if (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(f)) {
1228394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    receiver = ToObject(receiver);
122980c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  }
1230a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
1231975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org  var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
1232f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org  for (var i = 0; i < length; i++) {
1233f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org    if (i in array) {
1234f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      var element = array[i];
1235f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      // Prepare break slots for debugger step in.
1236f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      if (stepping) %DebugPrepareStepInIfStepping(f);
1237f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      if (!%_CallFunction(receiver, element, i, array, f)) return false;
123888d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org    }
123943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
124043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return true;
124141044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
124243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
124343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction ArrayMap(f, receiver) {
124457a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.map");
12451c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
1246a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // Pull out the length so that modifications to the length in the
1247a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // loop will not affect the looping and side effects are visible.
1248a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  var array = ToObject(this);
1249a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  var length = TO_UINT32(array.length);
1250a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
125134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  if (!IS_SPEC_FUNCTION(f)) {
125243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    throw MakeTypeError('called_non_callable', [ f ]);
125343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
125480c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  if (IS_NULL_OR_UNDEFINED(receiver)) {
125580c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    receiver = %GetDefaultReceiver(f) || receiver;
1256486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  } else if (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(f)) {
1257394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    receiver = ToObject(receiver);
125880c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  }
1259a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
12608f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  var result = new $Array();
12618f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  var accumulator = new InternalArray(length);
1262975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org  var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
1263f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org  for (var i = 0; i < length; i++) {
1264f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org    if (i in array) {
1265f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      var element = array[i];
1266f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      // Prepare break slots for debugger step in.
1267f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      if (stepping) %DebugPrepareStepInIfStepping(f);
1268f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      accumulator[i] = %_CallFunction(receiver, element, i, array, f);
126943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
127043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
12718f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  %MoveArrayContents(accumulator, result);
127243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return result;
127341044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
127443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
127543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
127643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction ArrayIndexOf(element, index) {
127757a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.indexOf");
12781c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
127965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  var length = TO_UINT32(this.length);
128065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (length == 0) return -1;
128140b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  if (IS_UNDEFINED(index)) {
128243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    index = 0;
128343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } else {
128443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    index = TO_INTEGER(index);
128543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // If index is negative, index from the end of the array.
128683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    if (index < 0) {
128783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      index = length + index;
128883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      // If index is still negative, search the entire array.
128983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      if (index < 0) index = 0;
129083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    }
129143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
12922ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  var min = index;
12932ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  var max = length;
12942b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org  if (UseSparseVariant(this, length, IS_ARRAY(this), max - min)) {
12952b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    %NormalizeElements(this);
1296f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    var indices = %GetArrayKeys(this, length);
1297f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    if (IS_NUMBER(indices)) {
1298f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      // It's an interval.
1299f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      max = indices;  // Capped by length already.
13002ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org      // Fall through to loop below.
13012ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    } else {
1302f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      if (indices.length == 0) return -1;
13032ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org      // Get all the keys in sorted order.
1304f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      var sortedKeys = GetSortedArrayKeys(this, indices);
13052ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org      var n = sortedKeys.length;
13062ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org      var i = 0;
13072ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org      while (i < n && sortedKeys[i] < index) i++;
13082ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org      while (i < n) {
13092ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org        var key = sortedKeys[i];
13102ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org        if (!IS_UNDEFINED(key) && this[key] === element) return key;
13112ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org        i++;
13122ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org      }
13132ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org      return -1;
13142ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    }
13152ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  }
131665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Lookup through the array.
1317cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  if (!IS_UNDEFINED(element)) {
13182ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    for (var i = min; i < max; i++) {
1319cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org      if (this[i] === element) return i;
1320cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    }
1321cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    return -1;
1322cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  }
13232ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  // Lookup through the array.
13242ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  for (var i = min; i < max; i++) {
1325cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    if (IS_UNDEFINED(this[i]) && i in this) {
1326cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org      return i;
132743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
132843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
132943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return -1;
133041044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
133143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
133243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
133343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction ArrayLastIndexOf(element, index) {
133457a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.lastIndexOf");
13351c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
133665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  var length = TO_UINT32(this.length);
133765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (length == 0) return -1;
133840b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  if (%_ArgumentsLength() < 2) {
133943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    index = length - 1;
134043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } else {
134143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    index = TO_INTEGER(index);
134243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // If index is negative, index from end of the array.
13432ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    if (index < 0) index += length;
134443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // If index is still negative, do not search the array.
13452ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    if (index < 0) return -1;
134643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    else if (index >= length) index = length - 1;
134743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
13482ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  var min = 0;
13492ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  var max = index;
13502b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org  if (UseSparseVariant(this, length, IS_ARRAY(this), index)) {
13512b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    %NormalizeElements(this);
1352f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    var indices = %GetArrayKeys(this, index + 1);
1353f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    if (IS_NUMBER(indices)) {
1354f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      // It's an interval.
1355f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      max = indices;  // Capped by index already.
13562ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org      // Fall through to loop below.
13572ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    } else {
1358f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      if (indices.length == 0) return -1;
13592ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org      // Get all the keys in sorted order.
1360f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      var sortedKeys = GetSortedArrayKeys(this, indices);
13612ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org      var i = sortedKeys.length - 1;
13622ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org      while (i >= 0) {
13632ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org        var key = sortedKeys[i];
13642ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org        if (!IS_UNDEFINED(key) && this[key] === element) return key;
13652ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org        i--;
13662ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org      }
13672ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org      return -1;
13682ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    }
13692ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  }
137043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Lookup through the array.
1371cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  if (!IS_UNDEFINED(element)) {
13722ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    for (var i = max; i >= min; i--) {
1373cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org      if (this[i] === element) return i;
1374cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    }
1375cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    return -1;
1376cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  }
13772ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  for (var i = max; i >= min; i--) {
1378cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    if (IS_UNDEFINED(this[i]) && i in this) {
1379cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org      return i;
138043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
138143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
138243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return -1;
138341044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
138443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
138543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
138665dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.orgfunction ArrayReduce(callback, current) {
138757a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.reduce");
13881c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
1389a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // Pull out the length so that modifications to the length in the
1390a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // loop will not affect the looping and side effects are visible.
1391a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  var array = ToObject(this);
1392a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  var length = ToUint32(array.length);
1393a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
139434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  if (!IS_SPEC_FUNCTION(callback)) {
139565dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org    throw MakeTypeError('called_non_callable', [callback]);
139665dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org  }
139780c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org
139865dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org  var i = 0;
139965dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org  find_initial: if (%_ArgumentsLength() < 2) {
140065dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org    for (; i < length; i++) {
1401a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org      current = array[i];
1402a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org      if (!IS_UNDEFINED(current) || i in array) {
140365dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org        i++;
140465dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org        break find_initial;
140565dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org      }
140665dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org    }
140765dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org    throw MakeTypeError('reduce_no_initial', []);
140865dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org  }
140965dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org
141080c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  var receiver = %GetDefaultReceiver(callback);
1411975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org  var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(callback);
1412f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org  for (; i < length; i++) {
1413f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org    if (i in array) {
1414f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      var element = array[i];
1415f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      // Prepare break slots for debugger step in.
1416f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      if (stepping) %DebugPrepareStepInIfStepping(callback);
1417f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      current = %_CallFunction(receiver, current, element, i, array, callback);
141888d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org    }
141965dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org  }
142065dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org  return current;
142165dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org}
142265dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org
142365dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.orgfunction ArrayReduceRight(callback, current) {
142457a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.reduceRight");
14251c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
1426a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // Pull out the length so that side effects are visible before the
1427a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // callback function is checked.
1428a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  var array = ToObject(this);
1429a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  var length = ToUint32(array.length);
1430a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
143134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  if (!IS_SPEC_FUNCTION(callback)) {
143265dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org    throw MakeTypeError('called_non_callable', [callback]);
143365dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org  }
143465dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org
1435a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  var i = length - 1;
143665dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org  find_initial: if (%_ArgumentsLength() < 2) {
143765dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org    for (; i >= 0; i--) {
1438a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org      current = array[i];
1439a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org      if (!IS_UNDEFINED(current) || i in array) {
144065dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org        i--;
144165dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org        break find_initial;
144265dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org      }
144365dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org    }
144465dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org    throw MakeTypeError('reduce_no_initial', []);
144565dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org  }
144665dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org
144780c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  var receiver = %GetDefaultReceiver(callback);
1448975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org  var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(callback);
1449f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org  for (; i >= 0; i--) {
1450f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org    if (i in array) {
1451f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      var element = array[i];
1452f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      // Prepare break slots for debugger step in.
1453f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      if (stepping) %DebugPrepareStepInIfStepping(callback);
1454f05311f128ad22c89cfb6063d9375945c02239b5machenbach@chromium.org      current = %_CallFunction(receiver, current, element, i, array, callback);
145565dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org    }
145665dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org  }
145765dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org  return current;
145865dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org}
145965dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org
14609d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com// ES5, 15.4.3.2
14619d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.comfunction ArrayIsArray(obj) {
14629d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  return IS_ARRAY(obj);
14639d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com}
146465dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org
146543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
146643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// -------------------------------------------------------------------
1467e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
14681805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.orgfunction SetUpArray() {
14691805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  %CheckIsBootstrapping();
1470e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
14711805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // Set up non-enumerable constructor property on the Array.prototype
147241044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org  // object.
14739bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  %AddNamedProperty($Array.prototype, "constructor", $Array, DONT_ENUM);
147441044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
14758640107360766c74218cf16d51b714b1f2138839machenbach@chromium.org  // Set up unscopable properties on the Array.prototype object.
14768640107360766c74218cf16d51b714b1f2138839machenbach@chromium.org  var unscopables = {
14778640107360766c74218cf16d51b714b1f2138839machenbach@chromium.org    __proto__: null,
14788640107360766c74218cf16d51b714b1f2138839machenbach@chromium.org    copyWithin: true,
14798640107360766c74218cf16d51b714b1f2138839machenbach@chromium.org    entries: true,
14808640107360766c74218cf16d51b714b1f2138839machenbach@chromium.org    fill: true,
14818640107360766c74218cf16d51b714b1f2138839machenbach@chromium.org    find: true,
14828640107360766c74218cf16d51b714b1f2138839machenbach@chromium.org    findIndex: true,
14838640107360766c74218cf16d51b714b1f2138839machenbach@chromium.org    keys: true,
14848640107360766c74218cf16d51b714b1f2138839machenbach@chromium.org  };
14858640107360766c74218cf16d51b714b1f2138839machenbach@chromium.org  %AddNamedProperty($Array.prototype, symbolUnscopables, unscopables,
14868640107360766c74218cf16d51b714b1f2138839machenbach@chromium.org      DONT_ENUM | READ_ONLY);
14878640107360766c74218cf16d51b714b1f2138839machenbach@chromium.org
14881805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // Set up non-enumerable functions on the Array object.
14899d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  InstallFunctions($Array, DONT_ENUM, $Array(
14909d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    "isArray", ArrayIsArray
14919d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  ));
14929d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
1493a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org  var specialFunctions = %SpecialArrayFunctions();
1494f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org
1495f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  var getFunction = function(name, jsBuiltin, len) {
1496f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    var f = jsBuiltin;
1497f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    if (specialFunctions.hasOwnProperty(name)) {
1498f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org      f = specialFunctions[name];
1499f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    }
1500f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    if (!IS_UNDEFINED(len)) {
1501f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org      %FunctionSetLength(f, len);
1502f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    }
1503f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    return f;
1504f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  };
1505f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org
15061805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // Set up non-enumerable functions of the Array.prototype object and
150741044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org  // set their names.
1508f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org  // Manipulate the length of some of the functions to meet
1509f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org  // expectations set by ECMA-262 or Mozilla.
151027bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org  InstallFunctions($Array.prototype, DONT_ENUM, $Array(
1511f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    "toString", getFunction("toString", ArrayToString),
1512f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    "toLocaleString", getFunction("toLocaleString", ArrayToLocaleString),
1513f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    "join", getFunction("join", ArrayJoin),
1514f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    "pop", getFunction("pop", ArrayPop),
1515f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    "push", getFunction("push", ArrayPush, 1),
1516aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org    "concat", getFunction("concat", ArrayConcatJS, 1),
1517f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    "reverse", getFunction("reverse", ArrayReverse),
1518f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    "shift", getFunction("shift", ArrayShift),
1519f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    "unshift", getFunction("unshift", ArrayUnshift, 1),
1520f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    "slice", getFunction("slice", ArraySlice, 2),
1521f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    "splice", getFunction("splice", ArraySplice, 2),
1522f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    "sort", getFunction("sort", ArraySort),
1523f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    "filter", getFunction("filter", ArrayFilter, 1),
1524f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    "forEach", getFunction("forEach", ArrayForEach, 1),
1525f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    "some", getFunction("some", ArraySome, 1),
1526f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    "every", getFunction("every", ArrayEvery, 1),
1527f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    "map", getFunction("map", ArrayMap, 1),
1528f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    "indexOf", getFunction("indexOf", ArrayIndexOf, 1),
1529f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    "lastIndexOf", getFunction("lastIndexOf", ArrayLastIndexOf, 1),
1530f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    "reduce", getFunction("reduce", ArrayReduce, 1),
1531f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    "reduceRight", getFunction("reduceRight", ArrayReduceRight, 1)
15329d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  ));
153325156ded31ef771a2d799ed902483d83b3ebcbdclrn@chromium.org
1534ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  %FinishArrayPrototypeSetup($Array.prototype);
15358f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org
15368f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  // The internal Array prototype doesn't need to be fancy, since it's never
15371805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // exposed to user code.
15381805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // Adding only the functions that are actually used.
15391805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  SetUpLockedPrototype(InternalArray, $Array(), $Array(
1540aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org    "concat", getFunction("concat", ArrayConcatJS),
154172204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org    "indexOf", getFunction("indexOf", ArrayIndexOf),
15421805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    "join", getFunction("join", ArrayJoin),
15431805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    "pop", getFunction("pop", ArrayPop),
154472204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org    "push", getFunction("push", ArrayPush),
154572204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org    "splice", getFunction("splice", ArraySplice)
15461805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  ));
1547c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org
1548c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org  SetUpLockedPrototype(InternalPackedArray, $Array(), $Array(
1549c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org    "join", getFunction("join", ArrayJoin),
1550c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org    "pop", getFunction("pop", ArrayPop),
1551c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org    "push", getFunction("push", ArrayPush)
1552c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org  ));
155341044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
155443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
15551805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.orgSetUpArray();
1556