| 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 |