quick_entrypoints_arm64.S revision f686c3feabe3519bedd1f3001e5dd598f46946ef
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#include "arch/quick_alloc_entrypoints.S"
20
21
22    /*
23     * Macro that sets up the callee save frame to conform with
24     * Runtime::CreateCalleeSaveMethod(kSaveAll)
25     */
26.macro SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
27    adrp xIP0, :got:_ZN3art7Runtime9instance_E
28    ldr xIP0, [xIP0, #:got_lo12:_ZN3art7Runtime9instance_E]
29
30    // Our registers aren't intermixed - just spill in order.
31    ldr xIP0, [xIP0]  // xIP0 = & (art::Runtime * art::Runtime.instance_) .
32
33    // xIP0 = (ArtMethod*) Runtime.instance_.callee_save_methods[kRefAndArgs]  .
34    // Loads appropriate callee-save-method.
35    ldr xIP0, [xIP0, RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET ]
36
37    sub sp, sp, #176
38    .cfi_adjust_cfa_offset 176
39
40    // Ugly compile-time check, but we only have the preprocessor.
41#if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVE != 176)
42#error "SAVE_ALL_CALLEE_SAVE_FRAME(ARM64) size not as expected."
43#endif
44
45    // Stack alignment filler [sp, #8].
46    // FP callee-saves.
47    stp d8, d9,   [sp, #16]
48    stp d10, d11, [sp, #32]
49    stp d12, d13, [sp, #48]
50    stp d14, d15, [sp, #64]
51
52    // GP callee-saves
53    stp x19, x20, [sp, #80]
54    .cfi_rel_offset x19, 80
55    .cfi_rel_offset x20, 88
56
57    stp x21, x22, [sp, #96]
58    .cfi_rel_offset x21, 96
59    .cfi_rel_offset x22, 104
60
61    stp x23, x24, [sp, #112]
62    .cfi_rel_offset x23, 112
63    .cfi_rel_offset x24, 120
64
65    stp x25, x26, [sp, #128]
66    .cfi_rel_offset x25, 128
67    .cfi_rel_offset x26, 136
68
69    stp x27, x28, [sp, #144]
70    .cfi_rel_offset x27, 144
71    .cfi_rel_offset x28, 152
72
73    stp x29, xLR, [sp, #160]
74    .cfi_rel_offset x29, 160
75    .cfi_rel_offset x30, 168
76
77    // Store ArtMethod* Runtime::callee_save_methods_[kRefsAndArgs].
78    str xIP0, [sp]
79    // Place sp in Thread::Current()->top_quick_frame.
80    mov xIP0, sp
81    str xIP0, [xSELF, # THREAD_TOP_QUICK_FRAME_OFFSET]
82.endm
83
84    /*
85     * Macro that sets up the callee save frame to conform with
86     * Runtime::CreateCalleeSaveMethod(kRefsOnly).
87     */
88.macro SETUP_REFS_ONLY_CALLEE_SAVE_FRAME
89    adrp xIP0, :got:_ZN3art7Runtime9instance_E
90    ldr xIP0, [xIP0, #:got_lo12:_ZN3art7Runtime9instance_E]
91
92    // Our registers aren't intermixed - just spill in order.
93    ldr xIP0, [xIP0]  // xIP0 = & (art::Runtime * art::Runtime.instance_) .
94
95    // xIP0 = (ArtMethod*) Runtime.instance_.callee_save_methods[kRefOnly]  .
96    // Loads appropriate callee-save-method.
97    ldr xIP0, [xIP0, RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET ]
98
99    sub sp, sp, #96
100    .cfi_adjust_cfa_offset 96
101
102    // Ugly compile-time check, but we only have the preprocessor.
103#if (FRAME_SIZE_REFS_ONLY_CALLEE_SAVE != 96)
104#error "REFS_ONLY_CALLEE_SAVE_FRAME(ARM64) size not as expected."
105#endif
106
107    // GP callee-saves.
108    // x20 paired with ArtMethod* - see below.
109    stp x21, x22, [sp, #16]
110    .cfi_rel_offset x21, 16
111    .cfi_rel_offset x22, 24
112
113    stp x23, x24, [sp, #32]
114    .cfi_rel_offset x23, 32
115    .cfi_rel_offset x24, 40
116
117    stp x25, x26, [sp, #48]
118    .cfi_rel_offset x25, 48
119    .cfi_rel_offset x26, 56
120
121    stp x27, x28, [sp, #64]
122    .cfi_rel_offset x27, 64
123    .cfi_rel_offset x28, 72
124
125    stp x29, xLR, [sp, #80]
126    .cfi_rel_offset x29, 80
127    .cfi_rel_offset x30, 88
128
129    // Store ArtMethod* Runtime::callee_save_methods_[kRefsOnly].
130    stp xIP0, x20, [sp]
131    .cfi_rel_offset x20, 8
132
133    // Place sp in Thread::Current()->top_quick_frame.
134    mov xIP0, sp
135    str xIP0, [xSELF, # THREAD_TOP_QUICK_FRAME_OFFSET]
136.endm
137
138// TODO: Probably no need to restore registers preserved by aapcs64.
139.macro RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
140    // Callee-saves.
141    ldr x20, [sp, #8]
142    .cfi_restore x20
143
144    ldp x21, x22, [sp, #16]
145    .cfi_restore x21
146    .cfi_restore x22
147
148    ldp x23, x24, [sp, #32]
149    .cfi_restore x23
150    .cfi_restore x24
151
152    ldp x25, x26, [sp, #48]
153    .cfi_restore x25
154    .cfi_restore x26
155
156    ldp x27, x28, [sp, #64]
157    .cfi_restore x27
158    .cfi_restore x28
159
160    ldp x29, xLR, [sp, #80]
161    .cfi_restore x29
162    .cfi_restore x30
163
164    add sp, sp, #96
165    .cfi_adjust_cfa_offset -96
166.endm
167
168.macro POP_REFS_ONLY_CALLEE_SAVE_FRAME
169    add sp, sp, #96
170    .cfi_adjust_cfa_offset - 96
171.endm
172
173.macro RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
174    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
175    ret
176.endm
177
178
179.macro SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL
180    sub sp, sp, #224
181    .cfi_adjust_cfa_offset 224
182
183    // Ugly compile-time check, but we only have the preprocessor.
184#if (FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE != 224)
185#error "REFS_AND_ARGS_CALLEE_SAVE_FRAME(ARM64) size not as expected."
186#endif
187
188    // Stack alignment filler [sp, #8].
189    // FP args.
190    stp d0, d1, [sp, #16]
191    stp d2, d3, [sp, #32]
192    stp d4, d5, [sp, #48]
193    stp d6, d7, [sp, #64]
194
195    // Core args.
196    stp x1, x2, [sp, #80]
197    .cfi_rel_offset x1, 80
198    .cfi_rel_offset x2, 88
199
200    stp x3, x4, [sp, #96]
201    .cfi_rel_offset x3, 96
202    .cfi_rel_offset x4, 104
203
204    stp x5, x6, [sp, #112]
205    .cfi_rel_offset x5, 112
206    .cfi_rel_offset x6, 120
207
208    // x7, Callee-saves.
209    stp x7, x20, [sp, #128]
210    .cfi_rel_offset x7, 128
211    .cfi_rel_offset x20, 136
212
213    stp x21, x22, [sp, #144]
214    .cfi_rel_offset x21, 144
215    .cfi_rel_offset x22, 152
216
217    stp x23, x24, [sp, #160]
218    .cfi_rel_offset x23, 160
219    .cfi_rel_offset x24, 168
220
221    stp x25, x26, [sp, #176]
222    .cfi_rel_offset x25, 176
223    .cfi_rel_offset x26, 184
224
225    stp x27, x28, [sp, #192]
226    .cfi_rel_offset x27, 192
227    .cfi_rel_offset x28, 200
228
229    // x29(callee-save) and LR.
230    stp x29, xLR, [sp, #208]
231    .cfi_rel_offset x29, 208
232    .cfi_rel_offset x30, 216
233
234.endm
235
236    /*
237     * Macro that sets up the callee save frame to conform with
238     * Runtime::CreateCalleeSaveMethod(kRefsAndArgs).
239     *
240     * TODO This is probably too conservative - saving FP & LR.
241     */
242.macro SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME
243    adrp xIP0, :got:_ZN3art7Runtime9instance_E
244    ldr xIP0, [xIP0, #:got_lo12:_ZN3art7Runtime9instance_E]
245
246    // Our registers aren't intermixed - just spill in order.
247    ldr xIP0, [xIP0]  // xIP0 = & (art::Runtime * art::Runtime.instance_) .
248
249    // xIP0 = (ArtMethod*) Runtime.instance_.callee_save_methods[kRefAndArgs]  .
250    ldr xIP0, [xIP0, RUNTIME_REFS_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET ]
251
252    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL
253
254    str xIP0, [sp]    // Store ArtMethod* Runtime::callee_save_methods_[kRefsAndArgs]
255    // Place sp in Thread::Current()->top_quick_frame.
256    mov xIP0, sp
257    str xIP0, [xSELF, # THREAD_TOP_QUICK_FRAME_OFFSET]
258.endm
259
260.macro SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_WITH_METHOD_IN_X0
261    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL
262    str x0, [sp, #0]  // Store ArtMethod* to bottom of stack.
263    // Place sp in Thread::Current()->top_quick_frame.
264    mov xIP0, sp
265    str xIP0, [xSELF, # THREAD_TOP_QUICK_FRAME_OFFSET]
266.endm
267
268// TODO: Probably no need to restore registers preserved by aapcs64.
269.macro RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
270    // FP args.
271    ldp d0, d1, [sp, #16]
272    ldp d2, d3, [sp, #32]
273    ldp d4, d5, [sp, #48]
274    ldp d6, d7, [sp, #64]
275
276    // Core args.
277    ldp x1, x2, [sp, #80]
278    .cfi_restore x1
279    .cfi_restore x2
280
281    ldp x3, x4, [sp, #96]
282    .cfi_restore x3
283    .cfi_restore x4
284
285    ldp x5, x6, [sp, #112]
286    .cfi_restore x5
287    .cfi_restore x6
288
289    // x7, Callee-saves.
290    ldp x7, x20, [sp, #128]
291    .cfi_restore x7
292    .cfi_restore x20
293
294    ldp x21, x22, [sp, #144]
295    .cfi_restore x21
296    .cfi_restore x22
297
298    ldp x23, x24, [sp, #160]
299    .cfi_restore x23
300    .cfi_restore x24
301
302    ldp x25, x26, [sp, #176]
303    .cfi_restore x25
304    .cfi_restore x26
305
306    ldp x27, x28, [sp, #192]
307    .cfi_restore x27
308    .cfi_restore x28
309
310    // x29(callee-save) and LR.
311    ldp x29, xLR, [sp, #208]
312    .cfi_restore x29
313    .cfi_restore x30
314
315    add sp, sp, #224
316    .cfi_adjust_cfa_offset -224
317.endm
318
319    /*
320     * Macro that sets up the callee save frame to conform with
321     * Runtime::CreateCalleeSaveMethod(kSaveEverything)
322     */
323.macro SETUP_SAVE_EVERYTHING_CALLEE_SAVE_FRAME
324    sub sp, sp, #512
325    .cfi_adjust_cfa_offset 512
326
327    // Ugly compile-time check, but we only have the preprocessor.
328#if (FRAME_SIZE_SAVE_EVERYTHING_CALLEE_SAVE != 512)
329#error "SAVE_EVERYTHING_CALLEE_SAVE_FRAME(ARM64) size not as expected."
330#endif
331
332    // Save FP registers.
333    stp d0, d1,   [sp, #8]
334    stp d2, d3,   [sp, #24]
335    stp d4, d5,   [sp, #40]
336    stp d6, d7,   [sp, #56]
337    stp d8, d9,   [sp, #72]
338    stp d10, d11, [sp, #88]
339    stp d12, d13, [sp, #104]
340    stp d14, d15, [sp, #120]
341    stp d16, d17, [sp, #136]
342    stp d18, d19, [sp, #152]
343    stp d20, d21, [sp, #168]
344    stp d22, d23, [sp, #184]
345    stp d24, d25, [sp, #200]
346    stp d26, d27, [sp, #216]
347    stp d28, d29, [sp, #232]
348    stp d30, d31, [sp, #248]
349
350    // Save core registers.
351    str x0,       [sp, #264]
352    .cfi_rel_offset x0, 264
353
354    stp x1, x2,   [sp, #272]
355    .cfi_rel_offset x1, 272
356    .cfi_rel_offset x2, 280
357
358    stp x3, x4,   [sp, #288]
359    .cfi_rel_offset x3, 288
360    .cfi_rel_offset x4, 296
361
362    stp x5, x6,   [sp, #304]
363    .cfi_rel_offset x5, 304
364    .cfi_rel_offset x6, 312
365
366    stp x7, x8,   [sp, #320]
367    .cfi_rel_offset x7, 320
368    .cfi_rel_offset x8, 328
369
370    stp x9, x10,  [sp, #336]
371    .cfi_rel_offset x9, 336
372    .cfi_rel_offset x10, 344
373
374    stp x11, x12, [sp, #352]
375    .cfi_rel_offset x11, 352
376    .cfi_rel_offset x12, 360
377
378    stp x13, x14, [sp, #368]
379    .cfi_rel_offset x13, 368
380    .cfi_rel_offset x14, 376
381
382    stp x15, x16, [sp, #384]
383    .cfi_rel_offset x15, 384
384    .cfi_rel_offset x16, 392
385
386    stp x17, x18, [sp, #400]
387    .cfi_rel_offset x17, 400
388    .cfi_rel_offset x18, 408
389
390    stp x19, x20, [sp, #416]
391    .cfi_rel_offset x19, 416
392    .cfi_rel_offset x20, 424
393
394    stp x21, x22, [sp, #432]
395    .cfi_rel_offset x21, 432
396    .cfi_rel_offset x22, 440
397
398    stp x23, x24, [sp, #448]
399    .cfi_rel_offset x23, 448
400    .cfi_rel_offset x24, 456
401
402    stp x25, x26, [sp, #464]
403    .cfi_rel_offset x25, 464
404    .cfi_rel_offset x26, 472
405
406    stp x27, x28, [sp, #480]
407    .cfi_rel_offset x27, 480
408    .cfi_rel_offset x28, 488
409
410    stp x29, xLR, [sp, #496]
411    .cfi_rel_offset x29, 496
412    .cfi_rel_offset x30, 504
413
414    adrp xIP0, :got:_ZN3art7Runtime9instance_E
415    ldr xIP0, [xIP0, #:got_lo12:_ZN3art7Runtime9instance_E]
416
417    ldr xIP0, [xIP0]  // xIP0 = & (art::Runtime * art::Runtime.instance_) .
418
419    // xIP0 = (ArtMethod*) Runtime.instance_.callee_save_methods[kSaveEverything]  .
420    // Loads appropriate callee-save-method.
421    ldr xIP0, [xIP0, RUNTIME_SAVE_EVERYTHING_CALLEE_SAVE_FRAME_OFFSET ]
422
423    // Store ArtMethod* Runtime::callee_save_methods_[kSaveEverything].
424    str xIP0, [sp]
425    // Place sp in Thread::Current()->top_quick_frame.
426    mov xIP0, sp
427    str xIP0, [xSELF, # THREAD_TOP_QUICK_FRAME_OFFSET]
428.endm
429
430.macro RESTORE_SAVE_EVERYTHING_CALLEE_SAVE_FRAME
431    // Restore FP registers.
432    ldp d0, d1,   [sp, #8]
433    ldp d2, d3,   [sp, #24]
434    ldp d4, d5,   [sp, #40]
435    ldp d6, d7,   [sp, #56]
436    ldp d8, d9,   [sp, #72]
437    ldp d10, d11, [sp, #88]
438    ldp d12, d13, [sp, #104]
439    ldp d14, d15, [sp, #120]
440    ldp d16, d17, [sp, #136]
441    ldp d18, d19, [sp, #152]
442    ldp d20, d21, [sp, #168]
443    ldp d22, d23, [sp, #184]
444    ldp d24, d25, [sp, #200]
445    ldp d26, d27, [sp, #216]
446    ldp d28, d29, [sp, #232]
447    ldp d30, d31, [sp, #248]
448
449    // Restore core registers.
450    ldr x0,       [sp, #264]
451    .cfi_restore x0
452
453    ldp x1, x2,   [sp, #272]
454    .cfi_restore x1
455    .cfi_restore x2
456
457    ldp x3, x4,   [sp, #288]
458    .cfi_restore x3
459    .cfi_restore x4
460
461    ldp x5, x6,   [sp, #304]
462    .cfi_restore x5
463    .cfi_restore x6
464
465    ldp x7, x8,   [sp, #320]
466    .cfi_restore x7
467    .cfi_restore x8
468
469    ldp x9, x10,  [sp, #336]
470    .cfi_restore x9
471    .cfi_restore x10
472
473    ldp x11, x12, [sp, #352]
474    .cfi_restore x11
475    .cfi_restore x12
476
477    ldp x13, x14, [sp, #368]
478    .cfi_restore x13
479    .cfi_restore x14
480
481    ldp x15, x16, [sp, #384]
482    .cfi_restore x15
483    .cfi_restore x16
484
485    ldp x17, x18, [sp, #400]
486    .cfi_restore x17
487    .cfi_restore x18
488
489    ldp x19, x20, [sp, #416]
490    .cfi_restore x19
491    .cfi_restore x20
492
493    ldp x21, x22, [sp, #432]
494    .cfi_restore x21
495    .cfi_restore x22
496
497    ldp x23, x24, [sp, #448]
498    .cfi_restore x23
499    .cfi_restore x24
500
501    ldp x25, x26, [sp, #464]
502    .cfi_restore x25
503    .cfi_restore x26
504
505    ldp x27, x28, [sp, #480]
506    .cfi_restore x27
507    .cfi_restore x28
508
509    ldp x29, xLR, [sp, #496]
510    .cfi_restore x29
511    .cfi_restore x30
512
513    add sp, sp, #512
514    .cfi_adjust_cfa_offset -512
515.endm
516
517.macro RETURN_IF_RESULT_IS_ZERO
518    cbnz x0, 1f                // result non-zero branch over
519    ret                        // return
5201:
521.endm
522
523.macro RETURN_IF_RESULT_IS_NON_ZERO
524    cbz x0, 1f                 // result zero branch over
525    ret                        // return
5261:
527.endm
528
529    /*
530     * Macro that set calls through to artDeliverPendingExceptionFromCode, where the pending
531     * exception is Thread::Current()->exception_
532     */
533.macro DELIVER_PENDING_EXCEPTION
534    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
535    mov x0, xSELF
536
537    // Point of no return.
538    b artDeliverPendingExceptionFromCode  // artDeliverPendingExceptionFromCode(Thread*)
539    brk 0  // Unreached
540.endm
541
542.macro RETURN_OR_DELIVER_PENDING_EXCEPTION_REG reg
543    ldr \reg, [xSELF, # THREAD_EXCEPTION_OFFSET]   // Get exception field.
544    cbnz \reg, 1f
545    ret
5461:
547    DELIVER_PENDING_EXCEPTION
548.endm
549
550.macro RETURN_OR_DELIVER_PENDING_EXCEPTION
551    RETURN_OR_DELIVER_PENDING_EXCEPTION_REG xIP0
552.endm
553
554// Same as above with x1. This is helpful in stubs that want to avoid clobbering another register.
555.macro RETURN_OR_DELIVER_PENDING_EXCEPTION_X1
556    RETURN_OR_DELIVER_PENDING_EXCEPTION_REG x1
557.endm
558
559.macro RETURN_IF_W0_IS_ZERO_OR_DELIVER
560    cbnz w0, 1f                // result non-zero branch over
561    ret                        // return
5621:
563    DELIVER_PENDING_EXCEPTION
564.endm
565
566.macro NO_ARG_RUNTIME_EXCEPTION c_name, cxx_name
567    .extern \cxx_name
568ENTRY \c_name
569    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
570    mov x0, xSELF                     // pass Thread::Current
571    b   \cxx_name                     // \cxx_name(Thread*)
572END \c_name
573.endm
574
575.macro ONE_ARG_RUNTIME_EXCEPTION c_name, cxx_name
576    .extern \cxx_name
577ENTRY \c_name
578    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context.
579    mov x1, xSELF                     // pass Thread::Current.
580    b   \cxx_name                     // \cxx_name(arg, Thread*).
581    brk 0
582END \c_name
583.endm
584
585.macro TWO_ARG_RUNTIME_EXCEPTION c_name, cxx_name
586    .extern \cxx_name
587ENTRY \c_name
588    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
589    mov x2, xSELF                     // pass Thread::Current
590    b   \cxx_name                     // \cxx_name(arg1, arg2, Thread*)
591    brk 0
592END \c_name
593.endm
594
595    /*
596     * Called by managed code, saves callee saves and then calls artThrowException
597     * that will place a mock Method* at the bottom of the stack. Arg1 holds the exception.
598     */
599ONE_ARG_RUNTIME_EXCEPTION art_quick_deliver_exception, artDeliverExceptionFromCode
600
601    /*
602     * Called by managed code to create and deliver a NullPointerException.
603     */
604NO_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode
605
606    /*
607     * Call installed by a signal handler to create and deliver a NullPointerException.
608     */
609ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception_from_signal, artThrowNullPointerExceptionFromSignal
610
611    /*
612     * Called by managed code to create and deliver an ArithmeticException.
613     */
614NO_ARG_RUNTIME_EXCEPTION art_quick_throw_div_zero, artThrowDivZeroFromCode
615
616    /*
617     * Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds
618     * index, arg2 holds limit.
619     */
620TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_array_bounds, artThrowArrayBoundsFromCode
621
622    /*
623     * Called by managed code to create and deliver a StringIndexOutOfBoundsException
624     * as if thrown from a call to String.charAt(). Arg1 holds index, arg2 holds limit.
625     */
626TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_string_bounds, artThrowStringBoundsFromCode
627
628    /*
629     * Called by managed code to create and deliver a StackOverflowError.
630     */
631NO_ARG_RUNTIME_EXCEPTION art_quick_throw_stack_overflow, artThrowStackOverflowFromCode
632
633    /*
634     * Called by managed code to create and deliver a NoSuchMethodError.
635     */
636ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_no_such_method, artThrowNoSuchMethodFromCode
637
638    /*
639     * All generated callsites for interface invokes and invocation slow paths will load arguments
640     * as usual - except instead of loading arg0/x0 with the target Method*, arg0/x0 will contain
641     * the method_idx.  This wrapper will save arg1-arg3, and call the appropriate C helper.
642     * NOTE: "this" is first visible argument of the target, and so can be found in arg1/x1.
643     *
644     * The helper will attempt to locate the target and return a 128-bit result in x0/x1 consisting
645     * of the target Method* in x0 and method->code_ in x1.
646     *
647     * If unsuccessful, the helper will return null/????. There will be a pending exception in the
648     * thread and we branch to another stub to deliver it.
649     *
650     * On success this wrapper will restore arguments and *jump* to the target, leaving the lr
651     * pointing back to the original caller.
652     *
653     * Adapted from ARM32 code.
654     *
655     * Clobbers xIP0.
656     */
657.macro INVOKE_TRAMPOLINE_BODY cxx_name
658    .extern \cxx_name
659    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME  // save callee saves in case allocation triggers GC
660    // Helper signature is always
661    // (method_idx, *this_object, *caller_method, *self, sp)
662
663    mov    x2, xSELF                      // pass Thread::Current
664    mov    x3, sp
665    bl     \cxx_name                      // (method_idx, this, Thread*, SP)
666    mov    xIP0, x1                       // save Method*->code_
667    RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
668    cbz    x0, 1f                         // did we find the target? if not go to exception delivery
669    br     xIP0                           // tail call to target
6701:
671    DELIVER_PENDING_EXCEPTION
672.endm
673.macro INVOKE_TRAMPOLINE c_name, cxx_name
674ENTRY \c_name
675    INVOKE_TRAMPOLINE_BODY \cxx_name
676END \c_name
677.endm
678
679INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck
680
681INVOKE_TRAMPOLINE art_quick_invoke_static_trampoline_with_access_check, artInvokeStaticTrampolineWithAccessCheck
682INVOKE_TRAMPOLINE art_quick_invoke_direct_trampoline_with_access_check, artInvokeDirectTrampolineWithAccessCheck
683INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
684INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
685
686
687.macro INVOKE_STUB_CREATE_FRAME
688
689SAVE_SIZE=15*8   // x4, x5, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, SP, LR, FP saved.
690SAVE_SIZE_AND_METHOD=SAVE_SIZE+8
691
692
693    mov x9, sp                             // Save stack pointer.
694    .cfi_register sp,x9
695
696    add x10, x2, # SAVE_SIZE_AND_METHOD    // calculate size of frame.
697    sub x10, sp, x10                       // Calculate SP position - saves + ArtMethod* + args
698    and x10, x10, # ~0xf                   // Enforce 16 byte stack alignment.
699    mov sp, x10                            // Set new SP.
700
701    sub x10, x9, #SAVE_SIZE                // Calculate new FP (later). Done here as we must move SP
702    .cfi_def_cfa_register x10              // before this.
703    .cfi_adjust_cfa_offset SAVE_SIZE
704
705    str x28, [x10, #112]
706    .cfi_rel_offset x28, 112
707
708    stp x26, x27, [x10, #96]
709    .cfi_rel_offset x26, 96
710    .cfi_rel_offset x27, 104
711
712    stp x24, x25, [x10, #80]
713    .cfi_rel_offset x24, 80
714    .cfi_rel_offset x25, 88
715
716    stp x22, x23, [x10, #64]
717    .cfi_rel_offset x22, 64
718    .cfi_rel_offset x23, 72
719
720    stp x20, x21, [x10, #48]
721    .cfi_rel_offset x20, 48
722    .cfi_rel_offset x21, 56
723
724    stp x9, x19, [x10, #32]                // Save old stack pointer and x19.
725    .cfi_rel_offset sp, 32
726    .cfi_rel_offset x19, 40
727
728    stp x4, x5, [x10, #16]                 // Save result and shorty addresses.
729    .cfi_rel_offset x4, 16
730    .cfi_rel_offset x5, 24
731
732    stp xFP, xLR, [x10]                    // Store LR & FP.
733    .cfi_rel_offset x29, 0
734    .cfi_rel_offset x30, 8
735
736    mov xFP, x10                           // Use xFP now, as it's callee-saved.
737    .cfi_def_cfa_register x29
738    mov xSELF, x3                          // Move thread pointer into SELF register.
739
740    // Copy arguments into stack frame.
741    // Use simple copy routine for now.
742    // 4 bytes per slot.
743    // X1 - source address
744    // W2 - args length
745    // X9 - destination address.
746    // W10 - temporary
747    add x9, sp, #8                         // Destination address is bottom of stack + null.
748
749    // Copy parameters into the stack. Use numeric label as this is a macro and Clang's assembler
750    // does not have unique-id variables.
7511:
752    cmp w2, #0
753    beq 2f
754    sub w2, w2, #4      // Need 65536 bytes of range.
755    ldr w10, [x1, x2]
756    str w10, [x9, x2]
757
758    b 1b
759
7602:
761    // Store null into ArtMethod* at bottom of frame.
762    str xzr, [sp]
763.endm
764
765.macro INVOKE_STUB_CALL_AND_RETURN
766
767    // load method-> METHOD_QUICK_CODE_OFFSET
768    ldr x9, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64]
769    // Branch to method.
770    blr x9
771
772    // Restore return value address and shorty address.
773    ldp x4,x5, [xFP, #16]
774    .cfi_restore x4
775    .cfi_restore x5
776
777    ldr x28, [xFP, #112]
778    .cfi_restore x28
779
780    ldp x26, x27, [xFP, #96]
781    .cfi_restore x26
782    .cfi_restore x27
783
784    ldp x24, x25, [xFP, #80]
785    .cfi_restore x24
786    .cfi_restore x25
787
788    ldp x22, x23, [xFP, #64]
789    .cfi_restore x22
790    .cfi_restore x23
791
792    ldp x20, x21, [xFP, #48]
793    .cfi_restore x20
794    .cfi_restore x21
795
796    // Store result (w0/x0/s0/d0) appropriately, depending on resultType.
797    ldrb w10, [x5]
798
799    // Check the return type and store the correct register into the jvalue in memory.
800    // Use numeric label as this is a macro and Clang's assembler does not have unique-id variables.
801
802    // Don't set anything for a void type.
803    cmp w10, #'V'
804    beq 3f
805
806    // Is it a double?
807    cmp w10, #'D'
808    bne 1f
809    str d0, [x4]
810    b 3f
811
8121:  // Is it a float?
813    cmp w10, #'F'
814    bne 2f
815    str s0, [x4]
816    b 3f
817
8182:  // Just store x0. Doesn't matter if it is 64 or 32 bits.
819    str x0, [x4]
820
8213:  // Finish up.
822    ldp x2, x19, [xFP, #32]   // Restore stack pointer and x19.
823    .cfi_restore x19
824    mov sp, x2
825    .cfi_restore sp
826
827    ldp xFP, xLR, [xFP]    // Restore old frame pointer and link register.
828    .cfi_restore x29
829    .cfi_restore x30
830
831    ret
832
833.endm
834
835
836/*
837 *  extern"C" void art_quick_invoke_stub(ArtMethod *method,   x0
838 *                                       uint32_t  *args,     x1
839 *                                       uint32_t argsize,    w2
840 *                                       Thread *self,        x3
841 *                                       JValue *result,      x4
842 *                                       char   *shorty);     x5
843 *  +----------------------+
844 *  |                      |
845 *  |  C/C++ frame         |
846 *  |       LR''           |
847 *  |       FP''           | <- SP'
848 *  +----------------------+
849 *  +----------------------+
850 *  |        x28           | <- TODO: Remove callee-saves.
851 *  |         :            |
852 *  |        x19           |
853 *  |        SP'           |
854 *  |        X5            |
855 *  |        X4            |        Saved registers
856 *  |        LR'           |
857 *  |        FP'           | <- FP
858 *  +----------------------+
859 *  | uint32_t out[n-1]    |
860 *  |    :      :          |        Outs
861 *  | uint32_t out[0]      |
862 *  | ArtMethod*           | <- SP  value=null
863 *  +----------------------+
864 *
865 * Outgoing registers:
866 *  x0    - Method*
867 *  x1-x7 - integer parameters.
868 *  d0-d7 - Floating point parameters.
869 *  xSELF = self
870 *  SP = & of ArtMethod*
871 *  x1 = "this" pointer.
872 *
873 */
874ENTRY art_quick_invoke_stub
875    // Spill registers as per AACPS64 calling convention.
876    INVOKE_STUB_CREATE_FRAME
877
878    // Fill registers x/w1 to x/w7 and s/d0 to s/d7 with parameters.
879    // Parse the passed shorty to determine which register to load.
880    // Load addresses for routines that load WXSD registers.
881    adr  x11, .LstoreW2
882    adr  x12, .LstoreX2
883    adr  x13, .LstoreS0
884    adr  x14, .LstoreD0
885
886    // Initialize routine offsets to 0 for integers and floats.
887    // x8 for integers, x15 for floating point.
888    mov x8, #0
889    mov x15, #0
890
891    add x10, x5, #1         // Load shorty address, plus one to skip return value.
892    ldr w1, [x9],#4         // Load "this" parameter, and increment arg pointer.
893
894    // Loop to fill registers.
895.LfillRegisters:
896    ldrb w17, [x10], #1       // Load next character in signature, and increment.
897    cbz w17, .LcallFunction   // Exit at end of signature. Shorty 0 terminated.
898
899    cmp  w17, #'F' // is this a float?
900    bne .LisDouble
901
902    cmp x15, # 8*12         // Skip this load if all registers full.
903    beq .Ladvance4
904
905    add x17, x13, x15       // Calculate subroutine to jump to.
906    br  x17
907
908.LisDouble:
909    cmp w17, #'D'           // is this a double?
910    bne .LisLong
911
912    cmp x15, # 8*12         // Skip this load if all registers full.
913    beq .Ladvance8
914
915    add x17, x14, x15       // Calculate subroutine to jump to.
916    br x17
917
918.LisLong:
919    cmp w17, #'J'           // is this a long?
920    bne .LisOther
921
922    cmp x8, # 6*12          // Skip this load if all registers full.
923    beq .Ladvance8
924
925    add x17, x12, x8        // Calculate subroutine to jump to.
926    br x17
927
928.LisOther:                  // Everything else takes one vReg.
929    cmp x8, # 6*12          // Skip this load if all registers full.
930    beq .Ladvance4
931
932    add x17, x11, x8        // Calculate subroutine to jump to.
933    br x17
934
935.Ladvance4:
936    add x9, x9, #4
937    b .LfillRegisters
938
939.Ladvance8:
940    add x9, x9, #8
941    b .LfillRegisters
942
943// Macro for loading a parameter into a register.
944//  counter - the register with offset into these tables
945//  size - the size of the register - 4 or 8 bytes.
946//  register - the name of the register to be loaded.
947.macro LOADREG counter size register return
948    ldr \register , [x9], #\size
949    add \counter, \counter, 12
950    b \return
951.endm
952
953// Store ints.
954.LstoreW2:
955    LOADREG x8 4 w2 .LfillRegisters
956    LOADREG x8 4 w3 .LfillRegisters
957    LOADREG x8 4 w4 .LfillRegisters
958    LOADREG x8 4 w5 .LfillRegisters
959    LOADREG x8 4 w6 .LfillRegisters
960    LOADREG x8 4 w7 .LfillRegisters
961
962// Store longs.
963.LstoreX2:
964    LOADREG x8 8 x2 .LfillRegisters
965    LOADREG x8 8 x3 .LfillRegisters
966    LOADREG x8 8 x4 .LfillRegisters
967    LOADREG x8 8 x5 .LfillRegisters
968    LOADREG x8 8 x6 .LfillRegisters
969    LOADREG x8 8 x7 .LfillRegisters
970
971// Store singles.
972.LstoreS0:
973    LOADREG x15 4 s0 .LfillRegisters
974    LOADREG x15 4 s1 .LfillRegisters
975    LOADREG x15 4 s2 .LfillRegisters
976    LOADREG x15 4 s3 .LfillRegisters
977    LOADREG x15 4 s4 .LfillRegisters
978    LOADREG x15 4 s5 .LfillRegisters
979    LOADREG x15 4 s6 .LfillRegisters
980    LOADREG x15 4 s7 .LfillRegisters
981
982// Store doubles.
983.LstoreD0:
984    LOADREG x15 8 d0 .LfillRegisters
985    LOADREG x15 8 d1 .LfillRegisters
986    LOADREG x15 8 d2 .LfillRegisters
987    LOADREG x15 8 d3 .LfillRegisters
988    LOADREG x15 8 d4 .LfillRegisters
989    LOADREG x15 8 d5 .LfillRegisters
990    LOADREG x15 8 d6 .LfillRegisters
991    LOADREG x15 8 d7 .LfillRegisters
992
993
994.LcallFunction:
995
996    INVOKE_STUB_CALL_AND_RETURN
997
998END art_quick_invoke_stub
999
1000/*  extern"C"
1001 *     void art_quick_invoke_static_stub(ArtMethod *method,   x0
1002 *                                       uint32_t  *args,     x1
1003 *                                       uint32_t argsize,    w2
1004 *                                       Thread *self,        x3
1005 *                                       JValue *result,      x4
1006 *                                       char   *shorty);     x5
1007 */
1008ENTRY art_quick_invoke_static_stub
1009    // Spill registers as per AACPS64 calling convention.
1010    INVOKE_STUB_CREATE_FRAME
1011
1012    // Fill registers x/w1 to x/w7 and s/d0 to s/d7 with parameters.
1013    // Parse the passed shorty to determine which register to load.
1014    // Load addresses for routines that load WXSD registers.
1015    adr  x11, .LstoreW1_2
1016    adr  x12, .LstoreX1_2
1017    adr  x13, .LstoreS0_2
1018    adr  x14, .LstoreD0_2
1019
1020    // Initialize routine offsets to 0 for integers and floats.
1021    // x8 for integers, x15 for floating point.
1022    mov x8, #0
1023    mov x15, #0
1024
1025    add x10, x5, #1     // Load shorty address, plus one to skip return value.
1026
1027    // Loop to fill registers.
1028.LfillRegisters2:
1029    ldrb w17, [x10], #1         // Load next character in signature, and increment.
1030    cbz w17, .LcallFunction2    // Exit at end of signature. Shorty 0 terminated.
1031
1032    cmp  w17, #'F'          // is this a float?
1033    bne .LisDouble2
1034
1035    cmp x15, # 8*12         // Skip this load if all registers full.
1036    beq .Ladvance4_2
1037
1038    add x17, x13, x15       // Calculate subroutine to jump to.
1039    br  x17
1040
1041.LisDouble2:
1042    cmp w17, #'D'           // is this a double?
1043    bne .LisLong2
1044
1045    cmp x15, # 8*12         // Skip this load if all registers full.
1046    beq .Ladvance8_2
1047
1048    add x17, x14, x15       // Calculate subroutine to jump to.
1049    br x17
1050
1051.LisLong2:
1052    cmp w17, #'J'           // is this a long?
1053    bne .LisOther2
1054
1055    cmp x8, # 7*12          // Skip this load if all registers full.
1056    beq .Ladvance8_2
1057
1058    add x17, x12, x8        // Calculate subroutine to jump to.
1059    br x17
1060
1061.LisOther2:                 // Everything else takes one vReg.
1062    cmp x8, # 7*12          // Skip this load if all registers full.
1063    beq .Ladvance4_2
1064
1065    add x17, x11, x8        // Calculate subroutine to jump to.
1066    br x17
1067
1068.Ladvance4_2:
1069    add x9, x9, #4
1070    b .LfillRegisters2
1071
1072.Ladvance8_2:
1073    add x9, x9, #8
1074    b .LfillRegisters2
1075
1076// Store ints.
1077.LstoreW1_2:
1078    LOADREG x8 4 w1 .LfillRegisters2
1079    LOADREG x8 4 w2 .LfillRegisters2
1080    LOADREG x8 4 w3 .LfillRegisters2
1081    LOADREG x8 4 w4 .LfillRegisters2
1082    LOADREG x8 4 w5 .LfillRegisters2
1083    LOADREG x8 4 w6 .LfillRegisters2
1084    LOADREG x8 4 w7 .LfillRegisters2
1085
1086// Store longs.
1087.LstoreX1_2:
1088    LOADREG x8 8 x1 .LfillRegisters2
1089    LOADREG x8 8 x2 .LfillRegisters2
1090    LOADREG x8 8 x3 .LfillRegisters2
1091    LOADREG x8 8 x4 .LfillRegisters2
1092    LOADREG x8 8 x5 .LfillRegisters2
1093    LOADREG x8 8 x6 .LfillRegisters2
1094    LOADREG x8 8 x7 .LfillRegisters2
1095
1096// Store singles.
1097.LstoreS0_2:
1098    LOADREG x15 4 s0 .LfillRegisters2
1099    LOADREG x15 4 s1 .LfillRegisters2
1100    LOADREG x15 4 s2 .LfillRegisters2
1101    LOADREG x15 4 s3 .LfillRegisters2
1102    LOADREG x15 4 s4 .LfillRegisters2
1103    LOADREG x15 4 s5 .LfillRegisters2
1104    LOADREG x15 4 s6 .LfillRegisters2
1105    LOADREG x15 4 s7 .LfillRegisters2
1106
1107// Store doubles.
1108.LstoreD0_2:
1109    LOADREG x15 8 d0 .LfillRegisters2
1110    LOADREG x15 8 d1 .LfillRegisters2
1111    LOADREG x15 8 d2 .LfillRegisters2
1112    LOADREG x15 8 d3 .LfillRegisters2
1113    LOADREG x15 8 d4 .LfillRegisters2
1114    LOADREG x15 8 d5 .LfillRegisters2
1115    LOADREG x15 8 d6 .LfillRegisters2
1116    LOADREG x15 8 d7 .LfillRegisters2
1117
1118
1119.LcallFunction2:
1120
1121    INVOKE_STUB_CALL_AND_RETURN
1122
1123END art_quick_invoke_static_stub
1124
1125
1126
1127/*  extern"C" void art_quick_osr_stub(void** stack,                x0
1128 *                                    size_t stack_size_in_bytes,  x1
1129 *                                    const uin8_t* native_pc,     x2
1130 *                                    JValue *result,              x3
1131 *                                    char   *shorty,              x4
1132 *                                    Thread *self)                x5
1133 */
1134ENTRY art_quick_osr_stub
1135SAVE_SIZE=15*8   // x3, x4, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, SP, LR, FP saved.
1136    mov x9, sp                             // Save stack pointer.
1137    .cfi_register sp,x9
1138
1139    sub x10, sp, # SAVE_SIZE
1140    and x10, x10, # ~0xf                   // Enforce 16 byte stack alignment.
1141    mov sp, x10                            // Set new SP.
1142
1143    str x28, [sp, #112]
1144    stp x26, x27, [sp, #96]
1145    stp x24, x25, [sp, #80]
1146    stp x22, x23, [sp, #64]
1147    stp x20, x21, [sp, #48]
1148    stp x9, x19, [sp, #32]                // Save old stack pointer and x19.
1149    stp x3, x4, [sp, #16]                 // Save result and shorty addresses.
1150    stp xFP, xLR, [sp]                    // Store LR & FP.
1151    mov xSELF, x5                         // Move thread pointer into SELF register.
1152
1153    sub sp, sp, #16
1154    str xzr, [sp]                         // Store null for ArtMethod* slot
1155    // Branch to stub.
1156    bl .Losr_entry
1157    add sp, sp, #16
1158
1159    // Restore return value address and shorty address.
1160    ldp x3,x4, [sp, #16]
1161    ldr x28, [sp, #112]
1162    ldp x26, x27, [sp, #96]
1163    ldp x24, x25, [sp, #80]
1164    ldp x22, x23, [sp, #64]
1165    ldp x20, x21, [sp, #48]
1166
1167    // Store result (w0/x0/s0/d0) appropriately, depending on resultType.
1168    ldrb w10, [x4]
1169
1170    // Check the return type and store the correct register into the jvalue in memory.
1171
1172    // Don't set anything for a void type.
1173    cmp w10, #'V'
1174    beq .Losr_exit
1175
1176    // Is it a double?
1177    cmp w10, #'D'
1178    bne .Lno_double
1179    str d0, [x3]
1180    b .Losr_exit
1181
1182.Lno_double:  // Is it a float?
1183    cmp w10, #'F'
1184    bne .Lno_float
1185    str s0, [x3]
1186    b .Losr_exit
1187
1188.Lno_float:  // Just store x0. Doesn't matter if it is 64 or 32 bits.
1189    str x0, [x3]
1190
1191.Losr_exit:  // Finish up.
1192    ldp x2, x19, [sp, #32]   // Restore stack pointer and x19.
1193    ldp xFP, xLR, [sp]    // Restore old frame pointer and link register.
1194    mov sp, x2
1195    ret
1196
1197.Losr_entry:
1198    // Update stack pointer for the callee
1199    sub sp, sp, x1
1200
1201    // Update link register slot expected by the callee.
1202    sub w1, w1, #8
1203    str lr, [sp, x1]
1204
1205    // Copy arguments into stack frame.
1206    // Use simple copy routine for now.
1207    // 4 bytes per slot.
1208    // X0 - source address
1209    // W1 - args length
1210    // SP - destination address.
1211    // W10 - temporary
1212.Losr_loop_entry:
1213    cmp w1, #0
1214    beq .Losr_loop_exit
1215    sub w1, w1, #4
1216    ldr w10, [x0, x1]
1217    str w10, [sp, x1]
1218    b .Losr_loop_entry
1219
1220.Losr_loop_exit:
1221    // Branch to the OSR entry point.
1222    br x2
1223
1224END art_quick_osr_stub
1225
1226    /*
1227     * On entry x0 is uintptr_t* gprs_ and x1 is uint64_t* fprs_
1228     */
1229
1230ENTRY art_quick_do_long_jump
1231    // Load FPRs
1232    ldp d0, d1, [x1], #16
1233    ldp d2, d3, [x1], #16
1234    ldp d4, d5, [x1], #16
1235    ldp d6, d7, [x1], #16
1236    ldp d8, d9, [x1], #16
1237    ldp d10, d11, [x1], #16
1238    ldp d12, d13, [x1], #16
1239    ldp d14, d15, [x1], #16
1240    ldp d16, d17, [x1], #16
1241    ldp d18, d19, [x1], #16
1242    ldp d20, d21, [x1], #16
1243    ldp d22, d23, [x1], #16
1244    ldp d24, d25, [x1], #16
1245    ldp d26, d27, [x1], #16
1246    ldp d28, d29, [x1], #16
1247    ldp d30, d31, [x1]
1248
1249    // Load GPRs
1250    // TODO: lots of those are smashed, could optimize.
1251    add x0, x0, #30*8
1252    ldp x30, x1, [x0], #-16          // LR & SP
1253    ldp x28, x29, [x0], #-16
1254    ldp x26, x27, [x0], #-16
1255    ldp x24, x25, [x0], #-16
1256    ldp x22, x23, [x0], #-16
1257    ldp x20, x21, [x0], #-16
1258    ldp x18, x19, [x0], #-16
1259    ldp x16, x17, [x0], #-16
1260    ldp x14, x15, [x0], #-16
1261    ldp x12, x13, [x0], #-16
1262    ldp x10, x11, [x0], #-16
1263    ldp x8, x9, [x0], #-16
1264    ldp x6, x7, [x0], #-16
1265    ldp x4, x5, [x0], #-16
1266    ldp x2, x3, [x0], #-16
1267    mov sp, x1
1268
1269    // Need to load PC, it's at the end (after the space for the unused XZR). Use x1.
1270    ldr x1, [x0, #33*8]
1271    // And the value of x0.
1272    ldr x0, [x0]
1273
1274    br  x1
1275END art_quick_do_long_jump
1276
1277    /*
1278     * Entry from managed code that calls artLockObjectFromCode, may block for GC. x0 holds the
1279     * possibly null object to lock.
1280     *
1281     * Derived from arm32 code.
1282     */
1283    .extern artLockObjectFromCode
1284ENTRY art_quick_lock_object
1285    cbz    w0, .Lslow_lock
1286    add    x4, x0, #MIRROR_OBJECT_LOCK_WORD_OFFSET  // exclusive load/store has no immediate anymore
1287.Lretry_lock:
1288    ldr    w2, [xSELF, #THREAD_ID_OFFSET] // TODO: Can the thread ID really change during the loop?
1289    ldxr   w1, [x4]
1290    mov    x3, x1
1291    and    w3, w3, #LOCK_WORD_GC_STATE_MASK_SHIFTED_TOGGLED  // zero the gc bits
1292    cbnz   w3, .Lnot_unlocked         // already thin locked
1293    // unlocked case - x1: original lock word that's zero except for the read barrier bits.
1294    orr    x2, x1, x2                 // x2 holds thread id with count of 0 with preserved read barrier bits
1295    stxr   w3, w2, [x4]
1296    cbnz   w3, .Llock_stxr_fail       // store failed, retry
1297    dmb    ishld                      // full (LoadLoad|LoadStore) memory barrier
1298    ret
1299.Lnot_unlocked:  // x1: original lock word
1300    lsr    w3, w1, LOCK_WORD_STATE_SHIFT
1301    cbnz   w3, .Lslow_lock            // if either of the top two bits are set, go slow path
1302    eor    w2, w1, w2                 // lock_word.ThreadId() ^ self->ThreadId()
1303    uxth   w2, w2                     // zero top 16 bits
1304    cbnz   w2, .Lslow_lock            // lock word and self thread id's match -> recursive lock
1305                                      // else contention, go to slow path
1306    mov    x3, x1                     // copy the lock word to check count overflow.
1307    and    w3, w3, #LOCK_WORD_GC_STATE_MASK_SHIFTED_TOGGLED  // zero the gc bits.
1308    add    w2, w3, #LOCK_WORD_THIN_LOCK_COUNT_ONE  // increment count in lock word placing in w2 to check overflow
1309    lsr    w3, w2, #LOCK_WORD_GC_STATE_SHIFT     // if the first gc state bit is set, we overflowed.
1310    cbnz   w3, .Lslow_lock            // if we overflow the count go slow path
1311    add    w2, w1, #LOCK_WORD_THIN_LOCK_COUNT_ONE  // increment count for real
1312    stxr   w3, w2, [x4]
1313    cbnz   w3, .Llock_stxr_fail       // store failed, retry
1314    ret
1315.Llock_stxr_fail:
1316    b      .Lretry_lock               // retry
1317.Lslow_lock:
1318    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  // save callee saves in case we block
1319    mov    x1, xSELF                  // pass Thread::Current
1320    bl     artLockObjectFromCode      // (Object* obj, Thread*)
1321    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
1322    RETURN_IF_W0_IS_ZERO_OR_DELIVER
1323END art_quick_lock_object
1324
1325ENTRY art_quick_lock_object_no_inline
1326    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  // save callee saves in case we block
1327    mov    x1, xSELF                  // pass Thread::Current
1328    bl     artLockObjectFromCode      // (Object* obj, Thread*)
1329    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
1330    RETURN_IF_W0_IS_ZERO_OR_DELIVER
1331END art_quick_lock_object_no_inline
1332
1333    /*
1334     * Entry from managed code that calls artUnlockObjectFromCode and delivers exception on failure.
1335     * x0 holds the possibly null object to lock.
1336     *
1337     * Derived from arm32 code.
1338     */
1339    .extern artUnlockObjectFromCode
1340ENTRY art_quick_unlock_object
1341    cbz    x0, .Lslow_unlock
1342    add    x4, x0, #MIRROR_OBJECT_LOCK_WORD_OFFSET  // exclusive load/store has no immediate anymore
1343.Lretry_unlock:
1344#ifndef USE_READ_BARRIER
1345    ldr    w1, [x4]
1346#else
1347    ldxr   w1, [x4]                   // Need to use atomic instructions for read barrier
1348#endif
1349    lsr    w2, w1, LOCK_WORD_STATE_SHIFT
1350    cbnz   w2, .Lslow_unlock          // if either of the top two bits are set, go slow path
1351    ldr    w2, [xSELF, #THREAD_ID_OFFSET]
1352    mov    x3, x1                     // copy lock word to check thread id equality
1353    and    w3, w3, #LOCK_WORD_GC_STATE_MASK_SHIFTED_TOGGLED  // zero the gc bits
1354    eor    w3, w3, w2                 // lock_word.ThreadId() ^ self->ThreadId()
1355    uxth   w3, w3                     // zero top 16 bits
1356    cbnz   w3, .Lslow_unlock          // do lock word and self thread id's match?
1357    mov    x3, x1                     // copy lock word to detect transition to unlocked
1358    and    w3, w3, #LOCK_WORD_GC_STATE_MASK_SHIFTED_TOGGLED  // zero the gc bits
1359    cmp    w3, #LOCK_WORD_THIN_LOCK_COUNT_ONE
1360    bpl    .Lrecursive_thin_unlock
1361    // transition to unlocked
1362    mov    x3, x1
1363    and    w3, w3, #LOCK_WORD_GC_STATE_MASK_SHIFTED  // w3: zero except for the preserved read barrier bits
1364    dmb    ish                        // full (LoadStore|StoreStore) memory barrier
1365#ifndef USE_READ_BARRIER
1366    str    w3, [x4]
1367#else
1368    stxr   w2, w3, [x4]               // Need to use atomic instructions for read barrier
1369    cbnz   w2, .Lunlock_stxr_fail     // store failed, retry
1370#endif
1371    ret
1372.Lrecursive_thin_unlock:  // w1: original lock word
1373    sub    w1, w1, #LOCK_WORD_THIN_LOCK_COUNT_ONE  // decrement count
1374#ifndef USE_READ_BARRIER
1375    str    w1, [x4]
1376#else
1377    stxr   w2, w1, [x4]               // Need to use atomic instructions for read barrier
1378    cbnz   w2, .Lunlock_stxr_fail     // store failed, retry
1379#endif
1380    ret
1381.Lunlock_stxr_fail:
1382    b      .Lretry_unlock               // retry
1383.Lslow_unlock:
1384    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  // save callee saves in case exception allocation triggers GC
1385    mov    x1, xSELF                  // pass Thread::Current
1386    bl     artUnlockObjectFromCode    // (Object* obj, Thread*)
1387    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
1388    RETURN_IF_W0_IS_ZERO_OR_DELIVER
1389END art_quick_unlock_object
1390
1391ENTRY art_quick_unlock_object_no_inline
1392    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  // save callee saves in case exception allocation triggers GC
1393    mov    x1, xSELF                  // pass Thread::Current
1394    bl     artUnlockObjectFromCode    // (Object* obj, Thread*)
1395    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
1396    RETURN_IF_W0_IS_ZERO_OR_DELIVER
1397END art_quick_unlock_object_no_inline
1398
1399    /*
1400     * Entry from managed code that calls artIsAssignableFromCode and on failure calls
1401     * artThrowClassCastException.
1402     */
1403    .extern artThrowClassCastException
1404ENTRY art_quick_check_cast
1405    // Store arguments and link register
1406    // Stack needs to be 16B aligned on calls.
1407    stp x0, x1, [sp,#-32]!
1408    .cfi_adjust_cfa_offset 32
1409    .cfi_rel_offset x0, 0
1410    .cfi_rel_offset x1, 8
1411    str xLR, [sp, #24]
1412    .cfi_rel_offset x30, 24
1413
1414    // Call runtime code
1415    bl artIsAssignableFromCode
1416
1417    // Check for exception
1418    cbz x0, .Lthrow_class_cast_exception
1419
1420    // Restore and return
1421    ldr xLR, [sp, #24]
1422    .cfi_restore x30
1423    ldp x0, x1, [sp], #32
1424    .cfi_restore x0
1425    .cfi_restore x1
1426    .cfi_adjust_cfa_offset -32
1427    ret
1428
1429    .cfi_adjust_cfa_offset 32         // Reset unwind info so following code unwinds.
1430
1431.Lthrow_class_cast_exception:
1432    // Restore
1433    ldr xLR, [sp, #24]
1434    .cfi_restore x30
1435    ldp x0, x1, [sp], #32
1436    .cfi_restore x0
1437    .cfi_restore x1
1438    .cfi_adjust_cfa_offset -32
1439
1440    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
1441    mov x2, xSELF                     // pass Thread::Current
1442    b artThrowClassCastException      // (Class*, Class*, Thread*)
1443    brk 0                             // We should not return here...
1444END art_quick_check_cast
1445
1446// Restore xReg's value from [sp, #offset] if xReg is not the same as xExclude.
1447.macro POP_REG_NE xReg, offset, xExclude
1448    .ifnc \xReg, \xExclude
1449        ldr \xReg, [sp, #\offset]     // restore xReg
1450        .cfi_restore \xReg
1451    .endif
1452.endm
1453
1454// Restore xReg1's value from [sp, #offset] if xReg1 is not the same as xExclude.
1455// Restore xReg2's value from [sp, #(offset + 8)] if xReg2 is not the same as xExclude.
1456.macro POP_REGS_NE xReg1, xReg2, offset, xExclude
1457    .ifc \xReg1, \xExclude
1458        ldr \xReg2, [sp, #(\offset + 8)]        // restore xReg2
1459    .else
1460        .ifc \xReg2, \xExclude
1461            ldr \xReg1, [sp, #\offset]          // restore xReg1
1462        .else
1463            ldp \xReg1, \xReg2, [sp, #\offset]  // restore xReg1 and xReg2
1464        .endif
1465    .endif
1466    .cfi_restore \xReg1
1467    .cfi_restore \xReg2
1468.endm
1469
1470    /*
1471     * Macro to insert read barrier, only used in art_quick_aput_obj.
1472     * xDest, wDest and xObj are registers, offset is a defined literal such as
1473     * MIRROR_OBJECT_CLASS_OFFSET. Dest needs both x and w versions of the same register to handle
1474     * name mismatch between instructions. This macro uses the lower 32b of register when possible.
1475     * TODO: When read barrier has a fast path, add heap unpoisoning support for the fast path.
1476     */
1477.macro READ_BARRIER xDest, wDest, xObj, xTemp, wTemp, offset, number
1478#ifdef USE_READ_BARRIER
1479#ifdef USE_BAKER_READ_BARRIER
1480    ldr \wTemp, [\xObj, #MIRROR_OBJECT_LOCK_WORD_OFFSET]
1481    tbnz \wTemp, #LOCK_WORD_READ_BARRIER_STATE_SHIFT, .Lrb_slowpath\number
1482    // False dependency to avoid needing load/load fence.
1483    add \xObj, \xObj, \xTemp, lsr #32
1484    ldr \wDest, [\xObj, #\offset]   // Heap reference = 32b. This also zero-extends to \xDest.
1485    UNPOISON_HEAP_REF \wDest
1486    b .Lrb_exit\number
1487#endif
1488.Lrb_slowpath\number:
1489    // Store registers used in art_quick_aput_obj (x0-x4, LR), stack is 16B aligned.
1490    stp x0, x1, [sp, #-48]!
1491    .cfi_adjust_cfa_offset 48
1492    .cfi_rel_offset x0, 0
1493    .cfi_rel_offset x1, 8
1494    stp x2, x3, [sp, #16]
1495    .cfi_rel_offset x2, 16
1496    .cfi_rel_offset x3, 24
1497    stp x4, xLR, [sp, #32]
1498    .cfi_rel_offset x4, 32
1499    .cfi_rel_offset x30, 40
1500
1501    // mov x0, \xRef                // pass ref in x0 (no-op for now since parameter ref is unused)
1502    .ifnc \xObj, x1
1503        mov x1, \xObj               // pass xObj
1504    .endif
1505    mov w2, #\offset                // pass offset
1506    bl artReadBarrierSlow           // artReadBarrierSlow(ref, xObj, offset)
1507    // No need to unpoison return value in w0, artReadBarrierSlow() would do the unpoisoning.
1508    .ifnc \wDest, w0
1509        mov \wDest, w0              // save return value in wDest
1510    .endif
1511
1512    // Conditionally restore saved registers
1513    POP_REG_NE x0, 0, \xDest
1514    POP_REG_NE x1, 8, \xDest
1515    POP_REG_NE x2, 16, \xDest
1516    POP_REG_NE x3, 24, \xDest
1517    POP_REG_NE x4, 32, \xDest
1518    ldr xLR, [sp, #40]
1519    .cfi_restore x30
1520    add sp, sp, #48
1521    .cfi_adjust_cfa_offset -48
1522.Lrb_exit\number:
1523#else
1524    ldr \wDest, [\xObj, #\offset]   // Heap reference = 32b. This also zero-extends to \xDest.
1525    UNPOISON_HEAP_REF \wDest
1526#endif  // USE_READ_BARRIER
1527.endm
1528
1529    /*
1530     * Entry from managed code for array put operations of objects where the value being stored
1531     * needs to be checked for compatibility.
1532     * x0 = array, x1 = index, x2 = value
1533     *
1534     * Currently all values should fit into w0/w1/w2, and w1 always will as indices are 32b. We
1535     * assume, though, that the upper 32b are zeroed out. At least for x1/w1 we can do better by
1536     * using index-zero-extension in load/stores.
1537     *
1538     * Temporaries: x3, x4
1539     * TODO: x4 OK? ip seems wrong here.
1540     */
1541ENTRY art_quick_aput_obj_with_null_and_bound_check
1542    tst x0, x0
1543    bne art_quick_aput_obj_with_bound_check
1544    b art_quick_throw_null_pointer_exception
1545END art_quick_aput_obj_with_null_and_bound_check
1546
1547ENTRY art_quick_aput_obj_with_bound_check
1548    ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]
1549    cmp w3, w1
1550    bhi art_quick_aput_obj
1551    mov x0, x1
1552    mov x1, x3
1553    b art_quick_throw_array_bounds
1554END art_quick_aput_obj_with_bound_check
1555
1556#ifdef USE_READ_BARRIER
1557    .extern artReadBarrierSlow
1558#endif
1559ENTRY art_quick_aput_obj
1560    cbz x2, .Ldo_aput_null
1561    READ_BARRIER x3, w3, x0, x3, w3, MIRROR_OBJECT_CLASS_OFFSET, 0  // Heap reference = 32b
1562                                                                    // This also zero-extends to x3
1563    READ_BARRIER x3, w3, x3, x4, w4, MIRROR_CLASS_COMPONENT_TYPE_OFFSET, 1 // Heap reference = 32b
1564    // This also zero-extends to x3
1565    READ_BARRIER x4, w4, x2, x4, w4, MIRROR_OBJECT_CLASS_OFFSET, 2  // Heap reference = 32b
1566                                                                    // This also zero-extends to x4
1567    cmp w3, w4  // value's type == array's component type - trivial assignability
1568    bne .Lcheck_assignability
1569.Ldo_aput:
1570    add x3, x0, #MIRROR_OBJECT_ARRAY_DATA_OFFSET
1571                                                         // "Compress" = do nothing
1572    POISON_HEAP_REF w2
1573    str w2, [x3, x1, lsl #2]                             // Heap reference = 32b
1574    ldr x3, [xSELF, #THREAD_CARD_TABLE_OFFSET]
1575    lsr x0, x0, #7
1576    strb w3, [x3, x0]
1577    ret
1578.Ldo_aput_null:
1579    add x3, x0, #MIRROR_OBJECT_ARRAY_DATA_OFFSET
1580                                                         // "Compress" = do nothing
1581    str w2, [x3, x1, lsl #2]                             // Heap reference = 32b
1582    ret
1583.Lcheck_assignability:
1584    // Store arguments and link register
1585    stp x0, x1, [sp,#-32]!
1586    .cfi_adjust_cfa_offset 32
1587    .cfi_rel_offset x0, 0
1588    .cfi_rel_offset x1, 8
1589    stp x2, xLR, [sp, #16]
1590    .cfi_rel_offset x2, 16
1591    .cfi_rel_offset x30, 24
1592
1593    // Call runtime code
1594    mov x0, x3              // Heap reference, 32b, "uncompress" = do nothing, already zero-extended
1595    mov x1, x4              // Heap reference, 32b, "uncompress" = do nothing, already zero-extended
1596    bl artIsAssignableFromCode
1597
1598    // Check for exception
1599    cbz x0, .Lthrow_array_store_exception
1600
1601    // Restore
1602    ldp x2, x30, [sp, #16]
1603    .cfi_restore x2
1604    .cfi_restore x30
1605    ldp x0, x1, [sp], #32
1606    .cfi_restore x0
1607    .cfi_restore x1
1608    .cfi_adjust_cfa_offset -32
1609
1610    add x3, x0, #MIRROR_OBJECT_ARRAY_DATA_OFFSET
1611                                                          // "Compress" = do nothing
1612    POISON_HEAP_REF w2
1613    str w2, [x3, x1, lsl #2]                              // Heap reference = 32b
1614    ldr x3, [xSELF, #THREAD_CARD_TABLE_OFFSET]
1615    lsr x0, x0, #7
1616    strb w3, [x3, x0]
1617    ret
1618    .cfi_adjust_cfa_offset 32  // 4 restores after cbz for unwinding.
1619.Lthrow_array_store_exception:
1620    ldp x2, x30, [sp, #16]
1621    .cfi_restore x2
1622    .cfi_restore x30
1623    ldp x0, x1, [sp], #32
1624    .cfi_restore x0
1625    .cfi_restore x1
1626    .cfi_adjust_cfa_offset -32
1627
1628    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
1629    mov x1, x2                    // Pass value.
1630    mov x2, xSELF                 // Pass Thread::Current.
1631    b artThrowArrayStoreException // (Object*, Object*, Thread*).
1632    brk 0                         // Unreached.
1633END art_quick_aput_obj
1634
1635// Macro to facilitate adding new allocation entrypoints.
1636.macro ONE_ARG_DOWNCALL name, entrypoint, return
1637    .extern \entrypoint
1638ENTRY \name
1639    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME // save callee saves in case of GC
1640    mov    x1, xSELF                  // pass Thread::Current
1641    bl     \entrypoint                // (uint32_t type_idx, Method* method, Thread*)
1642    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
1643    \return
1644END \name
1645.endm
1646
1647// Macro to facilitate adding new allocation entrypoints.
1648.macro TWO_ARG_DOWNCALL name, entrypoint, return
1649    .extern \entrypoint
1650ENTRY \name
1651    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME // save callee saves in case of GC
1652    mov    x2, xSELF                  // pass Thread::Current
1653    bl     \entrypoint                // (uint32_t type_idx, Method* method, Thread*)
1654    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
1655    \return
1656END \name
1657.endm
1658
1659// Macro to facilitate adding new allocation entrypoints.
1660.macro THREE_ARG_DOWNCALL name, entrypoint, return
1661    .extern \entrypoint
1662ENTRY \name
1663    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME // save callee saves in case of GC
1664    mov    x3, xSELF                  // pass Thread::Current
1665    bl     \entrypoint
1666    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
1667    \return
1668END \name
1669.endm
1670
1671// Macro to facilitate adding new allocation entrypoints.
1672.macro FOUR_ARG_DOWNCALL name, entrypoint, return
1673    .extern \entrypoint
1674ENTRY \name
1675    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME // save callee saves in case of GC
1676    mov    x4, xSELF                  // pass Thread::Current
1677    bl     \entrypoint                //
1678    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
1679    \return
1680    DELIVER_PENDING_EXCEPTION
1681END \name
1682.endm
1683
1684// Macros taking opportunity of code similarities for downcalls with referrer.
1685.macro ONE_ARG_REF_DOWNCALL name, entrypoint, return
1686    .extern \entrypoint
1687ENTRY \name
1688    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  // save callee saves in case of GC
1689    ldr    x1, [sp, #FRAME_SIZE_REFS_ONLY_CALLEE_SAVE] // Load referrer
1690    mov    x2, xSELF                  // pass Thread::Current
1691    bl     \entrypoint                // (uint32_t type_idx, Method* method, Thread*, SP)
1692    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
1693    \return
1694END \name
1695.endm
1696
1697.macro TWO_ARG_REF_DOWNCALL name, entrypoint, return
1698    .extern \entrypoint
1699ENTRY \name
1700    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  // save callee saves in case of GC
1701    ldr    x2, [sp, #FRAME_SIZE_REFS_ONLY_CALLEE_SAVE] // Load referrer
1702    mov    x3, xSELF                  // pass Thread::Current
1703    bl     \entrypoint
1704    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
1705    \return
1706END \name
1707.endm
1708
1709.macro THREE_ARG_REF_DOWNCALL name, entrypoint, return
1710    .extern \entrypoint
1711ENTRY \name
1712    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  // save callee saves in case of GC
1713    ldr    x3, [sp, #FRAME_SIZE_REFS_ONLY_CALLEE_SAVE] // Load referrer
1714    mov    x4, xSELF                  // pass Thread::Current
1715    bl     \entrypoint
1716    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
1717    \return
1718END \name
1719.endm
1720
1721.macro RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
1722    cbz w0, 1f                 // result zero branch over
1723    ret                        // return
17241:
1725    DELIVER_PENDING_EXCEPTION
1726.endm
1727
1728    /*
1729     * Entry from managed code that calls artHandleFillArrayDataFromCode and delivers exception on
1730     * failure.
1731     */
1732TWO_ARG_REF_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, RETURN_IF_W0_IS_ZERO_OR_DELIVER
1733
1734    /*
1735     * Entry from managed code when uninitialized static storage, this stub will run the class
1736     * initializer and deliver the exception on error. On success the static storage base is
1737     * returned.
1738     */
1739ONE_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
1740
1741ONE_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
1742ONE_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
1743
1744ONE_ARG_REF_DOWNCALL art_quick_get_boolean_static, artGetBooleanStaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION_X1
1745ONE_ARG_REF_DOWNCALL art_quick_get_byte_static, artGetByteStaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION_X1
1746ONE_ARG_REF_DOWNCALL art_quick_get_char_static, artGetCharStaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION_X1
1747ONE_ARG_REF_DOWNCALL art_quick_get_short_static, artGetShortStaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION_X1
1748ONE_ARG_REF_DOWNCALL art_quick_get32_static, artGet32StaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION_X1
1749ONE_ARG_REF_DOWNCALL art_quick_get64_static, artGet64StaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION_X1
1750ONE_ARG_REF_DOWNCALL art_quick_get_obj_static, artGetObjStaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION_X1
1751
1752TWO_ARG_REF_DOWNCALL art_quick_get_boolean_instance, artGetBooleanInstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION_X1
1753TWO_ARG_REF_DOWNCALL art_quick_get_byte_instance, artGetByteInstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION_X1
1754TWO_ARG_REF_DOWNCALL art_quick_get_char_instance, artGetCharInstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION_X1
1755TWO_ARG_REF_DOWNCALL art_quick_get_short_instance, artGetShortInstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION_X1
1756TWO_ARG_REF_DOWNCALL art_quick_get32_instance, artGet32InstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION_X1
1757TWO_ARG_REF_DOWNCALL art_quick_get64_instance, artGet64InstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION_X1
1758TWO_ARG_REF_DOWNCALL art_quick_get_obj_instance, artGetObjInstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION_X1
1759
1760TWO_ARG_REF_DOWNCALL art_quick_set8_static, artSet8StaticFromCode, RETURN_IF_W0_IS_ZERO_OR_DELIVER
1761TWO_ARG_REF_DOWNCALL art_quick_set16_static, artSet16StaticFromCode, RETURN_IF_W0_IS_ZERO_OR_DELIVER
1762TWO_ARG_REF_DOWNCALL art_quick_set32_static, artSet32StaticFromCode, RETURN_IF_W0_IS_ZERO_OR_DELIVER
1763TWO_ARG_REF_DOWNCALL art_quick_set_obj_static, artSetObjStaticFromCode, RETURN_IF_W0_IS_ZERO_OR_DELIVER
1764
1765THREE_ARG_REF_DOWNCALL art_quick_set8_instance, artSet8InstanceFromCode, RETURN_IF_W0_IS_ZERO_OR_DELIVER
1766THREE_ARG_REF_DOWNCALL art_quick_set16_instance, artSet16InstanceFromCode, RETURN_IF_W0_IS_ZERO_OR_DELIVER
1767THREE_ARG_REF_DOWNCALL art_quick_set32_instance, artSet32InstanceFromCode, RETURN_IF_W0_IS_ZERO_OR_DELIVER
1768THREE_ARG_REF_DOWNCALL art_quick_set64_instance, artSet64InstanceFromCode, RETURN_IF_W0_IS_ZERO_OR_DELIVER
1769THREE_ARG_REF_DOWNCALL art_quick_set_obj_instance, artSetObjInstanceFromCode, RETURN_IF_W0_IS_ZERO_OR_DELIVER
1770
1771// This is separated out as the argument order is different.
1772    .extern artSet64StaticFromCode
1773ENTRY art_quick_set64_static
1774    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  // save callee saves in case of GC
1775    ldr    x1, [sp, #FRAME_SIZE_REFS_ONLY_CALLEE_SAVE] // Load referrer
1776                                      // x2 contains the parameter
1777    mov    x3, xSELF                  // pass Thread::Current
1778    bl     artSet64StaticFromCode
1779    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
1780    RETURN_IF_W0_IS_ZERO_OR_DELIVER
1781END art_quick_set64_static
1782
1783    /*
1784     * Entry from managed code to resolve a string, this stub will allocate a String and deliver an
1785     * exception on error. On success the String is returned. w0 holds the string index. The fast
1786     * path check for hit in strings cache has already been performed.
1787     */
1788ONE_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
1789
1790// Generate the allocation entrypoints for each allocator.
1791GENERATE_ALLOC_ENTRYPOINTS_FOR_NON_REGION_ALLOCATORS
1792// Comment out allocators that have arm64 specific asm.
1793// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_region_tlab, RegionTLAB) implemented in asm
1794// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_region_tlab, RegionTLAB)
1795// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_region_tlab, RegionTLAB)
1796GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_region_tlab, RegionTLAB)
1797// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_region_tlab, RegionTLAB) implemented in asm
1798// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_region_tlab, RegionTLAB)
1799GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_region_tlab, RegionTLAB)
1800GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_region_tlab, RegionTLAB)
1801GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_region_tlab, RegionTLAB)
1802GENERATE_ALLOC_ENTRYPOINTS_ALLOC_STRING_FROM_BYTES(_region_tlab, RegionTLAB)
1803GENERATE_ALLOC_ENTRYPOINTS_ALLOC_STRING_FROM_CHARS(_region_tlab, RegionTLAB)
1804GENERATE_ALLOC_ENTRYPOINTS_ALLOC_STRING_FROM_STRING(_region_tlab, RegionTLAB)
1805
1806// A hand-written override for GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_rosalloc, RosAlloc).
1807ENTRY art_quick_alloc_object_rosalloc
1808    // Fast path rosalloc allocation.
1809    // x0: type_idx/return value, x1: ArtMethod*, xSELF(x19): Thread::Current
1810    // x2-x7: free.
1811    ldr    x2, [x1, #ART_METHOD_DEX_CACHE_TYPES_OFFSET_64]    // Load dex cache resolved types array
1812                                                              // Load the class (x2)
1813    ldr    w2, [x2, x0, lsl #COMPRESSED_REFERENCE_SIZE_SHIFT]
1814    cbz    x2, .Lart_quick_alloc_object_rosalloc_slow_path    // Check null class
1815                                                              // Check class status.
1816    ldr    w3, [x2, #MIRROR_CLASS_STATUS_OFFSET]
1817    cmp    x3, #MIRROR_CLASS_STATUS_INITIALIZED
1818    bne    .Lart_quick_alloc_object_rosalloc_slow_path
1819                                                              // Add a fake dependence from the
1820                                                              // following access flag and size
1821                                                              // loads to the status load.
1822                                                              // This is to prevent those loads
1823                                                              // from being reordered above the
1824                                                              // status load and reading wrong
1825                                                              // values (an alternative is to use
1826                                                              // a load-acquire for the status).
1827    eor    x3, x3, x3
1828    add    x2, x2, x3
1829                                                              // Check access flags has
1830                                                              // kAccClassIsFinalizable
1831    ldr    w3, [x2, #MIRROR_CLASS_ACCESS_FLAGS_OFFSET]
1832    tst    x3, #ACCESS_FLAGS_CLASS_IS_FINALIZABLE
1833    bne    .Lart_quick_alloc_object_rosalloc_slow_path
1834    ldr    x3, [xSELF, #THREAD_LOCAL_ALLOC_STACK_TOP_OFFSET]  // Check if the thread local
1835                                                              // allocation stack has room.
1836                                                              // ldp won't work due to large offset.
1837    ldr    x4, [xSELF, #THREAD_LOCAL_ALLOC_STACK_END_OFFSET]
1838    cmp    x3, x4
1839    bhs    .Lart_quick_alloc_object_rosalloc_slow_path
1840    ldr    w3, [x2, #MIRROR_CLASS_OBJECT_SIZE_OFFSET]         // Load the object size (x3)
1841    cmp    x3, #ROSALLOC_MAX_THREAD_LOCAL_BRACKET_SIZE        // Check if the size is for a thread
1842                                                              // local allocation
1843    bhs    .Lart_quick_alloc_object_rosalloc_slow_path
1844                                                              // Compute the rosalloc bracket index
1845                                                              // from the size.
1846                                                              // Align up the size by the rosalloc
1847                                                              // bracket quantum size and divide
1848                                                              // by the quantum size and subtract
1849                                                              // by 1. This code is a shorter but
1850                                                              // equivalent version.
1851    sub    x3, x3, #1
1852    lsr    x3, x3, #ROSALLOC_BRACKET_QUANTUM_SIZE_SHIFT
1853                                                              // Load the rosalloc run (x4)
1854    add    x4, xSELF, x3, lsl #POINTER_SIZE_SHIFT
1855    ldr    x4, [x4, #THREAD_ROSALLOC_RUNS_OFFSET]
1856                                                              // Load the free list head (x3). This
1857                                                              // will be the return val.
1858    ldr    x3, [x4, #(ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_HEAD_OFFSET)]
1859    cbz    x3, .Lart_quick_alloc_object_rosalloc_slow_path
1860    // "Point of no slow path". Won't go to the slow path from here on. OK to clobber x0 and x1.
1861    ldr    x1, [x3, #ROSALLOC_SLOT_NEXT_OFFSET]               // Load the next pointer of the head
1862                                                              // and update the list head with the
1863                                                              // next pointer.
1864    str    x1, [x4, #(ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_HEAD_OFFSET)]
1865                                                              // Store the class pointer in the
1866                                                              // header. This also overwrites the
1867                                                              // next pointer. The offsets are
1868                                                              // asserted to match.
1869#if ROSALLOC_SLOT_NEXT_OFFSET != MIRROR_OBJECT_CLASS_OFFSET
1870#error "Class pointer needs to overwrite next pointer."
1871#endif
1872    POISON_HEAP_REF w2
1873    str    w2, [x3, #MIRROR_OBJECT_CLASS_OFFSET]
1874                                                              // Fence. This is "ish" not "ishst" so
1875                                                              // that it also ensures ordering of
1876                                                              // the class status load with respect
1877                                                              // to later accesses to the class
1878                                                              // object. Alternatively we could use
1879                                                              // "ishst" if we use load-acquire for
1880                                                              // the class status load.)
1881                                                              // Needs to be done before pushing on
1882                                                              // allocation since Heap::VisitObjects
1883                                                              // relies on seeing the class pointer.
1884                                                              // b/28790624
1885    dmb    ish
1886                                                              // Push the new object onto the thread
1887                                                              // local allocation stack and
1888                                                              // increment the thread local
1889                                                              // allocation stack top.
1890    ldr    x1, [xSELF, #THREAD_LOCAL_ALLOC_STACK_TOP_OFFSET]
1891    str    w3, [x1], #COMPRESSED_REFERENCE_SIZE               // (Increment x1 as a side effect.)
1892    str    x1, [xSELF, #THREAD_LOCAL_ALLOC_STACK_TOP_OFFSET]
1893                                                              // Decrement the size of the free list
1894    ldr    w1, [x4, #(ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_SIZE_OFFSET)]
1895    sub    x1, x1, #1
1896                                                              // TODO: consider combining this store
1897                                                              // and the list head store above using
1898                                                              // strd.
1899    str    w1, [x4, #(ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_SIZE_OFFSET)]
1900
1901    mov    x0, x3                                             // Set the return value and return.
1902    ret
1903.Lart_quick_alloc_object_rosalloc_slow_path:
1904    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME      // save callee saves in case of GC
1905    mov    x2, xSELF                       // pass Thread::Current
1906    bl     artAllocObjectFromCodeRosAlloc  // (uint32_t type_idx, Method* method, Thread*)
1907    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
1908    RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
1909END art_quick_alloc_object_rosalloc
1910
1911
1912// The common fast path code for art_quick_alloc_array_region_tlab.
1913.macro ALLOC_ARRAY_TLAB_FAST_PATH slowPathLabel, xClass, wClass, xCount, wCount, xTemp0, wTemp0, xTemp1, wTemp1, xTemp2, wTemp2
1914    // Check null class
1915    cbz    \wClass, \slowPathLabel
1916    ALLOC_ARRAY_TLAB_FAST_PATH_RESOLVED \slowPathLabel, \xClass, \wClass, \xCount, \wCount, \xTemp0, \wTemp0, \xTemp1, \wTemp1, \xTemp2, \wTemp2
1917.endm
1918
1919// The common fast path code for art_quick_alloc_array_region_tlab.
1920.macro ALLOC_ARRAY_TLAB_FAST_PATH_RESOLVED slowPathLabel, xClass, wClass, xCount, wCount, xTemp0, wTemp0, xTemp1, wTemp1, xTemp2, wTemp2
1921    // Arrays are never finalizable, no need to check.
1922    ldr    \wTemp0, [\xClass, #MIRROR_CLASS_COMPONENT_TYPE_OFFSET] // Load component type
1923    ldr    \wTemp0, [\xTemp0, #MIRROR_CLASS_OBJECT_PRIMITIVE_TYPE_OFFSET]
1924    lsr    \xTemp0, \xTemp0, #PRIMITIVE_TYPE_SIZE_SHIFT_SHIFT // Component size shift is in high 16
1925                                                              // bits.
1926    lsl    \xTemp1, \xCount, \xTemp0                          // Calculate data size
1927    // Add array data offset and alignment.
1928    add    \xTemp1, \xTemp1, #(MIRROR_INT_ARRAY_DATA_OFFSET + OBJECT_ALIGNMENT_MASK)
1929    add    \xTemp0, \xTemp0, #1                               // Add 4 to the length only if the
1930                                                              // component size shift is 3
1931                                                              // (for 64 bit alignment).
1932    and    \xTemp0, \xTemp0, #4
1933    add    \xTemp1, \xTemp1, \xTemp0
1934    ldr    \xTemp0, [xSELF, #THREAD_LOCAL_POS_OFFSET]         // Check tlab for space, note that
1935                                                              // we use (end - begin) to handle
1936                                                              // negative size arrays.
1937    ldr    \xTemp2, [xSELF, #THREAD_LOCAL_END_OFFSET]
1938    sub    \xTemp2, \xTemp2, \xTemp0
1939    cmp    \xTemp1, \xTemp2
1940    bhi    \slowPathLabel
1941
1942    // "Point of no slow path". Won't go to the slow path from here on. OK to clobber x0 and x1.
1943                                                              // Round up the object size by the
1944                                                              // object alignment. (addr + 7) & ~7.
1945    and    \xTemp1, \xTemp1, #OBJECT_ALIGNMENT_MASK_TOGGLED
1946                                                              // Move old thread_local_pos to x0
1947                                                              // for the return value.
1948    mov    x0, \xTemp0
1949    add    \xTemp0, \xTemp0, \xTemp1
1950    str    \xTemp0, [xSELF, #THREAD_LOCAL_POS_OFFSET]         // Store new thread_local_pos.
1951    ldr    \xTemp0, [xSELF, #THREAD_LOCAL_OBJECTS_OFFSET]     // Increment thread_local_objects.
1952    add    \xTemp0, \xTemp0, #1
1953    str    \xTemp0, [xSELF, #THREAD_LOCAL_OBJECTS_OFFSET]
1954    POISON_HEAP_REF \wClass
1955    str    \wClass, [x0, #MIRROR_OBJECT_CLASS_OFFSET]         // Store the class pointer.
1956    str    \wCount, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]         // Store the array length.
1957                                                              // Fence. This is "ish" not "ishst" so
1958                                                              // that the code after this allocation
1959                                                              // site will see the right values in
1960                                                              // the fields of the class.
1961                                                              // Alternatively we could use "ishst"
1962                                                              // if we use load-acquire for the
1963                                                              // class status load.)
1964    dmb    ish
1965    ret
1966.endm
1967
1968// The common fast path code for art_quick_alloc_object_tlab and art_quick_alloc_object_region_tlab.
1969//
1970// x0: type_idx/return value, x1: ArtMethod*, x2: Class*, xSELF(x19): Thread::Current
1971// x3-x7: free.
1972// Need to preserve x0 and x1 to the slow path.
1973.macro ALLOC_OBJECT_TLAB_FAST_PATH slowPathLabel
1974    cbz    x2, \slowPathLabel                                 // Check null class
1975    ALLOC_OBJECT_TLAB_FAST_PATH_RESOLVED \slowPathLabel
1976.endm
1977
1978.macro ALLOC_OBJECT_TLAB_FAST_PATH_RESOLVED slowPathLabel
1979    ldr    w3, [x2, #MIRROR_CLASS_STATUS_OFFSET]              // Check class status.
1980    cmp    x3, #MIRROR_CLASS_STATUS_INITIALIZED
1981    bne    \slowPathLabel
1982                                                              // Add a fake dependence from the
1983                                                              // following access flag and size
1984                                                              // loads to the status load.
1985                                                              // This is to prevent those loads
1986                                                              // from being reordered above the
1987                                                              // status load and reading wrong
1988                                                              // values (an alternative is to use
1989                                                              // a load-acquire for the status).
1990    eor    x3, x3, x3
1991    add    x2, x2, x3
1992    ALLOC_OBJECT_TLAB_FAST_PATH_INITIALIZED \slowPathLabel
1993.endm
1994
1995.macro ALLOC_OBJECT_TLAB_FAST_PATH_INITIALIZED slowPathLabel
1996                                                              // Check access flags has
1997                                                              // kAccClassIsFinalizable.
1998    ldr    w3, [x2, #MIRROR_CLASS_ACCESS_FLAGS_OFFSET]
1999    tbnz   x3, #ACCESS_FLAGS_CLASS_IS_FINALIZABLE_BIT, \slowPathLabel
2000                                                              // Load thread_local_pos (x4) and
2001                                                              // thread_local_end (x5).
2002    ldr    x4, [xSELF, #THREAD_LOCAL_POS_OFFSET]
2003    ldr    x5, [xSELF, #THREAD_LOCAL_END_OFFSET]
2004    sub    x6, x5, x4                                         // Compute the remaining buf size.
2005    ldr    w7, [x2, #MIRROR_CLASS_OBJECT_SIZE_OFFSET]         // Load the object size (x7).
2006    cmp    x7, x6                                             // Check if it fits. OK to do this
2007                                                              // before rounding up the object size
2008                                                              // assuming the buf size alignment.
2009    bhi    \slowPathLabel
2010    // "Point of no slow path". Won't go to the slow path from here on. OK to clobber x0 and x1.
2011                                                              // Round up the object size by the
2012                                                              // object alignment. (addr + 7) & ~7.
2013    add    x7, x7, #OBJECT_ALIGNMENT_MASK
2014    and    x7, x7, #OBJECT_ALIGNMENT_MASK_TOGGLED
2015                                                              // Move old thread_local_pos to x0
2016                                                              // for the return value.
2017    mov    x0, x4
2018    add    x5, x0, x7
2019    str    x5, [xSELF, #THREAD_LOCAL_POS_OFFSET]              // Store new thread_local_pos.
2020    ldr    x5, [xSELF, #THREAD_LOCAL_OBJECTS_OFFSET]          // Increment thread_local_objects.
2021    add    x5, x5, #1
2022    str    x5, [xSELF, #THREAD_LOCAL_OBJECTS_OFFSET]
2023    POISON_HEAP_REF w2
2024    str    w2, [x0, #MIRROR_OBJECT_CLASS_OFFSET]              // Store the class pointer.
2025                                                              // Fence. This is "ish" not "ishst" so
2026                                                              // that the code after this allocation
2027                                                              // site will see the right values in
2028                                                              // the fields of the class.
2029                                                              // Alternatively we could use "ishst"
2030                                                              // if we use load-acquire for the
2031                                                              // class status load.)
2032    dmb    ish
2033    ret
2034.endm
2035
2036// A hand-written override for GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_tlab, TLAB).
2037ENTRY art_quick_alloc_object_tlab
2038    // Fast path tlab allocation.
2039    // x0: type_idx/return value, x1: ArtMethod*, xSELF(x19): Thread::Current
2040    // x2-x7: free.
2041#if defined(USE_READ_BARRIER)
2042    mvn    x0, xzr                                            // Read barrier not supported here.
2043    ret                                                       // Return -1.
2044#endif
2045    ldr    x2, [x1, #ART_METHOD_DEX_CACHE_TYPES_OFFSET_64]    // Load dex cache resolved types array
2046                                                              // Load the class (x2)
2047    ldr    w2, [x2, x0, lsl #COMPRESSED_REFERENCE_SIZE_SHIFT]
2048    ALLOC_OBJECT_TLAB_FAST_PATH .Lart_quick_alloc_object_tlab_slow_path
2049.Lart_quick_alloc_object_tlab_slow_path:
2050    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    // Save callee saves in case of GC.
2051    mov    x2, xSELF                     // Pass Thread::Current.
2052    bl     artAllocObjectFromCodeTLAB    // (uint32_t type_idx, Method* method, Thread*)
2053    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
2054    RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
2055END art_quick_alloc_object_tlab
2056
2057// A hand-written override for GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_region_tlab, RegionTLAB)
2058.macro GENERATE_ALLOC_OBJECT_REGION_TLAB name, entrypoint, fast_path, is_resolved
2059ENTRY \name
2060    // Fast path region tlab allocation.
2061    // x0: type_idx/return value, x1: ArtMethod*, xSELF(x19): Thread::Current
2062    // x2-x7: free.
2063#if !defined(USE_READ_BARRIER)
2064    mvn    x0, xzr                                            // Read barrier must be enabled here.
2065    ret                                                       // Return -1.
2066#endif
2067.if \is_resolved
2068    mov    x2, x0 // class is actually stored in x0 already
2069.else
2070    ldr    x2, [x1, #ART_METHOD_DEX_CACHE_TYPES_OFFSET_64]    // Load dex cache resolved types array
2071                                                              // Load the class (x2)
2072    ldr    w2, [x2, x0, lsl #COMPRESSED_REFERENCE_SIZE_SHIFT]
2073.endif
2074    // Most common case: GC is not marking.
2075    ldr    w3, [xSELF, #THREAD_IS_GC_MARKING_OFFSET]
2076    cbnz   x3, .Lmarking\name
2077.Ldo_allocation\name:
2078    \fast_path .Lslow_path\name
2079.Lmarking\name:
2080    // GC is marking, check the lock word of the class for the mark bit.
2081    // If the class is null, go slow path. The check is required to read the lock word.
2082    cbz    w2, .Lslow_path\name
2083    // Class is not null, check mark bit in lock word.
2084    ldr    w3, [x2, #MIRROR_OBJECT_LOCK_WORD_OFFSET]
2085    // If the bit is not zero, do the allocation.
2086    tbnz    w3, #LOCK_WORD_MARK_BIT_SHIFT, .Ldo_allocation\name
2087                                                              // The read barrier slow path. Mark
2088                                                              // the class.
2089    stp    x0, x1, [sp, #-32]!                                // Save registers (x0, x1, lr).
2090    str    xLR, [sp, #16]                                     // Align sp by 16 bytes.
2091    mov    x0, x2                                             // Pass the class as the first param.
2092    bl     artReadBarrierMark
2093    mov    x2, x0                                             // Get the (marked) class back.
2094    ldp    x0, x1, [sp, #0]                                   // Restore registers.
2095    ldr    xLR, [sp, #16]
2096    add    sp, sp, #32
2097    b      .Ldo_allocation\name
2098.Lslow_path\name:
2099    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME          // Save callee saves in case of GC.
2100    mov    x2, xSELF                           // Pass Thread::Current.
2101    bl     \entrypoint    // (uint32_t type_idx, Method* method, Thread*)
2102    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
2103    RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
2104END \name
2105.endm
2106
2107GENERATE_ALLOC_OBJECT_REGION_TLAB art_quick_alloc_object_region_tlab, artAllocObjectFromCodeRegionTLAB, ALLOC_OBJECT_TLAB_FAST_PATH, 0
2108GENERATE_ALLOC_OBJECT_REGION_TLAB art_quick_alloc_object_resolved_region_tlab, artAllocObjectFromCodeResolvedRegionTLAB, ALLOC_OBJECT_TLAB_FAST_PATH_RESOLVED, 1
2109GENERATE_ALLOC_OBJECT_REGION_TLAB art_quick_alloc_object_initialized_region_tlab, artAllocObjectFromCodeInitializedRegionTLAB, ALLOC_OBJECT_TLAB_FAST_PATH_INITIALIZED, 1
2110
2111// A hand-written override for GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY*(_region_tlab, RegionTLAB)
2112.macro GENERATE_ALLOC_ARRAY_REGION_TLAB name, entrypoint, fast_path, is_resolved
2113ENTRY \name
2114    // Fast path array allocation for region tlab allocation.
2115    // x0: uint32_t type_idx
2116    // x1: int32_t component_count
2117    // x2: ArtMethod* method
2118    // x3: Thread* self
2119    // x2-x7: free.
2120#if !defined(USE_READ_BARRIER)
2121    mvn    x0, xzr                                            // Read barrier must be enabled here.
2122    ret                                                       // Return -1.
2123#endif
2124.if \is_resolved
2125    mov    x3, x0
2126    // If already resolved, class is stored in x0
2127.else
2128    ldr    x3, [x2, #ART_METHOD_DEX_CACHE_TYPES_OFFSET_64]    // Load dex cache resolved types array
2129                                                              // Load the class (x2)
2130    ldr    w3, [x3, x0, lsl #COMPRESSED_REFERENCE_SIZE_SHIFT]
2131.endif
2132    // Most common case: GC is not marking.
2133    ldr    w4, [xSELF, #THREAD_IS_GC_MARKING_OFFSET]
2134    cbnz   x4, .Lmarking\name
2135.Ldo_allocation\name:
2136    \fast_path .Lslow_path\name, x3, w3, x1, w1, x4, w4, x5, w5, x6, w6
2137.Lmarking\name:
2138    // GC is marking, check the lock word of the class for the mark bit.
2139    // If the class is null, go slow path. The check is required to read the lock word.
2140    cbz    w3, .Lslow_path\name
2141    // Class is not null, check mark bit in lock word.
2142    ldr    w4, [x3, #MIRROR_OBJECT_LOCK_WORD_OFFSET]
2143    // If the bit is not zero, do the allocation.
2144    tbnz   w4, #LOCK_WORD_MARK_BIT_SHIFT, .Ldo_allocation\name
2145    b .Lslow_path\name
2146                                                              // The read barrier slow path. Mark
2147                                                              // the class.
2148    stp    x0, x1, [sp, #-32]!                                // Save registers (x0, x1, x2, lr).
2149    stp    x2, xLR, [sp, #16]
2150    mov    x0, x3                                             // Pass the class as the first param.
2151    bl     artReadBarrierMark
2152    mov    x3, x0                                             // Get the (marked) class back.
2153    ldp    x0, x1, [sp, #0]                                   // Restore registers.
2154    ldp    x2, xLR, [sp, #16]
2155    add    sp, sp, #32
2156    b      .Ldo_allocation\name
2157.Lslow_path\name:
2158    // x0: uint32_t type_idx
2159    // x1: int32_t component_count
2160    // x2: ArtMethod* method
2161    // x3: Thread* self
2162    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME // save callee saves in case of GC
2163    mov    x3, xSELF                  // pass Thread::Current
2164    bl     \entrypoint
2165    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
2166    RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
2167END \name
2168.endm
2169
2170GENERATE_ALLOC_ARRAY_REGION_TLAB art_quick_alloc_array_region_tlab, artAllocArrayFromCodeRegionTLAB, ALLOC_ARRAY_TLAB_FAST_PATH, 0
2171// TODO: art_quick_alloc_array_resolved_region_tlab seems to not get called. Investigate compiler.
2172GENERATE_ALLOC_ARRAY_REGION_TLAB art_quick_alloc_array_resolved_region_tlab, artAllocArrayFromCodeResolvedRegionTLAB, ALLOC_ARRAY_TLAB_FAST_PATH_RESOLVED, 1
2173
2174    /*
2175     * Called by managed code when the thread has been asked to suspend.
2176     */
2177    .extern artTestSuspendFromCode
2178ENTRY art_quick_test_suspend
2179    SETUP_SAVE_EVERYTHING_CALLEE_SAVE_FRAME   // save callee saves for stack crawl
2180    mov    x0, xSELF
2181    bl     artTestSuspendFromCode             // (Thread*)
2182    RESTORE_SAVE_EVERYTHING_CALLEE_SAVE_FRAME
2183    ret
2184END art_quick_test_suspend
2185
2186ENTRY art_quick_implicit_suspend
2187    mov    x0, xSELF
2188    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME          // save callee saves for stack crawl
2189    bl     artTestSuspendFromCode             // (Thread*)
2190    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
2191END art_quick_implicit_suspend
2192
2193     /*
2194     * Called by managed code that is attempting to call a method on a proxy class. On entry
2195     * x0 holds the proxy method and x1 holds the receiver; The frame size of the invoked proxy
2196     * method agrees with a ref and args callee save frame.
2197     */
2198     .extern artQuickProxyInvokeHandler
2199ENTRY art_quick_proxy_invoke_handler
2200    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_WITH_METHOD_IN_X0
2201    mov     x2, xSELF                   // pass Thread::Current
2202    mov     x3, sp                      // pass SP
2203    bl      artQuickProxyInvokeHandler  // (Method* proxy method, receiver, Thread*, SP)
2204    ldr     x2, [xSELF, THREAD_EXCEPTION_OFFSET]
2205    cbnz    x2, .Lexception_in_proxy    // success if no exception is pending
2206    RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME // Restore frame
2207    fmov    d0, x0                      // Store result in d0 in case it was float or double
2208    ret                                 // return on success
2209.Lexception_in_proxy:
2210    RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
2211    DELIVER_PENDING_EXCEPTION
2212END art_quick_proxy_invoke_handler
2213
2214    /*
2215     * Called to resolve an imt conflict.
2216     * x0 is the conflict ArtMethod.
2217     * xIP1 is a hidden argument that holds the target interface method's dex method index.
2218     *
2219     * Note that this stub writes to xIP0, xIP1, and x0.
2220     */
2221    .extern artInvokeInterfaceTrampoline
2222ENTRY art_quick_imt_conflict_trampoline
2223    ldr xIP0, [sp, #0]  // Load referrer
2224    ldr xIP0, [xIP0, #ART_METHOD_DEX_CACHE_METHODS_OFFSET_64]   // Load dex cache methods array
2225    ldr xIP0, [xIP0, xIP1, lsl #POINTER_SIZE_SHIFT]  // Load interface method
2226    ldr xIP1, [x0, #ART_METHOD_JNI_OFFSET_64]  // Load ImtConflictTable
2227    ldr x0, [xIP1]  // Load first entry in ImtConflictTable.
2228.Limt_table_iterate:
2229    cmp x0, xIP0
2230    // Branch if found. Benchmarks have shown doing a branch here is better.
2231    beq .Limt_table_found
2232    // If the entry is null, the interface method is not in the ImtConflictTable.
2233    cbz x0, .Lconflict_trampoline
2234    // Iterate over the entries of the ImtConflictTable.
2235    ldr x0, [xIP1, #(2 * __SIZEOF_POINTER__)]!
2236    b .Limt_table_iterate
2237.Limt_table_found:
2238    // We successfully hit an entry in the table. Load the target method
2239    // and jump to it.
2240    ldr x0, [xIP1, #__SIZEOF_POINTER__]
2241    ldr xIP0, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64]
2242    br xIP0
2243.Lconflict_trampoline:
2244    // Call the runtime stub to populate the ImtConflictTable and jump to the
2245    // resolved method.
2246    INVOKE_TRAMPOLINE_BODY artInvokeInterfaceTrampoline
2247END art_quick_imt_conflict_trampoline
2248
2249ENTRY art_quick_resolution_trampoline
2250    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME
2251    mov x2, xSELF
2252    mov x3, sp
2253    bl artQuickResolutionTrampoline  // (called, receiver, Thread*, SP)
2254    cbz x0, 1f
2255    mov xIP0, x0            // Remember returned code pointer in xIP0.
2256    ldr x0, [sp, #0]        // artQuickResolutionTrampoline puts called method in *SP.
2257    RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
2258    br xIP0
22591:
2260    RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
2261    DELIVER_PENDING_EXCEPTION
2262END art_quick_resolution_trampoline
2263
2264/*
2265 * Generic JNI frame layout:
2266 *
2267 * #-------------------#
2268 * |                   |
2269 * | caller method...  |
2270 * #-------------------#    <--- SP on entry
2271 * | Return X30/LR     |
2272 * | X29/FP            |    callee save
2273 * | X28               |    callee save
2274 * | X27               |    callee save
2275 * | X26               |    callee save
2276 * | X25               |    callee save
2277 * | X24               |    callee save
2278 * | X23               |    callee save
2279 * | X22               |    callee save
2280 * | X21               |    callee save
2281 * | X20               |    callee save
2282 * | X19               |    callee save
2283 * | X7                |    arg7
2284 * | X6                |    arg6
2285 * | X5                |    arg5
2286 * | X4                |    arg4
2287 * | X3                |    arg3
2288 * | X2                |    arg2
2289 * | X1                |    arg1
2290 * | D7                |    float arg 8
2291 * | D6                |    float arg 7
2292 * | D5                |    float arg 6
2293 * | D4                |    float arg 5
2294 * | D3                |    float arg 4
2295 * | D2                |    float arg 3
2296 * | D1                |    float arg 2
2297 * | D0                |    float arg 1
2298 * | Method*           | <- X0
2299 * #-------------------#
2300 * | local ref cookie  | // 4B
2301 * | handle scope size | // 4B
2302 * #-------------------#
2303 * | JNI Call Stack    |
2304 * #-------------------#    <--- SP on native call
2305 * |                   |
2306 * | Stack for Regs    |    The trampoline assembly will pop these values
2307 * |                   |    into registers for native call
2308 * #-------------------#
2309 * | Native code ptr   |
2310 * #-------------------#
2311 * | Free scratch      |
2312 * #-------------------#
2313 * | Ptr to (1)        |    <--- SP
2314 * #-------------------#
2315 */
2316    /*
2317     * Called to do a generic JNI down-call
2318     */
2319ENTRY art_quick_generic_jni_trampoline
2320    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_WITH_METHOD_IN_X0
2321
2322    // Save SP , so we can have static CFI info.
2323    mov x28, sp
2324    .cfi_def_cfa_register x28
2325
2326    // This looks the same, but is different: this will be updated to point to the bottom
2327    // of the frame when the handle scope is inserted.
2328    mov xFP, sp
2329
2330    mov xIP0, #5120
2331    sub sp, sp, xIP0
2332
2333    // prepare for artQuickGenericJniTrampoline call
2334    // (Thread*,  SP)
2335    //    x0      x1   <= C calling convention
2336    //   xSELF    xFP  <= where they are
2337
2338    mov x0, xSELF   // Thread*
2339    mov x1, xFP
2340    bl artQuickGenericJniTrampoline  // (Thread*, sp)
2341
2342    // The C call will have registered the complete save-frame on success.
2343    // The result of the call is:
2344    // x0: pointer to native code, 0 on error.
2345    // x1: pointer to the bottom of the used area of the alloca, can restore stack till there.
2346
2347    // Check for error = 0.
2348    cbz x0, .Lexception_in_native
2349
2350    // Release part of the alloca.
2351    mov sp, x1
2352
2353    // Save the code pointer
2354    mov xIP0, x0
2355
2356    // Load parameters from frame into registers.
2357    // TODO Check with artQuickGenericJniTrampoline.
2358    //      Also, check again APPCS64 - the stack arguments are interleaved.
2359    ldp x0, x1, [sp]
2360    ldp x2, x3, [sp, #16]
2361    ldp x4, x5, [sp, #32]
2362    ldp x6, x7, [sp, #48]
2363
2364    ldp d0, d1, [sp, #64]
2365    ldp d2, d3, [sp, #80]
2366    ldp d4, d5, [sp, #96]
2367    ldp d6, d7, [sp, #112]
2368
2369    add sp, sp, #128
2370
2371    blr xIP0        // native call.
2372
2373    // result sign extension is handled in C code
2374    // prepare for artQuickGenericJniEndTrampoline call
2375    // (Thread*, result, result_f)
2376    //    x0       x1       x2        <= C calling convention
2377    mov x1, x0      // Result (from saved).
2378    mov x0, xSELF   // Thread register.
2379    fmov x2, d0     // d0 will contain floating point result, but needs to go into x2
2380
2381    bl artQuickGenericJniEndTrampoline
2382
2383    // Pending exceptions possible.
2384    ldr x2, [xSELF, THREAD_EXCEPTION_OFFSET]
2385    cbnz x2, .Lexception_in_native
2386
2387    // Tear down the alloca.
2388    mov sp, x28
2389    .cfi_def_cfa_register sp
2390
2391    // Tear down the callee-save frame.
2392    RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
2393
2394    // store into fpr, for when it's a fpr return...
2395    fmov d0, x0
2396    ret
2397
2398.Lexception_in_native:
2399    // Move to x1 then sp to please assembler.
2400    ldr x1, [xSELF, # THREAD_TOP_QUICK_FRAME_OFFSET]
2401    mov sp, x1
2402    .cfi_def_cfa_register sp
2403    # This will create a new save-all frame, required by the runtime.
2404    DELIVER_PENDING_EXCEPTION
2405END art_quick_generic_jni_trampoline
2406
2407/*
2408 * Called to bridge from the quick to interpreter ABI. On entry the arguments match those
2409 * of a quick call:
2410 * x0 = method being called/to bridge to.
2411 * x1..x7, d0..d7 = arguments to that method.
2412 */
2413ENTRY art_quick_to_interpreter_bridge
2414    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME   // Set up frame and save arguments.
2415
2416    //  x0 will contain mirror::ArtMethod* method.
2417    mov x1, xSELF                          // How to get Thread::Current() ???
2418    mov x2, sp
2419
2420    // uint64_t artQuickToInterpreterBridge(mirror::ArtMethod* method, Thread* self,
2421    //                                      mirror::ArtMethod** sp)
2422    bl   artQuickToInterpreterBridge
2423
2424    RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME  // TODO: no need to restore arguments in this case.
2425
2426    fmov d0, x0
2427
2428    RETURN_OR_DELIVER_PENDING_EXCEPTION
2429END art_quick_to_interpreter_bridge
2430
2431
2432//
2433// Instrumentation-related stubs
2434//
2435    .extern artInstrumentationMethodEntryFromCode
2436ENTRY art_quick_instrumentation_entry
2437    SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME
2438
2439    mov   x20, x0             // Preserve method reference in a callee-save.
2440
2441    mov   x2, xSELF
2442    mov   x3, xLR
2443    bl    artInstrumentationMethodEntryFromCode  // (Method*, Object*, Thread*, LR)
2444
2445    mov   xIP0, x0            // x0 = result of call.
2446    mov   x0, x20             // Reload method reference.
2447
2448    RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME  // Note: will restore xSELF
2449    adr   xLR, art_quick_instrumentation_exit
2450    br    xIP0                // Tail-call method with lr set to art_quick_instrumentation_exit.
2451END art_quick_instrumentation_entry
2452
2453    .extern artInstrumentationMethodExitFromCode
2454ENTRY art_quick_instrumentation_exit
2455    mov   xLR, #0             // Clobber LR for later checks.
2456
2457    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME
2458
2459    // We need to save x0 and d0. We could use a callee-save from SETUP_REF_ONLY, but then
2460    // we would need to fully restore it. As there are a lot of callee-save registers, it seems
2461    // easier to have an extra small stack area.
2462
2463    str x0, [sp, #-16]!       // Save integer result.
2464    .cfi_adjust_cfa_offset 16
2465    str d0,  [sp, #8]         // Save floating-point result.
2466
2467    add   x1, sp, #16         // Pass SP.
2468    mov   x2, x0              // Pass integer result.
2469    fmov  x3, d0              // Pass floating-point result.
2470    mov   x0, xSELF           // Pass Thread.
2471    bl   artInstrumentationMethodExitFromCode    // (Thread*, SP, gpr_res, fpr_res)
2472
2473    mov   xIP0, x0            // Return address from instrumentation call.
2474    mov   xLR, x1             // r1 is holding link register if we're to bounce to deoptimize
2475
2476    ldr   d0, [sp, #8]        // Restore floating-point result.
2477    ldr   x0, [sp], 16        // Restore integer result, and drop stack area.
2478    .cfi_adjust_cfa_offset 16
2479
2480    POP_REFS_ONLY_CALLEE_SAVE_FRAME
2481
2482    br    xIP0                // Tail-call out.
2483END art_quick_instrumentation_exit
2484
2485    /*
2486     * Instrumentation has requested that we deoptimize into the interpreter. The deoptimization
2487     * will long jump to the upcall with a special exception of -1.
2488     */
2489    .extern artDeoptimize
2490ENTRY art_quick_deoptimize
2491    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
2492    mov    x0, xSELF          // Pass thread.
2493    bl     artDeoptimize      // artDeoptimize(Thread*)
2494    brk 0
2495END art_quick_deoptimize
2496
2497    /*
2498     * Compiled code has requested that we deoptimize into the interpreter. The deoptimization
2499     * will long jump to the upcall with a special exception of -1.
2500     */
2501    .extern artDeoptimizeFromCompiledCode
2502ENTRY art_quick_deoptimize_from_compiled_code
2503    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
2504    mov    x0, xSELF                      // Pass thread.
2505    bl     artDeoptimizeFromCompiledCode  // artDeoptimizeFromCompiledCode(Thread*)
2506    brk 0
2507END art_quick_deoptimize_from_compiled_code
2508
2509
2510    /*
2511     * String's indexOf.
2512     *
2513     * TODO: Not very optimized.
2514     * On entry:
2515     *    x0:   string object (known non-null)
2516     *    w1:   char to match (known <= 0xFFFF)
2517     *    w2:   Starting offset in string data
2518     */
2519ENTRY art_quick_indexof
2520    ldr   w3, [x0, #MIRROR_STRING_COUNT_OFFSET]
2521    add   x0, x0, #MIRROR_STRING_VALUE_OFFSET
2522
2523    /* Clamp start to [0..count] */
2524    cmp   w2, #0
2525    csel  w2, wzr, w2, lt
2526    cmp   w2, w3
2527    csel  w2, w3, w2, gt
2528
2529    /* Save a copy to compute result */
2530    mov   x5, x0
2531
2532    /* Build pointer to start of data to compare and pre-bias */
2533    add   x0, x0, x2, lsl #1
2534    sub   x0, x0, #2
2535
2536    /* Compute iteration count */
2537    sub   w2, w3, w2
2538
2539    /*
2540     * At this point we have:
2541     *  x0: start of the data to test
2542     *  w1: char to compare
2543     *  w2: iteration count
2544     *  x5: original start of string data
2545     */
2546
2547    subs  w2, w2, #4
2548    b.lt  .Lindexof_remainder
2549
2550.Lindexof_loop4:
2551    ldrh  w6, [x0, #2]!
2552    ldrh  w7, [x0, #2]!
2553    ldrh  wIP0, [x0, #2]!
2554    ldrh  wIP1, [x0, #2]!
2555    cmp   w6, w1
2556    b.eq  .Lmatch_0
2557    cmp   w7, w1
2558    b.eq  .Lmatch_1
2559    cmp   wIP0, w1
2560    b.eq  .Lmatch_2
2561    cmp   wIP1, w1
2562    b.eq  .Lmatch_3
2563    subs  w2, w2, #4
2564    b.ge  .Lindexof_loop4
2565
2566.Lindexof_remainder:
2567    adds  w2, w2, #4
2568    b.eq  .Lindexof_nomatch
2569
2570.Lindexof_loop1:
2571    ldrh  w6, [x0, #2]!
2572    cmp   w6, w1
2573    b.eq  .Lmatch_3
2574    subs  w2, w2, #1
2575    b.ne  .Lindexof_loop1
2576
2577.Lindexof_nomatch:
2578    mov   x0, #-1
2579    ret
2580
2581.Lmatch_0:
2582    sub   x0, x0, #6
2583    sub   x0, x0, x5
2584    asr   x0, x0, #1
2585    ret
2586.Lmatch_1:
2587    sub   x0, x0, #4
2588    sub   x0, x0, x5
2589    asr   x0, x0, #1
2590    ret
2591.Lmatch_2:
2592    sub   x0, x0, #2
2593    sub   x0, x0, x5
2594    asr   x0, x0, #1
2595    ret
2596.Lmatch_3:
2597    sub   x0, x0, x5
2598    asr   x0, x0, #1
2599    ret
2600END art_quick_indexof
2601
2602    /*
2603     * Create a function `name` calling the ReadBarrier::Mark routine,
2604     * getting its argument and returning its result through W register
2605     * `wreg` (corresponding to X register `xreg`), saving and restoring
2606     * all caller-save registers.
2607     *
2608     * If `wreg` is different from `w0`, the generated function follows a
2609     * non-standard runtime calling convention:
2610     * - register `wreg` is used to pass the (sole) argument of this
2611     *   function (instead of W0);
2612     * - register `wreg` is used to return the result of this function
2613     *   (instead of W0);
2614     * - W0 is treated like a normal (non-argument) caller-save register;
2615     * - everything else is the same as in the standard runtime calling
2616     *   convention (e.g. standard callee-save registers are preserved).
2617     */
2618.macro READ_BARRIER_MARK_REG name, wreg, xreg
2619ENTRY \name
2620    // Reference is null, no work to do at all.
2621    cbz \wreg, .Lret_rb_\name
2622    /*
2623     * Allocate 46 stack slots * 8 = 368 bytes:
2624     * - 20 slots for core registers X0-X19
2625     * - 24 slots for floating-point registers D0-D7 and D16-D31
2626     * -  1 slot for return address register XLR
2627     * -  1 padding slot for 16-byte stack alignment
2628     */
2629    // Use wIP0 as temp and check the mark bit of the reference. wIP0 is not used by the compiler.
2630    ldr   wIP0, [\xreg, #MIRROR_OBJECT_LOCK_WORD_OFFSET]
2631    tbz   wIP0, #LOCK_WORD_MARK_BIT_SHIFT, .Lslow_path_rb_\name
2632    ret
2633.Lslow_path_rb_\name:
2634    // Save all potentially live caller-save core registers.
2635    stp   x0, x1,   [sp, #-368]!
2636    .cfi_adjust_cfa_offset 368
2637    .cfi_rel_offset x0, 0
2638    .cfi_rel_offset x1, 8
2639    stp   x2, x3,   [sp, #16]
2640    .cfi_rel_offset x2, 16
2641    .cfi_rel_offset x3, 24
2642    stp   x4, x5,   [sp, #32]
2643    .cfi_rel_offset x4, 32
2644    .cfi_rel_offset x5, 40
2645    stp   x6, x7,   [sp, #48]
2646    .cfi_rel_offset x6, 48
2647    .cfi_rel_offset x7, 56
2648    stp   x8, x9,   [sp, #64]
2649    .cfi_rel_offset x8, 64
2650    .cfi_rel_offset x9, 72
2651    stp   x10, x11, [sp, #80]
2652    .cfi_rel_offset x10, 80
2653    .cfi_rel_offset x11, 88
2654    stp   x12, x13, [sp, #96]
2655    .cfi_rel_offset x12, 96
2656    .cfi_rel_offset x13, 104
2657    stp   x14, x15, [sp, #112]
2658    .cfi_rel_offset x14, 112
2659    .cfi_rel_offset x15, 120
2660    stp   x16, x17, [sp, #128]
2661    .cfi_rel_offset x16, 128
2662    .cfi_rel_offset x17, 136
2663    stp   x18, x19, [sp, #144]
2664    .cfi_rel_offset x18, 144
2665    .cfi_rel_offset x19, 152
2666    // Save all potentially live caller-save floating-point registers.
2667    stp   d0, d1,   [sp, #160]
2668    stp   d2, d3,   [sp, #176]
2669    stp   d4, d5,   [sp, #192]
2670    stp   d6, d7,   [sp, #208]
2671    stp   d16, d17, [sp, #224]
2672    stp   d18, d19, [sp, #240]
2673    stp   d20, d21, [sp, #256]
2674    stp   d22, d23, [sp, #272]
2675    stp   d24, d25, [sp, #288]
2676    stp   d26, d27, [sp, #304]
2677    stp   d28, d29, [sp, #320]
2678    stp   d30, d31, [sp, #336]
2679    // Save return address.
2680    str   xLR,      [sp, #352]
2681    .cfi_rel_offset x30, 352
2682    // (sp + #360 is a padding slot)
2683
2684    .ifnc \wreg, w0
2685      mov   w0, \wreg                   // Pass arg1 - obj from `wreg`
2686    .endif
2687    bl    artReadBarrierMark            // artReadBarrierMark(obj)
2688    .ifnc \wreg, w0
2689      mov   \wreg, w0                   // Return result into `wreg`
2690    .endif
2691
2692    // Restore core regs, except `xreg`, as `wreg` is used to return the
2693    // result of this function (simply remove it from the stack instead).
2694    POP_REGS_NE x0, x1,   0,   \xreg
2695    POP_REGS_NE x2, x3,   16,  \xreg
2696    POP_REGS_NE x4, x5,   32,  \xreg
2697    POP_REGS_NE x6, x7,   48,  \xreg
2698    POP_REGS_NE x8, x9,   64,  \xreg
2699    POP_REGS_NE x10, x11, 80,  \xreg
2700    POP_REGS_NE x12, x13, 96,  \xreg
2701    POP_REGS_NE x14, x15, 112, \xreg
2702    POP_REGS_NE x16, x17, 128, \xreg
2703    POP_REGS_NE x18, x19, 144, \xreg
2704    // Restore floating-point registers.
2705    ldp   d0, d1,   [sp, #160]
2706    ldp   d2, d3,   [sp, #176]
2707    ldp   d4, d5,   [sp, #192]
2708    ldp   d6, d7,   [sp, #208]
2709    ldp   d16, d17, [sp, #224]
2710    ldp   d18, d19, [sp, #240]
2711    ldp   d20, d21, [sp, #256]
2712    ldp   d22, d23, [sp, #272]
2713    ldp   d24, d25, [sp, #288]
2714    ldp   d26, d27, [sp, #304]
2715    ldp   d28, d29, [sp, #320]
2716    ldp   d30, d31, [sp, #336]
2717    // Restore return address and remove padding.
2718    ldr   xLR,      [sp, #352]
2719    .cfi_restore x30
2720    add sp, sp, #368
2721    .cfi_adjust_cfa_offset -368
2722.Lret_rb_\name:
2723    ret
2724END \name
2725.endm
2726
2727READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg00, w0,  x0
2728READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg01, w1,  x1
2729READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg02, w2,  x2
2730READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg03, w3,  x3
2731READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg04, w4,  x4
2732READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg05, w5,  x5
2733READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg06, w6,  x6
2734READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg07, w7,  x7
2735READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg08, w8,  x8
2736READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg09, w9,  x9
2737READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg10, w10, x10
2738READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg11, w11, x11
2739READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg12, w12, x12
2740READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg13, w13, x13
2741READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg14, w14, x14
2742READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg15, w15, x15
2743READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg16, w16, x16
2744READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg17, w17, x17
2745READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg18, w18, x18
2746READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg19, w19, x19
2747READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg20, w20, x20
2748READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg21, w21, x21
2749READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg22, w22, x22
2750READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg23, w23, x23
2751READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg24, w24, x24
2752READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg25, w25, x25
2753READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg26, w26, x26
2754READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg27, w27, x27
2755READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg28, w28, x28
2756READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg29, w29, x29
2757