1/* 2 * Copyright (C) 2014 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_arm64.S" 18 19 /* 20 * Jni dlsym lookup stub. 21 */ 22 .extern artFindNativeMethod 23 .extern artFindNativeMethodRunnable 24 25ENTRY art_jni_dlsym_lookup_stub 26 // spill regs. 27 stp x29, x30, [sp, #-16]! 28 .cfi_adjust_cfa_offset 16 29 .cfi_rel_offset x29, 0 30 .cfi_rel_offset x30, 8 31 mov x29, sp 32 stp d6, d7, [sp, #-16]! 33 .cfi_adjust_cfa_offset 16 34 stp d4, d5, [sp, #-16]! 35 .cfi_adjust_cfa_offset 16 36 stp d2, d3, [sp, #-16]! 37 .cfi_adjust_cfa_offset 16 38 stp d0, d1, [sp, #-16]! 39 .cfi_adjust_cfa_offset 16 40 stp x6, x7, [sp, #-16]! 41 .cfi_adjust_cfa_offset 16 42 stp x4, x5, [sp, #-16]! 43 .cfi_adjust_cfa_offset 16 44 stp x2, x3, [sp, #-16]! 45 .cfi_adjust_cfa_offset 16 46 stp x0, x1, [sp, #-16]! 47 .cfi_adjust_cfa_offset 16 48 49 mov x0, xSELF // pass Thread::Current() 50 // Call artFindNativeMethod() for normal native and artFindNativeMethodRunnable() 51 // for @FastNative or @CriticalNative. 52 ldr xIP0, [x0, #THREAD_TOP_QUICK_FRAME_OFFSET] // uintptr_t tagged_quick_frame 53 bic xIP0, xIP0, #1 // ArtMethod** sp 54 ldr xIP0, [xIP0] // ArtMethod* method 55 ldr xIP0, [xIP0, #ART_METHOD_ACCESS_FLAGS_OFFSET] // uint32_t access_flags 56 mov xIP1, #(ACCESS_FLAGS_METHOD_IS_FAST_NATIVE | ACCESS_FLAGS_METHOD_IS_CRITICAL_NATIVE) 57 tst xIP0, xIP1 58 b.ne .Llookup_stub_fast_native 59 bl artFindNativeMethod 60 b .Llookup_stub_continue 61 .Llookup_stub_fast_native: 62 bl artFindNativeMethodRunnable 63.Llookup_stub_continue: 64 mov x17, x0 // store result in scratch reg. 65 66 // load spill regs. 67 ldp x0, x1, [sp], #16 68 .cfi_adjust_cfa_offset -16 69 ldp x2, x3, [sp], #16 70 .cfi_adjust_cfa_offset -16 71 ldp x4, x5, [sp], #16 72 .cfi_adjust_cfa_offset -16 73 ldp x6, x7, [sp], #16 74 .cfi_adjust_cfa_offset -16 75 ldp d0, d1, [sp], #16 76 .cfi_adjust_cfa_offset -16 77 ldp d2, d3, [sp], #16 78 .cfi_adjust_cfa_offset -16 79 ldp d4, d5, [sp], #16 80 .cfi_adjust_cfa_offset -16 81 ldp d6, d7, [sp], #16 82 .cfi_adjust_cfa_offset -16 83 ldp x29, x30, [sp], #16 84 .cfi_adjust_cfa_offset -16 85 .cfi_restore x29 86 .cfi_restore x30 87 88 cbz x17, 1f // is method code null ? 89 br x17 // if non-null, tail call to method's code. 90 911: 92 ret // restore regs and return to caller to handle exception. 93END art_jni_dlsym_lookup_stub 94 95ENTRY art_jni_dlsym_lookup_critical_stub 96 // The hidden arg holding the tagged method (bit 0 set means GenericJNI) is x15. 97 // For Generic JNI we already have a managed frame, so we reuse the art_jni_dlsym_lookup_stub. 98 tbnz x15, #0, art_jni_dlsym_lookup_stub 99 100 // We need to create a GenericJNI managed frame above the stack args. 101 102 // GenericJNI frame is similar to SaveRegsAndArgs frame with the native method 103 // instead of runtime method saved at the bottom. Note that the runtime shall 104 // not examine the args here, otherwise we would have to move them in registers 105 // and stack to account for the difference between managed and native ABIs. 106 INCREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS 107 SETUP_SAVE_REFS_AND_ARGS_FRAME_INTERNAL sp 108 // Save the hidden arg as method pointer, x0 in the padding. 109 // (x0 is an arg in native ABI but not considered an arg in managed ABI.) 110 SAVE_TWO_REGS x15, x0, 0 111 112 // Call artCriticalNativeOutArgsSize(method) 113 mov x0, x15 // x0 := method (from hidden arg) 114 bl artCriticalNativeOutArgsSize 115 116 // Check if we have any stack args. 117 cbnz x0, .Lcritical_has_stack_args 118 119 // Without stack args, the frame is fully constructed. 120 // Place tagged managed sp in Thread::Current()->top_quick_frame. 121 mov xIP0, sp 122 orr xIP0, xIP0, #1 // Tag as GenericJNI frame. 123 str xIP0, [xSELF, #THREAD_TOP_QUICK_FRAME_OFFSET] 124 125 // Call artFindNativeMethodRunnable() 126 mov x0, xSELF // pass Thread::Current() 127 bl artFindNativeMethodRunnable 128 129 // Store result in scratch reg. 130 mov xIP0, x0 131 132 // Restore frame. 133 .cfi_remember_state 134 RESTORE_TWO_REGS x15, x0, 0 135 RESTORE_SAVE_REFS_AND_ARGS_FRAME 136 REFRESH_MARKING_REGISTER 137 138 // Check for exception. 139 cbz xIP0, .Lcritical_deliver_exception 140 141 // Do the tail call 142 br xIP0 143 .cfi_restore_state 144 .cfi_def_cfa_offset FRAME_SIZE_SAVE_REFS_AND_ARGS 145 146.Lcritical_has_stack_args: 147 // Move the out args size to a scratch register. 148 mov xIP0, x0 149 150 // Restore register args as we're about to move stack args. 151 RESTORE_TWO_REGS x15, x0, 0 152 RESTORE_SAVE_REFS_AND_ARGS_FRAME_INTERNAL sp 153 154 // Move out args. For simplicity include the return address at the end. 155 mov x8, sp // Destination. 156 add x9, sp, xIP0 // Destination end. 1571: 158 ldp x10, x11, [x8, #FRAME_SIZE_SAVE_REFS_AND_ARGS] 159 stp x10, x11, [x8], #16 160 cmp x8, x9 161 bne 1b 162 163 // Save our LR, load caller's LR and redefine CFI to take ownership of the JNI stub frame. 164 str xLR, [x9, #-__SIZEOF_POINTER__] 165 mov xLR, x11 // The last moved value from the loop above. 166 .cfi_def_cfa x9, FRAME_SIZE_SAVE_REFS_AND_ARGS 167 168 // Re-create the SaveRefsAndArgs frame above the args. 169 SETUP_SAVE_REFS_AND_ARGS_FRAME_INTERNAL x9 170 SAVE_TWO_REGS_BASE x9, x15, x0, 0 171 172 // Move the frame register to a callee-save register. 173 mov x29, x9 174 .cfi_def_cfa_register x29 175 176 // Place tagged managed sp in Thread::Current()->top_quick_frame. 177 orr xIP0, x29, #1 // Tag as GenericJNI frame. 178 str xIP0, [xSELF, #THREAD_TOP_QUICK_FRAME_OFFSET] 179 180 // Call artFindNativeMethodRunnable() 181 mov x0, xSELF // pass Thread::Current() 182 bl artFindNativeMethodRunnable 183 184 // Store result in scratch reg. 185 mov xIP0, x0 186 187 // Restore the frame. 188 mov x9, x29 189 .cfi_def_cfa_register x9 190 RESTORE_TWO_REGS_BASE x9, x15, x0, 0 191 RESTORE_SAVE_REFS_AND_ARGS_FRAME_INTERNAL x9 192 REFRESH_MARKING_REGISTER 193 194 // Check for exception. 195 cbz xIP0, 3f 196 197 // Move stack args to their original place. 198 mov x8, x9 1992: 200 ldp x10, x11, [x8, #-16]! 201 stp x10, x11, [x8, #FRAME_SIZE_SAVE_REFS_AND_ARGS] 202 cmp sp, x8 203 bne 2b 204 205 // Replace original return address with caller's return address. 206 ldr xIP1, [x9, #(FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__)] 207 str xLR, [x9, #(FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__)] 208 209 // Restore LR and redefine CFI to release ownership of the JNI stub frame. 210 .cfi_remember_state 211 mov xLR, xIP1 212 .cfi_def_cfa sp, FRAME_SIZE_SAVE_REFS_AND_ARGS 213 214 // Remove the frame reservation. 215 DECREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS 216 217 // Do the tail call. 218 br xIP0 219 .cfi_restore_state 220 .cfi_def_cfa x9, FRAME_SIZE_SAVE_REFS_AND_ARGS 221 2223: 223 // Drop stack args and the SaveRefsAndArgs reservation. 224 mov sp, x9 225 add sp, sp, #FRAME_SIZE_SAVE_REFS_AND_ARGS 226 .cfi_def_cfa sp, 0 227 228.Lcritical_deliver_exception: 229 // When delivering exception, we check that xSELF was saved but the SaveRefsAndArgs frame does 230 // not save it, so we cannot use DELIVER_PENDING_EXCEPTION_FRAME_READY with the above frames. 231 DELIVER_PENDING_EXCEPTION 232END art_jni_dlsym_lookup_critical_stub 233