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