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, 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   EXPORT_PC
74   // Fast-path which gets the method from thread-local cache.
75   FETCH_FROM_THREAD_CACHE x26, 5f
761:
77   // First argument is the 'this' pointer.
78   FETCH w1, 2
79   .if !$range
80   and w1, w1, #0xf
81   .endif
82   GET_VREG w1, w1
83   // Note: if w1 is null, this will be handled by our SIGSEGV handler.
84   ldr w2, [x1, #MIRROR_OBJECT_CLASS_OFFSET]
85   // Test the first two bits of the fetched ArtMethod:
86   // - If the first bit is set, this is a method on j.l.Object
87   // - If the second bit is set, this is a default method.
88   tst w26, #0x3
89   b.ne 3f
90   ldrh w3, [x26, #ART_METHOD_IMT_INDEX_OFFSET]
912:
92   ldr x2, [x2, #MIRROR_CLASS_IMT_PTR_OFFSET_64]
93   ldr x0, [x2, w3, uxtw #3]
94   .if $range
95   b NterpCommonInvokeInterfaceRange
96   .else
97   b NterpCommonInvokeInterface
98   .endif
993:
100   tbnz w26, #0, 4f
101   and x26, x26, #-4
102   ldrh w3, [x26, #ART_METHOD_METHOD_INDEX_OFFSET]
103   and w3, w3, #ART_METHOD_IMT_MASK
104   b 2b
1054:
106   lsr w26, w26, #16
107   add w2, w2, #MIRROR_CLASS_VTABLE_OFFSET_64
108   ldr x0, [x2, w26, uxtw #3]
109   .if $range
110   b NterpCommonInvokeInstanceRange
111   .else
112   b NterpCommonInvokeInstance
113   .endif
1145:
115   mov x0, xSELF
116   ldr x1, [sp]
117   mov x2, xPC
118   bl nterp_get_method
119   mov x26, x0
120   b 1b
121
122%def op_invoke_interface():
123%  invoke_interface(range="0")
124
125%def op_invoke_interface_range():
126%  invoke_interface(range="1")
127
128%def invoke_static(helper=""):
129   EXPORT_PC
130   // Fast-path which gets the method from thread-local cache.
131   FETCH_FROM_THREAD_CACHE x0, 1f
132   b $helper
1331:
134   mov x0, xSELF
135   ldr x1, [sp]
136   mov x2, xPC
137   bl nterp_get_method
138   b $helper
139
140%def op_invoke_static():
141%  invoke_static(helper="NterpCommonInvokeStatic")
142
143%def op_invoke_static_range():
144%  invoke_static(helper="NterpCommonInvokeStaticRange")
145
146%def invoke_virtual(helper="", range=""):
147   EXPORT_PC
148   // Fast-path which gets the method from thread-local cache.
149   FETCH_FROM_THREAD_CACHE x2, 2f
1501:
151   FETCH w1, 2
152   .if !$range
153   and w1, w1, #0xf
154   .endif
155   GET_VREG w1, w1
156   // Note: if w1 is null, this will be handled by our SIGSEGV handler.
157   ldr w0, [x1, #MIRROR_OBJECT_CLASS_OFFSET]
158   add w0, w0, #MIRROR_CLASS_VTABLE_OFFSET_64
159   ldr x0, [x0, w2, uxtw #3]
160   b $helper
1612:
162   mov x0, xSELF
163   ldr x1, [sp]
164   mov x2, xPC
165   bl nterp_get_method
166   mov x2, x0
167   b 1b
168
169%def op_invoke_virtual():
170%  invoke_virtual(helper="NterpCommonInvokeInstance", range="0")
171
172%def op_invoke_virtual_range():
173%  invoke_virtual(helper="NterpCommonInvokeInstanceRange", range="1")
174