| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 684 ASSERT(static_cast<int>(offset) == offset); | 684 ASSERT(static_cast<int>(offset) == offset); |
| 685 return static_cast<int>(offset); | 685 return static_cast<int>(offset); |
| 686 } | 686 } |
| 687 | 687 |
| 688 | 688 |
| 689 void MacroAssembler::PrepareCallApiFunction(int arg_stack_space) { | 689 void MacroAssembler::PrepareCallApiFunction(int arg_stack_space) { |
| 690 EnterApiExitFrame(arg_stack_space); | 690 EnterApiExitFrame(arg_stack_space); |
| 691 } | 691 } |
| 692 | 692 |
| 693 | 693 |
| 694 void MacroAssembler::CallApiFunctionAndReturn( | 694 void MacroAssembler::CallApiFunctionAndReturn(Address function_address, |
| 695 Address function_address, | 695 Address thunk_address, |
| 696 Address thunk_address, | 696 Register thunk_last_arg, |
| 697 Register thunk_last_arg, | 697 int stack_space, |
| 698 int stack_space, | 698 int return_value_offset) { |
| 699 Operand return_value_operand, | |
| 700 Operand* context_restore_operand) { | |
| 701 Label prologue; | 699 Label prologue; |
| 702 Label promote_scheduled_exception; | 700 Label promote_scheduled_exception; |
| 703 Label exception_handled; | |
| 704 Label delete_allocated_handles; | 701 Label delete_allocated_handles; |
| 705 Label leave_exit_frame; | 702 Label leave_exit_frame; |
| 706 Label write_back; | 703 Label write_back; |
| 707 | 704 |
| 708 Factory* factory = isolate()->factory(); | 705 Factory* factory = isolate()->factory(); |
| 709 ExternalReference next_address = | 706 ExternalReference next_address = |
| 710 ExternalReference::handle_scope_next_address(isolate()); | 707 ExternalReference::handle_scope_next_address(isolate()); |
| 711 const int kNextOffset = 0; | 708 const int kNextOffset = 0; |
| 712 const int kLimitOffset = Offset( | 709 const int kLimitOffset = Offset( |
| 713 ExternalReference::handle_scope_limit_address(isolate()), | 710 ExternalReference::handle_scope_limit_address(isolate()), |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 764 if (FLAG_log_timer_events) { | 761 if (FLAG_log_timer_events) { |
| 765 FrameScope frame(this, StackFrame::MANUAL); | 762 FrameScope frame(this, StackFrame::MANUAL); |
| 766 PushSafepointRegisters(); | 763 PushSafepointRegisters(); |
| 767 PrepareCallCFunction(1); | 764 PrepareCallCFunction(1); |
| 768 LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate())); | 765 LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate())); |
| 769 CallCFunction(ExternalReference::log_leave_external_function(isolate()), 1); | 766 CallCFunction(ExternalReference::log_leave_external_function(isolate()), 1); |
| 770 PopSafepointRegisters(); | 767 PopSafepointRegisters(); |
| 771 } | 768 } |
| 772 | 769 |
| 773 // Load the value from ReturnValue | 770 // Load the value from ReturnValue |
| 774 movq(rax, return_value_operand); | 771 movq(rax, Operand(rbp, return_value_offset * kPointerSize)); |
| 775 bind(&prologue); | 772 bind(&prologue); |
| 776 | 773 |
| 777 // No more valid handles (the result handle was the last one). Restore | 774 // No more valid handles (the result handle was the last one). Restore |
| 778 // previous handle scope. | 775 // previous handle scope. |
| 779 subl(Operand(base_reg, kLevelOffset), Immediate(1)); | 776 subl(Operand(base_reg, kLevelOffset), Immediate(1)); |
| 780 movq(Operand(base_reg, kNextOffset), prev_next_address_reg); | 777 movq(Operand(base_reg, kNextOffset), prev_next_address_reg); |
| 781 cmpq(prev_limit_reg, Operand(base_reg, kLimitOffset)); | 778 cmpq(prev_limit_reg, Operand(base_reg, kLimitOffset)); |
| 782 j(not_equal, &delete_allocated_handles); | 779 j(not_equal, &delete_allocated_handles); |
| 783 bind(&leave_exit_frame); | 780 bind(&leave_exit_frame); |
| 784 | 781 |
| 785 // Check if the function scheduled an exception. | 782 // Check if the function scheduled an exception. |
| 786 movq(rsi, scheduled_exception_address); | 783 movq(rsi, scheduled_exception_address); |
| 787 Cmp(Operand(rsi, 0), factory->the_hole_value()); | 784 Cmp(Operand(rsi, 0), factory->the_hole_value()); |
| 788 j(not_equal, &promote_scheduled_exception); | 785 j(not_equal, &promote_scheduled_exception); |
| 789 bind(&exception_handled); | |
| 790 | 786 |
| 791 #if ENABLE_EXTRA_CHECKS | 787 #if ENABLE_EXTRA_CHECKS |
| 792 // Check if the function returned a valid JavaScript value. | 788 // Check if the function returned a valid JavaScript value. |
| 793 Label ok; | 789 Label ok; |
| 794 Register return_value = rax; | 790 Register return_value = rax; |
| 795 Register map = rcx; | 791 Register map = rcx; |
| 796 | 792 |
| 797 JumpIfSmi(return_value, &ok, Label::kNear); | 793 JumpIfSmi(return_value, &ok, Label::kNear); |
| 798 movq(map, FieldOperand(return_value, HeapObject::kMapOffset)); | 794 movq(map, FieldOperand(return_value, HeapObject::kMapOffset)); |
| 799 | 795 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 816 j(equal, &ok, Label::kNear); | 812 j(equal, &ok, Label::kNear); |
| 817 | 813 |
| 818 CompareRoot(return_value, Heap::kNullValueRootIndex); | 814 CompareRoot(return_value, Heap::kNullValueRootIndex); |
| 819 j(equal, &ok, Label::kNear); | 815 j(equal, &ok, Label::kNear); |
| 820 | 816 |
| 821 Abort(kAPICallReturnedInvalidObject); | 817 Abort(kAPICallReturnedInvalidObject); |
| 822 | 818 |
| 823 bind(&ok); | 819 bind(&ok); |
| 824 #endif | 820 #endif |
| 825 | 821 |
| 826 bool restore_context = context_restore_operand != NULL; | 822 LeaveApiExitFrame(); |
| 827 if (restore_context) { | |
| 828 movq(rsi, *context_restore_operand); | |
| 829 } | |
| 830 LeaveApiExitFrame(!restore_context); | |
| 831 ret(stack_space * kPointerSize); | 823 ret(stack_space * kPointerSize); |
| 832 | 824 |
| 833 bind(&promote_scheduled_exception); | 825 bind(&promote_scheduled_exception); |
| 834 { | 826 TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1); |
| 835 FrameScope frame(this, StackFrame::INTERNAL); | |
| 836 CallRuntime(Runtime::kPromoteScheduledException, 0); | |
| 837 } | |
| 838 jmp(&exception_handled); | |
| 839 | 827 |
| 840 // HandleScope limit has changed. Delete allocated extensions. | 828 // HandleScope limit has changed. Delete allocated extensions. |
| 841 bind(&delete_allocated_handles); | 829 bind(&delete_allocated_handles); |
| 842 movq(Operand(base_reg, kLimitOffset), prev_limit_reg); | 830 movq(Operand(base_reg, kLimitOffset), prev_limit_reg); |
| 843 movq(prev_limit_reg, rax); | 831 movq(prev_limit_reg, rax); |
| 844 LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate())); | 832 LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate())); |
| 845 LoadAddress(rax, | 833 LoadAddress(rax, |
| 846 ExternalReference::delete_handle_scope_extensions(isolate())); | 834 ExternalReference::delete_handle_scope_extensions(isolate())); |
| 847 call(rax); | 835 call(rax); |
| 848 movq(rax, prev_limit_reg); | 836 movq(rax, prev_limit_reg); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 941 } | 929 } |
| 942 for (int i = kNumberOfSavedRegs - 1; i >= 0; i--) { | 930 for (int i = kNumberOfSavedRegs - 1; i >= 0; i--) { |
| 943 Register reg = saved_regs[i]; | 931 Register reg = saved_regs[i]; |
| 944 if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) { | 932 if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) { |
| 945 pop(reg); | 933 pop(reg); |
| 946 } | 934 } |
| 947 } | 935 } |
| 948 } | 936 } |
| 949 | 937 |
| 950 | 938 |
| 951 void MacroAssembler::Cvtlsi2sd(XMMRegister dst, Register src) { | |
| 952 xorps(dst, dst); | |
| 953 cvtlsi2sd(dst, src); | |
| 954 } | |
| 955 | |
| 956 | |
| 957 void MacroAssembler::Cvtlsi2sd(XMMRegister dst, const Operand& src) { | |
| 958 xorps(dst, dst); | |
| 959 cvtlsi2sd(dst, src); | |
| 960 } | |
| 961 | |
| 962 | |
| 963 void MacroAssembler::Set(Register dst, int64_t x) { | 939 void MacroAssembler::Set(Register dst, int64_t x) { |
| 964 if (x == 0) { | 940 if (x == 0) { |
| 965 xorl(dst, dst); | 941 xorl(dst, dst); |
| 966 } else if (is_uint32(x)) { | 942 } else if (is_uint32(x)) { |
| 967 movl(dst, Immediate(static_cast<uint32_t>(x))); | 943 movl(dst, Immediate(static_cast<uint32_t>(x))); |
| 968 } else if (is_int32(x)) { | 944 } else if (is_int32(x)) { |
| 969 movq(dst, Immediate(static_cast<int32_t>(x))); | 945 movq(dst, Immediate(static_cast<int32_t>(x))); |
| 970 } else { | 946 } else { |
| 971 movq(dst, x, RelocInfo::NONE64); | 947 movq(dst, x, RelocInfo::NONE64); |
| 972 } | 948 } |
| (...skipping 1961 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2934 // the double array. | 2910 // the double array. |
| 2935 Set(kScratchRegister, BitCast<uint64_t>( | 2911 Set(kScratchRegister, BitCast<uint64_t>( |
| 2936 FixedDoubleArray::canonical_not_the_hole_nan_as_double())); | 2912 FixedDoubleArray::canonical_not_the_hole_nan_as_double())); |
| 2937 movq(xmm_scratch, kScratchRegister); | 2913 movq(xmm_scratch, kScratchRegister); |
| 2938 jmp(&have_double_value, Label::kNear); | 2914 jmp(&have_double_value, Label::kNear); |
| 2939 | 2915 |
| 2940 bind(&smi_value); | 2916 bind(&smi_value); |
| 2941 // Value is a smi. convert to a double and store. | 2917 // Value is a smi. convert to a double and store. |
| 2942 // Preserve original value. | 2918 // Preserve original value. |
| 2943 SmiToInteger32(kScratchRegister, maybe_number); | 2919 SmiToInteger32(kScratchRegister, maybe_number); |
| 2944 Cvtlsi2sd(xmm_scratch, kScratchRegister); | 2920 cvtlsi2sd(xmm_scratch, kScratchRegister); |
| 2945 movsd(FieldOperand(elements, index, times_8, | 2921 movsd(FieldOperand(elements, index, times_8, |
| 2946 FixedDoubleArray::kHeaderSize - elements_offset), | 2922 FixedDoubleArray::kHeaderSize - elements_offset), |
| 2947 xmm_scratch); | 2923 xmm_scratch); |
| 2948 bind(&done); | 2924 bind(&done); |
| 2949 } | 2925 } |
| 2950 | 2926 |
| 2951 | 2927 |
| 2952 void MacroAssembler::CompareMap(Register obj, | 2928 void MacroAssembler::CompareMap(Register obj, |
| 2953 Handle<Map> map, | 2929 Handle<Map> map, |
| 2954 Label* early_success) { | 2930 Label* early_success) { |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3067 } | 3043 } |
| 3068 | 3044 |
| 3069 | 3045 |
| 3070 void MacroAssembler::DoubleToI(Register result_reg, | 3046 void MacroAssembler::DoubleToI(Register result_reg, |
| 3071 XMMRegister input_reg, | 3047 XMMRegister input_reg, |
| 3072 XMMRegister scratch, | 3048 XMMRegister scratch, |
| 3073 MinusZeroMode minus_zero_mode, | 3049 MinusZeroMode minus_zero_mode, |
| 3074 Label* conversion_failed, | 3050 Label* conversion_failed, |
| 3075 Label::Distance dst) { | 3051 Label::Distance dst) { |
| 3076 cvttsd2si(result_reg, input_reg); | 3052 cvttsd2si(result_reg, input_reg); |
| 3077 Cvtlsi2sd(xmm0, result_reg); | 3053 cvtlsi2sd(xmm0, result_reg); |
| 3078 ucomisd(xmm0, input_reg); | 3054 ucomisd(xmm0, input_reg); |
| 3079 j(not_equal, conversion_failed, dst); | 3055 j(not_equal, conversion_failed, dst); |
| 3080 j(parity_even, conversion_failed, dst); // NaN. | 3056 j(parity_even, conversion_failed, dst); // NaN. |
| 3081 if (minus_zero_mode == FAIL_ON_MINUS_ZERO) { | 3057 if (minus_zero_mode == FAIL_ON_MINUS_ZERO) { |
| 3082 Label done; | 3058 Label done; |
| 3083 // The integer converted back is equal to the original. We | 3059 // The integer converted back is equal to the original. We |
| 3084 // only have to test if we got -0 as an input. | 3060 // only have to test if we got -0 as an input. |
| 3085 testl(result_reg, result_reg); | 3061 testl(result_reg, result_reg); |
| 3086 j(not_zero, &done, Label::kNear); | 3062 j(not_zero, &done, Label::kNear); |
| 3087 movmskpd(result_reg, input_reg); | 3063 movmskpd(result_reg, input_reg); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 3104 Label done; | 3080 Label done; |
| 3105 ASSERT(!temp.is(xmm0)); | 3081 ASSERT(!temp.is(xmm0)); |
| 3106 | 3082 |
| 3107 // Heap number map check. | 3083 // Heap number map check. |
| 3108 CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 3084 CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 3109 Heap::kHeapNumberMapRootIndex); | 3085 Heap::kHeapNumberMapRootIndex); |
| 3110 j(not_equal, lost_precision, dst); | 3086 j(not_equal, lost_precision, dst); |
| 3111 | 3087 |
| 3112 movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3088 movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 3113 cvttsd2si(result_reg, xmm0); | 3089 cvttsd2si(result_reg, xmm0); |
| 3114 Cvtlsi2sd(temp, result_reg); | 3090 cvtlsi2sd(temp, result_reg); |
| 3115 ucomisd(xmm0, temp); | 3091 ucomisd(xmm0, temp); |
| 3116 RecordComment("Deferred TaggedToI: lost precision"); | 3092 RecordComment("Deferred TaggedToI: lost precision"); |
| 3117 j(not_equal, lost_precision, dst); | 3093 j(not_equal, lost_precision, dst); |
| 3118 RecordComment("Deferred TaggedToI: NaN"); | 3094 RecordComment("Deferred TaggedToI: NaN"); |
| 3119 j(parity_even, lost_precision, dst); // NaN. | 3095 j(parity_even, lost_precision, dst); // NaN. |
| 3120 if (minus_zero_mode == FAIL_ON_MINUS_ZERO) { | 3096 if (minus_zero_mode == FAIL_ON_MINUS_ZERO) { |
| 3121 testl(result_reg, result_reg); | 3097 testl(result_reg, result_reg); |
| 3122 j(not_zero, &done, Label::kNear); | 3098 j(not_zero, &done, Label::kNear); |
| 3123 movmskpd(result_reg, xmm0); | 3099 movmskpd(result_reg, xmm0); |
| 3124 andl(result_reg, Immediate(1)); | 3100 andl(result_reg, Immediate(1)); |
| (...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3700 // Get the return address from the stack and restore the frame pointer. | 3676 // Get the return address from the stack and restore the frame pointer. |
| 3701 movq(rcx, Operand(rbp, 1 * kPointerSize)); | 3677 movq(rcx, Operand(rbp, 1 * kPointerSize)); |
| 3702 movq(rbp, Operand(rbp, 0 * kPointerSize)); | 3678 movq(rbp, Operand(rbp, 0 * kPointerSize)); |
| 3703 | 3679 |
| 3704 // Drop everything up to and including the arguments and the receiver | 3680 // Drop everything up to and including the arguments and the receiver |
| 3705 // from the caller stack. | 3681 // from the caller stack. |
| 3706 lea(rsp, Operand(r15, 1 * kPointerSize)); | 3682 lea(rsp, Operand(r15, 1 * kPointerSize)); |
| 3707 | 3683 |
| 3708 PushReturnAddressFrom(rcx); | 3684 PushReturnAddressFrom(rcx); |
| 3709 | 3685 |
| 3710 LeaveExitFrameEpilogue(true); | 3686 LeaveExitFrameEpilogue(); |
| 3711 } | 3687 } |
| 3712 | 3688 |
| 3713 | 3689 |
| 3714 void MacroAssembler::LeaveApiExitFrame(bool restore_context) { | 3690 void MacroAssembler::LeaveApiExitFrame() { |
| 3715 movq(rsp, rbp); | 3691 movq(rsp, rbp); |
| 3716 pop(rbp); | 3692 pop(rbp); |
| 3717 | 3693 |
| 3718 LeaveExitFrameEpilogue(restore_context); | 3694 LeaveExitFrameEpilogue(); |
| 3719 } | 3695 } |
| 3720 | 3696 |
| 3721 | 3697 |
| 3722 void MacroAssembler::LeaveExitFrameEpilogue(bool restore_context) { | 3698 void MacroAssembler::LeaveExitFrameEpilogue() { |
| 3723 // Restore current context from top and clear it in debug mode. | 3699 // Restore current context from top and clear it in debug mode. |
| 3724 ExternalReference context_address(Isolate::kContextAddress, isolate()); | 3700 ExternalReference context_address(Isolate::kContextAddress, isolate()); |
| 3725 Operand context_operand = ExternalOperand(context_address); | 3701 Operand context_operand = ExternalOperand(context_address); |
| 3726 if (restore_context) { | 3702 movq(rsi, context_operand); |
| 3727 movq(rsi, context_operand); | |
| 3728 } | |
| 3729 #ifdef DEBUG | 3703 #ifdef DEBUG |
| 3730 movq(context_operand, Immediate(0)); | 3704 movq(context_operand, Immediate(0)); |
| 3731 #endif | 3705 #endif |
| 3732 | 3706 |
| 3733 // Clear the top frame. | 3707 // Clear the top frame. |
| 3734 ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, | 3708 ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, |
| 3735 isolate()); | 3709 isolate()); |
| 3736 Operand c_entry_fp_operand = ExternalOperand(c_entry_fp_address); | 3710 Operand c_entry_fp_operand = ExternalOperand(c_entry_fp_address); |
| 3737 movq(c_entry_fp_operand, Immediate(0)); | 3711 movq(c_entry_fp_operand, Immediate(0)); |
| 3738 } | 3712 } |
| (...skipping 1094 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4833 j(greater, &no_memento_available); | 4807 j(greater, &no_memento_available); |
| 4834 CompareRoot(MemOperand(scratch_reg, -AllocationMemento::kSize), | 4808 CompareRoot(MemOperand(scratch_reg, -AllocationMemento::kSize), |
| 4835 Heap::kAllocationMementoMapRootIndex); | 4809 Heap::kAllocationMementoMapRootIndex); |
| 4836 bind(&no_memento_available); | 4810 bind(&no_memento_available); |
| 4837 } | 4811 } |
| 4838 | 4812 |
| 4839 | 4813 |
| 4840 } } // namespace v8::internal | 4814 } } // namespace v8::internal |
| 4841 | 4815 |
| 4842 #endif // V8_TARGET_ARCH_X64 | 4816 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |