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 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 97 bool ManagedRuntimeCallingConvention::HasNext() { 98 return itr_args_ < NumArgs(); 99 } 100 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 118 bool ManagedRuntimeCallingConvention::IsCurrentArgExplicit() { 119 // Static methods have no implicit arguments, others implicitly pass this 120 return IsStatic() || (itr_args_ != 0); 121 } 122 123 bool ManagedRuntimeCallingConvention::IsCurrentArgPossiblyNull() { 124 return IsCurrentArgExplicit(); // any user parameter may be null 125 } 126 127 size_t ManagedRuntimeCallingConvention::CurrentParamSize() { 128 return ParamSize(itr_args_); 129 } 130 131 bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() { 132 return IsParamAReference(itr_args_); 133 } 134 135 bool ManagedRuntimeCallingConvention::IsCurrentParamAFloatOrDouble() { 136 return IsParamAFloatOrDouble(itr_args_); 137 } 138 139 bool ManagedRuntimeCallingConvention::IsCurrentParamADouble() { 140 return IsParamADouble(itr_args_); 141 } 142 143 bool ManagedRuntimeCallingConvention::IsCurrentParamALong() { 144 return IsParamALong(itr_args_); 145 } 146 147 // JNI calling convention 148 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 192 size_t JniCallingConvention::ReferenceCount() const { 193 return NumReferenceArgs() + (IsStatic() ? 1 : 0); 194 } 195 196 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 201 FrameOffset JniCallingConvention::ReturnValueSaveLocation() const { 202 // Segment state is 4 bytes long 203 return FrameOffset(SavedLocalReferenceCookieOffset().Int32Value() + 4); 204 } 205 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 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 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 247 bool JniCallingConvention::IsCurrentParamJniEnv() { 248 return (itr_args_ == kJniEnv); 249 } 250 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 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 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 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 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 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