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 @ 40c0f755

History | View | Annotate | Download (14.4 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 const declarations are shared with other native JS files.
43
// They are all declared at this one spot to avoid const redeclaration errors.
44
const $Object = global.Object;
45
const $Array = global.Array;
46
const $String = global.String;
47
const $Number = global.Number;
48
const $Function = global.Function;
49
const $Boolean = global.Boolean;
50
const $NaN = 0/0;
51

    
52

    
53
// ECMA-262, section 11.9.1, page 55.
54
function EQUALS(y) {
55
  if (IS_STRING(this) && IS_STRING(y)) return %StringEquals(this, y);
56
  var x = this;
57

    
58
  // NOTE: We use iteration instead of recursion, because it is
59
  // difficult to call EQUALS with the correct setting of 'this' in
60
  // an efficient way.
61
  while (true) {
62
    if (IS_NUMBER(x)) {
63
      if (y == null) return 1;  // not equal
64
      return %NumberEquals(x, %ToNumber(y));
65
    } else if (IS_STRING(x)) {
66
      if (IS_STRING(y)) return %StringEquals(x, y);
67
      if (IS_NUMBER(y)) return %NumberEquals(%ToNumber(x), y);
68
      if (IS_BOOLEAN(y)) return %NumberEquals(%ToNumber(x), %ToNumber(y));
69
      if (y == null) return 1;  // not equal
70
      y = %ToPrimitive(y, NO_HINT);
71
    } else if (IS_BOOLEAN(x)) {
72
      if (IS_BOOLEAN(y)) {
73
        return %_ObjectEquals(x, y) ? 0 : 1;
74
      }
75
      if (y == null) return 1;  // not equal
76
      return %NumberEquals(%ToNumber(x), %ToNumber(y));
77
    } else if (x == null) {
78
      // NOTE: This checks for both null and undefined.
79
      return (y == null) ? 0 : 1;
80
    } else {
81
      // x is not a number, boolean, null or undefined.
82
      if (y == null) return 1;  // not equal
83
      if (IS_OBJECT(y)) {
84
        return %_ObjectEquals(x, y) ? 0 : 1;
85
      }
86
      if (IS_FUNCTION(y)) {
87
        return %_ObjectEquals(x, y) ? 0 : 1;
88
      }
89

    
90
      x = %ToPrimitive(x, NO_HINT);
91
    }
92
  }
93
}
94

    
95
// ECMA-262, section 11.9.4, page 56.
96
function STRICT_EQUALS(x) {
97
  if (IS_STRING(this)) {
98
    if (!IS_STRING(x)) return 1;  // not equal
99
    return %StringEquals(this, x);
100
  } 
101

    
102
  if (IS_NUMBER(this)) {
103
    if (!IS_NUMBER(x)) return 1;  // not equal
104
    return %NumberEquals(this, x);
105
  } 
106

    
107
  // If anything else gets here, we just do simple identity check.
108
  // Objects (including functions), null, undefined and booleans were
109
  // checked in the CompareStub, so there should be nothing left.
110
  return %_ObjectEquals(this, x) ? 0 : 1;
111
}
112

    
113

    
114
// ECMA-262, section 11.8.5, page 53. The 'ncr' parameter is used as
115
// the result when either (or both) the operands are NaN.
116
function COMPARE(x, ncr) {
117
  // Fast case for numbers and strings.
118
  if (IS_NUMBER(this) && IS_NUMBER(x)) {
119
    return %NumberCompare(this, x, ncr);
120
  }
121
  if (IS_STRING(this) && IS_STRING(x)) {
122
    return %StringCompare(this, x);
123
  }
124

    
125
  // Default implementation.
126
  var a = %ToPrimitive(this, NUMBER_HINT);
127
  var b = %ToPrimitive(x, NUMBER_HINT);
128
  if (IS_STRING(a) && IS_STRING(b)) {
129
    return %StringCompare(a, b);
130
  } else {
131
    return %NumberCompare(%ToNumber(a), %ToNumber(b), ncr);
132
  }
133
}
134

    
135

    
136

    
137
/* -----------------------------------
138
   - - -   A r i t h m e t i c   - - -
139
   -----------------------------------
140
*/
141

    
142
// ECMA-262, section 11.6.1, page 50.
143
function ADD(x) {
144
  // Fast case: Check for number operands and do the addition.
145
  if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x);
146
  if (IS_STRING(this) && IS_STRING(x)) return %StringAdd(this, x);
147

    
148
  // Default implementation.
149
  var a = %ToPrimitive(this, NO_HINT);
150
  var b = %ToPrimitive(x, NO_HINT);
151
  
152
  if (IS_STRING(a)) {
153
    return %StringAdd(a, %ToString(b));
154
  } else if (IS_STRING(b)) {
155
    return %StringAdd(%ToString(a), b);
156
  } else {
157
    return %NumberAdd(%ToNumber(a), %ToNumber(b));
158
  }
159
}
160

    
161

    
162
// Left operand (this) is already a string.
163
function STRING_ADD_LEFT(x) {
164
  x = %ToString(%ToPrimitive(x, NO_HINT));
165
  return %StringAdd(this, x);
166
}
167

    
168

    
169
// Right operand (x) is already a string.
170
function STRING_ADD_RIGHT(x) {
171
  var a = %ToString(%ToPrimitive(this, NO_HINT));
172
  return %StringAdd(a, x);
173
}
174

    
175

    
176
// ECMA-262, section 11.6.2, page 50.
177
function SUB(x) {
178
  return %NumberSub(%ToNumber(this), %ToNumber(x));
179
}
180

    
181

    
182
// ECMA-262, section 11.5.1, page 48.
183
function MUL(x) {
184
  return %NumberMul(%ToNumber(this), %ToNumber(x));
185
}
186

    
187

    
188
// ECMA-262, section 11.5.2, page 49.
189
function DIV(x) {
190
  return %NumberDiv(%ToNumber(this), %ToNumber(x));
191
}
192

    
193

    
194
// ECMA-262, section 11.5.3, page 49.
195
function MOD(x) {
196
  return %NumberMod(%ToNumber(this), %ToNumber(x));
197
}
198

    
199

    
200

    
201
/* -------------------------------------------
202
   - - -   B i t   o p e r a t i o n s   - - -
203
   -------------------------------------------
204
*/
205

    
206
// ECMA-262, section 11.10, page 57.
207
function BIT_OR(x) {
208
  return %NumberOr(%ToNumber(this), %ToNumber(x));
209
}
210

    
211

    
212
// ECMA-262, section 11.10, page 57.
213
function BIT_AND(x) {
214
  return %NumberAnd(%ToNumber(this), %ToNumber(x));
215
}
216

    
217

    
218
// ECMA-262, section 11.10, page 57.
219
function BIT_XOR(x) {
220
  return %NumberXor(%ToNumber(this), %ToNumber(x));
221
}
222

    
223

    
224
// ECMA-262, section 11.4.7, page 47.
225
function UNARY_MINUS() {
226
  return %NumberUnaryMinus(%ToNumber(this));
227
}
228

    
229

    
230
// ECMA-262, section 11.4.8, page 48.
231
function BIT_NOT() {
232
  return %NumberNot(%ToNumber(this));
233
}
234

    
235

    
236
// ECMA-262, section 11.7.1, page 51.
237
function SHL(x) {
238
  return %NumberShl(%ToNumber(this), %ToNumber(x));
239
}
240

    
241

    
242
// ECMA-262, section 11.7.2, page 51.
243
function SAR(x) {
244
  return %NumberSar(%ToNumber(this), %ToNumber(x));
245
}
246

    
247

    
248
// ECMA-262, section 11.7.3, page 52.
249
function SHR(x) {
250
  return %NumberShr(%ToNumber(this), %ToNumber(x));
251
}
252

    
253

    
254

    
255
/* -----------------------------
256
   - - -   H e l p e r s   - - -
257
   -----------------------------
258
*/
259

    
260
// ECMA-262, section 11.4.1, page 46.
261
function DELETE(key) {
262
  return %DeleteProperty(%ToObject(this), %ToString(key));
263
}
264

    
265

    
266
// ECMA-262, section 11.8.7, page 54.
267
function IN(x) {
268
  if (x == null || (!IS_OBJECT(x) && !IS_FUNCTION(x))) {
269
    throw %MakeTypeError('invalid_in_operator_use', [this, x]);
270
  }
271
  return %_IsNonNegativeSmi(this) ? %HasElement(x, this) : %HasProperty(x, %ToString(this));
272
}
273

    
274

    
275
// ECMA-262, section 11.8.6, page 54. To make the implementation more
276
// efficient, the return value should be zero if the 'this' is an
277
// instance of F, and non-zero if not. This makes it possible to avoid
278
// an expensive ToBoolean conversion in the generated code.
279
function INSTANCE_OF(F) {
280
  var V = this;
281
  if (!IS_FUNCTION(F)) {
282
    throw %MakeTypeError('instanceof_function_expected', [V]);
283
  }
284

    
285
  // If V is not an object, return false.
286
  if (IS_NULL(V) || (!IS_OBJECT(V) && !IS_FUNCTION(V))) {
287
    return 1;
288
  }
289

    
290
  // Get the prototype of F; if it is not an object, throw an error.
291
  var O = F.prototype;
292
  if (IS_NULL(O) || (!IS_OBJECT(O) && !IS_FUNCTION(O))) {
293
    throw %MakeTypeError('instanceof_nonobject_proto', [O]);
294
  }
295

    
296
  // Return whether or not O is in the prototype chain of V.
297
  return %IsInPrototypeChain(O, V) ? 0 : 1;
298
}
299

    
300

    
301
// Get an array of property keys for the given object. Used in
302
// for-in statements.
303
function GET_KEYS() {
304
  return %GetPropertyNames(this);
305
}
306

    
307

    
308
// Filter a given key against an object by checking if the object
309
// has a property with the given key; return the key as a string if
310
// it has. Otherwise returns null. Used in for-in statements.
311
function FILTER_KEY(key) {
312
  var string = %ToString(key);
313
  if (%HasProperty(this, string)) return string;
314
  return null;
315
}
316

    
317

    
318
function CALL_NON_FUNCTION() {
319
  var callee = %GetCalledFunction();
320
  var delegate = %GetFunctionDelegate(callee);
321
  if (!IS_FUNCTION(delegate)) {
322
    throw %MakeTypeError('called_non_callable', [typeof callee]);
323
  }
324

    
325
  var parameters = %NewArguments(delegate);
326
  return delegate.apply(callee, parameters);
327
}
328

    
329

    
330
function APPLY_PREPARE(args) {
331
  var length;
332
  // First check whether length is a positive Smi and args is an array.  This is the
333
  // fast case.  If this fails, we do the slow case that takes care of more eventualities
334
  if (%_IsArray(args)) {
335
    length = args.length;
336
    if (%_IsSmi(length) && length >= 0 && length < 0x800000 && IS_FUNCTION(this)) {
337
      return length;
338
    }
339
  }
340

    
341
  length = (args == null) ? 0 : %ToUint32(args.length);
342

    
343
  // We can handle any number of apply arguments if the stack is
344
  // big enough, but sanity check the value to avoid overflow when
345
  // multiplying with pointer size.
346
  if (length > 0x800000) {
347
    throw %MakeRangeError('apply_overflow', [length]);
348
  }
349

    
350
  if (!IS_FUNCTION(this)) {
351
    throw %MakeTypeError('apply_non_function', [ %ToString(this), typeof this ]);
352
  }
353

    
354
  // Make sure the arguments list has the right type.
355
  if (args != null &&
356
      !%HasArrayClass(args) &&
357
      !%HasArgumentsClass(args)) {
358
    throw %MakeTypeError('apply_wrong_args', []);
359
  }
360

    
361
  // Return the length which is the number of arguments to copy to the
362
  // stack. It is guaranteed to be a small integer at this point.
363
  return length;
364
}
365

    
366

    
367
function APPLY_OVERFLOW(length) {
368
  throw %MakeRangeError('apply_overflow', [length]);
369
}
370

    
371

    
372
// Convert the receiver to an object - forward to ToObject.
373
function TO_OBJECT() {
374
  return %ToObject(this);
375
}
376

    
377

    
378
// Convert the receiver to a number - forward to ToNumber.
379
function TO_NUMBER() {
380
  return %ToNumber(this);
381
}
382

    
383

    
384
// Convert the receiver to a string - forward to ToString.
385
function TO_STRING() {
386
  return %ToString(this);
387
}
388

    
389

    
390
/* -------------------------------------
391
   - - -   C o n v e r s i o n s   - - -
392
   -------------------------------------
393
*/
394

    
395
// ECMA-262, section 9.1, page 30. Use null/undefined for no hint,
396
// (1) for number hint, and (2) for string hint.
397
function ToPrimitive(x, hint) {
398
  // Fast case check.
399
  if (IS_STRING(x)) return x;
400
  // Normal behavior.
401
  if (!IS_OBJECT(x) && !IS_FUNCTION(x)) return x;
402
  if (x == null) return x;  // check for null, undefined
403
  if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT;
404
  return (hint == NUMBER_HINT) ? %DefaultNumber(x) : %DefaultString(x);
405
}
406

    
407

    
408
// ECMA-262, section 9.3, page 31.
409
function ToNumber(x) {
410
  if (IS_NUMBER(x)) return x;
411
  if (IS_STRING(x)) return %StringToNumber(x);
412
  if (IS_BOOLEAN(x)) return x ? 1 : 0;
413
  if (IS_UNDEFINED(x)) return $NaN;
414
  return (IS_NULL(x)) ? 0 : ToNumber(%DefaultNumber(x));
415
}
416

    
417

    
418
// ECMA-262, section 9.8, page 35.
419
function ToString(x) {
420
  if (IS_STRING(x)) return x;
421
  if (IS_NUMBER(x)) return %NumberToString(x);
422
  if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
423
  if (IS_UNDEFINED(x)) return 'undefined';
424
  return (IS_NULL(x)) ? 'null' : %ToString(%DefaultString(x));
425
}
426

    
427

    
428
// ... where did this come from?
429
function ToBoolean(x) {
430
  if (IS_BOOLEAN(x)) return x;
431
  if (IS_STRING(x)) return x.length != 0;
432
  if (x == null) return false;
433
  if (IS_NUMBER(x)) return !((x == 0) || NUMBER_IS_NAN(x));
434
  return true;
435
}
436

    
437

    
438
// ECMA-262, section 9.9, page 36.
439
function ToObject(x) {
440
  if (IS_STRING(x)) return new $String(x);
441
  if (IS_NUMBER(x)) return new $Number(x);
442
  if (IS_BOOLEAN(x)) return new $Boolean(x);
443
  if (x == null) throw %MakeTypeError('null_to_object', []);
444
  return x;
445
}
446

    
447

    
448
// ECMA-262, section 9.4, page 34.
449
function ToInteger(x) {
450
  if (%_IsSmi(x)) return x;
451
  return %NumberToInteger(ToNumber(x));
452
}
453

    
454

    
455
// ECMA-262, section 9.6, page 34.
456
function ToUint32(x) {
457
  if (%_IsSmi(x) && x >= 0) return x;
458
  return %NumberToJSUint32(ToNumber(x));
459
}
460

    
461

    
462
// ECMA-262, section 9.5, page 34
463
function ToInt32(x) {
464
  if (%_IsSmi(x)) return x;
465
  return %NumberToJSInt32(ToNumber(x));
466
}
467

    
468

    
469

    
470
/* ---------------------------------
471
   - - -   U t i l i t i e s   - - -
472
   ---------------------------------
473
*/
474

    
475
// Returns if the given x is a primitive value - not an object or a
476
// function.
477
function IsPrimitive(x) {
478
  if (!IS_OBJECT(x) && !IS_FUNCTION(x)) {
479
    return true;
480
  } else {
481
    // Even though the type of null is "object", null is still
482
    // considered a primitive value.
483
    return IS_NULL(x);
484
  }
485
}
486

    
487

    
488
// ECMA-262, section 8.6.2.6, page 28.
489
function DefaultNumber(x) {
490
  if (IS_FUNCTION(x.valueOf)) {
491
    var v = x.valueOf();
492
    if (%IsPrimitive(v)) return v;
493
  }
494

    
495
  if (IS_FUNCTION(x.toString)) {
496
    var s = x.toString();
497
    if (%IsPrimitive(s)) return s;
498
  }
499

    
500
  throw %MakeTypeError('cannot_convert_to_primitive', []);
501
}
502

    
503

    
504
// ECMA-262, section 8.6.2.6, page 28.
505
function DefaultString(x) {
506
  if (IS_FUNCTION(x.toString)) {
507
    var s = x.toString();
508
    if (%IsPrimitive(s)) return s;
509
  }
510

    
511
  if (IS_FUNCTION(x.valueOf)) {
512
    var v = x.valueOf();
513
    if (%IsPrimitive(v)) return v;
514
  }
515

    
516
  throw %MakeTypeError('cannot_convert_to_primitive', []);
517
}
518

    
519

    
520
// NOTE: Setting the prototype for Array must take place as early as
521
// possible due to code generation for array literals.  When
522
// generating code for a array literal a boilerplate array is created
523
// that is cloned when running the code.  It is essiential that the
524
// boilerplate gets the right prototype.
525
%FunctionSetPrototype($Array, new $Array(0));