Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(263)

Side by Side Diff: src/array.js

Issue 6602081: Stop using plain Arrays internally in built-in functions. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Changed header in bootstrapper.cc Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/builtins-arm.cc ('k') | src/bootstrapper.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 15 matching lines...) Expand all
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 // This file relies on the fact that the following declarations have been made 28 // This file relies on the fact that the following declarations have been made
29 // in runtime.js: 29 // in runtime.js:
30 // const $Array = global.Array; 30 // const $Array = global.Array;
31 31
32 // ------------------------------------------------------------------- 32 // -------------------------------------------------------------------
33 33
34 // Global list of arrays visited during toString, toLocaleString and 34 // Global list of arrays visited during toString, toLocaleString and
35 // join invocations. 35 // join invocations.
36 var visited_arrays = new $Array(); 36 var visited_arrays = new InternalArray();
37 37
38 38
39 // Gets a sorted array of array keys. Useful for operations on sparse 39 // Gets a sorted array of array keys. Useful for operations on sparse
40 // arrays. Dupes have not been removed. 40 // arrays. Dupes have not been removed.
41 function GetSortedArrayKeys(array, intervals) { 41 function GetSortedArrayKeys(array, intervals) {
42 var length = intervals.length; 42 var length = intervals.length;
43 var keys = []; 43 var keys = [];
44 for (var k = 0; k < length; k++) { 44 for (var k = 0; k < length; k++) {
45 var key = intervals[k]; 45 var key = intervals[k];
46 if (key < 0) { 46 if (key < 0) {
(...skipping 19 matching lines...) Expand all
66 return keys; 66 return keys;
67 } 67 }
68 68
69 69
70 // Optimized for sparse arrays if separator is ''. 70 // Optimized for sparse arrays if separator is ''.
71 function SparseJoin(array, len, convert) { 71 function SparseJoin(array, len, convert) {
72 var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, len)); 72 var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, len));
73 var last_key = -1; 73 var last_key = -1;
74 var keys_length = keys.length; 74 var keys_length = keys.length;
75 75
76 var elements = new $Array(keys_length); 76 var elements = new InternalArray(keys_length);
77 var elements_length = 0; 77 var elements_length = 0;
78 78
79 for (var i = 0; i < keys_length; i++) { 79 for (var i = 0; i < keys_length; i++) {
80 var key = keys[i]; 80 var key = keys[i];
81 if (key != last_key) { 81 if (key != last_key) {
82 var e = array[key]; 82 var e = array[key];
83 if (!IS_STRING(e)) e = convert(e); 83 if (!IS_STRING(e)) e = convert(e);
84 elements[elements_length++] = e; 84 elements[elements_length++] = e;
85 last_key = key; 85 last_key = key;
86 } 86 }
(...skipping 28 matching lines...) Expand all
115 } 115 }
116 116
117 // Fast case for one-element arrays. 117 // Fast case for one-element arrays.
118 if (length == 1) { 118 if (length == 1) {
119 var e = array[0]; 119 var e = array[0];
120 if (IS_STRING(e)) return e; 120 if (IS_STRING(e)) return e;
121 return convert(e); 121 return convert(e);
122 } 122 }
123 123
124 // Construct an array for the elements. 124 // Construct an array for the elements.
125 var elements = new $Array(length); 125 var elements = new InternalArray(length);
126 126
127 // We pull the empty separator check outside the loop for speed! 127 // We pull the empty separator check outside the loop for speed!
128 if (separator.length == 0) { 128 if (separator.length == 0) {
129 var elements_length = 0; 129 var elements_length = 0;
130 for (var i = 0; i < length; i++) { 130 for (var i = 0; i < length; i++) {
131 var e = array[i]; 131 var e = array[i];
132 if (!IS_UNDEFINED(e)) { 132 if (!IS_UNDEFINED(e)) {
133 if (!IS_STRING(e)) e = convert(e); 133 if (!IS_STRING(e)) e = convert(e);
134 elements[elements_length++] = e; 134 elements[elements_length++] = e;
135 } 135 }
136 } 136 }
137 elements.length = elements_length; 137 elements.length = elements_length;
138 var result = %_FastAsciiArrayJoin(elements, ''); 138 var result = %_FastAsciiArrayJoin(elements, '');
139 if (!IS_UNDEFINED(result)) return result; 139 if (!IS_UNDEFINED(result)) return result;
140 return %StringBuilderConcat(elements, elements_length, ''); 140 return %StringBuilderConcat(elements, elements_length, '');
141 } 141 }
142 // Non-empty separator case. 142 // Non-empty separator case.
143 // If the first element is a number then use the heuristic that the 143 // If the first element is a number then use the heuristic that the
144 // remaining elements are also likely to be numbers. 144 // remaining elements are also likely to be numbers.
145 if (!IS_NUMBER(array[0])) { 145 if (!IS_NUMBER(array[0])) {
146 for (var i = 0; i < length; i++) { 146 for (var i = 0; i < length; i++) {
147 var e = array[i]; 147 var e = array[i];
148 if (!IS_STRING(e)) e = convert(e); 148 if (!IS_STRING(e)) e = convert(e);
149 elements[i] = e; 149 elements[i] = e;
150 } 150 }
151 } else { 151 } else {
152 for (var i = 0; i < length; i++) { 152 for (var i = 0; i < length; i++) {
153 var e = array[i]; 153 var e = array[i];
154 if (IS_NUMBER(e)) elements[i] = %_NumberToString(e); 154 if (IS_NUMBER(e)) elements[i] = %_NumberToString(e);
155 else { 155 else {
156 if (!IS_STRING(e)) e = convert(e); 156 if (!IS_STRING(e)) e = convert(e);
157 elements[i] = e; 157 elements[i] = e;
158 } 158 }
159 } 159 }
160 } 160 }
161 var result = %_FastAsciiArrayJoin(elements, separator); 161 var result = %_FastAsciiArrayJoin(elements, separator);
162 if (!IS_UNDEFINED(result)) return result; 162 if (!IS_UNDEFINED(result)) return result;
163 163
164 return %StringBuilderJoin(elements, length, separator); 164 return %StringBuilderJoin(elements, length, separator);
165 } finally { 165 } finally {
166 // Make sure to remove the last element of the visited array no 166 // Make sure to remove the last element of the visited array no
167 // matter what happens. 167 // matter what happens.
168 if (is_array) visited_arrays.length = visited_arrays.length - 1; 168 if (is_array) visited_arrays.length = visited_arrays.length - 1;
169 } 169 }
170 } 170 }
171 171
172 172
173 function ConvertToString(x) { 173 function ConvertToString(x) {
174 // Assumes x is a non-string. 174 // Assumes x is a non-string.
175 if (IS_NUMBER(x)) return %_NumberToString(x); 175 if (IS_NUMBER(x)) return %_NumberToString(x);
176 if (IS_BOOLEAN(x)) return x ? 'true' : 'false'; 176 if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
177 return (IS_NULL_OR_UNDEFINED(x)) ? '' : %ToString(%DefaultString(x)); 177 return (IS_NULL_OR_UNDEFINED(x)) ? '' : %ToString(%DefaultString(x));
178 } 178 }
179 179
180 180
181 function ConvertToLocaleString(e) { 181 function ConvertToLocaleString(e) {
182 if (e == null) { 182 if (e == null) {
183 return ''; 183 return '';
184 } else { 184 } else {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 } 234 }
235 } 235 }
236 } 236 }
237 } 237 }
238 238
239 239
240 // This function implements the optimized splice implementation that can use 240 // This function implements the optimized splice implementation that can use
241 // special array operations to handle sparse arrays in a sensible fashion. 241 // special array operations to handle sparse arrays in a sensible fashion.
242 function SmartMove(array, start_i, del_count, len, num_additional_args) { 242 function SmartMove(array, start_i, del_count, len, num_additional_args) {
243 // Move data to new array. 243 // Move data to new array.
244 var new_array = new $Array(len - del_count + num_additional_args); 244 var new_array = new InternalArray(len - del_count + num_additional_args);
245 var intervals = %GetArrayKeys(array, len); 245 var intervals = %GetArrayKeys(array, len);
246 var length = intervals.length; 246 var length = intervals.length;
247 for (var k = 0; k < length; k++) { 247 for (var k = 0; k < length; k++) {
248 var key = intervals[k]; 248 var key = intervals[k];
249 if (key < 0) { 249 if (key < 0) {
250 var j = -1 - key; 250 var j = -1 - key;
251 var interval_limit = j + intervals[++k]; 251 var interval_limit = j + intervals[++k];
252 while (j < start_i && j < interval_limit) { 252 while (j < start_i && j < interval_limit) {
253 // The spec could also be interpreted such that 253 // The spec could also be interpreted such that
254 // %HasLocalProperty would be the appropriate test. We follow 254 // %HasLocalProperty would be the appropriate test. We follow
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 for (var i = 0; i < m; i++) { 412 for (var i = 0; i < m; i++) {
413 this[i+n] = %_Arguments(i); 413 this[i+n] = %_Arguments(i);
414 } 414 }
415 this.length = n + m; 415 this.length = n + m;
416 return this.length; 416 return this.length;
417 } 417 }
418 418
419 419
420 function ArrayConcat(arg1) { // length == 1 420 function ArrayConcat(arg1) { // length == 1
421 var arg_count = %_ArgumentsLength(); 421 var arg_count = %_ArgumentsLength();
422 var arrays = new $Array(1 + arg_count); 422 var arrays = new InternalArray(1 + arg_count);
423 arrays[0] = this; 423 arrays[0] = this;
424 for (var i = 0; i < arg_count; i++) { 424 for (var i = 0; i < arg_count; i++) {
425 arrays[i + 1] = %_Arguments(i); 425 arrays[i + 1] = %_Arguments(i);
426 } 426 }
427 427
428 return %ArrayConcat(arrays); 428 return %ArrayConcat(arrays);
429 } 429 }
430 430
431 431
432 // For implementing reverse() on large, sparse arrays. 432 // For implementing reverse() on large, sparse arrays.
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after
918 throw MakeTypeError('called_non_callable', [ f ]); 918 throw MakeTypeError('called_non_callable', [ f ]);
919 } 919 }
920 // Pull out the length so that modifications to the length in the 920 // Pull out the length so that modifications to the length in the
921 // loop will not affect the looping. 921 // loop will not affect the looping.
922 var length = this.length; 922 var length = this.length;
923 var result = []; 923 var result = [];
924 var result_length = 0; 924 var result_length = 0;
925 for (var i = 0; i < length; i++) { 925 for (var i = 0; i < length; i++) {
926 var current = this[i]; 926 var current = this[i];
927 if (!IS_UNDEFINED(current) || i in this) { 927 if (!IS_UNDEFINED(current) || i in this) {
928 if (f.call(receiver, current, i, this)) result[result_length++] = current; 928 if (%_CallFunction(receiver, current, i, this, f)) {
929 result[result_length++] = current;
930 }
929 } 931 }
930 } 932 }
931 return result; 933 return result;
932 } 934 }
933 935
934 936
935 function ArrayForEach(f, receiver) { 937 function ArrayForEach(f, receiver) {
936 if (!IS_FUNCTION(f)) { 938 if (!IS_FUNCTION(f)) {
937 throw MakeTypeError('called_non_callable', [ f ]); 939 throw MakeTypeError('called_non_callable', [ f ]);
938 } 940 }
939 // Pull out the length so that modifications to the length in the 941 // Pull out the length so that modifications to the length in the
940 // loop will not affect the looping. 942 // loop will not affect the looping.
941 var length = TO_UINT32(this.length); 943 var length = TO_UINT32(this.length);
942 for (var i = 0; i < length; i++) { 944 for (var i = 0; i < length; i++) {
943 var current = this[i]; 945 var current = this[i];
944 if (!IS_UNDEFINED(current) || i in this) { 946 if (!IS_UNDEFINED(current) || i in this) {
945 f.call(receiver, current, i, this); 947 %_CallFunction(receiver, current, i, this, f);
946 } 948 }
947 } 949 }
948 } 950 }
949 951
950 952
951 // Executes the function once for each element present in the 953 // Executes the function once for each element present in the
952 // array until it finds one where callback returns true. 954 // array until it finds one where callback returns true.
953 function ArraySome(f, receiver) { 955 function ArraySome(f, receiver) {
954 if (!IS_FUNCTION(f)) { 956 if (!IS_FUNCTION(f)) {
955 throw MakeTypeError('called_non_callable', [ f ]); 957 throw MakeTypeError('called_non_callable', [ f ]);
956 } 958 }
957 // Pull out the length so that modifications to the length in the 959 // Pull out the length so that modifications to the length in the
958 // loop will not affect the looping. 960 // loop will not affect the looping.
959 var length = TO_UINT32(this.length); 961 var length = TO_UINT32(this.length);
960 for (var i = 0; i < length; i++) { 962 for (var i = 0; i < length; i++) {
961 var current = this[i]; 963 var current = this[i];
962 if (!IS_UNDEFINED(current) || i in this) { 964 if (!IS_UNDEFINED(current) || i in this) {
963 if (f.call(receiver, current, i, this)) return true; 965 if (%_CallFunction(receiver, current, i, this, f)) return true;
964 } 966 }
965 } 967 }
966 return false; 968 return false;
967 } 969 }
968 970
969 971
970 function ArrayEvery(f, receiver) { 972 function ArrayEvery(f, receiver) {
971 if (!IS_FUNCTION(f)) { 973 if (!IS_FUNCTION(f)) {
972 throw MakeTypeError('called_non_callable', [ f ]); 974 throw MakeTypeError('called_non_callable', [ f ]);
973 } 975 }
974 // Pull out the length so that modifications to the length in the 976 // Pull out the length so that modifications to the length in the
975 // loop will not affect the looping. 977 // loop will not affect the looping.
976 var length = TO_UINT32(this.length); 978 var length = TO_UINT32(this.length);
977 for (var i = 0; i < length; i++) { 979 for (var i = 0; i < length; i++) {
978 var current = this[i]; 980 var current = this[i];
979 if (!IS_UNDEFINED(current) || i in this) { 981 if (!IS_UNDEFINED(current) || i in this) {
980 if (!f.call(receiver, current, i, this)) return false; 982 if (!%_CallFunction(receiver, current, i, this, f)) return false;
981 } 983 }
982 } 984 }
983 return true; 985 return true;
984 } 986 }
985 987
986 function ArrayMap(f, receiver) { 988 function ArrayMap(f, receiver) {
987 if (!IS_FUNCTION(f)) { 989 if (!IS_FUNCTION(f)) {
988 throw MakeTypeError('called_non_callable', [ f ]); 990 throw MakeTypeError('called_non_callable', [ f ]);
989 } 991 }
990 // Pull out the length so that modifications to the length in the 992 // Pull out the length so that modifications to the length in the
991 // loop will not affect the looping. 993 // loop will not affect the looping.
992 var length = TO_UINT32(this.length); 994 var length = TO_UINT32(this.length);
993 var result = new $Array(length); 995 var result = new $Array();
996 var accumulator = new InternalArray(length);
994 for (var i = 0; i < length; i++) { 997 for (var i = 0; i < length; i++) {
995 var current = this[i]; 998 var current = this[i];
996 if (!IS_UNDEFINED(current) || i in this) { 999 if (!IS_UNDEFINED(current) || i in this) {
997 result[i] = f.call(receiver, current, i, this); 1000 accumulator[i] = %_CallFunction(receiver, current, i, this, f);
998 } 1001 }
999 } 1002 }
1003 %MoveArrayContents(accumulator, result);
1000 return result; 1004 return result;
1001 } 1005 }
1002 1006
1003 1007
1004 function ArrayIndexOf(element, index) { 1008 function ArrayIndexOf(element, index) {
1005 var length = TO_UINT32(this.length); 1009 var length = TO_UINT32(this.length);
1006 if (length == 0) return -1; 1010 if (length == 0) return -1;
1007 if (IS_UNDEFINED(index)) { 1011 if (IS_UNDEFINED(index)) {
1008 index = 0; 1012 index = 0;
1009 } else { 1013 } else {
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
1127 i++; 1131 i++;
1128 break find_initial; 1132 break find_initial;
1129 } 1133 }
1130 } 1134 }
1131 throw MakeTypeError('reduce_no_initial', []); 1135 throw MakeTypeError('reduce_no_initial', []);
1132 } 1136 }
1133 1137
1134 for (; i < length; i++) { 1138 for (; i < length; i++) {
1135 var element = this[i]; 1139 var element = this[i];
1136 if (!IS_UNDEFINED(element) || i in this) { 1140 if (!IS_UNDEFINED(element) || i in this) {
1137 current = callback.call(null, current, element, i, this); 1141 current = %_CallFunction(null, current, element, i, this, callback);
1138 } 1142 }
1139 } 1143 }
1140 return current; 1144 return current;
1141 } 1145 }
1142 1146
1143 function ArrayReduceRight(callback, current) { 1147 function ArrayReduceRight(callback, current) {
1144 if (!IS_FUNCTION(callback)) { 1148 if (!IS_FUNCTION(callback)) {
1145 throw MakeTypeError('called_non_callable', [callback]); 1149 throw MakeTypeError('called_non_callable', [callback]);
1146 } 1150 }
1147 var i = this.length - 1; 1151 var i = this.length - 1;
1148 1152
1149 find_initial: if (%_ArgumentsLength() < 2) { 1153 find_initial: if (%_ArgumentsLength() < 2) {
1150 for (; i >= 0; i--) { 1154 for (; i >= 0; i--) {
1151 current = this[i]; 1155 current = this[i];
1152 if (!IS_UNDEFINED(current) || i in this) { 1156 if (!IS_UNDEFINED(current) || i in this) {
1153 i--; 1157 i--;
1154 break find_initial; 1158 break find_initial;
1155 } 1159 }
1156 } 1160 }
1157 throw MakeTypeError('reduce_no_initial', []); 1161 throw MakeTypeError('reduce_no_initial', []);
1158 } 1162 }
1159 1163
1160 for (; i >= 0; i--) { 1164 for (; i >= 0; i--) {
1161 var element = this[i]; 1165 var element = this[i];
1162 if (!IS_UNDEFINED(element) || i in this) { 1166 if (!IS_UNDEFINED(element) || i in this) {
1163 current = callback.call(null, current, element, i, this); 1167 current = %_CallFunction(null, current, element, i, this, callback);
1164 } 1168 }
1165 } 1169 }
1166 return current; 1170 return current;
1167 } 1171 }
1168 1172
1169 // ES5, 15.4.3.2 1173 // ES5, 15.4.3.2
1170 function ArrayIsArray(obj) { 1174 function ArrayIsArray(obj) {
1171 return IS_ARRAY(obj); 1175 return IS_ARRAY(obj);
1172 } 1176 }
1173 1177
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1218 "some", getFunction("some", ArraySome, 1), 1222 "some", getFunction("some", ArraySome, 1),
1219 "every", getFunction("every", ArrayEvery, 1), 1223 "every", getFunction("every", ArrayEvery, 1),
1220 "map", getFunction("map", ArrayMap, 1), 1224 "map", getFunction("map", ArrayMap, 1),
1221 "indexOf", getFunction("indexOf", ArrayIndexOf, 1), 1225 "indexOf", getFunction("indexOf", ArrayIndexOf, 1),
1222 "lastIndexOf", getFunction("lastIndexOf", ArrayLastIndexOf, 1), 1226 "lastIndexOf", getFunction("lastIndexOf", ArrayLastIndexOf, 1),
1223 "reduce", getFunction("reduce", ArrayReduce, 1), 1227 "reduce", getFunction("reduce", ArrayReduce, 1),
1224 "reduceRight", getFunction("reduceRight", ArrayReduceRight, 1) 1228 "reduceRight", getFunction("reduceRight", ArrayReduceRight, 1)
1225 )); 1229 ));
1226 1230
1227 %FinishArrayPrototypeSetup($Array.prototype); 1231 %FinishArrayPrototypeSetup($Array.prototype);
1232
1233 // The internal Array prototype doesn't need to be fancy, since it's never
1234 // exposed to user code, so no hidden prototypes or DONT_ENUM attributes
1235 // are necessary.
1236 // The null __proto__ ensures that we never inherit any user created
1237 // getters or setters from, e.g., Object.prototype.
1238 InternalArray.prototype.__proto__ = null;
1239 // Adding only the functions that are actually used, and a toString.
1240 InternalArray.prototype.join = getFunction("join", ArrayJoin);
1241 InternalArray.prototype.pop = getFunction("pop", ArrayPop);
1242 InternalArray.prototype.push = getFunction("push", ArrayPush);
1243 InternalArray.prototype.toString = function() {
1244 return "Internal Array, length " + this.length;
1245 };
1228 } 1246 }
1229 1247
1230 1248
1231 SetupArray(); 1249 SetupArray();
OLDNEW
« no previous file with comments | « src/arm/builtins-arm.cc ('k') | src/bootstrapper.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698