1%def invoke(helper="NterpUnimplemented"):
2    call    SYMBOL($helper)
3
4%def op_invoke_custom():
5   EXPORT_PC
6   movzwl 2(rPC), %edi // call_site index, first argument of runtime call.
7   jmp NterpCommonInvokeCustom
8
9%def op_invoke_custom_range():
10   EXPORT_PC
11   movzwl 2(rPC), %edi // call_site index, first argument of runtime call.
12   jmp NterpCommonInvokeCustomRange
13
14%def invoke_direct_or_super(helper="", range=""):
15   EXPORT_PC
16   // Fast-path which gets the method from thread-local cache.
17   FETCH_FROM_THREAD_CACHE %rdi, 2f
181:
19   // Load the first argument (the 'this' pointer).
20   movzwl 4(rPC), %r11d // arguments
21   .if !$range
22   andq $$0xf, %r11
23   .endif
24   movl (rFP, %r11, 4), %esi
25   // NullPointerException check.
26   movl (%esi), %eax
27   jmp $helper
282:
29   movq rSELF:THREAD_SELF_OFFSET, %rdi
30   movq 0(%rsp), %rsi
31   movq rPC, %rdx
32   call nterp_get_method
33   movq %rax, %rdi
34   testl MACRO_LITERAL(1), %eax
35   je 1b
36   andq $$-2, %rdi  // Remove the extra bit that marks it's a String.<init> method.
37   .if $range
38   jmp NterpHandleStringInitRange
39   .else
40   jmp NterpHandleStringInit
41   .endif
42
43%def op_invoke_direct():
44%  invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0")
45
46%def op_invoke_direct_range():
47%  invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1")
48
49%def op_invoke_polymorphic():
50   EXPORT_PC
51   // No need to fetch the target method.
52   // Load the first argument (the 'this' pointer).
53   movzwl 4(rPC), %r11d // arguments
54   andq $$0xf, %r11
55   movl (rFP, %r11, 4), %esi
56   // NullPointerException check.
57   movl (%esi), %eax
58   jmp NterpCommonInvokePolymorphic
59
60%def op_invoke_polymorphic_range():
61   EXPORT_PC
62   // No need to fetch the target method.
63   // Load the first argument (the 'this' pointer).
64   movzwl 4(rPC), %r11d // arguments
65   movl (rFP, %r11, 4), %esi
66   // NullPointerException check.
67   movl (%esi), %eax
68   jmp NterpCommonInvokePolymorphicRange
69
70%def invoke_interface(helper="", range=""):
71   EXPORT_PC
72   // Fast-path which gets the method from thread-local cache.
73   FETCH_FROM_THREAD_CACHE %rax, 2f
741:
75   // First argument is the 'this' pointer.
76   movzwl 4(rPC), %r11d // arguments
77   .if !$range
78   andq $$0xf, %r11
79   .endif
80   movl (rFP, %r11, 4), %esi
81   movl MIRROR_OBJECT_CLASS_OFFSET(%esi), %edx
82   movq MIRROR_CLASS_IMT_PTR_OFFSET_64(%edx), %rdx
83   movq (%rdx, %rax, 8), %rdi
84   jmp $helper
852:
86   movq rSELF:THREAD_SELF_OFFSET, %rdi
87   movq 0(%rsp), %rsi
88   movq rPC, %rdx
89   call nterp_get_method
90   testl %eax, %eax
91   jns 1b
92   // For j.l.Object interface calls, the high bit is set. Also the method index is 16bits.
93   andl LITERAL(0xffff), %eax
94   .if $range
95   jmp NterpHandleInvokeInterfaceOnObjectMethodRange
96   .else
97   jmp NterpHandleInvokeInterfaceOnObjectMethod
98   .endif
99
100%def op_invoke_interface():
101%  invoke_interface(helper="NterpCommonInvokeInterface", range="0")
102
103%def op_invoke_interface_range():
104%  invoke_interface(helper="NterpCommonInvokeInterfaceRange", range="1")
105
106%def invoke_static(helper=""):
107   EXPORT_PC
108   // Fast-path which gets the method from thread-local cache.
109   FETCH_FROM_THREAD_CACHE %rdi, 1f
110   jmp $helper
1111:
112   movq rSELF:THREAD_SELF_OFFSET, %rdi
113   movq 0(%rsp), %rsi
114   movq rPC, %rdx
115   call nterp_get_method
116   movq %rax, %rdi
117   jmp $helper
118
119%def op_invoke_static():
120%  invoke_static(helper="NterpCommonInvokeStatic")
121
122%def op_invoke_static_range():
123%  invoke_static(helper="NterpCommonInvokeStaticRange")
124
125%def op_invoke_super():
126%  invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0")
127
128%def op_invoke_super_range():
129%  invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1")
130
131%def invoke_virtual(helper="", range=""):
132   EXPORT_PC
133   // Fast-path which gets the method from thread-local cache.
134   FETCH_FROM_THREAD_CACHE %rdi, 2f
1351:
136   // First argument is the 'this' pointer.
137   movzwl 4(rPC), %r11d // arguments
138   .if !$range
139   andq $$0xf, %r11
140   .endif
141   movl (rFP, %r11, 4), %esi
142   // Note: if esi is null, this will be handled by our SIGSEGV handler.
143   movl MIRROR_OBJECT_CLASS_OFFSET(%esi), %edx
144   movq MIRROR_CLASS_VTABLE_OFFSET_64(%edx, %edi, 8), %rdi
145   jmp $helper
1462:
147   movq rSELF:THREAD_SELF_OFFSET, %rdi
148   movq 0(%rsp), %rsi
149   movq rPC, %rdx
150   call nterp_get_method
151   movl %eax, %edi
152   jmp 1b
153
154%def op_invoke_virtual():
155%  invoke_virtual(helper="NterpCommonInvokeInstance", range="0")
156
157%def op_invoke_virtual_quick():
158   EXPORT_PC
159   movzwl 2(rPC), %eax // offset
160   // First argument is the 'this' pointer.
161   movzwl 4(rPC), %r11d // arguments
162   andq $$0xf, %r11
163   movl (rFP, %r11, 4), %esi
164   // Note: if esi is null, this will be handled by our SIGSEGV handler.
165   movl MIRROR_OBJECT_CLASS_OFFSET(%esi), %edx
166   movq MIRROR_CLASS_VTABLE_OFFSET_64(%edx, %eax, 8), %rdi
167   jmp NterpCommonInvokeInstance
168
169%def op_invoke_virtual_range():
170%  invoke_virtual(helper="NterpCommonInvokeInstanceRange", range="1")
171
172%def op_invoke_virtual_range_quick():
173   EXPORT_PC
174   movzwl 2(rPC), %eax // offset
175   // First argument is the 'this' pointer.
176   movzwl 4(rPC), %r11d // arguments
177   movl (rFP, %r11, 4), %esi
178   // Note: if esi is null, this will be handled by our SIGSEGV handler.
179   movl MIRROR_OBJECT_CLASS_OFFSET(%esi), %edx
180   movq MIRROR_CLASS_VTABLE_OFFSET_64(%edx, %eax, 8), %rdi
181   jmp NterpCommonInvokeInstanceRange
182