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/mips/calling_convention_mips.h" 22 #include "jni/quick/x86/calling_convention_x86.h" 23 #include "utils.h" 24 25 namespace art { 26 27 // Offset of Method within the frame 28 FrameOffset CallingConvention::MethodStackOffset() { 29 return displacement_; 30 } 31 32 // Managed runtime calling convention 33 34 ManagedRuntimeCallingConvention* ManagedRuntimeCallingConvention::Create( 35 bool is_static, bool is_synchronized, const char* shorty, InstructionSet instruction_set) { 36 switch (instruction_set) { 37 case kArm: 38 case kThumb2: 39 return new arm::ArmManagedRuntimeCallingConvention(is_static, is_synchronized, shorty); 40 case kMips: 41 return new mips::MipsManagedRuntimeCallingConvention(is_static, is_synchronized, shorty); 42 case kX86: 43 return new x86::X86ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty); 44 default: 45 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set; 46 return NULL; 47 } 48 } 49 50 bool ManagedRuntimeCallingConvention::HasNext() { 51 return itr_args_ < NumArgs(); 52 } 53 54 void ManagedRuntimeCallingConvention::Next() { 55 CHECK(HasNext()); 56 if (IsCurrentArgExplicit() && // don't query parameter type of implicit args 57 IsParamALongOrDouble(itr_args_)) { 58 itr_longs_and_doubles_++; 59 itr_slots_++; 60 } 61 if (IsCurrentParamAReference()) { 62 itr_refs_++; 63 } 64 itr_args_++; 65 itr_slots_++; 66 } 67 68 bool ManagedRuntimeCallingConvention::IsCurrentArgExplicit() { 69 // Static methods have no implicit arguments, others implicitly pass this 70 return IsStatic() || (itr_args_ != 0); 71 } 72 73 bool ManagedRuntimeCallingConvention::IsCurrentArgPossiblyNull() { 74 return IsCurrentArgExplicit(); // any user parameter may be null 75 } 76 77 size_t ManagedRuntimeCallingConvention::CurrentParamSize() { 78 return ParamSize(itr_args_); 79 } 80 81 bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() { 82 return IsParamAReference(itr_args_); 83 } 84 85 // JNI calling convention 86 87 JniCallingConvention* JniCallingConvention::Create(bool is_static, bool is_synchronized, 88 const char* shorty, 89 InstructionSet instruction_set) { 90 switch (instruction_set) { 91 case kArm: 92 case kThumb2: 93 return new arm::ArmJniCallingConvention(is_static, is_synchronized, shorty); 94 case kMips: 95 return new mips::MipsJniCallingConvention(is_static, is_synchronized, shorty); 96 case kX86: 97 return new x86::X86JniCallingConvention(is_static, is_synchronized, shorty); 98 default: 99 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set; 100 return NULL; 101 } 102 } 103 104 size_t JniCallingConvention::ReferenceCount() const { 105 return NumReferenceArgs() + (IsStatic() ? 1 : 0); 106 } 107 108 FrameOffset JniCallingConvention::SavedLocalReferenceCookieOffset() const { 109 size_t start_of_sirt = SirtLinkOffset().Int32Value() + kPointerSize; 110 size_t references_size = kPointerSize * ReferenceCount(); // size excluding header 111 return FrameOffset(start_of_sirt + references_size); 112 } 113 114 FrameOffset JniCallingConvention::ReturnValueSaveLocation() const { 115 // Segment state is 4 bytes long 116 return FrameOffset(SavedLocalReferenceCookieOffset().Int32Value() + 4); 117 } 118 119 bool JniCallingConvention::HasNext() { 120 if (itr_args_ <= kObjectOrClass) { 121 return true; 122 } else { 123 unsigned int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(); 124 return arg_pos < NumArgs(); 125 } 126 } 127 128 void JniCallingConvention::Next() { 129 CHECK(HasNext()); 130 if (itr_args_ > kObjectOrClass) { 131 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(); 132 if (IsParamALongOrDouble(arg_pos)) { 133 itr_longs_and_doubles_++; 134 itr_slots_++; 135 } 136 } 137 if (IsCurrentParamAReference()) { 138 itr_refs_++; 139 } 140 itr_args_++; 141 itr_slots_++; 142 } 143 144 bool JniCallingConvention::IsCurrentParamAReference() { 145 switch (itr_args_) { 146 case kJniEnv: 147 return false; // JNIEnv* 148 case kObjectOrClass: 149 return true; // jobject or jclass 150 default: { 151 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(); 152 return IsParamAReference(arg_pos); 153 } 154 } 155 } 156 157 // Return position of SIRT entry holding reference at the current iterator 158 // position 159 FrameOffset JniCallingConvention::CurrentParamSirtEntryOffset() { 160 CHECK(IsCurrentParamAReference()); 161 CHECK_GT(SirtLinkOffset(), SirtNumRefsOffset()); 162 // Address of 1st SIRT entry 163 int result = SirtLinkOffset().Int32Value() + kPointerSize; 164 result += itr_refs_ * kPointerSize; 165 CHECK_GT(result, SirtLinkOffset().Int32Value()); 166 return FrameOffset(result); 167 } 168 169 size_t JniCallingConvention::CurrentParamSize() { 170 if (itr_args_ <= kObjectOrClass) { 171 return kPointerSize; // JNIEnv or jobject/jclass 172 } else { 173 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(); 174 return ParamSize(arg_pos); 175 } 176 } 177 178 size_t JniCallingConvention::NumberOfExtraArgumentsForJni() { 179 // The first argument is the JNIEnv*. 180 // Static methods have an extra argument which is the jclass. 181 return IsStatic() ? 2 : 1; 182 } 183 184 } // namespace art 185