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 |