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 INCREASE_FRAME 72 32 // Save FPRs. 33 movq %xmm0, 0(%rsp) 34 movq %xmm1, 8(%rsp) 35 movq %xmm2, 16(%rsp) 36 movq %xmm3, 24(%rsp) 37 movq %xmm4, 32(%rsp) 38 movq %xmm5, 40(%rsp) 39 movq %xmm6, 48(%rsp) 40 movq %xmm7, 56(%rsp) 41 // prepare call 42 movq %gs:THREAD_SELF_OFFSET, %rdi // RDI := Thread::Current() 43 // Call artFindNativeMethod() for normal native and artFindNativeMethodRunnable() 44 // for @FastNative or @CriticalNative. 45 movq THREAD_TOP_QUICK_FRAME_OFFSET(%rdi), %rax // uintptr_t tagged_quick_frame 46 andq LITERAL(0xfffffffffffffffe), %rax // ArtMethod** sp 47 movq (%rax), %rax // ArtMethod* method 48 testl LITERAL(ACCESS_FLAGS_METHOD_IS_FAST_NATIVE | ACCESS_FLAGS_METHOD_IS_CRITICAL_NATIVE), \ 49 ART_METHOD_ACCESS_FLAGS_OFFSET(%rax) 50 jne .Llookup_stub_fast_or_critical_native 51 call SYMBOL(artFindNativeMethod) // (Thread*) 52 jmp .Llookup_stub_continue 53.Llookup_stub_fast_or_critical_native: 54 call SYMBOL(artFindNativeMethodRunnable) // (Thread*) 55.Llookup_stub_continue: 56 // restore arguments 57 movq 0(%rsp), %xmm0 58 movq 8(%rsp), %xmm1 59 movq 16(%rsp), %xmm2 60 movq 24(%rsp), %xmm3 61 movq 32(%rsp), %xmm4 62 movq 40(%rsp), %xmm5 63 movq 48(%rsp), %xmm6 64 movq 56(%rsp), %xmm7 65 DECREASE_FRAME 72 66 POP_ARG rcx // Arg. 67 POP_ARG rdx // Arg. 68 POP_ARG rsi // Arg. 69 POP_ARG rdi // Arg. (JniEnv for normal and @FastNative) 70 POP_ARG r8 // Arg. 71 POP_ARG r9 // Arg. 72 testq %rax, %rax // check if returned method code is null 73 jz .Lno_native_code_found // if null, jump to return to handle 74 jmp *%rax // otherwise, tail call to intended method 75.Lno_native_code_found: 76 ret 77END_FUNCTION art_jni_dlsym_lookup_stub 78 79DEFINE_FUNCTION art_jni_dlsym_lookup_critical_stub 80 // The hidden arg holding the tagged method (bit 0 set means GenericJNI) is RAX. 81 // For Generic JNI we already have a managed frame, so we reuse the art_jni_dlsym_lookup_stub. 82 testq LITERAL(1), %rax 83 jnz art_jni_dlsym_lookup_stub 84 85 // Save GPR args and method. 86 PUSH_ARG r9 87 PUSH_ARG r8 88 PUSH_ARG rdi 89 PUSH_ARG rsi 90 PUSH_ARG rdx 91 PUSH_ARG rcx 92 PUSH_ARG rax 93 // Create space for FPR args. 94 INCREASE_FRAME 8 * 8 95 // Save FPRs. 96 movq %xmm0, 0(%rsp) 97 movq %xmm1, 8(%rsp) 98 movq %xmm2, 16(%rsp) 99 movq %xmm3, 24(%rsp) 100 movq %xmm4, 32(%rsp) 101 movq %xmm5, 40(%rsp) 102 movq %xmm6, 48(%rsp) 103 movq %xmm7, 56(%rsp) 104 // Note: It's the caller's responsibility to preserve xmm12-xmm15 as the tail call 105 // to native shall always risk clobbering those. 106 107 // Call artCriticalNativeFrameSize(method, caller_pc). 108 movq %rax, %rdi // Pass the method from hidden arg. 109 movq 120(%rsp), %rsi // Pass caller PC. 110 call SYMBOL(artCriticalNativeFrameSize) 111 112 // Restore registers. 113 movq 0(%rsp), %xmm0 114 movq 8(%rsp), %xmm1 115 movq 16(%rsp), %xmm2 116 movq 24(%rsp), %xmm3 117 movq 32(%rsp), %xmm4 118 movq 40(%rsp), %xmm5 119 movq 48(%rsp), %xmm6 120 movq 56(%rsp), %xmm7 121 DECREASE_FRAME 8 * 8 122 POP_ARG r10 // Restore method to R10. 123 POP_ARG rcx 124 POP_ARG rdx 125 POP_ARG rsi 126 POP_ARG rdi 127 POP_ARG r8 128 POP_ARG r9 129 130 // Load caller PC to R11 and redefine return PC for CFI. 131 movq (%rsp), %r11 132 CFI_REGISTER(%rip, %r11) 133 134 // Reserve space for a SaveRefsAndArgs managed frame, either for the actual runtime 135 // method or for a GenericJNI frame which is similar but has a native method and a tag. 136 INCREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__ 137 138 // Calculate the number of QWORDs to move. 139 shrq LITERAL(3), %rax 140 jz .Lcritical_skip_copy_args 141 142 // Save RDI, RSI, RCX so that we can use them for moving stack args. 143 PUSH_ARG rdi 144 PUSH_ARG rsi 145 PUSH_ARG rcx 146 147 // Move the stack args. 148 movq %rax, %rcx 149 leaq 3 * __SIZEOF_POINTER__(%rsp), %rdi 150 leaq FRAME_SIZE_SAVE_REFS_AND_ARGS(%rdi), %rsi 151 rep movsq 152 153 // Restore RDI, RSI, RCX. 154 POP_ARG rcx 155 POP_ARG rsi 156 POP_ARG rdi 157 158.Lcritical_skip_copy_args: 159 // Calculate the base address of the managed frame. 160 leaq (%rsp, %rax, 8), %rax 161 162 // Spill registers for the SaveRefsAndArgs frame above the stack args. 163 // Note that the runtime shall not examine the args here, otherwise we would have to 164 // move them in registers and stack to account for the difference between managed and 165 // native ABIs. Do not update CFI while we hold the frame address in RAX and the values 166 // in registers are unchanged. 167 movq %r15, 192(%rax) 168 movq %r14, 184(%rax) 169 movq %r13, 176(%rax) 170 movq %r12, 168(%rax) 171 movq %r9, 160(%rax) 172 movq %r8, 152(%rax) 173 movq %rsi, 144(%rax) 174 movq %rbp, 136(%rax) 175 movq %rbx, 128(%rax) 176 movq %rdx, 120(%rax) 177 movq %rcx, 112(%rax) 178 movq %xmm0, 16(%rax) 179 movq %xmm1, 24(%rax) 180 movq %xmm2, 32(%rax) 181 movq %xmm3, 40(%rax) 182 movq %xmm4, 48(%rax) 183 movq %xmm5, 56(%rax) 184 movq %xmm6, 64(%rax) 185 movq %xmm7, 72(%rax) 186 // Skip managed ABI callee-saves xmm12-xmm15. 187 188 // Move the managed frame address to native callee-save register RBP and update CFI. 189 movq %rax, %rbp 190 CFI_EXPRESSION_BREG CFI_REG(r15), CFI_REG(rbp), 192 191 CFI_EXPRESSION_BREG CFI_REG(r14), CFI_REG(rbp), 184 192 CFI_EXPRESSION_BREG CFI_REG(r13), CFI_REG(rbp), 176 193 CFI_EXPRESSION_BREG CFI_REG(r12), CFI_REG(rbp), 168 194 // Skip args r9, r8, rsi. 195 CFI_EXPRESSION_BREG CFI_REG(rbp), CFI_REG(rbp), 136 196 CFI_EXPRESSION_BREG CFI_REG(rbx), CFI_REG(rbp), 128 197 // Skip args rdx, rcx. 198 // Skip args xmm0-xmm7. 199 200 leaq 1(%rbp), %rax // Prepare managed SP tagged for a GenericJNI frame. 201 testl LITERAL(ACCESS_FLAGS_METHOD_IS_NATIVE), ART_METHOD_ACCESS_FLAGS_OFFSET(%r10) 202 jnz .Lcritical_skip_prepare_runtime_method 203 204 // Save the return PC for managed stack walk. 205 // (When coming from a compiled stub, the correct return PC is already there.) 206 movq %r11, FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__(%rbp) 207 208 // Replace the target method with the SaveRefsAndArgs runtime method. 209 LOAD_RUNTIME_INSTANCE r10 210 movq RUNTIME_SAVE_REFS_AND_ARGS_METHOD_OFFSET(%r10), %r10 211 212 movq %rbp, %rax // Prepare untagged managed SP for the runtime method. 213 214.Lcritical_skip_prepare_runtime_method: 215 // Store the method on the bottom of the managed frame. 216 movq %r10, (%rbp) 217 218 // Place (maybe tagged) managed SP in Thread::Current()->top_quick_frame. 219 movq %rax, %gs:THREAD_TOP_QUICK_FRAME_OFFSET 220 221 // Save our return PC in the padding. 222 movq %r11, __SIZEOF_POINTER__(%rbp) 223 CFI_EXPRESSION_BREG CFI_REG(rip), CFI_REG(rbp), __SIZEOF_POINTER__ 224 225 // Preserve the native arg register RDI in callee-save register RBX which was saved above. 226 movq %rdi, %rbx 227 228 // Call artFindNativeMethodRunnable() 229 movq %gs:THREAD_SELF_OFFSET, %rdi // pass Thread::Current() 230 call SYMBOL(artFindNativeMethodRunnable) // (Thread*) 231 232 // Check for exception. 233 test %rax, %rax 234 jz .Lcritical_deliver_exception 235 236 CFI_REMEMBER_STATE 237 238 // Restore the native arg register RDI. 239 movq %rbx, %rdi 240 241 // Remember our return PC in R11. 242 movq __SIZEOF_POINTER__(%rbp), %r11 243 CFI_REGISTER(%rip, %r11) 244 245 // Remember the frame base address in r10 but do not redefine CFI. 246 movq %rbp, %r10 247 248 // Restore the frame. We shall not need the method anymore. 249 movq 16(%rbp), %xmm0 250 movq 24(%rbp), %xmm1 251 movq 32(%rbp), %xmm2 252 movq 40(%rbp), %xmm3 253 movq 48(%rbp), %xmm4 254 movq 56(%rbp), %xmm5 255 movq 64(%rbp), %xmm6 256 movq 72(%rbp), %xmm7 257 // Skip managed callee-saves xmm12-xmm15. 258 movq 112(%rbp), %rcx 259 movq 120(%rbp), %rdx 260 RESTORE_REG_BASE rbp, rbx, 128 261 // Delay restoring RBP as it's the managed frame base. 262 movq 144(%rbp), %rsi 263 movq 152(%rbp), %r8 264 movq 160(%rbp), %r9 265 RESTORE_REG_BASE rbp, r12, 168 266 RESTORE_REG_BASE rbp, r13, 176 267 RESTORE_REG_BASE rbp, r14, 184 268 RESTORE_REG_BASE rbp, r15, 192 269 // Restore RBP last. 270 RESTORE_REG_BASE rbp, rbp, 136 271 272 cmp %r10, %rsp 273 je .Lcritical_skip_copy_args_back 274 275 // Save RDI, RSI, RCX so that we can use them for moving stack args. 276 PUSH_ARG rdi 277 PUSH_ARG rsi 278 PUSH_ARG rcx 279 280 // Calculate the number of QWORDs to move. 281 leaq -3 * __SIZEOF_POINTER__(%r10), %rcx 282 subq %rsp, %rcx 283 shrq LITERAL(3), %rcx 284 285 // Move the stack args. 286 leaq -__SIZEOF_POINTER__(%r10), %rsi 287 leaq FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__(%r10), %rdi 288 std 289 rep movsq 290 cld 291 292 // Restore RDI, RSI, RCX. 293 POP_ARG rcx 294 POP_ARG rsi 295 POP_ARG rdi 296 297.Lcritical_skip_copy_args_back: 298 // Remove the frame reservation. 299 DECREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__ 300 301 // Store our return PC. 302 movq %r11, (%rsp) 303 CFI_REL_OFFSET(%rip, 0) 304 305 // Do the tail call. 306 jmp *%rax 307 CFI_RESTORE_STATE_AND_DEF_CFA(%rbp, FRAME_SIZE_SAVE_REFS_AND_ARGS) 308 309.Lcritical_deliver_exception: 310 DELIVER_PENDING_EXCEPTION_FRAME_READY 311END_FUNCTION art_jni_dlsym_lookup_critical_stub 312