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 18.extern InvokeInterpreter 19 20.global DeoptimizeAfterCFrame 21.type DeoptimizeAfterCFrame, %function 22DeoptimizeAfterCFrame: 23 CFI_STARTPROC 24 25 // Parameters: 26 // %rdi - thread 27 // %rsi - pc of the entry 28 // %rdx - pointer to interpreter Frame 29 // %rcx - pointer to cframe origin 30 // %r8 - last restored interpreter Frame 31 // %r9 - callee reg_mask 32 // 8(%rsp) - callee vreg_mask 33 34 // Morph CFrame into C2I bridge frame 35 // FROM TO 36 // lr lr 37 // fp <---- COMPILED_CODE_TO_INTERPRETER_BRIDGE 38 // method fp <---- 39 40 CFI_DEF_CFA(rcx, (2 * 8)) 41 CFI_REL_OFFSET(rbp, 0) 42 CFI_REL_OFFSET(THREAD_REG, -((CFRAME_CALLEE_REGS_START_SLOT + 0) * 8)) 43 CFI_REL_OFFSET(r14, -((CFRAME_CALLEE_REGS_START_SLOT + 1) * 8)) 44 CFI_REL_OFFSET(r13, -((CFRAME_CALLEE_REGS_START_SLOT + 2) * 8)) 45 CFI_REL_OFFSET(r12, -((CFRAME_CALLEE_REGS_START_SLOT + 3) * 8)) 46 CFI_REL_OFFSET(rbx, -((CFRAME_CALLEE_REGS_START_SLOT + 4) * 8)) 47 48 leaq -(((CFRAME_HEADER_SIZE - 2) * 8) + CALLEE_SAVED_SIZE)(%rcx), %rsp 49 // Additional padding to save lr to origin place 50 movq (%rcx), %r12 51 movq %r12, (-8)(%rcx) 52 53 subq $8, %rcx 54 CFI_ADJUST_CFA_OFFSET(8) 55 CFI_REL_OFFSET(rbp, 0) 56 57 movq %rcx, %rbp 58 CFI_DEF_CFA_REGISTER(rbp) 59 60 movq $COMPILED_CODE_TO_INTERPRETER_BRIDGE, (INT_METHOD_OFFSET * 8)(%rcx) 61 62 // Set IFrame's prev_frame to this C2I bridge frame 63 movq %rcx, FRAME_PREV_FRAME_OFFSET(%r8) 64 65 BOUNDARY_FRAME_SLOT = ((CFRAME_HEADER_SIZE - 3) + 1) 66 67 // Copy callee saved registers from cframe into boundary frame. 68 leaq -((CFRAME_CALLEE_REGS_START_SLOT - 1) * 8)(%rcx), %r12 69 leaq -(BOUNDARY_FRAME_SLOT * 8)(%rcx), %r13 70 71 movq (%r12), %rbx 72 movq %rbx, (%r13) 73 CFI_REL_OFFSET(THREAD_REG, -((BOUNDARY_FRAME_SLOT + 0) * 8)) 74 movq -8(%r12), %rbx 75 movq %rbx, -8(%r13) 76 CFI_REL_OFFSET(r14, -((BOUNDARY_FRAME_SLOT + 1) * 8)) 77 movq -16(%r12), %rbx 78 movq %rbx, -16(%r13) 79 CFI_REL_OFFSET(r13, -((BOUNDARY_FRAME_SLOT + 2) * 8)) 80 movq -24(%r12), %rbx 81 movq %rbx, -24(%r13) 82 CFI_REL_OFFSET(r12, -((BOUNDARY_FRAME_SLOT + 3) * 8)) 83 movq -32(%r12), %rbx 84 movq %rbx, -32(%r13) 85 CFI_REL_OFFSET(rbx, -((BOUNDARY_FRAME_SLOT + 4) * 8)) 86 87 // Save used registers 88 pushq %r8 89 pushq %rcx 90 pushq %rdx 91 pushq %rsi 92 pushq %rdi 93 94 movq %r8, %rcx 95 // Arguments are already lie in the registers, because signature of DeoptimizeAfterCFrame is similar to InvokeInterpreter 96 callq InvokeInterpreter@plt 97 movq %rax, %xmm0 98 99 // Restore used registers 100 popq %rdi 101 popq %rsi 102 popq %rdx 103 popq %rcx 104 popq %r8 105 106 // Restore stack pointer 107 movq %rcx, %rsp 108 109 // Restore callee saved registers 110 subq $(BOUNDARY_FRAME_SLOT * 8), %rcx 111 movq (%rcx), %THREAD_REG 112 movq -8(%rcx), %r14 113 CFI_RESTORE(r14) 114 movq -16(%rcx), %r13 115 CFI_RESTORE(r13) 116 movq -24(%rcx), %r12 117 CFI_RESTORE(r12) 118 movq -32(%rcx), %rbx 119 CFI_RESTORE(rbx) 120 121 // Restore thread register 122 movq %rdi, %THREAD_REG 123 CFI_RESTORE(THREAD_REG) 124 125 popq %rbp 126 CFI_RESTORE(rbp) 127 CFI_DEF_CFA(rsp, (2 * 8)) 128 addq $8, %rsp 129 CFI_ADJUST_CFA_OFFSET(-(1 * 8)) 130 retq 131 CFI_ENDPROC 132 133.global DeoptimizeAfterIFrame 134.type DeoptimizeAfterIFrame, %function 135DeoptimizeAfterIFrame: 136 CFI_STARTPROC 137 138 // Parameters: 139 // %rdi - thread 140 // %rsi - pc of the entry 141 // %rdx - pointer to interpreter Frame 142 // %rcx - pointer to cframe origin 143 // %r8 - last restored interpreter Frame 144 145 CFI_DEF_CFA(rcx, (2 * 8)) 146 CFI_REL_OFFSET(rbp, 0) 147 CFI_REL_OFFSET(r15, -((CFRAME_CALLEE_REGS_START_SLOT + 0) * 8)) 148 CFI_REL_OFFSET(r14, -((CFRAME_CALLEE_REGS_START_SLOT + 1) * 8)) 149 CFI_REL_OFFSET(r13, -((CFRAME_CALLEE_REGS_START_SLOT + 2) * 8)) 150 CFI_REL_OFFSET(r12, -((CFRAME_CALLEE_REGS_START_SLOT + 3) * 8)) 151 CFI_REL_OFFSET(rbx, -((CFRAME_CALLEE_REGS_START_SLOT + 4) * 8)) 152 153 movq %rcx, %rbp 154 CFI_DEF_CFA_REGISTER(rbp) 155 156 // Restore stack pointer to the fp pointer of the cframe 157 movq %rcx, %rsp 158 159 // Restore callee saved registers 160 subq $(CFRAME_CALLEE_REGS_START_SLOT * 8), %rcx 161 movq (%rcx), %r15 162 CFI_RESTORE(r15) 163 movq -8(%rcx), %r14 164 CFI_RESTORE(r14) 165 movq -16(%rcx), %r13 166 CFI_RESTORE(r13) 167 movq -24(%rcx), %r12 168 CFI_RESTORE(r12) 169 movq -32(%rcx), %rbx 170 CFI_RESTORE(rbx) 171 172 movq %r8, %rcx 173 callq InvokeInterpreter@plt 174 // InvokeInterpreter returns int64 value, but result can be double, so we copy value to vector register 175 movq %rax, %xmm0 176 177 popq %rbp 178 CFI_RESTORE(rbp) 179 CFI_DEF_CFA(rsp, (1 * 8)) 180 retq 181 CFI_ENDPROC 182 183.global DropCompiledFrameAndReturn 184.type DropCompiledFrameAndReturn, %function 185DropCompiledFrameAndReturn: 186 CFI_STARTPROC 187 188 // %rdi - pointer to cframe origin 189 190 CFI_DEF_CFA(rdi, (2 * 8)) 191 CFI_REL_OFFSET(rbp, 0) 192 CFI_REL_OFFSET(r15, -((CFRAME_CALLEE_REGS_START_SLOT + 0) * 8)) 193 CFI_REL_OFFSET(r14, -((CFRAME_CALLEE_REGS_START_SLOT + 1) * 8)) 194 CFI_REL_OFFSET(r13, -((CFRAME_CALLEE_REGS_START_SLOT + 2) * 8)) 195 CFI_REL_OFFSET(r12, -((CFRAME_CALLEE_REGS_START_SLOT + 3) * 8)) 196 CFI_REL_OFFSET(rbx, -((CFRAME_CALLEE_REGS_START_SLOT + 4) * 8)) 197 198 movq %rdi, %rbp 199 CFI_DEF_CFA_REGISTER(rbp) 200 movq %rdi, %rsp 201 202 // Restore callee saved registers from dropped CFrame 203 subq $(CFRAME_CALLEE_REGS_START_SLOT * 8), %rdi 204 movq (%rdi), %r15 205 CFI_RESTORE(r15) 206 movq -8(%rdi), %r14 207 CFI_RESTORE(r14) 208 movq -16(%rdi), %r13 209 CFI_RESTORE(r13) 210 movq -24(%rdi), %r12 211 CFI_RESTORE(r12) 212 movq -32(%rdi), %rbx 213 CFI_RESTORE(rbx) 214 215 // We need to clear return value, since it will be written to the IFrame's accumulator. Without this, it holds 216 // garbage and StackWalker verification might fail. 217 xorq %rax, %rax 218 219 popq %rbp 220 CFI_RESTORE(rbp) 221 CFI_DEF_CFA(rsp, (1 * 8)) 222 retq 223 CFI_ENDPROC 224