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