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 #if V8_TARGET_ARCH_X64 | 5 #if V8_TARGET_ARCH_X64 |
6 | 6 |
| 7 #include "src/api-arguments.h" |
7 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
8 #include "src/codegen.h" | 9 #include "src/codegen.h" |
9 #include "src/counters.h" | 10 #include "src/counters.h" |
10 #include "src/deoptimizer.h" | 11 #include "src/deoptimizer.h" |
11 #include "src/full-codegen/full-codegen.h" | 12 #include "src/full-codegen/full-codegen.h" |
12 #include "src/objects-inl.h" | 13 #include "src/objects-inl.h" |
13 | 14 |
14 namespace v8 { | 15 namespace v8 { |
15 namespace internal { | 16 namespace internal { |
16 | 17 |
(...skipping 2912 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2929 | 2930 |
2930 // CheckSpreadAndPushToStack will push rdx to save it. | 2931 // CheckSpreadAndPushToStack will push rdx to save it. |
2931 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); | 2932 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); |
2932 CheckSpreadAndPushToStack(masm); | 2933 CheckSpreadAndPushToStack(masm); |
2933 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, | 2934 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, |
2934 TailCallMode::kDisallow), | 2935 TailCallMode::kDisallow), |
2935 RelocInfo::CODE_TARGET); | 2936 RelocInfo::CODE_TARGET); |
2936 } | 2937 } |
2937 | 2938 |
2938 // static | 2939 // static |
| 2940 void Builtins::Generate_CallFunctionCallback(MacroAssembler* masm) { |
| 2941 // ----------- S t a t e ------------- |
| 2942 // -- rax : the number of arguments (not incl. the receiver) |
| 2943 // -- rdx : api function address |
| 2944 // -- rsp[0] : return address |
| 2945 // -- rsp[8] : holder |
| 2946 // -- rsp[16] : isolate |
| 2947 // -- rsp[24] : return value default |
| 2948 // -- rsp[32] : return value |
| 2949 // -- rsp[40] : call data |
| 2950 // -- rsp[48] : target |
| 2951 // -- rsp[56] : context save |
| 2952 // -- rsp[64] : new.target |
| 2953 // -- rsp[72] : last argument |
| 2954 // -- rsp[64 + argc * 8] : first argument |
| 2955 // -- rsp[72 + argc * 8] : receiver |
| 2956 // ----------------------------------- |
| 2957 typedef FunctionCallbackArguments FCA; |
| 2958 |
| 2959 STATIC_ASSERT(FCA::kNewTargetIndex == 7); |
| 2960 STATIC_ASSERT(FCA::kContextSaveIndex == 6); |
| 2961 STATIC_ASSERT(FCA::kCalleeIndex == 5); |
| 2962 STATIC_ASSERT(FCA::kDataIndex == 4); |
| 2963 STATIC_ASSERT(FCA::kReturnValueOffset == 3); |
| 2964 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); |
| 2965 STATIC_ASSERT(FCA::kIsolateIndex == 1); |
| 2966 STATIC_ASSERT(FCA::kHolderIndex == 0); |
| 2967 STATIC_ASSERT(FCA::kArgsLength == 8); |
| 2968 |
| 2969 // Compute the pointer to the implicit args on the stack. |
| 2970 __ leap(rbx, MemOperand(rsp, kPCOnStackSize)); |
| 2971 |
| 2972 // Allocate the v8::FunctionCallbackInfo structure in the arguments' space |
| 2973 // since it's not controlled by the GC. |
| 2974 const int kApiStackSpace = 3; |
| 2975 __ EnterApiExitFrame(kApiStackSpace); |
| 2976 // Initialize FunctionCallbackInfo::implicit_args_. |
| 2977 __ movp(StackSpaceOperand(0), rbx); |
| 2978 // Initialize FunctionCallbackInfo::values_. |
| 2979 __ leap(rbx, MemOperand(rbx, rax, times_pointer_size, |
| 2980 (FCA::kArgsLength - 1) * kPointerSize)); |
| 2981 __ movp(StackSpaceOperand(1), rbx); |
| 2982 // Initialize FunctionCallbackInfo::length_. |
| 2983 __ movp(StackSpaceOperand(2), rax); |
| 2984 |
| 2985 // Load first argument with pointer to FunctionCallbackInfo. |
| 2986 __ leap(arg_reg_1, StackSpaceOperand(0)); |
| 2987 |
| 2988 const int kNextOffset = 0; |
| 2989 const int kLimitOffset = AddressOffset( |
| 2990 ExternalReference::handle_scope_limit_address(masm->isolate()), |
| 2991 ExternalReference::handle_scope_next_address(masm->isolate())); |
| 2992 const int kLevelOffset = AddressOffset( |
| 2993 ExternalReference::handle_scope_level_address(masm->isolate()), |
| 2994 ExternalReference::handle_scope_next_address(masm->isolate())); |
| 2995 |
| 2996 // Allocate HandleScope in callee-save registers. |
| 2997 Register const prev_next_address_reg = r14; |
| 2998 Register const prev_limit_reg = rbx; |
| 2999 Register const base_reg = r15; |
| 3000 __ Move(base_reg, |
| 3001 ExternalReference::handle_scope_next_address(masm->isolate())); |
| 3002 __ movp(prev_next_address_reg, Operand(base_reg, kNextOffset)); |
| 3003 __ movp(prev_limit_reg, Operand(base_reg, kLimitOffset)); |
| 3004 __ addl(Operand(base_reg, kLevelOffset), Immediate(1)); |
| 3005 |
| 3006 // Check if profiling is active, and if so call the function indirectly |
| 3007 // via the invoke_function_callback helper. |
| 3008 Label call_indirect, done_call; |
| 3009 __ Move(rax, ExternalReference::is_profiling_address(masm->isolate())); |
| 3010 __ cmpb(MemOperand(rax, 0), Immediate(0)); |
| 3011 __ j(not_zero, &call_indirect, Label::kNear); |
| 3012 { |
| 3013 // Call the API function directly. |
| 3014 __ call(rdx); |
| 3015 } |
| 3016 __ jmp(&done_call, Label::kNear); |
| 3017 __ bind(&call_indirect); |
| 3018 { |
| 3019 // Call the API function indirectly when profiling is on. |
| 3020 __ Move(arg_reg_2, rdx); |
| 3021 __ Call(ExternalReference::invoke_function_callback(masm->isolate())); |
| 3022 } |
| 3023 __ bind(&done_call); |
| 3024 |
| 3025 // No more valid handles (the result handle was the last one). Restore |
| 3026 // previous handle scope. |
| 3027 Label delete_allocated_handles; |
| 3028 __ subl(Operand(base_reg, kLevelOffset), Immediate(1)); |
| 3029 __ movp(Operand(base_reg, kNextOffset), prev_next_address_reg); |
| 3030 __ cmpp(prev_limit_reg, Operand(base_reg, kLimitOffset)); |
| 3031 __ j(not_equal, &delete_allocated_handles); |
| 3032 |
| 3033 // Leave the API exit frame. |
| 3034 Label leave_exit_frame; |
| 3035 __ bind(&leave_exit_frame); |
| 3036 __ movp(rax, MemOperand(rbp, (2 + FCA::kReturnValueOffset) * kPointerSize)); |
| 3037 __ movp(rsi, MemOperand(rbp, (2 + FCA::kContextSaveIndex) * kPointerSize)); |
| 3038 __ movp(rbx, StackSpaceOperand(2)); |
| 3039 __ LeaveApiExitFrame(false); |
| 3040 |
| 3041 // Check if the function scheduled an exception. |
| 3042 Label promote_scheduled_exception; |
| 3043 __ Move(rdi, ExternalReference::scheduled_exception_address(masm->isolate())); |
| 3044 __ JumpIfNotRoot(MemOperand(rdi, 0), Heap::kTheHoleValueRootIndex, |
| 3045 &promote_scheduled_exception); |
| 3046 |
| 3047 // Check if the function returned a valid JavaScript value. |
| 3048 __ AssertApiCallResult(rax); |
| 3049 |
| 3050 // Drop the arguments and return. |
| 3051 __ PopReturnAddressTo(rcx); |
| 3052 __ leaq(rsp, MemOperand(rsp, rbx, times_pointer_size, |
| 3053 (FCA::kArgsLength + 1) * kPointerSize)); |
| 3054 __ PushReturnAddressFrom(rcx); |
| 3055 __ Ret(); |
| 3056 |
| 3057 // Re-throw by promoting a scheduled exception. |
| 3058 __ bind(&promote_scheduled_exception); |
| 3059 __ TailCallRuntime(Runtime::kPromoteScheduledException); |
| 3060 |
| 3061 // HandleScope limit has changed. Delete allocated extensions. |
| 3062 __ bind(&delete_allocated_handles); |
| 3063 { |
| 3064 __ movp(Operand(base_reg, kLimitOffset), prev_limit_reg); |
| 3065 __ LoadAddress(arg_reg_1, |
| 3066 ExternalReference::isolate_address(masm->isolate())); |
| 3067 __ Call(ExternalReference::delete_handle_scope_extensions(masm->isolate())); |
| 3068 } |
| 3069 __ jmp(&leave_exit_frame); |
| 3070 } |
| 3071 |
| 3072 // static |
2939 void Builtins::Generate_ConstructFunction(MacroAssembler* masm) { | 3073 void Builtins::Generate_ConstructFunction(MacroAssembler* masm) { |
2940 // ----------- S t a t e ------------- | 3074 // ----------- S t a t e ------------- |
2941 // -- rax : the number of arguments (not including the receiver) | 3075 // -- rax : the number of arguments (not including the receiver) |
2942 // -- rdx : the new target (checked to be a constructor) | 3076 // -- rdx : the new target (checked to be a constructor) |
2943 // -- rdi : the constructor to call (checked to be a JSFunction) | 3077 // -- rdi : the constructor to call (checked to be a JSFunction) |
2944 // ----------------------------------- | 3078 // ----------------------------------- |
2945 __ AssertFunction(rdi); | 3079 __ AssertFunction(rdi); |
2946 | 3080 |
2947 // Calling convention for function specific ConstructStubs require | 3081 // Calling convention for function specific ConstructStubs require |
2948 // rbx to contain either an AllocationSite or undefined. | 3082 // rbx to contain either an AllocationSite or undefined. |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3165 // Now jump to the instructions of the returned code object. | 3299 // Now jump to the instructions of the returned code object. |
3166 __ jmp(r11); | 3300 __ jmp(r11); |
3167 } | 3301 } |
3168 | 3302 |
3169 #undef __ | 3303 #undef __ |
3170 | 3304 |
3171 } // namespace internal | 3305 } // namespace internal |
3172 } // namespace v8 | 3306 } // namespace v8 |
3173 | 3307 |
3174 #endif // V8_TARGET_ARCH_X64 | 3308 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |