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