xref: /aosp_15_r20/art/runtime/interpreter/mterp/arm64ng/invoke.S (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1%def op_invoke_custom():
2   EXPORT_PC
3   FETCH w0, 1 // call_site index, first argument of runtime call.
4   b NterpCommonInvokeCustom
5
6%def op_invoke_custom_range():
7   EXPORT_PC
8   FETCH w0, 1 // call_site index, first argument of runtime call.
9   b NterpCommonInvokeCustomRange
10
11%def invoke_direct_or_super(helper="", range="", is_super=""):
12   EXPORT_PC
13   // Fast-path which gets the method from thread-local cache.
14%  fetch_from_thread_cache("x0", miss_label="2f")
151:
16   // Load the first argument (the 'this' pointer).
17   FETCH w1, 2
18   .if !$range
19   and w1, w1, #0xf
20   .endif
21   GET_VREG w1, w1
22   cbz w1, common_errNullObject    // bail if null
23   b $helper
242:
25   mov x0, xSELF
26   ldr x1, [sp]
27   mov x2, xPC
28   bl nterp_get_method
29   .if $is_super
30   b 1b
31   .else
32   tbz x0, #0, 1b
33   and x0, x0, #-2 // Remove the extra bit that marks it's a String.<init> method.
34   .if $range
35   b NterpHandleStringInitRange
36   .else
37   b NterpHandleStringInit
38   .endif
39   .endif
40
41%def op_invoke_direct():
42%  invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0", is_super="0")
43
44%def op_invoke_direct_range():
45%  invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1", is_super="0")
46
47%def op_invoke_super():
48%  invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0", is_super="1")
49
50%def op_invoke_super_range():
51%  invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1", is_super="1")
52
53%def op_invoke_polymorphic():
54   EXPORT_PC
55   // No need to fetch the target method.
56   // Load the first argument (the 'this' pointer).
57   FETCH w1, 2
58   and w1, w1, #0xf
59   GET_VREG w1, w1
60   cbz w1, common_errNullObject    // bail if null
61   b NterpCommonInvokePolymorphic
62
63%def op_invoke_polymorphic_range():
64   EXPORT_PC
65   // No need to fetch the target method.
66   // Load the first argument (the 'this' pointer).
67   FETCH w1, 2
68   GET_VREG w1, w1
69   cbz w1, common_errNullObject    // bail if null
70   b NterpCommonInvokePolymorphicRange
71
72%def invoke_interface(range=""):
73%  slow_path = add_slow_path(invoke_interface_slow_path, range)
74   EXPORT_PC
75   // Fast-path which gets the method from thread-local cache.
76%  fetch_from_thread_cache("x26", miss_label=slow_path)
77.L${opcode}_resume:
78   // First argument is the 'this' pointer.
79   FETCH w1, 2
80   .if !$range
81   and w1, w1, #0xf
82   .endif
83   GET_VREG w1, w1
84   // Note: if w1 is null, this will be handled by our SIGSEGV handler.
85   ldr w2, [x1, #MIRROR_OBJECT_CLASS_OFFSET]
86   UNPOISON_HEAP_REF w2
87   // Test the first two bits of the fetched ArtMethod:
88   // - If the first bit is set, this is a method on j.l.Object
89   // - If the second bit is set, this is a default method.
90   tst w26, #0x3
91   b.ne 2f
92   ldrh w3, [x26, #ART_METHOD_IMT_INDEX_OFFSET]
931:
94   ldr x2, [x2, #MIRROR_CLASS_IMT_PTR_OFFSET_64]
95   ldr x0, [x2, w3, uxtw #3]
96   .if $range
97   b NterpCommonInvokeInterfaceRange
98   .else
99   b NterpCommonInvokeInterface
100   .endif
1012:
102   tbnz w26, #0, 3f
103   and x26, x26, #-4
104   ldrh w3, [x26, #ART_METHOD_METHOD_INDEX_OFFSET]
105   and w3, w3, #ART_METHOD_IMT_MASK
106   b 1b
1073:
108   lsr w26, w26, #16
109   add w2, w2, #MIRROR_CLASS_VTABLE_OFFSET_64
110   ldr x0, [x2, w26, uxtw #3]
111   .if $range
112   b NterpCommonInvokeInstanceRange
113   .else
114   b NterpCommonInvokeInstance
115   .endif
116
117%def invoke_interface_slow_path(range):
118   mov x0, xSELF
119   ldr x1, [sp]
120   mov x2, xPC
121   bl nterp_get_method
122   mov x26, x0
123   b .L${opcode}_resume
124
125%def op_invoke_interface():
126%  invoke_interface(range="0")
127
128%def op_invoke_interface_range():
129%  invoke_interface(range="1")
130
131%def invoke_static(helper=""):
132   EXPORT_PC
133   // Fast-path which gets the method from thread-local cache.
134%  fetch_from_thread_cache("x0", miss_label="1f")
135   b $helper
1361:
137   mov x0, xSELF
138   ldr x1, [sp]
139   mov x2, xPC
140   bl nterp_get_method
141   b $helper
142
143%def op_invoke_static():
144%  invoke_static(helper="NterpCommonInvokeStatic")
145
146%def op_invoke_static_range():
147%  invoke_static(helper="NterpCommonInvokeStaticRange")
148
149%def invoke_virtual(helper="", range=""):
150   EXPORT_PC
151   // Fast-path which gets the method from thread-local cache.
152%  fetch_from_thread_cache("x2", miss_label="2f")
1531:
154   FETCH w1, 2
155   .if !$range
156   and w1, w1, #0xf
157   .endif
158   GET_VREG w1, w1
159   // Note: if w1 is null, this will be handled by our SIGSEGV handler.
160   ldr w0, [x1, #MIRROR_OBJECT_CLASS_OFFSET]
161   UNPOISON_HEAP_REF w0
162   add w0, w0, #MIRROR_CLASS_VTABLE_OFFSET_64
163   ldr x0, [x0, w2, uxtw #3]
164   b $helper
1652:
166   mov x0, xSELF
167   ldr x1, [sp]
168   mov x2, xPC
169   bl nterp_get_method
170   mov x2, x0
171   b 1b
172
173%def op_invoke_virtual():
174%  invoke_virtual(helper="NterpCommonInvokeInstance", range="0")
175
176%def op_invoke_virtual_range():
177%  invoke_virtual(helper="NterpCommonInvokeInstanceRange", range="1")
178