The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / runtime.js @ f230a1cf

History | View | Annotate | Download (19.5 KB)

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_SYMBOL(y)) return 1;  // not equal
73
        if (IS_NUMBER(y)) return %NumberEquals(%ToNumber(x), y);
74
        if (IS_BOOLEAN(y)) return %NumberEquals(%ToNumber(x), %ToNumber(y));
75
        if (IS_NULL_OR_UNDEFINED(y)) return 1;  // not equal
76
        y = %ToPrimitive(y, NO_HINT);
77
      }
78
    } else if (IS_SYMBOL(x)) {
79
      while (true) {
80
        if (IS_SYMBOL(y)) return %_ObjectEquals(x, y) ? 0 : 1;
81
        if (!IS_SPEC_OBJECT(y)) return 1;  // not equal
82
        y = %ToPrimitive(y, NO_HINT);
83
      }
84
    } else if (IS_BOOLEAN(x)) {
85
      if (IS_BOOLEAN(y)) return %_ObjectEquals(x, y) ? 0 : 1;
86
      if (IS_NULL_OR_UNDEFINED(y)) return 1;
87
      if (IS_NUMBER(y)) return %NumberEquals(%ToNumber(x), y);
88
      if (IS_STRING(y)) return %NumberEquals(%ToNumber(x), %ToNumber(y));
89
      if (IS_SYMBOL(y)) return 1;  // not equal
90
      // y is object.
91
      x = %ToNumber(x);
92
      y = %ToPrimitive(y, NO_HINT);
93
    } else if (IS_NULL_OR_UNDEFINED(x)) {
94
      return IS_NULL_OR_UNDEFINED(y) ? 0 : 1;
95
    } else {
96
      // x is an object.
97
      if (IS_SPEC_OBJECT(y)) {
98
        return %_ObjectEquals(x, y) ? 0 : 1;
99
      }
100
      if (IS_NULL_OR_UNDEFINED(y)) return 1;  // not equal
101
      if (IS_BOOLEAN(y)) y = %ToNumber(y);
102
      x = %ToPrimitive(x, NO_HINT);
103
    }
104
  }
105
}
106

    
107
// ECMA-262, section 11.9.4, page 56.
108
function STRICT_EQUALS(x) {
109
  if (IS_STRING(this)) {
110
    if (!IS_STRING(x)) return 1;  // not equal
111
    return %StringEquals(this, x);
112
  }
113

    
114
  if (IS_NUMBER(this)) {
115
    if (!IS_NUMBER(x)) return 1;  // not equal
116
    return %NumberEquals(this, x);
117
  }
118

    
119
  // If anything else gets here, we just do simple identity check.
120
  // Objects (including functions), null, undefined and booleans were
121
  // checked in the CompareStub, so there should be nothing left.
122
  return %_ObjectEquals(this, x) ? 0 : 1;
123
}
124

    
125

    
126
// ECMA-262, section 11.8.5, page 53. The 'ncr' parameter is used as
127
// the result when either (or both) the operands are NaN.
128
function COMPARE(x, ncr) {
129
  var left;
130
  var right;
131
  // Fast cases for string, numbers and undefined compares.
132
  if (IS_STRING(this)) {
133
    if (IS_STRING(x)) return %_StringCompare(this, x);
134
    if (IS_UNDEFINED(x)) return ncr;
135
    left = this;
136
  } else if (IS_NUMBER(this)) {
137
    if (IS_NUMBER(x)) return %NumberCompare(this, x, ncr);
138
    if (IS_UNDEFINED(x)) return ncr;
139
    left = this;
140
  } else if (IS_UNDEFINED(this)) {
141
    if (!IS_UNDEFINED(x)) {
142
      %ToPrimitive(x, NUMBER_HINT);
143
    }
144
    return ncr;
145
  } else if (IS_UNDEFINED(x)) {
146
    %ToPrimitive(this, NUMBER_HINT);
147
    return ncr;
148
  } else {
149
    left = %ToPrimitive(this, NUMBER_HINT);
150
  }
151

    
152
  right = %ToPrimitive(x, NUMBER_HINT);
153
  if (IS_STRING(left) && IS_STRING(right)) {
154
    return %_StringCompare(left, right);
155
  } else {
156
    var left_number = %ToNumber(left);
157
    var right_number = %ToNumber(right);
158
    if (NUMBER_IS_NAN(left_number) || NUMBER_IS_NAN(right_number)) return ncr;
159
    return %NumberCompare(left_number, right_number, ncr);
160
  }
161
}
162

    
163

    
164

    
165
/* -----------------------------------
166
   - - -   A r i t h m e t i c   - - -
167
   -----------------------------------
168
*/
169

    
170
// ECMA-262, section 11.6.1, page 50.
171
function ADD(x) {
172
  // Fast case: Check for number operands and do the addition.
173
  if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x);
