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: 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 45 ~ObjectLock() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 46 obj_->MonitorExit(self_); 47 } 48 49 void WaitIgnoringInterrupts() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 50 Monitor::Wait(self_, obj_, 0, 0, false, kWaiting); 51 } 52 53 void Notify() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 54 obj_->Notify(self_); 55 } 56 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) 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 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. 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 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 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 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 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 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 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 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 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 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: 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 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: 254 FieldHelper() : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), field_(NULL) {} 255 explicit FieldHelper(const mirror::ArtField* f) : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), field_(f) {} 256 FieldHelper(const mirror::ArtField* f, ClassLinker* l) 257 : class_linker_(l), dex_cache_(NULL), dex_file_(NULL), field_(f) {} 258 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 } 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 } 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 } 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 } 309 Primitive::Type GetTypeAsPrimitiveType() 310 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 311 return Primitive::GetType(GetTypeDescriptor()[0]); 312 } 313 bool IsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 314 Primitive::Type type = GetTypeAsPrimitiveType(); 315 return type != Primitive::kPrimNot; 316 } 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. 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: 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 } 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 } 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: 376 MethodHelper() 377 : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), method_(NULL), shorty_(NULL), 378 shorty_len_(0) {} 379 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 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 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 413 const mirror::ArtMethod* GetMethod() const { 414 return method_; 415 } 416 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 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 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 456 uint32_t GetShortyLength() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 457 if (shorty_ == NULL) { 458 GetShorty(); 459 } 460 return shorty_len_; 461 } 462 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 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 478 const DexFile::TypeList* GetParameterTypeList() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 479 const DexFile::ProtoId& proto = GetPrototype(); 480 return GetDexFile().GetProtoParameters(proto); 481 } 482 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 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 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 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 518 const char* GetDeclaringClassSourceFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 519 return ClassHelper(method_->GetDeclaringClass()).GetSourceFile(); 520 } 521 522 uint16_t GetClassDefIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 523 return method_->GetDeclaringClass()->GetDexClassDefIndex(); 524 } 525 526 const DexFile::ClassDef& GetClassDef() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 527 return GetDexFile().GetClassDef(GetClassDefIndex()); 528 } 529 530 mirror::ClassLoader* GetClassLoader() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 531 return method_->GetDeclaringClass()->GetClassLoader(); 532 } 533 534 bool IsStatic() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 535 return method_->IsStatic(); 536 } 537 538 bool IsClassInitializer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 539 return IsStatic() && StringPiece(GetName()) == "<clinit>"; 540 } 541 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. 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. 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. 566 bool IsParamAReference(size_t param) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 567 return GetParamPrimitiveType(param) == Primitive::kPrimNot; 568 } 569 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 584 const DexFile::CodeItem* GetCodeItem() 585 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 586 return GetDexFile().GetCodeItem(method_->GetCodeItemOffset()); 587 } 588 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 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 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 610 mirror::Class* GetDexCacheResolvedType(uint16_t type_idx) 611 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 612 return method_->GetDexCacheResolvedTypes()->Get(type_idx); 613 } 614 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 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 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. 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 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