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/shorty.S" 18#include "shorty_values.h" 19 20#define SHORTY_PTR_REG DEFAULT_SHORTY_PTR_REG 21#define SHORTY_REG DEFAULT_SHORTY_REG 22 23#include "arch/amd64/helpers_amd64.S" 24 25// Frame* CreateFrameForMethod(Method* method, Frame* prev); 26.extern CreateFrameForMethod 27// void InterpreterEntryPoint(const uint8_t* pc, Frame* frame); 28.extern InterpreterEntryPoint 29 30.extern DecrementHotnessCounter 31 32.global CompiledCodeToInterpreterBridge 33TYPE_FUNCTION(CompiledCodeToInterpreterBridge) 34CompiledCodeToInterpreterBridge: 35 CFI_STARTPROC 36 CFI_DEF_CFA(rsp, 8) 37 38 // Save return address to the TLS field 39 movq (%rsp), %rax 40 movq %rax, MANAGED_THREAD_NATIVE_PC_OFFSET(%THREAD_REG) 41 42 pushq $COMPILED_CODE_TO_INTERPRETER_BRIDGE 43 CFI_ADJUST_CFA_OFFSET(8) 44 45 // construct the frame 46 pushq %rbp 47 CFI_ADJUST_CFA_OFFSET(8) 48 CFI_REL_OFFSET(rbp, 0) 49 movq %rsp, %rbp // set frame pointer 50 CFI_DEF_CFA_REGISTER(rbp) 51 52 subq $8, %rsp 53 54 // save all the callee saved registers to the stack 55 // stack walker will read them during stack unwinding 56 pushq %r15 57 CFI_REL_OFFSET(r15, -(2 * 8)) 58 pushq %r14 59 CFI_REL_OFFSET(r14, -(3 * 8)) 60 pushq %r13 61 CFI_REL_OFFSET(r13, -(4 * 8)) 62 pushq %r12 63 CFI_REL_OFFSET(r12, -(5 * 8)) 64 pushq %rbx 65 CFI_REL_OFFSET(rbx, -(6 * 8)) 66 67 subq $8, %rsp 68 69 // Before we call DecrementHotnessCounter we should set pointer to C2I frame in the TLS, 70 // because compilation may fall into safepoint, so we need to make caller's callee registers 71 // visible for the stack walker. 72 movq %rbp, MANAGED_THREAD_FRAME_OFFSET(%THREAD_REG) 73 74 PUSH_GENERAL_REGS 75 PUSH_FP_REGS 76 77 movq %THREAD_REG, %rsi 78 callq DecrementHotnessCounter@plt 79 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_FP_REGS 88 POP_GENERAL_REGS 89 90 movq %rbp, %rsp 91 addq $16, %rsp 92 movq (%rbp), %rbp 93 CFI_REMEMBER_STATE 94 CFI_RESTORE(rbp) 95 CFI_DEF_CFA(rsp, 8) 96 97 movq METHOD_COMPILED_ENTRY_POINT_OFFSET(%rdi), %rax 98 jmp *%rax 99 CFI_RESTORE_STATE 100 CFI_DEF_CFA(rbp, (3 * 8)) 101 102.Lnot_compiled: 103 104 POP_FP_REGS 105 POP_GENERAL_REGS 106 107 // save arguments to the stack 108 PUSH_FP_REGS 109 PUSH_GENERAL_REGS 110 111 // %rsp % 16 == 0 here 112 113 movq %rdi, %rbx // save method to survive the call 114 115 // create an interpreter frame 116 movq %rbx, %rdi 117 movq %rbp, %rsi 118 callq CreateFrameForMethod@plt 119 movq %rax, %r13 120 121 // setup regs as follow 122 // %rax - SHORTY_PTR_REG, %r10d - SHORTY_REG, %r12 - iframe.vregs_ + num_vregs_, 123 // %rdx - gpr args, %rsi - float args, %rdi - stack args, %r8d - gpr arg counter, 124 // %r9d - float arg counter, %rcx, %r15 - temp, %r13 - iframe, %rbx - method, 125 // %r14 - method.shorty 126 movq METHOD_SHORTY_OFFSET(%rbx), %r14 127 movl FRAME_NUM_VREGS_OFFSET(%r13), %r12d 128 subl METHOD_NUM_ARGS_OFFSET(%rbx), %r12d 129 shlq $3, %r12 130 leaq FRAME_VREGS_OFFSET(%r13, %r12), %r12 131 leaq 8(%rsp), %rdx // skip Method* 132 leaq 48(%rsp), %rsi 133 leaq 24(%rbp), %rdi 134 movl $5, %r8d // 5 because we skip Method* arg 135 movl $8, %r9d 136 137 movq %r14, %rax 138 INIT_SHORTY_REG 139 140 // parameter 'this' of instance methods is not encoded in the shorty 141 // in case of instance method hack SHORTY_REG by replacing the return type by REF 142 // in the another case just skip the return type 143 144 // check whether the method is an instance 145 movl METHOD_ACCESS_FLAGS_OFFSET(%rbx), %ecx 146 testl $ACCESS_STATIC, %ecx 147 jne 1f 148 149 // it is an instance method 150 // replace the return type by REF 151 andl $0xFFFFFFF0, %SHORTY_REG // clear the least significant 4 bits 152 orl $SHORTY_REFERENCE, %SHORTY_REG 153 jmp .Lloop_copy_args 154 1551: 156 SKIP_SHORTY 157 158 // fill in the iframe 159.Lloop_copy_args: 160 NEXT_SHORTY %r11d 161 cmpl $0, %r11d 162 je .Lloopend_copy_args 163 164 // store the tag 165 xorq %rcx, %rcx 166 cmpl $SHORTY_REFERENCE, %r11d 167 sete %cl 168 movl FRAME_NUM_VREGS_OFFSET(%r13), %r15d 169 movq %rcx, (%r12, %r15, 8) 170 171 subl $SHORTY_FIRST_FLOAT, %r11d 172 cmpl $(SHORTY_NUM_FLOAT_TYPES - 1), %r11d 173 jbe 1f 174 175 // it is an int value or reference 176 cmpl $0, %r8d 177 je 2f 178 179 // the arg in a gpr 180 movq (%rdx), %r15 181 addq $8, %rdx 182 subl $1, %r8d 183 jmp 3f 1841: 185 // it is a float value 186 cmpl $0, %r9d 187 je 2f 188 189 // the arg in a float reg 190 movq (%rsi), %r15 191 addq $8, %rsi 192 subl $1, %r9d 193 jmp 3f 1942: 195 // it is a stack arg 196 movq (%rdi), %r15 197 addq $8, %rdi 1983: 199 movq %r15, (%r12) 200 addq $FRAME_VREGISTER_SIZE, %r12 201 jmp .Lloop_copy_args 202.Lloopend_copy_args: 203 204 // call InterpreterEntryPoint 205 movq %rbx, %rdi 206 movq %r13, %rsi 207 callq InterpreterEntryPoint@plt 208 209 // handle the result 210 // setup regs as follow 211 // %rdi - iframe, %r14d - *method.shorty, %rax - &iframe.acc_ 212 // %r12, %r13 - result 213 movq %r13, %rdi 214 leaq FRAME_ACC_OFFSET(%r13), %rax 215 movl (%r14), %r14d 216 andl $0xF, %r14d 217 218 cmpl $SHORTY_VOID, %r14d 219 jne 1f 220 221 // void method 222 callq FreeFrame@plt 223 jmp 4f 2241: 225 movq (%rax), %r12 226 movq FRAME_ACC_MIRROR_OFFSET(%rax), %r13 227 cmpl $SHORTY_REFERENCE, %r14d 228 jne 2f 229 // Result is a reference 230 callq FreeFrame@plt 231 // Clear the upper 32 bits, since the compiler may 232 // generate code that uses them 233 movl %r12d, %eax 234 movq %r13, %rdx 235 jmp 4f 2362: 237 subl $SHORTY_FIRST_FLOAT, %r14d 238 cmpl $(SHORTY_NUM_FLOAT_TYPES - 1), %r14d 239 jbe 3f 240 // result is an integer value 241 callq FreeFrame@plt 242 movq %r12, %rax 243 movq %r13, %rdx 244 jmp 4f 2453: 246 // result is a float value 247 callq FreeFrame@plt 248 movq %r12, %xmm0 2494: 250 leaq -48(%rbp), %rsp 251 popq %rbx 252 CFI_RESTORE(rbx) 253 popq %r12 254 CFI_RESTORE(r12) 255 popq %r13 256 CFI_RESTORE(r13) 257 popq %r14 258 CFI_RESTORE(r14) 259 popq %r15 260 CFI_RESTORE(r15) 261 addq $8, %rsp 262 popq %rbp 263 CFI_RESTORE(rbp) 264 CFI_DEF_CFA(rsp, (2 * 8)) 265 addq $8, %rsp 266 CFI_ADJUST_CFA_OFFSET(-(1 * 8)) 267 retq 268 CFI_ENDPROC 269