174
  if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x);
175

    
176
  // Default implementation.
177
  var a = %ToPrimitive(this, NO_HINT);
178
  var b = %ToPrimitive(x, NO_HINT);
179

    
180
  if (IS_STRING(a)) {
181
    return %_StringAdd(a, %ToString(b));
182
  } else if (IS_STRING(b)) {
183
    return %_StringAdd(%NonStringToString(a), b);
184
  } else {
185
    return %NumberAdd(%ToNumber(a), %ToNumber(b));
186
  }
187
}
188

    
189

    
190
// Left operand (this) is already a string.
191
function STRING_ADD_LEFT(y) {
192
  if (!IS_STRING(y)) {
193
    if (IS_STRING_WRAPPER(y) && %_IsStringWrapperSafeForDefaultValueOf(y)) {
194
      y = %_ValueOf(y);
195
    } else {
196
      y = IS_NUMBER(y)
197
          ? %_NumberToString(y)
198
          : %ToString(%ToPrimitive(y, NO_HINT));
199
    }
200
  }
201
  return %_StringAdd(this, y);
202
}
203

    
204

    
205
// Right operand (y) is already a string.
206
function STRING_ADD_RIGHT(y) {
207
  var x = this;
208
  if (!IS_STRING(x)) {
209
    if (IS_STRING_WRAPPER(x) && %_IsStringWrapperSafeForDefaultValueOf(x)) {
210
      x = %_ValueOf(x);
211
    } else {
212
      x = IS_NUMBER(x)
213
          ? %_NumberToString(x)
214
          : %ToString(%ToPrimitive(x, NO_HINT));
215
    }
216
  }
217
  return %_StringAdd(x, y);
218
}
219

    
220

    
221
// ECMA-262, section 11.6.2, page 50.
222
function SUB(y) {
223
  var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
224
  if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
225
  return %NumberSub(x, y);
226
}
227

    
228

    
229
// ECMA-262, section 11.5.1, page 48.
230
function MUL(y) {
231
  var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
232
  if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
233
  return %NumberMul(x, y);
234
}
235

    
236

    
237
// ECMA-262, section 11.5.2, page 49.
238
function DIV(y) {
239
  var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
240
  if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
241
  return %NumberDiv(x, y);
242
}
243

    
244

    
245
// ECMA-262, section 11.5.3, page 49.
246
function MOD(y) {
247
  var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
248
  if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
249
  return %NumberMod(x, y);
250
}
251

    
252

    
253

    
254
/* -------------------------------------------
255
   - - -   B i t   o p e r a t i o n s   - - -
256
   -------------------------------------------
257
*/
258

    
259
// ECMA-262, section 11.10, page 57.
260
function BIT_OR(y) {
261
  var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
262
  if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
263
  return %NumberOr(x, y);
264
}
265

    
266

    
267
// ECMA-262, section 11.10, page 57.
268
function BIT_AND(y) {
269
  var x;
270
  if (IS_NUMBER(this)) {
271
    x = this;
272
    if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
273
  } else {
274
    x = %NonNumberToNumber(this);
275
    // Make sure to convert the right operand to a number before
276
    // bailing out in the fast case, but after converting the
277
    // left operand. This ensures that valueOf methods on the right
278
    // operand are always executed.
279
    if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
280
    // Optimize for the case where we end up AND'ing a value
281
    // that doesn't convert to a number. This is common in
282
    // certain benchmarks.
283
    if (NUMBER_IS_NAN(x)) return 0;
284
  }
285
  return %NumberAnd(x, y);
286
}
287

    
288

    
289
// ECMA-262, section 11.10, page 57.
290
function BIT_XOR(y) {
291
  var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
292
  if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
293
  return %NumberXor(x, y);
294
}
295

    
296

    
297
// ECMA-262, section 11.7.1, page 51.
298
function SHL(y) {
299
  var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
300
  if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
301
  return %NumberShl(x, y);
302
}
303

    
304

    
305
// ECMA-262, section 11.7.2, page 51.
306
function SAR(y) {
307
  var x;
308
  if (IS_NUMBER(this)) {
309
    x = this;
310
    if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
311
  } else {
312
    x = %NonNumberToNumber(this);
313
    // Make sure to convert the right operand to a number before
314
    // bailing out in the fast case, but after converting the
315
    // left operand. This ensures that valueOf methods on the right
316
    // operand are always executed.
317
    if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
318
    // Optimize for the case where we end up shifting a value
319
    // that doesn't convert to a number. This is common in
320
    // certain benchmarks.
321
    if (NUMBER_IS_NAN(x)) return 0;
322
  }
323
  return %NumberSar(x, y);
324
}
325

    
326

    
327
// ECMA-262, section 11.7.3, page 52.
328
function SHR(y) {
329
  var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
330
  if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
331
  return %NumberShr(x, y);
332
}
333

    
334

    
335

    
336
/* -----------------------------
337
   - - -   H e l p e r s   - - -
338
   -----------------------------
339
*/
340

    
341
// ECMA-262, section 11.4.1, page 46.
342
function DELETE(key, strict) {
343
  return %DeleteProperty(%ToObject(this), %ToName(key), strict);
344
}
345

    
346

    
347
// ECMA-262, section 11.8.7, page 54.
348
function IN(x) {
349
  if (!IS_SPEC_OBJECT(x)) {
350
    throw %MakeTypeError('invalid_in_operator_use', [this, x]);
351
  }
352
  return %_IsNonNegativeSmi(this) ?
353
    %HasElement(x, this) : %HasProperty(x, %ToName(this));
354
}
355

    
356

    
357
// ECMA-262, section 11.8.6, page 54. To make the implementation more
358
// efficient, the return value should be zero if the 'this' is an
359
// instance of F, and non-zero if not. This makes it possible to avoid
360
// an expensive ToBoolean conversion in the generated code.
361
function INSTANCE_OF(F) {
362
  var V = this;
363
  if (!IS_SPEC_FUNCTION(F)) {
364
    throw %MakeTypeError('instanceof_function_expected', [V]);
365
  }
366

    
367
  // If V is not an object, return false.
368
  if (!IS_SPEC_OBJECT(V)) {
369
    return 1;
370
  }
371

    
372
  // Check if function is bound, if so, get [[BoundFunction]] from it
373
  // and use that instead of F.
374
  var bindings = %BoundFunctionGetBindings(F);
375
  if (bindings) {
376
    F = bindings[kBoundFunctionIndex];  // Always a non-bound function.
377
  }
378
  // Get the prototype of F; if it is not an object, throw an error.
379
  var O = F.prototype;
380
  if (!IS_SPEC_OBJECT(O)) {
381
    throw %MakeTypeError('instanceof_nonobject_proto', [O]);
382
  }
383

    
384
  // Return whether or not O is in the prototype chain of V.
385
  return %IsInPrototypeChain(O, V) ? 0 : 1;
386
}
387

    
388

    
389
// Filter a given key against an object by checking if the object
390
// has a property with the given key; return the key as a string if
391
// it has. Otherwise returns 0 (smi). Used in for-in statements.
392
function FILTER_KEY(key) {
393
  var string = %ToName(key);
394
  if (%HasProperty(this, string)) return string;
395
  return 0;
396
}
397

    
398

    
399
function CALL_NON_FUNCTION() {
400
  var delegate = %GetFunctionDelegate(this);
401
  if (!IS_FUNCTION(delegate)) {
402
    throw %MakeTypeError('called_non_callable', [typeof this]);
403
  }
404
  return %Apply(delegate, this, arguments, 0, %_ArgumentsLength());
405
}
406

    
407

    
408
function CALL_NON_FUNCTION_AS_CONSTRUCTOR() {
409
  var delegate = %GetConstructorDelegate(this);
410
  if (!IS_FUNCTION(delegate)) {
411
    throw %MakeTypeError('called_non_callable', [typeof this]);
412
  }
413
  return %Apply(delegate, this, arguments, 0, %_ArgumentsLength());
414
}
415

    
416

    
417
function CALL_FUNCTION_PROXY() {
418
  var arity = %_ArgumentsLength() - 1;
419
  var proxy = %_Arguments(arity);  // The proxy comes in as an additional arg.
420
  var trap = %GetCallTrap(proxy);
421
  return %Apply(trap, this, arguments, 0, arity);
422
}
423

    
424

    
425
function CALL_FUNCTION_PROXY_AS_CONSTRUCTOR() {
426
  var proxy = this;
427
  var trap = %GetConstructTrap(proxy);
428
  return %Apply(trap, this, arguments, 0, %_ArgumentsLength());
429
}
430

    
431

    
432
function APPLY_PREPARE(args) {
433
  var length;
434
  // First check whether length is a positive Smi and args is an
435
  // array. This is the fast case. If this fails, we do the slow case
436
  // that takes care of more eventualities.
437
  if (IS_ARRAY(args)) {
438
    length = args.length;
439
    if (%_IsSmi(length) && length >= 0 && length < 0x800000 &&
440
        IS_SPEC_FUNCTION(this)) {
441
      return length;
442
    }
443
  }
444

    
445
  length = (args == null) ? 0 : %ToUint32(args.length);
446

    
447
  // We can handle any number of apply arguments if the stack is
448
  // big enough, but sanity check the value to avoid overflow when
449
  // multiplying with pointer size.
450
  if (length > 0x800000) {
451
    throw %MakeRangeError('stack_overflow', []);
452
  }
453

    
454
  if (!IS_SPEC_FUNCTION(this)) {
455
    throw %MakeTypeError('apply_non_function',
456
                         [ %ToString(this), typeof this ]);
457
  }
458

    
459
  // Make sure the arguments list has the right type.
460
  if (args != null && !IS_SPEC_OBJECT(args)) {
461
    throw %MakeTypeError('apply_wrong_args', []);
462
  }
463

    
464
  // Return the length which is the number of arguments to copy to the
465
  // stack. It is guaranteed to be a small integer at this point.
466
  return length;
467
}
468

    
469

    
470
function APPLY_OVERFLOW(length) {
471
  throw %MakeRangeError('stack_overflow', []);
472
}
473

    
474

    
475
// Convert the receiver to an object - forward to ToObject.
476
function TO_OBJECT() {
477
  return %ToObject(this);
478
}
479

    
480

    
481
// Convert the receiver to a number - forward to ToNumber.
482
function TO_NUMBER() {
483
  return %ToNumber(this);
484
}
485

    
486

    
487
// Convert the receiver to a string - forward to ToString.
488
function TO_STRING() {
489
  return %ToString(this);
490
}
491

    
492

    
493
/* -------------------------------------
494
   - - -   C o n v e r s i o n s   - - -
495
   -------------------------------------
496
*/
497

    
498
// ECMA-262, section 9.1, page 30. Use null/undefined for no hint,
499
// (1) for number hint, and (2) for string hint.
500
function ToPrimitive(x, hint) {
501
  // Fast case check.
502
  if (IS_STRING(x)) return x;
503
  // Normal behavior.
504
  if (!IS_SPEC_OBJECT(x)) return x;
505
  if (IS_SYMBOL_WRAPPER(x)) return %_ValueOf(x);
506
  if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT;
507
  return (hint == NUMBER_HINT) ? %DefaultNumber(x) : %DefaultString(x);
508
}
509

    
510

    
511
// ECMA-262, section 9.2, page 30
512
function ToBoolean(x) {
513
  if (IS_BOOLEAN(x)) return x;
514
  if (IS_STRING(x)) return x.length != 0;
515
  if (x == null) return false;
516
  if (IS_NUMBER(x)) return !((x == 0) || NUMBER_IS_NAN(x));
517
  return true;
518
}
519

    
520

    
521
// ECMA-262, section 9.3, page 31.
522
function ToNumber(x) {
523
  if (IS_NUMBER(x)) return x;
524
  if (IS_STRING(x)) {
525
    return %_HasCachedArrayIndex(x) ? %_GetCachedArrayIndex(x)
526
                                    : %StringToNumber(x);
527
  }
528
  if (IS_BOOLEAN(x)) return x ? 1 : 0;
529
  if (IS_UNDEFINED(x)) return NAN;
530
  if (IS_SYMBOL(x)) return NAN;
531
  return (IS_NULL(x)) ? 0 : ToNumber(%DefaultNumber(x));
532
}
533

    
534
function NonNumberToNumber(x) {
535
  if (IS_STRING(x)) {
536
    return %_HasCachedArrayIndex(x) ? %_GetCachedArrayIndex(x)
537
                                    : %StringToNumber(x);
538
  }
539
  if (IS_BOOLEAN(x)) return x ? 1 : 0;
540
  if (IS_UNDEFINED(x)) return NAN;
541
  if (IS_SYMBOL(x)) return NAN;
542
  return (IS_NULL(x)) ? 0 : ToNumber(%DefaultNumber(x));
543
}
544

    
545

    
546
// ECMA-262, section 9.8, page 35.
547
function ToString(x) {
548
  if (IS_STRING(x)) return x;
549
  if (IS_NUMBER(x)) return %_NumberToString(x);
550
  if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
551
  if (IS_UNDEFINED(x)) return 'undefined';
552
  return (IS_NULL(x)) ? 'null' : %ToString(%DefaultString(x));
553
}
554

    
555
function NonStringToString(x) {
556
  if (IS_NUMBER(x)) return %_NumberToString(x);
557
  if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
558
  if (IS_UNDEFINED(x)) return 'undefined';
559
  return (IS_NULL(x)) ? 'null' : %ToString(%DefaultString(x));
560
}
561

    
562

    
563
// ES6 symbols
564
function ToName(x) {
565
  return IS_SYMBOL(x) ? x : %ToString(x);
566
}
567

    
568

    
569
// ECMA-262, section 9.9, page 36.
570
function ToObject(x) {
571
  if (IS_STRING(x)) return new $String(x);
572
  if (IS_SYMBOL(x)) return new $Symbol(x);
573
  if (IS_NUMBER(x)) return new $Number(x);
574
  if (IS_BOOLEAN(x)) return new $Boolean(x);
575
  if (IS_NULL_OR_UNDEFINED(x) && !IS_UNDETECTABLE(x)) {
576
    throw %MakeTypeError('undefined_or_null_to_object', []);
577
  }
578
  return x;
579
}
580

    
581

    
582
// ECMA-262, section 9.4, page 34.
583
function ToInteger(x) {
584
  if (%_IsSmi(x)) return x;
585
  return %NumberToInteger(ToNumber(x));
586
}
587

    
588

    
589
// ECMA-262, section 9.6, page 34.
590
function ToUint32(x) {
591
  if (%_IsSmi(x) && x >= 0) return x;
592
  return %NumberToJSUint32(ToNumber(x));
593
}
594

    
595

    
596
// ECMA-262, section 9.5, page 34
597
function ToInt32(x) {
598
  if (%_IsSmi(x)) return x;
599
  return %NumberToJSInt32(ToNumber(x));
600
}
601

    
602

    
603
// ES5, section 9.12
604
function SameValue(x, y) {
605
  if (typeof x != typeof y) return false;
606
  if (IS_NUMBER(x)) {
607
    if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true;
608
    // x is +0 and y is -0 or vice versa.
609
    if (x === 0 && y === 0 && (1 / x) != (1 / y)) return false;
610
  }
611
  return x === y;
612
}
613

    
614

    
615
/* ---------------------------------
616
   - - -   U t i l i t i e s   - - -
617
   ---------------------------------
618
*/
619

    
620
// Returns if the given x is a primitive value - not an object or a
621
// function.
622
function IsPrimitive(x) {
623
  // Even though the type of null is "object", null is still
624
  // considered a primitive value. IS_SPEC_OBJECT handles this correctly
625
  // (i.e., it will return false if x is null).
626
  return !IS_SPEC_OBJECT(x);
627
}
628

    
629

    
630
// ECMA-262, section 8.6.2.6, page 28.
631
function DefaultNumber(x) {
632
  var valueOf = x.valueOf;
633
  if (IS_SPEC_FUNCTION(valueOf)) {
634
    var v = %_CallFunction(x, valueOf);
635
    if (%IsPrimitive(v)) return v;
636
  }
637

    
638
  var toString = x.toString;
639
  if (IS_SPEC_FUNCTION(toString)) {
640
    var s = %_CallFunction(x, toString);
641
    if (%IsPrimitive(s)) return s;
642
  }
643

    
644
  throw %MakeTypeError('cannot_convert_to_primitive', []);
645
}
646

    
647
// ECMA-262, section 8.6.2.6, page 28.
648
function DefaultString(x) {
649
  var toString = x.toString;
650
  if (IS_SPEC_FUNCTION(toString)) {
651
    var s = %_CallFunction(x, toString);
652
    if (%IsPrimitive(s)) return s;
653
  }
654

    
655
  var valueOf = x.valueOf;
656
  if (IS_SPEC_FUNCTION(valueOf)) {
657
    var v = %_CallFunction(x, valueOf);
658
    if (%IsPrimitive(v)) return v;
659
  }
660

    
661
  throw %MakeTypeError('cannot_convert_to_primitive', []);
662
}
663

    
664
function ToPositiveInteger(x, rangeErrorName) {
665
  var i = TO_INTEGER(x);
666
  if (i < 0) throw %MakeRangeError(rangeErrorName);
667
  return i;
668
}
669

    
670

    
671
// NOTE: Setting the prototype for Array must take place as early as
672
// possible due to code generation for array literals.  When
673
// generating code for a array literal a boilerplate array is created
674
// that is cloned when running the code.  It is essential that the
675
// boilerplate gets the right prototype.
676
%FunctionSetPrototype($Array, new $Array(0));