• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_OBJECT_UTILS_H_
18 #define ART_RUNTIME_OBJECT_UTILS_H_
19 
20 #include "class_linker-inl.h"
21 #include "dex_file.h"
22 #include "monitor.h"
23 #include "mirror/art_field.h"
24 #include "mirror/art_method.h"
25 #include "mirror/class.h"
26 #include "mirror/dex_cache.h"
27 #include "mirror/iftable.h"
28 #include "mirror/string.h"
29 
30 #include "runtime.h"
31 #include "sirt_ref.h"
32 
33 #include <string>
34 
35 namespace art {
36 
37 class ObjectLock {
38  public:
ObjectLock(Thread * self,mirror::Object * object)39   explicit ObjectLock(Thread* self, mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
40       : self_(self), obj_(object) {
41     CHECK(object != NULL);
42     obj_->MonitorEnter(self_);
43   }
44 
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)45   ~ObjectLock() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
46     obj_->MonitorExit(self_);
47   }
48 
WaitIgnoringInterrupts()49   void WaitIgnoringInterrupts() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
50     Monitor::Wait(self_, obj_, 0, 0, false, kWaiting);
51   }
52 
Notify()53   void Notify() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
54     obj_->Notify(self_);
55   }
56 
NotifyAll()57   void NotifyAll() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
58     obj_->NotifyAll(self_);
59   }
60 
61  private:
62   Thread* const self_;
63   mirror::Object* obj_;
64   DISALLOW_COPY_AND_ASSIGN(ObjectLock);
65 };
66 
67 class ClassHelper {
68  public:
69   ClassHelper(const mirror::Class* c = NULL, ClassLinker* l = NULL)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)70       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
71       : class_linker_(l),
72         dex_cache_(NULL),
73         dex_file_(NULL),
74         interface_type_list_(NULL),
75         klass_(NULL) {
76     if (c != NULL) {
77       ChangeClass(c);
78     }
79   }
80 
ChangeClass(const mirror::Class * new_c)81   void ChangeClass(const mirror::Class* new_c)
82       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
83     CHECK(new_c != NULL) << "klass_=" << klass_;  // Log what we were changing from if any
84     CHECK(new_c->IsClass()) << "new_c=" << new_c;
85     if (dex_cache_ != NULL) {
86       mirror::DexCache* new_c_dex_cache = new_c->GetDexCache();
87       if (new_c_dex_cache != dex_cache_) {
88         dex_cache_ = new_c_dex_cache;
89         dex_file_ = NULL;
90       }
91     }
92     klass_ = new_c;
93     interface_type_list_ = NULL;
94   }
95 
96   // The returned const char* is only guaranteed to be valid for the lifetime of the ClassHelper.
97   // If you need it longer, copy it into a std::string.
GetDescriptor()98   const char* GetDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
99     CHECK(klass_ != NULL);
100     if (UNLIKELY(klass_->IsArrayClass())) {
101       return GetArrayDescriptor();
102     } else if (UNLIKELY(klass_->IsPrimitive())) {
103       return Primitive::Descriptor(klass_->GetPrimitiveType());
104     } else if (UNLIKELY(klass_->IsProxyClass())) {
105       descriptor_ = GetClassLinker()->GetDescriptorForProxy(klass_);
106       return descriptor_.c_str();
107     } else {
108       const DexFile& dex_file = GetDexFile();
109       const DexFile::TypeId& type_id = dex_file.GetTypeId(GetClassDef()->class_idx_);
110       return dex_file.GetTypeDescriptor(type_id);
111     }
112   }
113 
GetArrayDescriptor()114   const char* GetArrayDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
115     std::string result("[");
116     const mirror::Class* saved_klass = klass_;
117     CHECK(saved_klass != NULL);
118     ChangeClass(klass_->GetComponentType());
119     result += GetDescriptor();
120     ChangeClass(saved_klass);
121     descriptor_ = result;
122     return descriptor_.c_str();
123   }
124 
GetClassDef()125   const DexFile::ClassDef* GetClassDef() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
126     DCHECK(klass_ != nullptr);
127     uint16_t class_def_idx = klass_->GetDexClassDefIndex();
128     if (class_def_idx == DexFile::kDexNoIndex16) {
129       return nullptr;
130     }
131     return &GetDexFile().GetClassDef(class_def_idx);
132   }
133 
NumDirectInterfaces()134   uint32_t NumDirectInterfaces() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
135     DCHECK(klass_ != NULL);
136     if (klass_->IsPrimitive()) {
137       return 0;
138     } else if (klass_->IsArrayClass()) {
139       return 2;
140     } else if (klass_->IsProxyClass()) {
141       return klass_->GetIfTable()->GetLength();
142     } else {
143       const DexFile::TypeList* interfaces = GetInterfaceTypeList();
144       if (interfaces == NULL) {
145         return 0;
146       } else {
147         return interfaces->Size();
148       }
149     }
150   }
151 
GetDirectInterfaceTypeIdx(uint32_t idx)152   uint16_t GetDirectInterfaceTypeIdx(uint32_t idx)
153       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
154     DCHECK(klass_ != NULL);
155     DCHECK(!klass_->IsPrimitive());
156     DCHECK(!klass_->IsArrayClass());
157     return GetInterfaceTypeList()->GetTypeItem(idx).type_idx_;
158   }
159 
GetDirectInterface(uint32_t idx)160   mirror::Class* GetDirectInterface(uint32_t idx)
161       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
162     DCHECK(klass_ != NULL);
163     DCHECK(!klass_->IsPrimitive());
164     if (klass_->IsArrayClass()) {
165       if (idx == 0) {
166         return GetClassLinker()->FindSystemClass("Ljava/lang/Cloneable;");
167       } else {
168         DCHECK_EQ(1U, idx);
169         return GetClassLinker()->FindSystemClass("Ljava/io/Serializable;");
170       }
171     } else if (klass_->IsProxyClass()) {
172       return klass_->GetIfTable()->GetInterface(idx);
173     } else {
174       uint16_t type_idx = GetDirectInterfaceTypeIdx(idx);
175       mirror::Class* interface = GetDexCache()->GetResolvedType(type_idx);
176       if (interface == NULL) {
177         interface = GetClassLinker()->ResolveType(GetDexFile(), type_idx, klass_);
178         CHECK(interface != NULL || Thread::Current()->IsExceptionPending());
179       }
180       return interface;
181     }
182   }
183 
GetSourceFile()184   const char* GetSourceFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
185     std::string descriptor(GetDescriptor());
186     const DexFile& dex_file = GetDexFile();
187     const DexFile::ClassDef* dex_class_def = GetClassDef();
188     CHECK(dex_class_def != NULL);
189     return dex_file.GetSourceFile(*dex_class_def);
190   }
191 
GetLocation()192   std::string GetLocation() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
193     mirror::DexCache* dex_cache = GetDexCache();
194     if (dex_cache != NULL && !klass_->IsProxyClass()) {
195       return dex_cache->GetLocation()->ToModifiedUtf8();
196     } else {
197       // Arrays and proxies are generated and have no corresponding dex file location.
198       return "generated class";
199     }
200   }
201 
GetDexFile()202   const DexFile& GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
203     if (dex_file_ == NULL) {
204       dex_file_ = GetDexCache()->GetDexFile();
205     }
206     return *dex_file_;
207   }
208 
GetDexCache()209   mirror::DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
210     mirror::DexCache* result = dex_cache_;
211     if (result == NULL) {
212       DCHECK(klass_ != NULL);
213       result = klass_->GetDexCache();
214       dex_cache_ = result;
215     }
216     return result;
217   }
218 
219  private:
GetInterfaceTypeList()220   const DexFile::TypeList* GetInterfaceTypeList()
221       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
222     const DexFile::TypeList* result = interface_type_list_;
223     if (result == NULL) {
224       const DexFile::ClassDef* class_def = GetClassDef();
225       if (class_def != NULL) {
226         result =  GetDexFile().GetInterfacesList(*class_def);
227         interface_type_list_ = result;
228       }
229     }
230     return result;
231   }
232 
GetClassLinker()233   ClassLinker* GetClassLinker() {
234     ClassLinker* result = class_linker_;
235     if (result == NULL) {
236       result = Runtime::Current()->GetClassLinker();
237       class_linker_ = result;
238     }
239     return result;
240   }
241 
242   ClassLinker* class_linker_;
243   mirror::DexCache* dex_cache_;
244   const DexFile* dex_file_;
245   const DexFile::TypeList* interface_type_list_;
246   const mirror::Class* klass_;
247   std::string descriptor_;
248 
249   DISALLOW_COPY_AND_ASSIGN(ClassHelper);
250 };
251 
252 class FieldHelper {
253  public:
FieldHelper()254   FieldHelper() : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), field_(NULL) {}
FieldHelper(const mirror::ArtField * f)255   explicit FieldHelper(const mirror::ArtField* f) : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), field_(f) {}
FieldHelper(const mirror::ArtField * f,ClassLinker * l)256   FieldHelper(const mirror::ArtField* f, ClassLinker* l)
257       : class_linker_(l), dex_cache_(NULL), dex_file_(NULL), field_(f) {}
258 
ChangeField(const mirror::ArtField * new_f)259   void ChangeField(const mirror::ArtField* new_f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
260     DCHECK(new_f != NULL);
261     if (dex_cache_ != NULL) {
262       mirror::DexCache* new_f_dex_cache = new_f->GetDeclaringClass()->GetDexCache();
263       if (new_f_dex_cache != dex_cache_) {
264         dex_cache_ = new_f_dex_cache;
265         dex_file_ = NULL;
266       }
267     }
268     field_ = new_f;
269   }
GetName()270   const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
271     uint32_t field_index = field_->GetDexFieldIndex();
272     if (!field_->GetDeclaringClass()->IsProxyClass()) {
273       const DexFile& dex_file = GetDexFile();
274       return dex_file.GetFieldName(dex_file.GetFieldId(field_index));
275     } else {
276       DCHECK(field_->IsStatic());
277       DCHECK_LT(field_index, 2U);
278       return field_index == 0 ? "interfaces" : "throws";
279     }
280   }
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)281   mirror::Class* GetType(bool resolve = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
282     uint32_t field_index = field_->GetDexFieldIndex();
283     if (!field_->GetDeclaringClass()->IsProxyClass()) {
284       const DexFile& dex_file = GetDexFile();
285       const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
286       mirror::Class* type = GetDexCache()->GetResolvedType(field_id.type_idx_);
287       if (resolve && (type == NULL)) {
288         type = GetClassLinker()->ResolveType(field_id.type_idx_, field_);
289         CHECK(type != NULL || Thread::Current()->IsExceptionPending());
290       }
291       return type;
292     } else {
293       return GetClassLinker()->FindSystemClass(GetTypeDescriptor());
294     }
295   }
GetTypeDescriptor()296   const char* GetTypeDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
297     uint32_t field_index = field_->GetDexFieldIndex();
298     if (!field_->GetDeclaringClass()->IsProxyClass()) {
299       const DexFile& dex_file = GetDexFile();
300       const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
301       return dex_file.GetFieldTypeDescriptor(field_id);
302     } else {
303       DCHECK(field_->IsStatic());
304       DCHECK_LT(field_index, 2U);
305       // 0 == Class[] interfaces; 1 == Class[][] throws;
306       return field_index == 0 ? "[Ljava/lang/Class;" : "[[Ljava/lang/Class;";
307     }
308   }
GetTypeAsPrimitiveType()309   Primitive::Type GetTypeAsPrimitiveType()
310       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
311     return Primitive::GetType(GetTypeDescriptor()[0]);
312   }
IsPrimitiveType()313   bool IsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
314     Primitive::Type type = GetTypeAsPrimitiveType();
315     return type != Primitive::kPrimNot;
316   }
FieldSize()317   size_t FieldSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
318     Primitive::Type type = GetTypeAsPrimitiveType();
319     return Primitive::FieldSize(type);
320   }
321 
322   // The returned const char* is only guaranteed to be valid for the lifetime of the FieldHelper.
323   // If you need it longer, copy it into a std::string.
GetDeclaringClassDescriptor()324   const char* GetDeclaringClassDescriptor()
325       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
326     uint32_t field_index = field_->GetDexFieldIndex();
327     if (!field_->GetDeclaringClass()->IsProxyClass()) {
328       const DexFile& dex_file = GetDexFile();
329       const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
330       return dex_file.GetFieldDeclaringClassDescriptor(field_id);
331     } else {
332       DCHECK(field_->IsStatic());
333       DCHECK_LT(field_index, 2U);
334       // 0 == Class[] interfaces; 1 == Class[][] throws;
335       ClassHelper kh(field_->GetDeclaringClass());
336       declaring_class_descriptor_ = kh.GetDescriptor();
337       return declaring_class_descriptor_.c_str();
338     }
339   }
340 
341  private:
GetDexCache()342   mirror::DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
343     mirror::DexCache* result = dex_cache_;
344     if (result == NULL) {
345       result = field_->GetDeclaringClass()->GetDexCache();
346       dex_cache_ = result;
347     }
348     return result;
349   }
GetClassLinker()350   ClassLinker* GetClassLinker() {
351     ClassLinker* result = class_linker_;
352     if (result == NULL) {
353       result = Runtime::Current()->GetClassLinker();
354       class_linker_ = result;
355     }
356     return result;
357   }
GetDexFile()358   const DexFile& GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
359     if (dex_file_ == NULL) {
360       dex_file_ = GetDexCache()->GetDexFile();
361     }
362     return *dex_file_;
363   }
364 
365   ClassLinker* class_linker_;
366   mirror::DexCache* dex_cache_;
367   const DexFile* dex_file_;
368   const mirror::ArtField* field_;
369   std::string declaring_class_descriptor_;
370 
371   DISALLOW_COPY_AND_ASSIGN(FieldHelper);
372 };
373 
374 class MethodHelper {
375  public:
MethodHelper()376   MethodHelper()
377      : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), method_(NULL), shorty_(NULL),
378        shorty_len_(0) {}
379 
MethodHelper(const mirror::ArtMethod * m)380   explicit MethodHelper(const mirror::ArtMethod* m)
381       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
382       : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), method_(NULL), shorty_(NULL),
383         shorty_len_(0) {
384     SetMethod(m);
385   }
386 
MethodHelper(const mirror::ArtMethod * m,ClassLinker * l)387   MethodHelper(const mirror::ArtMethod* m, ClassLinker* l)
388       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
389       : class_linker_(l), dex_cache_(NULL), dex_file_(NULL), method_(NULL), shorty_(NULL),
390         shorty_len_(0) {
391     SetMethod(m);
392   }
393 
ChangeMethod(mirror::ArtMethod * new_m)394   void ChangeMethod(mirror::ArtMethod* new_m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
395     DCHECK(new_m != NULL);
396     if (dex_cache_ != NULL) {
397       mirror::Class* klass = new_m->GetDeclaringClass();
398       if (klass->IsProxyClass()) {
399         dex_cache_ = NULL;
400         dex_file_ = NULL;
401       } else {
402         mirror::DexCache* new_m_dex_cache = klass->GetDexCache();
403         if (new_m_dex_cache != dex_cache_) {
404           dex_cache_ = new_m_dex_cache;
405           dex_file_ = NULL;
406         }
407       }
408     }
409     SetMethod(new_m);
410     shorty_ = NULL;
411   }
412 
GetMethod()413   const mirror::ArtMethod* GetMethod() const {
414     return method_;
415   }
416 
GetName()417   const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
418     const DexFile& dex_file = GetDexFile();
419     uint32_t dex_method_idx = method_->GetDexMethodIndex();
420     if (dex_method_idx != DexFile::kDexNoIndex) {
421       return dex_file.GetMethodName(dex_file.GetMethodId(dex_method_idx));
422     } else {
423       Runtime* runtime = Runtime::Current();
424       if (method_ == runtime->GetResolutionMethod()) {
425         return "<runtime internal resolution method>";
426       } else if (method_ == runtime->GetCalleeSaveMethod(Runtime::kSaveAll)) {
427         return "<runtime internal callee-save all registers method>";
428       } else if (method_ == runtime->GetCalleeSaveMethod(Runtime::kRefsOnly)) {
429         return "<runtime internal callee-save reference registers method>";
430       } else if (method_ == runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs)) {
431         return "<runtime internal callee-save reference and argument registers method>";
432       } else {
433         return "<unknown runtime internal method>";
434       }
435     }
436   }
437 
GetNameAsString()438   mirror::String* GetNameAsString() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
439     const DexFile& dex_file = GetDexFile();
440     uint32_t dex_method_idx = method_->GetDexMethodIndex();
441     const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
442     return GetClassLinker()->ResolveString(dex_file, method_id.name_idx_, GetDexCache());
443   }
444 
GetShorty()445   const char* GetShorty() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
446     const char* result = shorty_;
447     if (result == NULL) {
448       const DexFile& dex_file = GetDexFile();
449       result = dex_file.GetMethodShorty(dex_file.GetMethodId(method_->GetDexMethodIndex()),
450                                         &shorty_len_);
451       shorty_ = result;
452     }
453     return result;
454   }
455 
GetShortyLength()456   uint32_t GetShortyLength() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
457     if (shorty_ == NULL) {
458       GetShorty();
459     }
460     return shorty_len_;
461   }
462 
GetSignature()463   const std::string GetSignature() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
464     const DexFile& dex_file = GetDexFile();
465     uint32_t dex_method_idx = method_->GetDexMethodIndex();
466     if (dex_method_idx != DexFile::kDexNoIndex) {
467       return dex_file.GetMethodSignature(dex_file.GetMethodId(dex_method_idx));
468     } else {
469       return "<no signature>";
470     }
471   }
472 
GetPrototype()473   const DexFile::ProtoId& GetPrototype() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
474     const DexFile& dex_file = GetDexFile();
475     return dex_file.GetMethodPrototype(dex_file.GetMethodId(method_->GetDexMethodIndex()));
476   }
477 
GetParameterTypeList()478   const DexFile::TypeList* GetParameterTypeList() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
479     const DexFile::ProtoId& proto = GetPrototype();
480     return GetDexFile().GetProtoParameters(proto);
481   }
482 
GetReturnType()483   mirror::Class* GetReturnType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
484     const DexFile& dex_file = GetDexFile();
485     const DexFile::MethodId& method_id = dex_file.GetMethodId(method_->GetDexMethodIndex());
486     const DexFile::ProtoId& proto_id = dex_file.GetMethodPrototype(method_id);
487     uint16_t return_type_idx = proto_id.return_type_idx_;
488     return GetClassFromTypeIdx(return_type_idx);
489   }
490 
GetReturnTypeDescriptor()491   const char* GetReturnTypeDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
492     const DexFile& dex_file = GetDexFile();
493     const DexFile::MethodId& method_id = dex_file.GetMethodId(method_->GetDexMethodIndex());
494     const DexFile::ProtoId& proto_id = dex_file.GetMethodPrototype(method_id);
495     uint16_t return_type_idx = proto_id.return_type_idx_;
496     return dex_file.GetTypeDescriptor(dex_file.GetTypeId(return_type_idx));
497   }
498 
GetLineNumFromDexPC(uint32_t dex_pc)499   int32_t GetLineNumFromDexPC(uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
500     if (dex_pc == DexFile::kDexNoIndex) {
501       return method_->IsNative() ? -2 : -1;
502     } else {
503       const DexFile& dex_file = GetDexFile();
504       return dex_file.GetLineNumFromPC(method_, dex_pc);
505     }
506   }
507 
GetDeclaringClassDescriptor()508   const char* GetDeclaringClassDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
509     const DexFile& dex_file = GetDexFile();
510     uint32_t dex_method_idx = method_->GetDexMethodIndex();
511     if (dex_method_idx != DexFile::kDexNoIndex) {
512       return dex_file.GetMethodDeclaringClassDescriptor(dex_file.GetMethodId(dex_method_idx));
513     } else {
514       return "<runtime method>";
515     }
516   }
517 
GetDeclaringClassSourceFile()518   const char* GetDeclaringClassSourceFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
519     return ClassHelper(method_->GetDeclaringClass()).GetSourceFile();
520   }
521 
GetClassDefIndex()522   uint16_t GetClassDefIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
523     return method_->GetDeclaringClass()->GetDexClassDefIndex();
524   }
525 
GetClassDef()526   const DexFile::ClassDef& GetClassDef() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
527     return GetDexFile().GetClassDef(GetClassDefIndex());
528   }
529 
GetClassLoader()530   mirror::ClassLoader* GetClassLoader() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
531     return method_->GetDeclaringClass()->GetClassLoader();
532   }
533 
IsStatic()534   bool IsStatic() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
535     return method_->IsStatic();
536   }
537 
IsClassInitializer()538   bool IsClassInitializer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
539     return IsStatic() && StringPiece(GetName()) == "<clinit>";
540   }
541 
NumArgs()542   size_t NumArgs() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
543     // "1 +" because the first in Args is the receiver.
544     // "- 1" because we don't count the return type.
545     return (IsStatic() ? 0 : 1) + GetShortyLength() - 1;
546   }
547 
548   // Get the primitive type associated with the given parameter.
GetParamPrimitiveType(size_t param)549   Primitive::Type GetParamPrimitiveType(size_t param) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
550     CHECK_LT(param, NumArgs());
551     if (IsStatic()) {
552       param++;  // 0th argument must skip return value at start of the shorty
553     } else if (param == 0) {
554       return Primitive::kPrimNot;
555     }
556     return Primitive::GetType(GetShorty()[param]);
557   }
558 
559   // Is the specified parameter a long or double, where parameter 0 is 'this' for instance methods.
IsParamALongOrDouble(size_t param)560   bool IsParamALongOrDouble(size_t param) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
561     Primitive::Type type = GetParamPrimitiveType(param);
562     return type == Primitive::kPrimLong || type == Primitive::kPrimDouble;
563   }
564 
565   // Is the specified parameter a reference, where parameter 0 is 'this' for instance methods.
IsParamAReference(size_t param)566   bool IsParamAReference(size_t param) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
567     return GetParamPrimitiveType(param) == Primitive::kPrimNot;
568   }
569 
HasSameNameAndSignature(MethodHelper * other)570   bool HasSameNameAndSignature(MethodHelper* other)
571       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
572     if (GetDexCache() == other->GetDexCache()) {
573       const DexFile& dex_file = GetDexFile();
574       const DexFile::MethodId& mid = dex_file.GetMethodId(method_->GetDexMethodIndex());
575       const DexFile::MethodId& other_mid =
576           dex_file.GetMethodId(other->method_->GetDexMethodIndex());
577       return mid.name_idx_ == other_mid.name_idx_ && mid.proto_idx_ == other_mid.proto_idx_;
578     }
579     StringPiece name(GetName());
580     StringPiece other_name(other->GetName());
581     return name == other_name && GetSignature() == other->GetSignature();
582   }
583 
GetCodeItem()584   const DexFile::CodeItem* GetCodeItem()
585       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
586     return GetDexFile().GetCodeItem(method_->GetCodeItemOffset());
587   }
588 
IsResolvedTypeIdx(uint16_t type_idx)589   bool IsResolvedTypeIdx(uint16_t type_idx) const
590       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
591     return method_->GetDexCacheResolvedTypes()->Get(type_idx) != NULL;
592   }
593 
GetClassFromTypeIdx(uint16_t type_idx)594   mirror::Class* GetClassFromTypeIdx(uint16_t type_idx)
595       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
596     mirror::Class* type = method_->GetDexCacheResolvedTypes()->Get(type_idx);
597     if (type == NULL) {
598       type = GetClassLinker()->ResolveType(type_idx, method_);
599       CHECK(type != NULL || Thread::Current()->IsExceptionPending());
600     }
601     return type;
602   }
603 
GetTypeDescriptorFromTypeIdx(uint16_t type_idx)604   const char* GetTypeDescriptorFromTypeIdx(uint16_t type_idx)
605       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
606     const DexFile& dex_file = GetDexFile();
607     return dex_file.GetTypeDescriptor(dex_file.GetTypeId(type_idx));
608   }
609 
GetDexCacheResolvedType(uint16_t type_idx)610   mirror::Class* GetDexCacheResolvedType(uint16_t type_idx)
611       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
612     return method_->GetDexCacheResolvedTypes()->Get(type_idx);
613   }
614 
GetDexFile()615   const DexFile& GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
616     const DexFile* result = dex_file_;
617     if (result == NULL) {
618       const mirror::DexCache* dex_cache = GetDexCache();
619       result = dex_file_ = dex_cache->GetDexFile();
620     }
621     return *result;
622   }
623 
GetDexCache()624   mirror::DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
625     mirror::DexCache* result = dex_cache_;
626     if (result == NULL) {
627       mirror::Class* klass = method_->GetDeclaringClass();
628       result = klass->GetDexCache();
629       dex_cache_ = result;
630     }
631     return result;
632   }
633 
ResolveString(uint32_t string_idx)634   mirror::String* ResolveString(uint32_t string_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
635     mirror::String* s = method_->GetDexCacheStrings()->Get(string_idx);
636     if (UNLIKELY(s == NULL)) {
637       s = GetClassLinker()->ResolveString(GetDexFile(), string_idx, GetDexCache());
638     }
639     return s;
640   }
641 
642  private:
643   // Set the method_ field, for proxy methods looking up the interface method via the resolved
644   // methods table.
SetMethod(const mirror::ArtMethod * method)645   void SetMethod(const mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
646     if (method != NULL) {
647       mirror::Class* klass = method->GetDeclaringClass();
648       if (UNLIKELY(klass->IsProxyClass())) {
649         mirror::ArtMethod* interface_method =
650             method->GetDexCacheResolvedMethods()->Get(method->GetDexMethodIndex());
651         DCHECK(interface_method != NULL);
652         DCHECK(interface_method == GetClassLinker()->FindMethodForProxy(klass, method));
653         method = interface_method;
654       }
655     }
656     method_ = method;
657   }
658 
GetClassLinker()659   ClassLinker* GetClassLinker() {
660     ClassLinker* result = class_linker_;
661     if (result == NULL) {
662       result = Runtime::Current()->GetClassLinker();
663       class_linker_ = result;
664     }
665     return result;
666   }
667 
668   ClassLinker* class_linker_;
669   mirror::DexCache* dex_cache_;
670   const DexFile* dex_file_;
671   const mirror::ArtMethod* method_;
672   const char* shorty_;
673   uint32_t shorty_len_;
674 
675   DISALLOW_COPY_AND_ASSIGN(MethodHelper);
676 };
677 
678 }  // namespace art
679 
680 #endif  // ART_RUNTIME_OBJECT_UTILS_H_
681