[V8] Introduce a QML compilation mode
[profile/ivi/qtjsbackend.git] / src / 3rdparty / v8 / src / runtime.js
1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 // This files contains runtime support implemented in JavaScript.
29
30 // CAUTION: Some of the functions specified in this file are called
31 // directly from compiled code. These are the functions with names in
32 // ALL CAPS. The compiled code passes the first argument in 'this' and
33 // it does not push the function onto the stack. This means that you
34 // cannot use contexts in all these functions.
35
36
37 /* -----------------------------------
38    - - -   C o m p a r i s o n   - - -
39    -----------------------------------
40 */
41
42 // The following declarations are shared with other native JS files.
43 // They are all declared at this one spot to avoid redeclaration errors.
44 var $Object = global.Object;
45 var $Array = global.Array;
46 var $String = global.String;
47 var $Number = global.Number;
48 var $Function = global.Function;
49 var $Boolean = global.Boolean;
50 var $NaN = %GetRootNaN();
51 var builtins = this;
52
53 // ECMA-262 Section 11.9.3.
54 function EQUALS(y) {
55   if (IS_STRING(this) && IS_STRING(y)) return %StringEquals(this, y);
56   var x = this;
57
58   while (true) {
59     if (IS_NUMBER(x)) {
60       while (true) {
61         if (IS_NUMBER(y)) return %NumberEquals(x, y);
62         if (IS_NULL_OR_UNDEFINED(y)) return 1;  // not equal
63         if (!IS_SPEC_OBJECT(y)) {
64           // String or boolean.
65           return %NumberEquals(x, %ToNumber(y));
66         }
67         y = %ToPrimitive(y, NO_HINT);
68       }
69     } else if (IS_STRING(x)) {
70       while (true) {
71         if (IS_STRING(y)) return %StringEquals(x, y);
72         if (IS_NUMBER(y)) return %NumberEquals(%ToNumber(x), y);
73         if (IS_BOOLEAN(y)) return %NumberEquals(%ToNumber(x), %ToNumber(y));
74         if (IS_NULL_OR_UNDEFINED(y)) return 1;  // not equal
75         y = %ToPrimitive(y, NO_HINT);
76       }
77     } else if (IS_BOOLEAN(x)) {
78       if (IS_BOOLEAN(y)) return %_ObjectEquals(x, y) ? 0 : 1;
79       if (IS_NULL_OR_UNDEFINED(y)) return 1;
80       if (IS_NUMBER(y)) return %NumberEquals(%ToNumber(x), y);
81       if (IS_STRING(y)) return %NumberEquals(%ToNumber(x), %ToNumber(y));
82       // y is object.
83       x = %ToNumber(x);
84       y = %ToPrimitive(y, NO_HINT);
85     } else if (IS_NULL_OR_UNDEFINED(x)) {
86       return IS_NULL_OR_UNDEFINED(y) ? 0 : 1;
87     } else {
88       // x is an object.
89       if (IS_SPEC_OBJECT(y)) {
90         return %_ObjectEquals(x, y) ? 0 : 1;
91       }
92       if (IS_NULL_OR_UNDEFINED(y)) return 1;  // not equal
93       if (IS_BOOLEAN(y)) y = %ToNumber(y);
94       x = %ToPrimitive(x, NO_HINT);
95     }
96   }
97 }
98
99 // ECMA-262, section 11.9.4, page 56.
100 function STRICT_EQUALS(x) {
101   if (IS_STRING(this)) {
102     if (!IS_STRING(x)) return 1;  // not equal
103     return %StringEquals(this, x);
104   }
105
106   if (IS_NUMBER(this)) {
107     if (!IS_NUMBER(x)) return 1;  // not equal
108     return %NumberEquals(this, x);
109   }
110
111   // If anything else gets here, we just do simple identity check.
112   // Objects (including functions), null, undefined and booleans were
113   // checked in the CompareStub, so there should be nothing left.
114   return %_ObjectEquals(this, x) ? 0 : 1;
115 }
116
117
118 // ECMA-262, section 11.8.5, page 53. The 'ncr' parameter is used as
119 // the result when either (or both) the operands are NaN.
120 function COMPARE(x, ncr) {
121   var left;
122   var right;
123   // Fast cases for string, numbers and undefined compares.
124   if (IS_STRING(this)) {
125     if (IS_STRING(x)) return %_StringCompare(this, x);
126     if (IS_UNDEFINED(x)) return ncr;
127     left = this;
128   } else if (IS_NUMBER(this)) {
129     if (IS_NUMBER(x)) return %NumberCompare(this, x, ncr);
130     if (IS_UNDEFINED(x)) return ncr;
131     left = this;
132   } else if (IS_UNDEFINED(this)) {
133     if (!IS_UNDEFINED(x)) {
134       %ToPrimitive(x, NUMBER_HINT);
135     }
136     return ncr;
137   } else if (IS_UNDEFINED(x)) {
138     %ToPrimitive(this, NUMBER_HINT);
139     return ncr;
140   } else {
141     left = %ToPrimitive(this, NUMBER_HINT);
142   }
143
144   right = %ToPrimitive(x, NUMBER_HINT);
145   if (IS_STRING(left) && IS_STRING(right)) {
146     return %_StringCompare(left, right);
147   } else {
148     var left_number = %ToNumber(left);
149     var right_number = %ToNumber(right);
150     if (NUMBER_IS_NAN(left_number) || NUMBER_IS_NAN(right_number)) return ncr;
151     return %NumberCompare(left_number, right_number, ncr);
152   }
153 }
154
155
156
157 /* -----------------------------------
158    - - -   A r i t h m e t i c   - - -
159    -----------------------------------
160 */
161
162 // ECMA-262, section 11.6.1, page 50.
163 function ADD(x) {
164   // Fast case: Check for number operands and do the addition.
165   if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x);
166   if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x);
167
168   // Default implementation.
169   var a = %ToPrimitive(this, NO_HINT);
170   var b = %ToPrimitive(x, NO_HINT);
171
172   if (IS_STRING(a)) {
173     return %_StringAdd(a, %ToString(b));
174   } else if (IS_STRING(b)) {
175     return %_StringAdd(%NonStringToString(a), b);
176   } else {
177     return %NumberAdd(%ToNumber(a), %ToNumber(b));
178   }
179 }
180
181
182 // Left operand (this) is already a string.
183 function STRING_ADD_LEFT(y) {
184   if (!IS_STRING(y)) {
185     if (IS_STRING_WRAPPER(y) && %_IsStringWrapperSafeForDefaultValueOf(y)) {
186       y = %_ValueOf(y);
187     } else {
188       y = IS_NUMBER(y)
189           ? %_NumberToString(y)
190           : %ToString(%ToPrimitive(y, NO_HINT));
191     }
192   }
193   return %_StringAdd(this, y);
194 }
195
196
197 // Right operand (y) is already a string.
198 function STRING_ADD_RIGHT(y) {
199   var x = this;
200   if (!IS_STRING(x)) {
201     if (IS_STRING_WRAPPER(x) && %_IsStringWrapperSafeForDefaultValueOf(x)) {
202       x = %_ValueOf(x);
203     } else {
204       x = IS_NUMBER(x)
205           ? %_NumberToString(x)
206           : %ToString(%ToPrimitive(x, NO_HINT));
207     }
208   }
209   return %_StringAdd(x, y);
210 }
211
212
213 // ECMA-262, section 11.6.2, page 50.
214 function SUB(y) {
215   var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
216   if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
217   return %NumberSub(x, y);
218 }
219
220
221 // ECMA-262, section 11.5.1, page 48.
222 function MUL(y) {
223   var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
224   if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
225   return %NumberMul(x, y);
226 }
227
228
229 // ECMA-262, section 11.5.2, page 49.
230 function DIV(y) {
231   var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
232   if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
233   return %NumberDiv(x, y);
234 }
235
236
237 // ECMA-262, section 11.5.3, page 49.
238 function MOD(y) {
239   var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
240   if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
241   return %NumberMod(x, y);
242 }
243
244
245
246 /* -------------------------------------------
247    - - -   B i t   o p e r a t i o n s   - - -
248    -------------------------------------------
249 */
250
251 // ECMA-262, section 11.10, page 57.
252 function BIT_OR(y) {
253   var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
254   if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
255   return %NumberOr(x, y);
256 }
257
258
259 // ECMA-262, section 11.10, page 57.
260 function BIT_AND(y) {
261   var x;
262   if (IS_NUMBER(this)) {
263     x = this;
264     if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
265   } else {
266     x = %NonNumberToNumber(this);
267     // Make sure to convert the right operand to a number before
268     // bailing out in the fast case, but after converting the
269     // left operand. This ensures that valueOf methods on the right
270     // operand are always executed.
271     if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
272     // Optimize for the case where we end up AND'ing a value
273     // that doesn't convert to a number. This is common in
274     // certain benchmarks.
275     if (NUMBER_IS_NAN(x)) return 0;
276   }
277   return %NumberAnd(x, y);
278 }
279
280
281 // ECMA-262, section 11.10, page 57.
282 function BIT_XOR(y) {
283   var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
284   if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
285   return %NumberXor(x, y);
286 }
287
288
289 // ECMA-262, section 11.4.7, page 47.
290 function UNARY_MINUS() {
291   var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
292   return %NumberUnaryMinus(x);
293 }
294
295
296 // ECMA-262, section 11.4.8, page 48.
297 function BIT_NOT() {
298   var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
299   return %NumberNot(x);
300 }
301
302
303 // ECMA-262, section 11.7.1, page 51.
304 function SHL(y) {
305   var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
306   if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
307   return %NumberShl(x, y);
308 }
309
310
311 // ECMA-262, section 11.7.2, page 51.
312 function SAR(y) {
313   var x;
314   if (IS_NUMBER(this)) {
315     x = this;
316     if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
317   } else {
318     x = %NonNumberToNumber(this);
319     // Make sure to convert the right operand to a number before
320     // bailing out in the fast case, but after converting the
321     // left operand. This ensures that valueOf methods on the right
322     // operand are always executed.
323     if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
324     // Optimize for the case where we end up shifting a value
325     // that doesn't convert to a number. This is common in
326     // certain benchmarks.
327     if (NUMBER_IS_NAN(x)) return 0;
328   }
329   return %NumberSar(x, y);
330 }
331
332
333 // ECMA-262, section 11.7.3, page 52.
334 function SHR(y) {
335   var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
336   if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
337   return %NumberShr(x, y);
338 }
339
340
341
342 /* -----------------------------
343    - - -   H e l p e r s   - - -
344    -----------------------------
345 */
346
347 // ECMA-262, section 11.4.1, page 46.
348 function DELETE(key, strict) {
349   return %DeleteProperty(%ToObject(this), %ToString(key), strict);
350 }
351
352
353 // ECMA-262, section 11.8.7, page 54.
354 function IN(x) {
355   if (!IS_SPEC_OBJECT(x)) {
356     throw %MakeTypeError('invalid_in_operator_use', [this, x]);
357   }
358   return %_IsNonNegativeSmi(this) ?
359     %HasElement(x, this) : %HasProperty(x, %ToString(this));
360 }
361
362
363 // ECMA-262, section 11.8.6, page 54. To make the implementation more
364 // efficient, the return value should be zero if the 'this' is an
365 // instance of F, and non-zero if not. This makes it possible to avoid
366 // an expensive ToBoolean conversion in the generated code.
367 function INSTANCE_OF(F) {
368   var V = this;
369   if (!IS_SPEC_FUNCTION(F)) {
370     throw %MakeTypeError('instanceof_function_expected', [V]);
371   }
372
373   // If V is not an object, return false.
374   if (!IS_SPEC_OBJECT(V)) {
375     return 1;
376   }
377
378   // Check if function is bound, if so, get [[BoundFunction]] from it
379   // and use that instead of F.
380   var bindings = %BoundFunctionGetBindings(F);
381   if (bindings) {
382     F = bindings[kBoundFunctionIndex];  // Always a non-bound function.
383   }
384   // Get the prototype of F; if it is not an object, throw an error.
385   var O = F.prototype;
386   if (!IS_SPEC_OBJECT(O)) {
387     throw %MakeTypeError('instanceof_nonobject_proto', [O]);
388   }
389
390   // Return whether or not O is in the prototype chain of V.
391   return %IsInPrototypeChain(O, V) ? 0 : 1;
392 }
393
394
395 // Filter a given key against an object by checking if the object
396 // has a property with the given key; return the key as a string if
397 // it has. Otherwise returns 0 (smi). Used in for-in statements.
398 function FILTER_KEY(key) {
399   var string = %ToString(key);
400   if (%HasProperty(this, string)) return string;
401   return 0;
402 }
403
404
405 function CALL_NON_FUNCTION() {
406   var delegate = %GetFunctionDelegate(this);
407   if (!IS_FUNCTION(delegate)) {
408     throw %MakeTypeError('called_non_callable', [typeof this]);
409   }
410   return %Apply(delegate, this, arguments, 0, %_ArgumentsLength());
411 }
412
413
414 function CALL_NON_FUNCTION_AS_CONSTRUCTOR() {
415   var delegate = %GetConstructorDelegate(this);
416   if (!IS_FUNCTION(delegate)) {
417     throw %MakeTypeError('called_non_callable', [typeof this]);
418   }
419   return %Apply(delegate, this, arguments, 0, %_ArgumentsLength());
420 }
421
422
423 function CALL_FUNCTION_PROXY() {
424   var arity = %_ArgumentsLength() - 1;
425   var proxy = %_Arguments(arity);  // The proxy comes in as an additional arg.
426   var trap = %GetCallTrap(proxy);
427   return %Apply(trap, this, arguments, 0, arity);
428 }
429
430
431 function CALL_FUNCTION_PROXY_AS_CONSTRUCTOR() {
432   var proxy = this;
433   var trap = %GetConstructTrap(proxy);
434   return %Apply(trap, this, arguments, 0, %_ArgumentsLength());
435 }
436
437
438 function APPLY_PREPARE(args) {
439   var length;
440   // First check whether length is a positive Smi and args is an
441   // array. This is the fast case. If this fails, we do the slow case
442   // that takes care of more eventualities.
443   if (IS_ARRAY(args)) {
444     length = args.length;
445     if (%_IsSmi(length) && length >= 0 && length < 0x800000 &&
446         IS_SPEC_FUNCTION(this)) {
447       return length;
448     }
449   }
450
451   length = (args == null) ? 0 : %ToUint32(args.length);
452
453   // We can handle any number of apply arguments if the stack is
454   // big enough, but sanity check the value to avoid overflow when
455   // multiplying with pointer size.
456   if (length > 0x800000) {
457     throw %MakeRangeError('stack_overflow', []);
458   }
459
460   if (!IS_SPEC_FUNCTION(this)) {
461     throw %MakeTypeError('apply_non_function',
462                          [ %ToString(this), typeof this ]);
463   }
464
465   // Make sure the arguments list has the right type.
466   if (args != null && !IS_SPEC_OBJECT(args)) {
467     throw %MakeTypeError('apply_wrong_args', []);
468   }
469
470   // Return the length which is the number of arguments to copy to the
471   // stack. It is guaranteed to be a small integer at this point.
472   return length;
473 }
474
475
476 function APPLY_OVERFLOW(length) {
477   throw %MakeRangeError('stack_overflow', []);
478 }
479
480
481 // Convert the receiver to an object - forward to ToObject.
482 function TO_OBJECT() {
483   return %ToObject(this);
484 }
485
486
487 // Convert the receiver to a number - forward to ToNumber.
488 function TO_NUMBER() {
489   return %ToNumber(this);
490 }
491
492
493 // Convert the receiver to a string - forward to ToString.
494 function TO_STRING() {
495   return %ToString(this);
496 }
497
498
499 /* -------------------------------------
500    - - -   C o n v e r s i o n s   - - -
501    -------------------------------------
502 */
503
504 // ECMA-262, section 9.1, page 30. Use null/undefined for no hint,
505 // (1) for number hint, and (2) for string hint.
506 function ToPrimitive(x, hint) {
507   // Fast case check.
508   if (IS_STRING(x)) return x;
509   // Normal behavior.
510   if (!IS_SPEC_OBJECT(x)) return x;
511   if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT;
512   return (hint == NUMBER_HINT) ? %DefaultNumber(x) : %DefaultString(x);
513 }
514
515
516 // ECMA-262, section 9.2, page 30
517 function ToBoolean(x) {
518   if (IS_BOOLEAN(x)) return x;
519   if (IS_STRING(x)) return x.length != 0;
520   if (x == null) return false;
521   if (IS_NUMBER(x)) return !((x == 0) || NUMBER_IS_NAN(x));
522   return true;
523 }
524
525
526 // ECMA-262, section 9.3, page 31.
527 function ToNumber(x) {
528   if (IS_NUMBER(x)) return x;
529   if (IS_STRING(x)) {
530     return %_HasCachedArrayIndex(x) ? %_GetCachedArrayIndex(x)
531                                     : %StringToNumber(x);
532   }
533   if (IS_BOOLEAN(x)) return x ? 1 : 0;
534   if (IS_UNDEFINED(x)) return $NaN;
535   return (IS_NULL(x)) ? 0 : ToNumber(%DefaultNumber(x));
536 }
537
538 function NonNumberToNumber(x) {
539   if (IS_STRING(x)) {
540     return %_HasCachedArrayIndex(x) ? %_GetCachedArrayIndex(x)
541                                     : %StringToNumber(x);
542   }
543   if (IS_BOOLEAN(x)) return x ? 1 : 0;
544   if (IS_UNDEFINED(x)) return $NaN;
545   return (IS_NULL(x)) ? 0 : ToNumber(%DefaultNumber(x));
546 }
547
548
549 // ECMA-262, section 9.8, page 35.
550 function ToString(x) {
551   if (IS_STRING(x)) return x;
552   if (IS_NUMBER(x)) return %_NumberToString(x);
553   if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
554   if (IS_UNDEFINED(x)) return 'undefined';
555   return (IS_NULL(x)) ? 'null' : %ToString(%DefaultString(x));
556 }
557
558 function NonStringToString(x) {
559   if (IS_NUMBER(x)) return %_NumberToString(x);
560   if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
561   if (IS_UNDEFINED(x)) return 'undefined';
562   return (IS_NULL(x)) ? 'null' : %ToString(%DefaultString(x));
563 }
564
565
566 // ECMA-262, section 9.9, page 36.
567 function ToObject(x) {
568   if (IS_STRING(x)) return new $String(x);
569   if (IS_NUMBER(x)) return new $Number(x);
570   if (IS_BOOLEAN(x)) return new $Boolean(x);
571   if (IS_NULL_OR_UNDEFINED(x) && !IS_UNDETECTABLE(x)) {
572     throw %MakeTypeError('null_to_object', []);
573   }
574   return x;
575 }
576
577
578 // ECMA-262, section 9.4, page 34.
579 function ToInteger(x) {
580   if (%_IsSmi(x)) return x;
581   return %NumberToInteger(ToNumber(x));
582 }
583
584
585 // ECMA-262, section 9.6, page 34.
586 function ToUint32(x) {
587   if (%_IsSmi(x) && x >= 0) return x;
588   return %NumberToJSUint32(ToNumber(x));
589 }
590
591
592 // ECMA-262, section 9.5, page 34
593 function ToInt32(x) {
594   if (%_IsSmi(x)) return x;
595   return %NumberToJSInt32(ToNumber(x));
596 }
597
598
599 // ES5, section 9.12
600 function SameValue(x, y) {
601   if (typeof x != typeof y) return false;
602   if (IS_NUMBER(x)) {
603     if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true;
604     // x is +0 and y is -0 or vice versa.
605     if (x === 0 && y === 0 && (1 / x) != (1 / y)) return false;
606   }
607   return x === y;
608 }
609
610
611 /* ---------------------------------
612    - - -   U t i l i t i e s   - - -
613    ---------------------------------
614 */
615
616 // Returns if the given x is a primitive value - not an object or a
617 // function.
618 function IsPrimitive(x) {
619   // Even though the type of null is "object", null is still
620   // considered a primitive value. IS_SPEC_OBJECT handles this correctly
621   // (i.e., it will return false if x is null).
622   return !IS_SPEC_OBJECT(x);
623 }
624
625
626 // ECMA-262, section 8.6.2.6, page 28.
627 function DefaultNumber(x) {
628   var valueOf = x.valueOf;
629   if (IS_SPEC_FUNCTION(valueOf)) {
630     var v = %_CallFunction(x, valueOf);
631     if (%IsPrimitive(v)) return v;
632   }
633
634   var toString = x.toString;
635   if (IS_SPEC_FUNCTION(toString)) {
636     var s = %_CallFunction(x, toString);
637     if (%IsPrimitive(s)) return s;
638   }
639
640   throw %MakeTypeError('cannot_convert_to_primitive', []);
641 }
642
643
644 // ECMA-262, section 8.6.2.6, page 28.
645 function DefaultString(x) {
646   var toString = x.toString;
647   if (IS_SPEC_FUNCTION(toString)) {
648     var s = %_CallFunction(x, toString);
649     if (%IsPrimitive(s)) return s;
650   }
651
652   var valueOf = x.valueOf;
653   if (IS_SPEC_FUNCTION(valueOf)) {
654     var v = %_CallFunction(x, valueOf);
655     if (%IsPrimitive(v)) return v;
656   }
657
658   throw %MakeTypeError('cannot_convert_to_primitive', []);
659 }
660
661
662 // NOTE: Setting the prototype for Array must take place as early as
663 // possible due to code generation for array literals.  When
664 // generating code for a array literal a boilerplate array is created
665 // that is cloned when running the code.  It is essential that the
666 // boilerplate gets the right prototype.
667 %FunctionSetPrototype($Array, new $Array(0));