xref: /aosp_15_r20/art/runtime/interpreter/mterp/armng/invoke.S (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1%def op_invoke_custom():
2   EXPORT_PC
3   FETCH r0, 1 // call_site index, first argument of runtime call.
4   b NterpCommonInvokeCustom
5
6%def op_invoke_custom_range():
7   EXPORT_PC
8   FETCH r0, 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("r0", miss_label="2f")
151:
16   // Load the first argument (the 'this' pointer).
17   FETCH r1, 2
18   .if !$range
19   and r1, r1, #0xf
20   .endif
21   GET_VREG r1, r1
22   cmp r1, #0
23   beq common_errNullObject    // bail if null
24   b $helper
252:
26   mov r0, rSELF
27   ldr r1, [sp]
28   mov r2, rPC
29   bl nterp_get_method
30   .if $is_super
31   b 1b
32   .else
33   tst r0, #1
34   beq 1b
35   and r0, r0, #-2 // Remove the extra bit that marks it's a String.<init> method.
36   .if $range
37   b NterpHandleStringInitRange
38   .else
39   b NterpHandleStringInit
40   .endif
41   .endif
42
43%def op_invoke_direct():
44%  invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0", is_super="0")
45
46%def op_invoke_direct_range():
47%  invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1", is_super="0")
48
49%def op_invoke_super():
50%  invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0", is_super="1")
51
52%def op_invoke_super_range():
53%  invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1", is_super="1")
54
55%def op_invoke_polymorphic():
56   EXPORT_PC
57   // No need to fetch the target method.
58   // Load the first argument (the 'this' pointer).
59   FETCH r1, 2
60   and r1, r1, #0xf
61   GET_VREG r1, r1
62   cmp r1, #0
63   beq common_errNullObject    // bail if null
64   b NterpCommonInvokePolymorphic
65
66%def op_invoke_polymorphic_range():
67   EXPORT_PC
68   // No need to fetch the target method.
69   // Load the first argument (the 'this' pointer).
70   FETCH r1, 2
71   GET_VREG r1, r1
72   cmp r1, #0
73   beq common_errNullObject    // bail if null
74   b NterpCommonInvokePolymorphicRange
75
76%def invoke_interface(range=""):
77%  slow_path = add_slow_path(op_invoke_interface_slow_path)
78   EXPORT_PC
79   // Fast-path which gets the method from thread-local cache.
80%  fetch_from_thread_cache("r4", miss_label=slow_path)
81.L${opcode}_resume:
82   // First argument is the 'this' pointer.
83   FETCH r1, 2
84   .if !$range
85   and r1, r1, #0xf
86   .endif
87   GET_VREG r1, r1
88   // Note: if r1 is null, this will be handled by our SIGSEGV handler.
89   ldr r2, [r1, #MIRROR_OBJECT_CLASS_OFFSET]
90   UNPOISON_HEAP_REF r2
91   // Test the first two bits of the fetched ArtMethod:
92   // - If the first bit is set, this is a method on j.l.Object
93   // - If the second bit is set, this is a default method.
94   tst r4, #3
95   bne 2f
96   ldrh r3, [r4, #ART_METHOD_IMT_INDEX_OFFSET]
971:
98   ldr r2, [r2, #MIRROR_CLASS_IMT_PTR_OFFSET_32]
99   ldr r0, [r2, r3, lsl #2]
100   .if $range
101   b NterpCommonInvokeInterfaceRange
102   .else
103   b NterpCommonInvokeInterface
104   .endif
1052:
106   tst r4, #1
107   bne 3f
108   and r4, r4, #-4
109   ldrh r3, [r4, #ART_METHOD_METHOD_INDEX_OFFSET]
110   and r3, r3, #ART_METHOD_IMT_MASK
111   b 1b
1123:
113   lsr r4, r4, #16
114   add r2, r2, #MIRROR_CLASS_VTABLE_OFFSET_32
115   ldr r0, [r2, r4, lsl #2]
116   .if $range
117   b NterpCommonInvokeInstanceRange
118   .else
119   b NterpCommonInvokeInstance
120   .endif
121
122%def op_invoke_interface_slow_path():
123   mov r0, rSELF
124   ldr r1, [sp]
125   mov r2, rPC
126   bl nterp_get_method
127   mov r4, r0
128   b .L${opcode}_resume
129
130%def op_invoke_interface():
131%  invoke_interface(range="0")
132
133%def op_invoke_interface_range():
134%  invoke_interface(range="1")
135
136%def invoke_static(helper=""):
137   EXPORT_PC
138   // Fast-path which gets the method from thread-local cache.
139%  fetch_from_thread_cache("r0", miss_label="1f")
140   b $helper
1411:
142   mov r0, rSELF
143   ldr r1, [sp]
144   mov r2, rPC
145   bl nterp_get_method
146   b $helper
147
148%def op_invoke_static():
149%  invoke_static(helper="NterpCommonInvokeStatic")
150
151%def op_invoke_static_range():
152%  invoke_static(helper="NterpCommonInvokeStaticRange")
153
154%def invoke_virtual(helper="", range=""):
155   EXPORT_PC
156   // Fast-path which gets the vtable offset from thread-local cache.
157%  fetch_from_thread_cache("r2", miss_label="2f")
1581:
159   FETCH r1, 2
160   .if !$range
161   and r1, r1, #0xf
162   .endif
163   GET_VREG r1, r1
164   // Note: if r1 is null, this will be handled by our SIGSEGV handler.
165   ldr r0, [r1, #MIRROR_OBJECT_CLASS_OFFSET]
166   UNPOISON_HEAP_REF r0
167   add r0, r0, #MIRROR_CLASS_VTABLE_OFFSET_32
168   ldr r0, [r0, r2, lsl #2]
169   b $helper
1702:
171   mov r0, rSELF
172   ldr r1, [sp]
173   mov r2, rPC
174   bl nterp_get_method
175   mov r2, r0
176   b 1b
177
178%def op_invoke_virtual():
179%  invoke_virtual(helper="NterpCommonInvokeInstance", range="0")
180
181%def op_invoke_virtual_range():
182%  invoke_virtual(helper="NterpCommonInvokeInstanceRange", range="1")
183