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/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 IncrementHotnessCounter 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 IncrementHotnessCounter 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 callq IncrementHotnessCounter@plt 78 79 cmpb $0, %al 80 je .Lnot_compiled 81 82 // Compilation successfully done, so recover caller's frame in the TLS, since C2I is not needed. 83 movq (%rbp), %r8 84 movq %r8, MANAGED_THREAD_FRAME_OFFSET(%THREAD_REG) 85 86 POP_FP_REGS 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 103 POP_FP_REGS 104 POP_GENERAL_REGS 105 106 // save arguments to the stack 107 PUSH_FP_REGS 108 PUSH_GENERAL_REGS 109 110 // %rsp % 16 == 0 here 111 112 movq %rdi, %rbx // save method to survive the call 113 114 // create an interpreter frame 115 movq %rbx, %rdi 116 movq %rbp, %rsi 117 callq CreateFrameForMethod@plt 118 movq %rax, %r13 119 120 // setup regs as follow 121 // %rax - SHORTY_PTR_REG, %r10d - SHORTY_REG, %r12 - iframe.vregs_ + num_vregs_, 122 // %rdx - gpr args, %rsi - float args, %rdi - stack args, %r8d - gpr arg counter, 123 // %r9d - float arg counter, %rcx, %r15 - temp, %r13 - iframe, %rbx - method, 124 // %r14 - method.shorty 125 movq METHOD_SHORTY_OFFSET(%rbx), %r14 126 movl FRAME_NUM_VREGS_OFFSET(%r13), %r12d 127 subl METHOD_NUM_ARGS_OFFSET(%rbx), %r12d 128 shlq $3, %r12 129 leaq FRAME_VREGS_OFFSET(%r13, %r12), %r12 130 leaq 8(%rsp), %rdx // skip Method* 131 leaq 48(%rsp), %rsi 132 leaq 24(%rbp), %rdi 133 movl $5, %r8d // 5 because we skip Method* arg 134 movl $8, %r9d 135 136 movq %r14, %rax 137 INIT_SHORTY_REG 138 139 // parameter 'this' of instance methods is not encoded in the shorty 140 // in case of instance method hack SHORTY_REG by replacing the return type by REF 141 // in the another case just skip the return type 142 143 // check whether the method is an instance 144 movl METHOD_ACCESS_FLAGS_OFFSET(%rbx), %ecx 145 testl $ACCESS_STATIC, %ecx 146 jne 1f 147 148 // it is an instance method 149 // replace the return type by REF 150 andl $0xFFFFFFF0, %SHORTY_REG // clear the least significant 4 bits 151 orl $SHORTY_REFERENCE, %SHORTY_REG 152 jmp .Lloop_copy_args 153 1541: 155 SKIP_SHORTY 156 157 // fill in the iframe 158.Lloop_copy_args: 159 NEXT_SHORTY %r11d 160 cmpl $0, %r11d 161 je .Lloopend_copy_args 162 163 // store the tag 164 xorq %rcx, %rcx 165 cmpl $SHORTY_REFERENCE, %r11d 166 sete %cl 167 movl FRAME_NUM_VREGS_OFFSET(%r13), %r15d 168 movq %rcx, (%r12, %r15, 8) 169 170 subl $SHORTY_FIRST_FLOAT, %r11d 171 cmpl $(SHORTY_NUM_FLOAT_TYPES - 1), %r11d 172 jbe 1f 173 174 // it is an int value or reference 175 cmpl $0, %r8d 176 je 2f 177 178 // the arg in a gpr 179 movq (%rdx), %r15 180 addq $8, %rdx 181 subl $1, %r8d 182 jmp 3f 1831: 184 // it is a float value 185 cmpl $0, %r9d 186 je 2f 187 188 // the arg in a float reg 189 movq (%rsi), %r15 190 addq $8, %rsi 191 subl $1, %r9d 192 jmp 3f 1932: 194 // it is a stack arg 195 movq (%rdi), %r15 196 addq $8, %rdi 1973: 198 movq %r15, (%r12) 199 addq $FRAME_VREGISTER_SIZE, %r12 200 jmp .Lloop_copy_args 201.Lloopend_copy_args: 202 203 // call InterpreterEntryPoint 204 movq %rbx, %rdi 205 movq %r13, %rsi 206 callq InterpreterEntryPoint@plt 207 208 // handle the result 209 // setup regs as follow 210 // %rdi - iframe, %r14d - *method.shorty, %rax - &iframe.acc_ 211 // %r12, %r13 - result 212 movq %r13, %rdi 213 leaq FRAME_ACC_OFFSET(%r13), %rax 214 movl (%r14), %r14d 215 andl $0xF, %r14d 216 217 cmpl $SHORTY_VOID, %r14d 218 jne 1f 219 220 // void method 221 callq FreeFrame@plt 222 jmp 3f 2231: 224 movq (%rax), %r12 225 movq FRAME_ACC_MIRROR_OFFSET(%rax), %r13 226 subl $SHORTY_FIRST_FLOAT, %r14d 227 cmpl $(SHORTY_NUM_FLOAT_TYPES - 1), %r14d 228 jbe 2f 229 230 // result is an integer or reference value 231 callq FreeFrame@plt 232 movq %r12, %rax 233 movq %r13, %rdx 234 jmp 3f 2352: 236 // result is a float value 237 callq FreeFrame@plt 238 movq %r12, %xmm0 2393: 240 leaq -48(%rbp), %rsp 241 popq %rbx 242 CFI_RESTORE(rbx) 243 popq %r12 244 CFI_RESTORE(r12) 245 popq %r13 246 CFI_RESTORE(r13) 247 popq %r14 248 CFI_RESTORE(r14) 249 popq %r15 250 CFI_RESTORE(r15) 251 addq $8, %rsp 252 popq %rbp 253 CFI_RESTORE(rbp) 254 CFI_DEF_CFA(rsp, (2 * 8)) 255 addq $8, %rsp 256 CFI_ADJUST_CFA_OFFSET(-(1 * 8)) 257 retq 258 CFI_ENDPROC 259