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