runtime.js 7.56 KB
Newer Older
1
// Copyright 2006-2008 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4 5 6 7 8

// This files contains runtime support implemented in JavaScript.

// CAUTION: Some of the functions specified in this file are called
// 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
// The following declarations are shared with other native JS files.
// They are all declared at this one spot to avoid redeclaration errors.
14

15
(function(global, utils) {
16 17 18 19 20 21

%CheckIsBootstrapping();

var GlobalArray = global.Array;
var GlobalBoolean = global.Boolean;
var GlobalString = global.String;
22 23
var isConcatSpreadableSymbol =
    utils.ImportNow("is_concat_spreadable_symbol");
24 25 26 27 28
var MakeRangeError;

utils.Import(function(from) {
  MakeRangeError = from.MakeRangeError;
});
29 30

// ----------------------------------------------------------------------------
31 32 33 34 35 36

/* -----------------------------
   - - -   H e l p e r s   - - -
   -----------------------------
*/

37
function APPLY_PREPARE(args) {
38
  var length;
39 40 41

  // First check that the receiver is callable.
  if (!IS_CALLABLE(this)) {
42
    throw %make_type_error(kApplyNonFunction, TO_STRING(this), typeof this);
43 44
  }

45 46 47
  // First check whether length is a positive Smi and args is an
  // array. This is the fast case. If this fails, we do the slow case
  // that takes care of more eventualities.
48
  if (IS_ARRAY(args)) {
49
    length = args.length;
50
    if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength) {
51 52 53 54
      return length;
    }
  }

55
  length = (args == null) ? 0 : TO_UINT32(args.length);
56 57 58 59

  // We can handle any number of apply arguments if the stack is
  // big enough, but sanity check the value to avoid overflow when
  // multiplying with pointer size.
60
  if (length > kSafeArgumentsLength) throw %make_range_error(kStackOverflow);
61 62

  // Make sure the arguments list has the right type.
63
  if (args != null && !IS_SPEC_OBJECT(args)) {
64
    throw %make_type_error(kWrongArgs, "Function.prototype.apply");
65
  }
66

67 68 69
  // Return the length which is the number of arguments to copy to the
  // stack. It is guaranteed to be a small integer at this point.
  return length;
70
}
71 72


73
function REFLECT_APPLY_PREPARE(args) {
74
  var length;
75 76 77

  // First check that the receiver is callable.
  if (!IS_CALLABLE(this)) {
78
    throw %make_type_error(kApplyNonFunction, TO_STRING(this), typeof this);
79 80
  }

81 82 83 84 85
  // First check whether length is a positive Smi and args is an
  // array. This is the fast case. If this fails, we do the slow case
  // that takes care of more eventualities.
  if (IS_ARRAY(args)) {
    length = args.length;
86
    if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength) {
87 88 89 90 91
      return length;
    }
  }

  if (!IS_SPEC_OBJECT(args)) {
92
    throw %make_type_error(kWrongArgs, "Reflect.apply");
93 94
  }

95
  length = TO_LENGTH(args.length);
96 97 98 99

  // We can handle any number of apply arguments if the stack is
  // big enough, but sanity check the value to avoid overflow when
  // multiplying with pointer size.
100
  if (length > kSafeArgumentsLength) throw %make_range_error(kStackOverflow);
101 102 103 104 105 106 107

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


108
function REFLECT_CONSTRUCT_PREPARE(
109
    args, newTarget) {
110
  var length;
111 112
  var ctorOk = IS_CALLABLE(this) && %IsConstructor(this);
  var newTargetOk = IS_CALLABLE(newTarget) && %IsConstructor(newTarget);
113 114 115 116 117 118 119 120 121 122 123 124 125

  // First check whether length is a positive Smi and args is an
  // array. This is the fast case. If this fails, we do the slow case
  // that takes care of more eventualities.
  if (IS_ARRAY(args)) {
    length = args.length;
    if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength &&
        ctorOk && newTargetOk) {
      return length;
    }
  }

  if (!ctorOk) {
126
    if (!IS_CALLABLE(this)) {
127
      throw %make_type_error(kCalledNonCallable, TO_STRING(this));
128
    } else {
129
      throw %make_type_error(kNotConstructor, TO_STRING(this));
130 131 132 133
    }
  }

  if (!newTargetOk) {
134
    if (!IS_CALLABLE(newTarget)) {
135
      throw %make_type_error(kCalledNonCallable, TO_STRING(newTarget));
136
    } else {
137
      throw %make_type_error(kNotConstructor, TO_STRING(newTarget));
138 139 140 141
    }
  }

  if (!IS_SPEC_OBJECT(args)) {
142
    throw %make_type_error(kWrongArgs, "Reflect.construct");
143 144
  }

145
  length = TO_LENGTH(args.length);
146 147 148 149

  // We can handle any number of apply arguments if the stack is
  // big enough, but sanity check the value to avoid overflow when
  // multiplying with pointer size.
150
  if (length > kSafeArgumentsLength) throw %make_range_error(kStackOverflow);
151 152 153 154 155 156 157

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


158
function CONCAT_ITERABLE_TO_ARRAY(iterable) {
159
  return %concat_iterable_to_array(this, iterable);
arv's avatar
arv committed
160 161 162
};


163 164 165 166 167
/* -------------------------------------
   - - -   C o n v e r s i o n s   - - -
   -------------------------------------
*/

168 169 170 171 172
// ES5, section 9.12
function SameValue(x, y) {
  if (typeof x != typeof y) return false;
  if (IS_NUMBER(x)) {
    if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true;
173
    // x is +0 and y is -0 or vice versa.
174 175 176
    if (x === 0 && y === 0 && %_IsMinusZero(x) != %_IsMinusZero(y)) {
      return false;
    }
177
  }
178
  if (IS_SIMD_VALUE(x)) return %SimdSameValue(x, y);
179
  return x === y;
180 181
}

182

d's avatar
d committed
183 184 185 186 187 188
// ES6, section 7.2.4
function SameValueZero(x, y) {
  if (typeof x != typeof y) return false;
  if (IS_NUMBER(x)) {
    if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true;
  }
189
  if (IS_SIMD_VALUE(x)) return %SimdSameValueZero(x, y);
d's avatar
d committed
190 191 192
  return x === y;
}

193

194 195 196
function ConcatIterableToArray(target, iterable) {
   var index = target.length;
   for (var element of iterable) {
197
     %AddElement(target, index++, element);
198 199 200 201
   }
   return target;
}

202 203 204 205 206 207 208

/* ---------------------------------
   - - -   U t i l i t i e s   - - -
   ---------------------------------
*/


209 210 211
// ES6, draft 10-14-14, section 22.1.3.1.1
function IsConcatSpreadable(O) {
  if (!IS_SPEC_OBJECT(O)) return false;
212
  var spreadable = O[isConcatSpreadableSymbol];
213
  if (IS_UNDEFINED(spreadable)) return IS_ARRAY(O);
214
  return TO_BOOLEAN(spreadable);
215 216 217
}


218
function ToPositiveInteger(x, rangeErrorIndex) {
219
  var i = TO_INTEGER_MAP_MINUS_ZERO(x);
220
  if (i < 0) throw MakeRangeError(rangeErrorIndex);
221 222 223
  return i;
}

224 225 226 227 228 229 230 231 232 233 234 235 236 237

function MaxSimple(a, b) {
  return a > b ? a : b;
}


function MinSimple(a, b) {
  return a > b ? b : a;
}


%SetForceInlineFlag(MaxSimple);
%SetForceInlineFlag(MinSimple);

238
//----------------------------------------------------------------------------
239 240 241 242

// NOTE: Setting the prototype for Array must take place as early as
// possible due to code generation for array literals.  When
// generating code for a array literal a boilerplate array is created
243
// that is cloned when running the code.  It is essential that the
244
// boilerplate gets the right prototype.
245 246
%FunctionSetPrototype(GlobalArray, new GlobalArray(0));

247
// ----------------------------------------------------------------------------
248
// Exports
249

250
utils.Export(function(to) {
251 252
  to.MaxSimple = MaxSimple;
  to.MinSimple = MinSimple;
253 254
  to.SameValue = SameValue;
  to.SameValueZero = SameValueZero;
255
  to.ToPositiveInteger = ToPositiveInteger;
256
});
257

258 259 260 261 262 263
%InstallToContext([
  "apply_prepare_builtin", APPLY_PREPARE,
  "concat_iterable_to_array_builtin", CONCAT_ITERABLE_TO_ARRAY,
  "reflect_apply_prepare_builtin", REFLECT_APPLY_PREPARE,
  "reflect_construct_prepare_builtin", REFLECT_CONSTRUCT_PREPARE,
]);
264

265 266 267
%InstallToContext([
  "concat_iterable_to_array", ConcatIterableToArray,
]);
268

269
})