Home | History | Annotate | Download | only in runtime
      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:
     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 
     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 
     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 
     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 
     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.
     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 
     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.
     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.
     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.
    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.
    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