1/** 2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "arch/asm_support.h" 17#include "arch/amd64/helpers_amd64.S" 18 19// Frame* CreateFrameForMethodWithActualArgsDyn(uint32_t num_actual_args, Method* method, Frame* prev); 20.extern CreateFrameForMethodWithActualArgsDyn 21// void InterpreterEntryPoint(Method* pc, Frame* frame, bool is_dynamic); 22.extern InterpreterEntryPoint 23// void FreeFrame(Frame* frame); 24.extern FreeFrame 25// bool DecrementHotnessCounterDyn(Method* method, TaggedValue func_obj); 26.extern DecrementHotnessCounterDyn 27 28// CompiledCodeToInterpreterBridgeDyn, follows DynamicMethod calling convention 29.global CompiledCodeToInterpreterBridgeDyn 30TYPE_FUNCTION(CompiledCodeToInterpreterBridgeDyn) 31CompiledCodeToInterpreterBridgeDyn: 32 CFI_STARTPROC 33 CFI_DEF_CFA(rsp, 8) 34 35 // method: %rdi 36 // num_args: %rsi 37 // arg_i: 24(%rbp, i, 8) 38 39 // Save return address to the TLS field 40 movq (%rsp), %rax 41 movq %rax, MANAGED_THREAD_NATIVE_PC_OFFSET(%THREAD_REG) 42 43 pushq $COMPILED_CODE_TO_INTERPRETER_BRIDGE 44 CFI_ADJUST_CFA_OFFSET(8) 45 46 // construct the frame 47 pushq %rbp 48 CFI_ADJUST_CFA_OFFSET(8) 49 CFI_REL_OFFSET(rbp, 0) 50 movq %rsp, %rbp // set frame pointer 51 CFI_DEF_CFA_REGISTER(rbp) 52 53 subq $8, %rsp 54 55 // save all the callee saved registers to the stack 56 // stack walker will read them during stack unwinding 57 pushq %r15 58 CFI_REL_OFFSET(r15, -(2 * 8)) 59 pushq %r14 60 CFI_REL_OFFSET(r14, -(3 * 8)) 61 pushq %r13 62 CFI_REL_OFFSET(r13, -(4 * 8)) 63 pushq %r12 64 CFI_REL_OFFSET(r12, -(5 * 8)) 65 pushq %rbx 66 CFI_REL_OFFSET(rbx, -(6 * 8)) 67 68 subq $8, %rsp 69 70 // Before we call DecrementHotnessCounterDyn we should set pointer to C2I frame in the TLS, 71 // because compilation may fall into safepoint, so we need to make caller's callee registers 72 // visible for the stack walker. 73 movq %rbp, MANAGED_THREAD_FRAME_OFFSET(%THREAD_REG) 74 75 PUSH_GENERAL_REGS 76 // Pass this function as second arg 77 movq 24(%rbp), %rsi 78 movq %THREAD_REG, %rdx 79 callq DecrementHotnessCounterDyn@plt 80 cmpb $0, %al 81 je .Lnot_compiled 82 83 // Compilation successfully done, so recover caller's frame in the TLS, since C2I is not needed. 84 movq (%rbp), %r8 85 movq %r8, MANAGED_THREAD_FRAME_OFFSET(%THREAD_REG) 86 87 POP_GENERAL_REGS 88 89 movq %rbp, %rsp 90 addq $16, %rsp 91 movq (%rbp), %rbp 92 CFI_REMEMBER_STATE 93 CFI_RESTORE(rbp) 94 CFI_DEF_CFA(rsp, 8) 95 96 movq METHOD_COMPILED_ENTRY_POINT_OFFSET(%rdi), %rax 97 jmp *%rax 98 CFI_RESTORE_STATE 99 CFI_DEF_CFA(rbp, (3 * 8)) 100 101.Lnot_compiled: 102 RELOAD_GENERAL_REGS 103 104 // Create an interpreter frame 105 // %r12 - iframe* 106 xchgq %rsi, %rdi 107 movq %rbp, %rdx 108 // Frame* CreateFrameForMethodWithActualArgsDyn(uint32_t num_actual_args, Method* method, Frame* prev); 109 callq CreateFrameForMethodWithActualArgsDyn@plt 110 movq %rax, %r12 111 112 POP_GENERAL_REGS 113 114 // setup regs as follows 115 // %r12 - iframe* 116 // %rdi - method* 117 // %rsi - num_actual_args 118 119 // %r15d - num_iframe_args = max(num_actual_args, mehtod->num_args_) 120 // %rax - iframe.vregs_ + num_vregs_ 121 movl METHOD_NUM_ARGS_OFFSET(%rdi), %r15d 122 cmpl %r15d, %esi 123 cmovge %esi, %r15d 124 movl FRAME_NUM_VREGS_OFFSET(%r12), %eax 125 subl %r15d, %eax 126 leaq FRAME_VREGS_OFFSET(%r12, %rax, FRAME_VREGISTER_SIZE), %rax 127 128 test %rsi, %rsi 129 jz .Linit_rest 130 131 // copy actual args 132 // %rdx - incoming stack arguments 133 leaq 24(%rbp), %rdx 134 leal -FRAME_VREGISTER_SIZE(, %esi, FRAME_VREGISTER_SIZE), %r14d 135.Lloop_actual: 136 movq (%rdx, %r14), %rcx 137 movq %rcx, (%rax, %r14) 138 subl $FRAME_VREGISTER_SIZE, %r14d 139 jae .Lloop_actual 140 141.Linit_rest: 142 // r15d - num_rest_args = num_iframe_args - num_actual_args 143 subl %esi, %r15d 144 jz .Lcall_interpreter 145 146 // init rest args 147 // %r14 - iframe.vregs_ + num_vregs_ + num_actual_args 148 // %rax - initial tagged value (TAGGED_VALUE_UNDEFINED) 149 leaq (%rax, %rsi, FRAME_VREGISTER_SIZE), %r14 150 movq $TAGGED_VALUE_UNDEFINED, %rax 151 leal -FRAME_VREGISTER_SIZE(, %r15d, FRAME_VREGISTER_SIZE), %r15d 152.Lloop_rest: 153 movq %rax, (%r14, %r15) 154 subl $FRAME_VREGISTER_SIZE, %r15d 155 jae .Lloop_rest 156 157.Lcall_interpreter: 158#if defined(PANDA_WITH_ECMASCRIPT) && defined(ARK_INTRINSIC_SET) 159 // Setup EcmascriptEnvironment 160 // %r14 - this func (1st arg) 161 // %rax - iframe ext data 162 movq 24(%rbp), %r14 163 164 leaq (EXTFRAME_EXT_DATA_OFFSET-EXTFRAME_FRAME_OFFSET)(%r12), %rax 165 166 // Store constant pool to iframe 167 movq JSFUNCTION_CONSTANT_POOL_OFFSET(%r14), %r15 168 movq %r15, ECMASCRIPT_ENVIRONMENT_CONSTANT_POOL_OFFSET(%rax) 169 170 // Store lexical env to iframe 171 movq JSFUNCTION_LEXICAL_ENV_OFFSET(%r14), %r15 172 movq %r15, ECMASCRIPT_ENVIRONMENT_LEXICAL_ENV_OFFSET(%rax) 173 174 // Store this func to iframe 175 movq %r14, ECMASCRIPT_ENVIRONMENT_THIS_FUNC_OFFSET(%rax) 176#endif 177 178 // call InterpreterEntryPoint 179 movq %r12, %rsi 180 // void InterpreterEntryPoint(Method *method, Frame* frame); 181 callq InterpreterEntryPoint@plt 182 183 // handle the result 184 // setup regs as follows 185 // %r12 - iframe* 186 // %r13/%r14 - result 187 leaq FRAME_ACC_OFFSET(%r12), %rax 188 movq (%rax), %r13 189 movq FRAME_ACC_MIRROR_OFFSET(%rax), %r14 190 191 movq %r12, %rdi 192 // void FreeFrame(Frame* frame); 193 callq FreeFrame@plt 194 195 movq %r13, %rax 196 movq %r14, %rdx 197 198 leaq -48(%rbp), %rsp 199 popq %rbx 200 CFI_RESTORE(rbx) 201 popq %r12 202 CFI_RESTORE(r12) 203 popq %r13 204 CFI_RESTORE(r13) 205 popq %r14 206 CFI_RESTORE(r14) 207 popq %r15 208 CFI_RESTORE(r15) 209 addq $8, %rsp 210 211 popq %rbp 212 CFI_RESTORE(rbp) 213 CFI_DEF_CFA(rsp, (2 * 8)) 214 addq $8, %rsp 215 CFI_ADJUST_CFA_OFFSET(-(1 * 8)) 216 retq 217 CFI_ENDPROC 218