1b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Copyright 2010 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This file relies on the fact that the following declarations have been made
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// in runtime.js:
303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// var $Array = global.Array;
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Global list of arrays visited during toString, toLocaleString and
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// join invocations.
36e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvar visited_arrays = new InternalArray();
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Gets a sorted array of array keys.  Useful for operations on sparse
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// arrays.  Dupes have not been removed.
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction GetSortedArrayKeys(array, intervals) {
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var length = intervals.length;
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var keys = [];
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (var k = 0; k < length; k++) {
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var key = intervals[k];
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (key < 0) {
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      var j = -1 - key;
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      var limit = j + intervals[++k];
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      for (; j < limit; j++) {
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        var e = array[j];
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (!IS_UNDEFINED(e) || j in array) {
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          keys.push(j);
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // The case where key is undefined also ends here.
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (!IS_UNDEFINED(key)) {
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        var e = array[key];
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (!IS_UNDEFINED(e) || key in array) {
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          keys.push(key);
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  keys.sort(function(a, b) { return a - b; });
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return keys;
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
70257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochfunction SparseJoinWithSeparator(array, len, convert, separator) {
71257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, len));
72257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  var totalLength = 0;
73257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  var elements = new InternalArray(keys.length * 2);
74257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  var previousKey = -1;
75257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (var i = 0; i < keys.length; i++) {
76257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    var key = keys[i];
77257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (key != previousKey) {  // keys may contain duplicates.
78257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      var e = array[key];
79257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (!IS_STRING(e)) e = convert(e);
80257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      elements[i * 2] = key;
81257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      elements[i * 2 + 1] = e;
82257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      previousKey = key;
83257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
84257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
85257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return %SparseJoinWithSeparator(elements, len, separator);
86257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
87257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
88257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Optimized for sparse arrays if separator is ''.
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction SparseJoin(array, len, convert) {
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, len));
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var last_key = -1;
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var keys_length = keys.length;
94e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
95e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  var elements = new InternalArray(keys_length);
96e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  var elements_length = 0;
97e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (var i = 0; i < keys_length; i++) {
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var key = keys[i];
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (key != last_key) {
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      var e = array[key];
102e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (!IS_STRING(e)) e = convert(e);
103e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      elements[elements_length++] = e;
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      last_key = key;
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
107e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return %StringBuilderConcat(elements, elements_length, '');
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction UseSparseVariant(object, length, is_array) {
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block   return is_array &&
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       length > 1000 &&
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       (!%_IsSmi(length) ||
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        %EstimateNumberOfElements(object) < (length >> 2));
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction Join(array, length, separator, convert) {
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (length == 0) return '';
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var is_array = IS_ARRAY(array);
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (is_array) {
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If the array is cyclic, return the empty string for already
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // visited arrays.
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!%PushIfAbsent(visited_arrays, array)) return '';
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Attempt to convert the elements.
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  try {
132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (UseSparseVariant(array, length, is_array)) {
133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (separator.length == 0) {
134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        return SparseJoin(array, length, convert);
135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else {
136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        return SparseJoinWithSeparator(array, length, convert, separator);
137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Fast case for one-element arrays.
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (length == 1) {
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      var e = array[0];
143b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      if (IS_STRING(e)) return e;
144b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      return convert(e);
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
147e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Construct an array for the elements.
148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    var elements = new InternalArray(length);
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
150d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // We pull the empty separator check outside the loop for speed!
151d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (separator.length == 0) {
152b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      var elements_length = 0;
153d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      for (var i = 0; i < length; i++) {
154d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        var e = array[i];
155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        if (!IS_STRING(e)) e = convert(e);
156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        elements[elements_length++] = e;
157d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
158086aeeaae12517475c22695a200be45495516549Ben Murdoch      elements.length = elements_length;
159086aeeaae12517475c22695a200be45495516549Ben Murdoch      var result = %_FastAsciiArrayJoin(elements, '');
160086aeeaae12517475c22695a200be45495516549Ben Murdoch      if (!IS_UNDEFINED(result)) return result;
161086aeeaae12517475c22695a200be45495516549Ben Murdoch      return %StringBuilderConcat(elements, elements_length, '');
162086aeeaae12517475c22695a200be45495516549Ben Murdoch    }
163b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    // Non-empty separator case.
164e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // If the first element is a number then use the heuristic that the
165b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    // remaining elements are also likely to be numbers.
166b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    if (!IS_NUMBER(array[0])) {
167b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      for (var i = 0; i < length; i++) {
168b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        var e = array[i];
169086aeeaae12517475c22695a200be45495516549Ben Murdoch        if (!IS_STRING(e)) e = convert(e);
170086aeeaae12517475c22695a200be45495516549Ben Murdoch        elements[i] = e;
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
172e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
173b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      for (var i = 0; i < length; i++) {
174b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        var e = array[i];
17569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        if (IS_NUMBER(e)) {
17669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          e = %_NumberToString(e);
17769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        } else if (!IS_STRING(e)) {
17869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          e = convert(e);
17969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        }
18069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        elements[i] = e;
181b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      }
182086aeeaae12517475c22695a200be45495516549Ben Murdoch    }
183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    var result = %_FastAsciiArrayJoin(elements, separator);
184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (!IS_UNDEFINED(result)) return result;
185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return %StringBuilderJoin(elements, length, separator);
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } finally {
1881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Make sure to remove the last element of the visited array no
1891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // matter what happens.
1901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (is_array) visited_arrays.length = visited_arrays.length - 1;
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochfunction ConvertToString(x) {
196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Assumes x is a non-string.
197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (IS_NUMBER(x)) return %_NumberToString(x);
198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return (IS_NULL_OR_UNDEFINED(x)) ? '' : %ToString(%DefaultString(x));
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ConvertToLocaleString(e) {
2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (IS_NULL_OR_UNDEFINED(e)) {
205e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return '';
206e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // According to ES5, section 15.4.4.3, the toLocaleString conversion
2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // must throw a TypeError if ToObject(e).toLocaleString isn't
2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // callable.
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var e_obj = ToObject(e);
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return %ToString(e_obj.toLocaleString());
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This function implements the optimized splice implementation that can use
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// special array operations to handle sparse arrays in a sensible fashion.
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction SmartSlice(array, start_i, del_count, len, deleted_elements) {
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move deleted elements to a new array (the return value from splice).
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Intervals array can contain keys and intervals.  See comment in Concat.
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var intervals = %GetArrayKeys(array, start_i + del_count);
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var length = intervals.length;
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (var k = 0; k < length; k++) {
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var key = intervals[k];
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (key < 0) {
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      var j = -1 - key;
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      var interval_limit = j + intervals[++k];
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (j < start_i) {
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        j = start_i;
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      for (; j < interval_limit; j++) {
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // ECMA-262 15.4.4.12 line 10.  The spec could also be
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // interpreted such that %HasLocalProperty would be the
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // appropriate test.  We follow KJS in consulting the
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // prototype.
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        var current = array[j];
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (!IS_UNDEFINED(current) || j in array) {
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          deleted_elements[j - start_i] = current;
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (!IS_UNDEFINED(key)) {
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (key >= start_i) {
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // ECMA-262 15.4.4.12 line 10.  The spec could also be
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // interpreted such that %HasLocalProperty would be the
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // appropriate test.  We follow KJS in consulting the
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // prototype.
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          var current = array[key];
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (!IS_UNDEFINED(current) || key in array) {
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            deleted_elements[key - start_i] = current;
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This function implements the optimized splice implementation that can use
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// special array operations to handle sparse arrays in a sensible fashion.
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction SmartMove(array, start_i, del_count, len, num_additional_args) {
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move data to new array.
263e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  var new_array = new InternalArray(len - del_count + num_additional_args);
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var intervals = %GetArrayKeys(array, len);
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var length = intervals.length;
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (var k = 0; k < length; k++) {
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var key = intervals[k];
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (key < 0) {
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      var j = -1 - key;
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      var interval_limit = j + intervals[++k];
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      while (j < start_i && j < interval_limit) {
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // The spec could also be interpreted such that
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // %HasLocalProperty would be the appropriate test.  We follow
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // KJS in consulting the prototype.
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        var current = array[j];
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (!IS_UNDEFINED(current) || j in array) {
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          new_array[j] = current;
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        j++;
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      j = start_i + del_count;
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      while (j < interval_limit) {
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // ECMA-262 15.4.4.12 lines 24 and 41.  The spec could also be
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // interpreted such that %HasLocalProperty would be the
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // appropriate test.  We follow KJS in consulting the
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // prototype.
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        var current = array[j];
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (!IS_UNDEFINED(current) || j in array) {
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          new_array[j - del_count + num_additional_args] = current;
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        j++;
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (!IS_UNDEFINED(key)) {
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (key < start_i) {
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // The spec could also be interpreted such that
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // %HasLocalProperty would be the appropriate test.  We follow
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // KJS in consulting the prototype.
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          var current = array[key];
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (!IS_UNDEFINED(current) || key in array) {
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            new_array[key] = current;
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (key >= start_i + del_count) {
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // ECMA-262 15.4.4.12 lines 24 and 41.  The spec could also
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // be interpreted such that %HasLocalProperty would be the
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // appropriate test.  We follow KJS in consulting the
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // prototype.
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          var current = array[key];
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (!IS_UNDEFINED(current) || key in array) {
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            new_array[key - del_count + num_additional_args] = current;
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move contents of new_array into this array
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  %MoveArrayContents(new_array, array);
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This is part of the old simple-minded splice.  We are using it either
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// because the receiver is not an array (so we have no choice) or because we
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// know we are not deleting or moving a lot of elements.
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction SimpleSlice(array, start_i, del_count, len, deleted_elements) {
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (var i = 0; i < del_count; i++) {
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var index = start_i + i;
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The spec could also be interpreted such that %HasLocalProperty
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // would be the appropriate test.  We follow KJS in consulting the
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // prototype.
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var current = array[index];
3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!IS_UNDEFINED(current) || index in array) {
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      deleted_elements[i] = current;
3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction SimpleMove(array, start_i, del_count, len, num_additional_args) {
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (num_additional_args !== del_count) {
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Move the existing elements after the elements to be deleted
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // to the right position in the resulting array.
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (num_additional_args > del_count) {
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      for (var i = len - del_count; i > start_i; i--) {
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        var from_index = i + del_count - 1;
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        var to_index = i + num_additional_args - 1;
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // The spec could also be interpreted such that
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // %HasLocalProperty would be the appropriate test.  We follow
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // KJS in consulting the prototype.
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        var current = array[from_index];
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (!IS_UNDEFINED(current) || from_index in array) {
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          array[to_index] = current;
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          delete array[to_index];
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      for (var i = start_i; i < len - del_count; i++) {
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        var from_index = i + del_count;
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        var to_index = i + num_additional_args;
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // The spec could also be interpreted such that
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // %HasLocalProperty would be the appropriate test.  We follow
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // KJS in consulting the prototype.
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        var current = array[from_index];
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (!IS_UNDEFINED(current) || from_index in array) {
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          array[to_index] = current;
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          delete array[to_index];
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      for (var i = len; i > len - del_count + num_additional_args; i--) {
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        delete array[i - 1];
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ArrayToString() {
3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var array;
3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var func;
3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (IS_ARRAY(this)) {
3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    func = this.join;
3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (func === ArrayJoin) {
3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return Join(this, this.length, ',', ConvertToString);
3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    array = this;
3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    array = ToObject(this);
3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    func = array.join;
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!IS_SPEC_FUNCTION(func)) {
3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return %_CallFunction(array, ObjectToString);
3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return %_CallFunction(array, func);
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ArrayToLocaleString() {
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var array = ToObject(this);
4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var arrayLen = array.length;
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var len = TO_UINT32(arrayLen);
4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (len === 0) return "";
4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return Join(array, len, ',', ConvertToLocaleString);
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ArrayJoin(separator) {
411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["Array.prototype.join"]);
414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
416e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (IS_UNDEFINED(separator)) {
417e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    separator = ',';
418e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else if (!IS_STRING(separator)) {
419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    separator = NonStringToString(separator);
420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
4218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  var result = %_FastAsciiArrayJoin(this, separator);
423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!IS_UNDEFINED(result)) return result;
4248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return Join(this, TO_UINT32(this.length), separator, ConvertToString);
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Removes the last element from the array and returns it. See
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ECMA-262, section 15.4.4.6.
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ArrayPop() {
432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["Array.prototype.pop"]);
435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
437e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  var n = TO_UINT32(this.length);
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (n == 0) {
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.length = n;
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  n--;
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var value = this[n];
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.length = n;
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  delete this[n];
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return value;
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Appends the arguments to the end of the array and returns the new
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// length of the array. See ECMA-262, section 15.4.4.7.
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ArrayPush() {
453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["Array.prototype.push"]);
456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  var n = TO_UINT32(this.length);
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var m = %_ArgumentsLength();
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (var i = 0; i < m; i++) {
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this[i+n] = %_Arguments(i);
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.length = n + m;
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return this.length;
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ArrayConcat(arg1) {  // length == 1
469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["Array.prototype.concat"]);
472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var arg_count = %_ArgumentsLength();
475e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  var arrays = new InternalArray(1 + arg_count);
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  arrays[0] = this;
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (var i = 0; i < arg_count; i++) {
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arrays[i + 1] = %_Arguments(i);
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return %ArrayConcat(arrays);
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// For implementing reverse() on large, sparse arrays.
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction SparseReverse(array, len) {
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, len));
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var high_counter = keys.length - 1;
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var low_counter = 0;
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (low_counter <= high_counter) {
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var i = keys[low_counter];
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var j = keys[high_counter];
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var j_complement = len - j - 1;
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var low, high;
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (j_complement <= i) {
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      high = j;
4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      while (keys[--high_counter] == j) { }
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      low = j_complement;
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (j_complement >= i) {
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      low = i;
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      while (keys[++low_counter] == i) { }
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      high = len - i - 1;
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var current_i = array[low];
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!IS_UNDEFINED(current_i) || low in array) {
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      var current_j = array[high];
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (!IS_UNDEFINED(current_j) || high in array) {
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        array[low] = current_j;
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        array[high] = current_i;
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        array[high] = current_i;
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        delete array[low];
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      var current_j = array[high];
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (!IS_UNDEFINED(current_j) || high in array) {
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        array[low] = current_j;
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        delete array[high];
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ArrayReverse() {
530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["Array.prototype.reverse"]);
533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
535e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  var j = TO_UINT32(this.length) - 1;
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (UseSparseVariant(this, j, IS_ARRAY(this))) {
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SparseReverse(this, j+1);
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return this;
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (var i = 0; i < j; i++, j--) {
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var current_i = this[i];
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!IS_UNDEFINED(current_i) || i in this) {
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      var current_j = this[j];
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (!IS_UNDEFINED(current_j) || j in this) {
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        this[i] = current_j;
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        this[j] = current_i;
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        this[j] = current_i;
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        delete this[i];
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      var current_j = this[j];
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (!IS_UNDEFINED(current_j) || j in this) {
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        this[i] = current_j;
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        delete this[j];
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return this;
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ArrayShift() {
566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["Array.prototype.shift"]);
569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
571e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  var len = TO_UINT32(this.length);
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (len === 0) {
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this.length = 0;
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var first = this[0];
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (IS_ARRAY(this)) {
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SmartMove(this, 0, 1, len, 0);
5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SimpleMove(this, 0, 1, len, 0);
5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.length = len - 1;
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return first;
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ArrayUnshift(arg1) {  // length == 1
593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["Array.prototype.unshift"]);
596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
598e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  var len = TO_UINT32(this.length);
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var num_arguments = %_ArgumentsLength();
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (IS_ARRAY(this)) {
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SmartMove(this, 0, 0, len, num_arguments);
6033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SimpleMove(this, 0, 0, len, num_arguments);
6053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (var i = 0; i < num_arguments; i++) {
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this[i] = %_Arguments(i);
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.length = len + num_arguments;
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return len + num_arguments;
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ArraySlice(start, end) {
618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["Array.prototype.slice"]);
621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
623e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  var len = TO_UINT32(this.length);
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var start_i = TO_INTEGER(start);
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var end_i = len;
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (end !== void 0) end_i = TO_INTEGER(end);
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (start_i < 0) {
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    start_i += len;
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (start_i < 0) start_i = 0;
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (start_i > len) start_i = len;
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (end_i < 0) {
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    end_i += len;
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (end_i < 0) end_i = 0;
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (end_i > len) end_i = len;
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var result = [];
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (end_i < start_i) return result;
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (IS_ARRAY(this) &&
6483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      (end_i > 1000) &&
6493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      (%EstimateNumberOfElements(this) < end_i)) {
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SmartSlice(this, start_i, end_i - start_i, len, result);
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SimpleSlice(this, start_i, end_i - start_i, len, result);
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result.length = end_i - start_i;
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ArraySplice(start, delete_count) {
662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["Array.prototype.splice"]);
665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var num_arguments = %_ArgumentsLength();
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  var len = TO_UINT32(this.length);
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var start_i = TO_INTEGER(start);
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (start_i < 0) {
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    start_i += len;
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (start_i < 0) start_i = 0;
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (start_i > len) start_i = len;
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
679402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
6801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // given as a request to delete all the elements from the start.
6811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // And it differs from the case of undefined delete count.
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This does not follow ECMA-262, but we do the same for
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // compatibility.
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var del_count = 0;
6851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (num_arguments == 1) {
6861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    del_count = len - start_i;
6871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    del_count = TO_INTEGER(delete_count);
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (del_count < 0) del_count = 0;
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (del_count > len - start_i) del_count = len - start_i;
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var deleted_elements = [];
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  deleted_elements.length = del_count;
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Number of elements to add.
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var num_additional_args = 0;
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (num_arguments > 2) {
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    num_additional_args = num_arguments - 2;
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var use_simple_splice = true;
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (IS_ARRAY(this) && num_additional_args !== del_count) {
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If we are only deleting/moving a few things near the end of the
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // array then the simple version is going to be faster, because it
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // doesn't touch most of the array.
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var estimated_non_hole_elements = %EstimateNumberOfElements(this);
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (len > 20 && (estimated_non_hole_elements >> 2) < (len - start_i)) {
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      use_simple_splice = false;
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (use_simple_splice) {
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SimpleSlice(this, start_i, del_count, len, deleted_elements);
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SimpleMove(this, start_i, del_count, len, num_additional_args);
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SmartSlice(this, start_i, del_count, len, deleted_elements);
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SmartMove(this, start_i, del_count, len, num_additional_args);
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Insert the arguments into the resulting array in
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // place of the deleted elements.
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var i = start_i;
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var arguments_index = 2;
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var arguments_length = %_ArgumentsLength();
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (arguments_index < arguments_length) {
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    this[i++] = %_Arguments(arguments_index++);
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.length = len - del_count + num_additional_args;
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the deleted elements.
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return deleted_elements;
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ArraySort(comparefn) {
738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["Array.prototype.sort"]);
741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // In-place QuickSort algorithm.
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // For short (length <= 22) arrays, insertion sort is used for efficiency.
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
746589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (!IS_SPEC_FUNCTION(comparefn)) {
7476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    comparefn = function (x, y) {
7486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (x === y) return 0;
7496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (%_IsSmi(x) && %_IsSmi(y)) {
7506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        return %SmiLexicographicCompare(x, y);
7516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
7526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      x = ToString(x);
7536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      y = ToString(y);
7546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (x == y) return 0;
7556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      else return x < y ? -1 : 1;
7566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    };
7576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
75869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  var receiver = %GetDefaultReceiver(comparefn);
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var InsertionSort = function InsertionSort(a, from, to) {
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (var i = from + 1; i < to; i++) {
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      var element = a[i];
7636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      for (var j = i - 1; j >= from; j--) {
7646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        var tmp = a[j];
7653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        var order = %_CallFunction(receiver, tmp, element, comparefn);
7666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (order > 0) {
7676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          a[j + 1] = tmp;
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
7696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          break;
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
7726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      a[j + 1] = element;
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
7743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var QuickSort = function QuickSort(a, from, to) {
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Insertion sort is faster for short arrays.
778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (to - from <= 10) {
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      InsertionSort(a, from, to);
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Find a pivot as the median of first, last and middle element.
783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    var v0 = a[from];
784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    var v1 = a[to - 1];
785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    var middle_index = from + ((to - from) >> 1);
786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    var v2 = a[middle_index];
7873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    var c01 = %_CallFunction(receiver, v0, v1, comparefn);
788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (c01 > 0) {
789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // v1 < v0, so swap them.
790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      var tmp = v0;
791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      v0 = v1;
792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      v1 = tmp;
793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } // v0 <= v1.
7943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    var c02 = %_CallFunction(receiver, v0, v2, comparefn);
795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (c02 >= 0) {
796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // v2 <= v0 <= v1.
797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      var tmp = v0;
798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      v0 = v2;
799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      v2 = v1;
800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      v1 = tmp;
801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // v0 <= v1 && v0 < v2
8033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      var c12 = %_CallFunction(receiver, v1, v2, comparefn);
804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (c12 > 0) {
805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // v0 <= v2 < v1
806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        var tmp = v1;
807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        v1 = v2;
808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        v2 = tmp;
809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // v0 <= v1 <= v2
812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    a[from] = v0;
813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    a[to - 1] = v2;
814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    var pivot = v1;
815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    var low_end = from + 1;   // Upper bound of elements lower than pivot.
816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    var high_start = to - 1;  // Lower bound of elements greater than pivot.
817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    a[middle_index] = a[low_end];
818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    a[low_end] = pivot;
819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // From low_end to i are elements equal to pivot.
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // From i to high_start are elements that haven't been compared yet.
822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    partition: for (var i = low_end + 1; i < high_start; i++) {
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      var element = a[i];
8243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      var order = %_CallFunction(receiver, element, pivot, comparefn);
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (order < 0) {
8265710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch        a[i] = a[low_end];
8275710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch        a[low_end] = element;
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        low_end++;
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (order > 0) {
830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        do {
831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          high_start--;
832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          if (high_start == i) break partition;
833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          var top_elem = a[high_start];
8343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          order = %_CallFunction(receiver, top_elem, pivot, comparefn);
835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        } while (order > 0);
8365710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch        a[i] = a[high_start];
8375710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch        a[high_start] = element;
838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (order < 0) {
8395710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch          element = a[i];
8405710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch          a[i] = a[low_end];
8415710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch          a[low_end] = element;
842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          low_end++;
843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    QuickSort(a, from, low_end);
847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    QuickSort(a, high_start, to);
8483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Copy elements in the range 0..length from obj's prototype chain
851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // to obj itself, if obj has holes. Return one more than the maximal index
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // of a prototype property.
8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var CopyFromPrototype = function CopyFromPrototype(obj, length) {
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var max = 0;
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (var proto = obj.__proto__; proto; proto = proto.__proto__) {
856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      var indices = %GetArrayKeys(proto, length);
857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (indices.length > 0) {
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (indices[0] == -1) {
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // It's an interval.
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          var proto_length = indices[1];
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          for (var i = 0; i < proto_length; i++) {
862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            if (!obj.hasOwnProperty(i) && proto.hasOwnProperty(i)) {
863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              obj[i] = proto[i];
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              if (i >= max) { max = i + 1; }
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          for (var i = 0; i < indices.length; i++) {
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            var index = indices[i];
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            if (!IS_UNDEFINED(index) &&
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                !obj.hasOwnProperty(index) && proto.hasOwnProperty(index)) {
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              obj[index] = proto[index];
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              if (index >= max) { max = index + 1; }
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return max;
8803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set a value of "undefined" on all indices in the range from..to
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // where a prototype of obj has an element. I.e., shadow all prototype
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements in that range.
8853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var ShadowPrototypeElements = function(obj, from, to) {
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (var proto = obj.__proto__; proto; proto = proto.__proto__) {
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      var indices = %GetArrayKeys(proto, to);
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (indices.length > 0) {
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (indices[0] == -1) {
890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // It's an interval.
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          var proto_length = indices[1];
892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          for (var i = from; i < proto_length; i++) {
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            if (proto.hasOwnProperty(i)) {
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              obj[i] = void 0;
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          for (var i = 0; i < indices.length; i++) {
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            var index = indices[i];
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            if (!IS_UNDEFINED(index) && from <= index &&
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                proto.hasOwnProperty(index)) {
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              obj[index] = void 0;
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
9083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var SafeRemoveArrayHoles = function SafeRemoveArrayHoles(obj) {
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Copy defined elements from the end to fill in all holes and undefineds
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // in the beginning of the array.  Write undefineds and holes at the end
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // after loop is finished.
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var first_undefined = 0;
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var last_defined = length - 1;
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var num_holes = 0;
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    while (first_undefined < last_defined) {
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Find first undefined element.
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      while (first_undefined < last_defined &&
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             !IS_UNDEFINED(obj[first_undefined])) {
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        first_undefined++;
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Maintain the invariant num_holes = the number of holes in the original
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // array with indices <= first_undefined or > last_defined.
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (!obj.hasOwnProperty(first_undefined)) {
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        num_holes++;
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Find last defined element.
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      while (first_undefined < last_defined &&
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             IS_UNDEFINED(obj[last_defined])) {
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (!obj.hasOwnProperty(last_defined)) {
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          num_holes++;
934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        last_defined--;
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (first_undefined < last_defined) {
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Fill in hole or undefined.
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        obj[first_undefined] = obj[last_defined];
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        obj[last_defined] = void 0;
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If there were any undefineds in the entire array, first_undefined
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // points to one past the last defined element.  Make this true if
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // there were no undefineds, as well, so that first_undefined == number
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // of defined elements.
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!IS_UNDEFINED(obj[first_undefined])) first_undefined++;
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Fill in the undefineds and the holes.  There may be a hole where
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // an undefined should be and vice versa.
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var i;
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (i = first_undefined; i < length - num_holes; i++) {
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      obj[i] = void 0;
953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (i = length - num_holes; i < length; i++) {
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // For compatability with Webkit, do not expose elements in the prototype.
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (i in obj.__proto__) {
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        obj[i] = void 0;
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        delete obj[i];
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Return the number of defined elements.
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return first_undefined;
9653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  var length = TO_UINT32(this.length);
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (length < 2) return this;
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var is_array = IS_ARRAY(this);
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var max_prototype_element;
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!is_array) {
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // For compatibility with JSC, we also sort elements inherited from
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // the prototype chain on non-Array objects.
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // We do this by copying them to this object and sorting only
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // local elements. This is not very efficient, but sorting with
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // inherited elements happens very, very rarely, if at all.
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The specification allows "implementation dependent" behavior
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // if an element on the prototype chain has an element that
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // might interact with sorting.
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    max_prototype_element = CopyFromPrototype(this, length);
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var num_non_undefined = %RemoveArrayHoles(this, length);
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (num_non_undefined == -1) {
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // There were indexed accessors in the array.  Move array holes and
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // undefineds to the end using a Javascript function that is safe
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // in the presence of accessors.
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    num_non_undefined = SafeRemoveArrayHoles(this);
990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  QuickSort(this, 0, num_non_undefined);
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!is_array && (num_non_undefined + 1 < max_prototype_element)) {
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // For compatibility with JSC, we shadow any elements in the prototype
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // chain that has become exposed by sort moving a hole to its position.
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ShadowPrototypeElements(this, num_non_undefined, max_prototype_element);
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return this;
1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The following functions cannot be made efficient on sparse arrays while
1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// preserving the semantics, since the calls to the receiver function can add
1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// or delete elements from the array.
1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ArrayFilter(f, receiver) {
1008257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
1009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
1010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["Array.prototype.filter"]);
1011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Pull out the length so that modifications to the length in the
10143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // loop will not affect the looping and side effects are visible.
10153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var array = ToObject(this);
10163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var length = ToUint32(array.length);
10173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1018589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (!IS_SPEC_FUNCTION(f)) {
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    throw MakeTypeError('called_non_callable', [ f ]);
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
102169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (IS_NULL_OR_UNDEFINED(receiver)) {
102269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    receiver = %GetDefaultReceiver(f) || receiver;
10233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (!IS_SPEC_OBJECT(receiver)) {
10243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    receiver = ToObject(receiver);
102569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
10263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var result = new $Array();
10283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var accumulator = new InternalArray();
10293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var accumulator_length = 0;
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (var i = 0; i < length; i++) {
10313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (i in array) {
10323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      var element = array[i];
10333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (%_CallFunction(receiver, element, i, array, f)) {
10343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        accumulator[accumulator_length++] = element;
1035e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
10383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  %MoveArrayContents(accumulator, result);
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ArrayForEach(f, receiver) {
1044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
1045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
1046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["Array.prototype.forEach"]);
1047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Pull out the length so that modifications to the length in the
10503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // loop will not affect the looping and side effects are visible.
10513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var array = ToObject(this);
10523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var length = TO_UINT32(array.length);
10533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1054589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (!IS_SPEC_FUNCTION(f)) {
1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    throw MakeTypeError('called_non_callable', [ f ]);
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
105769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (IS_NULL_OR_UNDEFINED(receiver)) {
105869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    receiver = %GetDefaultReceiver(f) || receiver;
10593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (!IS_SPEC_OBJECT(receiver)) {
10603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    receiver = ToObject(receiver);
106169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
10623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (var i = 0; i < length; i++) {
10643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (i in array) {
10653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      var element = array[i];
10663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      %_CallFunction(receiver, element, i, array, f);
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Executes the function once for each element present in the
1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// array until it finds one where callback returns true.
1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ArraySome(f, receiver) {
1075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
1076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
1077257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["Array.prototype.some"]);
1078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Pull out the length so that modifications to the length in the
10813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // loop will not affect the looping and side effects are visible.
10823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var array = ToObject(this);
10833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var length = TO_UINT32(array.length);
10843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1085589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (!IS_SPEC_FUNCTION(f)) {
1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    throw MakeTypeError('called_non_callable', [ f ]);
1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
108869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (IS_NULL_OR_UNDEFINED(receiver)) {
108969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    receiver = %GetDefaultReceiver(f) || receiver;
10903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (!IS_SPEC_OBJECT(receiver)) {
10913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    receiver = ToObject(receiver);
109269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
10933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (var i = 0; i < length; i++) {
10953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (i in array) {
10963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      var element = array[i];
10973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (%_CallFunction(receiver, element, i, array, f)) return true;
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return false;
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ArrayEvery(f, receiver) {
1105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
1106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
1107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["Array.prototype.every"]);
1108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Pull out the length so that modifications to the length in the
11113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // loop will not affect the looping and side effects are visible.
11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var array = ToObject(this);
11133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var length = TO_UINT32(array.length);
11143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1115589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (!IS_SPEC_FUNCTION(f)) {
1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    throw MakeTypeError('called_non_callable', [ f ]);
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
111869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (IS_NULL_OR_UNDEFINED(receiver)) {
111969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    receiver = %GetDefaultReceiver(f) || receiver;
11203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (!IS_SPEC_OBJECT(receiver)) {
11213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    receiver = ToObject(receiver);
112269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
11233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (var i = 0; i < length; i++) {
11253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (i in array) {
11263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      var element = array[i];
11273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!%_CallFunction(receiver, element, i, array, f)) return false;
1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ArrayMap(f, receiver) {
1134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
1135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
1136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["Array.prototype.map"]);
1137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Pull out the length so that modifications to the length in the
11403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // loop will not affect the looping and side effects are visible.
11413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var array = ToObject(this);
11423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var length = TO_UINT32(array.length);
11433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1144589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (!IS_SPEC_FUNCTION(f)) {
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    throw MakeTypeError('called_non_callable', [ f ]);
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
114769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (IS_NULL_OR_UNDEFINED(receiver)) {
114869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    receiver = %GetDefaultReceiver(f) || receiver;
11493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (!IS_SPEC_OBJECT(receiver)) {
11503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    receiver = ToObject(receiver);
115169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
11523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1153e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  var result = new $Array();
1154e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  var accumulator = new InternalArray(length);
1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (var i = 0; i < length; i++) {
11563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (i in array) {
11573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      var element = array[i];
11583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      accumulator[i] = %_CallFunction(receiver, element, i, array, f);
1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  %MoveArrayContents(accumulator, result);
1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ArrayIndexOf(element, index) {
1167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
1168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
1169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["Array.prototype.indexOf"]);
1170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
117280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  var length = TO_UINT32(this.length);
117380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (length == 0) return -1;
11748defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (IS_UNDEFINED(index)) {
1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    index = 0;
1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    index = TO_INTEGER(index);
1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If index is negative, index from the end of the array.
11791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (index < 0) {
11801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      index = length + index;
11811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // If index is still negative, search the entire array.
11821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (index < 0) index = 0;
11831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
118559151504615d929945dc59db37bf1166937748c6Steve Block  var min = index;
118659151504615d929945dc59db37bf1166937748c6Steve Block  var max = length;
1187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (UseSparseVariant(this, length, IS_ARRAY(this))) {
118859151504615d929945dc59db37bf1166937748c6Steve Block    var intervals = %GetArrayKeys(this, length);
118959151504615d929945dc59db37bf1166937748c6Steve Block    if (intervals.length == 2 && intervals[0] < 0) {
119059151504615d929945dc59db37bf1166937748c6Steve Block      // A single interval.
119159151504615d929945dc59db37bf1166937748c6Steve Block      var intervalMin = -(intervals[0] + 1);
119259151504615d929945dc59db37bf1166937748c6Steve Block      var intervalMax = intervalMin + intervals[1];
1193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (min < intervalMin) min = intervalMin;
119459151504615d929945dc59db37bf1166937748c6Steve Block      max = intervalMax;  // Capped by length already.
119559151504615d929945dc59db37bf1166937748c6Steve Block      // Fall through to loop below.
119659151504615d929945dc59db37bf1166937748c6Steve Block    } else {
119759151504615d929945dc59db37bf1166937748c6Steve Block      if (intervals.length == 0) return -1;
119859151504615d929945dc59db37bf1166937748c6Steve Block      // Get all the keys in sorted order.
119959151504615d929945dc59db37bf1166937748c6Steve Block      var sortedKeys = GetSortedArrayKeys(this, intervals);
120059151504615d929945dc59db37bf1166937748c6Steve Block      var n = sortedKeys.length;
120159151504615d929945dc59db37bf1166937748c6Steve Block      var i = 0;
120259151504615d929945dc59db37bf1166937748c6Steve Block      while (i < n && sortedKeys[i] < index) i++;
120359151504615d929945dc59db37bf1166937748c6Steve Block      while (i < n) {
120459151504615d929945dc59db37bf1166937748c6Steve Block        var key = sortedKeys[i];
120559151504615d929945dc59db37bf1166937748c6Steve Block        if (!IS_UNDEFINED(key) && this[key] === element) return key;
120659151504615d929945dc59db37bf1166937748c6Steve Block        i++;
120759151504615d929945dc59db37bf1166937748c6Steve Block      }
120859151504615d929945dc59db37bf1166937748c6Steve Block      return -1;
120959151504615d929945dc59db37bf1166937748c6Steve Block    }
121059151504615d929945dc59db37bf1166937748c6Steve Block  }
121180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Lookup through the array.
12126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!IS_UNDEFINED(element)) {
121359151504615d929945dc59db37bf1166937748c6Steve Block    for (var i = min; i < max; i++) {
12146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (this[i] === element) return i;
12156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
12166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return -1;
12176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
121859151504615d929945dc59db37bf1166937748c6Steve Block  // Lookup through the array.
121959151504615d929945dc59db37bf1166937748c6Steve Block  for (var i = min; i < max; i++) {
12206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (IS_UNDEFINED(this[i]) && i in this) {
12216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return i;
1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return -1;
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ArrayLastIndexOf(element, index) {
1229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
1230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
1231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["Array.prototype.lastIndexOf"]);
1232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
123480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  var length = TO_UINT32(this.length);
123580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (length == 0) return -1;
12368defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (%_ArgumentsLength() < 2) {
1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    index = length - 1;
1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    index = TO_INTEGER(index);
1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If index is negative, index from end of the array.
124159151504615d929945dc59db37bf1166937748c6Steve Block    if (index < 0) index += length;
1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If index is still negative, do not search the array.
124359151504615d929945dc59db37bf1166937748c6Steve Block    if (index < 0) return -1;
1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    else if (index >= length) index = length - 1;
1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
124659151504615d929945dc59db37bf1166937748c6Steve Block  var min = 0;
124759151504615d929945dc59db37bf1166937748c6Steve Block  var max = index;
1248e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (UseSparseVariant(this, length, IS_ARRAY(this))) {
124959151504615d929945dc59db37bf1166937748c6Steve Block    var intervals = %GetArrayKeys(this, index + 1);
125059151504615d929945dc59db37bf1166937748c6Steve Block    if (intervals.length == 2 && intervals[0] < 0) {
125159151504615d929945dc59db37bf1166937748c6Steve Block      // A single interval.
125259151504615d929945dc59db37bf1166937748c6Steve Block      var intervalMin = -(intervals[0] + 1);
125359151504615d929945dc59db37bf1166937748c6Steve Block      var intervalMax = intervalMin + intervals[1];
1254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (min < intervalMin) min = intervalMin;
125559151504615d929945dc59db37bf1166937748c6Steve Block      max = intervalMax;  // Capped by index already.
125659151504615d929945dc59db37bf1166937748c6Steve Block      // Fall through to loop below.
125759151504615d929945dc59db37bf1166937748c6Steve Block    } else {
125859151504615d929945dc59db37bf1166937748c6Steve Block      if (intervals.length == 0) return -1;
125959151504615d929945dc59db37bf1166937748c6Steve Block      // Get all the keys in sorted order.
126059151504615d929945dc59db37bf1166937748c6Steve Block      var sortedKeys = GetSortedArrayKeys(this, intervals);
126159151504615d929945dc59db37bf1166937748c6Steve Block      var i = sortedKeys.length - 1;
126259151504615d929945dc59db37bf1166937748c6Steve Block      while (i >= 0) {
126359151504615d929945dc59db37bf1166937748c6Steve Block        var key = sortedKeys[i];
126459151504615d929945dc59db37bf1166937748c6Steve Block        if (!IS_UNDEFINED(key) && this[key] === element) return key;
126559151504615d929945dc59db37bf1166937748c6Steve Block        i--;
126659151504615d929945dc59db37bf1166937748c6Steve Block      }
126759151504615d929945dc59db37bf1166937748c6Steve Block      return -1;
126859151504615d929945dc59db37bf1166937748c6Steve Block    }
126959151504615d929945dc59db37bf1166937748c6Steve Block  }
1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Lookup through the array.
12716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!IS_UNDEFINED(element)) {
127259151504615d929945dc59db37bf1166937748c6Steve Block    for (var i = max; i >= min; i--) {
12736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (this[i] === element) return i;
12746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
12756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return -1;
12766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
127759151504615d929945dc59db37bf1166937748c6Steve Block  for (var i = max; i >= min; i--) {
12786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (IS_UNDEFINED(this[i]) && i in this) {
12796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return i;
1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return -1;
1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ArrayReduce(callback, current) {
1287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
1288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
1289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["Array.prototype.reduce"]);
1290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Pull out the length so that modifications to the length in the
12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // loop will not affect the looping and side effects are visible.
12943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var array = ToObject(this);
12953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var length = ToUint32(array.length);
12963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1297589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (!IS_SPEC_FUNCTION(callback)) {
1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    throw MakeTypeError('called_non_callable', [callback]);
1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
130069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var i = 0;
1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  find_initial: if (%_ArgumentsLength() < 2) {
1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (; i < length; i++) {
13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      current = array[i];
13053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!IS_UNDEFINED(current) || i in array) {
1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        i++;
1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break find_initial;
1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    throw MakeTypeError('reduce_no_initial', []);
1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
131369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  var receiver = %GetDefaultReceiver(callback);
1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (; i < length; i++) {
13153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (i in array) {
13163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      var element = array[i];
13173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      current = %_CallFunction(receiver, current, element, i, array, callback);
1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return current;
1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ArrayReduceRight(callback, current) {
1324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
1325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
1326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["Array.prototype.reduceRight"]);
1327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
13293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Pull out the length so that side effects are visible before the
13303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // callback function is checked.
13313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var array = ToObject(this);
13323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var length = ToUint32(array.length);
13333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1334589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (!IS_SPEC_FUNCTION(callback)) {
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    throw MakeTypeError('called_non_callable', [callback]);
1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var i = length - 1;
1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  find_initial: if (%_ArgumentsLength() < 2) {
1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (; i >= 0; i--) {
13413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      current = array[i];
13423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!IS_UNDEFINED(current) || i in array) {
1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        i--;
1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break find_initial;
1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    throw MakeTypeError('reduce_no_initial', []);
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
135069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  var receiver = %GetDefaultReceiver(callback);
1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (; i >= 0; i--) {
13523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (i in array) {
13533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      var element = array[i];
13543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      current = %_CallFunction(receiver, current, element, i, array, callback);
1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return current;
1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// ES5, 15.4.3.2
13613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockfunction ArrayIsArray(obj) {
13623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return IS_ARRAY(obj);
13633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------
1367589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochfunction SetUpArray() {
1368589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  %CheckIsBootstrapping();
1369589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Set up non-enumerable constructor property on the Array.prototype
1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object.
1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  %SetProperty($Array.prototype, "constructor", $Array, DONT_ENUM);
1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1373589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Set up non-enumerable functions on the Array object.
13743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  InstallFunctions($Array, DONT_ENUM, $Array(
13753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    "isArray", ArrayIsArray
13763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ));
13773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  var specialFunctions = %SpecialArrayFunctions({});
13796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  var getFunction = function(name, jsBuiltin, len) {
13816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    var f = jsBuiltin;
13826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (specialFunctions.hasOwnProperty(name)) {
13836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      f = specialFunctions[name];
13846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
13856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (!IS_UNDEFINED(len)) {
13866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      %FunctionSetLength(f, len);
13876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
13886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return f;
13893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
13906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1391589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Set up non-enumerable functions of the Array.prototype object and
1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // set their names.
1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Manipulate the length of some of the functions to meet
1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // expectations set by ECMA-262 or Mozilla.
13953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InstallFunctions($Array.prototype, DONT_ENUM, $Array(
13966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "toString", getFunction("toString", ArrayToString),
13976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "toLocaleString", getFunction("toLocaleString", ArrayToLocaleString),
13986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "join", getFunction("join", ArrayJoin),
13996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "pop", getFunction("pop", ArrayPop),
14006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "push", getFunction("push", ArrayPush, 1),
14016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "concat", getFunction("concat", ArrayConcat, 1),
14026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "reverse", getFunction("reverse", ArrayReverse),
14036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "shift", getFunction("shift", ArrayShift),
14046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "unshift", getFunction("unshift", ArrayUnshift, 1),
14056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "slice", getFunction("slice", ArraySlice, 2),
14066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "splice", getFunction("splice", ArraySplice, 2),
14076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "sort", getFunction("sort", ArraySort),
14086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "filter", getFunction("filter", ArrayFilter, 1),
14096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "forEach", getFunction("forEach", ArrayForEach, 1),
14106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "some", getFunction("some", ArraySome, 1),
14116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "every", getFunction("every", ArrayEvery, 1),
14126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "map", getFunction("map", ArrayMap, 1),
14136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "indexOf", getFunction("indexOf", ArrayIndexOf, 1),
14146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "lastIndexOf", getFunction("lastIndexOf", ArrayLastIndexOf, 1),
14156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "reduce", getFunction("reduce", ArrayReduce, 1),
14166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    "reduceRight", getFunction("reduceRight", ArrayReduceRight, 1)
14176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ));
14186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  %FinishArrayPrototypeSetup($Array.prototype);
1420e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1421e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // The internal Array prototype doesn't need to be fancy, since it's never
1422589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // exposed to user code.
1423589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Adding only the functions that are actually used.
1424589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  SetUpLockedPrototype(InternalArray, $Array(), $Array(
1425589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    "join", getFunction("join", ArrayJoin),
1426589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    "pop", getFunction("pop", ArrayPop),
1427589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    "push", getFunction("push", ArrayPush)
1428589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ));
1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1431589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochSetUpArray();
1432