| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
| 8 | 8 |
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
| 10 #include "src/base/division-by-constant.h" | 10 #include "src/base/division-by-constant.h" |
| (...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 685 | 685 |
| 686 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid, | 686 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid, |
| 687 int num_arguments, | 687 int num_arguments, |
| 688 int result_size) { | 688 int result_size) { |
| 689 TailCallExternalReference(ExternalReference(fid, isolate()), | 689 TailCallExternalReference(ExternalReference(fid, isolate()), |
| 690 num_arguments, | 690 num_arguments, |
| 691 result_size); | 691 result_size); |
| 692 } | 692 } |
| 693 | 693 |
| 694 | 694 |
| 695 static int Offset(ExternalReference ref0, ExternalReference ref1) { | |
| 696 int64_t offset = (ref0.address() - ref1.address()); | |
| 697 // Check that fits into int. | |
| 698 DCHECK(static_cast<int>(offset) == offset); | |
| 699 return static_cast<int>(offset); | |
| 700 } | |
| 701 | |
| 702 | |
| 703 void MacroAssembler::PrepareCallApiFunction(int arg_stack_space) { | |
| 704 EnterApiExitFrame(arg_stack_space); | |
| 705 } | |
| 706 | |
| 707 | |
| 708 void MacroAssembler::CallApiFunctionAndReturn( | |
| 709 Register function_address, ExternalReference thunk_ref, | |
| 710 Register thunk_last_arg, int stack_space, Operand* stack_space_operand, | |
| 711 Operand return_value_operand, Operand* context_restore_operand) { | |
| 712 Label prologue; | |
| 713 Label promote_scheduled_exception; | |
| 714 Label exception_handled; | |
| 715 Label delete_allocated_handles; | |
| 716 Label leave_exit_frame; | |
| 717 Label write_back; | |
| 718 | |
| 719 Factory* factory = isolate()->factory(); | |
| 720 ExternalReference next_address = | |
| 721 ExternalReference::handle_scope_next_address(isolate()); | |
| 722 const int kNextOffset = 0; | |
| 723 const int kLimitOffset = Offset( | |
| 724 ExternalReference::handle_scope_limit_address(isolate()), | |
| 725 next_address); | |
| 726 const int kLevelOffset = Offset( | |
| 727 ExternalReference::handle_scope_level_address(isolate()), | |
| 728 next_address); | |
| 729 ExternalReference scheduled_exception_address = | |
| 730 ExternalReference::scheduled_exception_address(isolate()); | |
| 731 | |
| 732 DCHECK(rdx.is(function_address) || r8.is(function_address)); | |
| 733 // Allocate HandleScope in callee-save registers. | |
| 734 Register prev_next_address_reg = r14; | |
| 735 Register prev_limit_reg = rbx; | |
| 736 Register base_reg = r15; | |
| 737 Move(base_reg, next_address); | |
| 738 movp(prev_next_address_reg, Operand(base_reg, kNextOffset)); | |
| 739 movp(prev_limit_reg, Operand(base_reg, kLimitOffset)); | |
| 740 addl(Operand(base_reg, kLevelOffset), Immediate(1)); | |
| 741 | |
| 742 if (FLAG_log_timer_events) { | |
| 743 FrameScope frame(this, StackFrame::MANUAL); | |
| 744 PushSafepointRegisters(); | |
| 745 PrepareCallCFunction(1); | |
| 746 LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate())); | |
| 747 CallCFunction(ExternalReference::log_enter_external_function(isolate()), 1); | |
| 748 PopSafepointRegisters(); | |
| 749 } | |
| 750 | |
| 751 | |
| 752 Label profiler_disabled; | |
| 753 Label end_profiler_check; | |
| 754 Move(rax, ExternalReference::is_profiling_address(isolate())); | |
| 755 cmpb(Operand(rax, 0), Immediate(0)); | |
| 756 j(zero, &profiler_disabled); | |
| 757 | |
| 758 // Third parameter is the address of the actual getter function. | |
| 759 Move(thunk_last_arg, function_address); | |
| 760 Move(rax, thunk_ref); | |
| 761 jmp(&end_profiler_check); | |
| 762 | |
| 763 bind(&profiler_disabled); | |
| 764 // Call the api function! | |
| 765 Move(rax, function_address); | |
| 766 | |
| 767 bind(&end_profiler_check); | |
| 768 | |
| 769 // Call the api function! | |
| 770 call(rax); | |
| 771 | |
| 772 if (FLAG_log_timer_events) { | |
| 773 FrameScope frame(this, StackFrame::MANUAL); | |
| 774 PushSafepointRegisters(); | |
| 775 PrepareCallCFunction(1); | |
| 776 LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate())); | |
| 777 CallCFunction(ExternalReference::log_leave_external_function(isolate()), 1); | |
| 778 PopSafepointRegisters(); | |
| 779 } | |
| 780 | |
| 781 // Load the value from ReturnValue | |
| 782 movp(rax, return_value_operand); | |
| 783 bind(&prologue); | |
| 784 | |
| 785 // No more valid handles (the result handle was the last one). Restore | |
| 786 // previous handle scope. | |
| 787 subl(Operand(base_reg, kLevelOffset), Immediate(1)); | |
| 788 movp(Operand(base_reg, kNextOffset), prev_next_address_reg); | |
| 789 cmpp(prev_limit_reg, Operand(base_reg, kLimitOffset)); | |
| 790 j(not_equal, &delete_allocated_handles); | |
| 791 bind(&leave_exit_frame); | |
| 792 | |
| 793 // Check if the function scheduled an exception. | |
| 794 Move(rsi, scheduled_exception_address); | |
| 795 Cmp(Operand(rsi, 0), factory->the_hole_value()); | |
| 796 j(not_equal, &promote_scheduled_exception); | |
| 797 bind(&exception_handled); | |
| 798 | |
| 799 #if DEBUG | |
| 800 // Check if the function returned a valid JavaScript value. | |
| 801 Label ok; | |
| 802 Register return_value = rax; | |
| 803 Register map = rcx; | |
| 804 | |
| 805 JumpIfSmi(return_value, &ok, Label::kNear); | |
| 806 movp(map, FieldOperand(return_value, HeapObject::kMapOffset)); | |
| 807 | |
| 808 CmpInstanceType(map, LAST_NAME_TYPE); | |
| 809 j(below_equal, &ok, Label::kNear); | |
| 810 | |
| 811 CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); | |
| 812 j(above_equal, &ok, Label::kNear); | |
| 813 | |
| 814 CompareRoot(map, Heap::kHeapNumberMapRootIndex); | |
| 815 j(equal, &ok, Label::kNear); | |
| 816 | |
| 817 CompareRoot(return_value, Heap::kUndefinedValueRootIndex); | |
| 818 j(equal, &ok, Label::kNear); | |
| 819 | |
| 820 CompareRoot(return_value, Heap::kTrueValueRootIndex); | |
| 821 j(equal, &ok, Label::kNear); | |
| 822 | |
| 823 CompareRoot(return_value, Heap::kFalseValueRootIndex); | |
| 824 j(equal, &ok, Label::kNear); | |
| 825 | |
| 826 CompareRoot(return_value, Heap::kNullValueRootIndex); | |
| 827 j(equal, &ok, Label::kNear); | |
| 828 | |
| 829 Abort(kAPICallReturnedInvalidObject); | |
| 830 | |
| 831 bind(&ok); | |
| 832 #endif | |
| 833 | |
| 834 bool restore_context = context_restore_operand != NULL; | |
| 835 if (restore_context) { | |
| 836 movp(rsi, *context_restore_operand); | |
| 837 } | |
| 838 if (stack_space_operand != nullptr) { | |
| 839 movp(rbx, *stack_space_operand); | |
| 840 } | |
| 841 LeaveApiExitFrame(!restore_context); | |
| 842 if (stack_space_operand != nullptr) { | |
| 843 DCHECK_EQ(stack_space, 0); | |
| 844 PopReturnAddressTo(rcx); | |
| 845 addq(rsp, rbx); | |
| 846 jmp(rcx); | |
| 847 } else { | |
| 848 ret(stack_space * kPointerSize); | |
| 849 } | |
| 850 | |
| 851 bind(&promote_scheduled_exception); | |
| 852 { | |
| 853 FrameScope frame(this, StackFrame::INTERNAL); | |
| 854 CallRuntime(Runtime::kPromoteScheduledException, 0); | |
| 855 } | |
| 856 jmp(&exception_handled); | |
| 857 | |
| 858 // HandleScope limit has changed. Delete allocated extensions. | |
| 859 bind(&delete_allocated_handles); | |
| 860 movp(Operand(base_reg, kLimitOffset), prev_limit_reg); | |
| 861 movp(prev_limit_reg, rax); | |
| 862 LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate())); | |
| 863 LoadAddress(rax, | |
| 864 ExternalReference::delete_handle_scope_extensions(isolate())); | |
| 865 call(rax); | |
| 866 movp(rax, prev_limit_reg); | |
| 867 jmp(&leave_exit_frame); | |
| 868 } | |
| 869 | |
| 870 | |
| 871 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext, | 695 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext, |
| 872 int result_size) { | 696 int result_size) { |
| 873 // Set the entry point and jump to the C entry runtime stub. | 697 // Set the entry point and jump to the C entry runtime stub. |
| 874 LoadAddress(rbx, ext); | 698 LoadAddress(rbx, ext); |
| 875 CEntryStub ces(isolate(), result_size); | 699 CEntryStub ces(isolate(), result_size); |
| 876 jmp(ces.GetCode(), RelocInfo::CODE_TARGET); | 700 jmp(ces.GetCode(), RelocInfo::CODE_TARGET); |
| 877 } | 701 } |
| 878 | 702 |
| 879 | 703 |
| 880 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, | 704 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, |
| (...skipping 4522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5403 if (mag.shift > 0) sarl(rdx, Immediate(mag.shift)); | 5227 if (mag.shift > 0) sarl(rdx, Immediate(mag.shift)); |
| 5404 movl(rax, dividend); | 5228 movl(rax, dividend); |
| 5405 shrl(rax, Immediate(31)); | 5229 shrl(rax, Immediate(31)); |
| 5406 addl(rdx, rax); | 5230 addl(rdx, rax); |
| 5407 } | 5231 } |
| 5408 | 5232 |
| 5409 | 5233 |
| 5410 } } // namespace v8::internal | 5234 } } // namespace v8::internal |
| 5411 | 5235 |
| 5412 #endif // V8_TARGET_ARCH_X64 | 5236 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |