OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 (function(global, utils, extrasUtils) { | 5 (function(global, utils, extrasUtils) { |
6 | 6 |
7 "use strict"; | 7 "use strict"; |
8 | 8 |
9 %CheckIsBootstrapping(); | 9 %CheckIsBootstrapping(); |
10 | 10 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 var result = ObjectDefineProperty(array, i, { | 67 var result = ObjectDefineProperty(array, i, { |
68 value: value, writable: true, configurable: true, enumerable: true | 68 value: value, writable: true, configurable: true, enumerable: true |
69 }); | 69 }); |
70 if (!result) throw MakeTypeError(kStrictCannotAssign, i); | 70 if (!result) throw MakeTypeError(kStrictCannotAssign, i); |
71 } else { | 71 } else { |
72 AddIndexedProperty(array, i, value); | 72 AddIndexedProperty(array, i, value); |
73 } | 73 } |
74 } | 74 } |
75 | 75 |
76 | 76 |
| 77 // Global list of arrays visited during toString, toLocaleString and |
| 78 // join invocations. |
| 79 var visited_arrays = new InternalArray(); |
| 80 |
| 81 |
77 // Gets a sorted array of array keys. Useful for operations on sparse | 82 // Gets a sorted array of array keys. Useful for operations on sparse |
78 // arrays. Dupes have not been removed. | 83 // arrays. Dupes have not been removed. |
79 function GetSortedArrayKeys(array, indices) { | 84 function GetSortedArrayKeys(array, indices) { |
80 var keys = new InternalArray(); | 85 var keys = new InternalArray(); |
81 if (IS_NUMBER(indices)) { | 86 if (IS_NUMBER(indices)) { |
82 // It's an interval | 87 // It's an interval |
83 var limit = indices; | 88 var limit = indices; |
84 for (var i = 0; i < limit; ++i) { | 89 for (var i = 0; i < limit; ++i) { |
85 var e = array[i]; | 90 var e = array[i]; |
86 if (!IS_UNDEFINED(e) || i in array) { | 91 if (!IS_UNDEFINED(e) || i in array) { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 var e = array[key]; | 143 var e = array[key]; |
139 if (!IS_STRING(e)) e = convert(e); | 144 if (!IS_STRING(e)) e = convert(e); |
140 elements[elements_length++] = e; | 145 elements[elements_length++] = e; |
141 last_key = key; | 146 last_key = key; |
142 } | 147 } |
143 } | 148 } |
144 return %StringBuilderConcat(elements, elements_length, ''); | 149 return %StringBuilderConcat(elements, elements_length, ''); |
145 } | 150 } |
146 | 151 |
147 | 152 |
148 function StringBuilderJoin(elements, length, separator) { | |
149 length = MinSimple(elements.length, length); | |
150 if (length == 0) return ""; | |
151 var result = elements[0]; | |
152 for (var i = 1; i < length; i++) { | |
153 result = result + separator + elements[i]; | |
154 } | |
155 return result; | |
156 } | |
157 | |
158 | |
159 function UseSparseVariant(array, length, is_array, touched) { | 153 function UseSparseVariant(array, length, is_array, touched) { |
160 // Only use the sparse variant on arrays that are likely to be sparse and the | 154 // Only use the sparse variant on arrays that are likely to be sparse and the |
161 // number of elements touched in the operation is relatively small compared to | 155 // number of elements touched in the operation is relatively small compared to |
162 // the overall size of the array. | 156 // the overall size of the array. |
163 if (!is_array || length < 1000 || %IsObserved(array) || | 157 if (!is_array || length < 1000 || %IsObserved(array) || |
164 %HasComplexElements(array)) { | 158 %HasComplexElements(array)) { |
165 return false; | 159 return false; |
166 } | 160 } |
167 if (!%_IsSmi(length)) { | 161 if (!%_IsSmi(length)) { |
168 return true; | 162 return true; |
169 } | 163 } |
170 var elements_threshold = length >> 2; // No more than 75% holes | 164 var elements_threshold = length >> 2; // No more than 75% holes |
171 var estimated_elements = %EstimateNumberOfElements(array); | 165 var estimated_elements = %EstimateNumberOfElements(array); |
172 return (estimated_elements < elements_threshold) && | 166 return (estimated_elements < elements_threshold) && |
173 (touched > estimated_elements * 4); | 167 (touched > estimated_elements * 4); |
174 } | 168 } |
175 | 169 |
176 function Stack() { | |
177 this.length = 0; | |
178 this.values = new InternalArray(); | |
179 } | |
180 | |
181 // Predeclare the instance variables on the prototype. Otherwise setting them in | |
182 // the constructor will leak the instance through settings on Object.prototype. | |
183 Stack.prototype.length = null; | |
184 Stack.prototype.values = null; | |
185 | |
186 function StackPush(stack, value) { | |
187 stack.values[stack.length++] = value; | |
188 } | |
189 | |
190 function StackPop(stack) { | |
191 stack.values[--stack.length] = null | |
192 } | |
193 | |
194 function StackHas(stack, v) { | |
195 var length = stack.length; | |
196 var values = stack.values; | |
197 for (var i = 0; i < length; i++) { | |
198 if (values[i] === v) return true; | |
199 } | |
200 return false; | |
201 } | |
202 | |
203 // Global list of arrays visited during toString, toLocaleString and | |
204 // join invocations. | |
205 var visited_arrays = new Stack(); | |
206 | 170 |
207 function Join(array, length, separator, convert) { | 171 function Join(array, length, separator, convert) { |
208 if (length == 0) return ''; | 172 if (length == 0) return ''; |
209 | 173 |
210 var is_array = IS_ARRAY(array); | 174 var is_array = IS_ARRAY(array); |
211 | 175 |
212 if (is_array) { | 176 if (is_array) { |
213 // If the array is cyclic, return the empty string for already | 177 // If the array is cyclic, return the empty string for already |
214 // visited arrays. | 178 // visited arrays. |
215 if (StackHas(visited_arrays, array)) return ''; | 179 if (!%PushIfAbsent(visited_arrays, array)) return ''; |
216 StackPush(visited_arrays, array); | |
217 } | 180 } |
218 | 181 |
219 // Attempt to convert the elements. | 182 // Attempt to convert the elements. |
220 try { | 183 try { |
221 if (UseSparseVariant(array, length, is_array, length)) { | 184 if (UseSparseVariant(array, length, is_array, length)) { |
222 %NormalizeElements(array); | 185 %NormalizeElements(array); |
223 if (separator.length == 0) { | 186 if (separator.length == 0) { |
224 return SparseJoin(array, length, convert); | 187 return SparseJoin(array, length, convert); |
225 } else { | 188 } else { |
226 return SparseJoinWithSeparatorJS(array, length, convert, separator); | 189 return SparseJoinWithSeparatorJS(array, length, convert, separator); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 for (var i = 1; i < length; i++) { | 228 for (var i = 1; i < length; i++) { |
266 e = array[i]; | 229 e = array[i]; |
267 if (IS_NUMBER(e)) { | 230 if (IS_NUMBER(e)) { |
268 e = %_NumberToString(e); | 231 e = %_NumberToString(e); |
269 } else if (!IS_STRING(e)) { | 232 } else if (!IS_STRING(e)) { |
270 e = convert(e); | 233 e = convert(e); |
271 } | 234 } |
272 elements[i] = e; | 235 elements[i] = e; |
273 } | 236 } |
274 } | 237 } |
275 return StringBuilderJoin(elements, length, separator); | 238 return %StringBuilderJoin(elements, length, separator); |
276 } finally { | 239 } finally { |
277 // Make sure to remove the last element of the visited array no | 240 // Make sure to remove the last element of the visited array no |
278 // matter what happens. | 241 // matter what happens. |
279 if (is_array) StackPop(visited_arrays); | 242 if (is_array) visited_arrays.length = visited_arrays.length - 1; |
280 } | 243 } |
281 } | 244 } |
282 | 245 |
283 | 246 |
284 function ConvertToString(x) { | 247 function ConvertToString(x) { |
285 if (IS_NULL_OR_UNDEFINED(x)) { | 248 if (IS_NULL_OR_UNDEFINED(x)) { |
286 return ''; | 249 return ''; |
287 } else { | 250 } else { |
288 return TO_STRING(x); | 251 return TO_STRING(x); |
289 } | 252 } |
(...skipping 1699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1989 to.InnerArrayIncludes = InnerArrayIncludes; | 1952 to.InnerArrayIncludes = InnerArrayIncludes; |
1990 to.InnerArrayIndexOf = InnerArrayIndexOf; | 1953 to.InnerArrayIndexOf = InnerArrayIndexOf; |
1991 to.InnerArrayJoin = InnerArrayJoin; | 1954 to.InnerArrayJoin = InnerArrayJoin; |
1992 to.InnerArrayLastIndexOf = InnerArrayLastIndexOf; | 1955 to.InnerArrayLastIndexOf = InnerArrayLastIndexOf; |
1993 to.InnerArrayReduce = InnerArrayReduce; | 1956 to.InnerArrayReduce = InnerArrayReduce; |
1994 to.InnerArrayReduceRight = InnerArrayReduceRight; | 1957 to.InnerArrayReduceRight = InnerArrayReduceRight; |
1995 to.InnerArraySome = InnerArraySome; | 1958 to.InnerArraySome = InnerArraySome; |
1996 to.InnerArraySort = InnerArraySort; | 1959 to.InnerArraySort = InnerArraySort; |
1997 to.InnerArrayToLocaleString = InnerArrayToLocaleString; | 1960 to.InnerArrayToLocaleString = InnerArrayToLocaleString; |
1998 to.PackedArrayReverse = PackedArrayReverse; | 1961 to.PackedArrayReverse = PackedArrayReverse; |
1999 to.Stack = Stack; | |
2000 to.StackHas = StackHas; | |
2001 to.StackPush = StackPush; | |
2002 to.StackPop = StackPop; | |
2003 }); | 1962 }); |
2004 | 1963 |
2005 %InstallToContext([ | 1964 %InstallToContext([ |
2006 "array_pop", ArrayPop, | 1965 "array_pop", ArrayPop, |
2007 "array_push", ArrayPush, | 1966 "array_push", ArrayPush, |
2008 "array_shift", ArrayShift, | 1967 "array_shift", ArrayShift, |
2009 "array_splice", ArraySplice, | 1968 "array_splice", ArraySplice, |
2010 "array_slice", ArraySlice, | 1969 "array_slice", ArraySlice, |
2011 "array_unshift", ArrayUnshift, | 1970 "array_unshift", ArrayUnshift, |
2012 ]); | 1971 ]); |
2013 | 1972 |
2014 }); | 1973 }); |
OLD | NEW |