| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // This files contains runtime support implemented in JavaScript. | 5 // This files contains runtime support implemented in JavaScript. |
| 6 | 6 |
| 7 // CAUTION: Some of the functions specified in this file are called | 7 // CAUTION: Some of the functions specified in this file are called |
| 8 // directly from compiled code. These are the functions with names in | 8 // directly from compiled code. These are the functions with names in |
| 9 // ALL CAPS. The compiled code passes the first argument in 'this'. | 9 // ALL CAPS. The compiled code passes the first argument in 'this'. |
| 10 | 10 |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 149 throw %make_type_error(kStrongImplicitConversion); | 149 throw %make_type_error(kStrongImplicitConversion); |
| 150 } | 150 } |
| 151 | 151 |
| 152 | 152 |
| 153 | 153 |
| 154 /* ----------------------------------- | 154 /* ----------------------------------- |
| 155 - - - A r i t h m e t i c - - - | 155 - - - A r i t h m e t i c - - - |
| 156 ----------------------------------- | 156 ----------------------------------- |
| 157 */ | 157 */ |
| 158 | 158 |
| 159 // ECMA-262, section 11.6.1, page 50. | |
| 160 function ADD(x) { | |
| 161 // Fast case: Check for number operands and do the addition. | |
| 162 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x); | |
| 163 if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x); | |
| 164 | |
| 165 // Default implementation. | |
| 166 var a = %to_primitive(this, NO_HINT); | |
| 167 var b = %to_primitive(x, NO_HINT); | |
| 168 | |
| 169 if (IS_STRING(a)) { | |
| 170 return %_StringAdd(a, %to_string_fun(b)); | |
| 171 } else if (IS_STRING(b)) { | |
| 172 return %_StringAdd(%non_string_to_string(a), b); | |
| 173 } else { | |
| 174 return %NumberAdd(%to_number_fun(a), %to_number_fun(b)); | |
| 175 } | |
| 176 } | |
| 177 | |
| 178 | |
| 179 // Strong mode ADD throws if an implicit conversion would be performed | |
| 180 function ADD_STRONG(x) { | |
| 181 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x); | |
| 182 if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x); | |
| 183 | |
| 184 throw %make_type_error(kStrongImplicitConversion); | |
| 185 } | |
| 186 | |
| 187 | |
| 188 // Left operand (this) is already a string. | 159 // Left operand (this) is already a string. |
| 189 function STRING_ADD_LEFT(y) { | 160 function STRING_ADD_LEFT(y) { |
| 190 if (!IS_STRING(y)) { | 161 if (!IS_STRING(y)) { |
| 191 if (IS_STRING_WRAPPER(y) && %_IsStringWrapperSafeForDefaultValueOf(y)) { | 162 if (IS_STRING_WRAPPER(y) && %_IsStringWrapperSafeForDefaultValueOf(y)) { |
| 192 y = %_ValueOf(y); | 163 y = %_ValueOf(y); |
| 193 } else { | 164 } else { |
| 194 y = IS_NUMBER(y) | 165 y = IS_NUMBER(y) |
| 195 ? %_NumberToString(y) | 166 ? %_NumberToString(y) |
| 196 : %to_string_fun(%to_primitive(y, NO_HINT)); | 167 : %to_string_fun(%to_primitive(y, NO_HINT)); |
| 197 } | 168 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 209 } else { | 180 } else { |
| 210 x = IS_NUMBER(x) | 181 x = IS_NUMBER(x) |
| 211 ? %_NumberToString(x) | 182 ? %_NumberToString(x) |
| 212 : %to_string_fun(%to_primitive(x, NO_HINT)); | 183 : %to_string_fun(%to_primitive(x, NO_HINT)); |
| 213 } | 184 } |
| 214 } | 185 } |
| 215 return %_StringAdd(x, y); | 186 return %_StringAdd(x, y); |
| 216 } | 187 } |
| 217 | 188 |
| 218 | 189 |
| 219 // ECMA-262, section 11.6.2, page 50. | |
| 220 function SUB(y) { | |
| 221 var x = IS_NUMBER(this) ? this : %non_number_to_number(this); | |
| 222 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
| 223 return %NumberSub(x, y); | |
| 224 } | |
| 225 | |
| 226 | |
| 227 // Strong mode SUB throws if an implicit conversion would be performed | |
| 228 function SUB_STRONG(y) { | |
| 229 if (IS_NUMBER(this) && IS_NUMBER(y)) { | |
| 230 return %NumberSub(this, y); | |
| 231 } | |
| 232 throw %make_type_error(kStrongImplicitConversion); | |
| 233 } | |
| 234 | |
| 235 | |
| 236 // ECMA-262, section 11.5.1, page 48. | |
| 237 function MUL(y) { | |
| 238 var x = IS_NUMBER(this) ? this : %non_number_to_number(this); | |
| 239 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
| 240 return %NumberMul(x, y); | |
| 241 } | |
| 242 | |
| 243 | |
| 244 // Strong mode MUL throws if an implicit conversion would be performed | |
| 245 function MUL_STRONG(y) { | |
| 246 if (IS_NUMBER(this) && IS_NUMBER(y)) { | |
| 247 return %NumberMul(this, y); | |
| 248 } | |
| 249 throw %make_type_error(kStrongImplicitConversion); | |
| 250 } | |
| 251 | |
| 252 | |
| 253 // ECMA-262, section 11.5.2, page 49. | |
| 254 function DIV(y) { | |
| 255 var x = IS_NUMBER(this) ? this : %non_number_to_number(this); | |
| 256 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
| 257 return %NumberDiv(x, y); | |
| 258 } | |
| 259 | |
| 260 | |
| 261 // Strong mode DIV throws if an implicit conversion would be performed | |
| 262 function DIV_STRONG(y) { | |
| 263 if (IS_NUMBER(this) && IS_NUMBER(y)) { | |
| 264 return %NumberDiv(this, y); | |
| 265 } | |
| 266 throw %make_type_error(kStrongImplicitConversion); | |
| 267 } | |
| 268 | |
| 269 | |
| 270 // ECMA-262, section 11.5.3, page 49. | |
| 271 function MOD(y) { | |
| 272 var x = IS_NUMBER(this) ? this : %non_number_to_number(this); | |
| 273 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
| 274 return %NumberMod(x, y); | |
| 275 } | |
| 276 | |
| 277 | |
| 278 // Strong mode MOD throws if an implicit conversion would be performed | |
| 279 function MOD_STRONG(y) { | |
| 280 if (IS_NUMBER(this) && IS_NUMBER(y)) { | |
| 281 return %NumberMod(this, y); | |
| 282 } | |
| 283 throw %make_type_error(kStrongImplicitConversion); | |
| 284 } | |
| 285 | |
| 286 | |
| 287 /* ------------------------------------------- | |
| 288 - - - B i t o p e r a t i o n s - - - | |
| 289 ------------------------------------------- | |
| 290 */ | |
| 291 | |
| 292 // ECMA-262, section 11.10, page 57. | |
| 293 function BIT_OR(y) { | |
| 294 var x = IS_NUMBER(this) ? this : %non_number_to_number(this); | |
| 295 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
| 296 return %NumberOr(x, y); | |
| 297 } | |
| 298 | |
| 299 | |
| 300 // Strong mode BIT_OR throws if an implicit conversion would be performed | |
| 301 function BIT_OR_STRONG(y) { | |
| 302 if (IS_NUMBER(this) && IS_NUMBER(y)) { | |
| 303 return %NumberOr(this, y); | |
| 304 } | |
| 305 throw %make_type_error(kStrongImplicitConversion); | |
| 306 } | |
| 307 | |
| 308 | |
| 309 // ECMA-262, section 11.10, page 57. | |
| 310 function BIT_AND(y) { | |
| 311 var x; | |
| 312 if (IS_NUMBER(this)) { | |
| 313 x = this; | |
| 314 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
| 315 } else { | |
| 316 x = %non_number_to_number(this); | |
| 317 // Make sure to convert the right operand to a number before | |
| 318 // bailing out in the fast case, but after converting the | |
| 319 // left operand. This ensures that valueOf methods on the right | |
| 320 // operand are always executed. | |
| 321 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
| 322 // Optimize for the case where we end up AND'ing a value | |
| 323 // that doesn't convert to a number. This is common in | |
| 324 // certain benchmarks. | |
| 325 if (NUMBER_IS_NAN(x)) return 0; | |
| 326 } | |
| 327 return %NumberAnd(x, y); | |
| 328 } | |
| 329 | |
| 330 | |
| 331 // Strong mode BIT_AND throws if an implicit conversion would be performed | |
| 332 function BIT_AND_STRONG(y) { | |
| 333 if (IS_NUMBER(this) && IS_NUMBER(y)) { | |
| 334 return %NumberAnd(this, y); | |
| 335 } | |
| 336 throw %make_type_error(kStrongImplicitConversion); | |
| 337 } | |
| 338 | |
| 339 | |
| 340 // ECMA-262, section 11.10, page 57. | |
| 341 function BIT_XOR(y) { | |
| 342 var x = IS_NUMBER(this) ? this : %non_number_to_number(this); | |
| 343 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
| 344 return %NumberXor(x, y); | |
| 345 } | |
| 346 | |
| 347 | |
| 348 // Strong mode BIT_XOR throws if an implicit conversion would be performed | |
| 349 function BIT_XOR_STRONG(y) { | |
| 350 if (IS_NUMBER(this) && IS_NUMBER(y)) { | |
| 351 return %NumberXor(this, y); | |
| 352 } | |
| 353 throw %make_type_error(kStrongImplicitConversion); | |
| 354 } | |
| 355 | |
| 356 | |
| 357 // ECMA-262, section 11.7.1, page 51. | |
| 358 function SHL(y) { | |
| 359 var x = IS_NUMBER(this) ? this : %non_number_to_number(this); | |
| 360 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
| 361 return %NumberShl(x, y); | |
| 362 } | |
| 363 | |
| 364 | |
| 365 // Strong mode SHL throws if an implicit conversion would be performed | |
| 366 function SHL_STRONG(y) { | |
| 367 if (IS_NUMBER(this) && IS_NUMBER(y)) { | |
| 368 return %NumberShl(this, y); | |
| 369 } | |
| 370 throw %make_type_error(kStrongImplicitConversion); | |
| 371 } | |
| 372 | |
| 373 | |
| 374 // ECMA-262, section 11.7.2, page 51. | |
| 375 function SAR(y) { | |
| 376 var x; | |
| 377 if (IS_NUMBER(this)) { | |
| 378 x = this; | |
| 379 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
| 380 } else { | |
| 381 x = %non_number_to_number(this); | |
| 382 // Make sure to convert the right operand to a number before | |
| 383 // bailing out in the fast case, but after converting the | |
| 384 // left operand. This ensures that valueOf methods on the right | |
| 385 // operand are always executed. | |
| 386 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
| 387 // Optimize for the case where we end up shifting a value | |
| 388 // that doesn't convert to a number. This is common in | |
| 389 // certain benchmarks. | |
| 390 if (NUMBER_IS_NAN(x)) return 0; | |
| 391 } | |
| 392 return %NumberSar(x, y); | |
| 393 } | |
| 394 | |
| 395 | |
| 396 // Strong mode SAR throws if an implicit conversion would be performed | |
| 397 function SAR_STRONG(y) { | |
| 398 if (IS_NUMBER(this) && IS_NUMBER(y)) { | |
| 399 return %NumberSar(this, y); | |
| 400 } | |
| 401 throw %make_type_error(kStrongImplicitConversion); | |
| 402 } | |
| 403 | |
| 404 | |
| 405 // ECMA-262, section 11.7.3, page 52. | |
| 406 function SHR(y) { | |
| 407 var x = IS_NUMBER(this) ? this : %non_number_to_number(this); | |
| 408 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | |
| 409 return %NumberShr(x, y); | |
| 410 } | |
| 411 | |
| 412 | |
| 413 // Strong mode SHR throws if an implicit conversion would be performed | |
| 414 function SHR_STRONG(y) { | |
| 415 if (IS_NUMBER(this) && IS_NUMBER(y)) { | |
| 416 return %NumberShr(this, y); | |
| 417 } | |
| 418 throw %make_type_error(kStrongImplicitConversion); | |
| 419 } | |
| 420 | |
| 421 | |
| 422 /* ----------------------------- | 190 /* ----------------------------- |
| 423 - - - H e l p e r s - - - | 191 - - - H e l p e r s - - - |
| 424 ----------------------------- | 192 ----------------------------- |
| 425 */ | 193 */ |
| 426 | 194 |
| 427 function CALL_NON_FUNCTION_AS_CONSTRUCTOR() { | 195 function CALL_NON_FUNCTION_AS_CONSTRUCTOR() { |
| 428 var delegate = %GetConstructorDelegate(this); | 196 var delegate = %GetConstructorDelegate(this); |
| 429 return %Apply(delegate, this, arguments, 0, %_ArgumentsLength()); | 197 return %Apply(delegate, this, arguments, 0, %_ArgumentsLength()); |
| 430 } | 198 } |
| 431 | 199 |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 774 $sameValue = SameValue; | 542 $sameValue = SameValue; |
| 775 $sameValueZero = SameValueZero; | 543 $sameValueZero = SameValueZero; |
| 776 $toInteger = ToInteger; | 544 $toInteger = ToInteger; |
| 777 $toLength = ToLength; | 545 $toLength = ToLength; |
| 778 $toNumber = ToNumber; | 546 $toNumber = ToNumber; |
| 779 $toPositiveInteger = ToPositiveInteger; | 547 $toPositiveInteger = ToPositiveInteger; |
| 780 $toPrimitive = ToPrimitive; | 548 $toPrimitive = ToPrimitive; |
| 781 $toString = ToString; | 549 $toString = ToString; |
| 782 | 550 |
| 783 %InstallToContext([ | 551 %InstallToContext([ |
| 784 "add_builtin", ADD, | |
| 785 "add_strong_builtin", ADD_STRONG, | |
| 786 "apply_prepare_builtin", APPLY_PREPARE, | 552 "apply_prepare_builtin", APPLY_PREPARE, |
| 787 "bit_and_builtin", BIT_AND, | |
| 788 "bit_and_strong_builtin", BIT_AND_STRONG, | |
| 789 "bit_or_builtin", BIT_OR, | |
| 790 "bit_or_strong_builtin", BIT_OR_STRONG, | |
| 791 "bit_xor_builtin", BIT_XOR, | |
| 792 "bit_xor_strong_builtin", BIT_XOR_STRONG, | |
| 793 "call_function_proxy_as_constructor_builtin", CALL_FUNCTION_PROXY_AS_CONSTRUCT
OR, | 553 "call_function_proxy_as_constructor_builtin", CALL_FUNCTION_PROXY_AS_CONSTRUCT
OR, |
| 794 "call_non_function_as_constructor_builtin", CALL_NON_FUNCTION_AS_CONSTRUCTOR, | 554 "call_non_function_as_constructor_builtin", CALL_NON_FUNCTION_AS_CONSTRUCTOR, |
| 795 "compare_builtin", COMPARE, | 555 "compare_builtin", COMPARE, |
| 796 "compare_strong_builtin", COMPARE_STRONG, | 556 "compare_strong_builtin", COMPARE_STRONG, |
| 797 "concat_iterable_to_array_builtin", CONCAT_ITERABLE_TO_ARRAY, | 557 "concat_iterable_to_array_builtin", CONCAT_ITERABLE_TO_ARRAY, |
| 798 "div_builtin", DIV, | |
| 799 "div_strong_builtin", DIV_STRONG, | |
| 800 "equals_builtin", EQUALS, | 558 "equals_builtin", EQUALS, |
| 801 "mod_builtin", MOD, | |
| 802 "mod_strong_builtin", MOD_STRONG, | |
| 803 "mul_builtin", MUL, | |
| 804 "mul_strong_builtin", MUL_STRONG, | |
| 805 "reflect_apply_prepare_builtin", REFLECT_APPLY_PREPARE, | 559 "reflect_apply_prepare_builtin", REFLECT_APPLY_PREPARE, |
| 806 "reflect_construct_prepare_builtin", REFLECT_CONSTRUCT_PREPARE, | 560 "reflect_construct_prepare_builtin", REFLECT_CONSTRUCT_PREPARE, |
| 807 "sar_builtin", SAR, | |
| 808 "sar_strong_builtin", SAR_STRONG, | |
| 809 "shl_builtin", SHL, | |
| 810 "shl_strong_builtin", SHL_STRONG, | |
| 811 "shr_builtin", SHR, | |
| 812 "shr_strong_builtin", SHR_STRONG, | |
| 813 "stack_overflow_builtin", STACK_OVERFLOW, | 561 "stack_overflow_builtin", STACK_OVERFLOW, |
| 814 "string_add_left_builtin", STRING_ADD_LEFT, | 562 "string_add_left_builtin", STRING_ADD_LEFT, |
| 815 "string_add_right_builtin", STRING_ADD_RIGHT, | 563 "string_add_right_builtin", STRING_ADD_RIGHT, |
| 816 "sub_builtin", SUB, | |
| 817 "sub_strong_builtin", SUB_STRONG, | |
| 818 ]); | 564 ]); |
| 819 | 565 |
| 820 %InstallToContext([ | 566 %InstallToContext([ |
| 821 "concat_iterable_to_array", ConcatIterableToArray, | 567 "concat_iterable_to_array", ConcatIterableToArray, |
| 822 "non_number_to_number", NonNumberToNumber, | 568 "non_number_to_number", NonNumberToNumber, |
| 823 "non_string_to_string", NonStringToString, | 569 "non_string_to_string", NonStringToString, |
| 824 "to_integer_fun", ToInteger, | 570 "to_integer_fun", ToInteger, |
| 825 "to_length_fun", ToLength, | 571 "to_length_fun", ToLength, |
| 826 "to_number_fun", ToNumber, | 572 "to_number_fun", ToNumber, |
| 827 "to_primitive", ToPrimitive, | 573 "to_primitive", ToPrimitive, |
| 828 "to_string_fun", ToString, | 574 "to_string_fun", ToString, |
| 829 ]); | 575 ]); |
| 830 | 576 |
| 831 utils.Export(function(to) { | 577 utils.Export(function(to) { |
| 832 to.ToBoolean = ToBoolean; | 578 to.ToBoolean = ToBoolean; |
| 833 to.ToLength = ToLength; | 579 to.ToLength = ToLength; |
| 834 to.ToNumber = ToNumber; | 580 to.ToNumber = ToNumber; |
| 835 to.ToPrimitive = ToPrimitive; | 581 to.ToPrimitive = ToPrimitive; |
| 836 to.ToString = ToString; | 582 to.ToString = ToString; |
| 837 }); | 583 }); |
| 838 | 584 |
| 839 }) | 585 }) |
| OLD | NEW |