63a733fcb614ea249ba2469695a0ab2f1cf3aa0e
[platform/upstream/v8.git] / src / runtime.js
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
3 // found in the LICENSE file.
4
5 // This files contains runtime support implemented in JavaScript.
6
7 // CAUTION: Some of the functions specified in this file are called
8 // directly from compiled code. These are the functions with names in
9 // ALL CAPS. The compiled code passes the first argument in 'this'.
10
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.
18 // 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_LEFT_STRONG;
27 var STRING_ADD_RIGHT;
28 var STRING_ADD_RIGHT_STRONG;
29 var SUB;
30 var SUB_STRONG;
31 var MUL;
32 var MUL_STRONG;
33 var DIV;
34 var DIV_STRONG;
35 var MOD;
36 var MOD_STRONG;
37 var BIT_OR;
38 var BIT_OR_STRONG;
39 var BIT_AND;
40 var BIT_AND_STRONG;
41 var BIT_XOR;
42 var BIT_XOR_STRONG;
43 var SHL;
44 var SHL_STRONG;
45 var SAR;
46 var SAR_STRONG;
47 var SHR;
48 var SHR_STRONG;
49 var DELETE;
50 var IN;
51 var INSTANCE_OF;
52 var CALL_NON_FUNCTION;
53 var CALL_NON_FUNCTION_AS_CONSTRUCTOR;
54 var CALL_FUNCTION_PROXY;
55 var CALL_FUNCTION_PROXY_AS_CONSTRUCTOR;
56 var CONCAT_ITERABLE_TO_ARRAY;
57 var APPLY_PREPARE;
58 var REFLECT_APPLY_PREPARE;
59 var REFLECT_CONSTRUCT_PREPARE;
60 var STACK_OVERFLOW;
61 var TO_OBJECT;
62 var TO_NUMBER;
63 var TO_STRING;
64 var TO_NAME;
65
66 var $defaultNumber;
67 var $defaultString;
68 var $NaN;
69 var $nonNumberToNumber;
70 var $nonStringToString;
71 var $sameValue;
72 var $sameValueZero;
73 var $toBoolean;
74 var $toInt32;
75 var $toInteger;
76 var $toLength;
77 var $toName;
78 var $toNumber;
79 var $toObject;
80 var $toPositiveInteger;
81 var $toPrimitive;
82 var $toString;
83 var $toUint32;
84
85 (function(global, utils) {
86
87 %CheckIsBootstrapping();
88
89 var GlobalArray = global.Array;
90 var GlobalBoolean = global.Boolean;
91 var GlobalString = global.String;
92 var GlobalNumber = global.Number;
93
94 // ----------------------------------------------------------------------------
95
96 // ECMA-262 Section 11.9.3.
97 EQUALS = function EQUALS(y) {
98   if (IS_STRING(this) && IS_STRING(y)) return %StringEquals(this, y);
99   var x = this;
100
101   while (true) {
102     if (IS_NUMBER(x)) {
103       while (true) {
104         if (IS_NUMBER(y)) return %NumberEquals(x, y);
105         if (IS_NULL_OR_UNDEFINED(y)) return 1;  // not equal
106         if (IS_SYMBOL(y) || IS_FLOAT32X4(y)) return 1;  // not equal
107         if (!IS_SPEC_OBJECT(y)) {
108           // String or boolean.
109           return %NumberEquals(x, %$toNumber(y));
110         }
111         y = %$toPrimitive(y, NO_HINT);
112       }
113     } else if (IS_STRING(x)) {
114       while (true) {
115         if (IS_STRING(y)) return %StringEquals(x, y);
116         if (IS_SYMBOL(y) || IS_FLOAT32X4(y)) return 1;  // not equal
117         if (IS_NUMBER(y)) return %NumberEquals(%$toNumber(x), y);
118         if (IS_BOOLEAN(y)) return %NumberEquals(%$toNumber(x), %$toNumber(y));
119         if (IS_NULL_OR_UNDEFINED(y)) return 1;  // not equal
120         y = %$toPrimitive(y, NO_HINT);
121       }
122     } else if (IS_SYMBOL(x)) {
123       if (IS_SYMBOL(y)) return %_ObjectEquals(x, y) ? 0 : 1;
124       return 1; // not equal
125     } else if (IS_BOOLEAN(x)) {
126       if (IS_BOOLEAN(y)) return %_ObjectEquals(x, y) ? 0 : 1;
127       if (IS_NULL_OR_UNDEFINED(y)) return 1;
128       if (IS_NUMBER(y)) return %NumberEquals(%$toNumber(x), y);
129       if (IS_STRING(y)) return %NumberEquals(%$toNumber(x), %$toNumber(y));
130       if (IS_SYMBOL(y) || IS_FLOAT32X4(y)) return 1;  // not equal
131       // y is object.
132       x = %$toNumber(x);
133       y = %$toPrimitive(y, NO_HINT);
134     } else if (IS_NULL_OR_UNDEFINED(x)) {
135       return IS_NULL_OR_UNDEFINED(y) ? 0 : 1;
136     } else if (IS_FLOAT32X4(x)) {
137       if (IS_FLOAT32X4(y))
138         return %Float32x4Equals(x, y);
139       return 1;  // not equal
140     } else {
141       // x is an object.
142       if (IS_SPEC_OBJECT(y)) {
143         return %_ObjectEquals(x, y) ? 0 : 1;
144       }
145       if (IS_NULL_OR_UNDEFINED(y)) return 1;  // not equal
146       if (IS_SYMBOL(y) || IS_FLOAT32X4(y)) return 1;  // not equal
147       if (IS_BOOLEAN(y)) y = %$toNumber(y);
148       x = %$toPrimitive(x, NO_HINT);
149     }
150   }
151 }
152
153 // ECMA-262, section 11.9.4, page 56.
154 STRICT_EQUALS = function STRICT_EQUALS(x) {
155   if (IS_STRING(this)) {
156     if (!IS_STRING(x)) return 1;  // not equal
157     return %StringEquals(this, x);
158   }
159
160   if (IS_NUMBER(this)) {
161     if (!IS_NUMBER(x)) return 1;  // not equal
162     return %NumberEquals(this, x);
163   }
164
165   if (IS_FLOAT32X4(this) && IS_FLOAT32X4(x))
166     return %Float32x4Equals(this, x);
167
168   // If anything else gets here, we just do simple identity check.
169   // Objects (including functions), null, undefined and booleans were
170   // checked in the CompareStub, so there should be nothing left.
171   return %_ObjectEquals(this, x) ? 0 : 1;
172 }
173
174
175 // ECMA-262, section 11.8.5, page 53. The 'ncr' parameter is used as
176 // the result when either (or both) the operands are NaN.
177 COMPARE = function COMPARE(x, ncr) {
178   var left;
179   var right;
180   // Fast cases for string, numbers and undefined compares.
181   if (IS_STRING(this)) {
182     if (IS_STRING(x)) return %_StringCompare(this, x);
183     if (IS_UNDEFINED(x)) return ncr;
184     left = this;
185   } else if (IS_NUMBER(this)) {
186     if (IS_NUMBER(x)) return %NumberCompare(this, x, ncr);
187     if (IS_UNDEFINED(x)) return ncr;
188     left = this;
189   } else if (IS_UNDEFINED(this)) {
190     if (!IS_UNDEFINED(x)) {
191       %$toPrimitive(x, NUMBER_HINT);
192     }
193     return ncr;
194   } else if (IS_UNDEFINED(x)) {
195     %$toPrimitive(this, NUMBER_HINT);
196     return ncr;
197   } else {
198     left = %$toPrimitive(this, NUMBER_HINT);
199   }
200
201   right = %$toPrimitive(x, NUMBER_HINT);
202   if (IS_STRING(left) && IS_STRING(right)) {
203     return %_StringCompare(left, right);
204   } else {
205     var left_number = %$toNumber(left);
206     var right_number = %$toNumber(right);
207     if (NUMBER_IS_NAN(left_number) || NUMBER_IS_NAN(right_number)) return ncr;
208     return %NumberCompare(left_number, right_number, ncr);
209   }
210 }
211
212 // Strong mode COMPARE throws if an implicit conversion would be performed
213 COMPARE_STRONG = function COMPARE_STRONG(x, ncr) {
214   if (IS_STRING(this) && IS_STRING(x)) return %_StringCompare(this, x);
215   if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberCompare(this, x, ncr);
216
217   throw %MakeTypeError(kStrongImplicitConversion);
218 }
219
220
221
222 /* -----------------------------------
223    - - -   A r i t h m e t i c   - - -
224    -----------------------------------
225 */
226
227 // ECMA-262, section 11.6.1, page 50.
228 ADD = function ADD(x) {
229   // Fast case: Check for number operands and do the addition.
230   if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x);
231   if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x);
232
233   // Default implementation.
234   var a = %$toPrimitive(this, NO_HINT);
235   var b = %$toPrimitive(x, NO_HINT);
236
237   if (IS_STRING(a)) {
238     return %_StringAdd(a, %$toString(b));
239   } else if (IS_STRING(b)) {
240     return %_StringAdd(%$nonStringToString(a), b);
241   } else {
242     return %NumberAdd(%$toNumber(a), %$toNumber(b));
243   }
244 }
245
246
247 // Strong mode ADD throws if an implicit conversion would be performed
248 ADD_STRONG = function ADD_STRONG(x) {
249   if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x);
250   if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x);
251
252   throw %MakeTypeError(kStrongImplicitConversion);
253 }
254
255
256 // Left operand (this) is already a string.
257 STRING_ADD_LEFT = function STRING_ADD_LEFT(y) {
258   if (!IS_STRING(y)) {
259     if (IS_STRING_WRAPPER(y) && %_IsStringWrapperSafeForDefaultValueOf(y)) {
260       y = %_ValueOf(y);
261     } else {
262       y = IS_NUMBER(y)
263           ? %_NumberToString(y)
264           : %$toString(%$toPrimitive(y, NO_HINT));
265     }
266   }
267   return %_StringAdd(this, y);
268 }
269
270
271 // Left operand (this) is already a string.
272 STRING_ADD_LEFT_STRONG = function STRING_ADD_LEFT_STRONG(y) {
273   if (IS_STRING(y)) {
274     return %_StringAdd(this, y);
275   }
276   throw %MakeTypeError(kStrongImplicitConversion);
277 }
278
279
280 // Right operand (y) is already a string.
281 STRING_ADD_RIGHT = function STRING_ADD_RIGHT(y) {
282   var x = this;
283   if (!IS_STRING(x)) {
284     if (IS_STRING_WRAPPER(x) && %_IsStringWrapperSafeForDefaultValueOf(x)) {
285       x = %_ValueOf(x);
286     } else {
287       x = IS_NUMBER(x)
288           ? %_NumberToString(x)
289           : %$toString(%$toPrimitive(x, NO_HINT));
290     }
291   }
292   return %_StringAdd(x, y);
293 }
294
295
296 // Right operand (y) is already a string.
297 STRING_ADD_RIGHT_STRONG = function STRING_ADD_RIGHT_STRONG(y) {
298   if (IS_STRING(this)) {
299     return %_StringAdd(this, y);
300   }
301   throw %MakeTypeError(kStrongImplicitConversion);
302 }
303
304
305 // ECMA-262, section 11.6.2, page 50.
306 SUB = function SUB(y) {
307   var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
308   if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
309   return %NumberSub(x, y);
310 }
311
312
313 // Strong mode SUB throws if an implicit conversion would be performed
314 SUB_STRONG = function SUB_STRONG(y) {
315   if (IS_NUMBER(this) && IS_NUMBER(y)) {
316     return %NumberSub(this, y);
317   }
318   throw %MakeTypeError(kStrongImplicitConversion);
319 }
320
321
322 // ECMA-262, section 11.5.1, page 48.
323 MUL = function MUL(y) {
324   var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
325   if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
326   return %NumberMul(x, y);
327 }
328
329
330 // Strong mode MUL throws if an implicit conversion would be performed
331 MUL_STRONG = function MUL_STRONG(y) {
332   if (IS_NUMBER(this) && IS_NUMBER(y)) {
333     return %NumberMul(this, y);
334   }
335   throw %MakeTypeError(kStrongImplicitConversion);
336 }
337
338
339 // ECMA-262, section 11.5.2, page 49.
340 DIV = function DIV(y) {
341   var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
342   if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
343   return %NumberDiv(x, y);
344 }
345
346
347 // Strong mode DIV throws if an implicit conversion would be performed
348 DIV_STRONG = function DIV_STRONG(y) {
349   if (IS_NUMBER(this) && IS_NUMBER(y)) {
350     return %NumberDiv(this, y);
351   }
352   throw %MakeTypeError(kStrongImplicitConversion);
353 }
354
355
356 // ECMA-262, section 11.5.3, page 49.
357 MOD = function MOD(y) {
358   var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
359   if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
360   return %NumberMod(x, y);
361 }
362
363
364 // Strong mode MOD throws if an implicit conversion would be performed
365 MOD_STRONG = function MOD_STRONG(y) {
366   if (IS_NUMBER(this) && IS_NUMBER(y)) {
367     return %NumberMod(this, y);
368   }
369   throw %MakeTypeError(kStrongImplicitConversion);
370 }
371
372
373 /* -------------------------------------------
374    - - -   B i t   o p e r a t i o n s   - - -
375    -------------------------------------------
376 */
377
378 // ECMA-262, section 11.10, page 57.
379 BIT_OR = function BIT_OR(y) {
380   var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
381   if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
382   return %NumberOr(x, y);
383 }
384
385
386 // Strong mode BIT_OR throws if an implicit conversion would be performed
387 BIT_OR_STRONG = function BIT_OR_STRONG(y) {
388   if (IS_NUMBER(this) && IS_NUMBER(y)) {
389     return %NumberOr(this, y);
390   }
391   throw %MakeTypeError(kStrongImplicitConversion);
392 }
393
394
395 // ECMA-262, section 11.10, page 57.
396 BIT_AND = function BIT_AND(y) {
397   var x;
398   if (IS_NUMBER(this)) {
399     x = this;
400     if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
401   } else {
402     x = %$nonNumberToNumber(this);
403     // Make sure to convert the right operand to a number before
404     // bailing out in the fast case, but after converting the
405     // left operand. This ensures that valueOf methods on the right
406     // operand are always executed.
407     if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
408     // Optimize for the case where we end up AND'ing a value
409     // that doesn't convert to a number. This is common in
410     // certain benchmarks.
411     if (NUMBER_IS_NAN(x)) return 0;
412   }
413   return %NumberAnd(x, y);
414 }
415
416
417 // Strong mode BIT_AND throws if an implicit conversion would be performed
418 BIT_AND_STRONG = function BIT_AND_STRONG(y) {
419   if (IS_NUMBER(this) && IS_NUMBER(y)) {
420     return %NumberAnd(this, y);
421   }
422   throw %MakeTypeError(kStrongImplicitConversion);
423 }
424
425
426 // ECMA-262, section 11.10, page 57.
427 BIT_XOR = function BIT_XOR(y) {
428   var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
429   if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
430   return %NumberXor(x, y);
431 }
432
433
434 // Strong mode BIT_XOR throws if an implicit conversion would be performed
435 BIT_XOR_STRONG = function BIT_XOR_STRONG(y) {
436   if (IS_NUMBER(this) && IS_NUMBER(y)) {
437     return %NumberXor(this, y);
438   }
439   throw %MakeTypeError(kStrongImplicitConversion);
440 }
441
442
443 // ECMA-262, section 11.7.1, page 51.
444 SHL = function SHL(y) {
445   var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
446   if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
447   return %NumberShl(x, y);
448 }
449
450
451 // Strong mode SHL throws if an implicit conversion would be performed
452 SHL_STRONG = function SHL_STRONG(y) {
453   if (IS_NUMBER(this) && IS_NUMBER(y)) {
454     return %NumberShl(this, y);
455   }
456   throw %MakeTypeError(kStrongImplicitConversion);
457 }
458
459
460 // ECMA-262, section 11.7.2, page 51.
461 SAR = function SAR(y) {
462   var x;
463   if (IS_NUMBER(this)) {
464     x = this;
465     if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
466   } else {
467     x = %$nonNumberToNumber(this);
468     // Make sure to convert the right operand to a number before
469     // bailing out in the fast case, but after converting the
470     // left operand. This ensures that valueOf methods on the right
471     // operand are always executed.
472     if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
473     // Optimize for the case where we end up shifting a value
474     // that doesn't convert to a number. This is common in
475     // certain benchmarks.
476     if (NUMBER_IS_NAN(x)) return 0;
477   }
478   return %NumberSar(x, y);
479 }
480
481
482 // Strong mode SAR throws if an implicit conversion would be performed
483 SAR_STRONG = function SAR_STRONG(y) {
484   if (IS_NUMBER(this) && IS_NUMBER(y)) {
485     return %NumberSar(this, y);
486   }
487   throw %MakeTypeError(kStrongImplicitConversion);
488 }
489
490
491 // ECMA-262, section 11.7.3, page 52.
492 SHR = function SHR(y) {
493   var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
494   if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
495   return %NumberShr(x, y);
496 }
497
498
499 // Strong mode SHR throws if an implicit conversion would be performed
500 SHR_STRONG = function SHR_STRONG(y) {
501   if (IS_NUMBER(this) && IS_NUMBER(y)) {
502     return %NumberShr(this, y);
503   }
504   throw %MakeTypeError(kStrongImplicitConversion);
505 }
506
507
508 /* -----------------------------
509    - - -   H e l p e r s   - - -
510    -----------------------------
511 */
512
513 // ECMA-262, section 11.4.1, page 46.
514 DELETE = function DELETE(key, language_mode) {
515   return %DeleteProperty(%$toObject(this), key, language_mode);
516 }
517
518
519 // ECMA-262, section 11.8.7, page 54.
520 IN = function IN(x) {
521   if (!IS_SPEC_OBJECT(x)) {
522     throw %MakeTypeError(kInvalidInOperatorUse, this, x);
523   }
524   if (%_IsNonNegativeSmi(this)) {
525     if (IS_ARRAY(x) && %_HasFastPackedElements(x)) {
526       return this < x.length;
527     }
528     return %HasElement(x, this);
529   }
530   return %HasProperty(x, %$toName(this));
531 }
532
533
534 // ECMA-262, section 11.8.6, page 54. To make the implementation more
535 // efficient, the return value should be zero if the 'this' is an
536 // instance of F, and non-zero if not. This makes it possible to avoid
537 // an expensive ToBoolean conversion in the generated code.
538 INSTANCE_OF = function INSTANCE_OF(F) {
539   var V = this;
540   if (!IS_SPEC_FUNCTION(F)) {
541     throw %MakeTypeError(kInstanceofFunctionExpected, F);
542   }
543
544   // If V is not an object, return false.
545   if (!IS_SPEC_OBJECT(V)) {
546     return 1;
547   }
548
549   // Check if function is bound, if so, get [[BoundFunction]] from it
550   // and use that instead of F.
551   var bindings = %BoundFunctionGetBindings(F);
552   if (bindings) {
553     F = bindings[kBoundFunctionIndex];  // Always a non-bound function.
554   }
555   // Get the prototype of F; if it is not an object, throw an error.
556   var O = F.prototype;
557   if (!IS_SPEC_OBJECT(O)) {
558     throw %MakeTypeError(kInstanceofNonobjectProto, O);
559   }
560
561   // Return whether or not O is in the prototype chain of V.
562   return %IsInPrototypeChain(O, V) ? 0 : 1;
563 }
564
565
566 CALL_NON_FUNCTION = function CALL_NON_FUNCTION() {
567   var delegate = %GetFunctionDelegate(this);
568   if (!IS_FUNCTION(delegate)) {
569     var callsite = %RenderCallSite();
570     if (callsite == "") callsite = typeof this;
571     throw %MakeTypeError(kCalledNonCallable, callsite);
572   }
573   return %Apply(delegate, this, arguments, 0, %_ArgumentsLength());
574 }
575
576
577 CALL_NON_FUNCTION_AS_CONSTRUCTOR = function CALL_NON_FUNCTION_AS_CONSTRUCTOR() {
578   var delegate = %GetConstructorDelegate(this);
579   if (!IS_FUNCTION(delegate)) {
580     var callsite = %RenderCallSite();
581     if (callsite == "") callsite = typeof this;
582     throw %MakeTypeError(kCalledNonCallable, callsite);
583   }
584   return %Apply(delegate, this, arguments, 0, %_ArgumentsLength());
585 }
586
587
588 CALL_FUNCTION_PROXY = function CALL_FUNCTION_PROXY() {
589   var arity = %_ArgumentsLength() - 1;
590   var proxy = %_Arguments(arity);  // The proxy comes in as an additional arg.
591   var trap = %GetCallTrap(proxy);
592   return %Apply(trap, this, arguments, 0, arity);
593 }
594
595
596 CALL_FUNCTION_PROXY_AS_CONSTRUCTOR =
597     function CALL_FUNCTION_PROXY_AS_CONSTRUCTOR () {
598   var proxy = this;
599   var trap = %GetConstructTrap(proxy);
600   return %Apply(trap, this, arguments, 0, %_ArgumentsLength());
601 }
602
603
604 APPLY_PREPARE = function APPLY_PREPARE(args) {
605   var length;
606   // First check whether length is a positive Smi and args is an
607   // array. This is the fast case. If this fails, we do the slow case
608   // that takes care of more eventualities.
609   if (IS_ARRAY(args)) {
610     length = args.length;
611     if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength &&
612         IS_SPEC_FUNCTION(this)) {
613       return length;
614     }
615   }
616
617   length = (args == null) ? 0 : %$toUint32(args.length);
618
619   // We can handle any number of apply arguments if the stack is
620   // big enough, but sanity check the value to avoid overflow when
621   // multiplying with pointer size.
622   if (length > kSafeArgumentsLength) throw %MakeRangeError(kStackOverflow);
623
624   if (!IS_SPEC_FUNCTION(this)) {
625     throw %MakeTypeError(kApplyNonFunction, %$toString(this), typeof this);
626   }
627
628   // Make sure the arguments list has the right type.
629   if (args != null && !IS_SPEC_OBJECT(args)) {
630     throw %MakeTypeError(kWrongArgs, "Function.prototype.apply");
631   }
632
633   // Return the length which is the number of arguments to copy to the
634   // stack. It is guaranteed to be a small integer at this point.
635   return length;
636 }
637
638
639 REFLECT_APPLY_PREPARE = function REFLECT_APPLY_PREPARE(args) {
640   var length;
641   // First check whether length is a positive Smi and args is an
642   // array. This is the fast case. If this fails, we do the slow case
643   // that takes care of more eventualities.
644   if (IS_ARRAY(args)) {
645     length = args.length;
646     if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength &&
647         IS_SPEC_FUNCTION(this)) {
648       return length;
649     }
650   }
651
652   if (!IS_SPEC_FUNCTION(this)) {
653     throw %MakeTypeError(kCalledNonCallable, %$toString(this));
654   }
655
656   if (!IS_SPEC_OBJECT(args)) {
657     throw %MakeTypeError(kWrongArgs, "Reflect.apply");
658   }
659
660   length = %$toLength(args.length);
661
662   // We can handle any number of apply arguments if the stack is
663   // big enough, but sanity check the value to avoid overflow when
664   // multiplying with pointer size.
665   if (length > kSafeArgumentsLength) throw %MakeRangeError(kStackOverflow);
666
667   // Return the length which is the number of arguments to copy to the
668   // stack. It is guaranteed to be a small integer at this point.
669   return length;
670 }
671
672
673 REFLECT_CONSTRUCT_PREPARE = function REFLECT_CONSTRUCT_PREPARE(
674     args, newTarget) {
675   var length;
676   var ctorOk = IS_SPEC_FUNCTION(this) && %IsConstructor(this);
677   var newTargetOk = IS_SPEC_FUNCTION(newTarget) && %IsConstructor(newTarget);
678
679   // First check whether length is a positive Smi and args is an
680   // array. This is the fast case. If this fails, we do the slow case
681   // that takes care of more eventualities.
682   if (IS_ARRAY(args)) {
683     length = args.length;
684     if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength &&
685         ctorOk && newTargetOk) {
686       return length;
687     }
688   }
689
690   if (!ctorOk) {
691     if (!IS_SPEC_FUNCTION(this)) {
692       throw %MakeTypeError(kCalledNonCallable, %$toString(this));
693     } else {
694       throw %MakeTypeError(kNotConstructor, %$toString(this));
695     }
696   }
697
698   if (!newTargetOk) {
699     if (!IS_SPEC_FUNCTION(newTarget)) {
700       throw %MakeTypeError(kCalledNonCallable, %$toString(newTarget));
701     } else {
702       throw %MakeTypeError(kNotConstructor, %$toString(newTarget));
703     }
704   }
705
706   if (!IS_SPEC_OBJECT(args)) {
707     throw %MakeTypeError(kWrongArgs, "Reflect.construct");
708   }
709
710   length = %$toLength(args.length);
711
712   // We can handle any number of apply arguments if the stack is
713   // big enough, but sanity check the value to avoid overflow when
714   // multiplying with pointer size.
715   if (length > kSafeArgumentsLength) throw %MakeRangeError(kStackOverflow);
716
717   // Return the length which is the number of arguments to copy to the
718   // stack. It is guaranteed to be a small integer at this point.
719   return length;
720 }
721
722
723 CONCAT_ITERABLE_TO_ARRAY = function CONCAT_ITERABLE_TO_ARRAY(iterable) {
724   return %$concatIterableToArray(this, iterable);
725 };
726
727
728 STACK_OVERFLOW = function STACK_OVERFLOW(length) {
729   throw %MakeRangeError(kStackOverflow);
730 }
731
732
733 // Convert the receiver to an object - forward to ToObject.
734 TO_OBJECT = function TO_OBJECT() {
735   return %$toObject(this);
736 }
737
738
739 // Convert the receiver to a number - forward to ToNumber.
740 TO_NUMBER = function TO_NUMBER() {
741   return %$toNumber(this);
742 }
743
744
745 // Convert the receiver to a string - forward to ToString.
746 TO_STRING = function TO_STRING() {
747   return %$toString(this);
748 }
749
750
751 // Convert the receiver to a string or symbol - forward to ToName.
752 TO_NAME = function TO_NAME() {
753   return %$toName(this);
754 }
755
756
757 /* -------------------------------------
758    - - -   C o n v e r s i o n s   - - -
759    -------------------------------------
760 */
761
762 // ECMA-262, section 9.1, page 30. Use null/undefined for no hint,
763 // (1) for number hint, and (2) for string hint.
764 function ToPrimitive(x, hint) {
765   // Fast case check.
766   if (IS_STRING(x)) return x;
767   // Normal behavior.
768   if (!IS_SPEC_OBJECT(x)) return x;
769   if (IS_FLOAT32X4(x)) return x;
770   if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT;
771   return (hint == NUMBER_HINT) ? DefaultNumber(x) : DefaultString(x);
772 }
773
774
775 // ECMA-262, section 9.2, page 30
776 function ToBoolean(x) {
777   if (IS_BOOLEAN(x)) return x;
778   if (IS_STRING(x)) return x.length != 0;
779   if (x == null) return false;
780   if (IS_NUMBER(x)) return !((x == 0) || NUMBER_IS_NAN(x));
781   return true;
782 }
783
784
785 // ECMA-262, section 9.3, page 31.
786 function ToNumber(x) {
787   if (IS_NUMBER(x)) return x;
788   if (IS_STRING(x)) {
789     return %_HasCachedArrayIndex(x) ? %_GetCachedArrayIndex(x)
790                                     : %StringToNumber(x);
791   }
792   if (IS_BOOLEAN(x)) return x ? 1 : 0;
793   if (IS_UNDEFINED(x)) return NAN;
794   // Types that can't be converted to number are caught in DefaultNumber.
795   return (IS_NULL(x)) ? 0 : ToNumber(DefaultNumber(x));
796 }
797
798 function NonNumberToNumber(x) {
799   if (IS_STRING(x)) {
800     return %_HasCachedArrayIndex(x) ? %_GetCachedArrayIndex(x)
801                                     : %StringToNumber(x);
802   }
803   if (IS_BOOLEAN(x)) return x ? 1 : 0;
804   if (IS_UNDEFINED(x)) return NAN;
805   // Types that can't be converted to number are caught in DefaultNumber.
806   return (IS_NULL(x)) ? 0 : ToNumber(DefaultNumber(x));
807 }
808
809
810 // ECMA-262, section 9.8, page 35.
811 function ToString(x) {
812   if (IS_STRING(x)) return x;
813   if (IS_NUMBER(x)) return %_NumberToString(x);
814   if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
815   if (IS_UNDEFINED(x)) return 'undefined';
816   // Types that can't be converted to string are caught in DefaultString.
817   return (IS_NULL(x)) ? 'null' : ToString(DefaultString(x));
818 }
819
820 function NonStringToString(x) {
821   if (IS_NUMBER(x)) return %_NumberToString(x);
822   if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
823   if (IS_UNDEFINED(x)) return 'undefined';
824   // Types that can't be converted to string are caught in DefaultString.
825   return (IS_NULL(x)) ? 'null' : ToString(DefaultString(x));
826 }
827
828
829 // ES6 symbols
830 function ToName(x) {
831   return IS_SYMBOL(x) ? x : ToString(x);
832 }
833
834
835 // ECMA-262, section 9.9, page 36.
836 function ToObject(x) {
837   if (IS_STRING(x)) return new GlobalString(x);
838   if (IS_NUMBER(x)) return new GlobalNumber(x);
839   if (IS_BOOLEAN(x)) return new GlobalBoolean(x);
840   if (IS_SYMBOL(x)) return %NewSymbolWrapper(x);
841   if (IS_FLOAT32X4(x)) return %NewFloat32x4Wrapper(x);
842   if (IS_NULL_OR_UNDEFINED(x) && !IS_UNDETECTABLE(x)) {
843     throw MakeTypeError(kUndefinedOrNullToObject);
844   }
845   return x;
846 }
847
848
849 // ECMA-262, section 9.4, page 34.
850 function ToInteger(x) {
851   if (%_IsSmi(x)) return x;
852   return %NumberToInteger(ToNumber(x));
853 }
854
855
856 // ES6, draft 08-24-14, section 7.1.15
857 function ToLength(arg) {
858   arg = ToInteger(arg);
859   if (arg < 0) return 0;
860   return arg < GlobalNumber.MAX_SAFE_INTEGER ? arg
861                                              : GlobalNumber.MAX_SAFE_INTEGER;
862 }
863
864
865 // ECMA-262, section 9.6, page 34.
866 function ToUint32(x) {
867   if (%_IsSmi(x) && x >= 0) return x;
868   return %NumberToJSUint32(ToNumber(x));
869 }
870
871
872 // ECMA-262, section 9.5, page 34
873 function ToInt32(x) {
874   if (%_IsSmi(x)) return x;
875   return %NumberToJSInt32(ToNumber(x));
876 }
877
878
879 // ES5, section 9.12
880 function SameValue(x, y) {
881   if (typeof x != typeof y) return false;
882   if (IS_NUMBER(x)) {
883     if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true;
884     // x is +0 and y is -0 or vice versa.
885     if (x === 0 && y === 0 && %_IsMinusZero(x) != %_IsMinusZero(y)) {
886       return false;
887     }
888   }
889   if (IS_FLOAT32X4(x)) {
890     return %Float32x4SameValue(x, y);
891   }
892   return x === y;
893 }
894
895
896 // ES6, section 7.2.4
897 function SameValueZero(x, y) {
898   if (typeof x != typeof y) return false;
899   if (IS_NUMBER(x)) {
900     if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true;
901   }
902   if (IS_FLOAT32X4(x)) {
903     return %Float32x4SameValueZero(x, y);
904   }
905   return x === y;
906 }
907
908
909 function ConcatIterableToArray(target, iterable) {
910    var index = target.length;
911    for (var element of iterable) {
912      %AddElement(target, index++, element);
913    }
914    return target;
915 }
916
917
918 /* ---------------------------------
919    - - -   U t i l i t i e s   - - -
920    ---------------------------------
921 */
922
923 // Returns if the given x is a primitive value - not an object or a
924 // function.
925 function IsPrimitive(x) {
926   // Even though the type of null is "object", null is still
927   // considered a primitive value. IS_SPEC_OBJECT handles this correctly
928   // (i.e., it will return false if x is null).
929   return !IS_SPEC_OBJECT(x);
930 }
931
932
933 // ES6, draft 10-14-14, section 22.1.3.1.1
934 function IsConcatSpreadable(O) {
935   if (!IS_SPEC_OBJECT(O)) return false;
936   var spreadable = O[symbolIsConcatSpreadable];
937   if (IS_UNDEFINED(spreadable)) return IS_ARRAY(O);
938   return ToBoolean(spreadable);
939 }
940
941
942 // ECMA-262, section 8.6.2.6, page 28.
943 function DefaultNumber(x) {
944   var valueOf = x.valueOf;
945   if (IS_SPEC_FUNCTION(valueOf)) {
946     var v = %_CallFunction(x, valueOf);
947     if (IS_SYMBOL(v)) throw MakeTypeError(kSymbolToNumber);
948     if (IS_FLOAT32X4(v)) throw MakeTypeError(kSimdToNumber);
949     if (IsPrimitive(v)) return v;
950   }
951   var toString = x.toString;
952   if (IS_SPEC_FUNCTION(toString)) {
953     var s = %_CallFunction(x, toString);
954     if (IsPrimitive(s)) return s;
955   }
956   throw MakeTypeError(kCannotConvertToPrimitive);
957 }
958
959 // ECMA-262, section 8.6.2.6, page 28.
960 function DefaultString(x) {
961   if (!IS_SYMBOL_WRAPPER(x)) {
962     if (IS_SYMBOL(x)) throw MakeTypeError(kSymbolToString);
963     var toString = x.toString;
964     if (IS_SPEC_FUNCTION(toString)) {
965       var s = %_CallFunction(x, toString);
966       if (IsPrimitive(s)) return s;
967     }
968
969     var valueOf = x.valueOf;
970     if (IS_SPEC_FUNCTION(valueOf)) {
971       var v = %_CallFunction(x, valueOf);
972       if (IsPrimitive(v)) return v;
973     }
974   }
975   throw MakeTypeError(kCannotConvertToPrimitive);
976 }
977
978 function ToPositiveInteger(x, rangeErrorIndex) {
979   var i = TO_INTEGER_MAP_MINUS_ZERO(x);
980   if (i < 0) throw MakeRangeError(rangeErrorIndex);
981   return i;
982 }
983
984 //----------------------------------------------------------------------------
985
986 // NOTE: Setting the prototype for Array must take place as early as
987 // possible due to code generation for array literals.  When
988 // generating code for a array literal a boilerplate array is created
989 // that is cloned when running the code.  It is essential that the
990 // boilerplate gets the right prototype.
991 %FunctionSetPrototype(GlobalArray, new GlobalArray(0));
992
993 //----------------------------------------------------------------------------
994
995 $concatIterableToArray = ConcatIterableToArray;
996 $defaultNumber = DefaultNumber;
997 $defaultString = DefaultString;
998 $NaN = %GetRootNaN();
999 $nonNumberToNumber = NonNumberToNumber;
1000 $nonStringToString = NonStringToString;
1001 $sameValue = SameValue;
1002 $sameValueZero = SameValueZero;
1003 $toBoolean = ToBoolean;
1004 $toInt32 = ToInt32;
1005 $toInteger = ToInteger;
1006 $toLength = ToLength;
1007 $toName = ToName;
1008 $toNumber = ToNumber;
1009 $toObject = ToObject;
1010 $toPositiveInteger = ToPositiveInteger;
1011 $toPrimitive = ToPrimitive;
1012 $toString = ToString;
1013 $toUint32 = ToUint32;
1014
1015 })