| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 592 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 603 | 603 |
| 604 // 2. Get the function to call (passed as receiver) from the stack, check | 604 // 2. Get the function to call (passed as receiver) from the stack, check |
| 605 // if it is a function. | 605 // if it is a function. |
| 606 Label non_function; | 606 Label non_function; |
| 607 // The function to call is at position n+1 on the stack. | 607 // The function to call is at position n+1 on the stack. |
| 608 __ movq(rdi, Operand(rsp, rax, times_pointer_size, 1 * kPointerSize)); | 608 __ movq(rdi, Operand(rsp, rax, times_pointer_size, 1 * kPointerSize)); |
| 609 __ JumpIfSmi(rdi, &non_function); | 609 __ JumpIfSmi(rdi, &non_function); |
| 610 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 610 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
| 611 __ j(not_equal, &non_function); | 611 __ j(not_equal, &non_function); |
| 612 | 612 |
| 613 // 3a. Patch the first argument if necessary when calling a function. | 613 // Change context eagerly in case we need the global receiver. |
| 614 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 615 |
| 614 Label shift_arguments; | 616 Label shift_arguments; |
| 615 { Label convert_to_object, use_global_receiver, patch_receiver; | 617 __ jmp(&shift_arguments); |
| 616 // Change context eagerly in case we need the global receiver. | |
| 617 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | |
| 618 | 618 |
| 619 __ movq(rbx, Operand(rsp, rax, times_pointer_size, 0)); | 619 // 3. Patch the first argument when calling a non-function. The |
| 620 __ JumpIfSmi(rbx, &convert_to_object); | 620 // CALL_NON_FUNCTION builtin expects the non-function callee as |
| 621 | 621 // receiver, so overwrite the first argument which will ultimately |
| 622 __ CompareRoot(rbx, Heap::kNullValueRootIndex); | 622 // become the receiver. |
| 623 __ j(equal, &use_global_receiver); | |
| 624 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); | |
| 625 __ j(equal, &use_global_receiver); | |
| 626 | |
| 627 __ CmpObjectType(rbx, FIRST_JS_OBJECT_TYPE, rcx); | |
| 628 __ j(below, &convert_to_object); | |
| 629 __ CmpInstanceType(rcx, LAST_JS_OBJECT_TYPE); | |
| 630 __ j(below_equal, &shift_arguments); | |
| 631 | |
| 632 __ bind(&convert_to_object); | |
| 633 __ EnterInternalFrame(); // In order to preserve argument count. | |
| 634 __ Integer32ToSmi(rax, rax); | |
| 635 __ push(rax); | |
| 636 | |
| 637 __ push(rbx); | |
| 638 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | |
| 639 __ movq(rbx, rax); | |
| 640 | |
| 641 __ pop(rax); | |
| 642 __ SmiToInteger32(rax, rax); | |
| 643 __ LeaveInternalFrame(); | |
| 644 // Restore the function to rdi. | |
| 645 __ movq(rdi, Operand(rsp, rax, times_pointer_size, 1 * kPointerSize)); | |
| 646 __ jmp(&patch_receiver); | |
| 647 | |
| 648 // Use the global receiver object from the called function as the | |
| 649 // receiver. | |
| 650 __ bind(&use_global_receiver); | |
| 651 const int kGlobalIndex = | |
| 652 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; | |
| 653 __ movq(rbx, FieldOperand(rsi, kGlobalIndex)); | |
| 654 __ movq(rbx, FieldOperand(rbx, GlobalObject::kGlobalContextOffset)); | |
| 655 __ movq(rbx, FieldOperand(rbx, kGlobalIndex)); | |
| 656 __ movq(rbx, FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); | |
| 657 | |
| 658 __ bind(&patch_receiver); | |
| 659 __ movq(Operand(rsp, rax, times_pointer_size, 0), rbx); | |
| 660 | |
| 661 __ jmp(&shift_arguments); | |
| 662 } | |
| 663 | |
| 664 | |
| 665 // 3b. Patch the first argument when calling a non-function. The | |
| 666 // CALL_NON_FUNCTION builtin expects the non-function callee as | |
| 667 // receiver, so overwrite the first argument which will ultimately | |
| 668 // become the receiver. | |
| 669 __ bind(&non_function); | 623 __ bind(&non_function); |
| 670 __ movq(Operand(rsp, rax, times_pointer_size, 0), rdi); | 624 __ movq(Operand(rsp, rax, times_pointer_size, 0), rdi); |
| 671 __ Set(rdi, 0); | 625 __ Set(rdi, 0); |
| 672 | 626 |
| 673 // 4. Shift arguments and return address one slot down on the stack | 627 // 4. Shift arguments and return address one slot down on the stack |
| 674 // (overwriting the original receiver). Adjust argument count to make | 628 // (overwriting the original receiver). Adjust argument count to make |
| 675 // the original first argument the new receiver. | 629 // the original first argument the new receiver. |
| 676 __ bind(&shift_arguments); | 630 __ bind(&shift_arguments); |
| 677 { Label loop; | 631 { Label loop; |
| 678 __ movq(rcx, rax); | 632 __ movq(rcx, rax); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 762 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; | 716 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; |
| 763 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; | 717 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; |
| 764 __ push(rax); // limit | 718 __ push(rax); // limit |
| 765 __ push(Immediate(0)); // index | 719 __ push(Immediate(0)); // index |
| 766 | 720 |
| 767 // Change context eagerly to get the right global object if | 721 // Change context eagerly to get the right global object if |
| 768 // necessary. | 722 // necessary. |
| 769 __ movq(rdi, Operand(rbp, kFunctionOffset)); | 723 __ movq(rdi, Operand(rbp, kFunctionOffset)); |
| 770 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 724 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 771 | 725 |
| 772 // Compute the receiver. | 726 // Push the receiver. |
| 773 Label call_to_object, use_global_receiver, push_receiver; | |
| 774 __ movq(rbx, Operand(rbp, kReceiverOffset)); | 727 __ movq(rbx, Operand(rbp, kReceiverOffset)); |
| 775 __ JumpIfSmi(rbx, &call_to_object); | |
| 776 __ CompareRoot(rbx, Heap::kNullValueRootIndex); | |
| 777 __ j(equal, &use_global_receiver); | |
| 778 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); | |
| 779 __ j(equal, &use_global_receiver); | |
| 780 | |
| 781 // If given receiver is already a JavaScript object then there's no | |
| 782 // reason for converting it. | |
| 783 __ CmpObjectType(rbx, FIRST_JS_OBJECT_TYPE, rcx); | |
| 784 __ j(below, &call_to_object); | |
| 785 __ CmpInstanceType(rcx, LAST_JS_OBJECT_TYPE); | |
| 786 __ j(below_equal, &push_receiver); | |
| 787 | |
| 788 // Convert the receiver to an object. | |
| 789 __ bind(&call_to_object); | |
| 790 __ push(rbx); | |
| 791 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | |
| 792 __ movq(rbx, rax); | |
| 793 __ jmp(&push_receiver); | |
| 794 | |
| 795 // Use the current global receiver object as the receiver. | |
| 796 __ bind(&use_global_receiver); | |
| 797 const int kGlobalOffset = | |
| 798 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; | |
| 799 __ movq(rbx, FieldOperand(rsi, kGlobalOffset)); | |
| 800 __ movq(rbx, FieldOperand(rbx, GlobalObject::kGlobalContextOffset)); | |
| 801 __ movq(rbx, FieldOperand(rbx, kGlobalOffset)); | |
| 802 __ movq(rbx, FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); | |
| 803 | |
| 804 // Push the receiver. | |
| 805 __ bind(&push_receiver); | |
| 806 __ push(rbx); | 728 __ push(rbx); |
| 807 | 729 |
| 808 // Copy all arguments from the array to the stack. | 730 // Copy all arguments from the array to the stack. |
| 809 Label entry, loop; | 731 Label entry, loop; |
| 810 __ movq(rax, Operand(rbp, kIndexOffset)); | 732 __ movq(rax, Operand(rbp, kIndexOffset)); |
| 811 __ jmp(&entry); | 733 __ jmp(&entry); |
| 812 __ bind(&loop); | 734 __ bind(&loop); |
| 813 __ movq(rdx, Operand(rbp, kArgumentsOffset)); // load arguments | 735 __ movq(rdx, Operand(rbp, kArgumentsOffset)); // load arguments |
| 814 | 736 |
| 815 // Use inline caching to speed up access to arguments. | 737 // Use inline caching to speed up access to arguments. |
| (...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1382 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { | 1304 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { |
| 1383 __ int3(); | 1305 __ int3(); |
| 1384 } | 1306 } |
| 1385 | 1307 |
| 1386 | 1308 |
| 1387 #undef __ | 1309 #undef __ |
| 1388 | 1310 |
| 1389 } } // namespace v8::internal | 1311 } } // namespace v8::internal |
| 1390 | 1312 |
| 1391 #endif // V8_TARGET_ARCH_X64 | 1313 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |