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="", is_super=""):
15   EXPORT_PC
16   // Fast-path which gets the method from thread-local cache.
17%  fetch_from_thread_cache("%rdi", miss_label="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   .if $is_super
35   jmp 1b
36   .else
37   testl MACRO_LITERAL(1), %eax
38   je 1b
39   andq $$-2, %rdi  // Remove the extra bit that marks it's a String.<init> method.
40   .if $range
41   jmp NterpHandleStringInitRange
42   .else
43   jmp NterpHandleStringInit
44   .endif
45   .endif
46
47%def op_invoke_direct():
48%  invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0", is_super="0")
49
50%def op_invoke_direct_range():
51%  invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1", is_super="0")
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   movzwl 4(rPC), %r11d // arguments
58   andq $$0xf, %r11
59   movl (rFP, %r11, 4), %esi
60   // NullPointerException check.
61   movl (%esi), %eax
62   jmp NterpCommonInvokePolymorphic
63
64%def op_invoke_polymorphic_range():
65   EXPORT_PC
66   // No need to fetch the target method.
67   // Load the first argument (the 'this' pointer).
68   movzwl 4(rPC), %r11d // arguments
69   movl (rFP, %r11, 4), %esi
70   // NullPointerException check.
71   movl (%esi), %eax
72   jmp NterpCommonInvokePolymorphicRange
73
74%def invoke_interface(helper="", range=""):
75%  slow_path = add_slow_path(op_invoke_interface_slow_path)
76   EXPORT_PC
77   // Fast-path which gets the interface method from thread-local cache.
78%  fetch_from_thread_cache("%rax", miss_label=slow_path)
79.L${opcode}_resume:
80   // First argument is the 'this' pointer.
81   movzwl 4(rPC), %r11d // arguments
82   .if !$range
83   andq $$0xf, %r11
84   .endif
85   movl (rFP, %r11, 4), %esi
86   movl MIRROR_OBJECT_CLASS_OFFSET(%esi), %edx
87   UNPOISON_HEAP_REF edx
88   // Test the first two bits of the fetched ArtMethod:
89   // - If the first bit is set, this is a method on j.l.Object
90   // - If the second bit is set, this is a default method.
91   testl $$3, %eax
92   jne 2f
93   movzw ART_METHOD_IMT_INDEX_OFFSET(%rax), %ecx
941:
95   movq MIRROR_CLASS_IMT_PTR_OFFSET_64(%edx), %rdx
96   movq (%rdx, %rcx, 8), %rdi
97   jmp $helper
982:
99   testl $$1, %eax
100   .if $range
101   jne NterpHandleInvokeInterfaceOnObjectMethodRange
102   .else
103   jne NterpHandleInvokeInterfaceOnObjectMethod
104   .endif
105   // Default method
106   andq $$-4, %rax
107   movzw ART_METHOD_METHOD_INDEX_OFFSET(%rax), %ecx
108   andl $$ART_METHOD_IMT_MASK, %ecx
109   jmp 1b
110
111%def op_invoke_interface_slow_path():
112   movq rSELF:THREAD_SELF_OFFSET, %rdi
113   movq 0(%rsp), %rsi
114   movq rPC, %rdx
115   call nterp_get_method
116   jmp .L${opcode}_resume
117
118%def op_invoke_interface():
119%  invoke_interface(helper="NterpCommonInvokeInterface", range="0")
120
121%def op_invoke_interface_range():
122%  invoke_interface(helper="NterpCommonInvokeInterfaceRange", range="1")
123
124%def invoke_static(helper=""):
125   EXPORT_PC
126   // Fast-path which gets the method from thread-local cache.
127%  fetch_from_thread_cache("%rdi", miss_label="1f")
128   jmp $helper
1291:
130   movq rSELF:THREAD_SELF_OFFSET, %rdi
131   movq 0(%rsp), %rsi
132   movq rPC, %rdx
133   call nterp_get_method
134   movq %rax, %rdi
135   jmp $helper
136
137%def op_invoke_static():
138%  invoke_static(helper="NterpCommonInvokeStatic")
139
140%def op_invoke_static_range():
141%  invoke_static(helper="NterpCommonInvokeStaticRange")
142
143%def op_invoke_super():
144%  invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0", is_super="1")
145
146%def op_invoke_super_range():
147%  invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1", is_super="1")
148
149%def invoke_virtual(helper="", range=""):
150   EXPORT_PC
151   // Fast-path which gets the method from thread-local cache.
152%  fetch_from_thread_cache("%rdi", miss_label="2f")
1531:
154   // First argument is the 'this' pointer.
155   movzwl 4(rPC), %r11d // arguments
156   .if !$range
157   andq $$0xf, %r11
158   .endif
159   movl (rFP, %r11, 4), %esi
160   // Note: if esi is null, this will be handled by our SIGSEGV handler.
161   movl MIRROR_OBJECT_CLASS_OFFSET(%esi), %edx
162   UNPOISON_HEAP_REF edx
163   movq MIRROR_CLASS_VTABLE_OFFSET_64(%edx, %edi, 8), %rdi
164   jmp $helper
1652:
166   movq rSELF:THREAD_SELF_OFFSET, %rdi
167   movq 0(%rsp), %rsi
168   movq rPC, %rdx
169   call nterp_get_method
170   movl %eax, %edi
171   jmp 1b
172
173%def op_invoke_virtual():
174%  invoke_virtual(helper="NterpCommonInvokeInstance", range="0")
175
176%def op_invoke_virtual_range():
177%  invoke_virtual(helper="NterpCommonInvokeInstanceRange", range="1")
178