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/aarch64/helpers_aarch64.S" 18#include "shorty_values.h" 19 20.extern InvokeInterpreter 21 22.macro CFRAME_COPY_LR fpreg 23 ldr lr, [\fpreg, #(-CFRAME_FLAGS_SLOT * 8)] 24 tst lr, #CFRAME_KIND_OSR 25 beq 1f 26 ldr lr, [\fpreg, #(-(CFRAME_LOCALS_START_SLOT + 2) * 8)] 27 str lr, [\fpreg, #(-CFRAME_LR_SLOT * 8)] 281: 29.endm 30 31.macro CFRAME_GET_LR fpreg 32 ldr lr, [\fpreg, #(-CFRAME_FLAGS_SLOT * 8)] 33 tst lr, #CFRAME_KIND_OSR 34 bne 1f 35 ldr lr, [\fpreg, #(-CFRAME_LR_SLOT * 8)] 36 b 2f 371: 38 ldr lr, [\fpreg, #(-(CFRAME_LOCALS_START_SLOT + 2) * 8)] 392: 40.endm 41 42.macro RESTORE_CALLEE_REGISTERS basereg 43 ldp x27, x28, [\basereg, #-16]! 44 ldp x25, x26, [\basereg, #-16]! 45 ldp x23, x24, [\basereg, #-16]! 46 ldp x21, x22, [\basereg, #-16]! 47 ldp x19, x20, [\basereg, #-16]! 48 ldp d14, d15, [\basereg, #-16]! 49 ldp d12, d13, [\basereg, #-16]! 50 ldp d10, d11, [\basereg, #-16]! 51 ldp d8, d9, [\basereg, #-16]! 52.endm 53 54// ============================================================================ 55 56.global DeoptimizeAfterCFrame 57.type DeoptimizeAfterCFrame, %function 58DeoptimizeAfterCFrame: 59 CFI_STARTPROC 60 61 // Parameters: 62 // x0 - thread 63 // x1 - pc of the entry 64 // x2 - pointer to interpreter Frame 65 // x3 - pointer to cframe origin 66 // x4 - last restored interpreter Frame 67 // x5 - pointer to a callee-saved registers buffer from StackWalker 68 69 CFI_DEF_CFA(x3, (2 * 8)) 70 CFI_REL_OFFSET(lr, 8) 71 CFI_REL_OFFSET(fp, 0) 72 CFI_REL_OFFSET(x28, -((CFRAME_CALLEE_REGS_START_SLOT + 0) * 8)) 73 CFI_REL_OFFSET(x27, -((CFRAME_CALLEE_REGS_START_SLOT + 1) * 8)) 74 CFI_REL_OFFSET(x26, -((CFRAME_CALLEE_REGS_START_SLOT + 2) * 8)) 75 CFI_REL_OFFSET(x25, -((CFRAME_CALLEE_REGS_START_SLOT + 3) * 8)) 76 CFI_REL_OFFSET(x24, -((CFRAME_CALLEE_REGS_START_SLOT + 4) * 8)) 77 CFI_REL_OFFSET(x23, -((CFRAME_CALLEE_REGS_START_SLOT + 5) * 8)) 78 CFI_REL_OFFSET(x22, -((CFRAME_CALLEE_REGS_START_SLOT + 6) * 8)) 79 CFI_REL_OFFSET(x21, -((CFRAME_CALLEE_REGS_START_SLOT + 7) * 8)) 80 CFI_REL_OFFSET(x20, -((CFRAME_CALLEE_REGS_START_SLOT + 8) * 8)) 81 CFI_REL_OFFSET(x19, -((CFRAME_CALLEE_REGS_START_SLOT + 9) * 8)) 82 CFI_REL_OFFSET(d15, -((CFRAME_CALLEE_REGS_START_SLOT + 10) * 8)) 83 CFI_REL_OFFSET(d14, -((CFRAME_CALLEE_REGS_START_SLOT + 11) * 8)) 84 CFI_REL_OFFSET(d13, -((CFRAME_CALLEE_REGS_START_SLOT + 12) * 8)) 85 CFI_REL_OFFSET(d12, -((CFRAME_CALLEE_REGS_START_SLOT + 13) * 8)) 86 CFI_REL_OFFSET(d11, -((CFRAME_CALLEE_REGS_START_SLOT + 14) * 8)) 87 CFI_REL_OFFSET(d10, -((CFRAME_CALLEE_REGS_START_SLOT + 15) * 8)) 88 CFI_REL_OFFSET(d9, -((CFRAME_CALLEE_REGS_START_SLOT + 16) * 8)) 89 CFI_REL_OFFSET(d8, -((CFRAME_CALLEE_REGS_START_SLOT + 17) * 8)) 90 91 // Morph CFrame into C2I bridge frame 92 // FROM TO 93 // lr lr 94 // fp <---- COMPILED_CODE_TO_INTERPRETER_BRIDGE 95 // method fp <---- 96 sub sp, x3, #(((CFRAME_HEADER_SIZE - 2) * 8) + CALLEE_SAVED_SIZE) 97 ldr x7, [x3] 98 mov x8, #COMPILED_CODE_TO_INTERPRETER_BRIDGE 99 stp x7, x8, [x3, #-8]! 100 CFI_ADJUST_CFA_OFFSET(8) 101 CFI_REL_OFFSET(fp, 0) 102 103 mov fp, x3 104 CFI_DEF_CFA_REGISTER(fp) 105 106 // Set last IFrame's prev_frame to this C2I bridge frame 107 str x3, [x4, #FRAME_PREV_FRAME_OFFSET] 108 109 BOUNDARY_FRAME_SLOT = ((CFRAME_HEADER_SIZE - 3) + 1) 110 111 // Copy callee saved registers from StackWalker into boundary frame. 112 // Note, we do not preserve x5 (holding a pointer to a callee-saved 113 // registers buffer from StackWalker) as it is not needed later on. 114 sub x17, x3, #((BOUNDARY_FRAME_SLOT - 1) * 8) 115 ldp x14, x15, [x5, #-16]! 116 stp x14, x15, [x17, #-16]! 117 CFI_REL_OFFSET(x28, -((BOUNDARY_FRAME_SLOT + 0) * 8)) 118 CFI_REL_OFFSET(x27, -((BOUNDARY_FRAME_SLOT + 1) * 8)) 119 ldp x14, x15, [x5, #-16]! 120 stp x14, x15, [x17, #-16]! 121 CFI_REL_OFFSET(x26, -((BOUNDARY_FRAME_SLOT + 2) * 8)) 122 CFI_REL_OFFSET(x25, -((BOUNDARY_FRAME_SLOT + 3) * 8)) 123 ldp x14, x15, [x5, #-16]! 124 stp x14, x15, [x17, #-16]! 125 CFI_REL_OFFSET(x24, -((BOUNDARY_FRAME_SLOT + 4) * 8)) 126 CFI_REL_OFFSET(x23, -((BOUNDARY_FRAME_SLOT + 5) * 8)) 127 ldp x14, x15, [x5, #-16]! 128 stp x14, x15, [x17, #-16]! 129 CFI_REL_OFFSET(x22, -((BOUNDARY_FRAME_SLOT + 6) * 8)) 130 CFI_REL_OFFSET(x21, -((BOUNDARY_FRAME_SLOT + 7) * 8)) 131 ldp x14, x15, [x5, #-16]! 132 stp x14, x15, [x17, #-16]! 133 CFI_REL_OFFSET(x20, -((BOUNDARY_FRAME_SLOT + 8) * 8)) 134 CFI_REL_OFFSET(x19, -((BOUNDARY_FRAME_SLOT + 9) * 8)) 135 ldp x14, x15, [x5, #-16]! 136 stp x14, x15, [x17, #-16]! 137 CFI_REL_OFFSET(d15, -((BOUNDARY_FRAME_SLOT + 10) * 8)) 138 CFI_REL_OFFSET(d14, -((BOUNDARY_FRAME_SLOT + 11) * 8)) 139 ldp x14, x15, [x5, #-16]! 140 stp x14, x15, [x17, #-16]! 141 CFI_REL_OFFSET(d13, -((BOUNDARY_FRAME_SLOT + 12) * 8)) 142 CFI_REL_OFFSET(d12, -((BOUNDARY_FRAME_SLOT + 13) * 8)) 143 ldp x14, x15, [x5, #-16]! 144 stp x14, x15, [x17, #-16]! 145 CFI_REL_OFFSET(d11, -((BOUNDARY_FRAME_SLOT + 14) * 8)) 146 CFI_REL_OFFSET(d10, -((BOUNDARY_FRAME_SLOT + 15) * 8)) 147 ldp x14, x15, [x5, #-16]! 148 stp x14, x15, [x17, #-16]! 149 CFI_REL_OFFSET(d9, -((BOUNDARY_FRAME_SLOT + 16) * 8)) 150 CFI_REL_OFFSET(d8, -((BOUNDARY_FRAME_SLOT + 17) * 8)) 151 152 ASSERT_REGS_CMP sp, x17, eq 153 154 // Save used registers 155 stp x0, x1, [sp, #-16]! 156 stp x2, x3, [sp, #-16]! 157 158 mov x3, x4 159 // Arguments are already lie in the registers, because signature of DeoptimizeAfterCFrame is similar to InvokeInterpreter 160 bl InvokeInterpreter 161 162 // Restore used registers, but not x0 which holds result of the invoked method and should survive to the end 163 // So we use r7 instead of r0 for restoring THRED_REG 164 ldp x2, x3, [sp], #16 165 ldp x7, x1, [sp], #16 166 167 // Restore callee saved registers 168 sub x3, x3, #((BOUNDARY_FRAME_SLOT - 1) * 8) 169 RESTORE_CALLEE_REGISTERS x3 170 CFI_RESTORE(x28) 171 CFI_RESTORE(x27) 172 CFI_RESTORE(x26) 173 CFI_RESTORE(x25) 174 CFI_RESTORE(x24) 175 CFI_RESTORE(x23) 176 CFI_RESTORE(x22) 177 CFI_RESTORE(x21) 178 CFI_RESTORE(x20) 179 CFI_RESTORE(x19) 180 CFI_RESTORE(d15) 181 CFI_RESTORE(d14) 182 CFI_RESTORE(d13) 183 CFI_RESTORE(d12) 184 CFI_RESTORE(d11) 185 CFI_RESTORE(d10) 186 CFI_RESTORE(d9) 187 CFI_RESTORE(d8) 188 189 # Restore stack pointer 190 add sp, sp, #(((CFRAME_HEADER_SIZE - 2) * 8) + CALLEE_SAVED_SIZE) 191 192 ldr fp, [sp, #-8] 193 CFI_RESTORE(fp) 194 CFI_DEF_CFA(sp, (2 * 8)) 195 ldr lr, [sp, #8] 196 CFI_RESTORE(lr) 197 add sp, sp, #16 198 CFI_ADJUST_CFA_OFFSET(-(2 * 8)) 199 mov THREAD_REG, x7 200 CFI_RESTORE(THREAD_REG) 201 fmov d0, x0 202 ret 203 CFI_ENDPROC 204 205 206.global DeoptimizeAfterIFrame 207.type DeoptimizeAfterIFrame, %function 208DeoptimizeAfterIFrame: 209 CFI_STARTPROC 210 CFI_DEF_CFA(sp, 0) 211#ifndef NDEBUG 212 stp fp, lr, [sp, #-16]! 213 CFI_ADJUST_CFA_OFFSET(2 * 8) 214 CFI_REL_OFFSET(lr, 8) 215#endif 216 217 // Parameters: 218 // x0 - thread 219 // x1 - pc of the entry 220 // x2 - pointer to interpreter Frame 221 // x3 - pointer to cframe origin 222 // x4 - last restored interpreter Frame 223 // x5 - pointer to a callee-saved registers buffer from StackWalker 224 225 CFRAME_COPY_LR x3 226 227 CFI_DEF_CFA(x3, (2 * 8)) 228 CFI_REL_OFFSET(lr, 8) 229 CFI_REL_OFFSET(fp, 0) 230 CFI_REL_OFFSET(x28, -((CFRAME_CALLEE_REGS_START_SLOT + 0) * 8)) 231 CFI_REL_OFFSET(x27, -((CFRAME_CALLEE_REGS_START_SLOT + 1) * 8)) 232 CFI_REL_OFFSET(x26, -((CFRAME_CALLEE_REGS_START_SLOT + 2) * 8)) 233 CFI_REL_OFFSET(x25, -((CFRAME_CALLEE_REGS_START_SLOT + 3) * 8)) 234 CFI_REL_OFFSET(x24, -((CFRAME_CALLEE_REGS_START_SLOT + 4) * 8)) 235 CFI_REL_OFFSET(x23, -((CFRAME_CALLEE_REGS_START_SLOT + 5) * 8)) 236 CFI_REL_OFFSET(x22, -((CFRAME_CALLEE_REGS_START_SLOT + 6) * 8)) 237 CFI_REL_OFFSET(x21, -((CFRAME_CALLEE_REGS_START_SLOT + 7) * 8)) 238 CFI_REL_OFFSET(x20, -((CFRAME_CALLEE_REGS_START_SLOT + 8) * 8)) 239 CFI_REL_OFFSET(x19, -((CFRAME_CALLEE_REGS_START_SLOT + 9) * 8)) 240 CFI_REL_OFFSET(d15, -((CFRAME_CALLEE_REGS_START_SLOT + 10) * 8)) 241 CFI_REL_OFFSET(d14, -((CFRAME_CALLEE_REGS_START_SLOT + 11) * 8)) 242 CFI_REL_OFFSET(d13, -((CFRAME_CALLEE_REGS_START_SLOT + 12) * 8)) 243 CFI_REL_OFFSET(d12, -((CFRAME_CALLEE_REGS_START_SLOT + 13) * 8)) 244 CFI_REL_OFFSET(d11, -((CFRAME_CALLEE_REGS_START_SLOT + 14) * 8)) 245 CFI_REL_OFFSET(d10, -((CFRAME_CALLEE_REGS_START_SLOT + 15) * 8)) 246 CFI_REL_OFFSET(d9, -((CFRAME_CALLEE_REGS_START_SLOT + 16) * 8)) 247 CFI_REL_OFFSET(d8, -((CFRAME_CALLEE_REGS_START_SLOT + 17) * 8)) 248 249 // Restore fp by pointer to the I2C boundary frame 250 mov fp, x3 251 CFI_DEF_CFA_REGISTER(fp) 252 253 // Restore return address, so after interperter finished, it returns to the I2C bridge 254 255 // Restore callee saved registers 256 RESTORE_CALLEE_REGISTERS x5 257 CFI_RESTORE(x28) 258 CFI_RESTORE(x27) 259 CFI_RESTORE(x26) 260 CFI_RESTORE(x25) 261 CFI_RESTORE(x24) 262 CFI_RESTORE(x23) 263 CFI_RESTORE(x22) 264 CFI_RESTORE(x21) 265 CFI_RESTORE(x20) 266 CFI_RESTORE(x19) 267 CFI_RESTORE(d15) 268 CFI_RESTORE(d14) 269 CFI_RESTORE(d13) 270 CFI_RESTORE(d12) 271 CFI_RESTORE(d11) 272 CFI_RESTORE(d10) 273 CFI_RESTORE(d9) 274 CFI_RESTORE(d8) 275 276 // Restore stack pointer to the beginning of the cframe 277 mov sp, fp 278 279 mov x3, x4 280 bl InvokeInterpreter 281 // InvokeInterpreter returns int64 value, but result can be double, so we copy value to vector register 282 fmov d0, x0 283 284 ldp fp, lr, [sp], #16 285 CFI_RESTORE(fp) 286 CFI_RESTORE(lr) 287 CFI_DEF_CFA(sp, 0) 288 ret 289 CFI_ENDPROC 290 291 292.global DropCompiledFrameAndReturn 293.type DropCompiledFrameAndReturn, %function 294DropCompiledFrameAndReturn: 295 CFI_STARTPROC 296 CFI_DEF_CFA(sp, 0) 297#ifndef NDEBUG 298 stp fp, lr, [sp, #-16]! 299 CFI_ADJUST_CFA_OFFSET(2 * 8) 300 CFI_REL_OFFSET(lr, 8) 301#endif 302 303 // x0 - pointer to cframe origin 304 // x1 - pointer to a callee-saved registers buffer from StackWalker 305 CFRAME_GET_LR x0 306 307 CFI_DEF_CFA(x0, (2 * 8)) 308 CFI_RESTORE(lr) 309 CFI_REL_OFFSET(fp, 0) 310 CFI_REL_OFFSET(x28, -((CFRAME_CALLEE_REGS_START_SLOT + 0) * 8)) 311 CFI_REL_OFFSET(x27, -((CFRAME_CALLEE_REGS_START_SLOT + 1) * 8)) 312 CFI_REL_OFFSET(x26, -((CFRAME_CALLEE_REGS_START_SLOT + 2) * 8)) 313 CFI_REL_OFFSET(x25, -((CFRAME_CALLEE_REGS_START_SLOT + 3) * 8)) 314 CFI_REL_OFFSET(x24, -((CFRAME_CALLEE_REGS_START_SLOT + 4) * 8)) 315 CFI_REL_OFFSET(x23, -((CFRAME_CALLEE_REGS_START_SLOT + 5) * 8)) 316 CFI_REL_OFFSET(x22, -((CFRAME_CALLEE_REGS_START_SLOT + 6) * 8)) 317 CFI_REL_OFFSET(x21, -((CFRAME_CALLEE_REGS_START_SLOT + 7) * 8)) 318 CFI_REL_OFFSET(x20, -((CFRAME_CALLEE_REGS_START_SLOT + 8) * 8)) 319 CFI_REL_OFFSET(x19, -((CFRAME_CALLEE_REGS_START_SLOT + 9) * 8)) 320 CFI_REL_OFFSET(d15, -((CFRAME_CALLEE_REGS_START_SLOT + 10) * 8)) 321 CFI_REL_OFFSET(d14, -((CFRAME_CALLEE_REGS_START_SLOT + 11) * 8)) 322 CFI_REL_OFFSET(d13, -((CFRAME_CALLEE_REGS_START_SLOT + 12) * 8)) 323 CFI_REL_OFFSET(d12, -((CFRAME_CALLEE_REGS_START_SLOT + 13) * 8)) 324 CFI_REL_OFFSET(d11, -((CFRAME_CALLEE_REGS_START_SLOT + 14) * 8)) 325 CFI_REL_OFFSET(d10, -((CFRAME_CALLEE_REGS_START_SLOT + 15) * 8)) 326 CFI_REL_OFFSET(d9, -((CFRAME_CALLEE_REGS_START_SLOT + 16) * 8)) 327 CFI_REL_OFFSET(d8, -((CFRAME_CALLEE_REGS_START_SLOT + 17) * 8)) 328 329 mov fp, x0 330 CFI_DEF_CFA_REGISTER(fp) 331 332 // Restore callee saved registers 333 RESTORE_CALLEE_REGISTERS x1 334 CFI_RESTORE(x28) 335 CFI_RESTORE(x27) 336 CFI_RESTORE(x26) 337 CFI_RESTORE(x25) 338 CFI_RESTORE(x24) 339 CFI_RESTORE(x23) 340 CFI_RESTORE(x22) 341 CFI_RESTORE(x21) 342 CFI_RESTORE(x20) 343 CFI_RESTORE(x19) 344 CFI_RESTORE(d15) 345 CFI_RESTORE(d14) 346 CFI_RESTORE(d13) 347 CFI_RESTORE(d12) 348 CFI_RESTORE(d11) 349 CFI_RESTORE(d10) 350 CFI_RESTORE(d9) 351 CFI_RESTORE(d8) 352 353 // We need to clear return value, since it will be written to the IFrame's accumulator. Without this, it holds 354 // garbage and StackWalker verification might fail. 355 mov x0, xzr 356 357 mov sp, fp 358 ldr fp, [sp], #16 359 CFI_RESTORE(fp) 360 CFI_DEF_CFA(sp, 0) 361 ret 362 CFI_ENDPROC 363