xref: /aosp_15_r20/art/compiler/jni/quick/calling_convention.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2011 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "calling_convention.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h>
20*795d594fSAndroid Build Coastguard Worker 
21*795d594fSAndroid Build Coastguard Worker #include "arch/instruction_set.h"
22*795d594fSAndroid Build Coastguard Worker #include "indirect_reference_table.h"
23*795d594fSAndroid Build Coastguard Worker 
24*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_arm
25*795d594fSAndroid Build Coastguard Worker #include "jni/quick/arm/calling_convention_arm.h"
26*795d594fSAndroid Build Coastguard Worker #endif
27*795d594fSAndroid Build Coastguard Worker 
28*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_arm64
29*795d594fSAndroid Build Coastguard Worker #include "jni/quick/arm64/calling_convention_arm64.h"
30*795d594fSAndroid Build Coastguard Worker #endif
31*795d594fSAndroid Build Coastguard Worker 
32*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_riscv64
33*795d594fSAndroid Build Coastguard Worker #include "jni/quick/riscv64/calling_convention_riscv64.h"
34*795d594fSAndroid Build Coastguard Worker #endif
35*795d594fSAndroid Build Coastguard Worker 
36*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_x86
37*795d594fSAndroid Build Coastguard Worker #include "jni/quick/x86/calling_convention_x86.h"
38*795d594fSAndroid Build Coastguard Worker #endif
39*795d594fSAndroid Build Coastguard Worker 
40*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_x86_64
41*795d594fSAndroid Build Coastguard Worker #include "jni/quick/x86_64/calling_convention_x86_64.h"
42*795d594fSAndroid Build Coastguard Worker #endif
43*795d594fSAndroid Build Coastguard Worker 
44*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
45*795d594fSAndroid Build Coastguard Worker 
46*795d594fSAndroid Build Coastguard Worker // Managed runtime calling convention
47*795d594fSAndroid Build Coastguard Worker 
Create(ArenaAllocator * allocator,bool is_static,bool is_synchronized,std::string_view shorty,InstructionSet instruction_set)48*795d594fSAndroid Build Coastguard Worker std::unique_ptr<ManagedRuntimeCallingConvention> ManagedRuntimeCallingConvention::Create(
49*795d594fSAndroid Build Coastguard Worker     ArenaAllocator* allocator,
50*795d594fSAndroid Build Coastguard Worker     bool is_static,
51*795d594fSAndroid Build Coastguard Worker     bool is_synchronized,
52*795d594fSAndroid Build Coastguard Worker     std::string_view shorty,
53*795d594fSAndroid Build Coastguard Worker     InstructionSet instruction_set) {
54*795d594fSAndroid Build Coastguard Worker   switch (instruction_set) {
55*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_arm
56*795d594fSAndroid Build Coastguard Worker     case InstructionSet::kArm:
57*795d594fSAndroid Build Coastguard Worker     case InstructionSet::kThumb2:
58*795d594fSAndroid Build Coastguard Worker       return std::unique_ptr<ManagedRuntimeCallingConvention>(
59*795d594fSAndroid Build Coastguard Worker           new (allocator) arm::ArmManagedRuntimeCallingConvention(
60*795d594fSAndroid Build Coastguard Worker               is_static, is_synchronized, shorty));
61*795d594fSAndroid Build Coastguard Worker #endif
62*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_arm64
63*795d594fSAndroid Build Coastguard Worker     case InstructionSet::kArm64:
64*795d594fSAndroid Build Coastguard Worker       return std::unique_ptr<ManagedRuntimeCallingConvention>(
65*795d594fSAndroid Build Coastguard Worker           new (allocator) arm64::Arm64ManagedRuntimeCallingConvention(
66*795d594fSAndroid Build Coastguard Worker               is_static, is_synchronized, shorty));
67*795d594fSAndroid Build Coastguard Worker #endif
68*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_riscv64
69*795d594fSAndroid Build Coastguard Worker     case InstructionSet::kRiscv64:
70*795d594fSAndroid Build Coastguard Worker       return std::unique_ptr<ManagedRuntimeCallingConvention>(
71*795d594fSAndroid Build Coastguard Worker           new (allocator) riscv64::Riscv64ManagedRuntimeCallingConvention(
72*795d594fSAndroid Build Coastguard Worker               is_static, is_synchronized, shorty));
73*795d594fSAndroid Build Coastguard Worker #endif
74*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_x86
75*795d594fSAndroid Build Coastguard Worker     case InstructionSet::kX86:
76*795d594fSAndroid Build Coastguard Worker       return std::unique_ptr<ManagedRuntimeCallingConvention>(
77*795d594fSAndroid Build Coastguard Worker           new (allocator) x86::X86ManagedRuntimeCallingConvention(
78*795d594fSAndroid Build Coastguard Worker               is_static, is_synchronized, shorty));
79*795d594fSAndroid Build Coastguard Worker #endif
80*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_x86_64
81*795d594fSAndroid Build Coastguard Worker     case InstructionSet::kX86_64:
82*795d594fSAndroid Build Coastguard Worker       return std::unique_ptr<ManagedRuntimeCallingConvention>(
83*795d594fSAndroid Build Coastguard Worker           new (allocator) x86_64::X86_64ManagedRuntimeCallingConvention(
84*795d594fSAndroid Build Coastguard Worker               is_static, is_synchronized, shorty));
85*795d594fSAndroid Build Coastguard Worker #endif
86*795d594fSAndroid Build Coastguard Worker     default:
87*795d594fSAndroid Build Coastguard Worker       UNUSED(allocator);
88*795d594fSAndroid Build Coastguard Worker       UNUSED(is_static);
89*795d594fSAndroid Build Coastguard Worker       UNUSED(is_synchronized);
90*795d594fSAndroid Build Coastguard Worker       UNUSED(shorty);
91*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
92*795d594fSAndroid Build Coastguard Worker       UNREACHABLE();
93*795d594fSAndroid Build Coastguard Worker   }
94*795d594fSAndroid Build Coastguard Worker }
95*795d594fSAndroid Build Coastguard Worker 
HasNext()96*795d594fSAndroid Build Coastguard Worker bool ManagedRuntimeCallingConvention::HasNext() {
97*795d594fSAndroid Build Coastguard Worker   return itr_args_ < NumArgs();
98*795d594fSAndroid Build Coastguard Worker }
99*795d594fSAndroid Build Coastguard Worker 
Next()100*795d594fSAndroid Build Coastguard Worker void ManagedRuntimeCallingConvention::Next() {
101*795d594fSAndroid Build Coastguard Worker   CHECK(HasNext());
102*795d594fSAndroid Build Coastguard Worker   if (IsCurrentArgExplicit() &&  // don't query parameter type of implicit args
103*795d594fSAndroid Build Coastguard Worker       IsParamALongOrDouble(itr_args_)) {
104*795d594fSAndroid Build Coastguard Worker     itr_longs_and_doubles_++;
105*795d594fSAndroid Build Coastguard Worker     itr_slots_++;
106*795d594fSAndroid Build Coastguard Worker   }
107*795d594fSAndroid Build Coastguard Worker   if (IsParamAFloatOrDouble(itr_args_)) {
108*795d594fSAndroid Build Coastguard Worker     itr_float_and_doubles_++;
109*795d594fSAndroid Build Coastguard Worker   }
110*795d594fSAndroid Build Coastguard Worker   if (IsCurrentParamAReference()) {
111*795d594fSAndroid Build Coastguard Worker     itr_refs_++;
112*795d594fSAndroid Build Coastguard Worker   }
113*795d594fSAndroid Build Coastguard Worker   itr_args_++;
114*795d594fSAndroid Build Coastguard Worker   itr_slots_++;
115*795d594fSAndroid Build Coastguard Worker }
116*795d594fSAndroid Build Coastguard Worker 
IsCurrentArgExplicit()117*795d594fSAndroid Build Coastguard Worker bool ManagedRuntimeCallingConvention::IsCurrentArgExplicit() {
118*795d594fSAndroid Build Coastguard Worker   // Static methods have no implicit arguments, others implicitly pass this
119*795d594fSAndroid Build Coastguard Worker   return IsStatic() || (itr_args_ != 0);
120*795d594fSAndroid Build Coastguard Worker }
121*795d594fSAndroid Build Coastguard Worker 
IsCurrentArgPossiblyNull()122*795d594fSAndroid Build Coastguard Worker bool ManagedRuntimeCallingConvention::IsCurrentArgPossiblyNull() {
123*795d594fSAndroid Build Coastguard Worker   return IsCurrentArgExplicit();  // any user parameter may be null
124*795d594fSAndroid Build Coastguard Worker }
125*795d594fSAndroid Build Coastguard Worker 
CurrentParamSize()126*795d594fSAndroid Build Coastguard Worker size_t ManagedRuntimeCallingConvention::CurrentParamSize() {
127*795d594fSAndroid Build Coastguard Worker   return ParamSize(itr_args_, /*reference_size=*/ sizeof(mirror::HeapReference<mirror::Object>));
128*795d594fSAndroid Build Coastguard Worker }
129*795d594fSAndroid Build Coastguard Worker 
IsCurrentParamAReference()130*795d594fSAndroid Build Coastguard Worker bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() {
131*795d594fSAndroid Build Coastguard Worker   return IsParamAReference(itr_args_);
132*795d594fSAndroid Build Coastguard Worker }
133*795d594fSAndroid Build Coastguard Worker 
IsCurrentParamAFloatOrDouble()134*795d594fSAndroid Build Coastguard Worker bool ManagedRuntimeCallingConvention::IsCurrentParamAFloatOrDouble() {
135*795d594fSAndroid Build Coastguard Worker   return IsParamAFloatOrDouble(itr_args_);
136*795d594fSAndroid Build Coastguard Worker }
137*795d594fSAndroid Build Coastguard Worker 
IsCurrentParamADouble()138*795d594fSAndroid Build Coastguard Worker bool ManagedRuntimeCallingConvention::IsCurrentParamADouble() {
139*795d594fSAndroid Build Coastguard Worker   return IsParamADouble(itr_args_);
140*795d594fSAndroid Build Coastguard Worker }
141*795d594fSAndroid Build Coastguard Worker 
IsCurrentParamALong()142*795d594fSAndroid Build Coastguard Worker bool ManagedRuntimeCallingConvention::IsCurrentParamALong() {
143*795d594fSAndroid Build Coastguard Worker   return IsParamALong(itr_args_);
144*795d594fSAndroid Build Coastguard Worker }
145*795d594fSAndroid Build Coastguard Worker 
146*795d594fSAndroid Build Coastguard Worker // JNI calling convention
147*795d594fSAndroid Build Coastguard Worker 
Create(ArenaAllocator * allocator,bool is_static,bool is_synchronized,bool is_fast_native,bool is_critical_native,std::string_view shorty,InstructionSet instruction_set)148*795d594fSAndroid Build Coastguard Worker std::unique_ptr<JniCallingConvention> JniCallingConvention::Create(ArenaAllocator* allocator,
149*795d594fSAndroid Build Coastguard Worker                                                                    bool is_static,
150*795d594fSAndroid Build Coastguard Worker                                                                    bool is_synchronized,
151*795d594fSAndroid Build Coastguard Worker                                                                    bool is_fast_native,
152*795d594fSAndroid Build Coastguard Worker                                                                    bool is_critical_native,
153*795d594fSAndroid Build Coastguard Worker                                                                    std::string_view shorty,
154*795d594fSAndroid Build Coastguard Worker                                                                    InstructionSet instruction_set) {
155*795d594fSAndroid Build Coastguard Worker   switch (instruction_set) {
156*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_arm
157*795d594fSAndroid Build Coastguard Worker     case InstructionSet::kArm:
158*795d594fSAndroid Build Coastguard Worker     case InstructionSet::kThumb2:
159*795d594fSAndroid Build Coastguard Worker       return std::unique_ptr<JniCallingConvention>(
160*795d594fSAndroid Build Coastguard Worker           new (allocator) arm::ArmJniCallingConvention(
161*795d594fSAndroid Build Coastguard Worker               is_static, is_synchronized, is_fast_native, is_critical_native, shorty));
162*795d594fSAndroid Build Coastguard Worker #endif
163*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_arm64
164*795d594fSAndroid Build Coastguard Worker     case InstructionSet::kArm64:
165*795d594fSAndroid Build Coastguard Worker       return std::unique_ptr<JniCallingConvention>(
166*795d594fSAndroid Build Coastguard Worker           new (allocator) arm64::Arm64JniCallingConvention(
167*795d594fSAndroid Build Coastguard Worker               is_static, is_synchronized, is_fast_native, is_critical_native, shorty));
168*795d594fSAndroid Build Coastguard Worker #endif
169*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_riscv64
170*795d594fSAndroid Build Coastguard Worker     case InstructionSet::kRiscv64:
171*795d594fSAndroid Build Coastguard Worker       return std::unique_ptr<JniCallingConvention>(
172*795d594fSAndroid Build Coastguard Worker           new (allocator) riscv64::Riscv64JniCallingConvention(
173*795d594fSAndroid Build Coastguard Worker               is_static, is_synchronized, is_fast_native, is_critical_native, shorty));
174*795d594fSAndroid Build Coastguard Worker #endif
175*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_x86
176*795d594fSAndroid Build Coastguard Worker     case InstructionSet::kX86:
177*795d594fSAndroid Build Coastguard Worker       return std::unique_ptr<JniCallingConvention>(
178*795d594fSAndroid Build Coastguard Worker           new (allocator) x86::X86JniCallingConvention(
179*795d594fSAndroid Build Coastguard Worker               is_static, is_synchronized, is_fast_native, is_critical_native, shorty));
180*795d594fSAndroid Build Coastguard Worker #endif
181*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_x86_64
182*795d594fSAndroid Build Coastguard Worker     case InstructionSet::kX86_64:
183*795d594fSAndroid Build Coastguard Worker       return std::unique_ptr<JniCallingConvention>(
184*795d594fSAndroid Build Coastguard Worker           new (allocator) x86_64::X86_64JniCallingConvention(
185*795d594fSAndroid Build Coastguard Worker               is_static, is_synchronized, is_fast_native, is_critical_native, shorty));
186*795d594fSAndroid Build Coastguard Worker #endif
187*795d594fSAndroid Build Coastguard Worker     default:
188*795d594fSAndroid Build Coastguard Worker       UNUSED(allocator);
189*795d594fSAndroid Build Coastguard Worker       UNUSED(is_static);
190*795d594fSAndroid Build Coastguard Worker       UNUSED(is_synchronized);
191*795d594fSAndroid Build Coastguard Worker       UNUSED(is_fast_native);
192*795d594fSAndroid Build Coastguard Worker       UNUSED(is_critical_native);
193*795d594fSAndroid Build Coastguard Worker       UNUSED(shorty);
194*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
195*795d594fSAndroid Build Coastguard Worker       UNREACHABLE();
196*795d594fSAndroid Build Coastguard Worker   }
197*795d594fSAndroid Build Coastguard Worker }
198*795d594fSAndroid Build Coastguard Worker 
ReferenceCount() const199*795d594fSAndroid Build Coastguard Worker size_t JniCallingConvention::ReferenceCount() const {
200*795d594fSAndroid Build Coastguard Worker   return NumReferenceArgs() + (IsStatic() ? 1 : 0);
201*795d594fSAndroid Build Coastguard Worker }
202*795d594fSAndroid Build Coastguard Worker 
HasNext()203*795d594fSAndroid Build Coastguard Worker bool JniCallingConvention::HasNext() {
204*795d594fSAndroid Build Coastguard Worker   if (IsCurrentArgExtraForJni()) {
205*795d594fSAndroid Build Coastguard Worker     return true;
206*795d594fSAndroid Build Coastguard Worker   } else {
207*795d594fSAndroid Build Coastguard Worker     size_t arg_pos = GetIteratorPositionWithinShorty();
208*795d594fSAndroid Build Coastguard Worker     return arg_pos < NumArgs();
209*795d594fSAndroid Build Coastguard Worker   }
210*795d594fSAndroid Build Coastguard Worker }
211*795d594fSAndroid Build Coastguard Worker 
Next()212*795d594fSAndroid Build Coastguard Worker void JniCallingConvention::Next() {
213*795d594fSAndroid Build Coastguard Worker   CHECK(HasNext());
214*795d594fSAndroid Build Coastguard Worker   if (IsCurrentParamALong() || IsCurrentParamADouble()) {
215*795d594fSAndroid Build Coastguard Worker     itr_longs_and_doubles_++;
216*795d594fSAndroid Build Coastguard Worker     itr_slots_++;
217*795d594fSAndroid Build Coastguard Worker   }
218*795d594fSAndroid Build Coastguard Worker   if (IsCurrentParamAFloatOrDouble()) {
219*795d594fSAndroid Build Coastguard Worker     itr_float_and_doubles_++;
220*795d594fSAndroid Build Coastguard Worker   }
221*795d594fSAndroid Build Coastguard Worker   if (IsCurrentParamAReference()) {
222*795d594fSAndroid Build Coastguard Worker     itr_refs_++;
223*795d594fSAndroid Build Coastguard Worker   }
224*795d594fSAndroid Build Coastguard Worker   // This default/fallthrough case also covers the extra JNIEnv* argument,
225*795d594fSAndroid Build Coastguard Worker   // as well as any other single-slot primitives.
226*795d594fSAndroid Build Coastguard Worker   itr_args_++;
227*795d594fSAndroid Build Coastguard Worker   itr_slots_++;
228*795d594fSAndroid Build Coastguard Worker }
229*795d594fSAndroid Build Coastguard Worker 
IsCurrentParamAReference()230*795d594fSAndroid Build Coastguard Worker bool JniCallingConvention::IsCurrentParamAReference() {
231*795d594fSAndroid Build Coastguard Worker   bool return_value;
232*795d594fSAndroid Build Coastguard Worker   if (SwitchExtraJniArguments(itr_args_,
233*795d594fSAndroid Build Coastguard Worker                               false,  // JNIEnv*
234*795d594fSAndroid Build Coastguard Worker                               true,   // jobject or jclass
235*795d594fSAndroid Build Coastguard Worker                               /* out parameters */
236*795d594fSAndroid Build Coastguard Worker                               &return_value)) {
237*795d594fSAndroid Build Coastguard Worker     return return_value;
238*795d594fSAndroid Build Coastguard Worker   } else {
239*795d594fSAndroid Build Coastguard Worker     size_t arg_pos = GetIteratorPositionWithinShorty();
240*795d594fSAndroid Build Coastguard Worker     return IsParamAReference(arg_pos);
241*795d594fSAndroid Build Coastguard Worker   }
242*795d594fSAndroid Build Coastguard Worker }
243*795d594fSAndroid Build Coastguard Worker 
244*795d594fSAndroid Build Coastguard Worker 
IsCurrentParamJniEnv()245*795d594fSAndroid Build Coastguard Worker bool JniCallingConvention::IsCurrentParamJniEnv() {
246*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(!HasJniEnv())) {
247*795d594fSAndroid Build Coastguard Worker     return false;
248*795d594fSAndroid Build Coastguard Worker   }
249*795d594fSAndroid Build Coastguard Worker   return (itr_args_ == kJniEnv);
250*795d594fSAndroid Build Coastguard Worker }
251*795d594fSAndroid Build Coastguard Worker 
IsCurrentParamAFloatOrDouble()252*795d594fSAndroid Build Coastguard Worker bool JniCallingConvention::IsCurrentParamAFloatOrDouble() {
253*795d594fSAndroid Build Coastguard Worker   bool return_value;
254*795d594fSAndroid Build Coastguard Worker   if (SwitchExtraJniArguments(itr_args_,
255*795d594fSAndroid Build Coastguard Worker                               false,  // jnienv*
256*795d594fSAndroid Build Coastguard Worker                               false,  // jobject or jclass
257*795d594fSAndroid Build Coastguard Worker                               /* out parameters */
258*795d594fSAndroid Build Coastguard Worker                               &return_value)) {
259*795d594fSAndroid Build Coastguard Worker     return return_value;
260*795d594fSAndroid Build Coastguard Worker   } else {
261*795d594fSAndroid Build Coastguard Worker     size_t arg_pos = GetIteratorPositionWithinShorty();
262*795d594fSAndroid Build Coastguard Worker     return IsParamAFloatOrDouble(arg_pos);
263*795d594fSAndroid Build Coastguard Worker   }
264*795d594fSAndroid Build Coastguard Worker }
265*795d594fSAndroid Build Coastguard Worker 
IsCurrentParamADouble()266*795d594fSAndroid Build Coastguard Worker bool JniCallingConvention::IsCurrentParamADouble() {
267*795d594fSAndroid Build Coastguard Worker   bool return_value;
268*795d594fSAndroid Build Coastguard Worker   if (SwitchExtraJniArguments(itr_args_,
269*795d594fSAndroid Build Coastguard Worker                               false,  // jnienv*
270*795d594fSAndroid Build Coastguard Worker                               false,  // jobject or jclass
271*795d594fSAndroid Build Coastguard Worker                               /* out parameters */
272*795d594fSAndroid Build Coastguard Worker                               &return_value)) {
273*795d594fSAndroid Build Coastguard Worker     return return_value;
274*795d594fSAndroid Build Coastguard Worker   } else {
275*795d594fSAndroid Build Coastguard Worker     size_t arg_pos = GetIteratorPositionWithinShorty();
276*795d594fSAndroid Build Coastguard Worker     return IsParamADouble(arg_pos);
277*795d594fSAndroid Build Coastguard Worker   }
278*795d594fSAndroid Build Coastguard Worker }
279*795d594fSAndroid Build Coastguard Worker 
IsCurrentParamALong()280*795d594fSAndroid Build Coastguard Worker bool JniCallingConvention::IsCurrentParamALong() {
281*795d594fSAndroid Build Coastguard Worker   bool return_value;
282*795d594fSAndroid Build Coastguard Worker   if (SwitchExtraJniArguments(itr_args_,
283*795d594fSAndroid Build Coastguard Worker                               false,  // jnienv*
284*795d594fSAndroid Build Coastguard Worker                               false,  // jobject or jclass
285*795d594fSAndroid Build Coastguard Worker                               /* out parameters */
286*795d594fSAndroid Build Coastguard Worker                               &return_value)) {
287*795d594fSAndroid Build Coastguard Worker     return return_value;
288*795d594fSAndroid Build Coastguard Worker   } else {
289*795d594fSAndroid Build Coastguard Worker     size_t arg_pos = GetIteratorPositionWithinShorty();
290*795d594fSAndroid Build Coastguard Worker     return IsParamALong(arg_pos);
291*795d594fSAndroid Build Coastguard Worker   }
292*795d594fSAndroid Build Coastguard Worker }
293*795d594fSAndroid Build Coastguard Worker 
CurrentParamSize() const294*795d594fSAndroid Build Coastguard Worker size_t JniCallingConvention::CurrentParamSize() const {
295*795d594fSAndroid Build Coastguard Worker   if (IsCurrentArgExtraForJni()) {
296*795d594fSAndroid Build Coastguard Worker     return static_cast<size_t>(frame_pointer_size_);  // JNIEnv or jobject/jclass
297*795d594fSAndroid Build Coastguard Worker   } else {
298*795d594fSAndroid Build Coastguard Worker     size_t arg_pos = GetIteratorPositionWithinShorty();
299*795d594fSAndroid Build Coastguard Worker     // References are converted to `jobject` for the native call. Pass `frame_pointer_size_`.
300*795d594fSAndroid Build Coastguard Worker     return ParamSize(arg_pos, /*reference_size=*/ static_cast<size_t>(frame_pointer_size_));
301*795d594fSAndroid Build Coastguard Worker   }
302*795d594fSAndroid Build Coastguard Worker }
303*795d594fSAndroid Build Coastguard Worker 
NumberOfExtraArgumentsForJni() const304*795d594fSAndroid Build Coastguard Worker size_t JniCallingConvention::NumberOfExtraArgumentsForJni() const {
305*795d594fSAndroid Build Coastguard Worker   if (LIKELY(HasExtraArgumentsForJni())) {
306*795d594fSAndroid Build Coastguard Worker     // The first argument is the JNIEnv*.
307*795d594fSAndroid Build Coastguard Worker     // Static methods have an extra argument which is the jclass.
308*795d594fSAndroid Build Coastguard Worker     return IsStatic() ? 2 : 1;
309*795d594fSAndroid Build Coastguard Worker   } else {
310*795d594fSAndroid Build Coastguard Worker     // Critical natives exclude the JNIEnv and the jclass/this parameters.
311*795d594fSAndroid Build Coastguard Worker     return 0;
312*795d594fSAndroid Build Coastguard Worker   }
313*795d594fSAndroid Build Coastguard Worker }
314*795d594fSAndroid Build Coastguard Worker 
HasSelfClass() const315*795d594fSAndroid Build Coastguard Worker bool JniCallingConvention::HasSelfClass() const {
316*795d594fSAndroid Build Coastguard Worker   if (!IsStatic()) {
317*795d594fSAndroid Build Coastguard Worker     // Virtual functions: There is never an implicit jclass parameter.
318*795d594fSAndroid Build Coastguard Worker     return false;
319*795d594fSAndroid Build Coastguard Worker   } else {
320*795d594fSAndroid Build Coastguard Worker     // Static functions: There is an implicit jclass parameter unless it's @CriticalNative.
321*795d594fSAndroid Build Coastguard Worker     return HasExtraArgumentsForJni();
322*795d594fSAndroid Build Coastguard Worker   }
323*795d594fSAndroid Build Coastguard Worker }
324*795d594fSAndroid Build Coastguard Worker 
GetIteratorPositionWithinShorty() const325*795d594fSAndroid Build Coastguard Worker size_t JniCallingConvention::GetIteratorPositionWithinShorty() const {
326*795d594fSAndroid Build Coastguard Worker   // We need to subtract out the extra JNI arguments if we want to use this iterator position
327*795d594fSAndroid Build Coastguard Worker   // with the inherited CallingConvention member functions, which rely on scanning the shorty.
328*795d594fSAndroid Build Coastguard Worker   // Note that our shorty does *not* include the JNIEnv, jclass/jobject parameters.
329*795d594fSAndroid Build Coastguard Worker   DCHECK_GE(itr_args_, NumberOfExtraArgumentsForJni());
330*795d594fSAndroid Build Coastguard Worker   return itr_args_ - NumberOfExtraArgumentsForJni();
331*795d594fSAndroid Build Coastguard Worker }
332*795d594fSAndroid Build Coastguard Worker 
IsCurrentArgExtraForJni() const333*795d594fSAndroid Build Coastguard Worker bool JniCallingConvention::IsCurrentArgExtraForJni() const {
334*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(!HasExtraArgumentsForJni())) {
335*795d594fSAndroid Build Coastguard Worker     return false;  // If there are no extra args, we can never be an extra.
336*795d594fSAndroid Build Coastguard Worker   }
337*795d594fSAndroid Build Coastguard Worker   // Only parameters kJniEnv and kObjectOrClass are considered extra.
338*795d594fSAndroid Build Coastguard Worker   return itr_args_ <= kObjectOrClass;
339*795d594fSAndroid Build Coastguard Worker }
340*795d594fSAndroid Build Coastguard Worker 
SwitchExtraJniArguments(size_t switch_value,bool case_jni_env,bool case_object_or_class,bool * return_value) const341*795d594fSAndroid Build Coastguard Worker bool JniCallingConvention::SwitchExtraJniArguments(size_t switch_value,
342*795d594fSAndroid Build Coastguard Worker                                                    bool case_jni_env,
343*795d594fSAndroid Build Coastguard Worker                                                    bool case_object_or_class,
344*795d594fSAndroid Build Coastguard Worker                                                    /* out parameters */
345*795d594fSAndroid Build Coastguard Worker                                                    bool* return_value) const {
346*795d594fSAndroid Build Coastguard Worker   DCHECK(return_value != nullptr);
347*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(!HasExtraArgumentsForJni())) {
348*795d594fSAndroid Build Coastguard Worker     return false;
349*795d594fSAndroid Build Coastguard Worker   }
350*795d594fSAndroid Build Coastguard Worker 
351*795d594fSAndroid Build Coastguard Worker   switch (switch_value) {
352*795d594fSAndroid Build Coastguard Worker     case kJniEnv:
353*795d594fSAndroid Build Coastguard Worker       *return_value = case_jni_env;
354*795d594fSAndroid Build Coastguard Worker       return true;
355*795d594fSAndroid Build Coastguard Worker     case kObjectOrClass:
356*795d594fSAndroid Build Coastguard Worker       *return_value = case_object_or_class;
357*795d594fSAndroid Build Coastguard Worker       return true;
358*795d594fSAndroid Build Coastguard Worker     default:
359*795d594fSAndroid Build Coastguard Worker       return false;
360*795d594fSAndroid Build Coastguard Worker   }
361*795d594fSAndroid Build Coastguard Worker }
362*795d594fSAndroid Build Coastguard Worker 
363*795d594fSAndroid Build Coastguard Worker 
364*795d594fSAndroid Build Coastguard Worker }  // namespace art
365