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, 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_helper(lambda: 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, ${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   // Test the first two bits of the fetched ArtMethod:
91   // - If the first bit is set, this is a method on j.l.Object
92   // - If the second bit is set, this is a default method.
93   tst r4, #3
94   bne 2f
95   ldrh r3, [r4, #ART_METHOD_IMT_INDEX_OFFSET]
961:
97   ldr r2, [r2, #MIRROR_CLASS_IMT_PTR_OFFSET_32]
98   ldr r0, [r2, r3, lsl #2]
99   .if $range
100   b NterpCommonInvokeInterfaceRange
101   .else
102   b NterpCommonInvokeInterface
103   .endif
1042:
105   tst r4, #1
106   bne 3f
107   and r4, r4, #-4
108   ldrh r3, [r4, #ART_METHOD_METHOD_INDEX_OFFSET]
109   and r3, r3, #ART_METHOD_IMT_MASK
110   b 1b
1113:
112   lsr r4, r4, #16
113   add r2, r2, #MIRROR_CLASS_VTABLE_OFFSET_32
114   ldr r0, [r2, r4, lsl #2]
115   .if $range
116   b NterpCommonInvokeInstanceRange
117   .else
118   b NterpCommonInvokeInstance
119   .endif
120
121%def op_invoke_interface_slow_path():
122   mov r0, rSELF
123   ldr r1, [sp]
124   mov r2, rPC
125   bl nterp_get_method
126   mov r4, r0
127   b .L${opcode}_resume
128
129%def op_invoke_interface():
130%  invoke_interface(range="0")
131
132%def op_invoke_interface_range():
133%  invoke_interface(range="1")
134
135%def invoke_static(helper=""):
136   EXPORT_PC
137   // Fast-path which gets the method from thread-local cache.
138   FETCH_FROM_THREAD_CACHE r0, 1f
139   b $helper
1401:
141   mov r0, rSELF
142   ldr r1, [sp]
143   mov r2, rPC
144   bl nterp_get_method
145   b $helper
146
147%def op_invoke_static():
148%  invoke_static(helper="NterpCommonInvokeStatic")
149
150%def op_invoke_static_range():
151%  invoke_static(helper="NterpCommonInvokeStaticRange")
152
153%def invoke_virtual(helper="", range=""):
154   EXPORT_PC
155   // Fast-path which gets the vtable offset from thread-local cache.
156   FETCH_FROM_THREAD_CACHE r2, 2f
1571:
158   FETCH r1, 2
159   .if !$range
160   and r1, r1, #0xf
161   .endif
162   GET_VREG r1, r1
163   // Note: if r1 is null, this will be handled by our SIGSEGV handler.
164   ldr r0, [r1, #MIRROR_OBJECT_CLASS_OFFSET]
165   add r0, r0, #MIRROR_CLASS_VTABLE_OFFSET_32
166   ldr r0, [r0, r2, lsl #2]
167   b $helper
1682:
169   mov r0, rSELF
170   ldr r1, [sp]
171   mov r2, rPC
172   bl nterp_get_method
173   mov r2, r0
174   b 1b
175
176%def op_invoke_virtual():
177%  invoke_virtual(helper="NterpCommonInvokeInstance", range="0")
178
179%def op_invoke_virtual_range():
180%  invoke_virtual(helper="NterpCommonInvokeInstanceRange", range="1")
181