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 #include "jni/quick/arm/calling_convention_arm.h" 21 #include "jni/quick/arm64/calling_convention_arm64.h" 22 #include "jni/quick/mips/calling_convention_mips.h" 23 #include "jni/quick/x86/calling_convention_x86.h" 24 #include "jni/quick/x86_64/calling_convention_x86_64.h" 25 #include "utils.h" 26 27 namespace art { 28 29 // Managed runtime calling convention 30 31 ManagedRuntimeCallingConvention* ManagedRuntimeCallingConvention::Create( 32 bool is_static, bool is_synchronized, const char* shorty, InstructionSet instruction_set) { 33 switch (instruction_set) { 34 case kArm: 35 case kThumb2: 36 return new arm::ArmManagedRuntimeCallingConvention(is_static, is_synchronized, shorty); 37 case kArm64: 38 return new arm64::Arm64ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty); 39 case kMips: 40 return new mips::MipsManagedRuntimeCallingConvention(is_static, is_synchronized, shorty); 41 case kX86: 42 return new x86::X86ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty); 43 case kX86_64: 44 return new x86_64::X86_64ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty); 45 default: 46 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set; 47 return NULL; 48 } 49 } 50 51 bool ManagedRuntimeCallingConvention::HasNext() { 52 return itr_args_ < NumArgs(); 53 } 54 55 void ManagedRuntimeCallingConvention::Next() { 56 CHECK(HasNext()); 57 if (IsCurrentArgExplicit() && // don't query parameter type of implicit args 58 IsParamALongOrDouble(itr_args_)) { 59 itr_longs_and_doubles_++; 60 itr_slots_++; 61 } 62 if (IsParamAFloatOrDouble(itr_args_)) { 63 itr_float_and_doubles_++; 64 } 65 if (IsCurrentParamAReference()) { 66 itr_refs_++; 67 } 68 itr_args_++; 69 itr_slots_++; 70 } 71 72 bool ManagedRuntimeCallingConvention::IsCurrentArgExplicit() { 73 // Static methods have no implicit arguments, others implicitly pass this 74 return IsStatic() || (itr_args_ != 0); 75 } 76 77 bool ManagedRuntimeCallingConvention::IsCurrentArgPossiblyNull() { 78 return IsCurrentArgExplicit(); // any user parameter may be null 79 } 80 81 size_t ManagedRuntimeCallingConvention::CurrentParamSize() { 82 return ParamSize(itr_args_); 83 } 84 85 bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() { 86 return IsParamAReference(itr_args_); 87 } 88 89 bool ManagedRuntimeCallingConvention::IsCurrentParamAFloatOrDouble() { 90 return IsParamAFloatOrDouble(itr_args_); 91 } 92 93 bool ManagedRuntimeCallingConvention::IsCurrentParamADouble() { 94 return IsParamADouble(itr_args_); 95 } 96 97 bool ManagedRuntimeCallingConvention::IsCurrentParamALong() { 98 return IsParamALong(itr_args_); 99 } 100 101 // JNI calling convention 102 103 JniCallingConvention* JniCallingConvention::Create(bool is_static, bool is_synchronized, 104 const char* shorty, 105 InstructionSet instruction_set) { 106 switch (instruction_set) { 107 case kArm: 108 case kThumb2: 109 return new arm::ArmJniCallingConvention(is_static, is_synchronized, shorty); 110 case kArm64: 111 return new arm64::Arm64JniCallingConvention(is_static, is_synchronized, shorty); 112 case kMips: 113 return new mips::MipsJniCallingConvention(is_static, is_synchronized, shorty); 114 case kX86: 115 return new x86::X86JniCallingConvention(is_static, is_synchronized, shorty); 116 case kX86_64: 117 return new x86_64::X86_64JniCallingConvention(is_static, is_synchronized, shorty); 118 default: 119 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set; 120 return NULL; 121 } 122 } 123 124 size_t JniCallingConvention::ReferenceCount() const { 125 return NumReferenceArgs() + (IsStatic() ? 1 : 0); 126 } 127 128 FrameOffset JniCallingConvention::SavedLocalReferenceCookieOffset() const { 129 size_t references_size = handle_scope_pointer_size_ * ReferenceCount(); // size excluding header 130 return FrameOffset(HandleerencesOffset().Int32Value() + references_size); 131 } 132 133 FrameOffset JniCallingConvention::ReturnValueSaveLocation() const { 134 // Segment state is 4 bytes long 135 return FrameOffset(SavedLocalReferenceCookieOffset().Int32Value() + 4); 136 } 137 138 bool JniCallingConvention::HasNext() { 139 if (itr_args_ <= kObjectOrClass) { 140 return true; 141 } else { 142 unsigned int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(); 143 return arg_pos < NumArgs(); 144 } 145 } 146 147 void JniCallingConvention::Next() { 148 CHECK(HasNext()); 149 if (itr_args_ > kObjectOrClass) { 150 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(); 151 if (IsParamALongOrDouble(arg_pos)) { 152 itr_longs_and_doubles_++; 153 itr_slots_++; 154 } 155 } 156 if (IsCurrentParamAFloatOrDouble()) { 157 itr_float_and_doubles_++; 158 } 159 if (IsCurrentParamAReference()) { 160 itr_refs_++; 161 } 162 itr_args_++; 163 itr_slots_++; 164 } 165 166 bool JniCallingConvention::IsCurrentParamAReference() { 167 switch (itr_args_) { 168 case kJniEnv: 169 return false; // JNIEnv* 170 case kObjectOrClass: 171 return true; // jobject or jclass 172 default: { 173 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(); 174 return IsParamAReference(arg_pos); 175 } 176 } 177 } 178 179 bool JniCallingConvention::IsCurrentParamJniEnv() { 180 return (itr_args_ == kJniEnv); 181 } 182 183 bool JniCallingConvention::IsCurrentParamAFloatOrDouble() { 184 switch (itr_args_) { 185 case kJniEnv: 186 return false; // JNIEnv* 187 case kObjectOrClass: 188 return false; // jobject or jclass 189 default: { 190 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(); 191 return IsParamAFloatOrDouble(arg_pos); 192 } 193 } 194 } 195 196 bool JniCallingConvention::IsCurrentParamADouble() { 197 switch (itr_args_) { 198 case kJniEnv: 199 return false; // JNIEnv* 200 case kObjectOrClass: 201 return false; // jobject or jclass 202 default: { 203 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(); 204 return IsParamADouble(arg_pos); 205 } 206 } 207 } 208 209 bool JniCallingConvention::IsCurrentParamALong() { 210 switch (itr_args_) { 211 case kJniEnv: 212 return false; // JNIEnv* 213 case kObjectOrClass: 214 return false; // jobject or jclass 215 default: { 216 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(); 217 return IsParamALong(arg_pos); 218 } 219 } 220 } 221 222 // Return position of handle scope entry holding reference at the current iterator 223 // position 224 FrameOffset JniCallingConvention::CurrentParamHandleScopeEntryOffset() { 225 CHECK(IsCurrentParamAReference()); 226 CHECK_LT(HandleScopeLinkOffset(), HandleScopeNumRefsOffset()); 227 int result = HandleerencesOffset().Int32Value() + itr_refs_ * handle_scope_pointer_size_; 228 CHECK_GT(result, HandleScopeNumRefsOffset().Int32Value()); 229 return FrameOffset(result); 230 } 231 232 size_t JniCallingConvention::CurrentParamSize() { 233 if (itr_args_ <= kObjectOrClass) { 234 return frame_pointer_size_; // JNIEnv or jobject/jclass 235 } else { 236 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(); 237 return ParamSize(arg_pos); 238 } 239 } 240 241 size_t JniCallingConvention::NumberOfExtraArgumentsForJni() { 242 // The first argument is the JNIEnv*. 243 // Static methods have an extra argument which is the jclass. 244 return IsStatic() ? 2 : 1; 245 } 246 247 } // namespace art 248