1/** 2 * Copyright (c) 2021-2022 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 IncrementHotnessCounter(Method* method, bool is_dynamic); 26.extern IncrementHotnessCounter 27// DecodedTaggedValue GetInitialTaggedValue(Method*) 28.extern GetInitialTaggedValue 29 30// CompiledCodeToInterpreterBridgeDyn(Method* method, uint32_t num_args, int64_t func_obj, int64_t func_tag, int64_t arg_i, int64_t tag_i, ...) 31.global CompiledCodeToInterpreterBridgeDyn 32TYPE_FUNCTION(CompiledCodeToInterpreterBridgeDyn) 33CompiledCodeToInterpreterBridgeDyn: 34 CFI_STARTPROC 35 CFI_DEF_CFA(rsp, 8) 36 37 // method: %rdi 38 // num_args: %rsi 39 // func_obj: %rdx 40 // arg_0: %r8 41 // arg_i: 8*i(%rbp) 42 // tag_i: 8*(i+1)(%rbp) 43 44 // Save return address to the TLS field 45 movq (%rsp), %rax 46 movq %rax, MANAGED_THREAD_NATIVE_PC_OFFSET(%THREAD_REG) 47 48 pushq $COMPILED_CODE_TO_INTERPRETER_BRIDGE 49 CFI_ADJUST_CFA_OFFSET(8) 50 51 // construct the frame 52 pushq %rbp 53 CFI_ADJUST_CFA_OFFSET(8) 54 CFI_REL_OFFSET(rbp, 0) 55 movq %rsp, %rbp // set frame pointer 56 CFI_DEF_CFA_REGISTER(rbp) 57 58 subq $8, %rsp 59 60 // save all the callee saved registers to the stack 61 // stack walker will read them during stack unwinding 62 pushq %r15 63 CFI_REL_OFFSET(r15, -(2 * 8)) 64 pushq %r14 65 CFI_REL_OFFSET(r14, -(3 * 8)) 66 pushq %r13 67 CFI_REL_OFFSET(r13, -(4 * 8)) 68 pushq %r12 69 CFI_REL_OFFSET(r12, -(5 * 8)) 70 pushq %rbx 71 CFI_REL_OFFSET(rbx, -(6 * 8)) 72 73 subq $8, %rsp 74 75 // Before we call IncrementHotnessCounter we should set pointer to C2I frame in the TLS, 76 // because compilation may fall into safepoint, so we need to make caller's callee registers 77 // visible for the stack walker. 78 movq %rbp, MANAGED_THREAD_FRAME_OFFSET(%THREAD_REG) 79 80 PUSH_GENERAL_REGS 81 82 callq IncrementHotnessCounter@plt 83 cmpb $0, %al 84 je .Lnot_compiled 85 86 // Compilation successfully done, so recover caller's frame in the TLS, since C2I is not needed. 87 movq (%rbp), %r8 88 movq %r8, MANAGED_THREAD_FRAME_OFFSET(%THREAD_REG) 89 90 POP_GENERAL_REGS 91 92 movq %rbp, %rsp 93 addq $16, %rsp 94 movq (%rbp), %rbp 95 CFI_REMEMBER_STATE 96 CFI_RESTORE(rbp) 97 CFI_DEF_CFA(rsp, 8) 98 99 movq METHOD_COMPILED_ENTRY_POINT_OFFSET(%rdi), %rax 100 jmp *%rax 101 CFI_RESTORE_STATE 102 CFI_DEF_CFA(rbp, (3 * 8)) 103 104.Lnot_compiled: 105 106 POP_GENERAL_REGS 107 108 // save arguments to the stack 109 PUSH_GENERAL_REGS 110 111 // %rsp % 16 == 0 here 112 113 // save method* before call 114 movq %rdi, %r14 115 116 // create an interpreter frame 117 movq %rsi, %rdi 118 addq $1, %rdi // count function object 119 // get num args in r15d 120 // num_args = max(num_args, method->num_args_) 121 movl METHOD_NUM_ARGS_OFFSET(%r14), %r15d 122 cmpl %r15d, %edi 123 cmovge %edi, %r15d 124 // get number of rest arguments in r13 125 movl %r15d, %r13d 126 subl %edi, %r13d 127 128 movq %r14, %rsi 129 leaq (%rbp), %rdx 130 // Frame* CreateFrameForMethodWithActualArgsDyn(uint32_t num_actual_args, Method* method, Frame* prev); 131 callq CreateFrameForMethodWithActualArgsDyn@plt 132 movq %rax, %r12 // iframe* 133 134 POP_GENERAL_REGS 135 136 // setup regs as follow 137 // %rax - iframe.vregs_ + num_vregs_ 138 // %rdi - stack args 139 // %rsi - num args 140 // %rdx - func obj 141 // %r8 - arg0 142 // %rbx - method* 143 // %r12 - iframe* 144 // %r13 - num of rest arguments 145 movl FRAME_NUM_VREGS_OFFSET(%rax), %ebx 146 subl %r15d, %ebx 147 shll $3, %ebx 148 leaq FRAME_VREGS_OFFSET(%r12,%rbx), %rax 149 movq %rdi, %rbx // method* 150 leaq 24(%rbp), %rdi 151 152 movq %rdx, (%rax) 153 addq $FRAME_VREGISTER_SIZE, %rax 154 cmpl $0, %esi 155 je .Lrest_args 156 157 movq %r8, (%rax) 158 addq $FRAME_VREGISTER_SIZE, %rax 159 subl $1, %esi 160 je .Lrest_args 161 162.Lloop: 163 movq (%rdi), %rdx 164 addq $FRAME_VREGISTER_SIZE, %rdi 165 166 movq %rdx, (%rax) 167 addq $FRAME_VREGISTER_SIZE, %rax 168 169 subl $1, %esi 170 ja .Lloop 171 172.Lrest_args: 173 // mov rax to r14 to survive the call 174 movq %rax, %r14 175 // set the first arg Method* 176 movq %rbx, %rdi 177 callq GetInitialTaggedValue@plt 178 179 // setup regs as follow 180 // rax / rdx - initial value / tag 181 // %rbx - method* 182 // %r12 - iframe 183 // %r13 - num rest args 184 // %r14 - pointer to the current arg vreg 185 1861: // fill in the reset args 187 test %r13, %r13 188 je .Lcall_interpreter 189 movq %rax, (%r14) 190 addq $FRAME_VREGISTER_SIZE, %r14 191 subl $1, %r13d 192 jmp 1b 193 194.Lcall_interpreter: 195 // call InterpreterEntryPoint 196 movq %rbx, %rdi 197 movq %r12, %rsi 198 // void InterpreterEntryPoint(Method *method, Frame* frame); 199 callq InterpreterEntryPoint@plt 200 201 // handle the result 202 // setup regs as follow 203 // %rax - &iframe.acc_ 204 // %r12 - iframe* 205 // %r13/%r14 - result 206 leaq FRAME_ACC_OFFSET(%r12), %rax 207 208 movq (%rax), %r13 209 movq FRAME_ACC_MIRROR_OFFSET(%rax), %r14 210 211 movq %r12, %rdi 212 // void FreeFrame(Frame* frame); 213 callq FreeFrame@plt 214 215 movq %r13, %rax 216 movq %r14, %rdx 217 218 leaq -48(%rbp), %rsp 219 popq %rbx 220 CFI_RESTORE(rbx) 221 popq %r12 222 CFI_RESTORE(r12) 223 popq %r13 224 CFI_RESTORE(r13) 225 popq %r14 226 CFI_RESTORE(r14) 227 popq %r15 228 CFI_RESTORE(r15) 229 addq $8, %rsp 230 popq %rbp 231 CFI_RESTORE(rbp) 232 CFI_DEF_CFA(rsp, (2 * 8)) 233 addq $8, %rsp 234 CFI_ADJUST_CFA_OFFSET(-(1 * 8)) 235 retq 236 CFI_ENDPROC 237