Chromium Code Reviews| 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 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 358 %HasElement(x, this) : %HasProperty(x, %ToString(this)); | 358 %HasElement(x, this) : %HasProperty(x, %ToString(this)); |
| 359 } | 359 } |
| 360 | 360 |
| 361 | 361 |
| 362 // ECMA-262, section 11.8.6, page 54. To make the implementation more | 362 // ECMA-262, section 11.8.6, page 54. To make the implementation more |
| 363 // efficient, the return value should be zero if the 'this' is an | 363 // efficient, the return value should be zero if the 'this' is an |
| 364 // instance of F, and non-zero if not. This makes it possible to avoid | 364 // instance of F, and non-zero if not. This makes it possible to avoid |
| 365 // an expensive ToBoolean conversion in the generated code. | 365 // an expensive ToBoolean conversion in the generated code. |
| 366 function INSTANCE_OF(F) { | 366 function INSTANCE_OF(F) { |
| 367 var V = this; | 367 var V = this; |
| 368 if (!IS_FUNCTION(F)) { | 368 if (!IS_SPEC_FUNCTION(F)) { |
| 369 throw %MakeTypeError('instanceof_function_expected', [V]); | 369 throw %MakeTypeError('instanceof_function_expected', [V]); |
| 370 } | 370 } |
| 371 | 371 |
| 372 // If V is not an object, return false. | 372 // If V is not an object, return false. |
| 373 if (!IS_SPEC_OBJECT(V)) { | 373 if (!IS_SPEC_OBJECT(V)) { |
| 374 return 1; | 374 return 1; |
| 375 } | 375 } |
| 376 | 376 |
| 377 // Get the prototype of F; if it is not an object, throw an error. | 377 // Get the prototype of F; if it is not an object, throw an error. |
| 378 var O = F.prototype; | 378 var O = F.prototype; |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 398 function FILTER_KEY(key) { | 398 function FILTER_KEY(key) { |
| 399 var string = %ToString(key); | 399 var string = %ToString(key); |
| 400 if (%HasProperty(this, string)) return string; | 400 if (%HasProperty(this, string)) return string; |
| 401 return 0; | 401 return 0; |
| 402 } | 402 } |
| 403 | 403 |
| 404 | 404 |
| 405 function CALL_NON_FUNCTION() { | 405 function CALL_NON_FUNCTION() { |
| 406 var delegate = %GetFunctionDelegate(this); | 406 var delegate = %GetFunctionDelegate(this); |
| 407 if (!IS_FUNCTION(delegate)) { | 407 if (!IS_FUNCTION(delegate)) { |
| 408 throw %MakeTypeError('called_non_callable', [typeof this]); | 408 if (%IsJSFunctionProxy(this)) { |
|
Kevin Millikin (Chromium)
2011/09/08 17:30:40
Can we get into this case, where CALL_NON_FUNCTION
rossberg
2011/09/09 17:05:30
Done (subsuming part of change 7849021).
| |
| 409 delegate = %GetCallTrap(this); | |
| 410 } else { | |
| 411 throw %MakeTypeError('called_non_callable', [typeof this]); | |
| 412 } | |
| 409 } | 413 } |
| 410 return delegate.apply(this, arguments); | 414 return delegate.apply(this, arguments); |
| 411 } | 415 } |
| 412 | 416 |
| 413 | 417 |
| 414 function CALL_NON_FUNCTION_AS_CONSTRUCTOR() { | 418 function CALL_NON_FUNCTION_AS_CONSTRUCTOR() { |
| 415 var delegate = %GetConstructorDelegate(this); | 419 var delegate = %GetConstructorDelegate(this); |
| 416 if (!IS_FUNCTION(delegate)) { | 420 if (!IS_FUNCTION(delegate)) { |
| 417 throw %MakeTypeError('called_non_callable', [typeof this]); | 421 if (%IsJSFunctionProxy(this)) { |
| 422 delegate = %GetConstructTrap(this); | |
| 423 } else { | |
| 424 throw %MakeTypeError('called_non_callable', [typeof this]); | |
| 425 } | |
| 418 } | 426 } |
| 419 return delegate.apply(this, arguments); | 427 return delegate.apply(this, arguments); |
| 420 } | 428 } |
| 421 | 429 |
| 422 | 430 |
| 431 function CALL_FUNCTION_PROXY() { | |
| 432 var arity = %_ArgumentsLength() - 1; | |
| 433 var proxy = arguments[arity]; // The proxy comes in as an additional arg. | |
|
Kevin Millikin (Chromium)
2011/09/08 17:30:40
You can also use %_Arguments(arity) to get the arg
rossberg
2011/09/09 17:05:30
Done (although we have to materialize the argument
| |
| 434 var trap = %GetCallTrap(proxy); | |
| 435 // TODO(rossberg): hm, shouldn't I be using $Function and friends? | |
| 436 // But how do I get it in a builtin? | |
| 437 return global.Function.prototype.apply.call( | |
|
Kevin Millikin (Chromium)
2011/09/08 17:30:40
You can't, the JS builtins are called with the con
rossberg
2011/09/09 17:05:30
I implemented an %Apply native.
| |
| 438 trap, this, global.Array.prototype.slice.call(arguments, 0, arity)); | |
| 439 } | |
| 440 | |
| 441 | |
| 442 function CALL_FUNCTION_PROXY_AS_CONSTRUCTOR(proxy) { | |
| 443 var trap = %GetConstructTrap(proxy); | |
| 444 var receiver = void 0; | |
| 445 if (!IS_UNDEFINED(trap)) { | |
| 446 trap = %GetCallTrap(proxy); | |
| 447 var proto = proxy.prototype; | |
| 448 if (!IS_SPEC_OBJECT(proto) && proto !== null) { | |
| 449 throw MakeTypeError("proto_object_or_null", [proto]); | |
| 450 } | |
| 451 receiver = new global.Object(); | |
| 452 receiver.__proto__ = proto; | |
| 453 } | |
| 454 return global.Function.prototype.apply.call( | |
| 455 trap, this, global.Array.prototype.shift.call(arguments)); | |
| 456 } | |
| 457 | |
| 458 | |
| 423 function APPLY_PREPARE(args) { | 459 function APPLY_PREPARE(args) { |
| 424 var length; | 460 var length; |
| 425 // First check whether length is a positive Smi and args is an | 461 // First check whether length is a positive Smi and args is an |
| 426 // array. This is the fast case. If this fails, we do the slow case | 462 // array. This is the fast case. If this fails, we do the slow case |
| 427 // that takes care of more eventualities. | 463 // that takes care of more eventualities. |
| 428 if (IS_ARRAY(args)) { | 464 if (IS_ARRAY(args)) { |
| 429 length = args.length; | 465 length = args.length; |
| 430 if (%_IsSmi(length) && length >= 0 && length < 0x800000 && IS_FUNCTION(this) ) { | 466 if (%_IsSmi(length) && length >= 0 && length < 0x800000 && |
| 467 IS_SPEC_FUNCTION(this)) { | |
| 431 return length; | 468 return length; |
| 432 } | 469 } |
| 433 } | 470 } |
| 434 | 471 |
| 435 length = (args == null) ? 0 : %ToUint32(args.length); | 472 length = (args == null) ? 0 : %ToUint32(args.length); |
| 436 | 473 |
| 437 // We can handle any number of apply arguments if the stack is | 474 // We can handle any number of apply arguments if the stack is |
| 438 // big enough, but sanity check the value to avoid overflow when | 475 // big enough, but sanity check the value to avoid overflow when |
| 439 // multiplying with pointer size. | 476 // multiplying with pointer size. |
| 440 if (length > 0x800000) { | 477 if (length > 0x800000) { |
| 441 throw %MakeRangeError('stack_overflow', []); | 478 throw %MakeRangeError('stack_overflow', []); |
| 442 } | 479 } |
| 443 | 480 |
| 444 if (!IS_FUNCTION(this)) { | 481 if (!IS_SPEC_FUNCTION(this)) { |
| 445 throw %MakeTypeError('apply_non_function', [ %ToString(this), typeof this ]) ; | 482 throw %MakeTypeError('apply_non_function', [ %ToString(this), typeof this ]) ; |
| 446 } | 483 } |
| 447 | 484 |
| 448 // Make sure the arguments list has the right type. | 485 // Make sure the arguments list has the right type. |
| 449 if (args != null && !IS_ARRAY(args) && !IS_ARGUMENTS(args)) { | 486 if (args != null && !IS_ARRAY(args) && !IS_ARGUMENTS(args)) { |
| 450 throw %MakeTypeError('apply_wrong_args', []); | 487 throw %MakeTypeError('apply_wrong_args', []); |
| 451 } | 488 } |
| 452 | 489 |
| 453 // Return the length which is the number of arguments to copy to the | 490 // Return the length which is the number of arguments to copy to the |
| 454 // stack. It is guaranteed to be a small integer at this point. | 491 // stack. It is guaranteed to be a small integer at this point. |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 602 // Even though the type of null is "object", null is still | 639 // Even though the type of null is "object", null is still |
| 603 // considered a primitive value. IS_SPEC_OBJECT handles this correctly | 640 // considered a primitive value. IS_SPEC_OBJECT handles this correctly |
| 604 // (i.e., it will return false if x is null). | 641 // (i.e., it will return false if x is null). |
| 605 return !IS_SPEC_OBJECT(x); | 642 return !IS_SPEC_OBJECT(x); |
| 606 } | 643 } |
| 607 | 644 |
| 608 | 645 |
| 609 // ECMA-262, section 8.6.2.6, page 28. | 646 // ECMA-262, section 8.6.2.6, page 28. |
| 610 function DefaultNumber(x) { | 647 function DefaultNumber(x) { |
| 611 var valueOf = x.valueOf; | 648 var valueOf = x.valueOf; |
| 612 if (IS_FUNCTION(valueOf)) { | 649 if (IS_SPEC_FUNCTION(valueOf)) { |
| 613 var v = %_CallFunction(x, valueOf); | 650 var v = %_CallFunction(x, valueOf); |
| 614 if (%IsPrimitive(v)) return v; | 651 if (%IsPrimitive(v)) return v; |
| 615 } | 652 } |
| 616 | 653 |
| 617 var toString = x.toString; | 654 var toString = x.toString; |
| 618 if (IS_FUNCTION(toString)) { | 655 if (IS_SPEC_FUNCTION(toString)) { |
| 619 var s = %_CallFunction(x, toString); | 656 var s = %_CallFunction(x, toString); |
| 620 if (%IsPrimitive(s)) return s; | 657 if (%IsPrimitive(s)) return s; |
| 621 } | 658 } |
| 622 | 659 |
| 623 throw %MakeTypeError('cannot_convert_to_primitive', []); | 660 throw %MakeTypeError('cannot_convert_to_primitive', []); |
| 624 } | 661 } |
| 625 | 662 |
| 626 | 663 |
| 627 // ECMA-262, section 8.6.2.6, page 28. | 664 // ECMA-262, section 8.6.2.6, page 28. |
| 628 function DefaultString(x) { | 665 function DefaultString(x) { |
| 629 var toString = x.toString; | 666 var toString = x.toString; |
| 630 if (IS_FUNCTION(toString)) { | 667 if (IS_SPEC_FUNCTION(toString)) { |
| 631 var s = %_CallFunction(x, toString); | 668 var s = %_CallFunction(x, toString); |
| 632 if (%IsPrimitive(s)) return s; | 669 if (%IsPrimitive(s)) return s; |
| 633 } | 670 } |
| 634 | 671 |
| 635 var valueOf = x.valueOf; | 672 var valueOf = x.valueOf; |
| 636 if (IS_FUNCTION(valueOf)) { | 673 if (IS_SPEC_FUNCTION(valueOf)) { |
| 637 var v = %_CallFunction(x, valueOf); | 674 var v = %_CallFunction(x, valueOf); |
| 638 if (%IsPrimitive(v)) return v; | 675 if (%IsPrimitive(v)) return v; |
| 639 } | 676 } |
| 640 | 677 |
| 641 throw %MakeTypeError('cannot_convert_to_primitive', []); | 678 throw %MakeTypeError('cannot_convert_to_primitive', []); |
| 642 } | 679 } |
| 643 | 680 |
| 644 | 681 |
| 645 // NOTE: Setting the prototype for Array must take place as early as | 682 // NOTE: Setting the prototype for Array must take place as early as |
| 646 // possible due to code generation for array literals. When | 683 // possible due to code generation for array literals. When |
| 647 // generating code for a array literal a boilerplate array is created | 684 // generating code for a array literal a boilerplate array is created |
| 648 // that is cloned when running the code. It is essential that the | 685 // that is cloned when running the code. It is essential that the |
| 649 // boilerplate gets the right prototype. | 686 // boilerplate gets the right prototype. |
| 650 %FunctionSetPrototype($Array, new $Array(0)); | 687 %FunctionSetPrototype($Array, new $Array(0)); |
| OLD | NEW |