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 #ifndef ART_RUNTIME_METHOD_HELPER_H_ 18 #define ART_RUNTIME_METHOD_HELPER_H_ 19 20 #include "base/macros.h" 21 #include "handle.h" 22 #include "mirror/art_method.h" 23 #include "primitive.h" 24 25 namespace art { 26 27 class MethodHelper { 28 public: MethodHelper(Handle<mirror::ArtMethod> m)29 explicit MethodHelper(Handle<mirror::ArtMethod> m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) 30 : method_(m), shorty_(nullptr), shorty_len_(0) { 31 SetMethod(m.Get()); 32 } 33 ChangeMethod(mirror::ArtMethod * new_m)34 void ChangeMethod(mirror::ArtMethod* new_m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 35 DCHECK(new_m != nullptr); 36 SetMethod(new_m); 37 shorty_ = nullptr; 38 } 39 GetMethod()40 mirror::ArtMethod* GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 41 return method_->GetInterfaceMethodIfProxy(); 42 } 43 44 mirror::String* GetNameAsString(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 45 GetShorty()46 const char* GetShorty() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 47 const char* result = shorty_; 48 if (result == nullptr) { 49 result = method_->GetShorty(&shorty_len_); 50 shorty_ = result; 51 } 52 return result; 53 } 54 GetShortyLength()55 uint32_t GetShortyLength() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 56 if (shorty_ == nullptr) { 57 GetShorty(); 58 } 59 return shorty_len_; 60 } 61 62 // Counts the number of references in the parameter list of the corresponding method. 63 // Note: Thus does _not_ include "this" for non-static methods. GetNumberOfReferenceArgsWithoutReceiver()64 uint32_t GetNumberOfReferenceArgsWithoutReceiver() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 65 const char* shorty = GetShorty(); 66 uint32_t refs = 0; 67 for (uint32_t i = 1; i < shorty_len_ ; ++i) { 68 if (shorty[i] == 'L') { 69 refs++; 70 } 71 } 72 73 return refs; 74 } 75 76 // May cause thread suspension due to GetClassFromTypeIdx calling ResolveType this caused a large 77 // number of bugs at call sites. 78 mirror::Class* GetReturnType(bool resolve = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 79 NumArgs()80 size_t NumArgs() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 81 // "1 +" because the first in Args is the receiver. 82 // "- 1" because we don't count the return type. 83 return (method_->IsStatic() ? 0 : 1) + GetShortyLength() - 1; 84 } 85 86 // Get the primitive type associated with the given parameter. GetParamPrimitiveType(size_t param)87 Primitive::Type GetParamPrimitiveType(size_t param) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 88 CHECK_LT(param, NumArgs()); 89 if (GetMethod()->IsStatic()) { 90 param++; // 0th argument must skip return value at start of the shorty 91 } else if (param == 0) { 92 return Primitive::kPrimNot; 93 } 94 return Primitive::GetType(GetShorty()[param]); 95 } 96 97 // Is the specified parameter a long or double, where parameter 0 is 'this' for instance methods. IsParamALongOrDouble(size_t param)98 bool IsParamALongOrDouble(size_t param) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 99 Primitive::Type type = GetParamPrimitiveType(param); 100 return type == Primitive::kPrimLong || type == Primitive::kPrimDouble; 101 } 102 103 // Is the specified parameter a reference, where parameter 0 is 'this' for instance methods. IsParamAReference(size_t param)104 bool IsParamAReference(size_t param) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 105 return GetParamPrimitiveType(param) == Primitive::kPrimNot; 106 } 107 108 ALWAYS_INLINE bool HasSameNameAndSignature(MethodHelper* other) 109 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 110 111 bool HasSameSignatureWithDifferentClassLoaders(MethodHelper* other) 112 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 113 114 mirror::Class* GetClassFromTypeIdx(uint16_t type_idx, bool resolve = true) 115 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 116 117 mirror::String* ResolveString(uint32_t string_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 118 119 uint32_t FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile) 120 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 121 122 // The name_and_signature_idx MUST point to a MethodId with the same name and signature in the 123 // other_dexfile, such as the method index used to resolve this method in the other_dexfile. 124 uint32_t FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile, 125 uint32_t name_and_signature_idx) 126 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 127 128 private: 129 // Set the method_ field, for proxy methods looking up the interface method via the resolved 130 // methods table. SetMethod(mirror::ArtMethod * method)131 void SetMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 132 method_.Assign(method); 133 } 134 135 Handle<mirror::ArtMethod> method_; 136 const char* shorty_; 137 uint32_t shorty_len_; 138 139 DISALLOW_COPY_AND_ASSIGN(MethodHelper); 140 }; 141 142 } // namespace art 143 144 #endif // ART_RUNTIME_METHOD_HELPER_H_ 145