1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "asm_support_x86_64.S" 18 19 /* 20 * Jni dlsym lookup stub. 21 */ 22DEFINE_FUNCTION art_jni_dlsym_lookup_stub 23 // Save callee and GPR args. 24 PUSH_ARG r9 // Arg. 25 PUSH_ARG r8 // Arg. 26 PUSH_ARG rdi // Arg. (JniEnv for normal and @FastNative) 27 PUSH_ARG rsi // Arg. 28 PUSH_ARG rdx // Arg. 29 PUSH_ARG rcx // Arg. 30 // Create space for FPR args, plus padding for alignment 31 subq LITERAL(72), %rsp 32 CFI_ADJUST_CFA_OFFSET(72) 33 // Save FPRs. 34 movq %xmm0, 0(%rsp) 35 movq %xmm1, 8(%rsp) 36 movq %xmm2, 16(%rsp) 37 movq %xmm3, 24(%rsp) 38 movq %xmm4, 32(%rsp) 39 movq %xmm5, 40(%rsp) 40 movq %xmm6, 48(%rsp) 41 movq %xmm7, 56(%rsp) 42 // prepare call 43 movq %gs:THREAD_SELF_OFFSET, %rdi // RDI := Thread::Current() 44 // Call artFindNativeMethod() for normal native and artFindNativeMethodRunnable() 45 // for @FastNative or @CriticalNative. 46 movq THREAD_TOP_QUICK_FRAME_OFFSET(%rdi), %rax // uintptr_t tagged_quick_frame 47 andq LITERAL(0xfffffffffffffffe), %rax // ArtMethod** sp 48 movq (%rax), %rax // ArtMethod* method 49 testl LITERAL(ACCESS_FLAGS_METHOD_IS_FAST_NATIVE | ACCESS_FLAGS_METHOD_IS_CRITICAL_NATIVE), \ 50 ART_METHOD_ACCESS_FLAGS_OFFSET(%rax) 51 jne .Llookup_stub_fast_native 52 call SYMBOL(artFindNativeMethod) // (Thread*) 53 jmp .Llookup_stub_continue 54.Llookup_stub_fast_native: 55 call SYMBOL(artFindNativeMethodRunnable) // (Thread*) 56.Llookup_stub_continue: 57 // restore arguments 58 movq 0(%rsp), %xmm0 59 movq 8(%rsp), %xmm1 60 movq 16(%rsp), %xmm2 61 movq 24(%rsp), %xmm3 62 movq 32(%rsp), %xmm4 63 movq 40(%rsp), %xmm5 64 movq 48(%rsp), %xmm6 65 movq 56(%rsp), %xmm7 66 addq LITERAL(72), %rsp 67 CFI_ADJUST_CFA_OFFSET(-72) 68 POP_ARG rcx // Arg. 69 POP_ARG rdx // Arg. 70 POP_ARG rsi // Arg. 71 POP_ARG rdi // Arg. (JniEnv for normal and @FastNative) 72 POP_ARG r8 // Arg. 73 POP_ARG r9 // Arg. 74 testq %rax, %rax // check if returned method code is null 75 jz .Lno_native_code_found // if null, jump to return to handle 76 jmp *%rax // otherwise, tail call to intended method 77.Lno_native_code_found: 78 ret 79END_FUNCTION art_jni_dlsym_lookup_stub 80 81DEFINE_FUNCTION art_jni_dlsym_lookup_critical_stub 82 // The hidden arg holding the tagged method (bit 0 set means GenericJNI) is r11. 83 // For Generic JNI we already have a managed frame, so we reuse the art_jni_dlsym_lookup_stub. 84 testq LITERAL(1), %r11 85 jnz art_jni_dlsym_lookup_stub 86 87 // We need to create a GenericJNI managed frame above the stack args. 88 89 // GenericJNI frame is similar to SaveRegsAndArgs frame with the native method 90 // instead of runtime method saved at the bottom. 91 92 // As we always have "stack args" on x86-64 (due to xmm12-xmm15 being callee-save 93 // in managed ABI but caller-save in native ABI), do not create a proper frame yet 94 // as we do on other architectures where it's useful for no stack args case. 95 96 // Reserve space for the frame (return PC is on stack). 97 subq MACRO_LITERAL(FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__), %rsp 98 CFI_ADJUST_CFA_OFFSET(FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__) 99 100 // Save GPR args. 101 PUSH_ARG r9 102 PUSH_ARG r8 103 PUSH_ARG rdi 104 PUSH_ARG rsi 105 PUSH_ARG rdx 106 PUSH_ARG rcx 107 // Create space for FPR args. 108 subq LITERAL(64), %rsp 109 CFI_ADJUST_CFA_OFFSET(64) 110 // Save FPRs. 111 movq %xmm0, 0(%rsp) 112 movq %xmm1, 8(%rsp) 113 movq %xmm2, 16(%rsp) 114 movq %xmm3, 24(%rsp) 115 movq %xmm4, 32(%rsp) 116 movq %xmm5, 40(%rsp) 117 movq %xmm6, 48(%rsp) 118 movq %xmm7, 56(%rsp) 119 120 // Add alignment padding. 121 subq MACRO_LITERAL(__SIZEOF_POINTER__), %rsp 122 CFI_ADJUST_CFA_OFFSET(__SIZEOF_POINTER__) 123 // Save hidden arg. 124 PUSH_ARG r11 125 126 // Call artCriticalNativeOutArgsSize(method). 127 movq %r11, %rdi // Pass the method from hidden arg. 128 call SYMBOL(artCriticalNativeOutArgsSize) 129 130 // Calculate the address of the end of the move destination and redefine CFI to take 131 // ownership of the JNI stub frame. 132 leaq 16 * __SIZEOF_POINTER__(%rsp, %rax, 1), %r10 // 16 QWORDs of registers saved above. 133 CFI_DEF_CFA(%r10, FRAME_SIZE_SAVE_REFS_AND_ARGS) 134 135 // Calculate the number of QWORDs to move. 136 shrq LITERAL(3), %rax 137 leaq -1(%rax), %rcx // Do not move the return PC. 138 139 // Load our return PC to EAX. 140 movq FRAME_SIZE_SAVE_REFS_AND_ARGS + (16 - 1) * __SIZEOF_POINTER__(%rsp), %rax 141 142 // Mov the stack args. 143 leaq 16 * __SIZEOF_POINTER__(%rsp), %rdi 144 leaq FRAME_SIZE_SAVE_REFS_AND_ARGS(%rdi), %rsi 145 rep movsq 146 147 // Save our return PC. 148 movq %rax, (%rdi) 149 150 // Pop the hidden arg and alignment padding. 151 popq %r11 // No `.cfi_adjust_cfa_offset`, CFA register is currently R10, not RSP. 152 addq MACRO_LITERAL(__SIZEOF_POINTER__), %rsp // ditto 153 154 // Fill the SaveRefsAndArgs frame above the args, without actual args. Note that 155 // the runtime shall not examine the args here, otherwise we would have to move them in 156 // registers and stack to account for the difference between managed and native ABIs. 157 SAVE_REG_BASE r10, r15, 192 158 SAVE_REG_BASE r10, r14, 184 159 SAVE_REG_BASE r10, r13, 176 160 SAVE_REG_BASE r10, r12, 168 161 // Skip args r9, r8, rsi. 162 SAVE_REG_BASE r10, rbp, 136 163 SAVE_REG_BASE r10, rbx, 128 164 // Skip args rdx, rcx. 165 // Skip args xmm0-xmm7. 166 // Copy managed callee-saves xmm12-xmm15 from out args to the managed frame as they 167 // may theoretically store variables or unwinding data. (The compiled stub preserves 168 // them but the artCriticalNativeOutArgsSize() call above may clobber them.) 169 movq -5 * __SIZEOF_POINTER__(%r10), %xmm12 170 movq -4 * __SIZEOF_POINTER__(%r10), %xmm13 171 movq -3 * __SIZEOF_POINTER__(%r10), %xmm14 172 movq -2 * __SIZEOF_POINTER__(%r10), %xmm15 173 movq %xmm12, 80(%r10) 174 movq %xmm13, 88(%r10) 175 movq %xmm14, 96(%r10) 176 movq %xmm15, 104(%r10) 177 // Save the hidden arg as method pointer at the bottom of the stack. 178 movq %r11, (%r10) 179 180 // Move the frame register to a callee-save register. 181 movq %r10, %rbp 182 CFI_DEF_CFA_REGISTER(%rbp) 183 184 // Place tagged managed sp in Thread::Current()->top_quick_frame. 185 leaq 1(%rbp), %rax // Tag as GenericJNI frame. 186 movq %rax, %gs:THREAD_TOP_QUICK_FRAME_OFFSET 187 188 // Call artFindNativeMethodRunnable() 189 movq %gs:THREAD_SELF_OFFSET, %rdi // pass Thread::Current() 190 call SYMBOL(artFindNativeMethodRunnable) // (Thread*) 191 192 // Check for exception. 193 test %rax, %rax 194 jz 2f 195 196 // Restore the frame. We shall not need the method anymore. 197 .cfi_remember_state 198 movq %rbp, %r10 199 CFI_DEF_CFA_REGISTER(%r10) 200 // Skip args xmm0-xmm7 and managed callee-saves xmm12-xmm15 (not needed for native call). 201 // Skip args rdx, rcx. 202 RESTORE_REG_BASE r10, rbx, 128 203 RESTORE_REG_BASE r10, rbp, 136 204 // Skip args r9, r8, rsi. 205 RESTORE_REG_BASE r10, r12, 168 206 RESTORE_REG_BASE r10, r13, 176 207 RESTORE_REG_BASE r10, r14, 184 208 RESTORE_REG_BASE r10, r15, 192 209 210 // Remember our return PC in R11. 211 movq -__SIZEOF_POINTER__(%r10), %r11 212 213 // Calculate the number of DWORDs to move. 214 leaq -(1 + 14) * __SIZEOF_POINTER__(%r10), %rcx // Do not move return PC, 14 arg regs saved. 215 subq %rsp, %rcx 216 shrq LITERAL(3), %rcx 217 218 // Mov stack args to their original place. 219 leaq -2 * __SIZEOF_POINTER__(%r10), %rsi 220 leaq FRAME_SIZE_SAVE_REFS_AND_ARGS - 2 * __SIZEOF_POINTER__(%r10), %rdi 221 std 222 rep movsq 223 cld 224 225 // Store our return PC. 226 movq %r11, (%rdi) 227 228 // Redefine CFI to release ownership of the JNI stub frame. 229 CFI_DEF_CFA(%rsp, FRAME_SIZE_SAVE_REFS_AND_ARGS + 14 * __SIZEOF_POINTER__) 230 231 // Restore args. 232 movq 0(%rsp), %xmm0 233 movq 8(%rsp), %xmm1 234 movq 16(%rsp), %xmm2 235 movq 24(%rsp), %xmm3 236 movq 32(%rsp), %xmm4 237 movq 40(%rsp), %xmm5 238 movq 48(%rsp), %xmm6 239 movq 56(%rsp), %xmm7 240 addq LITERAL(64), %rsp 241 CFI_ADJUST_CFA_OFFSET(-64) 242 POP_ARG rcx 243 POP_ARG rdx 244 POP_ARG rsi 245 POP_ARG rdi 246 POP_ARG r8 247 POP_ARG r9 248 249 // Remove the frame reservation. 250 addq LITERAL(FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__), %rsp 251 CFI_ADJUST_CFA_OFFSET(-(FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__)) 252 253 // Do the tail call. 254 jmp *%rax 255 CFI_RESTORE_STATE_AND_DEF_CFA(%rbp, FRAME_SIZE_SAVE_REFS_AND_ARGS) 256 2572: 258 // Drop the args from the stack (the r11 and padding was already removed). 259 addq LITERAL(14 * __SIZEOF_POINTER__), %rsp 260 261 DELIVER_PENDING_EXCEPTION_FRAME_READY 262END_FUNCTION art_jni_dlsym_lookup_critical_stub 263