• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "calling_convention.h"
18 
19 #include "base/logging.h"
20 
21 #ifdef ART_ENABLE_CODEGEN_arm
22 #include "jni/quick/arm/calling_convention_arm.h"
23 #endif
24 
25 #ifdef ART_ENABLE_CODEGEN_arm64
26 #include "jni/quick/arm64/calling_convention_arm64.h"
27 #endif
28 
29 #ifdef ART_ENABLE_CODEGEN_mips
30 #include "jni/quick/mips/calling_convention_mips.h"
31 #endif
32 
33 #ifdef ART_ENABLE_CODEGEN_mips64
34 #include "jni/quick/mips64/calling_convention_mips64.h"
35 #endif
36 
37 #ifdef ART_ENABLE_CODEGEN_x86
38 #include "jni/quick/x86/calling_convention_x86.h"
39 #endif
40 
41 #ifdef ART_ENABLE_CODEGEN_x86_64
42 #include "jni/quick/x86_64/calling_convention_x86_64.h"
43 #endif
44 
45 namespace art {
46 
47 // Managed runtime calling convention
48 
Create(ArenaAllocator * arena,bool is_static,bool is_synchronized,const char * shorty,InstructionSet instruction_set)49 std::unique_ptr<ManagedRuntimeCallingConvention> ManagedRuntimeCallingConvention::Create(
50     ArenaAllocator* arena,
51     bool is_static,
52     bool is_synchronized,
53     const char* shorty,
54     InstructionSet instruction_set) {
55   switch (instruction_set) {
56 #ifdef ART_ENABLE_CODEGEN_arm
57     case kArm:
58     case kThumb2:
59       return std::unique_ptr<ManagedRuntimeCallingConvention>(
60           new (arena) arm::ArmManagedRuntimeCallingConvention(is_static, is_synchronized, shorty));
61 #endif
62 #ifdef ART_ENABLE_CODEGEN_arm64
63     case kArm64:
64       return std::unique_ptr<ManagedRuntimeCallingConvention>(
65           new (arena) arm64::Arm64ManagedRuntimeCallingConvention(
66               is_static, is_synchronized, shorty));
67 #endif
68 #ifdef ART_ENABLE_CODEGEN_mips
69     case kMips:
70       return std::unique_ptr<ManagedRuntimeCallingConvention>(
71           new (arena) mips::MipsManagedRuntimeCallingConvention(
72               is_static, is_synchronized, shorty));
73 #endif
74 #ifdef ART_ENABLE_CODEGEN_mips64
75     case kMips64:
76       return std::unique_ptr<ManagedRuntimeCallingConvention>(
77           new (arena) mips64::Mips64ManagedRuntimeCallingConvention(
78               is_static, is_synchronized, shorty));
79 #endif
80 #ifdef ART_ENABLE_CODEGEN_x86
81     case kX86:
82       return std::unique_ptr<ManagedRuntimeCallingConvention>(
83           new (arena) x86::X86ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty));
84 #endif
85 #ifdef ART_ENABLE_CODEGEN_x86_64
86     case kX86_64:
87       return std::unique_ptr<ManagedRuntimeCallingConvention>(
88           new (arena) x86_64::X86_64ManagedRuntimeCallingConvention(
89               is_static, is_synchronized, shorty));
90 #endif
91     default:
92       LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
93       UNREACHABLE();
94   }
95 }
96 
HasNext()97 bool ManagedRuntimeCallingConvention::HasNext() {
98   return itr_args_ < NumArgs();
99 }
100 
Next()101 void ManagedRuntimeCallingConvention::Next() {
102   CHECK(HasNext());
103   if (IsCurrentArgExplicit() &&  // don't query parameter type of implicit args
104       IsParamALongOrDouble(itr_args_)) {
105     itr_longs_and_doubles_++;
106     itr_slots_++;
107   }
108   if (IsParamAFloatOrDouble(itr_args_)) {
109     itr_float_and_doubles_++;
110   }
111   if (IsCurrentParamAReference()) {
112     itr_refs_++;
113   }
114   itr_args_++;
115   itr_slots_++;
116 }
117 
IsCurrentArgExplicit()118 bool ManagedRuntimeCallingConvention::IsCurrentArgExplicit() {
119   // Static methods have no implicit arguments, others implicitly pass this
120   return IsStatic() || (itr_args_ != 0);
121 }
122 
IsCurrentArgPossiblyNull()123 bool ManagedRuntimeCallingConvention::IsCurrentArgPossiblyNull() {
124   return IsCurrentArgExplicit();  // any user parameter may be null
125 }
126 
CurrentParamSize()127 size_t ManagedRuntimeCallingConvention::CurrentParamSize() {
128   return ParamSize(itr_args_);
129 }
130 
IsCurrentParamAReference()131 bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() {
132   return IsParamAReference(itr_args_);
133 }
134 
IsCurrentParamAFloatOrDouble()135 bool ManagedRuntimeCallingConvention::IsCurrentParamAFloatOrDouble() {
136   return IsParamAFloatOrDouble(itr_args_);
137 }
138 
IsCurrentParamADouble()139 bool ManagedRuntimeCallingConvention::IsCurrentParamADouble() {
140   return IsParamADouble(itr_args_);
141 }
142 
IsCurrentParamALong()143 bool ManagedRuntimeCallingConvention::IsCurrentParamALong() {
144   return IsParamALong(itr_args_);
145 }
146 
147 // JNI calling convention
148 
Create(ArenaAllocator * arena,bool is_static,bool is_synchronized,const char * shorty,InstructionSet instruction_set)149 std::unique_ptr<JniCallingConvention> JniCallingConvention::Create(ArenaAllocator* arena,
150                                                                    bool is_static,
151                                                                    bool is_synchronized,
152                                                                    const char* shorty,
153                                                                    InstructionSet instruction_set) {
154   switch (instruction_set) {
155 #ifdef ART_ENABLE_CODEGEN_arm
156     case kArm:
157     case kThumb2:
158       return std::unique_ptr<JniCallingConvention>(
159           new (arena) arm::ArmJniCallingConvention(is_static, is_synchronized, shorty));
160 #endif
161 #ifdef ART_ENABLE_CODEGEN_arm64
162     case kArm64:
163       return std::unique_ptr<JniCallingConvention>(
164           new (arena) arm64::Arm64JniCallingConvention(is_static, is_synchronized, shorty));
165 #endif
166 #ifdef ART_ENABLE_CODEGEN_mips
167     case kMips:
168       return std::unique_ptr<JniCallingConvention>(
169           new (arena) mips::MipsJniCallingConvention(is_static, is_synchronized, shorty));
170 #endif
171 #ifdef ART_ENABLE_CODEGEN_mips64
172     case kMips64:
173       return std::unique_ptr<JniCallingConvention>(
174           new (arena) mips64::Mips64JniCallingConvention(is_static, is_synchronized, shorty));
175 #endif
176 #ifdef ART_ENABLE_CODEGEN_x86
177     case kX86:
178       return std::unique_ptr<JniCallingConvention>(
179           new (arena) x86::X86JniCallingConvention(is_static, is_synchronized, shorty));
180 #endif
181 #ifdef ART_ENABLE_CODEGEN_x86_64
182     case kX86_64:
183       return std::unique_ptr<JniCallingConvention>(
184           new (arena) x86_64::X86_64JniCallingConvention(is_static, is_synchronized, shorty));
185 #endif
186     default:
187       LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
188       UNREACHABLE();
189   }
190 }
191 
ReferenceCount() const192 size_t JniCallingConvention::ReferenceCount() const {
193   return NumReferenceArgs() + (IsStatic() ? 1 : 0);
194 }
195 
SavedLocalReferenceCookieOffset() const196 FrameOffset JniCallingConvention::SavedLocalReferenceCookieOffset() const {
197   size_t references_size = handle_scope_pointer_size_ * ReferenceCount();  // size excluding header
198   return FrameOffset(HandleReferencesOffset().Int32Value() + references_size);
199 }
200 
ReturnValueSaveLocation() const201 FrameOffset JniCallingConvention::ReturnValueSaveLocation() const {
202   // Segment state is 4 bytes long
203   return FrameOffset(SavedLocalReferenceCookieOffset().Int32Value() + 4);
204 }
205 
HasNext()206 bool JniCallingConvention::HasNext() {
207   if (itr_args_ <= kObjectOrClass) {
208     return true;
209   } else {
210     unsigned int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
211     return arg_pos < NumArgs();
212   }
213 }
214 
Next()215 void JniCallingConvention::Next() {
216   CHECK(HasNext());
217   if (itr_args_ > kObjectOrClass) {
218     int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
219     if (IsParamALongOrDouble(arg_pos)) {
220       itr_longs_and_doubles_++;
221       itr_slots_++;
222     }
223   }
224   if (IsCurrentParamAFloatOrDouble()) {
225     itr_float_and_doubles_++;
226   }
227   if (IsCurrentParamAReference()) {
228     itr_refs_++;
229   }
230   itr_args_++;
231   itr_slots_++;
232 }
233 
IsCurrentParamAReference()234 bool JniCallingConvention::IsCurrentParamAReference() {
235   switch (itr_args_) {
236     case kJniEnv:
237       return false;  // JNIEnv*
238     case kObjectOrClass:
239       return true;   // jobject or jclass
240     default: {
241       int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
242       return IsParamAReference(arg_pos);
243     }
244   }
245 }
246 
IsCurrentParamJniEnv()247 bool JniCallingConvention::IsCurrentParamJniEnv() {
248   return (itr_args_ == kJniEnv);
249 }
250 
IsCurrentParamAFloatOrDouble()251 bool JniCallingConvention::IsCurrentParamAFloatOrDouble() {
252   switch (itr_args_) {
253     case kJniEnv:
254       return false;  // JNIEnv*
255     case kObjectOrClass:
256       return false;   // jobject or jclass
257     default: {
258       int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
259       return IsParamAFloatOrDouble(arg_pos);
260     }
261   }
262 }
263 
IsCurrentParamADouble()264 bool JniCallingConvention::IsCurrentParamADouble() {
265   switch (itr_args_) {
266     case kJniEnv:
267       return false;  // JNIEnv*
268     case kObjectOrClass:
269       return false;   // jobject or jclass
270     default: {
271       int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
272       return IsParamADouble(arg_pos);
273     }
274   }
275 }
276 
IsCurrentParamALong()277 bool JniCallingConvention::IsCurrentParamALong() {
278   switch (itr_args_) {
279     case kJniEnv:
280       return false;  // JNIEnv*
281     case kObjectOrClass:
282       return false;   // jobject or jclass
283     default: {
284       int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
285       return IsParamALong(arg_pos);
286     }
287   }
288 }
289 
290 // Return position of handle scope entry holding reference at the current iterator
291 // position
CurrentParamHandleScopeEntryOffset()292 FrameOffset JniCallingConvention::CurrentParamHandleScopeEntryOffset() {
293   CHECK(IsCurrentParamAReference());
294   CHECK_LT(HandleScopeLinkOffset(), HandleScopeNumRefsOffset());
295   int result = HandleReferencesOffset().Int32Value() + itr_refs_ * handle_scope_pointer_size_;
296   CHECK_GT(result, HandleScopeNumRefsOffset().Int32Value());
297   return FrameOffset(result);
298 }
299 
CurrentParamSize()300 size_t JniCallingConvention::CurrentParamSize() {
301   if (itr_args_ <= kObjectOrClass) {
302     return frame_pointer_size_;  // JNIEnv or jobject/jclass
303   } else {
304     int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
305     return ParamSize(arg_pos);
306   }
307 }
308 
NumberOfExtraArgumentsForJni()309 size_t JniCallingConvention::NumberOfExtraArgumentsForJni() {
310   // The first argument is the JNIEnv*.
311   // Static methods have an extra argument which is the jclass.
312   return IsStatic() ? 2 : 1;
313 }
314 
315 }  // namespace art
316