| 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 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 function ADD(x) { | 158 function ADD(x) { |
| 159 // Fast case: Check for number operands and do the addition. | 159 // Fast case: Check for number operands and do the addition. |
| 160 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x); | 160 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x); |
| 161 if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x); | 161 if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x); |
| 162 | 162 |
| 163 // Default implementation. | 163 // Default implementation. |
| 164 var a = %to_primitive(this, NO_HINT); | 164 var a = %to_primitive(this, NO_HINT); |
| 165 var b = %to_primitive(x, NO_HINT); | 165 var b = %to_primitive(x, NO_HINT); |
| 166 | 166 |
| 167 if (IS_STRING(a)) { | 167 if (IS_STRING(a)) { |
| 168 return %_StringAdd(a, %to_string_fun(b)); | 168 return %_StringAdd(a, TO_STRING(b)); |
| 169 } else if (IS_STRING(b)) { | 169 } else if (IS_STRING(b)) { |
| 170 return %_StringAdd(%non_string_to_string(a), b); | 170 return %_StringAdd(%non_string_to_string(a), b); |
| 171 } else { | 171 } else { |
| 172 return %NumberAdd(%to_number_fun(a), %to_number_fun(b)); | 172 return %NumberAdd(%to_number_fun(a), %to_number_fun(b)); |
| 173 } | 173 } |
| 174 } | 174 } |
| 175 | 175 |
| 176 | 176 |
| 177 // Strong mode ADD throws if an implicit conversion would be performed | 177 // Strong mode ADD throws if an implicit conversion would be performed |
| 178 function ADD_STRONG(x) { | 178 function ADD_STRONG(x) { |
| 179 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x); | 179 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x); |
| 180 if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x); | 180 if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x); |
| 181 | 181 |
| 182 throw %make_type_error(kStrongImplicitConversion); | 182 throw %make_type_error(kStrongImplicitConversion); |
| 183 } | 183 } |
| 184 | 184 |
| 185 | 185 |
| 186 // Left operand (this) is already a string. | 186 // Left operand (this) is already a string. |
| 187 function STRING_ADD_LEFT(y) { | 187 function STRING_ADD_LEFT(y) { |
| 188 if (!IS_STRING(y)) { | 188 if (!IS_STRING(y)) { |
| 189 if (IS_STRING_WRAPPER(y) && %_IsStringWrapperSafeForDefaultValueOf(y)) { | 189 if (IS_STRING_WRAPPER(y) && %_IsStringWrapperSafeForDefaultValueOf(y)) { |
| 190 y = %_ValueOf(y); | 190 y = %_ValueOf(y); |
| 191 } else { | 191 } else { |
| 192 y = IS_NUMBER(y) | 192 y = IS_NUMBER(y) |
| 193 ? %_NumberToString(y) | 193 ? %_NumberToString(y) |
| 194 : %to_string_fun(%to_primitive(y, NO_HINT)); | 194 : TO_STRING(%to_primitive(y, NO_HINT)); |
| 195 } | 195 } |
| 196 } | 196 } |
| 197 return %_StringAdd(this, y); | 197 return %_StringAdd(this, y); |
| 198 } | 198 } |
| 199 | 199 |
| 200 | 200 |
| 201 // Right operand (y) is already a string. | 201 // Right operand (y) is already a string. |
| 202 function STRING_ADD_RIGHT(y) { | 202 function STRING_ADD_RIGHT(y) { |
| 203 var x = this; | 203 var x = this; |
| 204 if (!IS_STRING(x)) { | 204 if (!IS_STRING(x)) { |
| 205 if (IS_STRING_WRAPPER(x) && %_IsStringWrapperSafeForDefaultValueOf(x)) { | 205 if (IS_STRING_WRAPPER(x) && %_IsStringWrapperSafeForDefaultValueOf(x)) { |
| 206 x = %_ValueOf(x); | 206 x = %_ValueOf(x); |
| 207 } else { | 207 } else { |
| 208 x = IS_NUMBER(x) | 208 x = IS_NUMBER(x) |
| 209 ? %_NumberToString(x) | 209 ? %_NumberToString(x) |
| 210 : %to_string_fun(%to_primitive(x, NO_HINT)); | 210 : TO_STRING(%to_primitive(x, NO_HINT)); |
| 211 } | 211 } |
| 212 } | 212 } |
| 213 return %_StringAdd(x, y); | 213 return %_StringAdd(x, y); |
| 214 } | 214 } |
| 215 | 215 |
| 216 | 216 |
| 217 // ECMA-262, section 11.6.2, page 50. | 217 // ECMA-262, section 11.6.2, page 50. |
| 218 function SUB(y) { | 218 function SUB(y) { |
| 219 var x = IS_NUMBER(this) ? this : %non_number_to_number(this); | 219 var x = IS_NUMBER(this) ? this : %non_number_to_number(this); |
| 220 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | 220 if (!IS_NUMBER(y)) y = %non_number_to_number(y); |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 } | 488 } |
| 489 | 489 |
| 490 length = (args == null) ? 0 : TO_UINT32(args.length); | 490 length = (args == null) ? 0 : TO_UINT32(args.length); |
| 491 | 491 |
| 492 // We can handle any number of apply arguments if the stack is | 492 // We can handle any number of apply arguments if the stack is |
| 493 // big enough, but sanity check the value to avoid overflow when | 493 // big enough, but sanity check the value to avoid overflow when |
| 494 // multiplying with pointer size. | 494 // multiplying with pointer size. |
| 495 if (length > kSafeArgumentsLength) throw %make_range_error(kStackOverflow); | 495 if (length > kSafeArgumentsLength) throw %make_range_error(kStackOverflow); |
| 496 | 496 |
| 497 if (!IS_SPEC_FUNCTION(this)) { | 497 if (!IS_SPEC_FUNCTION(this)) { |
| 498 throw %make_type_error(kApplyNonFunction, %to_string_fun(this), typeof this)
; | 498 throw %make_type_error(kApplyNonFunction, TO_STRING(this), typeof this); |
| 499 } | 499 } |
| 500 | 500 |
| 501 // Make sure the arguments list has the right type. | 501 // Make sure the arguments list has the right type. |
| 502 if (args != null && !IS_SPEC_OBJECT(args)) { | 502 if (args != null && !IS_SPEC_OBJECT(args)) { |
| 503 throw %make_type_error(kWrongArgs, "Function.prototype.apply"); | 503 throw %make_type_error(kWrongArgs, "Function.prototype.apply"); |
| 504 } | 504 } |
| 505 | 505 |
| 506 // Return the length which is the number of arguments to copy to the | 506 // Return the length which is the number of arguments to copy to the |
| 507 // stack. It is guaranteed to be a small integer at this point. | 507 // stack. It is guaranteed to be a small integer at this point. |
| 508 return length; | 508 return length; |
| 509 } | 509 } |
| 510 | 510 |
| 511 | 511 |
| 512 function REFLECT_APPLY_PREPARE(args) { | 512 function REFLECT_APPLY_PREPARE(args) { |
| 513 var length; | 513 var length; |
| 514 // First check whether length is a positive Smi and args is an | 514 // First check whether length is a positive Smi and args is an |
| 515 // array. This is the fast case. If this fails, we do the slow case | 515 // array. This is the fast case. If this fails, we do the slow case |
| 516 // that takes care of more eventualities. | 516 // that takes care of more eventualities. |
| 517 if (IS_ARRAY(args)) { | 517 if (IS_ARRAY(args)) { |
| 518 length = args.length; | 518 length = args.length; |
| 519 if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength && | 519 if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength && |
| 520 IS_SPEC_FUNCTION(this)) { | 520 IS_SPEC_FUNCTION(this)) { |
| 521 return length; | 521 return length; |
| 522 } | 522 } |
| 523 } | 523 } |
| 524 | 524 |
| 525 if (!IS_SPEC_FUNCTION(this)) { | 525 if (!IS_SPEC_FUNCTION(this)) { |
| 526 throw %make_type_error(kCalledNonCallable, %to_string_fun(this)); | 526 throw %make_type_error(kCalledNonCallable, TO_STRING(this)); |
| 527 } | 527 } |
| 528 | 528 |
| 529 if (!IS_SPEC_OBJECT(args)) { | 529 if (!IS_SPEC_OBJECT(args)) { |
| 530 throw %make_type_error(kWrongArgs, "Reflect.apply"); | 530 throw %make_type_error(kWrongArgs, "Reflect.apply"); |
| 531 } | 531 } |
| 532 | 532 |
| 533 length = %to_length_fun(args.length); | 533 length = %to_length_fun(args.length); |
| 534 | 534 |
| 535 // We can handle any number of apply arguments if the stack is | 535 // We can handle any number of apply arguments if the stack is |
| 536 // big enough, but sanity check the value to avoid overflow when | 536 // big enough, but sanity check the value to avoid overflow when |
| (...skipping 18 matching lines...) Expand all Loading... |
| 555 if (IS_ARRAY(args)) { | 555 if (IS_ARRAY(args)) { |
| 556 length = args.length; | 556 length = args.length; |
| 557 if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength && | 557 if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength && |
| 558 ctorOk && newTargetOk) { | 558 ctorOk && newTargetOk) { |
| 559 return length; | 559 return length; |
| 560 } | 560 } |
| 561 } | 561 } |
| 562 | 562 |
| 563 if (!ctorOk) { | 563 if (!ctorOk) { |
| 564 if (!IS_SPEC_FUNCTION(this)) { | 564 if (!IS_SPEC_FUNCTION(this)) { |
| 565 throw %make_type_error(kCalledNonCallable, %to_string_fun(this)); | 565 throw %make_type_error(kCalledNonCallable, TO_STRING(this)); |
| 566 } else { | 566 } else { |
| 567 throw %make_type_error(kNotConstructor, %to_string_fun(this)); | 567 throw %make_type_error(kNotConstructor, TO_STRING(this)); |
| 568 } | 568 } |
| 569 } | 569 } |
| 570 | 570 |
| 571 if (!newTargetOk) { | 571 if (!newTargetOk) { |
| 572 if (!IS_SPEC_FUNCTION(newTarget)) { | 572 if (!IS_SPEC_FUNCTION(newTarget)) { |
| 573 throw %make_type_error(kCalledNonCallable, %to_string_fun(newTarget)); | 573 throw %make_type_error(kCalledNonCallable, TO_STRING(newTarget)); |
| 574 } else { | 574 } else { |
| 575 throw %make_type_error(kNotConstructor, %to_string_fun(newTarget)); | 575 throw %make_type_error(kNotConstructor, TO_STRING(newTarget)); |
| 576 } | 576 } |
| 577 } | 577 } |
| 578 | 578 |
| 579 if (!IS_SPEC_OBJECT(args)) { | 579 if (!IS_SPEC_OBJECT(args)) { |
| 580 throw %make_type_error(kWrongArgs, "Reflect.construct"); | 580 throw %make_type_error(kWrongArgs, "Reflect.construct"); |
| 581 } | 581 } |
| 582 | 582 |
| 583 length = %to_length_fun(args.length); | 583 length = %to_length_fun(args.length); |
| 584 | 584 |
| 585 // We can handle any number of apply arguments if the stack is | 585 // We can handle any number of apply arguments if the stack is |
| (...skipping 16 matching lines...) Expand all Loading... |
| 602 throw %make_range_error(kStackOverflow); | 602 throw %make_range_error(kStackOverflow); |
| 603 } | 603 } |
| 604 | 604 |
| 605 | 605 |
| 606 // Convert the receiver to a number - forward to ToNumber. | 606 // Convert the receiver to a number - forward to ToNumber. |
| 607 function TO_NUMBER() { | 607 function TO_NUMBER() { |
| 608 return %to_number_fun(this); | 608 return %to_number_fun(this); |
| 609 } | 609 } |
| 610 | 610 |
| 611 | 611 |
| 612 // Convert the receiver to a string - forward to ToString. | |
| 613 function TO_STRING() { | |
| 614 return %to_string_fun(this); | |
| 615 } | |
| 616 | |
| 617 | |
| 618 /* ------------------------------------- | 612 /* ------------------------------------- |
| 619 - - - C o n v e r s i o n s - - - | 613 - - - C o n v e r s i o n s - - - |
| 620 ------------------------------------- | 614 ------------------------------------- |
| 621 */ | 615 */ |
| 622 | 616 |
| 623 // ECMA-262, section 9.1, page 30. Use null/undefined for no hint, | 617 // ECMA-262, section 9.1, page 30. Use null/undefined for no hint, |
| 624 // (1) for number hint, and (2) for string hint. | 618 // (1) for number hint, and (2) for string hint. |
| 625 function ToPrimitive(x, hint) { | 619 function ToPrimitive(x, hint) { |
| 626 if (!IS_SPEC_OBJECT(x)) return x; | 620 if (!IS_SPEC_OBJECT(x)) return x; |
| 627 if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT; | 621 if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT; |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 866 ]); | 860 ]); |
| 867 | 861 |
| 868 %InstallToContext([ | 862 %InstallToContext([ |
| 869 "concat_iterable_to_array", ConcatIterableToArray, | 863 "concat_iterable_to_array", ConcatIterableToArray, |
| 870 "non_number_to_number", NonNumberToNumber, | 864 "non_number_to_number", NonNumberToNumber, |
| 871 "non_string_to_string", NonStringToString, | 865 "non_string_to_string", NonStringToString, |
| 872 "to_integer_fun", ToInteger, | 866 "to_integer_fun", ToInteger, |
| 873 "to_length_fun", ToLength, | 867 "to_length_fun", ToLength, |
| 874 "to_number_fun", ToNumber, | 868 "to_number_fun", ToNumber, |
| 875 "to_primitive", ToPrimitive, | 869 "to_primitive", ToPrimitive, |
| 876 "to_string_fun", ToString, | |
| 877 ]); | 870 ]); |
| 878 | 871 |
| 879 utils.Export(function(to) { | 872 utils.Export(function(to) { |
| 880 to.ToBoolean = ToBoolean; | 873 to.ToBoolean = ToBoolean; |
| 881 to.ToLength = ToLength; | 874 to.ToLength = ToLength; |
| 882 to.ToNumber = ToNumber; | 875 to.ToNumber = ToNumber; |
| 883 to.ToPrimitive = ToPrimitive; | 876 to.ToPrimitive = ToPrimitive; |
| 884 to.ToString = ToString; | 877 to.ToString = ToString; |
| 885 }); | 878 }); |
| 886 | 879 |
| 887 }) | 880 }) |
| OLD | NEW |