OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 // This files contains runtime support implemented in JavaScript. | 5 // This files contains runtime support implemented in JavaScript. |
6 | 6 |
7 // CAUTION: Some of the functions specified in this file are called | 7 // CAUTION: Some of the functions specified in this file are called |
8 // directly from compiled code. These are the functions with names in | 8 // directly from compiled code. These are the functions with names in |
9 // ALL CAPS. The compiled code passes the first argument in 'this'. | 9 // ALL CAPS. The compiled code passes the first argument in 'this'. |
10 | 10 |
11 | 11 |
12 /* ----------------------------------- | |
13 - - - C o m p a r i s o n - - - | |
14 ----------------------------------- | |
15 */ | |
16 | |
17 // The following declarations are shared with other native JS files. | 12 // The following declarations are shared with other native JS files. |
18 // They are all declared at this one spot to avoid redeclaration errors. | 13 // They are all declared at this one spot to avoid redeclaration errors. |
19 var EQUALS; | |
20 var STRICT_EQUALS; | |
21 var COMPARE; | |
22 var COMPARE_STRONG; | |
23 var ADD; | |
24 var ADD_STRONG; | |
25 var STRING_ADD_LEFT; | |
26 var STRING_ADD_RIGHT; | |
27 var SUB; | |
28 var SUB_STRONG; | |
29 var MUL; | |
30 var MUL_STRONG; | |
31 var DIV; | |
32 var DIV_STRONG; | |
33 var MOD; | |
34 var MOD_STRONG; | |
35 var BIT_OR; | |
36 var BIT_OR_STRONG; | |
37 var BIT_AND; | |
38 var BIT_AND_STRONG; | |
39 var BIT_XOR; | |
40 var BIT_XOR_STRONG; | |
41 var SHL; | |
42 var SHL_STRONG; | |
43 var SAR; | |
44 var SAR_STRONG; | |
45 var SHR; | |
46 var SHR_STRONG; | |
47 var IN; | |
48 var INSTANCE_OF; | |
49 var CALL_NON_FUNCTION; | |
50 var CALL_NON_FUNCTION_AS_CONSTRUCTOR; | |
51 var CALL_FUNCTION_PROXY; | |
52 var CALL_FUNCTION_PROXY_AS_CONSTRUCTOR; | |
53 var CONCAT_ITERABLE_TO_ARRAY; | |
54 var APPLY_PREPARE; | |
55 var REFLECT_APPLY_PREPARE; | |
56 var REFLECT_CONSTRUCT_PREPARE; | |
57 var STACK_OVERFLOW; | |
58 var TO_NUMBER; | |
59 var TO_STRING; | |
60 var TO_NAME; | |
61 | |
62 var $defaultNumber; | 14 var $defaultNumber; |
63 var $defaultString; | 15 var $defaultString; |
64 var $NaN; | 16 var $NaN; |
65 var $nonNumberToNumber; | 17 var $nonNumberToNumber; |
66 var $nonStringToString; | 18 var $nonStringToString; |
67 var $sameValue; | 19 var $sameValue; |
68 var $sameValueZero; | 20 var $sameValueZero; |
69 var $toBoolean; | 21 var $toBoolean; |
70 var $toInteger; | 22 var $toInteger; |
71 var $toLength; | 23 var $toLength; |
72 var $toName; | 24 var $toName; |
73 var $toNumber; | 25 var $toNumber; |
74 var $toPositiveInteger; | 26 var $toPositiveInteger; |
75 var $toPrimitive; | 27 var $toPrimitive; |
76 var $toString; | 28 var $toString; |
77 | 29 |
78 (function(global, utils) { | 30 (function(global, utils) { |
79 | 31 |
80 %CheckIsBootstrapping(); | 32 %CheckIsBootstrapping(); |
81 | 33 |
82 var GlobalArray = global.Array; | 34 var GlobalArray = global.Array; |
83 var GlobalBoolean = global.Boolean; | 35 var GlobalBoolean = global.Boolean; |
84 var GlobalString = global.String; | 36 var GlobalString = global.String; |
85 var GlobalNumber = global.Number; | 37 var GlobalNumber = global.Number; |
86 | 38 |
87 // ---------------------------------------------------------------------------- | 39 // ---------------------------------------------------------------------------- |
88 | 40 |
| 41 /* ----------------------------------- |
| 42 - - - C o m p a r i s o n - - - |
| 43 ----------------------------------- |
| 44 */ |
| 45 |
89 // ECMA-262 Section 11.9.3. | 46 // ECMA-262 Section 11.9.3. |
90 EQUALS = function EQUALS(y) { | 47 function EQUALS(y) { |
91 if (IS_STRING(this) && IS_STRING(y)) return %StringEquals(this, y); | 48 if (IS_STRING(this) && IS_STRING(y)) return %StringEquals(this, y); |
92 var x = this; | 49 var x = this; |
93 | 50 |
94 while (true) { | 51 while (true) { |
95 if (IS_NUMBER(x)) { | 52 if (IS_NUMBER(x)) { |
96 while (true) { | 53 while (true) { |
97 if (IS_NUMBER(y)) return %NumberEquals(x, y); | 54 if (IS_NUMBER(y)) return %NumberEquals(x, y); |
98 if (IS_NULL_OR_UNDEFINED(y)) return 1; // not equal | 55 if (IS_NULL_OR_UNDEFINED(y)) return 1; // not equal |
99 if (!IS_SPEC_OBJECT(y)) { | 56 if (!IS_SPEC_OBJECT(y)) { |
100 if (IS_SYMBOL(y) || IS_SIMD_VALUE(y)) return 1; // not equal | 57 if (IS_SYMBOL(y) || IS_SIMD_VALUE(y)) return 1; // not equal |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 return 1; // not equal | 96 return 1; // not equal |
140 } | 97 } |
141 x = %$toPrimitive(x, NO_HINT); | 98 x = %$toPrimitive(x, NO_HINT); |
142 } | 99 } |
143 } | 100 } |
144 } | 101 } |
145 | 102 |
146 | 103 |
147 // ECMA-262, section 11.8.5, page 53. The 'ncr' parameter is used as | 104 // ECMA-262, section 11.8.5, page 53. The 'ncr' parameter is used as |
148 // the result when either (or both) the operands are NaN. | 105 // the result when either (or both) the operands are NaN. |
149 COMPARE = function COMPARE(x, ncr) { | 106 function COMPARE(x, ncr) { |
150 var left; | 107 var left; |
151 var right; | 108 var right; |
152 // Fast cases for string, numbers and undefined compares. | 109 // Fast cases for string, numbers and undefined compares. |
153 if (IS_STRING(this)) { | 110 if (IS_STRING(this)) { |
154 if (IS_STRING(x)) return %_StringCompare(this, x); | 111 if (IS_STRING(x)) return %_StringCompare(this, x); |
155 if (IS_UNDEFINED(x)) return ncr; | 112 if (IS_UNDEFINED(x)) return ncr; |
156 left = this; | 113 left = this; |
157 } else if (IS_NUMBER(this)) { | 114 } else if (IS_NUMBER(this)) { |
158 if (IS_NUMBER(x)) return %NumberCompare(this, x, ncr); | 115 if (IS_NUMBER(x)) return %NumberCompare(this, x, ncr); |
159 if (IS_UNDEFINED(x)) return ncr; | 116 if (IS_UNDEFINED(x)) return ncr; |
(...skipping 15 matching lines...) Expand all Loading... |
175 return %_StringCompare(left, right); | 132 return %_StringCompare(left, right); |
176 } else { | 133 } else { |
177 var left_number = %$toNumber(left); | 134 var left_number = %$toNumber(left); |
178 var right_number = %$toNumber(right); | 135 var right_number = %$toNumber(right); |
179 if (NUMBER_IS_NAN(left_number) || NUMBER_IS_NAN(right_number)) return ncr; | 136 if (NUMBER_IS_NAN(left_number) || NUMBER_IS_NAN(right_number)) return ncr; |
180 return %NumberCompare(left_number, right_number, ncr); | 137 return %NumberCompare(left_number, right_number, ncr); |
181 } | 138 } |
182 } | 139 } |
183 | 140 |
184 // Strong mode COMPARE throws if an implicit conversion would be performed | 141 // Strong mode COMPARE throws if an implicit conversion would be performed |
185 COMPARE_STRONG = function COMPARE_STRONG(x, ncr) { | 142 function COMPARE_STRONG(x, ncr) { |
186 if (IS_STRING(this) && IS_STRING(x)) return %_StringCompare(this, x); | 143 if (IS_STRING(this) && IS_STRING(x)) return %_StringCompare(this, x); |
187 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberCompare(this, x, ncr); | 144 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberCompare(this, x, ncr); |
188 | 145 |
189 throw %MakeTypeError(kStrongImplicitConversion); | 146 throw %MakeTypeError(kStrongImplicitConversion); |
190 } | 147 } |
191 | 148 |
192 | 149 |
193 | 150 |
194 /* ----------------------------------- | 151 /* ----------------------------------- |
195 - - - A r i t h m e t i c - - - | 152 - - - A r i t h m e t i c - - - |
196 ----------------------------------- | 153 ----------------------------------- |
197 */ | 154 */ |
198 | 155 |
199 // ECMA-262, section 11.6.1, page 50. | 156 // ECMA-262, section 11.6.1, page 50. |
200 ADD = function ADD(x) { | 157 function ADD(x) { |
201 // Fast case: Check for number operands and do the addition. | 158 // Fast case: Check for number operands and do the addition. |
202 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x); | 159 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x); |
203 if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x); | 160 if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x); |
204 | 161 |
205 // Default implementation. | 162 // Default implementation. |
206 var a = %$toPrimitive(this, NO_HINT); | 163 var a = %$toPrimitive(this, NO_HINT); |
207 var b = %$toPrimitive(x, NO_HINT); | 164 var b = %$toPrimitive(x, NO_HINT); |
208 | 165 |
209 if (IS_STRING(a)) { | 166 if (IS_STRING(a)) { |
210 return %_StringAdd(a, %$toString(b)); | 167 return %_StringAdd(a, %$toString(b)); |
211 } else if (IS_STRING(b)) { | 168 } else if (IS_STRING(b)) { |
212 return %_StringAdd(%$nonStringToString(a), b); | 169 return %_StringAdd(%$nonStringToString(a), b); |
213 } else { | 170 } else { |
214 return %NumberAdd(%$toNumber(a), %$toNumber(b)); | 171 return %NumberAdd(%$toNumber(a), %$toNumber(b)); |
215 } | 172 } |
216 } | 173 } |
217 | 174 |
218 | 175 |
219 // Strong mode ADD throws if an implicit conversion would be performed | 176 // Strong mode ADD throws if an implicit conversion would be performed |
220 ADD_STRONG = function ADD_STRONG(x) { | 177 function ADD_STRONG(x) { |
221 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x); | 178 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x); |
222 if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x); | 179 if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x); |
223 | 180 |
224 throw %MakeTypeError(kStrongImplicitConversion); | 181 throw %MakeTypeError(kStrongImplicitConversion); |
225 } | 182 } |
226 | 183 |
227 | 184 |
228 // Left operand (this) is already a string. | 185 // Left operand (this) is already a string. |
229 STRING_ADD_LEFT = function STRING_ADD_LEFT(y) { | 186 function STRING_ADD_LEFT(y) { |
230 if (!IS_STRING(y)) { | 187 if (!IS_STRING(y)) { |
231 if (IS_STRING_WRAPPER(y) && %_IsStringWrapperSafeForDefaultValueOf(y)) { | 188 if (IS_STRING_WRAPPER(y) && %_IsStringWrapperSafeForDefaultValueOf(y)) { |
232 y = %_ValueOf(y); | 189 y = %_ValueOf(y); |
233 } else { | 190 } else { |
234 y = IS_NUMBER(y) | 191 y = IS_NUMBER(y) |
235 ? %_NumberToString(y) | 192 ? %_NumberToString(y) |
236 : %$toString(%$toPrimitive(y, NO_HINT)); | 193 : %$toString(%$toPrimitive(y, NO_HINT)); |
237 } | 194 } |
238 } | 195 } |
239 return %_StringAdd(this, y); | 196 return %_StringAdd(this, y); |
240 } | 197 } |
241 | 198 |
242 | 199 |
243 // Right operand (y) is already a string. | 200 // Right operand (y) is already a string. |
244 STRING_ADD_RIGHT = function STRING_ADD_RIGHT(y) { | 201 function STRING_ADD_RIGHT(y) { |
245 var x = this; | 202 var x = this; |
246 if (!IS_STRING(x)) { | 203 if (!IS_STRING(x)) { |
247 if (IS_STRING_WRAPPER(x) && %_IsStringWrapperSafeForDefaultValueOf(x)) { | 204 if (IS_STRING_WRAPPER(x) && %_IsStringWrapperSafeForDefaultValueOf(x)) { |
248 x = %_ValueOf(x); | 205 x = %_ValueOf(x); |
249 } else { | 206 } else { |
250 x = IS_NUMBER(x) | 207 x = IS_NUMBER(x) |
251 ? %_NumberToString(x) | 208 ? %_NumberToString(x) |
252 : %$toString(%$toPrimitive(x, NO_HINT)); | 209 : %$toString(%$toPrimitive(x, NO_HINT)); |
253 } | 210 } |
254 } | 211 } |
255 return %_StringAdd(x, y); | 212 return %_StringAdd(x, y); |
256 } | 213 } |
257 | 214 |
258 | 215 |
259 // ECMA-262, section 11.6.2, page 50. | 216 // ECMA-262, section 11.6.2, page 50. |
260 SUB = function SUB(y) { | 217 function SUB(y) { |
261 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this); | 218 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this); |
262 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); | 219 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); |
263 return %NumberSub(x, y); | 220 return %NumberSub(x, y); |
264 } | 221 } |
265 | 222 |
266 | 223 |
267 // Strong mode SUB throws if an implicit conversion would be performed | 224 // Strong mode SUB throws if an implicit conversion would be performed |
268 SUB_STRONG = function SUB_STRONG(y) { | 225 function SUB_STRONG(y) { |
269 if (IS_NUMBER(this) && IS_NUMBER(y)) { | 226 if (IS_NUMBER(this) && IS_NUMBER(y)) { |
270 return %NumberSub(this, y); | 227 return %NumberSub(this, y); |
271 } | 228 } |
272 throw %MakeTypeError(kStrongImplicitConversion); | 229 throw %MakeTypeError(kStrongImplicitConversion); |
273 } | 230 } |
274 | 231 |
275 | 232 |
276 // ECMA-262, section 11.5.1, page 48. | 233 // ECMA-262, section 11.5.1, page 48. |
277 MUL = function MUL(y) { | 234 function MUL(y) { |
278 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this); | 235 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this); |
279 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); | 236 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); |
280 return %NumberMul(x, y); | 237 return %NumberMul(x, y); |
281 } | 238 } |
282 | 239 |
283 | 240 |
284 // Strong mode MUL throws if an implicit conversion would be performed | 241 // Strong mode MUL throws if an implicit conversion would be performed |
285 MUL_STRONG = function MUL_STRONG(y) { | 242 function MUL_STRONG(y) { |
286 if (IS_NUMBER(this) && IS_NUMBER(y)) { | 243 if (IS_NUMBER(this) && IS_NUMBER(y)) { |
287 return %NumberMul(this, y); | 244 return %NumberMul(this, y); |
288 } | 245 } |
289 throw %MakeTypeError(kStrongImplicitConversion); | 246 throw %MakeTypeError(kStrongImplicitConversion); |
290 } | 247 } |
291 | 248 |
292 | 249 |
293 // ECMA-262, section 11.5.2, page 49. | 250 // ECMA-262, section 11.5.2, page 49. |
294 DIV = function DIV(y) { | 251 function DIV(y) { |
295 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this); | 252 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this); |
296 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); | 253 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); |
297 return %NumberDiv(x, y); | 254 return %NumberDiv(x, y); |
298 } | 255 } |
299 | 256 |
300 | 257 |
301 // Strong mode DIV throws if an implicit conversion would be performed | 258 // Strong mode DIV throws if an implicit conversion would be performed |
302 DIV_STRONG = function DIV_STRONG(y) { | 259 function DIV_STRONG(y) { |
303 if (IS_NUMBER(this) && IS_NUMBER(y)) { | 260 if (IS_NUMBER(this) && IS_NUMBER(y)) { |
304 return %NumberDiv(this, y); | 261 return %NumberDiv(this, y); |
305 } | 262 } |
306 throw %MakeTypeError(kStrongImplicitConversion); | 263 throw %MakeTypeError(kStrongImplicitConversion); |
307 } | 264 } |
308 | 265 |
309 | 266 |
310 // ECMA-262, section 11.5.3, page 49. | 267 // ECMA-262, section 11.5.3, page 49. |
311 MOD = function MOD(y) { | 268 function MOD(y) { |
312 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this); | 269 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this); |
313 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); | 270 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); |
314 return %NumberMod(x, y); | 271 return %NumberMod(x, y); |
315 } | 272 } |
316 | 273 |
317 | 274 |
318 // Strong mode MOD throws if an implicit conversion would be performed | 275 // Strong mode MOD throws if an implicit conversion would be performed |
319 MOD_STRONG = function MOD_STRONG(y) { | 276 function MOD_STRONG(y) { |
320 if (IS_NUMBER(this) && IS_NUMBER(y)) { | 277 if (IS_NUMBER(this) && IS_NUMBER(y)) { |
321 return %NumberMod(this, y); | 278 return %NumberMod(this, y); |
322 } | 279 } |
323 throw %MakeTypeError(kStrongImplicitConversion); | 280 throw %MakeTypeError(kStrongImplicitConversion); |
324 } | 281 } |
325 | 282 |
326 | 283 |
327 /* ------------------------------------------- | 284 /* ------------------------------------------- |
328 - - - B i t o p e r a t i o n s - - - | 285 - - - B i t o p e r a t i o n s - - - |
329 ------------------------------------------- | 286 ------------------------------------------- |
330 */ | 287 */ |
331 | 288 |
332 // ECMA-262, section 11.10, page 57. | 289 // ECMA-262, section 11.10, page 57. |
333 BIT_OR = function BIT_OR(y) { | 290 function BIT_OR(y) { |
334 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this); | 291 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this); |
335 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); | 292 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); |
336 return %NumberOr(x, y); | 293 return %NumberOr(x, y); |
337 } | 294 } |
338 | 295 |
339 | 296 |
340 // Strong mode BIT_OR throws if an implicit conversion would be performed | 297 // Strong mode BIT_OR throws if an implicit conversion would be performed |
341 BIT_OR_STRONG = function BIT_OR_STRONG(y) { | 298 function BIT_OR_STRONG(y) { |
342 if (IS_NUMBER(this) && IS_NUMBER(y)) { | 299 if (IS_NUMBER(this) && IS_NUMBER(y)) { |
343 return %NumberOr(this, y); | 300 return %NumberOr(this, y); |
344 } | 301 } |
345 throw %MakeTypeError(kStrongImplicitConversion); | 302 throw %MakeTypeError(kStrongImplicitConversion); |
346 } | 303 } |
347 | 304 |
348 | 305 |
349 // ECMA-262, section 11.10, page 57. | 306 // ECMA-262, section 11.10, page 57. |
350 BIT_AND = function BIT_AND(y) { | 307 function BIT_AND(y) { |
351 var x; | 308 var x; |
352 if (IS_NUMBER(this)) { | 309 if (IS_NUMBER(this)) { |
353 x = this; | 310 x = this; |
354 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); | 311 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); |
355 } else { | 312 } else { |
356 x = %$nonNumberToNumber(this); | 313 x = %$nonNumberToNumber(this); |
357 // Make sure to convert the right operand to a number before | 314 // Make sure to convert the right operand to a number before |
358 // bailing out in the fast case, but after converting the | 315 // bailing out in the fast case, but after converting the |
359 // left operand. This ensures that valueOf methods on the right | 316 // left operand. This ensures that valueOf methods on the right |
360 // operand are always executed. | 317 // operand are always executed. |
361 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); | 318 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); |
362 // Optimize for the case where we end up AND'ing a value | 319 // Optimize for the case where we end up AND'ing a value |
363 // that doesn't convert to a number. This is common in | 320 // that doesn't convert to a number. This is common in |
364 // certain benchmarks. | 321 // certain benchmarks. |
365 if (NUMBER_IS_NAN(x)) return 0; | 322 if (NUMBER_IS_NAN(x)) return 0; |
366 } | 323 } |
367 return %NumberAnd(x, y); | 324 return %NumberAnd(x, y); |
368 } | 325 } |
369 | 326 |
370 | 327 |
371 // Strong mode BIT_AND throws if an implicit conversion would be performed | 328 // Strong mode BIT_AND throws if an implicit conversion would be performed |
372 BIT_AND_STRONG = function BIT_AND_STRONG(y) { | 329 function BIT_AND_STRONG(y) { |
373 if (IS_NUMBER(this) && IS_NUMBER(y)) { | 330 if (IS_NUMBER(this) && IS_NUMBER(y)) { |
374 return %NumberAnd(this, y); | 331 return %NumberAnd(this, y); |
375 } | 332 } |
376 throw %MakeTypeError(kStrongImplicitConversion); | 333 throw %MakeTypeError(kStrongImplicitConversion); |
377 } | 334 } |
378 | 335 |
379 | 336 |
380 // ECMA-262, section 11.10, page 57. | 337 // ECMA-262, section 11.10, page 57. |
381 BIT_XOR = function BIT_XOR(y) { | 338 function BIT_XOR(y) { |
382 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this); | 339 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this); |
383 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); | 340 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); |
384 return %NumberXor(x, y); | 341 return %NumberXor(x, y); |
385 } | 342 } |
386 | 343 |
387 | 344 |
388 // Strong mode BIT_XOR throws if an implicit conversion would be performed | 345 // Strong mode BIT_XOR throws if an implicit conversion would be performed |
389 BIT_XOR_STRONG = function BIT_XOR_STRONG(y) { | 346 function BIT_XOR_STRONG(y) { |
390 if (IS_NUMBER(this) && IS_NUMBER(y)) { | 347 if (IS_NUMBER(this) && IS_NUMBER(y)) { |
391 return %NumberXor(this, y); | 348 return %NumberXor(this, y); |
392 } | 349 } |
393 throw %MakeTypeError(kStrongImplicitConversion); | 350 throw %MakeTypeError(kStrongImplicitConversion); |
394 } | 351 } |
395 | 352 |
396 | 353 |
397 // ECMA-262, section 11.7.1, page 51. | 354 // ECMA-262, section 11.7.1, page 51. |
398 SHL = function SHL(y) { | 355 function SHL(y) { |
399 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this); | 356 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this); |
400 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); | 357 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); |
401 return %NumberShl(x, y); | 358 return %NumberShl(x, y); |
402 } | 359 } |
403 | 360 |
404 | 361 |
405 // Strong mode SHL throws if an implicit conversion would be performed | 362 // Strong mode SHL throws if an implicit conversion would be performed |
406 SHL_STRONG = function SHL_STRONG(y) { | 363 function SHL_STRONG(y) { |
407 if (IS_NUMBER(this) && IS_NUMBER(y)) { | 364 if (IS_NUMBER(this) && IS_NUMBER(y)) { |
408 return %NumberShl(this, y); | 365 return %NumberShl(this, y); |
409 } | 366 } |
410 throw %MakeTypeError(kStrongImplicitConversion); | 367 throw %MakeTypeError(kStrongImplicitConversion); |
411 } | 368 } |
412 | 369 |
413 | 370 |
414 // ECMA-262, section 11.7.2, page 51. | 371 // ECMA-262, section 11.7.2, page 51. |
415 SAR = function SAR(y) { | 372 function SAR(y) { |
416 var x; | 373 var x; |
417 if (IS_NUMBER(this)) { | 374 if (IS_NUMBER(this)) { |
418 x = this; | 375 x = this; |
419 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); | 376 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); |
420 } else { | 377 } else { |
421 x = %$nonNumberToNumber(this); | 378 x = %$nonNumberToNumber(this); |
422 // Make sure to convert the right operand to a number before | 379 // Make sure to convert the right operand to a number before |
423 // bailing out in the fast case, but after converting the | 380 // bailing out in the fast case, but after converting the |
424 // left operand. This ensures that valueOf methods on the right | 381 // left operand. This ensures that valueOf methods on the right |
425 // operand are always executed. | 382 // operand are always executed. |
426 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); | 383 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); |
427 // Optimize for the case where we end up shifting a value | 384 // Optimize for the case where we end up shifting a value |
428 // that doesn't convert to a number. This is common in | 385 // that doesn't convert to a number. This is common in |
429 // certain benchmarks. | 386 // certain benchmarks. |
430 if (NUMBER_IS_NAN(x)) return 0; | 387 if (NUMBER_IS_NAN(x)) return 0; |
431 } | 388 } |
432 return %NumberSar(x, y); | 389 return %NumberSar(x, y); |
433 } | 390 } |
434 | 391 |
435 | 392 |
436 // Strong mode SAR throws if an implicit conversion would be performed | 393 // Strong mode SAR throws if an implicit conversion would be performed |
437 SAR_STRONG = function SAR_STRONG(y) { | 394 function SAR_STRONG(y) { |
438 if (IS_NUMBER(this) && IS_NUMBER(y)) { | 395 if (IS_NUMBER(this) && IS_NUMBER(y)) { |
439 return %NumberSar(this, y); | 396 return %NumberSar(this, y); |
440 } | 397 } |
441 throw %MakeTypeError(kStrongImplicitConversion); | 398 throw %MakeTypeError(kStrongImplicitConversion); |
442 } | 399 } |
443 | 400 |
444 | 401 |
445 // ECMA-262, section 11.7.3, page 52. | 402 // ECMA-262, section 11.7.3, page 52. |
446 SHR = function SHR(y) { | 403 function SHR(y) { |
447 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this); | 404 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this); |
448 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); | 405 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y); |
449 return %NumberShr(x, y); | 406 return %NumberShr(x, y); |
450 } | 407 } |
451 | 408 |
452 | 409 |
453 // Strong mode SHR throws if an implicit conversion would be performed | 410 // Strong mode SHR throws if an implicit conversion would be performed |
454 SHR_STRONG = function SHR_STRONG(y) { | 411 function SHR_STRONG(y) { |
455 if (IS_NUMBER(this) && IS_NUMBER(y)) { | 412 if (IS_NUMBER(this) && IS_NUMBER(y)) { |
456 return %NumberShr(this, y); | 413 return %NumberShr(this, y); |
457 } | 414 } |
458 throw %MakeTypeError(kStrongImplicitConversion); | 415 throw %MakeTypeError(kStrongImplicitConversion); |
459 } | 416 } |
460 | 417 |
461 | 418 |
462 /* ----------------------------- | 419 /* ----------------------------- |
463 - - - H e l p e r s - - - | 420 - - - H e l p e r s - - - |
464 ----------------------------- | 421 ----------------------------- |
465 */ | 422 */ |
466 | 423 |
467 // ECMA-262, section 11.8.7, page 54. | 424 // ECMA-262, section 11.8.7, page 54. |
468 IN = function IN(x) { | 425 function IN(x) { |
469 if (!IS_SPEC_OBJECT(x)) { | 426 if (!IS_SPEC_OBJECT(x)) { |
470 throw %MakeTypeError(kInvalidInOperatorUse, this, x); | 427 throw %MakeTypeError(kInvalidInOperatorUse, this, x); |
471 } | 428 } |
472 if (%_IsNonNegativeSmi(this)) { | 429 if (%_IsNonNegativeSmi(this)) { |
473 if (IS_ARRAY(x) && %_HasFastPackedElements(x)) { | 430 if (IS_ARRAY(x) && %_HasFastPackedElements(x)) { |
474 return this < x.length; | 431 return this < x.length; |
475 } | 432 } |
476 return %HasElement(x, this); | 433 return %HasElement(x, this); |
477 } | 434 } |
478 return %HasProperty(x, %$toName(this)); | 435 return %HasProperty(x, %$toName(this)); |
479 } | 436 } |
480 | 437 |
481 | 438 |
482 // ECMA-262, section 11.8.6, page 54. To make the implementation more | 439 // ECMA-262, section 11.8.6, page 54. To make the implementation more |
483 // efficient, the return value should be zero if the 'this' is an | 440 // efficient, the return value should be zero if the 'this' is an |
484 // instance of F, and non-zero if not. This makes it possible to avoid | 441 // instance of F, and non-zero if not. This makes it possible to avoid |
485 // an expensive ToBoolean conversion in the generated code. | 442 // an expensive ToBoolean conversion in the generated code. |
486 INSTANCE_OF = function INSTANCE_OF(F) { | 443 function INSTANCE_OF(F) { |
487 var V = this; | 444 var V = this; |
488 if (!IS_SPEC_FUNCTION(F)) { | 445 if (!IS_SPEC_FUNCTION(F)) { |
489 throw %MakeTypeError(kInstanceofFunctionExpected, F); | 446 throw %MakeTypeError(kInstanceofFunctionExpected, F); |
490 } | 447 } |
491 | 448 |
492 // If V is not an object, return false. | 449 // If V is not an object, return false. |
493 if (!IS_SPEC_OBJECT(V)) { | 450 if (!IS_SPEC_OBJECT(V)) { |
494 return 1; | 451 return 1; |
495 } | 452 } |
496 | 453 |
497 // Check if function is bound, if so, get [[BoundFunction]] from it | 454 // Check if function is bound, if so, get [[BoundFunction]] from it |
498 // and use that instead of F. | 455 // and use that instead of F. |
499 var bindings = %BoundFunctionGetBindings(F); | 456 var bindings = %BoundFunctionGetBindings(F); |
500 if (bindings) { | 457 if (bindings) { |
501 F = bindings[kBoundFunctionIndex]; // Always a non-bound function. | 458 F = bindings[kBoundFunctionIndex]; // Always a non-bound function. |
502 } | 459 } |
503 // Get the prototype of F; if it is not an object, throw an error. | 460 // Get the prototype of F; if it is not an object, throw an error. |
504 var O = F.prototype; | 461 var O = F.prototype; |
505 if (!IS_SPEC_OBJECT(O)) { | 462 if (!IS_SPEC_OBJECT(O)) { |
506 throw %MakeTypeError(kInstanceofNonobjectProto, O); | 463 throw %MakeTypeError(kInstanceofNonobjectProto, O); |
507 } | 464 } |
508 | 465 |
509 // Return whether or not O is in the prototype chain of V. | 466 // Return whether or not O is in the prototype chain of V. |
510 return %IsInPrototypeChain(O, V) ? 0 : 1; | 467 return %IsInPrototypeChain(O, V) ? 0 : 1; |
511 } | 468 } |
512 | 469 |
513 | 470 |
514 CALL_NON_FUNCTION = function CALL_NON_FUNCTION() { | 471 function CALL_NON_FUNCTION() { |
515 var delegate = %GetFunctionDelegate(this); | 472 var delegate = %GetFunctionDelegate(this); |
516 if (!IS_FUNCTION(delegate)) { | 473 if (!IS_FUNCTION(delegate)) { |
517 var callsite = %RenderCallSite(); | 474 var callsite = %RenderCallSite(); |
518 if (callsite == "") callsite = typeof this; | 475 if (callsite == "") callsite = typeof this; |
519 throw %MakeTypeError(kCalledNonCallable, callsite); | 476 throw %MakeTypeError(kCalledNonCallable, callsite); |
520 } | 477 } |
521 return %Apply(delegate, this, arguments, 0, %_ArgumentsLength()); | 478 return %Apply(delegate, this, arguments, 0, %_ArgumentsLength()); |
522 } | 479 } |
523 | 480 |
524 | 481 |
525 CALL_NON_FUNCTION_AS_CONSTRUCTOR = function CALL_NON_FUNCTION_AS_CONSTRUCTOR() { | 482 function CALL_NON_FUNCTION_AS_CONSTRUCTOR() { |
526 var delegate = %GetConstructorDelegate(this); | 483 var delegate = %GetConstructorDelegate(this); |
527 if (!IS_FUNCTION(delegate)) { | 484 if (!IS_FUNCTION(delegate)) { |
528 var callsite = %RenderCallSite(); | 485 var callsite = %RenderCallSite(); |
529 if (callsite == "") callsite = typeof this; | 486 if (callsite == "") callsite = typeof this; |
530 throw %MakeTypeError(kCalledNonCallable, callsite); | 487 throw %MakeTypeError(kCalledNonCallable, callsite); |
531 } | 488 } |
532 return %Apply(delegate, this, arguments, 0, %_ArgumentsLength()); | 489 return %Apply(delegate, this, arguments, 0, %_ArgumentsLength()); |
533 } | 490 } |
534 | 491 |
535 | 492 |
536 CALL_FUNCTION_PROXY = function CALL_FUNCTION_PROXY() { | 493 function CALL_FUNCTION_PROXY() { |
537 var arity = %_ArgumentsLength() - 1; | 494 var arity = %_ArgumentsLength() - 1; |
538 var proxy = %_Arguments(arity); // The proxy comes in as an additional arg. | 495 var proxy = %_Arguments(arity); // The proxy comes in as an additional arg. |
539 var trap = %GetCallTrap(proxy); | 496 var trap = %GetCallTrap(proxy); |
540 return %Apply(trap, this, arguments, 0, arity); | 497 return %Apply(trap, this, arguments, 0, arity); |
541 } | 498 } |
542 | 499 |
543 | 500 |
544 CALL_FUNCTION_PROXY_AS_CONSTRUCTOR = | 501 function CALL_FUNCTION_PROXY_AS_CONSTRUCTOR () { |
545 function CALL_FUNCTION_PROXY_AS_CONSTRUCTOR () { | |
546 var proxy = this; | 502 var proxy = this; |
547 var trap = %GetConstructTrap(proxy); | 503 var trap = %GetConstructTrap(proxy); |
548 return %Apply(trap, this, arguments, 0, %_ArgumentsLength()); | 504 return %Apply(trap, this, arguments, 0, %_ArgumentsLength()); |
549 } | 505 } |
550 | 506 |
551 | 507 |
552 APPLY_PREPARE = function APPLY_PREPARE(args) { | 508 function APPLY_PREPARE(args) { |
553 var length; | 509 var length; |
554 // First check whether length is a positive Smi and args is an | 510 // First check whether length is a positive Smi and args is an |
555 // array. This is the fast case. If this fails, we do the slow case | 511 // array. This is the fast case. If this fails, we do the slow case |
556 // that takes care of more eventualities. | 512 // that takes care of more eventualities. |
557 if (IS_ARRAY(args)) { | 513 if (IS_ARRAY(args)) { |
558 length = args.length; | 514 length = args.length; |
559 if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength && | 515 if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength && |
560 IS_SPEC_FUNCTION(this)) { | 516 IS_SPEC_FUNCTION(this)) { |
561 return length; | 517 return length; |
562 } | 518 } |
(...skipping 14 matching lines...) Expand all Loading... |
577 if (args != null && !IS_SPEC_OBJECT(args)) { | 533 if (args != null && !IS_SPEC_OBJECT(args)) { |
578 throw %MakeTypeError(kWrongArgs, "Function.prototype.apply"); | 534 throw %MakeTypeError(kWrongArgs, "Function.prototype.apply"); |
579 } | 535 } |
580 | 536 |
581 // Return the length which is the number of arguments to copy to the | 537 // Return the length which is the number of arguments to copy to the |
582 // stack. It is guaranteed to be a small integer at this point. | 538 // stack. It is guaranteed to be a small integer at this point. |
583 return length; | 539 return length; |
584 } | 540 } |
585 | 541 |
586 | 542 |
587 REFLECT_APPLY_PREPARE = function REFLECT_APPLY_PREPARE(args) { | 543 function REFLECT_APPLY_PREPARE(args) { |
588 var length; | 544 var length; |
589 // First check whether length is a positive Smi and args is an | 545 // First check whether length is a positive Smi and args is an |
590 // array. This is the fast case. If this fails, we do the slow case | 546 // array. This is the fast case. If this fails, we do the slow case |
591 // that takes care of more eventualities. | 547 // that takes care of more eventualities. |
592 if (IS_ARRAY(args)) { | 548 if (IS_ARRAY(args)) { |
593 length = args.length; | 549 length = args.length; |
594 if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength && | 550 if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength && |
595 IS_SPEC_FUNCTION(this)) { | 551 IS_SPEC_FUNCTION(this)) { |
596 return length; | 552 return length; |
597 } | 553 } |
(...skipping 13 matching lines...) Expand all Loading... |
611 // big enough, but sanity check the value to avoid overflow when | 567 // big enough, but sanity check the value to avoid overflow when |
612 // multiplying with pointer size. | 568 // multiplying with pointer size. |
613 if (length > kSafeArgumentsLength) throw %MakeRangeError(kStackOverflow); | 569 if (length > kSafeArgumentsLength) throw %MakeRangeError(kStackOverflow); |
614 | 570 |
615 // Return the length which is the number of arguments to copy to the | 571 // Return the length which is the number of arguments to copy to the |
616 // stack. It is guaranteed to be a small integer at this point. | 572 // stack. It is guaranteed to be a small integer at this point. |
617 return length; | 573 return length; |
618 } | 574 } |
619 | 575 |
620 | 576 |
621 REFLECT_CONSTRUCT_PREPARE = function REFLECT_CONSTRUCT_PREPARE( | 577 function REFLECT_CONSTRUCT_PREPARE( |
622 args, newTarget) { | 578 args, newTarget) { |
623 var length; | 579 var length; |
624 var ctorOk = IS_SPEC_FUNCTION(this) && %IsConstructor(this); | 580 var ctorOk = IS_SPEC_FUNCTION(this) && %IsConstructor(this); |
625 var newTargetOk = IS_SPEC_FUNCTION(newTarget) && %IsConstructor(newTarget); | 581 var newTargetOk = IS_SPEC_FUNCTION(newTarget) && %IsConstructor(newTarget); |
626 | 582 |
627 // First check whether length is a positive Smi and args is an | 583 // First check whether length is a positive Smi and args is an |
628 // array. This is the fast case. If this fails, we do the slow case | 584 // array. This is the fast case. If this fails, we do the slow case |
629 // that takes care of more eventualities. | 585 // that takes care of more eventualities. |
630 if (IS_ARRAY(args)) { | 586 if (IS_ARRAY(args)) { |
631 length = args.length; | 587 length = args.length; |
(...skipping 29 matching lines...) Expand all Loading... |
661 // big enough, but sanity check the value to avoid overflow when | 617 // big enough, but sanity check the value to avoid overflow when |
662 // multiplying with pointer size. | 618 // multiplying with pointer size. |
663 if (length > kSafeArgumentsLength) throw %MakeRangeError(kStackOverflow); | 619 if (length > kSafeArgumentsLength) throw %MakeRangeError(kStackOverflow); |
664 | 620 |
665 // Return the length which is the number of arguments to copy to the | 621 // Return the length which is the number of arguments to copy to the |
666 // stack. It is guaranteed to be a small integer at this point. | 622 // stack. It is guaranteed to be a small integer at this point. |
667 return length; | 623 return length; |
668 } | 624 } |
669 | 625 |
670 | 626 |
671 CONCAT_ITERABLE_TO_ARRAY = function CONCAT_ITERABLE_TO_ARRAY(iterable) { | 627 function CONCAT_ITERABLE_TO_ARRAY(iterable) { |
672 return %$concatIterableToArray(this, iterable); | 628 return %$concatIterableToArray(this, iterable); |
673 }; | 629 }; |
674 | 630 |
675 | 631 |
676 STACK_OVERFLOW = function STACK_OVERFLOW(length) { | 632 function STACK_OVERFLOW(length) { |
677 throw %MakeRangeError(kStackOverflow); | 633 throw %MakeRangeError(kStackOverflow); |
678 } | 634 } |
679 | 635 |
680 | 636 |
681 // Convert the receiver to a number - forward to ToNumber. | 637 // Convert the receiver to a number - forward to ToNumber. |
682 TO_NUMBER = function TO_NUMBER() { | 638 function TO_NUMBER() { |
683 return %$toNumber(this); | 639 return %$toNumber(this); |
684 } | 640 } |
685 | 641 |
686 | 642 |
687 // Convert the receiver to a string - forward to ToString. | 643 // Convert the receiver to a string - forward to ToString. |
688 TO_STRING = function TO_STRING() { | 644 function TO_STRING() { |
689 return %$toString(this); | 645 return %$toString(this); |
690 } | 646 } |
691 | 647 |
692 | 648 |
693 // Convert the receiver to a string or symbol - forward to ToName. | 649 // Convert the receiver to a string or symbol - forward to ToName. |
694 TO_NAME = function TO_NAME() { | 650 function TO_NAME() { |
695 return %$toName(this); | 651 return %$toName(this); |
696 } | 652 } |
697 | 653 |
698 | 654 |
699 /* ------------------------------------- | 655 /* ------------------------------------- |
700 - - - C o n v e r s i o n s - - - | 656 - - - C o n v e r s i o n s - - - |
701 ------------------------------------- | 657 ------------------------------------- |
702 */ | 658 */ |
703 | 659 |
704 // ECMA-262, section 9.1, page 30. Use null/undefined for no hint, | 660 // ECMA-262, section 9.1, page 30. Use null/undefined for no hint, |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
909 $sameValueZero = SameValueZero; | 865 $sameValueZero = SameValueZero; |
910 $toBoolean = ToBoolean; | 866 $toBoolean = ToBoolean; |
911 $toInteger = ToInteger; | 867 $toInteger = ToInteger; |
912 $toLength = ToLength; | 868 $toLength = ToLength; |
913 $toName = ToName; | 869 $toName = ToName; |
914 $toNumber = ToNumber; | 870 $toNumber = ToNumber; |
915 $toPositiveInteger = ToPositiveInteger; | 871 $toPositiveInteger = ToPositiveInteger; |
916 $toPrimitive = ToPrimitive; | 872 $toPrimitive = ToPrimitive; |
917 $toString = ToString; | 873 $toString = ToString; |
918 | 874 |
| 875 %InstallJSBuiltins({ |
| 876 EQUALS, |
| 877 COMPARE, |
| 878 COMPARE_STRONG, |
| 879 ADD, |
| 880 ADD_STRONG, |
| 881 STRING_ADD_LEFT, |
| 882 STRING_ADD_RIGHT, |
| 883 SUB, |
| 884 SUB_STRONG, |
| 885 MUL, |
| 886 MUL_STRONG, |
| 887 DIV, |
| 888 DIV_STRONG, |
| 889 MOD, |
| 890 MOD_STRONG, |
| 891 BIT_OR, |
| 892 BIT_OR_STRONG, |
| 893 BIT_AND, |
| 894 BIT_AND_STRONG, |
| 895 BIT_XOR, |
| 896 BIT_XOR_STRONG, |
| 897 SHL, |
| 898 SHL_STRONG, |
| 899 SAR, |
| 900 SAR_STRONG, |
| 901 SHR, |
| 902 SHR_STRONG, |
| 903 IN, |
| 904 INSTANCE_OF, |
| 905 CALL_NON_FUNCTION, |
| 906 CALL_NON_FUNCTION_AS_CONSTRUCTOR, |
| 907 CALL_FUNCTION_PROXY, |
| 908 CALL_FUNCTION_PROXY_AS_CONSTRUCTOR, |
| 909 CONCAT_ITERABLE_TO_ARRAY, |
| 910 APPLY_PREPARE, |
| 911 REFLECT_APPLY_PREPARE, |
| 912 REFLECT_CONSTRUCT_PREPARE, |
| 913 STACK_OVERFLOW, |
| 914 TO_NUMBER, |
| 915 TO_STRING, |
| 916 TO_NAME, |
| 917 }); |
| 918 |
919 utils.ExportToRuntime(function(to) { | 919 utils.ExportToRuntime(function(to) { |
920 to.ToNumber = $toNumber; | 920 to.ToNumber = $toNumber; |
921 to.ToString = $toString; | 921 to.ToString = $toString; |
922 to.ToInteger = $toInteger; | 922 to.ToInteger = $toInteger; |
923 to.ToLength = $toLength; | 923 to.ToLength = $toLength; |
924 }); | 924 }); |
925 | 925 |
926 }) | 926 }) |
OLD | NEW |