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