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_arm.S" 18 19 /* 20 * Jni dlsym lookup stub. 21 */ 22 .extern artFindNativeMethod 23 .extern artFindNativeMethodRunnable 24ENTRY art_jni_dlsym_lookup_stub 25 push {r0, r1, r2, r3, lr} @ spill regs 26 .cfi_adjust_cfa_offset 20 27 .cfi_rel_offset r0, 0 28 .cfi_rel_offset r1, 4 29 .cfi_rel_offset r2, 8 30 .cfi_rel_offset r3, 12 31 .cfi_rel_offset lr, 16 32 sub sp, #12 @ pad stack pointer to align frame 33 .cfi_adjust_cfa_offset 12 34 35 mov r0, rSELF @ pass Thread::Current() 36 // Call artFindNativeMethod() for normal native and artFindNativeMethodRunnable() 37 // for @FastNative or @CriticalNative. 38 ldr ip, [r0, #THREAD_TOP_QUICK_FRAME_OFFSET] // uintptr_t tagged_quick_frame 39 bic ip, #1 // ArtMethod** sp 40 ldr ip, [ip] // ArtMethod* method 41 ldr ip, [ip, #ART_METHOD_ACCESS_FLAGS_OFFSET] // uint32_t access_flags 42 tst ip, #(ACCESS_FLAGS_METHOD_IS_FAST_NATIVE | ACCESS_FLAGS_METHOD_IS_CRITICAL_NATIVE) 43 bne .Llookup_stub_fast_native 44 blx artFindNativeMethod 45 b .Llookup_stub_continue 46.Llookup_stub_fast_native: 47 blx artFindNativeMethodRunnable 48.Llookup_stub_continue: 49 mov r12, r0 @ save result in r12 50 51 add sp, #12 @ restore stack pointer 52 .cfi_adjust_cfa_offset -12 53 cbz r0, 1f @ is method code null? 54 pop {r0, r1, r2, r3, lr} @ restore regs 55 .cfi_adjust_cfa_offset -20 56 .cfi_restore r0 57 .cfi_restore r1 58 .cfi_restore r2 59 .cfi_restore r3 60 .cfi_restore lr 61 bx r12 @ if non-null, tail call to method's code 621: 63 pop {r0, r1, r2, r3, pc} @ restore regs and return to caller to handle exception 64END art_jni_dlsym_lookup_stub 65 66ENTRY art_jni_dlsym_lookup_critical_stub 67 // The hidden arg holding the tagged method (bit 0 set means GenericJNI) is r4. 68 // For Generic JNI we already have a managed frame, so we reuse the art_jni_dlsym_lookup_stub. 69 tst r4, #1 70 bne art_jni_dlsym_lookup_stub 71 72 // We need to create a GenericJNI managed frame above the stack args. 73 74 // GenericJNI frame is similar to SaveRegsAndArgs frame with the native method 75 // instead of runtime method saved at the bottom. Note that the runtime shall 76 // not examine the args here, otherwise we would have to move them in registers 77 // and stack to account for the difference between managed and native ABIs. 78 SETUP_SAVE_REFS_AND_ARGS_FRAME_REGISTERS_ONLY 79 // Save the hidden arg as method pointer, r0 in the padding. 80 // (x0 is an arg in native ABI but not considered an arg in managed ABI.) 81 strd r4, r0, [sp] 82 83 // Call artCriticalNativeOutArgsSize(method) 84 mov r0, r4 // r0 := method (from hidden arg) 85 bl artCriticalNativeOutArgsSize 86 87 // Check if we have any stack args. 88 cbnz r0, .Lcritical_has_stack_args 89 90 // Without stack args, the frame is fully constructed. 91 // Place tagged managed sp in Thread::Current()->top_quick_frame. 92 mov ip, sp 93 orr ip, #1 // Tag as GenericJNI frame. 94 str ip, [rSELF, #THREAD_TOP_QUICK_FRAME_OFFSET] 95 96 // Call artFindNativeMethodRunnable() 97 mov r0, rSELF // pass Thread::Current() 98 bl artFindNativeMethodRunnable 99 100 // Store result in scratch reg. 101 mov ip, r0 102 103 // Restore frame. 104 .cfi_remember_state 105 ldrd r4, r0, [sp] 106 RESTORE_SAVE_REFS_AND_ARGS_FRAME 107 REFRESH_MARKING_REGISTER 108 109 // Check for exception. 110 cmp ip, #0 111 beq .Lcritical_deliver_exception 112 113 // Do the tail call. 114 bx ip 115 .cfi_restore_state 116 .cfi_def_cfa_offset FRAME_SIZE_SAVE_REFS_AND_ARGS 117 118.Lcritical_has_stack_args: 119 // Move the out args size to a scratch register. 120 mov ip, r0 121 122 // Restore register args as we're about to move stack args. 123 ldrd r4, r0, [sp] 124 RESTORE_SAVE_REFS_AND_ARGS_FRAME 125 126 // Reserve space for SaveRefsAndArgs frame. 127 sub sp, #FRAME_SIZE_SAVE_REFS_AND_ARGS 128 .cfi_adjust_cfa_offset FRAME_SIZE_SAVE_REFS_AND_ARGS 129 130 // Save arg regs so that we can use them as temporaries. 131 push {r0-r3} 132 .cfi_adjust_cfa_offset 16 133 134 // Move out args. For simplicity include the return address at the end. 135 add r0, sp, #16 // Destination. 136 add ip, r0, ip // Destination end. 1371: 138 ldrd r2, r3, [r0, #FRAME_SIZE_SAVE_REFS_AND_ARGS] 139 strd r2, r3, [r0], #8 140 cmp r0, ip 141 bne 1b 142 143 // Save our LR, load caller's LR and redefine CFI to take ownership of the JNI stub frame. 144 str lr, [ip, #-__SIZEOF_POINTER__] 145 mov lr, r3 // The last moved value from the loop above. 146 .cfi_def_cfa ip, FRAME_SIZE_SAVE_REFS_AND_ARGS 147 148 // Restore arg regs. 149 pop {r0-r3} // No `.cfi_adjust_cfa_offset`, CFA register is currently ip, not sp. 150 151 // Re-create the SaveRefsAndArgs frame above the args. 152 strd r4, r0, [ip] // r0 in the padding as before. 153 add r4, ip, FRAME_SIZE_SAVE_REFS_AND_ARGS - 40 154 stmia r4, {r1-r3, r5-r8, r10-r11, lr} @ 10 words of callee saves and args. 155 .cfi_rel_offset r1, FRAME_SIZE_SAVE_REFS_AND_ARGS - 40 + 0 156 .cfi_rel_offset r2, FRAME_SIZE_SAVE_REFS_AND_ARGS - 40 + 4 157 .cfi_rel_offset r3, FRAME_SIZE_SAVE_REFS_AND_ARGS - 40 + 8 158 .cfi_rel_offset r5, FRAME_SIZE_SAVE_REFS_AND_ARGS - 40 + 12 159 .cfi_rel_offset r6, FRAME_SIZE_SAVE_REFS_AND_ARGS - 40 + 16 160 .cfi_rel_offset r7, FRAME_SIZE_SAVE_REFS_AND_ARGS - 40 + 20 161 .cfi_rel_offset r8, FRAME_SIZE_SAVE_REFS_AND_ARGS - 40 + 24 162 .cfi_rel_offset r10, FRAME_SIZE_SAVE_REFS_AND_ARGS - 40 + 28 163 .cfi_rel_offset r11, FRAME_SIZE_SAVE_REFS_AND_ARGS - 40 + 32 164 .cfi_rel_offset lr, FRAME_SIZE_SAVE_REFS_AND_ARGS - 40 + 36 165 vstmdb r4!, {s0-s15} @ 16 words of float args. 166 167 // Move the frame register to a callee-save register. 168 mov r11, ip 169 .cfi_def_cfa_register r11 170 171 // Place tagged managed sp in Thread::Current()->top_quick_frame. 172 orr ip, r11, #1 // Tag as GenericJNI frame. 173 str ip, [rSELF, #THREAD_TOP_QUICK_FRAME_OFFSET] 174 175 // Call artFindNativeMethodRunnable() 176 mov r0, rSELF // pass Thread::Current() 177 bl artFindNativeMethodRunnable 178 179 // Store result in scratch reg. 180 mov ip, r0 181 182 // Restore the frame. We shall not need the method anymore, so use r4 as scratch register. 183 mov r4, r11 184 .cfi_def_cfa_register r4 185 ldr r0, [r4, #4] 186 add r11, r4, #(FRAME_SIZE_SAVE_REFS_AND_ARGS - 40 - 64) 187 vldmia r11!, {s0-s15} @ 16 words of float args. 188 ldmia r11, {r1-r3, r5-r8, r10-r11, lr} @ 10 words of callee saves and args. 189 .cfi_restore r1 190 .cfi_restore r2 191 .cfi_restore r3 192 .cfi_restore r5 193 .cfi_restore r6 194 .cfi_restore r7 195 .cfi_restore r8 196 .cfi_restore r10 197 .cfi_restore r11 198 .cfi_restore lr 199 REFRESH_MARKING_REGISTER 200 201 // Check for exception. 202 cmp ip, #0 203 beq 3f 204 205 // Save arg regs so that we can use them as temporaries. 206 push {r0-r3} // No `.cfi_adjust_cfa_offset`, CFA register is currently r4, not sp. 207 208 // Move stack args to their original place. 209 mov r0, r4 210 add r1, sp, #16 2112: 212 ldrd r2, r3, [r0, #-8]! 213 strd r2, r3, [r0, #FRAME_SIZE_SAVE_REFS_AND_ARGS] 214 cmp r1, r0 215 bne 2b 216 217 // Replace original return address with caller's return address. 218 ldr r1, [r4, #(FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__)] 219 str lr, [r4, #(FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__)] 220 221 // Restore LR and redefine CFI to release ownership of the JNI stub frame. 222 .cfi_remember_state 223 mov lr, r1 224 .cfi_def_cfa sp, FRAME_SIZE_SAVE_REFS_AND_ARGS + 16 225 226 // Restore args 227 pop {r0-r3} 228 .cfi_adjust_cfa_offset -16 229 230 // Remove the frame reservation. 231 add sp, #FRAME_SIZE_SAVE_REFS_AND_ARGS 232 .cfi_adjust_cfa_offset -FRAME_SIZE_SAVE_REFS_AND_ARGS 233 234 // Do the tail call. 235 bx ip 236 .cfi_restore_state 237 .cfi_def_cfa x4, FRAME_SIZE_SAVE_REFS_AND_ARGS 238 2393: 240 // Drop stack args and the SaveRefsAndArgs reservation. 241 mov sp, r4 242 add sp, #FRAME_SIZE_SAVE_REFS_AND_ARGS 243 .cfi_def_cfa sp, 0 244 245.Lcritical_deliver_exception: 246 // When delivering exception, we check that rSELF was saved but the SaveRefsAndArgs frame does 247 // not save it, so we cannot use DELIVER_PENDING_EXCEPTION_FRAME_READY with the above frames. 248 DELIVER_PENDING_EXCEPTION 249END art_jni_dlsym_lookup_critical_stub 250