diff options
55 files changed, 578 insertions, 832 deletions
diff --git a/compiler/driver/compiler_driver-inl.h b/compiler/driver/compiler_driver-inl.h index 2d0dd3cda2..9efd636d2f 100644 --- a/compiler/driver/compiler_driver-inl.h +++ b/compiler/driver/compiler_driver-inl.h @@ -31,10 +31,6 @@ namespace art { -inline mirror::DexCache* CompilerDriver::GetDexCache(const DexCompilationUnit* mUnit) { - return mUnit->GetClassLinker()->FindDexCache(Thread::Current(), *mUnit->GetDexFile(), false); -} - inline mirror::ClassLoader* CompilerDriver::GetClassLoader(const ScopedObjectAccess& soa, const DexCompilationUnit* mUnit) { return soa.Decode<mirror::ClassLoader>(mUnit->GetClassLoader()).Decode(); @@ -87,10 +83,6 @@ inline ArtField* CompilerDriver::ResolveFieldWithDexFile( return resolved_field; } -inline mirror::DexCache* CompilerDriver::FindDexCache(const DexFile* dex_file) { - return Runtime::Current()->GetClassLinker()->FindDexCache(Thread::Current(), *dex_file, false); -} - inline ArtField* CompilerDriver::ResolveField( const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit, @@ -100,31 +92,16 @@ inline ArtField* CompilerDriver::ResolveField( is_static); } -inline void CompilerDriver::GetResolvedFieldDexFileLocation( - ArtField* resolved_field, const DexFile** declaring_dex_file, - uint16_t* declaring_class_idx, uint16_t* declaring_field_idx) { - mirror::Class* declaring_class = resolved_field->GetDeclaringClass(); - *declaring_dex_file = declaring_class->GetDexCache()->GetDexFile(); - *declaring_class_idx = declaring_class->GetDexTypeIndex(); - *declaring_field_idx = resolved_field->GetDexFieldIndex(); -} - -inline bool CompilerDriver::IsFieldVolatile(ArtField* field) { - return field->IsVolatile(); -} - -inline MemberOffset CompilerDriver::GetFieldOffset(ArtField* field) { - return field->GetOffset(); -} - inline std::pair<bool, bool> CompilerDriver::IsFastInstanceField( mirror::DexCache* dex_cache, mirror::Class* referrer_class, ArtField* resolved_field, uint16_t field_idx) { DCHECK(!resolved_field->IsStatic()); - mirror::Class* fields_class = resolved_field->GetDeclaringClass(); + ObjPtr<mirror::Class> fields_class = resolved_field->GetDeclaringClass(); bool fast_get = referrer_class != nullptr && - referrer_class->CanAccessResolvedField(fields_class, resolved_field, - dex_cache, field_idx); + referrer_class->CanAccessResolvedField(fields_class.Decode(), + resolved_field, + dex_cache, + field_idx); bool fast_put = fast_get && (!resolved_field->IsFinal() || fields_class == referrer_class); return std::make_pair(fast_get, fast_put); } @@ -167,13 +144,13 @@ inline std::pair<bool, bool> CompilerDriver::IsClassOfStaticMemberAvailableToRef uint32_t* storage_index) { DCHECK(resolved_member->IsStatic()); if (LIKELY(referrer_class != nullptr)) { - mirror::Class* members_class = resolved_member->GetDeclaringClass(); + ObjPtr<mirror::Class> members_class = resolved_member->GetDeclaringClass(); if (members_class == referrer_class) { *storage_index = members_class->GetDexTypeIndex(); return std::make_pair(true, true); } if (CanAccessResolvedMember<ArtMember>( - referrer_class, members_class, resolved_member, dex_cache, member_idx)) { + referrer_class, members_class.Decode(), resolved_member, dex_cache, member_idx)) { // We have the resolved member, we must make it into a index for the referrer // in its static storage (which may fail if it doesn't have a slot for it) // TODO: for images we can elide the static storage base null check @@ -217,43 +194,6 @@ inline bool CompilerDriver::IsClassOfStaticMethodAvailableToReferrer( return result.first; } -inline bool CompilerDriver::IsStaticFieldInReferrerClass(mirror::Class* referrer_class, - ArtField* resolved_field) { - DCHECK(resolved_field->IsStatic()); - mirror::Class* fields_class = resolved_field->GetDeclaringClass(); - return referrer_class == fields_class; -} - -inline bool CompilerDriver::CanAssumeClassIsInitialized(mirror::Class* klass) { - // Being loaded is a pre-requisite for being initialized but let's do the cheap check first. - // - // NOTE: When AOT compiling an app, we eagerly initialize app classes (and potentially their - // super classes in the boot image) but only those that have a trivial initialization, i.e. - // without <clinit>() or static values in the dex file for that class or any of its super - // classes. So while we could see the klass as initialized during AOT compilation and have - // it only loaded at runtime, the needed initialization would have to be trivial and - // unobservable from Java, so we may as well treat it as initialized. - if (!klass->IsInitialized()) { - return false; - } - return CanAssumeClassIsLoaded(klass); -} - -inline bool CompilerDriver::CanReferrerAssumeClassIsInitialized(mirror::Class* referrer_class, - mirror::Class* klass) { - return (referrer_class != nullptr - && !referrer_class->IsInterface() - && referrer_class->IsSubClass(klass)) - || CanAssumeClassIsInitialized(klass); -} - -inline bool CompilerDriver::IsStaticFieldsClassInitialized(mirror::Class* referrer_class, - ArtField* resolved_field) { - DCHECK(resolved_field->IsStatic()); - mirror::Class* fields_class = resolved_field->GetDeclaringClass(); - return CanReferrerAssumeClassIsInitialized(referrer_class, fields_class); -} - inline ArtMethod* CompilerDriver::ResolveMethod( ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit, @@ -273,35 +213,6 @@ inline ArtMethod* CompilerDriver::ResolveMethod( return resolved_method; } -inline void CompilerDriver::GetResolvedMethodDexFileLocation( - ArtMethod* resolved_method, const DexFile** declaring_dex_file, - uint16_t* declaring_class_idx, uint16_t* declaring_method_idx) { - mirror::Class* declaring_class = resolved_method->GetDeclaringClass(); - *declaring_dex_file = declaring_class->GetDexCache()->GetDexFile(); - *declaring_class_idx = declaring_class->GetDexTypeIndex(); - *declaring_method_idx = resolved_method->GetDexMethodIndex(); -} - -inline uint16_t CompilerDriver::GetResolvedMethodVTableIndex( - ArtMethod* resolved_method, InvokeType type) { - if (type == kVirtual || type == kSuper) { - return resolved_method->GetMethodIndex(); - } else if (type == kInterface) { - return resolved_method->GetDexMethodIndex(); - } else { - return DexFile::kDexNoIndex16; - } -} - -inline bool CompilerDriver::IsMethodsClassInitialized(mirror::Class* referrer_class, - ArtMethod* resolved_method) { - if (!resolved_method->IsStatic()) { - return true; - } - mirror::Class* methods_class = resolved_method->GetDeclaringClass(); - return CanReferrerAssumeClassIsInitialized(referrer_class, methods_class); -} - } // namespace art #endif // ART_COMPILER_DRIVER_COMPILER_DRIVER_INL_H_ diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 2ec3f164e3..2ad30eeb95 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -95,8 +95,6 @@ class CompilerDriver::AOTCompilationStats { public: AOTCompilationStats() : stats_lock_("AOT compilation statistics lock"), - types_in_dex_cache_(0), types_not_in_dex_cache_(0), - strings_in_dex_cache_(0), strings_not_in_dex_cache_(0), resolved_types_(0), unresolved_types_(0), resolved_instance_fields_(0), unresolved_instance_fields_(0), resolved_local_static_fields_(0), resolved_static_fields_(0), unresolved_static_fields_(0), @@ -112,8 +110,6 @@ class CompilerDriver::AOTCompilationStats { } void Dump() { - DumpStat(types_in_dex_cache_, types_not_in_dex_cache_, "types known to be in dex cache"); - DumpStat(strings_in_dex_cache_, strings_not_in_dex_cache_, "strings known to be in dex cache"); DumpStat(resolved_types_, unresolved_types_, "types resolved"); DumpStat(resolved_instance_fields_, unresolved_instance_fields_, "instance fields resolved"); DumpStat(resolved_local_static_fields_ + resolved_static_fields_, unresolved_static_fields_, @@ -164,26 +160,6 @@ class CompilerDriver::AOTCompilationStats { #define STATS_LOCK() #endif - void TypeInDexCache() REQUIRES(!stats_lock_) { - STATS_LOCK(); - types_in_dex_cache_++; - } - - void TypeNotInDexCache() REQUIRES(!stats_lock_) { - STATS_LOCK(); - types_not_in_dex_cache_++; - } - - void StringInDexCache() REQUIRES(!stats_lock_) { - STATS_LOCK(); - strings_in_dex_cache_++; - } - - void StringNotInDexCache() REQUIRES(!stats_lock_) { - STATS_LOCK(); - strings_not_in_dex_cache_++; - } - void TypeDoesntNeedAccessCheck() REQUIRES(!stats_lock_) { STATS_LOCK(); resolved_types_++; @@ -225,67 +201,6 @@ class CompilerDriver::AOTCompilationStats { type_based_devirtualization_++; } - // Indicate that a method of the given type was resolved at compile time. - void ResolvedMethod(InvokeType type) REQUIRES(!stats_lock_) { - DCHECK_LE(type, kMaxInvokeType); - STATS_LOCK(); - resolved_methods_[type]++; - } - - // Indicate that a method of the given type was unresolved at compile time as it was in an - // unknown dex file. - void UnresolvedMethod(InvokeType type) REQUIRES(!stats_lock_) { - DCHECK_LE(type, kMaxInvokeType); - STATS_LOCK(); - unresolved_methods_[type]++; - } - - // Indicate that a type of virtual method dispatch has been converted into a direct method - // dispatch. - void VirtualMadeDirect(InvokeType type) REQUIRES(!stats_lock_) { - DCHECK(type == kVirtual || type == kInterface || type == kSuper); - STATS_LOCK(); - virtual_made_direct_[type]++; - } - - // Indicate that a method of the given type was able to call directly into boot. - void DirectCallsToBoot(InvokeType type) REQUIRES(!stats_lock_) { - DCHECK_LE(type, kMaxInvokeType); - STATS_LOCK(); - direct_calls_to_boot_[type]++; - } - - // Indicate that a method of the given type was able to be resolved directly from boot. - void DirectMethodsToBoot(InvokeType type) REQUIRES(!stats_lock_) { - DCHECK_LE(type, kMaxInvokeType); - STATS_LOCK(); - direct_methods_to_boot_[type]++; - } - - void ProcessedInvoke(InvokeType type, int flags) REQUIRES(!stats_lock_) { - STATS_LOCK(); - if (flags == 0) { - unresolved_methods_[type]++; - } else { - DCHECK_NE((flags & kFlagMethodResolved), 0); - resolved_methods_[type]++; - if ((flags & kFlagVirtualMadeDirect) != 0) { - virtual_made_direct_[type]++; - if ((flags & kFlagPreciseTypeDevirtualization) != 0) { - type_based_devirtualization_++; - } - } else { - DCHECK_EQ((flags & kFlagPreciseTypeDevirtualization), 0); - } - if ((flags & kFlagDirectCallToBoot) != 0) { - direct_calls_to_boot_[type]++; - } - if ((flags & kFlagDirectMethodToBoot) != 0) { - direct_methods_to_boot_[type]++; - } - } - } - // A check-cast could be eliminated due to verifier type analysis. void SafeCast() REQUIRES(!stats_lock_) { STATS_LOCK(); @@ -301,12 +216,6 @@ class CompilerDriver::AOTCompilationStats { private: Mutex stats_lock_; - size_t types_in_dex_cache_; - size_t types_not_in_dex_cache_; - - size_t strings_in_dex_cache_; - size_t strings_not_in_dex_cache_; - size_t resolved_types_; size_t unresolved_types_; @@ -849,9 +758,10 @@ void CompilerDriver::Resolve(jobject class_loader, // TODO: Collect the relevant string indices in parallel, then allocate them sequentially in a // stable order. -static void ResolveConstStrings(CompilerDriver* driver, +static void ResolveConstStrings(Handle<mirror::DexCache> dex_cache, const DexFile& dex_file, - const DexFile::CodeItem* code_item) { + const DexFile::CodeItem* code_item) + REQUIRES_SHARED(Locks::mutator_lock_) { if (code_item == nullptr) { // Abstract or native method. return; @@ -859,18 +769,19 @@ static void ResolveConstStrings(CompilerDriver* driver, const uint16_t* code_ptr = code_item->insns_; const uint16_t* code_end = code_item->insns_ + code_item->insns_size_in_code_units_; + ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); while (code_ptr < code_end) { const Instruction* inst = Instruction::At(code_ptr); switch (inst->Opcode()) { case Instruction::CONST_STRING: { uint32_t string_index = inst->VRegB_21c(); - driver->CanAssumeStringIsPresentInDexCache(dex_file, string_index); + class_linker->ResolveString(dex_file, string_index, dex_cache); break; } case Instruction::CONST_STRING_JUMBO: { uint32_t string_index = inst->VRegB_31c(); - driver->CanAssumeStringIsPresentInDexCache(dex_file, string_index); + class_linker->ResolveString(dex_file, string_index, dex_cache); break; } @@ -885,7 +796,13 @@ static void ResolveConstStrings(CompilerDriver* driver, static void ResolveConstStrings(CompilerDriver* driver, const std::vector<const DexFile*>& dex_files, TimingLogger* timings) { + ScopedObjectAccess soa(Thread::Current()); + StackHandleScope<1> hs(soa.Self()); + ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); + MutableHandle<mirror::DexCache> dex_cache(hs.NewHandle<mirror::DexCache>(nullptr)); + for (const DexFile* dex_file : dex_files) { + dex_cache.Assign(class_linker->FindDexCache(soa.Self(), *dex_file, false)); TimingLogger::ScopedTiming t("Resolve const-string Strings", timings); size_t class_def_count = dex_file->NumClassDefs(); @@ -926,7 +843,7 @@ static void ResolveConstStrings(CompilerDriver* driver, continue; } previous_direct_method_idx = method_idx; - ResolveConstStrings(driver, *dex_file, it.GetMethodCodeItem()); + ResolveConstStrings(dex_cache, *dex_file, it.GetMethodCodeItem()); it.Next(); } // Virtual methods. @@ -940,7 +857,7 @@ static void ResolveConstStrings(CompilerDriver* driver, continue; } previous_virtual_method_idx = method_idx; - ResolveConstStrings(driver, *dex_file, it.GetMethodCodeItem()); + ResolveConstStrings(dex_cache, *dex_file, it.GetMethodCodeItem()); it.Next(); } DCHECK(!it.HasNext()); @@ -1411,54 +1328,6 @@ void CompilerDriver::MarkForDexToDexCompilation(Thread* self, const MethodRefere dex_to_dex_references_.back().GetMethodIndexes().SetBit(method_ref.dex_method_index); } -bool CompilerDriver::CanAssumeTypeIsPresentInDexCache(Handle<mirror::DexCache> dex_cache, - uint32_t type_idx) { - bool result = false; - if ((IsBootImage() && - IsImageClass(dex_cache->GetDexFile()->StringDataByIdx( - dex_cache->GetDexFile()->GetTypeId(type_idx).descriptor_idx_))) || - Runtime::Current()->UseJitCompilation()) { - mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx); - result = (resolved_class != nullptr); - } - - if (result) { - stats_->TypeInDexCache(); - } else { - stats_->TypeNotInDexCache(); - } - return result; -} - -bool CompilerDriver::CanAssumeStringIsPresentInDexCache(const DexFile& dex_file, - uint32_t string_idx) { - // See also Compiler::ResolveDexFile - - bool result = false; - if (IsBootImage() || Runtime::Current()->UseJitCompilation()) { - ScopedObjectAccess soa(Thread::Current()); - StackHandleScope<1> hs(soa.Self()); - ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); - Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache( - soa.Self(), dex_file, false))); - if (IsBootImage()) { - // We resolve all const-string strings when building for the image. - class_linker->ResolveString(dex_file, string_idx, dex_cache); - result = true; - } else { - // Just check whether the dex cache already has the string. - DCHECK(Runtime::Current()->UseJitCompilation()); - result = (dex_cache->GetResolvedString(string_idx) != nullptr); - } - } - if (result) { - stats_->StringInDexCache(); - } else { - stats_->StringNotInDexCache(); - } - return result; -} - bool CompilerDriver::CanAccessTypeWithoutChecks(uint32_t referrer_idx, Handle<mirror::DexCache> dex_cache, uint32_t type_idx) { @@ -1522,108 +1391,6 @@ bool CompilerDriver::CanAccessInstantiableTypeWithoutChecks(uint32_t referrer_id return result; } -bool CompilerDriver::CanEmbedTypeInCode(const DexFile& dex_file, uint32_t type_idx, - bool* is_type_initialized, bool* use_direct_type_ptr, - uintptr_t* direct_type_ptr, bool* out_is_finalizable) { - ScopedObjectAccess soa(Thread::Current()); - Runtime* runtime = Runtime::Current(); - mirror::DexCache* dex_cache = runtime->GetClassLinker()->FindDexCache( - soa.Self(), dex_file, false); - mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx); - if (resolved_class == nullptr) { - return false; - } - if (GetCompilerOptions().GetCompilePic()) { - // Do not allow a direct class pointer to be used when compiling for position-independent - return false; - } - *out_is_finalizable = resolved_class->IsFinalizable(); - gc::Heap* heap = runtime->GetHeap(); - const bool compiling_boot = heap->IsCompilingBoot(); - const bool support_boot_image_fixup = GetSupportBootImageFixup(); - if (compiling_boot) { - // boot -> boot class pointers. - // True if the class is in the image at boot compiling time. - const bool is_image_class = IsBootImage() && IsImageClass( - dex_file.StringDataByIdx(dex_file.GetTypeId(type_idx).descriptor_idx_)); - // True if pc relative load works. - if (is_image_class && support_boot_image_fixup) { - *is_type_initialized = resolved_class->IsInitialized(); - *use_direct_type_ptr = false; - *direct_type_ptr = 0; - return true; - } else { - return false; - } - } else if (runtime->UseJitCompilation() && !heap->IsMovableObject(resolved_class)) { - *is_type_initialized = resolved_class->IsInitialized(); - // If the class may move around, then don't embed it as a direct pointer. - *use_direct_type_ptr = true; - *direct_type_ptr = reinterpret_cast<uintptr_t>(resolved_class); - return true; - } else { - // True if the class is in the image at app compiling time. - const bool class_in_image = heap->FindSpaceFromObject(resolved_class, false)->IsImageSpace(); - if (class_in_image && support_boot_image_fixup) { - // boot -> app class pointers. - *is_type_initialized = resolved_class->IsInitialized(); - // TODO This is somewhat hacky. We should refactor all of this invoke codepath. - *use_direct_type_ptr = !GetCompilerOptions().GetIncludePatchInformation(); - *direct_type_ptr = reinterpret_cast<uintptr_t>(resolved_class); - return true; - } else { - // app -> app class pointers. - // Give up because app does not have an image and class - // isn't created at compile time. TODO: implement this - // if/when each app gets an image. - return false; - } - } -} - -bool CompilerDriver::CanEmbedReferenceTypeInCode(ClassReference* ref, - bool* use_direct_ptr, - uintptr_t* direct_type_ptr) { - CHECK(ref != nullptr); - CHECK(use_direct_ptr != nullptr); - CHECK(direct_type_ptr != nullptr); - - ScopedObjectAccess soa(Thread::Current()); - mirror::Class* reference_class = mirror::Reference::GetJavaLangRefReference(); - bool is_initialized = false; - bool unused_finalizable; - // Make sure we have a finished Reference class object before attempting to use it. - if (!CanEmbedTypeInCode(*reference_class->GetDexCache()->GetDexFile(), - reference_class->GetDexTypeIndex(), &is_initialized, - use_direct_ptr, direct_type_ptr, &unused_finalizable) || - !is_initialized) { - return false; - } - ref->first = &reference_class->GetDexFile(); - ref->second = reference_class->GetDexClassDefIndex(); - return true; -} - -uint32_t CompilerDriver::GetReferenceSlowFlagOffset() const { - ScopedObjectAccess soa(Thread::Current()); - mirror::Class* klass = mirror::Reference::GetJavaLangRefReference(); - DCHECK(klass->IsInitialized()); - return klass->GetSlowPathFlagOffset().Uint32Value(); -} - -uint32_t CompilerDriver::GetReferenceDisableFlagOffset() const { - ScopedObjectAccess soa(Thread::Current()); - mirror::Class* klass = mirror::Reference::GetJavaLangRefReference(); - DCHECK(klass->IsInitialized()); - return klass->GetDisableIntrinsicFlagOffset().Uint32Value(); -} - -DexCacheArraysLayout CompilerDriver::GetDexCacheArraysLayout(const DexFile* dex_file) { - return ContainsElement(GetDexFilesForOatFile(), dex_file) - ? DexCacheArraysLayout(GetInstructionSetPointerSize(instruction_set_), dex_file) - : DexCacheArraysLayout(); -} - void CompilerDriver::ProcessedInstanceField(bool resolved) { if (!resolved) { stats_->UnresolvedInstanceField(); @@ -1642,10 +1409,6 @@ void CompilerDriver::ProcessedStaticField(bool resolved, bool local) { } } -void CompilerDriver::ProcessedInvoke(InvokeType invoke_type, int flags) { - stats_->ProcessedInvoke(invoke_type, flags); -} - ArtField* CompilerDriver::ComputeInstanceFieldInfo(uint32_t field_idx, const DexCompilationUnit* mUnit, bool is_put, const ScopedObjectAccess& soa) { diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index 52a04cc46b..fc63df1925 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -189,15 +189,6 @@ class CompilerDriver { uint16_t class_def_index) REQUIRES(!requires_constructor_barrier_lock_); - // Callbacks from compiler to see what runtime checks must be generated. - - bool CanAssumeTypeIsPresentInDexCache(Handle<mirror::DexCache> dex_cache, - uint32_t type_idx) - REQUIRES_SHARED(Locks::mutator_lock_); - - bool CanAssumeStringIsPresentInDexCache(const DexFile& dex_file, uint32_t string_idx) - REQUIRES(!Locks::mutator_lock_); - // Are runtime access checks necessary in the compiled code? bool CanAccessTypeWithoutChecks(uint32_t referrer_idx, Handle<mirror::DexCache> dex_cache, @@ -212,24 +203,6 @@ class CompilerDriver { bool* out_is_finalizable) REQUIRES_SHARED(Locks::mutator_lock_); - bool CanEmbedTypeInCode(const DexFile& dex_file, uint32_t type_idx, - bool* is_type_initialized, bool* use_direct_type_ptr, - uintptr_t* direct_type_ptr, bool* out_is_finalizable); - - // Query methods for the java.lang.ref.Reference class. - bool CanEmbedReferenceTypeInCode(ClassReference* ref, - bool* use_direct_type_ptr, uintptr_t* direct_type_ptr); - uint32_t GetReferenceSlowFlagOffset() const; - uint32_t GetReferenceDisableFlagOffset() const; - - // Get the DexCache for the - mirror::DexCache* GetDexCache(const DexCompilationUnit* mUnit) - REQUIRES_SHARED(Locks::mutator_lock_); - - mirror::ClassLoader* GetClassLoader(const ScopedObjectAccess& soa, - const DexCompilationUnit* mUnit) - REQUIRES_SHARED(Locks::mutator_lock_); - // Resolve compiling method's class. Returns null on failure. mirror::Class* ResolveCompilingMethodsClass( const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, @@ -257,19 +230,6 @@ class CompilerDriver { uint32_t field_idx, bool is_static) REQUIRES_SHARED(Locks::mutator_lock_); - // Get declaration location of a resolved field. - void GetResolvedFieldDexFileLocation( - ArtField* resolved_field, const DexFile** declaring_dex_file, - uint16_t* declaring_class_idx, uint16_t* declaring_field_idx) - REQUIRES_SHARED(Locks::mutator_lock_); - - bool IsFieldVolatile(ArtField* field) REQUIRES_SHARED(Locks::mutator_lock_); - MemberOffset GetFieldOffset(ArtField* field) REQUIRES_SHARED(Locks::mutator_lock_); - - // Find a dex cache for a dex file. - inline mirror::DexCache* FindDexCache(const DexFile* dex_file) - REQUIRES_SHARED(Locks::mutator_lock_); - // Can we fast-path an IGET/IPUT access to an instance field? If yes, compute the field offset. std::pair<bool, bool> IsFastInstanceField( mirror::DexCache* dex_cache, mirror::Class* referrer_class, @@ -295,15 +255,6 @@ class CompilerDriver { uint32_t* storage_index) REQUIRES_SHARED(Locks::mutator_lock_); - // Is static field's in referrer's class? - bool IsStaticFieldInReferrerClass(mirror::Class* referrer_class, ArtField* resolved_field) - REQUIRES_SHARED(Locks::mutator_lock_); - - // Is static field's class initialized? - bool IsStaticFieldsClassInitialized(mirror::Class* referrer_class, - ArtField* resolved_field) - REQUIRES_SHARED(Locks::mutator_lock_); - // Resolve a method. Returns null on failure, including incompatible class change. ArtMethod* ResolveMethod( ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, @@ -311,37 +262,8 @@ class CompilerDriver { uint32_t method_idx, InvokeType invoke_type, bool check_incompatible_class_change = true) REQUIRES_SHARED(Locks::mutator_lock_); - // Get declaration location of a resolved field. - void GetResolvedMethodDexFileLocation( - ArtMethod* resolved_method, const DexFile** declaring_dex_file, - uint16_t* declaring_class_idx, uint16_t* declaring_method_idx) - REQUIRES_SHARED(Locks::mutator_lock_); - - // Get the index in the vtable of the method. - uint16_t GetResolvedMethodVTableIndex( - ArtMethod* resolved_method, InvokeType type) - REQUIRES_SHARED(Locks::mutator_lock_); - - // Is method's class initialized for an invoke? - // For static invokes to determine whether we need to consider potential call to <clinit>(). - // For non-static invokes, assuming a non-null reference, the class is always initialized. - bool IsMethodsClassInitialized(mirror::Class* referrer_class, ArtMethod* resolved_method) - REQUIRES_SHARED(Locks::mutator_lock_); - - // Get the layout of dex cache arrays for a dex file. Returns invalid layout if the - // dex cache arrays don't have a fixed layout. - DexCacheArraysLayout GetDexCacheArraysLayout(const DexFile* dex_file); - void ProcessedInstanceField(bool resolved); void ProcessedStaticField(bool resolved, bool local); - void ProcessedInvoke(InvokeType invoke_type, int flags); - - void ComputeFieldInfo(uint32_t field_idx, const DexCompilationUnit* mUnit, - const ScopedObjectAccess& soa, bool is_static, - ArtField** resolved_field, - mirror::Class** referrer_class, - mirror::DexCache** dex_cache) - REQUIRES_SHARED(Locks::mutator_lock_); // Can we fast path instance field access? Computes field's offset and volatility. bool ComputeInstanceFieldInfo(uint32_t field_idx, const DexCompilationUnit* mUnit, bool is_put, @@ -393,6 +315,7 @@ class CompilerDriver { void SetDedupeEnabled(bool dedupe_enabled) { compiled_method_storage_.SetDedupeEnabled(dedupe_enabled); } + bool DedupeEnabled() const { return compiled_method_storage_.DedupeEnabled(); } @@ -456,6 +379,13 @@ class CompilerDriver { return current_dex_to_dex_methods_; } + // Compute constant code and method pointers when possible. + void GetCodeAndMethodForDirectCall(const mirror::Class* referrer_class, + ArtMethod* method, + /* out */ uintptr_t* direct_code, + /* out */ uintptr_t* direct_method) + REQUIRES_SHARED(Locks::mutator_lock_); + private: // Return whether the declaring class of `resolved_member` is // available to `referrer_class` for read or write access using two @@ -484,38 +414,9 @@ class CompilerDriver { uint32_t field_idx) REQUIRES_SHARED(Locks::mutator_lock_); - // Can we assume that the klass is initialized? - bool CanAssumeClassIsInitialized(mirror::Class* klass) - REQUIRES_SHARED(Locks::mutator_lock_); - bool CanReferrerAssumeClassIsInitialized(mirror::Class* referrer_class, mirror::Class* klass) - REQUIRES_SHARED(Locks::mutator_lock_); - - // These flags are internal to CompilerDriver for collecting INVOKE resolution statistics. - // The only external contract is that unresolved method has flags 0 and resolved non-0. - enum { - kBitMethodResolved = 0, - kBitVirtualMadeDirect, - kBitPreciseTypeDevirtualization, - kBitDirectCallToBoot, - kBitDirectMethodToBoot - }; - static constexpr int kFlagMethodResolved = 1 << kBitMethodResolved; - static constexpr int kFlagVirtualMadeDirect = 1 << kBitVirtualMadeDirect; - static constexpr int kFlagPreciseTypeDevirtualization = 1 << kBitPreciseTypeDevirtualization; - static constexpr int kFlagDirectCallToBoot = 1 << kBitDirectCallToBoot; - static constexpr int kFlagDirectMethodToBoot = 1 << kBitDirectMethodToBoot; - static constexpr int kFlagsMethodResolvedVirtualMadeDirect = - kFlagMethodResolved | kFlagVirtualMadeDirect; - static constexpr int kFlagsMethodResolvedPreciseTypeDevirtualization = - kFlagsMethodResolvedVirtualMadeDirect | kFlagPreciseTypeDevirtualization; - - public: // TODO make private or eliminate. - // Compute constant code and method pointers when possible. - void GetCodeAndMethodForDirectCall(const mirror::Class* referrer_class, - ArtMethod* method, - /* out */ uintptr_t* direct_code, - /* out */ uintptr_t* direct_method) - REQUIRES_SHARED(Locks::mutator_lock_); + mirror::ClassLoader* GetClassLoader(const ScopedObjectAccess& soa, + const DexCompilationUnit* mUnit) + REQUIRES_SHARED(Locks::mutator_lock_); private: void PreCompile(jobject class_loader, @@ -573,8 +474,6 @@ class CompilerDriver { REQUIRES(!Locks::mutator_lock_, !compiled_classes_lock_); void UpdateImageClasses(TimingLogger* timings) REQUIRES(!Locks::mutator_lock_); - static void FindClinitImageClassesCallback(mirror::Object* object, void* arg) - REQUIRES_SHARED(Locks::mutator_lock_); void Compile(jobject class_loader, const std::vector<const DexFile*>& dex_files, diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc index 41bda60a60..210943c88b 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -908,7 +908,7 @@ void ImageWriter::PruneNonImageClasses() { ArtField** resolved_fields = dex_cache->GetResolvedFields(); for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) { ArtField* field = mirror::DexCache::GetElementPtrSize(resolved_fields, i, target_ptr_size_); - if (field != nullptr && !KeepClass(field->GetDeclaringClass())) { + if (field != nullptr && !KeepClass(field->GetDeclaringClass().Decode())) { dex_cache->SetResolvedField(i, nullptr, target_ptr_size_); } } @@ -1742,7 +1742,7 @@ void ImageWriter::CopyAndFixupNativeData(size_t oat_index) { case kNativeObjectRelocationTypeArtField: { memcpy(dest, pair.first, sizeof(ArtField)); reinterpret_cast<ArtField*>(dest)->SetDeclaringClass( - GetImageAddress(reinterpret_cast<ArtField*>(pair.first)->GetDeclaringClass())); + GetImageAddress(reinterpret_cast<ArtField*>(pair.first)->GetDeclaringClass().Decode())); break; } case kNativeObjectRelocationTypeRuntimeMethod: diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc index 5a47df1a0d..15cebfe71b 100644 --- a/compiler/optimizing/reference_type_propagation.cc +++ b/compiler/optimizing/reference_type_propagation.cc @@ -84,7 +84,7 @@ class ReferenceTypePropagation::RTPVisitor : public HGraphDelegateVisitor { void VisitNewArray(HNewArray* instr) OVERRIDE; void VisitParameterValue(HParameterValue* instr) OVERRIDE; void UpdateFieldAccessTypeInfo(HInstruction* instr, const FieldInfo& info); - void SetClassAsTypeInfo(HInstruction* instr, mirror::Class* klass, bool is_exact) + void SetClassAsTypeInfo(HInstruction* instr, ObjPtr<mirror::Class> klass, bool is_exact) REQUIRES_SHARED(Locks::mutator_lock_); void VisitInstanceFieldGet(HInstanceFieldGet* instr) OVERRIDE; void VisitStaticFieldGet(HStaticFieldGet* instr) OVERRIDE; @@ -427,7 +427,7 @@ void ReferenceTypePropagation::BoundTypeForIfInstanceOf(HBasicBlock* block) { } void ReferenceTypePropagation::RTPVisitor::SetClassAsTypeInfo(HInstruction* instr, - mirror::Class* klass, + ObjPtr<mirror::Class> klass, bool is_exact) { if (instr->IsInvokeStaticOrDirect() && instr->AsInvokeStaticOrDirect()->IsStringInit()) { // Calls to String.<init> are replaced with a StringFactory. @@ -454,7 +454,7 @@ void ReferenceTypePropagation::RTPVisitor::SetClassAsTypeInfo(HInstruction* inst } instr->SetReferenceTypeInfo( ReferenceTypeInfo::Create(handle_cache_->GetStringClassHandle(), /* is_exact */ true)); - } else if (IsAdmissible(klass)) { + } else if (IsAdmissible(klass.Decode())) { ReferenceTypeInfo::TypeHandle handle = handle_cache_->NewHandle(klass); is_exact = is_exact || handle->CannotBeAssignedFromOtherTypes(); instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(handle, is_exact)); @@ -512,7 +512,7 @@ void ReferenceTypePropagation::RTPVisitor::UpdateFieldAccessTypeInfo(HInstructio } ScopedObjectAccess soa(Thread::Current()); - mirror::Class* klass = nullptr; + ObjPtr<mirror::Class> klass; // The field index is unknown only during tests. if (info.GetFieldIndex() != kUnknownFieldIndex) { diff --git a/compiler/optimizing/reference_type_propagation.h b/compiler/optimizing/reference_type_propagation.h index 1fa6624902..61428b2a45 100644 --- a/compiler/optimizing/reference_type_propagation.h +++ b/compiler/optimizing/reference_type_propagation.h @@ -21,6 +21,7 @@ #include "driver/dex_compilation_unit.h" #include "handle_scope-inl.h" #include "nodes.h" +#include "obj_ptr.h" #include "optimization.h" #include "optimizing_compiler_stats.h" @@ -62,6 +63,11 @@ class ReferenceTypePropagation : public HOptimization { return handles_->NewHandle(object); } + template <typename T> + MutableHandle<T> NewHandle(ObjPtr<T> object) REQUIRES_SHARED(Locks::mutator_lock_) { + return handles_->NewHandle(object); + } + ReferenceTypeInfo::TypeHandle GetObjectClassHandle(); ReferenceTypeInfo::TypeHandle GetClassClassHandle(); ReferenceTypeInfo::TypeHandle GetStringClassHandle(); diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index be5224beb5..4d0dc5696e 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -1687,7 +1687,9 @@ class ImageDumper { ImageDumper* const image_dumper_; }; - static void PrettyObjectValue(std::ostream& os, mirror::Class* type, mirror::Object* value) + static void PrettyObjectValue(std::ostream& os, + ObjPtr<mirror::Class> type, + ObjPtr<mirror::Object> value) REQUIRES_SHARED(Locks::mutator_lock_) { CHECK(type != nullptr); if (value == nullptr) { @@ -1700,11 +1702,11 @@ class ImageDumper { mirror::Class* klass = value->AsClass(); os << StringPrintf("%p Class: %s\n", klass, PrettyDescriptor(klass).c_str()); } else { - os << StringPrintf("%p %s\n", value, PrettyDescriptor(type).c_str()); + os << StringPrintf("%p %s\n", value.Decode(), PrettyDescriptor(type).c_str()); } } - static void PrintField(std::ostream& os, ArtField* field, mirror::Object* obj) + static void PrintField(std::ostream& os, ArtField* field, ObjPtr<mirror::Object> obj) REQUIRES_SHARED(Locks::mutator_lock_) { os << StringPrintf("%s: ", field->GetName()); switch (field->GetTypeAsPrimitiveType()) { @@ -1736,16 +1738,17 @@ class ImageDumper { case Primitive::kPrimNot: { // Get the value, don't compute the type unless it is non-null as we don't want // to cause class loading. - mirror::Object* value = field->GetObj(obj); + ObjPtr<mirror::Object> value = field->GetObj(obj); if (value == nullptr) { os << StringPrintf("null %s\n", PrettyDescriptor(field->GetTypeDescriptor()).c_str()); } else { // Grab the field type without causing resolution. - mirror::Class* field_type = field->GetType<false>(); + ObjPtr<mirror::Class> field_type = field->GetType<false>(); if (field_type != nullptr) { PrettyObjectValue(os, field_type, value); } else { - os << StringPrintf("%p %s\n", value, + os << StringPrintf("%p %s\n", + value.Decode(), PrettyDescriptor(field->GetTypeDescriptor()).c_str()); } } diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc index d58f38cc06..b259f64d1e 100644 --- a/patchoat/patchoat.cc +++ b/patchoat/patchoat.cc @@ -504,7 +504,8 @@ class PatchOatArtFieldVisitor : public ArtFieldVisitor { void Visit(ArtField* field) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { ArtField* const dest = patch_oat_->RelocatedCopyOf(field); - dest->SetDeclaringClass(patch_oat_->RelocatedAddressOfPointer(field->GetDeclaringClass())); + dest->SetDeclaringClass( + patch_oat_->RelocatedAddressOfPointer(field->GetDeclaringClass().Decode())); } private: diff --git a/runtime/arch/stub_test.cc b/runtime/arch/stub_test.cc index 5e39f42814..432ba36587 100644 --- a/runtime/arch/stub_test.cc +++ b/runtime/arch/stub_test.cc @@ -1688,7 +1688,7 @@ static void set_and_check_instance(ArtField* f, mirror::Object* trg, EXPECT_EQ(res, reinterpret_cast<size_t>(val)) << "Value " << val; - EXPECT_EQ(val, f->GetObj(trg)); + EXPECT_OBJ_PTR_EQ(val, f->GetObj(trg)); } #endif diff --git a/runtime/art_field-inl.h b/runtime/art_field-inl.h index ca96169971..a52c714687 100644 --- a/runtime/art_field-inl.h +++ b/runtime/art_field-inl.h @@ -34,15 +34,15 @@ namespace art { template<ReadBarrierOption kReadBarrierOption> -inline mirror::Class* ArtField::GetDeclaringClass() { +inline ObjPtr<mirror::Class> ArtField::GetDeclaringClass() { GcRootSource gc_root_source(this); - mirror::Class* result = declaring_class_.Read<kReadBarrierOption>(&gc_root_source); + ObjPtr<mirror::Class> result = declaring_class_.Read<kReadBarrierOption>(&gc_root_source); DCHECK(result != nullptr); DCHECK(result->IsLoaded() || result->IsErroneous()) << result->GetStatus(); return result; } -inline void ArtField::SetDeclaringClass(mirror::Class* new_declaring_class) { +inline void ArtField::SetDeclaringClass(ObjPtr<mirror::Class> new_declaring_class) { declaring_class_ = GcRoot<mirror::Class>(new_declaring_class); } @@ -61,7 +61,7 @@ inline MemberOffset ArtField::GetOffsetDuringLinking() { return MemberOffset(offset_); } -inline uint32_t ArtField::Get32(mirror::Object* object) { +inline uint32_t ArtField::Get32(ObjPtr<mirror::Object> object) { DCHECK(object != nullptr) << PrettyField(this); DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); if (UNLIKELY(IsVolatile())) { @@ -71,7 +71,7 @@ inline uint32_t ArtField::Get32(mirror::Object* object) { } template<bool kTransactionActive> -inline void ArtField::Set32(mirror::Object* object, uint32_t new_value) { +inline void ArtField::Set32(ObjPtr<mirror::Object> object, uint32_t new_value) { DCHECK(object != nullptr) << PrettyField(this); DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); if (UNLIKELY(IsVolatile())) { @@ -81,7 +81,7 @@ inline void ArtField::Set32(mirror::Object* object, uint32_t new_value) { } } -inline uint64_t ArtField::Get64(mirror::Object* object) { +inline uint64_t ArtField::Get64(ObjPtr<mirror::Object> object) { DCHECK(object != nullptr) << PrettyField(this); DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); if (UNLIKELY(IsVolatile())) { @@ -91,7 +91,7 @@ inline uint64_t ArtField::Get64(mirror::Object* object) { } template<bool kTransactionActive> -inline void ArtField::Set64(mirror::Object* object, uint64_t new_value) { +inline void ArtField::Set64(ObjPtr<mirror::Object> object, uint64_t new_value) { DCHECK(object != nullptr) << PrettyField(this); DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); if (UNLIKELY(IsVolatile())) { @@ -101,23 +101,24 @@ inline void ArtField::Set64(mirror::Object* object, uint64_t new_value) { } } -inline mirror::Object* ArtField::GetObj(mirror::Object* object) { +template<class MirrorType> +inline ObjPtr<MirrorType> ArtField::GetObj(ObjPtr<mirror::Object> object) { DCHECK(object != nullptr) << PrettyField(this); DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); if (UNLIKELY(IsVolatile())) { - return object->GetFieldObjectVolatile<mirror::Object>(GetOffset()); + return object->GetFieldObjectVolatile<MirrorType>(GetOffset()); } - return object->GetFieldObject<mirror::Object>(GetOffset()); + return object->GetFieldObject<MirrorType>(GetOffset()); } template<bool kTransactionActive> -inline void ArtField::SetObj(mirror::Object* object, mirror::Object* new_value) { +inline void ArtField::SetObj(ObjPtr<mirror::Object> object, ObjPtr<mirror::Object> new_value) { DCHECK(object != nullptr) << PrettyField(this); DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); if (UNLIKELY(IsVolatile())) { - object->SetFieldObjectVolatile<kTransactionActive>(GetOffset(), new_value); + object->SetFieldObjectVolatile<kTransactionActive>(GetOffset(), new_value.Decode()); } else { - object->SetFieldObject<kTransactionActive>(GetOffset(), new_value); + object->SetFieldObject<kTransactionActive>(GetOffset(), new_value.Decode()); } } @@ -140,46 +141,46 @@ inline void ArtField::SetObj(mirror::Object* object, mirror::Object* new_value) (object)->SetField ## type<kTransactionActive>(GetOffset(), value); \ } -inline uint8_t ArtField::GetBoolean(mirror::Object* object) { +inline uint8_t ArtField::GetBoolean(ObjPtr<mirror::Object> object) { FIELD_GET(object, Boolean); } template<bool kTransactionActive> -inline void ArtField::SetBoolean(mirror::Object* object, uint8_t z) { +inline void ArtField::SetBoolean(ObjPtr<mirror::Object> object, uint8_t z) { FIELD_SET(object, Boolean, z); } -inline int8_t ArtField::GetByte(mirror::Object* object) { +inline int8_t ArtField::GetByte(ObjPtr<mirror::Object> object) { FIELD_GET(object, Byte); } template<bool kTransactionActive> -inline void ArtField::SetByte(mirror::Object* object, int8_t b) { +inline void ArtField::SetByte(ObjPtr<mirror::Object> object, int8_t b) { FIELD_SET(object, Byte, b); } -inline uint16_t ArtField::GetChar(mirror::Object* object) { +inline uint16_t ArtField::GetChar(ObjPtr<mirror::Object> object) { FIELD_GET(object, Char); } template<bool kTransactionActive> -inline void ArtField::SetChar(mirror::Object* object, uint16_t c) { +inline void ArtField::SetChar(ObjPtr<mirror::Object> object, uint16_t c) { FIELD_SET(object, Char, c); } -inline int16_t ArtField::GetShort(mirror::Object* object) { +inline int16_t ArtField::GetShort(ObjPtr<mirror::Object> object) { FIELD_GET(object, Short); } template<bool kTransactionActive> -inline void ArtField::SetShort(mirror::Object* object, int16_t s) { +inline void ArtField::SetShort(ObjPtr<mirror::Object> object, int16_t s) { FIELD_SET(object, Short, s); } #undef FIELD_GET #undef FIELD_SET -inline int32_t ArtField::GetInt(mirror::Object* object) { +inline int32_t ArtField::GetInt(ObjPtr<mirror::Object> object) { if (kIsDebugBuild) { Primitive::Type type = GetTypeAsPrimitiveType(); CHECK(type == Primitive::kPrimInt || type == Primitive::kPrimFloat) << PrettyField(this); @@ -188,7 +189,7 @@ inline int32_t ArtField::GetInt(mirror::Object* object) { } template<bool kTransactionActive> -inline void ArtField::SetInt(mirror::Object* object, int32_t i) { +inline void ArtField::SetInt(ObjPtr<mirror::Object> object, int32_t i) { if (kIsDebugBuild) { Primitive::Type type = GetTypeAsPrimitiveType(); CHECK(type == Primitive::kPrimInt || type == Primitive::kPrimFloat) << PrettyField(this); @@ -196,7 +197,7 @@ inline void ArtField::SetInt(mirror::Object* object, int32_t i) { Set32<kTransactionActive>(object, i); } -inline int64_t ArtField::GetLong(mirror::Object* object) { +inline int64_t ArtField::GetLong(ObjPtr<mirror::Object> object) { if (kIsDebugBuild) { Primitive::Type type = GetTypeAsPrimitiveType(); CHECK(type == Primitive::kPrimLong || type == Primitive::kPrimDouble) << PrettyField(this); @@ -205,7 +206,7 @@ inline int64_t ArtField::GetLong(mirror::Object* object) { } template<bool kTransactionActive> -inline void ArtField::SetLong(mirror::Object* object, int64_t j) { +inline void ArtField::SetLong(ObjPtr<mirror::Object> object, int64_t j) { if (kIsDebugBuild) { Primitive::Type type = GetTypeAsPrimitiveType(); CHECK(type == Primitive::kPrimLong || type == Primitive::kPrimDouble) << PrettyField(this); @@ -213,7 +214,7 @@ inline void ArtField::SetLong(mirror::Object* object, int64_t j) { Set64<kTransactionActive>(object, j); } -inline float ArtField::GetFloat(mirror::Object* object) { +inline float ArtField::GetFloat(ObjPtr<mirror::Object> object) { DCHECK_EQ(Primitive::kPrimFloat, GetTypeAsPrimitiveType()) << PrettyField(this); JValue bits; bits.SetI(Get32(object)); @@ -221,14 +222,14 @@ inline float ArtField::GetFloat(mirror::Object* object) { } template<bool kTransactionActive> -inline void ArtField::SetFloat(mirror::Object* object, float f) { +inline void ArtField::SetFloat(ObjPtr<mirror::Object> object, float f) { DCHECK_EQ(Primitive::kPrimFloat, GetTypeAsPrimitiveType()) << PrettyField(this); JValue bits; bits.SetF(f); Set32<kTransactionActive>(object, bits.GetI()); } -inline double ArtField::GetDouble(mirror::Object* object) { +inline double ArtField::GetDouble(ObjPtr<mirror::Object> object) { DCHECK_EQ(Primitive::kPrimDouble, GetTypeAsPrimitiveType()) << PrettyField(this); JValue bits; bits.SetJ(Get64(object)); @@ -236,20 +237,20 @@ inline double ArtField::GetDouble(mirror::Object* object) { } template<bool kTransactionActive> -inline void ArtField::SetDouble(mirror::Object* object, double d) { +inline void ArtField::SetDouble(ObjPtr<mirror::Object> object, double d) { DCHECK_EQ(Primitive::kPrimDouble, GetTypeAsPrimitiveType()) << PrettyField(this); JValue bits; bits.SetD(d); Set64<kTransactionActive>(object, bits.GetJ()); } -inline mirror::Object* ArtField::GetObject(mirror::Object* object) { +inline ObjPtr<mirror::Object> ArtField::GetObject(ObjPtr<mirror::Object> object) { DCHECK_EQ(Primitive::kPrimNot, GetTypeAsPrimitiveType()) << PrettyField(this); return GetObj(object); } template<bool kTransactionActive> -inline void ArtField::SetObject(mirror::Object* object, mirror::Object* l) { +inline void ArtField::SetObject(ObjPtr<mirror::Object> object, ObjPtr<mirror::Object> l) { DCHECK_EQ(Primitive::kPrimNot, GetTypeAsPrimitiveType()) << PrettyField(this); SetObj<kTransactionActive>(object, l); } @@ -288,16 +289,16 @@ inline bool ArtField::IsPrimitiveType() REQUIRES_SHARED(Locks::mutator_lock_) { } template <bool kResolve> -inline mirror::Class* ArtField::GetType() { +inline ObjPtr<mirror::Class> ArtField::GetType() { const uint32_t field_index = GetDexFieldIndex(); - auto* declaring_class = GetDeclaringClass(); + ObjPtr<mirror::Class> declaring_class = GetDeclaringClass(); if (UNLIKELY(declaring_class->IsProxyClass())) { return ProxyFindSystemClass(GetTypeDescriptor()); } auto* dex_cache = declaring_class->GetDexCache(); const DexFile* const dex_file = dex_cache->GetDexFile(); const DexFile::FieldId& field_id = dex_file->GetFieldId(field_index); - mirror::Class* type = dex_cache->GetResolvedType(field_id.type_idx_); + ObjPtr<mirror::Class> type = dex_cache->GetResolvedType(field_id.type_idx_); if (kResolve && UNLIKELY(type == nullptr)) { type = ResolveGetType(field_id.type_idx_); CHECK(type != nullptr || Thread::Current()->IsExceptionPending()); @@ -309,7 +310,7 @@ inline size_t ArtField::FieldSize() REQUIRES_SHARED(Locks::mutator_lock_) { return Primitive::ComponentSize(GetTypeAsPrimitiveType()); } -inline mirror::DexCache* ArtField::GetDexCache() REQUIRES_SHARED(Locks::mutator_lock_) { +inline ObjPtr<mirror::DexCache> ArtField::GetDexCache() REQUIRES_SHARED(Locks::mutator_lock_) { return GetDeclaringClass()->GetDexCache(); } @@ -317,13 +318,13 @@ inline const DexFile* ArtField::GetDexFile() REQUIRES_SHARED(Locks::mutator_lock return GetDexCache()->GetDexFile(); } -inline mirror::String* ArtField::GetStringName(Thread* self, bool resolve) { +inline ObjPtr<mirror::String> ArtField::GetStringName(Thread* self, bool resolve) { auto dex_field_index = GetDexFieldIndex(); CHECK_NE(dex_field_index, DexFile::kDexNoIndex); - auto* dex_cache = GetDexCache(); + ObjPtr<mirror::DexCache> dex_cache = GetDexCache(); const auto* dex_file = dex_cache->GetDexFile(); const auto& field_id = dex_file->GetFieldId(dex_field_index); - auto* name = dex_cache->GetResolvedString(field_id.name_idx_); + ObjPtr<mirror::String> name = dex_cache->GetResolvedString(field_id.name_idx_); if (resolve && name == nullptr) { name = ResolveGetStringName(self, *dex_file, field_id.name_idx_, dex_cache); } @@ -337,8 +338,8 @@ inline void ArtField::VisitRoots(RootVisitorType& visitor) { template <typename Visitor> inline void ArtField::UpdateObjects(const Visitor& visitor) { - mirror::Class* old_class = DeclaringClassRoot().Read<kWithoutReadBarrier>(); - mirror::Class* new_class = visitor(old_class); + ObjPtr<mirror::Class> old_class = DeclaringClassRoot().Read<kWithoutReadBarrier>(); + ObjPtr<mirror::Class> new_class = visitor(old_class.Decode()); if (old_class != new_class) { SetDeclaringClass(new_class); } @@ -369,7 +370,7 @@ static inline ArtField* FindFieldWithOffset( } template <bool kExactOffset> -inline ArtField* ArtField::FindInstanceFieldWithOffset(mirror::Class* klass, +inline ArtField* ArtField::FindInstanceFieldWithOffset(ObjPtr<mirror::Class> klass, uint32_t field_offset) { DCHECK(klass != nullptr); ArtField* field = FindFieldWithOffset<kExactOffset>(klass->GetIFields(), field_offset); @@ -382,7 +383,8 @@ inline ArtField* ArtField::FindInstanceFieldWithOffset(mirror::Class* klass, } template <bool kExactOffset> -inline ArtField* ArtField::FindStaticFieldWithOffset(mirror::Class* klass, uint32_t field_offset) { +inline ArtField* ArtField::FindStaticFieldWithOffset(ObjPtr<mirror::Class> klass, + uint32_t field_offset) { DCHECK(klass != nullptr); return FindFieldWithOffset<kExactOffset>(klass->GetSFields(), field_offset); } diff --git a/runtime/art_field.cc b/runtime/art_field.cc index 3b4db0bd1e..78c62d6f37 100644 --- a/runtime/art_field.cc +++ b/runtime/art_field.cc @@ -30,10 +30,6 @@ namespace art { -ArtField::ArtField() : access_flags_(0), field_dex_idx_(0), offset_(0) { - declaring_class_ = GcRoot<mirror::Class>(nullptr); -} - void ArtField::SetOffset(MemberOffset num_bytes) { DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous()); if (kIsDebugBuild && Runtime::Current()->IsAotCompiler() && @@ -47,20 +43,23 @@ void ArtField::SetOffset(MemberOffset num_bytes) { offset_ = num_bytes.Uint32Value(); } -mirror::Class* ArtField::ProxyFindSystemClass(const char* descriptor) { +ObjPtr<mirror::Class> ArtField::ProxyFindSystemClass(const char* descriptor) { DCHECK(GetDeclaringClass()->IsProxyClass()); return Runtime::Current()->GetClassLinker()->FindSystemClass(Thread::Current(), descriptor); } -mirror::Class* ArtField::ResolveGetType(uint32_t type_idx) { +ObjPtr<mirror::Class> ArtField::ResolveGetType(uint32_t type_idx) { return Runtime::Current()->GetClassLinker()->ResolveType(type_idx, this); } -mirror::String* ArtField::ResolveGetStringName(Thread* self, const DexFile& dex_file, - uint32_t string_idx, mirror::DexCache* dex_cache) { +ObjPtr<mirror::String> ArtField::ResolveGetStringName(Thread* self, + const DexFile& dex_file, + uint32_t string_idx, + ObjPtr<mirror::DexCache> dex_cache) { StackHandleScope<1> hs(self); - return Runtime::Current()->GetClassLinker()->ResolveString( - dex_file, string_idx, hs.NewHandle(dex_cache)); + return Runtime::Current()->GetClassLinker()->ResolveString(dex_file, + string_idx, + hs.NewHandle(dex_cache)); } } // namespace art diff --git a/runtime/art_field.h b/runtime/art_field.h index 16e6c758e8..8ba383c007 100644 --- a/runtime/art_field.h +++ b/runtime/art_field.h @@ -21,6 +21,7 @@ #include "gc_root.h" #include "modifiers.h" +#include "obj_ptr.h" #include "offsets.h" #include "primitive.h" #include "read_barrier_option.h" @@ -39,12 +40,10 @@ class String; class ArtField FINAL { public: - ArtField(); - template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier> - mirror::Class* GetDeclaringClass() REQUIRES_SHARED(Locks::mutator_lock_); + ObjPtr<mirror::Class> GetDeclaringClass() REQUIRES_SHARED(Locks::mutator_lock_); - void SetDeclaringClass(mirror::Class *new_declaring_class) + void SetDeclaringClass(ObjPtr<mirror::Class> new_declaring_class) REQUIRES_SHARED(Locks::mutator_lock_); uint32_t GetAccessFlags() REQUIRES_SHARED(Locks::mutator_lock_); @@ -87,68 +86,72 @@ class ArtField FINAL { void SetOffset(MemberOffset num_bytes) REQUIRES_SHARED(Locks::mutator_lock_); // field access, null object for static fields - uint8_t GetBoolean(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + uint8_t GetBoolean(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_); template<bool kTransactionActive> - void SetBoolean(mirror::Object* object, uint8_t z) REQUIRES_SHARED(Locks::mutator_lock_); + void SetBoolean(ObjPtr<mirror::Object> object, uint8_t z) REQUIRES_SHARED(Locks::mutator_lock_); - int8_t GetByte(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + int8_t GetByte(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_); template<bool kTransactionActive> - void SetByte(mirror::Object* object, int8_t b) REQUIRES_SHARED(Locks::mutator_lock_); + void SetByte(ObjPtr<mirror::Object> object, int8_t b) REQUIRES_SHARED(Locks::mutator_lock_); - uint16_t GetChar(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + uint16_t GetChar(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_); template<bool kTransactionActive> - void SetChar(mirror::Object* object, uint16_t c) REQUIRES_SHARED(Locks::mutator_lock_); + void SetChar(ObjPtr<mirror::Object> object, uint16_t c) REQUIRES_SHARED(Locks::mutator_lock_); - int16_t GetShort(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + int16_t GetShort(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_); template<bool kTransactionActive> - void SetShort(mirror::Object* object, int16_t s) REQUIRES_SHARED(Locks::mutator_lock_); + void SetShort(ObjPtr<mirror::Object> object, int16_t s) REQUIRES_SHARED(Locks::mutator_lock_); - int32_t GetInt(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + int32_t GetInt(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_); template<bool kTransactionActive> - void SetInt(mirror::Object* object, int32_t i) REQUIRES_SHARED(Locks::mutator_lock_); + void SetInt(ObjPtr<mirror::Object> object, int32_t i) REQUIRES_SHARED(Locks::mutator_lock_); - int64_t GetLong(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + int64_t GetLong(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_); template<bool kTransactionActive> - void SetLong(mirror::Object* object, int64_t j) REQUIRES_SHARED(Locks::mutator_lock_); + void SetLong(ObjPtr<mirror::Object> object, int64_t j) REQUIRES_SHARED(Locks::mutator_lock_); - float GetFloat(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + float GetFloat(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_); template<bool kTransactionActive> - void SetFloat(mirror::Object* object, float f) REQUIRES_SHARED(Locks::mutator_lock_); + void SetFloat(ObjPtr<mirror::Object> object, float f) REQUIRES_SHARED(Locks::mutator_lock_); - double GetDouble(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + double GetDouble(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_); template<bool kTransactionActive> - void SetDouble(mirror::Object* object, double d) REQUIRES_SHARED(Locks::mutator_lock_); + void SetDouble(ObjPtr<mirror::Object> object, double d) REQUIRES_SHARED(Locks::mutator_lock_); - mirror::Object* GetObject(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + ObjPtr<mirror::Object> GetObject(ObjPtr<mirror::Object> object) + REQUIRES_SHARED(Locks::mutator_lock_); template<bool kTransactionActive> - void SetObject(mirror::Object* object, mirror::Object* l) + void SetObject(ObjPtr<mirror::Object> object, ObjPtr<mirror::Object> l) REQUIRES_SHARED(Locks::mutator_lock_); // Raw field accesses. - uint32_t Get32(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + uint32_t Get32(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_); template<bool kTransactionActive> - void Set32(mirror::Object* object, uint32_t new_value) + void Set32(ObjPtr<mirror::Object> object, uint32_t new_value) REQUIRES_SHARED(Locks::mutator_lock_); - uint64_t Get64(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + uint64_t Get64(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_); template<bool kTransactionActive> - void Set64(mirror::Object* object, uint64_t new_value) REQUIRES_SHARED(Locks::mutator_lock_); + void Set64(ObjPtr<mirror::Object> object, uint64_t new_value) + REQUIRES_SHARED(Locks::mutator_lock_); - mirror::Object* GetObj(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + template<class MirrorType = mirror::Object> + ObjPtr<MirrorType> GetObj(ObjPtr<mirror::Object> object) + REQUIRES_SHARED(Locks::mutator_lock_); template<bool kTransactionActive> - void SetObj(mirror::Object* object, mirror::Object* new_value) + void SetObj(ObjPtr<mirror::Object> object, ObjPtr<mirror::Object> new_value) REQUIRES_SHARED(Locks::mutator_lock_); // NO_THREAD_SAFETY_ANALYSIS since we don't know what the callback requires. @@ -163,20 +166,20 @@ class ArtField FINAL { // If kExactOffset is true then we only find the matching offset, not the field containing the // offset. template <bool kExactOffset = true> - static ArtField* FindInstanceFieldWithOffset(mirror::Class* klass, uint32_t field_offset) + static ArtField* FindInstanceFieldWithOffset(ObjPtr<mirror::Class> klass, uint32_t field_offset) REQUIRES_SHARED(Locks::mutator_lock_); // Returns a static field with this offset in the given class or null if not found. // If kExactOffset is true then we only find the matching offset, not the field containing the // offset. template <bool kExactOffset = true> - static ArtField* FindStaticFieldWithOffset(mirror::Class* klass, uint32_t field_offset) + static ArtField* FindStaticFieldWithOffset(ObjPtr<mirror::Class> klass, uint32_t field_offset) REQUIRES_SHARED(Locks::mutator_lock_); const char* GetName() REQUIRES_SHARED(Locks::mutator_lock_); // Resolves / returns the name from the dex cache. - mirror::String* GetStringName(Thread* self, bool resolve) + ObjPtr<mirror::String> GetStringName(Thread* self, bool resolve) REQUIRES_SHARED(Locks::mutator_lock_); const char* GetTypeDescriptor() REQUIRES_SHARED(Locks::mutator_lock_); @@ -186,11 +189,11 @@ class ArtField FINAL { bool IsPrimitiveType() REQUIRES_SHARED(Locks::mutator_lock_); template <bool kResolve> - mirror::Class* GetType() REQUIRES_SHARED(Locks::mutator_lock_); + ObjPtr<mirror::Class> GetType() REQUIRES_SHARED(Locks::mutator_lock_); size_t FieldSize() REQUIRES_SHARED(Locks::mutator_lock_); - mirror::DexCache* GetDexCache() REQUIRES_SHARED(Locks::mutator_lock_); + ObjPtr<mirror::DexCache> GetDexCache() REQUIRES_SHARED(Locks::mutator_lock_); const DexFile* GetDexFile() REQUIRES_SHARED(Locks::mutator_lock_); @@ -204,22 +207,24 @@ class ArtField FINAL { REQUIRES_SHARED(Locks::mutator_lock_); private: - mirror::Class* ProxyFindSystemClass(const char* descriptor) + ObjPtr<mirror::Class> ProxyFindSystemClass(const char* descriptor) REQUIRES_SHARED(Locks::mutator_lock_); - mirror::Class* ResolveGetType(uint32_t type_idx) REQUIRES_SHARED(Locks::mutator_lock_); - mirror::String* ResolveGetStringName(Thread* self, const DexFile& dex_file, uint32_t string_idx, - mirror::DexCache* dex_cache) + ObjPtr<mirror::Class> ResolveGetType(uint32_t type_idx) REQUIRES_SHARED(Locks::mutator_lock_); + ObjPtr<mirror::String> ResolveGetStringName(Thread* self, + const DexFile& dex_file, + uint32_t string_idx, + ObjPtr<mirror::DexCache> dex_cache) REQUIRES_SHARED(Locks::mutator_lock_); GcRoot<mirror::Class> declaring_class_; - uint32_t access_flags_; + uint32_t access_flags_ = 0; // Dex cache index of field id - uint32_t field_dex_idx_; + uint32_t field_dex_idx_ = 0; // Offset of field within an instance or in the Class' static fields - uint32_t offset_; + uint32_t offset_ = 0; }; } // namespace art diff --git a/runtime/base/logging.cc b/runtime/base/logging.cc index 17873b541c..d09e66f3c4 100644 --- a/runtime/base/logging.cc +++ b/runtime/base/logging.cc @@ -27,7 +27,7 @@ // Headers for LogMessage::LogLine. #ifdef ART_TARGET_ANDROID -#include "cutils/log.h" +#include <android/log.h> #include <android/set_abort_message.h> #else #include <sys/types.h> diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc index 9f0770285a..c671b81dbd 100644 --- a/runtime/check_jni.cc +++ b/runtime/check_jni.cc @@ -274,7 +274,7 @@ class ScopedCheck { AbortF("field operation on NULL object: %p", java_object); return false; } - if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o.Decode())) { + if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) { Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR)); AbortF("field operation on invalid %s: %p", ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), @@ -334,7 +334,7 @@ class ScopedCheck { } if (invoke != kVirtual) { ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc); - if (!m->GetDeclaringClass()->IsAssignableFrom(c.Decode())) { + if (!m->GetDeclaringClass()->IsAssignableFrom(c)) { AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual", PrettyMethod(m).c_str(), PrettyClass(c).c_str()); return false; @@ -388,7 +388,7 @@ class ScopedCheck { return false; } ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class); - if (!m->GetDeclaringClass()->IsAssignableFrom(c.Decode())) { + if (!m->GetDeclaringClass()->IsAssignableFrom(c)) { AbortF("can't call static %s on class %s", PrettyMethod(m).c_str(), PrettyClass(c).c_str()); return false; } @@ -939,7 +939,7 @@ class ScopedCheck { ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc); if (c == nullptr) { *msg += "NULL"; - } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c.Decode())) { + } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c)) { StringAppendF(msg, "INVALID POINTER:%p", jc); } else if (!c->IsClass()) { *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + PrettyTypeOf(c); @@ -1108,7 +1108,7 @@ class ScopedCheck { } ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array); - if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a.Decode()))) { + if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a))) { Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR)); AbortF("jarray is an invalid %s: %p (%p)", ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(), diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h index 51e5aae3d0..378da57bba 100644 --- a/runtime/class_linker-inl.h +++ b/runtime/class_linker-inl.h @@ -63,6 +63,7 @@ inline mirror::Class* ClassLinker::FindArrayClass(Thread* self, mirror::Class** } inline mirror::String* ClassLinker::ResolveString(uint32_t string_idx, ArtMethod* referrer) { + Thread::PoisonObjectPointersIfDebug(); mirror::Class* declaring_class = referrer->GetDeclaringClass(); // MethodVerifier refuses methods with string_idx out of bounds. DCHECK_LT(string_idx, declaring_class->GetDexFile().NumStringIds());; @@ -70,7 +71,6 @@ inline mirror::String* ClassLinker::ResolveString(uint32_t string_idx, ArtMethod mirror::StringDexCachePair::Lookup(declaring_class->GetDexCacheStrings(), string_idx, mirror::DexCache::kDexCacheStringCacheSize).Read(); - Thread::PoisonObjectPointersIfDebug(); if (UNLIKELY(string == nullptr)) { StackHandleScope<1> hs(Thread::Current()); Handle<mirror::DexCache> dex_cache(hs.NewHandle(declaring_class->GetDexCache())); @@ -84,8 +84,8 @@ inline mirror::String* ClassLinker::ResolveString(uint32_t string_idx, ArtMethod } inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, ArtMethod* referrer) { - mirror::Class* resolved_type = referrer->GetDexCacheResolvedType(type_idx, image_pointer_size_); Thread::PoisonObjectPointersIfDebug(); + mirror::Class* resolved_type = referrer->GetDexCacheResolvedType(type_idx, image_pointer_size_); if (UNLIKELY(resolved_type == nullptr)) { mirror::Class* declaring_class = referrer->GetDeclaringClass(); StackHandleScope<2> hs(Thread::Current()); @@ -100,10 +100,10 @@ inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, ArtMethod* ref } inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, ArtField* referrer) { - mirror::Class* declaring_class = referrer->GetDeclaringClass(); + Thread::PoisonObjectPointersIfDebug(); + ObjPtr<mirror::Class> declaring_class = referrer->GetDeclaringClass(); mirror::DexCache* dex_cache_ptr = declaring_class->GetDexCache(); mirror::Class* resolved_type = dex_cache_ptr->GetResolvedType(type_idx); - Thread::PoisonObjectPointersIfDebug(); if (UNLIKELY(resolved_type == nullptr)) { StackHandleScope<2> hs(Thread::Current()); Handle<mirror::DexCache> dex_cache(hs.NewHandle(dex_cache_ptr)); diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 7dea614fdb..0d3c0127d5 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -1090,7 +1090,7 @@ bool ClassLinker::IsBootClassLoader(ScopedObjectAccessAlreadyRunnable& soa, } static mirror::String* GetDexPathListElementName(ScopedObjectAccessUnchecked& soa, - mirror::Object* element) + ObjPtr<mirror::Object> element) REQUIRES_SHARED(Locks::mutator_lock_) { ArtField* const dex_file_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile); @@ -1100,11 +1100,11 @@ static mirror::String* GetDexPathListElementName(ScopedObjectAccessUnchecked& so DCHECK(dex_file_name_field != nullptr); DCHECK(element != nullptr); CHECK_EQ(dex_file_field->GetDeclaringClass(), element->GetClass()) << PrettyTypeOf(element); - mirror::Object* dex_file = dex_file_field->GetObject(element); + ObjPtr<mirror::Object> dex_file = dex_file_field->GetObject(element); if (dex_file == nullptr) { return nullptr; } - mirror::Object* const name_object = dex_file_name_field->GetObject(dex_file); + ObjPtr<mirror::Object> name_object = dex_file_name_field->GetObject(dex_file); if (name_object != nullptr) { return name_object->AsString(); } @@ -1131,28 +1131,28 @@ static bool FlattenPathClassLoader(mirror::ClassLoader* class_loader, // Unsupported class loader. return false; } - mirror::Object* dex_path_list = dex_path_list_field->GetObject(class_loader); + ObjPtr<mirror::Object> dex_path_list = dex_path_list_field->GetObject(class_loader); if (dex_path_list != nullptr) { // DexPathList has an array dexElements of Elements[] which each contain a dex file. - mirror::Object* dex_elements_obj = dex_elements_field->GetObject(dex_path_list); + ObjPtr<mirror::Object> dex_elements_obj = dex_elements_field->GetObject(dex_path_list); // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look // at the mCookie which is a DexFile vector. if (dex_elements_obj != nullptr) { - mirror::ObjectArray<mirror::Object>* dex_elements = + ObjPtr<mirror::ObjectArray<mirror::Object>> dex_elements = dex_elements_obj->AsObjectArray<mirror::Object>(); // Reverse order since we insert the parent at the front. for (int32_t i = dex_elements->GetLength() - 1; i >= 0; --i) { - mirror::Object* const element = dex_elements->GetWithoutChecks(i); + ObjPtr<mirror::Object> element = dex_elements->GetWithoutChecks(i); if (element == nullptr) { *error_msg = StringPrintf("Null dex element at index %d", i); return false; } - mirror::String* const name = GetDexPathListElementName(soa, element); + ObjPtr<mirror::String> const name = GetDexPathListElementName(soa, element); if (name == nullptr) { *error_msg = StringPrintf("Null name for dex element at index %d", i); return false; } - out_dex_file_names->push_front(name); + out_dex_file_names->push_front(name.Decode()); } } } @@ -2395,12 +2395,12 @@ bool ClassLinker::FindClassInPathClassLoader(ScopedObjectAccessAlreadyRunnable& ArtField* const cookie_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie); ArtField* const dex_file_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile); - mirror::Object* dex_path_list = + ObjPtr<mirror::Object> dex_path_list = soa.DecodeField(WellKnownClasses::dalvik_system_PathClassLoader_pathList)-> GetObject(class_loader.Get()); if (dex_path_list != nullptr && dex_file_field != nullptr && cookie_field != nullptr) { // DexPathList has an array dexElements of Elements[] which each contain a dex file. - mirror::Object* dex_elements_obj = + ObjPtr<mirror::Object> dex_elements_obj = soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements)-> GetObject(dex_path_list); // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look @@ -2409,14 +2409,14 @@ bool ClassLinker::FindClassInPathClassLoader(ScopedObjectAccessAlreadyRunnable& Handle<mirror::ObjectArray<mirror::Object>> dex_elements = hs.NewHandle(dex_elements_obj->AsObjectArray<mirror::Object>()); for (int32_t i = 0; i < dex_elements->GetLength(); ++i) { - mirror::Object* element = dex_elements->GetWithoutChecks(i); + ObjPtr<mirror::Object> element = dex_elements->GetWithoutChecks(i); if (element == nullptr) { // Should never happen, fall back to java code to throw a NPE. break; } - mirror::Object* dex_file = dex_file_field->GetObject(element); + ObjPtr<mirror::Object> dex_file = dex_file_field->GetObject(element); if (dex_file != nullptr) { - mirror::LongArray* long_array = cookie_field->GetObject(dex_file)->AsLongArray(); + ObjPtr<mirror::LongArray> long_array = cookie_field->GetObject(dex_file)->AsLongArray(); if (long_array == nullptr) { // This should never happen so log a warning. LOG(WARNING) << "Null DexFile::mCookie for " << descriptor; @@ -7638,6 +7638,32 @@ mirror::String* ClassLinker::LookupString(const DexFile& dex_file, return string; } +ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(const DexFile& dex_file, + uint16_t type_idx, + ObjPtr<mirror::DexCache> dex_cache, + ObjPtr<mirror::ClassLoader> class_loader) { + ObjPtr<mirror::Class> type = dex_cache->GetResolvedType(type_idx); + if (type == nullptr) { + const char* descriptor = dex_file.StringByTypeIdx(type_idx); + DCHECK_NE(*descriptor, '\0') << "descriptor is empty string"; + if (descriptor[1] == '\0') { + // only the descriptors of primitive types should be 1 character long, also avoid class lookup + // for primitive classes that aren't backed by dex files. + type = FindPrimitiveClass(descriptor[0]); + } else { + Thread* const self = Thread::Current(); + DCHECK(self != nullptr); + const size_t hash = ComputeModifiedUtf8Hash(descriptor); + // Find the class in the loaded classes table. + type = LookupClass(self, descriptor, hash, class_loader.Decode()); + } + } + if (type != nullptr || type->IsResolved()) { + return type; + } + return nullptr; +} + mirror::Class* ClassLinker::ResolveType(const DexFile& dex_file, uint16_t type_idx, mirror::Class* referrer) { @@ -8256,16 +8282,18 @@ jobject ClassLinker::CreatePathClassLoader(Thread* self, ScopedObjectAccessUnchecked soa(self); // For now, create a libcore-level DexFile for each ART DexFile. This "explodes" multidex. - StackHandleScope<10> hs(self); + StackHandleScope<11> hs(self); ArtField* dex_elements_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements); - mirror::Class* dex_elements_class = dex_elements_field->GetType<true>(); - DCHECK(dex_elements_class != nullptr); + Handle<mirror::Class> dex_elements_class(hs.NewHandle(dex_elements_field->GetType<true>())); + DCHECK(dex_elements_class.Get() != nullptr); DCHECK(dex_elements_class->IsArrayClass()); Handle<mirror::ObjectArray<mirror::Object>> h_dex_elements(hs.NewHandle( - mirror::ObjectArray<mirror::Object>::Alloc(self, dex_elements_class, dex_files.size()))); + mirror::ObjectArray<mirror::Object>::Alloc(self, + dex_elements_class.Get(), + dex_files.size()))); Handle<mirror::Class> h_dex_element_class = hs.NewHandle(dex_elements_class->GetComponentType()); diff --git a/runtime/class_linker.h b/runtime/class_linker.h index df7fb6115f..f69a5767e2 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -278,6 +278,14 @@ class ClassLinker { REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!dex_lock_, !Roles::uninterruptible_); + // Look up a resolved type with the given ID from the DexFile. The ClassLoader is used to search + // for the type, since it may be referenced from but not contained within the given DexFile. + ObjPtr<mirror::Class> LookupResolvedType(const DexFile& dex_file, + uint16_t type_idx, + ObjPtr<mirror::DexCache> dex_cache, + ObjPtr<mirror::ClassLoader> class_loader) + REQUIRES_SHARED(Locks::mutator_lock_); + // Resolve a type with the given ID from the DexFile, storing the // result in DexCache. The ClassLoader is used to search for the // type, since it may be referenced from but not contained within diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index 451b752ee5..4a926e7619 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -243,10 +243,10 @@ class ClassLinkerTest : public CommonRuntimeTest { kRuntimePointerSize)); } - void AssertField(mirror::Class* klass, ArtField* field) + void AssertField(ObjPtr<mirror::Class> klass, ArtField* field) REQUIRES_SHARED(Locks::mutator_lock_) { EXPECT_TRUE(field != nullptr); - EXPECT_EQ(klass, field->GetDeclaringClass()); + EXPECT_OBJ_PTR_EQ(klass, field->GetDeclaringClass()); EXPECT_TRUE(field->GetName() != nullptr); EXPECT_TRUE(field->GetType<true>() != nullptr); } @@ -358,7 +358,7 @@ class ClassLinkerTest : public CommonRuntimeTest { MemberOffset current_ref_offset = start_ref_offset; for (size_t i = 0; i < klass->NumInstanceFields(); i++) { ArtField* field = klass->GetInstanceField(i); - mirror::Class* field_type = field->GetType<true>(); + ObjPtr<mirror::Class> field_type = field->GetType<true>(); ASSERT_TRUE(field_type != nullptr); if (!field->IsPrimitiveType()) { ASSERT_TRUE(!field_type->IsPrimitive()); @@ -865,6 +865,28 @@ TEST_F(ClassLinkerTest, FindClass) { AssertNonExistentClass("[[[[LNonExistentClass;"); } +TEST_F(ClassLinkerTest, LookupResolvedType) { + ScopedObjectAccess soa(Thread::Current()); + StackHandleScope<1> hs(soa.Self()); + Handle<mirror::ClassLoader> class_loader( + hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("MyClass")))); + AssertNonExistentClass("LMyClass;"); + ObjPtr<mirror::Class> klass = class_linker_->FindClass(soa.Self(), "LMyClass;", class_loader); + uint32_t type_idx = klass->GetClassDef()->class_idx_; + ObjPtr<mirror::DexCache> dex_cache = klass->GetDexCache(); + const DexFile& dex_file = klass->GetDexFile(); + EXPECT_EQ(dex_cache->GetResolvedType(type_idx), klass.Decode()); + EXPECT_OBJ_PTR_EQ( + class_linker_->LookupResolvedType(dex_file, type_idx, dex_cache, class_loader.Get()), + klass); + // Zero out the resolved type and make sure LookupResolvedType still finds it. + dex_cache->SetResolvedType(type_idx, nullptr); + EXPECT_TRUE(dex_cache->GetResolvedType(type_idx) == nullptr); + EXPECT_OBJ_PTR_EQ( + class_linker_->LookupResolvedType(dex_file, type_idx, dex_cache, class_loader.Get()), + klass); +} + TEST_F(ClassLinkerTest, LibCore) { ScopedObjectAccess soa(Thread::Current()); ASSERT_TRUE(java_lang_dex_file_ != nullptr); @@ -1018,8 +1040,8 @@ TEST_F(ClassLinkerTest, StaticFields) { "Ljava/lang/String;"); EXPECT_EQ(s8->GetTypeAsPrimitiveType(), Primitive::kPrimNot); EXPECT_TRUE(s8->GetObject(statics.Get())->AsString()->Equals("android")); - s8->SetObject<false>(s8->GetDeclaringClass(), - mirror::String::AllocFromModifiedUtf8(soa.Self(), "robot")); + mirror::String* str_value = mirror::String::AllocFromModifiedUtf8(soa.Self(), "robot"); + s8->SetObject<false>(s8->GetDeclaringClass(), str_value); // TODO: Remove EXPECT_FALSE when GCC can handle EXPECT_EQ // http://code.google.com/p/googletest/issues/detail?id=322 diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc index eda1ddd87c..ea0719502a 100644 --- a/runtime/common_runtime_test.cc +++ b/runtime/common_runtime_test.cc @@ -523,12 +523,12 @@ std::vector<const DexFile*> CommonRuntimeTestImpl::GetDexFiles(jobject jclass_lo ArtField* cookie_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie); ArtField* dex_file_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile); - mirror::Object* dex_path_list = + ObjPtr<mirror::Object> dex_path_list = soa.DecodeField(WellKnownClasses::dalvik_system_PathClassLoader_pathList)-> GetObject(class_loader.Get()); if (dex_path_list != nullptr && dex_file_field!= nullptr && cookie_field != nullptr) { // DexPathList has an array dexElements of Elements[] which each contain a dex file. - mirror::Object* dex_elements_obj = + ObjPtr<mirror::Object> dex_elements_obj = soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements)-> GetObject(dex_path_list); // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look @@ -537,14 +537,14 @@ std::vector<const DexFile*> CommonRuntimeTestImpl::GetDexFiles(jobject jclass_lo Handle<mirror::ObjectArray<mirror::Object>> dex_elements = hs.NewHandle(dex_elements_obj->AsObjectArray<mirror::Object>()); for (int32_t i = 0; i < dex_elements->GetLength(); ++i) { - mirror::Object* element = dex_elements->GetWithoutChecks(i); + ObjPtr<mirror::Object> element = dex_elements->GetWithoutChecks(i); if (element == nullptr) { // Should never happen, fall back to java code to throw a NPE. break; } - mirror::Object* dex_file = dex_file_field->GetObject(element); + ObjPtr<mirror::Object> dex_file = dex_file_field->GetObject(element); if (dex_file != nullptr) { - mirror::LongArray* long_array = cookie_field->GetObject(dex_file)->AsLongArray(); + ObjPtr<mirror::LongArray> long_array = cookie_field->GetObject(dex_file)->AsLongArray(); DCHECK(long_array != nullptr); int32_t long_array_size = long_array->GetLength(); for (int32_t j = kDexFileIndexStart; j < long_array_size; ++j) { diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h index a7948e4e84..2158d81b44 100644 --- a/runtime/common_runtime_test.h +++ b/runtime/common_runtime_test.h @@ -25,10 +25,18 @@ #include "arch/instruction_set.h" #include "base/mutex.h" #include "globals.h" +// TODO: Add inl file and avoid including inl. +#include "obj_ptr-inl.h" #include "os.h" namespace art { +// OBJ pointer helpers to avoid needing .Decode everywhere. +#define EXPECT_OBJ_PTR_EQ(a, b) EXPECT_EQ(MakeObjPtr(a).Decode(), MakeObjPtr(b).Decode()); +#define ASSERT_OBJ_PTR_EQ(a, b) ASSERT_EQ(MakeObjPtr(a).Decode(), MakeObjPtr(b).Decode()); +#define EXPECT_OBJ_PTR_NE(a, b) EXPECT_NE(MakeObjPtr(a).Decode(), MakeObjPtr(b).Decode()); +#define ASSERT_OBJ_PTR_NE(a, b) ASSERT_NE(MakeObjPtr(a).Decode(), MakeObjPtr(b).Decode()); + class ClassLinker; class CompilerCallbacks; class DexFile; diff --git a/runtime/debugger.cc b/runtime/debugger.cc index 0206caef4c..1bdb0fccd8 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -46,6 +46,7 @@ #include "mirror/object_array-inl.h" #include "mirror/string-inl.h" #include "mirror/throwable.h" +#include "obj_ptr-inl.h" #include "reflection.h" #include "safe_map.h" #include "scoped_thread_state_change-inl.h" @@ -985,7 +986,7 @@ void Dbg::DisposeObject(JDWP::ObjectId object_id, uint32_t reference_count) { gRegistry->DisposeObject(object_id, reference_count); } -JDWP::JdwpTypeTag Dbg::GetTypeTag(mirror::Class* klass) { +JDWP::JdwpTypeTag Dbg::GetTypeTag(ObjPtr<mirror::Class> klass) { DCHECK(klass != nullptr); if (klass->IsArrayClass()) { return JDWP::TT_ARRAY; @@ -1367,12 +1368,12 @@ bool Dbg::MatchLocation(const JDWP::JdwpLocation& expected_location, return m == event_location.method; } -bool Dbg::MatchType(mirror::Class* event_class, JDWP::RefTypeId class_id) { +bool Dbg::MatchType(ObjPtr<mirror::Class> event_class, JDWP::RefTypeId class_id) { if (event_class == nullptr) { return false; } JDWP::JdwpError error; - mirror::Class* expected_class = DecodeClass(class_id, &error); + ObjPtr<mirror::Class> expected_class = DecodeClass(class_id, &error); CHECK(expected_class != nullptr); return expected_class->IsAssignableFrom(event_class); } @@ -1742,7 +1743,7 @@ static JValue GetArtFieldValue(ArtField* f, mirror::Object* o) return field_value; case Primitive::kPrimNot: - field_value.SetL(f->GetObject(o)); + field_value.SetL(f->GetObject(o).Decode()); return field_value; case Primitive::kPrimVoid: @@ -1868,7 +1869,7 @@ static JDWP::JdwpError SetArtFieldValue(ArtField* f, mirror::Object* o, uint64_t return JDWP::ERR_INVALID_OBJECT; } if (v != nullptr) { - mirror::Class* field_type; + ObjPtr<mirror::Class> field_type; { StackHandleScope<2> hs(Thread::Current()); HandleWrapper<mirror::Object> h_v(hs.NewHandleWrapper(&v)); @@ -1994,8 +1995,7 @@ JDWP::JdwpError Dbg::GetThreadName(JDWP::ObjectId thread_id, std::string* name) CHECK(thread_object != nullptr) << error; ArtField* java_lang_Thread_name_field = soa.DecodeField(WellKnownClasses::java_lang_Thread_name); - mirror::String* s = - reinterpret_cast<mirror::String*>(java_lang_Thread_name_field->GetObject(thread_object)); + ObjPtr<mirror::String> s(java_lang_Thread_name_field->GetObject(thread_object)); if (s != nullptr) { *name = s->ToModifiedUtf8(); } @@ -2021,7 +2021,7 @@ JDWP::JdwpError Dbg::GetThreadGroup(JDWP::ObjectId thread_id, JDWP::ExpandBuf* p CHECK(c != nullptr); ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_group); CHECK(f != nullptr); - mirror::Object* group = f->GetObject(thread_object); + ObjPtr<mirror::Object> group = f->GetObject(thread_object); CHECK(group != nullptr); JDWP::ObjectId thread_group_id = gRegistry->Add(group); expandBufAddObjectId(pReply, thread_group_id); @@ -2063,7 +2063,7 @@ JDWP::JdwpError Dbg::GetThreadGroupName(JDWP::ObjectId thread_group_id, JDWP::Ex ScopedAssertNoThreadSuspension ants("Debugger: GetThreadGroupName"); ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_name); CHECK(f != nullptr); - mirror::String* s = reinterpret_cast<mirror::String*>(f->GetObject(thread_group)); + ObjPtr<mirror::String> s = f->GetObject(thread_group)->AsString(); std::string thread_group_name(s->ToModifiedUtf8()); expandBufAddUtf8String(pReply, thread_group_name); @@ -2077,7 +2077,7 @@ JDWP::JdwpError Dbg::GetThreadGroupParent(JDWP::ObjectId thread_group_id, JDWP:: if (error != JDWP::ERR_NONE) { return error; } - mirror::Object* parent; + ObjPtr<mirror::Object> parent; { ScopedAssertNoThreadSuspension ants("Debugger: GetThreadGroupParent"); ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_parent); @@ -2104,12 +2104,12 @@ static void GetChildThreadGroups(ScopedObjectAccessUnchecked& soa, mirror::Objec // Get the ThreadGroup[] "groups" out of this thread group... ArtField* groups_field = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_groups); - mirror::Object* groups_array = groups_field->GetObject(thread_group); + ObjPtr<mirror::Object> groups_array = groups_field->GetObject(thread_group); CHECK(groups_array != nullptr); CHECK(groups_array->IsObjectArray()); - mirror::ObjectArray<mirror::Object>* groups_array_as_array = + ObjPtr<mirror::ObjectArray<mirror::Object>> groups_array_as_array = groups_array->AsObjectArray<mirror::Object>(); // Copy the first 'size' elements out of the array into the result. @@ -2154,7 +2154,7 @@ JDWP::JdwpError Dbg::GetThreadGroupChildren(JDWP::ObjectId thread_group_id, JDWP::ObjectId Dbg::GetSystemThreadGroupId() { ScopedObjectAccessUnchecked soa(Thread::Current()); ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_systemThreadGroup); - mirror::Object* group = f->GetObject(f->GetDeclaringClass()); + ObjPtr<mirror::Object> group = f->GetObject(f->GetDeclaringClass()); return gRegistry->Add(group); } @@ -2252,7 +2252,7 @@ static bool IsInDesiredThreadGroup(ScopedObjectAccessUnchecked& soa, } ArtField* thread_group_field = soa.DecodeField(WellKnownClasses::java_lang_Thread_group); DCHECK(thread_group_field != nullptr); - mirror::Object* group = thread_group_field->GetObject(peer); + ObjPtr<mirror::Object> group = thread_group_field->GetObject(peer); return (group == desired_thread_group); } diff --git a/runtime/debugger.h b/runtime/debugger.h index 7398c4e767..5d0315e9a1 100644 --- a/runtime/debugger.h +++ b/runtime/debugger.h @@ -31,6 +31,7 @@ #include "jdwp/jdwp.h" #include "jni.h" #include "jvalue.h" +#include "obj_ptr.h" #include "thread.h" #include "thread_state.h" @@ -317,7 +318,7 @@ class Dbg { const JDWP::EventLocation& event_location) REQUIRES_SHARED(Locks::mutator_lock_); - static bool MatchType(mirror::Class* event_class, JDWP::RefTypeId class_id) + static bool MatchType(ObjPtr<mirror::Class> event_class, JDWP::RefTypeId class_id) REQUIRES_SHARED(Locks::mutator_lock_); static bool MatchField(JDWP::RefTypeId expected_type_id, JDWP::FieldId expected_field_id, @@ -689,7 +690,7 @@ class Dbg { static JDWP::JdwpTag TagFromObject(const ScopedObjectAccessUnchecked& soa, mirror::Object* o) REQUIRES_SHARED(Locks::mutator_lock_); - static JDWP::JdwpTypeTag GetTypeTag(mirror::Class* klass) + static JDWP::JdwpTypeTag GetTypeTag(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_); static JDWP::FieldId ToFieldId(const ArtField* f) diff --git a/runtime/dex_file_annotations.cc b/runtime/dex_file_annotations.cc index 5763479fe3..feb75a8293 100644 --- a/runtime/dex_file_annotations.cc +++ b/runtime/dex_file_annotations.cc @@ -54,7 +54,7 @@ bool IsVisibilityCompatible(uint32_t actual, uint32_t expected) { const DexFile::AnnotationSetItem* FindAnnotationSetForField(ArtField* field) REQUIRES_SHARED(Locks::mutator_lock_) { const DexFile* dex_file = field->GetDexFile(); - mirror::Class* klass = field->GetDeclaringClass(); + ObjPtr<mirror::Class> klass = field->GetDeclaringClass(); const DexFile::AnnotationsDirectoryItem* annotations_dir = dex_file->GetAnnotationsDirectory(*klass->GetClassDef()); if (annotations_dir == nullptr) { @@ -302,7 +302,7 @@ bool ProcessAnnotationValue(Handle<mirror::Class> klass, REQUIRES_SHARED(Locks::mutator_lock_) { const DexFile& dex_file = klass->GetDexFile(); Thread* self = Thread::Current(); - mirror::Object* element_object = nullptr; + ObjPtr<mirror::Object> element_object = nullptr; bool set_object = false; Primitive::Type primitive_type = Primitive::kPrimVoid; const uint8_t* annotation = *annotation_ptr; @@ -577,7 +577,7 @@ bool ProcessAnnotationValue(Handle<mirror::Class> klass, } if (set_object) { - annotation_value->value_.SetL(element_object); + annotation_value->value_.SetL(element_object.Decode()); } return true; diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h index 99b8805099..e37db7dd92 100644 --- a/runtime/entrypoints/entrypoint_utils-inl.h +++ b/runtime/entrypoints/entrypoint_utils-inl.h @@ -410,14 +410,15 @@ inline ArtField* FindFieldFromCode(uint32_t field_idx, DCHECK(self->IsExceptionPending()); // Throw exception and unwind. return nullptr; // Failure. } - mirror::Class* fields_class = resolved_field->GetDeclaringClass(); + ObjPtr<mirror::Class> fields_class = resolved_field->GetDeclaringClass(); if (access_check) { if (UNLIKELY(resolved_field->IsStatic() != is_static)) { ThrowIncompatibleClassChangeErrorField(resolved_field, is_static, referrer); return nullptr; } mirror::Class* referring_class = referrer->GetDeclaringClass(); - if (UNLIKELY(!referring_class->CheckResolvedFieldAccess(fields_class, resolved_field, + if (UNLIKELY(!referring_class->CheckResolvedFieldAccess(fields_class, + resolved_field, field_idx))) { DCHECK(self->IsExceptionPending()); // Throw exception and unwind. return nullptr; // Failure. @@ -696,7 +697,7 @@ inline ArtField* FindFieldFast(uint32_t field_idx, ArtMethod* referrer, FindFiel // Incompatible class change. return nullptr; } - mirror::Class* fields_class = resolved_field->GetDeclaringClass(); + ObjPtr<mirror::Class> fields_class = resolved_field->GetDeclaringClass(); if (is_static) { // Check class is initialized else fail so that we can contend to initialize the class with // other threads that may be racing to do this. diff --git a/runtime/entrypoints/quick/quick_field_entrypoints.cc b/runtime/entrypoints/quick/quick_field_entrypoints.cc index 5b65029dfb..70eb1de87c 100644 --- a/runtime/entrypoints/quick/quick_field_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_field_entrypoints.cc @@ -151,14 +151,14 @@ extern "C" mirror::Object* artGetObjStaticFromCode(uint32_t field_idx, StaticObjectRead, sizeof(mirror::HeapReference<mirror::Object>)); if (LIKELY(field != nullptr)) { - return field->GetObj(field->GetDeclaringClass()); + return field->GetObj(field->GetDeclaringClass()).Decode(); } field = FindFieldFromCode<StaticObjectRead, true>(field_idx, referrer, self, sizeof(mirror::HeapReference<mirror::Object>)); if (LIKELY(field != nullptr)) { - return field->GetObj(field->GetDeclaringClass()); + return field->GetObj(field->GetDeclaringClass()).Decode(); } return nullptr; // Will throw exception by checking with Thread::Current. } @@ -299,7 +299,7 @@ extern "C" mirror::Object* artGetObjInstanceFromCode(uint32_t field_idx, InstanceObjectRead, sizeof(mirror::HeapReference<mirror::Object>)); if (LIKELY(field != nullptr && obj != nullptr)) { - return field->GetObj(obj); + return field->GetObj(obj).Decode(); } field = FindInstanceField<InstanceObjectRead, true>(field_idx, referrer, @@ -307,7 +307,7 @@ extern "C" mirror::Object* artGetObjInstanceFromCode(uint32_t field_idx, sizeof(mirror::HeapReference<mirror::Object>), &obj); if (LIKELY(field != nullptr)) { - return field->GetObj(obj); + return field->GetObj(obj).Decode(); } return nullptr; // Will throw exception by checking with Thread::Current. } diff --git a/runtime/gc_root-inl.h b/runtime/gc_root-inl.h index ae8a38f43e..11ccd33bc2 100644 --- a/runtime/gc_root-inl.h +++ b/runtime/gc_root-inl.h @@ -21,6 +21,7 @@ #include <sstream> +#include "obj_ptr-inl.h" #include "read_barrier-inl.h" namespace art { @@ -31,10 +32,15 @@ inline MirrorType* GcRoot<MirrorType>::Read(GcRootSource* gc_root_source) const return down_cast<MirrorType*>( ReadBarrier::BarrierForRoot<mirror::Object, kReadBarrierOption>(&root_, gc_root_source)); } + template<class MirrorType> inline GcRoot<MirrorType>::GcRoot(MirrorType* ref) : root_(mirror::CompressedReference<mirror::Object>::FromMirrorPtr(ref)) { } +template<class MirrorType> +inline GcRoot<MirrorType>::GcRoot(ObjPtr<MirrorType, kIsDebugBuild> ref) + : GcRoot(ref.Decode()) { } + inline std::string RootInfo::ToString() const { std::ostringstream oss; Describe(oss); diff --git a/runtime/gc_root.h b/runtime/gc_root.h index 0a98f55827..85cd0a4717 100644 --- a/runtime/gc_root.h +++ b/runtime/gc_root.h @@ -24,6 +24,7 @@ namespace art { class ArtField; class ArtMethod; +template<class MirrorType, bool kPoison> class ObjPtr; namespace mirror { class Object; @@ -196,7 +197,10 @@ class GcRoot { } ALWAYS_INLINE GcRoot() {} - explicit ALWAYS_INLINE GcRoot(MirrorType* ref) REQUIRES_SHARED(Locks::mutator_lock_); + explicit ALWAYS_INLINE GcRoot(MirrorType* ref) + REQUIRES_SHARED(Locks::mutator_lock_); + explicit ALWAYS_INLINE GcRoot(ObjPtr<MirrorType, kIsDebugBuild> ref) + REQUIRES_SHARED(Locks::mutator_lock_); private: // Root visitors take pointers to root_ and place them in CompressedReference** arrays. We use a diff --git a/runtime/handle_scope-inl.h b/runtime/handle_scope-inl.h index 75a0391086..1814746d7a 100644 --- a/runtime/handle_scope-inl.h +++ b/runtime/handle_scope-inl.h @@ -135,6 +135,12 @@ inline void StackHandleScope<kNumReferences>::SetReference(size_t i, mirror::Obj GetReferences()[i].Assign(object); } +template<class MirrorType, bool kPoison> +inline MutableHandle<MirrorType> StackHandleScopeCollection::NewHandle( + ObjPtr<MirrorType, kPoison> ptr) { + return NewHandle(ptr.Decode()); +} + } // namespace art #endif // ART_RUNTIME_HANDLE_SCOPE_INL_H_ diff --git a/runtime/handle_scope.h b/runtime/handle_scope.h index 2b283ae3df..fc729a547b 100644 --- a/runtime/handle_scope.h +++ b/runtime/handle_scope.h @@ -252,6 +252,10 @@ class StackHandleScopeCollection { return scopes_.top()->NewHandle(object); } + template<class MirrorType, bool kPoison> + MutableHandle<MirrorType> NewHandle(ObjPtr<MirrorType, kPoison> ptr) + REQUIRES_SHARED(Locks::mutator_lock_); + private: static constexpr size_t kNumReferencesPerScope = 4; diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc index 5934f13b30..7a6162cd07 100644 --- a/runtime/interpreter/interpreter_common.cc +++ b/runtime/interpreter/interpreter_common.cc @@ -46,7 +46,7 @@ bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst CHECK(self->IsExceptionPending()); return false; } - Object* obj; + ObjPtr<Object> obj; if (is_static) { obj = f->GetDeclaringClass(); } else { @@ -60,9 +60,18 @@ bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst // Report this field access to instrumentation if needed. instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); if (UNLIKELY(instrumentation->HasFieldReadListeners())) { - Object* this_object = f->IsStatic() ? nullptr : obj; - instrumentation->FieldReadEvent(self, this_object, shadow_frame.GetMethod(), - shadow_frame.GetDexPC(), f); + StackHandleScope<1> hs(self); + // Wrap in handle wrapper in case the listener does thread suspension. + HandleWrapperObjPtr<mirror::Object> h(hs.NewHandleWrapper(&obj)); + ObjPtr<Object> this_object; + if (!f->IsStatic()) { + this_object = obj; + } + instrumentation->FieldReadEvent(self, + this_object.Decode(), + shadow_frame.GetMethod(), + shadow_frame.GetDexPC(), + f); } uint32_t vregA = is_static ? inst->VRegA_21c(inst_data) : inst->VRegA_22c(inst_data); switch (field_type) { @@ -85,7 +94,7 @@ bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst shadow_frame.SetVRegLong(vregA, f->GetLong(obj)); break; case Primitive::kPrimNot: - shadow_frame.SetVRegReference(vregA, f->GetObject(obj)); + shadow_frame.SetVRegReference(vregA, f->GetObject(obj).Decode()); break; default: LOG(FATAL) << "Unreachable: " << field_type; @@ -241,7 +250,7 @@ bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame, const Instruction CHECK(self->IsExceptionPending()); return false; } - Object* obj; + ObjPtr<Object> obj; if (is_static) { obj = f->GetDeclaringClass(); } else { @@ -257,10 +266,16 @@ bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame, const Instruction // the field from the base of the object, we need to look for it first. instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); if (UNLIKELY(instrumentation->HasFieldWriteListeners())) { + StackHandleScope<1> hs(self); + // Wrap in handle wrapper in case the listener does thread suspension. + HandleWrapperObjPtr<mirror::Object> h(hs.NewHandleWrapper(&obj)); JValue field_value = GetFieldValue<field_type>(shadow_frame, vregA); - Object* this_object = f->IsStatic() ? nullptr : obj; - instrumentation->FieldWriteEvent(self, this_object, shadow_frame.GetMethod(), - shadow_frame.GetDexPC(), f, field_value); + ObjPtr<Object> this_object = f->IsStatic() ? nullptr : obj; + instrumentation->FieldWriteEvent(self, this_object.Decode(), + shadow_frame.GetMethod(), + shadow_frame.GetDexPC(), + f, + field_value); } switch (field_type) { case Primitive::kPrimBoolean: @@ -286,14 +301,14 @@ bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame, const Instruction if (do_assignability_check && reg != nullptr) { // FieldHelper::GetType can resolve classes, use a handle wrapper which will restore the // object in the destructor. - Class* field_class; + ObjPtr<Class> field_class; { StackHandleScope<2> hs(self); HandleWrapper<mirror::Object> h_reg(hs.NewHandleWrapper(®)); - HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&obj)); + HandleWrapperObjPtr<mirror::Object> h_obj(hs.NewHandleWrapper(&obj)); field_class = f->GetType<true>(); } - if (!reg->VerifierInstanceOf(field_class)) { + if (!reg->VerifierInstanceOf(field_class.Decode())) { // This should never happen. std::string temp1, temp2, temp3; self->ThrowNewExceptionF("Ljava/lang/VirtualMachineError;", @@ -489,15 +504,14 @@ void AbortTransactionV(Thread* self, const char* fmt, va_list args) { // Separate declaration is required solely for the attributes. template <bool is_range, - bool do_assignability_check, - size_t kVarArgMax> + bool do_assignability_check> REQUIRES_SHARED(Locks::mutator_lock_) static inline bool DoCallCommon(ArtMethod* called_method, Thread* self, ShadowFrame& shadow_frame, JValue* result, uint16_t number_of_inputs, - uint32_t (&arg)[kVarArgMax], + uint32_t (&arg)[Instruction::kMaxVarArgRegs], uint32_t vregC) ALWAYS_INLINE; void ArtInterpreterToCompiledCodeBridge(Thread* self, @@ -563,14 +577,13 @@ void SetStringInitValueToAllAliases(ShadowFrame* shadow_frame, } template <bool is_range, - bool do_assignability_check, - size_t kVarArgMax> + bool do_assignability_check> static inline bool DoCallCommon(ArtMethod* called_method, Thread* self, ShadowFrame& shadow_frame, JValue* result, uint16_t number_of_inputs, - uint32_t (&arg)[kVarArgMax], + uint32_t (&arg)[Instruction::kMaxVarArgRegs], uint32_t vregC) { bool string_init = false; // Replace calls to String.<init> with equivalent StringFactory call. diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc index 39846da467..eb8cdbc70d 100644 --- a/runtime/interpreter/unstarted_runtime.cc +++ b/runtime/interpreter/unstarted_runtime.cc @@ -786,9 +786,9 @@ static void GetSystemProperty(Thread* self, kAndroidHardcodedSystemPropertiesFieldName); return; } - Handle<mirror::ObjectArray<mirror::ObjectArray<mirror::String>>> h_2string_array( - hs.NewHandle(reinterpret_cast<mirror::ObjectArray<mirror::ObjectArray<mirror::String>>*>( - static_properties->GetObject(h_props_class.Get())))); + ObjPtr<mirror::Object> props = static_properties->GetObject(h_props_class.Get()); + Handle<mirror::ObjectArray<mirror::ObjectArray<mirror::String>>> h_2string_array(hs.NewHandle( + props->AsObjectArray<mirror::ObjectArray<mirror::String>>())); if (h_2string_array.Get() == nullptr) { AbortTransactionOrFail(self, "Field %s is null", kAndroidHardcodedSystemPropertiesFieldName); return; diff --git a/runtime/jdwp/object_registry.cc b/runtime/jdwp/object_registry.cc index 9ba62c93cd..dc3bf16a09 100644 --- a/runtime/jdwp/object_registry.cc +++ b/runtime/jdwp/object_registry.cc @@ -19,6 +19,7 @@ #include "handle_scope-inl.h" #include "jni_internal.h" #include "mirror/class.h" +#include "obj_ptr-inl.h" #include "scoped_thread_state_change-inl.h" namespace art { @@ -35,7 +36,7 @@ ObjectRegistry::ObjectRegistry() : lock_("ObjectRegistry lock", kJdwpObjectRegistryLock), next_id_(1) { } -JDWP::RefTypeId ObjectRegistry::AddRefType(mirror::Class* c) { +JDWP::RefTypeId ObjectRegistry::AddRefType(ObjPtr<mirror::Class> c) { return Add(c); } @@ -43,7 +44,7 @@ JDWP::RefTypeId ObjectRegistry::AddRefType(Handle<mirror::Class> c_h) { return Add(c_h); } -JDWP::ObjectId ObjectRegistry::Add(mirror::Object* o) { +JDWP::ObjectId ObjectRegistry::Add(ObjPtr<mirror::Object> o) { if (o == nullptr) { return 0; } @@ -118,7 +119,9 @@ JDWP::ObjectId ObjectRegistry::InternalAdd(Handle<T> obj_h) { return entry->id; } -bool ObjectRegistry::ContainsLocked(Thread* self, mirror::Object* o, int32_t identity_hash_code, +bool ObjectRegistry::ContainsLocked(Thread* self, + ObjPtr<mirror::Object> o, + int32_t identity_hash_code, ObjectRegistryEntry** out_entry) { DCHECK(o != nullptr); for (auto it = object_to_entry_.lower_bound(identity_hash_code), end = object_to_entry_.end(); diff --git a/runtime/jdwp/object_registry.h b/runtime/jdwp/object_registry.h index 7fa57c6370..9cacc66c32 100644 --- a/runtime/jdwp/object_registry.h +++ b/runtime/jdwp/object_registry.h @@ -25,6 +25,7 @@ #include "base/casts.h" #include "handle.h" #include "jdwp/jdwp.h" +#include "obj_ptr.h" #include "safe_map.h" namespace art { @@ -62,11 +63,11 @@ class ObjectRegistry { public: ObjectRegistry(); - JDWP::ObjectId Add(mirror::Object* o) + JDWP::ObjectId Add(ObjPtr<mirror::Object> o) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_, !lock_); - JDWP::RefTypeId AddRefType(mirror::Class* c) + JDWP::RefTypeId AddRefType(ObjPtr<mirror::Class> c) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_, !lock_); @@ -121,7 +122,9 @@ class ObjectRegistry { void Promote(ObjectRegistryEntry& entry) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(lock_); - bool ContainsLocked(Thread* self, mirror::Object* o, int32_t identity_hash_code, + bool ContainsLocked(Thread* self, + ObjPtr<mirror::Object> o, + int32_t identity_hash_code, ObjectRegistryEntry** out_entry) REQUIRES(lock_) REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc index 7b2757897e..7977815066 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -97,15 +97,20 @@ static void ThrowNoSuchMethodError(ScopedObjectAccess& soa, mirror::Class* c, kind, c->GetDescriptor(&temp), name, sig); } -static void ReportInvalidJNINativeMethod(const ScopedObjectAccess& soa, mirror::Class* c, - const char* kind, jint idx, bool return_errors) +static void ReportInvalidJNINativeMethod(const ScopedObjectAccess& soa, + ObjPtr<mirror::Class> c, + const char* kind, + jint idx, + bool return_errors) REQUIRES_SHARED(Locks::mutator_lock_) { LOG(return_errors ? ::android::base::ERROR : ::android::base::FATAL) << "Failed to register native method in " << PrettyDescriptor(c) << " in " << c->GetDexCache()->GetLocation()->ToModifiedUtf8() << ": " << kind << " is null at index " << idx; soa.Self()->ThrowNewExceptionF("Ljava/lang/NoSuchMethodError;", - "%s is null at index %d", kind, idx); + "%s is null at index %d", + kind, + idx); } static ObjPtr<mirror::Class> EnsureInitialized(Thread* self, ObjPtr<mirror::Class> klass) @@ -282,7 +287,7 @@ int ThrowNewException(JNIEnv* env, jclass exception_class, const char* msg, jobj return JNI_ERR; } ScopedObjectAccess soa(env); - soa.Self()->SetException(soa.Decode<mirror::Throwable>(exception.get()).Decode()); + soa.Self()->SetException(soa.Decode<mirror::Throwable>(exception.get())); return JNI_OK; } @@ -417,7 +422,7 @@ class JNI { ScopedObjectAccess soa(env); ObjPtr<mirror::Class> c1 = soa.Decode<mirror::Class>(java_class1); ObjPtr<mirror::Class> c2 = soa.Decode<mirror::Class>(java_class2); - return c2->IsAssignableFrom(c1.Decode()) ? JNI_TRUE : JNI_FALSE; + return c2->IsAssignableFrom(c1) ? JNI_TRUE : JNI_FALSE; } static jboolean IsInstanceOf(JNIEnv* env, jobject jobj, jclass java_class) { @@ -439,7 +444,7 @@ class JNI { if (exception == nullptr) { return JNI_ERR; } - soa.Self()->SetException(exception.Decode()); + soa.Self()->SetException(exception); return JNI_OK; } @@ -1227,7 +1232,7 @@ class JNI { ScopedObjectAccess soa(env); ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj); ArtField* f = soa.DecodeField(fid); - return soa.AddLocalReference<jobject>(f->GetObject(o.Decode())); + return soa.AddLocalReference<jobject>(f->GetObject(o)); } static jobject GetStaticObjectField(JNIEnv* env, jclass, jfieldID fid) { @@ -1244,7 +1249,7 @@ class JNI { ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object); ObjPtr<mirror::Object> v = soa.Decode<mirror::Object>(java_value); ArtField* f = soa.DecodeField(fid); - f->SetObject<false>(o.Decode(), v.Decode()); + f->SetObject<false>(o, v); } static void SetStaticObjectField(JNIEnv* env, jclass, jfieldID fid, jobject java_value) { @@ -1252,7 +1257,7 @@ class JNI { ScopedObjectAccess soa(env); ObjPtr<mirror::Object> v = soa.Decode<mirror::Object>(java_value); ArtField* f = soa.DecodeField(fid); - f->SetObject<false>(f->GetDeclaringClass(), v.Decode()); + f->SetObject<false>(f->GetDeclaringClass(), v); } #define GET_PRIMITIVE_FIELD(fn, instance) \ @@ -1261,7 +1266,7 @@ class JNI { ScopedObjectAccess soa(env); \ ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(instance); \ ArtField* f = soa.DecodeField(fid); \ - return f->Get ##fn (o.Decode()) + return f->Get ##fn (o) #define GET_STATIC_PRIMITIVE_FIELD(fn) \ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(fid); \ @@ -1275,7 +1280,7 @@ class JNI { ScopedObjectAccess soa(env); \ ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(instance); \ ArtField* f = soa.DecodeField(fid); \ - f->Set ##fn <false>(o.Decode(), value) + f->Set ##fn <false>(o, value) #define SET_STATIC_PRIMITIVE_FIELD(fn, value) \ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid); \ @@ -2159,13 +2164,13 @@ class JNI { const char* sig = methods[i].signature; const void* fnPtr = methods[i].fnPtr; if (UNLIKELY(name == nullptr)) { - ReportInvalidJNINativeMethod(soa, c.Decode(), "method name", i, return_errors); + ReportInvalidJNINativeMethod(soa, c, "method name", i, return_errors); return JNI_ERR; } else if (UNLIKELY(sig == nullptr)) { - ReportInvalidJNINativeMethod(soa, c.Decode(), "method signature", i, return_errors); + ReportInvalidJNINativeMethod(soa, c, "method signature", i, return_errors); return JNI_ERR; } else if (UNLIKELY(fnPtr == nullptr)) { - ReportInvalidJNINativeMethod(soa, c.Decode(), "native function", i, return_errors); + ReportInvalidJNINativeMethod(soa, c, "native function", i, return_errors); return JNI_ERR; } bool is_fast = false; diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h index 5a5f717530..3cbd58b778 100644 --- a/runtime/mirror/class-inl.h +++ b/runtime/mirror/class-inl.h @@ -341,13 +341,13 @@ inline bool Class::Implements(Class* klass) { // Don't forget about primitive types. // Object[] = int[] --> false // -inline bool Class::IsArrayAssignableFromArray(Class* src) { +inline bool Class::IsArrayAssignableFromArray(ObjPtr<Class> src) { DCHECK(IsArrayClass()) << PrettyClass(this); DCHECK(src->IsArrayClass()) << PrettyClass(src); return GetComponentType()->IsAssignableFrom(src->GetComponentType()); } -inline bool Class::IsAssignableFromArray(Class* src) { +inline bool Class::IsAssignableFromArray(ObjPtr<Class> src) { DCHECK(!IsInterface()) << PrettyClass(this); // handled first in IsAssignableFrom DCHECK(src->IsArrayClass()) << PrettyClass(src); if (!IsArrayClass()) { @@ -362,34 +362,29 @@ inline bool Class::IsAssignableFromArray(Class* src) { } template <bool throw_on_failure, bool use_referrers_cache> -inline bool Class::ResolvedFieldAccessTest(Class* access_to, ArtField* field, - uint32_t field_idx, DexCache* dex_cache) { +inline bool Class::ResolvedFieldAccessTest(ObjPtr<Class> access_to, + ArtField* field, + uint32_t field_idx, + ObjPtr<DexCache> dex_cache) { DCHECK_EQ(use_referrers_cache, dex_cache == nullptr); if (UNLIKELY(!this->CanAccess(access_to))) { // The referrer class can't access the field's declaring class but may still be able // to access the field if the FieldId specifies an accessible subclass of the declaring // class rather than the declaring class itself. - DexCache* referrer_dex_cache = use_referrers_cache ? this->GetDexCache() : dex_cache; + ObjPtr<DexCache> referrer_dex_cache = use_referrers_cache ? this->GetDexCache() : dex_cache; uint32_t class_idx = referrer_dex_cache->GetDexFile()->GetFieldId(field_idx).class_idx_; // The referenced class has already been resolved with the field, but may not be in the dex - // cache. Using ResolveType here without handles in the caller should be safe since there + // cache. Use LookupResolveType here to search the class table if it is not in the dex cache. // should be no thread suspension due to the class being resolved. - // TODO: Clean this up to use handles in the caller. - Class* dex_access_to; - { - StackHandleScope<2> hs(Thread::Current()); - Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(referrer_dex_cache)); - Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(access_to->GetClassLoader())); - dex_access_to = Runtime::Current()->GetClassLinker()->ResolveType( - *referrer_dex_cache->GetDexFile(), - class_idx, - h_dex_cache, - h_class_loader); - } + ObjPtr<Class> dex_access_to = Runtime::Current()->GetClassLinker()->LookupResolvedType( + *referrer_dex_cache->GetDexFile(), + class_idx, + referrer_dex_cache, + access_to->GetClassLoader()); DCHECK(dex_access_to != nullptr); if (UNLIKELY(!this->CanAccess(dex_access_to))) { if (throw_on_failure) { - ThrowIllegalAccessErrorClass(this, dex_access_to); + ThrowIllegalAccessErrorClass(this, dex_access_to.Decode()); } return false; } @@ -404,36 +399,32 @@ inline bool Class::ResolvedFieldAccessTest(Class* access_to, ArtField* field, } template <bool throw_on_failure, bool use_referrers_cache, InvokeType throw_invoke_type> -inline bool Class::ResolvedMethodAccessTest(Class* access_to, ArtMethod* method, - uint32_t method_idx, DexCache* dex_cache) { +inline bool Class::ResolvedMethodAccessTest(ObjPtr<Class> access_to, + ArtMethod* method, + uint32_t method_idx, + ObjPtr<DexCache> dex_cache) { static_assert(throw_on_failure || throw_invoke_type == kStatic, "Non-default throw invoke type"); DCHECK_EQ(use_referrers_cache, dex_cache == nullptr); if (UNLIKELY(!this->CanAccess(access_to))) { // The referrer class can't access the method's declaring class but may still be able // to access the method if the MethodId specifies an accessible subclass of the declaring // class rather than the declaring class itself. - DexCache* referrer_dex_cache = use_referrers_cache ? this->GetDexCache() : dex_cache; + ObjPtr<DexCache> referrer_dex_cache = use_referrers_cache ? this->GetDexCache() : dex_cache; uint32_t class_idx = referrer_dex_cache->GetDexFile()->GetMethodId(method_idx).class_idx_; // The referenced class has already been resolved with the method, but may not be in the dex - // cache. Using ResolveType here without handles in the caller should be safe since there - // should be no thread suspension due to the class being resolved. - // TODO: Clean this up to use handles in the caller. - Class* dex_access_to; - { - StackHandleScope<2> hs(Thread::Current()); - Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(referrer_dex_cache)); - Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(access_to->GetClassLoader())); - dex_access_to = Runtime::Current()->GetClassLinker()->ResolveType( - *referrer_dex_cache->GetDexFile(), - class_idx, - h_dex_cache, - h_class_loader); - } + // cache. + ObjPtr<Class> dex_access_to = Runtime::Current()->GetClassLinker()->LookupResolvedType( + *referrer_dex_cache->GetDexFile(), + class_idx, + referrer_dex_cache, + access_to->GetClassLoader()); DCHECK(dex_access_to != nullptr); if (UNLIKELY(!this->CanAccess(dex_access_to))) { if (throw_on_failure) { - ThrowIllegalAccessErrorClassForMethodDispatch(this, dex_access_to, - method, throw_invoke_type); + ThrowIllegalAccessErrorClassForMethodDispatch(this, + dex_access_to.Decode(), + method, + throw_invoke_type); } return false; } @@ -447,14 +438,17 @@ inline bool Class::ResolvedMethodAccessTest(Class* access_to, ArtMethod* method, return false; } -inline bool Class::CanAccessResolvedField(Class* access_to, ArtField* field, - DexCache* dex_cache, uint32_t field_idx) { +inline bool Class::CanAccessResolvedField(ObjPtr<Class> access_to, + ArtField* field, + ObjPtr<DexCache> dex_cache, + uint32_t field_idx) { return ResolvedFieldAccessTest<false, false>(access_to, field, field_idx, dex_cache); } -inline bool Class::CheckResolvedFieldAccess(Class* access_to, ArtField* field, +inline bool Class::CheckResolvedFieldAccess(ObjPtr<Class> access_to, + ArtField* field, uint32_t field_idx) { - return ResolvedFieldAccessTest<true, true>(access_to, field, field_idx, nullptr); + return ResolvedFieldAccessTest<true, true>(access_to.Decode(), field, field_idx, nullptr); } inline bool Class::CanAccessResolvedMethod(Class* access_to, ArtMethod* method, @@ -469,10 +463,10 @@ inline bool Class::CheckResolvedMethodAccess(Class* access_to, ArtMethod* method nullptr); } -inline bool Class::IsSubClass(Class* klass) { +inline bool Class::IsSubClass(ObjPtr<Class> klass) { DCHECK(!IsInterface()) << PrettyClass(this); DCHECK(!IsArrayClass()) << PrettyClass(this); - Class* current = this; + ObjPtr<Class> current = this; do { if (current == klass) { return true; @@ -1032,7 +1026,7 @@ inline bool Class::IsArrayClass() { return GetComponentType<kVerifyFlags, kReadBarrierOption>() != nullptr; } -inline bool Class::IsAssignableFrom(Class* src) { +inline bool Class::IsAssignableFrom(ObjPtr<Class> src) { DCHECK(src != nullptr); if (this == src) { // Can always assign to things of the same type. @@ -1113,6 +1107,34 @@ inline void Class::FixupNativePointers(mirror::Class* dest, } } +inline bool Class::CanAccess(ObjPtr<Class> that) { + return that->IsPublic() || this->IsInSamePackage(that); +} + + +inline bool Class::CanAccessMember(ObjPtr<Class> access_to, uint32_t member_flags) { + // Classes can access all of their own members + if (this == access_to) { + return true; + } + // Public members are trivially accessible + if (member_flags & kAccPublic) { + return true; + } + // Private members are trivially not accessible + if (member_flags & kAccPrivate) { + return false; + } + // Check for protected access from a sub-class, which may or may not be in the same package. + if (member_flags & kAccProtected) { + if (!this->IsInterface() && this->IsSubClass(access_to)) { + return true; + } + } + // Allow protected access from other classes in the same package. + return this->IsInSamePackage(access_to); +} + } // namespace mirror } // namespace art diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index 2e5f532606..40742d2731 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -308,9 +308,9 @@ bool Class::IsInSamePackage(const StringPiece& descriptor1, const StringPiece& d } } -bool Class::IsInSamePackage(Class* that) { - Class* klass1 = this; - Class* klass2 = that; +bool Class::IsInSamePackage(ObjPtr<Class> that) { + ObjPtr<Class> klass1 = this; + ObjPtr<Class> klass2 = that; if (klass1 == klass2) { return true; } diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index 6c1259bf50..a0d6f37672 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -611,50 +611,28 @@ class MANAGED Class FINAL : public Object { } // Returns true if this class is in the same packages as that class. - bool IsInSamePackage(Class* that) REQUIRES_SHARED(Locks::mutator_lock_); + bool IsInSamePackage(ObjPtr<Class> that) REQUIRES_SHARED(Locks::mutator_lock_); static bool IsInSamePackage(const StringPiece& descriptor1, const StringPiece& descriptor2); // Returns true if this class can access that class. - bool CanAccess(Class* that) REQUIRES_SHARED(Locks::mutator_lock_) { - return that->IsPublic() || this->IsInSamePackage(that); - } + bool CanAccess(ObjPtr<Class> that) REQUIRES_SHARED(Locks::mutator_lock_); // Can this class access a member in the provided class with the provided member access flags? // Note that access to the class isn't checked in case the declaring class is protected and the // method has been exposed by a public sub-class - bool CanAccessMember(Class* access_to, uint32_t member_flags) - REQUIRES_SHARED(Locks::mutator_lock_) { - // Classes can access all of their own members - if (this == access_to) { - return true; - } - // Public members are trivially accessible - if (member_flags & kAccPublic) { - return true; - } - // Private members are trivially not accessible - if (member_flags & kAccPrivate) { - return false; - } - // Check for protected access from a sub-class, which may or may not be in the same package. - if (member_flags & kAccProtected) { - if (!this->IsInterface() && this->IsSubClass(access_to)) { - return true; - } - } - // Allow protected access from other classes in the same package. - return this->IsInSamePackage(access_to); - } + bool CanAccessMember(ObjPtr<Class> access_to, uint32_t member_flags) + REQUIRES_SHARED(Locks::mutator_lock_); // Can this class access a resolved field? // Note that access to field's class is checked and this may require looking up the class // referenced by the FieldId in the DexFile in case the declaring class is inaccessible. - bool CanAccessResolvedField(Class* access_to, ArtField* field, - DexCache* dex_cache, uint32_t field_idx) + bool CanAccessResolvedField(ObjPtr<Class> access_to, + ArtField* field, + ObjPtr<DexCache> dex_cache, + uint32_t field_idx) REQUIRES_SHARED(Locks::mutator_lock_); - bool CheckResolvedFieldAccess(Class* access_to, ArtField* field, - uint32_t field_idx) + bool CheckResolvedFieldAccess(ObjPtr<Class> access_to, ArtField* field, uint32_t field_idx) REQUIRES_SHARED(Locks::mutator_lock_); // Can this class access a resolved method? @@ -668,14 +646,14 @@ class MANAGED Class FINAL : public Object { uint32_t method_idx) REQUIRES_SHARED(Locks::mutator_lock_); - bool IsSubClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_); + bool IsSubClass(ObjPtr<Class> klass) REQUIRES_SHARED(Locks::mutator_lock_); // Can src be assigned to this class? For example, String can be assigned to Object (by an // upcast), however, an Object cannot be assigned to a String as a potentially exception throwing // downcast would be necessary. Similarly for interfaces, a class that implements (or an interface // that extends) another can be assigned to its parent, but not vice-versa. All Classes may assign // to themselves. Classes for primitive types may not assign to each other. - ALWAYS_INLINE bool IsAssignableFrom(Class* src) REQUIRES_SHARED(Locks::mutator_lock_); + ALWAYS_INLINE bool IsAssignableFrom(ObjPtr<Class> src) REQUIRES_SHARED(Locks::mutator_lock_); template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, ReadBarrierOption kReadBarrierOption = kWithReadBarrier> @@ -1309,17 +1287,22 @@ class MANAGED Class FINAL : public Object { void SetVerifyError(Object* klass) REQUIRES_SHARED(Locks::mutator_lock_); template <bool throw_on_failure, bool use_referrers_cache> - bool ResolvedFieldAccessTest(Class* access_to, ArtField* field, - uint32_t field_idx, DexCache* dex_cache) + bool ResolvedFieldAccessTest(ObjPtr<Class> access_to, + ArtField* field, + uint32_t field_idx, + ObjPtr<DexCache> dex_cache) REQUIRES_SHARED(Locks::mutator_lock_); + template <bool throw_on_failure, bool use_referrers_cache, InvokeType throw_invoke_type> - bool ResolvedMethodAccessTest(Class* access_to, ArtMethod* resolved_method, - uint32_t method_idx, DexCache* dex_cache) + bool ResolvedMethodAccessTest(ObjPtr<Class> access_to, + ArtMethod* resolved_method, + uint32_t method_idx, + ObjPtr<DexCache> dex_cache) REQUIRES_SHARED(Locks::mutator_lock_); bool Implements(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_); - bool IsArrayAssignableFromArray(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_); - bool IsAssignableFromArray(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_); + bool IsArrayAssignableFromArray(ObjPtr<Class> klass) REQUIRES_SHARED(Locks::mutator_lock_); + bool IsAssignableFromArray(ObjPtr<Class> klass) REQUIRES_SHARED(Locks::mutator_lock_); void CheckObjectAlloc() REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/runtime/mirror/field-inl.h b/runtime/mirror/field-inl.h index 8b0f8ce1f0..ec32cb6e36 100644 --- a/runtime/mirror/field-inl.h +++ b/runtime/mirror/field-inl.h @@ -78,6 +78,11 @@ inline mirror::Field* Field::CreateFromArtField(Thread* self, ArtField* field, b return ret.Get(); } +template<bool kTransactionActive> +void Field::SetDeclaringClass(ObjPtr<mirror::Class> c) { + SetFieldObject<kTransactionActive>(OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_), c.Decode()); +} + } // namespace mirror } // namespace art diff --git a/runtime/mirror/field.h b/runtime/mirror/field.h index f378568258..c5357c9d39 100644 --- a/runtime/mirror/field.h +++ b/runtime/mirror/field.h @@ -20,6 +20,7 @@ #include "accessible_object.h" #include "base/enums.h" #include "gc_root.h" +#include "obj_ptr.h" #include "object.h" #include "object_callbacks.h" #include "read_barrier_option.h" @@ -109,9 +110,7 @@ class MANAGED Field : public AccessibleObject { int32_t offset_; template<bool kTransactionActive> - void SetDeclaringClass(mirror::Class* c) REQUIRES_SHARED(Locks::mutator_lock_) { - SetFieldObject<kTransactionActive>(OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_), c); - } + void SetDeclaringClass(ObjPtr<mirror::Class> c) REQUIRES_SHARED(Locks::mutator_lock_); template<bool kTransactionActive> void SetType(mirror::Class* type) REQUIRES_SHARED(Locks::mutator_lock_) { diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc index c37deb52bd..90b97fd143 100644 --- a/runtime/mirror/object.cc +++ b/runtime/mirror/object.cc @@ -213,7 +213,7 @@ void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_val if (field.GetOffset().Int32Value() == field_offset.Int32Value()) { CHECK_NE(field.GetTypeAsPrimitiveType(), Primitive::kPrimNot); // TODO: resolve the field type for moving GC. - mirror::Class* field_type = field.GetType<!kMovingCollector>(); + ObjPtr<mirror::Class> field_type = field.GetType<!kMovingCollector>(); if (field_type != nullptr) { CHECK(field_type->IsAssignableFrom(new_value->GetClass())); } @@ -230,7 +230,7 @@ void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_val if (field.GetOffset().Int32Value() == field_offset.Int32Value()) { CHECK_NE(field.GetTypeAsPrimitiveType(), Primitive::kPrimNot); // TODO: resolve the field type for moving GC. - mirror::Class* field_type = field.GetType<!kMovingCollector>(); + ObjPtr<mirror::Class> field_type = field.GetType<!kMovingCollector>(); if (field_type != nullptr) { CHECK(field_type->IsAssignableFrom(new_value->GetClass())); } diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc index 40ee3a2e50..a573ae631a 100644 --- a/runtime/mirror/object_test.cc +++ b/runtime/mirror/object_test.cc @@ -384,12 +384,12 @@ TEST_F(ObjectTest, StaticFieldFromCode) { ArtField* field = FindFieldFromCode<StaticObjectRead, true>(field_idx, clinit, Thread::Current(), sizeof(HeapReference<Object>)); - Object* s0 = field->GetObj(klass); + ObjPtr<Object> s0 = field->GetObj(klass); EXPECT_TRUE(s0 != nullptr); Handle<CharArray> char_array(hs.NewHandle(CharArray::Alloc(soa.Self(), 0))); field->SetObj<false>(field->GetDeclaringClass(), char_array.Get()); - EXPECT_EQ(char_array.Get(), field->GetObj(klass)); + EXPECT_OBJ_PTR_EQ(char_array.Get(), field->GetObj(klass)); field->SetObj<false>(field->GetDeclaringClass(), nullptr); EXPECT_EQ(nullptr, field->GetObj(klass)); @@ -759,7 +759,7 @@ TEST_F(ObjectTest, ObjectPointer) { EXPECT_TRUE(!X.IsNull()); EXPECT_TRUE(X.IsValid()); EXPECT_TRUE(X.Decode() != nullptr); - EXPECT_EQ(h_X.Get(), X.Decode()); + EXPECT_OBJ_PTR_EQ(h_X.Get(), X); // FindClass may cause thread suspension, it should invalidate X. ObjPtr<Class, /*kPoison*/ true> Y(class_linker_->FindClass(soa.Self(), "LY;", class_loader)); EXPECT_TRUE(!Y.IsNull()); @@ -773,7 +773,7 @@ TEST_F(ObjectTest, ObjectPointer) { X.Assign(h_X.Get()); EXPECT_TRUE(!X.IsNull()); EXPECT_TRUE(X.IsValid()); - EXPECT_EQ(h_X.Get(), X.Decode()); + EXPECT_OBJ_PTR_EQ(h_X.Get(), X); // Allow thread suspension to invalidate Y. soa.Self()->AllowThreadSuspension(); @@ -793,7 +793,7 @@ TEST_F(ObjectTest, ObjectPointer) { unpoisoned = h_X.Get(); EXPECT_FALSE(unpoisoned.IsNull()); EXPECT_TRUE(unpoisoned == h_X.Get()); - EXPECT_EQ(unpoisoned.Decode(), h_X.Get()); + EXPECT_OBJ_PTR_EQ(unpoisoned, h_X.Get()); } } // namespace mirror diff --git a/runtime/monitor_android.cc b/runtime/monitor_android.cc index 671cb60037..0d1839baf4 100644 --- a/runtime/monitor_android.cc +++ b/runtime/monitor_android.cc @@ -21,7 +21,7 @@ #include <sys/stat.h> #include <sys/types.h> -#include "cutils/log.h" +#include <android/log.h> #define EVENT_LOG_TAG_dvm_lock_sample 20003 diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc index acad2a941b..64e5a638ab 100644 --- a/runtime/oat_file_manager.cc +++ b/runtime/oat_file_manager.cc @@ -30,6 +30,7 @@ #include "handle_scope-inl.h" #include "mirror/class_loader.h" #include "oat_file_assistant.h" +#include "obj_ptr-inl.h" #include "scoped_thread_state_change-inl.h" #include "thread-inl.h" #include "thread_list.h" @@ -223,7 +224,7 @@ static void AddNext(/*inout*/DexFileAndClassPair* original, } } -static void IterateOverJavaDexFile(mirror::Object* dex_file, +static void IterateOverJavaDexFile(ObjPtr<mirror::Object> dex_file, ArtField* const cookie_field, std::function<bool(const DexFile*)> fn) REQUIRES_SHARED(Locks::mutator_lock_) { @@ -258,12 +259,12 @@ static void IterateOverPathClassLoader( ArtField* const cookie_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie); ArtField* const dex_file_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile); - mirror::Object* dex_path_list = + ObjPtr<mirror::Object> dex_path_list = soa.DecodeField(WellKnownClasses::dalvik_system_PathClassLoader_pathList)-> GetObject(class_loader.Get()); if (dex_path_list != nullptr && dex_file_field != nullptr && cookie_field != nullptr) { // DexPathList has an array dexElements of Elements[] which each contain a dex file. - mirror::Object* dex_elements_obj = + ObjPtr<mirror::Object> dex_elements_obj = soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements)-> GetObject(dex_path_list); // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look @@ -276,7 +277,7 @@ static void IterateOverPathClassLoader( // Should never happen, fall back to java code to throw a NPE. break; } - mirror::Object* dex_file = dex_file_field->GetObject(element); + ObjPtr<mirror::Object> dex_file = dex_file_field->GetObject(element); IterateOverJavaDexFile(dex_file, cookie_field, fn); } } @@ -360,7 +361,7 @@ static void GetDexFilesFromDexElementsArray( // We support this being dalvik.system.DexPathList$Element and dalvik.system.DexFile. - mirror::Object* dex_file; + ObjPtr<mirror::Object> dex_file; if (element_class == element->GetClass()) { dex_file = dex_file_field->GetObject(element); } else if (dexfile_class == element->GetClass()) { diff --git a/runtime/obj_ptr.h b/runtime/obj_ptr.h index d5ac33d8b3..7c0c9df7d2 100644 --- a/runtime/obj_ptr.h +++ b/runtime/obj_ptr.h @@ -88,11 +88,13 @@ class ObjPtr { return Decode() == ptr.Decode(); } - ALWAYS_INLINE bool operator==(const MirrorType* ptr) const REQUIRES_SHARED(Locks::mutator_lock_) { + template <typename PointerType> + ALWAYS_INLINE bool operator==(const PointerType* ptr) const + REQUIRES_SHARED(Locks::mutator_lock_) { return Decode() == ptr; } - ALWAYS_INLINE bool operator==(std::nullptr_t) const REQUIRES_SHARED(Locks::mutator_lock_) { + ALWAYS_INLINE bool operator==(std::nullptr_t) const { return IsNull(); } @@ -100,16 +102,18 @@ class ObjPtr { return Decode() != ptr.Decode(); } - ALWAYS_INLINE bool operator!=(const MirrorType* ptr) const REQUIRES_SHARED(Locks::mutator_lock_) { + template <typename PointerType> + ALWAYS_INLINE bool operator!=(const PointerType* ptr) const + REQUIRES_SHARED(Locks::mutator_lock_) { return Decode() != ptr; } - ALWAYS_INLINE bool operator!=(std::nullptr_t) const REQUIRES_SHARED(Locks::mutator_lock_) { + ALWAYS_INLINE bool operator!=(std::nullptr_t) const { return !IsNull(); } // Decode unchecked does not check that object pointer is valid. Do not use if you can avoid it. - ALWAYS_INLINE MirrorType* DecodeUnchecked() const REQUIRES_SHARED(Locks::mutator_lock_) { + ALWAYS_INLINE MirrorType* DecodeUnchecked() const { if (kPoison) { return reinterpret_cast<MirrorType*>( static_cast<uintptr_t>(static_cast<uint32_t>(reference_ << kObjectAlignmentShift))); @@ -133,14 +137,40 @@ class ObjPtr { uintptr_t reference_; }; +template<class MirrorType, bool kPoison, typename PointerType> +ALWAYS_INLINE bool operator==(const PointerType* a, const ObjPtr<MirrorType, kPoison>& b) + REQUIRES_SHARED(Locks::mutator_lock_) { + return b == a; +} + +template<class MirrorType, bool kPoison> +ALWAYS_INLINE bool operator==(std::nullptr_t, const ObjPtr<MirrorType, kPoison>& b) { + return b == nullptr; +} + +template<typename MirrorType, bool kPoison, typename PointerType> +ALWAYS_INLINE bool operator!=(const PointerType* a, const ObjPtr<MirrorType, kPoison>& b) + REQUIRES_SHARED(Locks::mutator_lock_) { + return b != a; +} + +template<class MirrorType, bool kPoison> +ALWAYS_INLINE bool operator!=(std::nullptr_t, const ObjPtr<MirrorType, kPoison>& b) { + return b != nullptr; +} + template<class MirrorType, bool kPoison = kIsDebugBuild> static inline ObjPtr<MirrorType, kPoison> MakeObjPtr(MirrorType* ptr) { return ObjPtr<MirrorType, kPoison>(ptr); } +template<class MirrorType, bool kPoison = kIsDebugBuild> +static inline ObjPtr<MirrorType, kPoison> MakeObjPtr(ObjPtr<MirrorType, kPoison> ptr) { + return ObjPtr<MirrorType, kPoison>(ptr); +} + template<class MirrorType, bool kPoison> -ALWAYS_INLINE std::ostream& operator<<(std::ostream& os, ObjPtr<MirrorType, kPoison> ptr) - REQUIRES_SHARED(Locks::mutator_lock_); +ALWAYS_INLINE std::ostream& operator<<(std::ostream& os, ObjPtr<MirrorType, kPoison> ptr); } // namespace art diff --git a/runtime/openjdkjvmti/transform.cc b/runtime/openjdkjvmti/transform.cc index ac348e7246..9c42b2ff85 100644 --- a/runtime/openjdkjvmti/transform.cc +++ b/runtime/openjdkjvmti/transform.cc @@ -209,9 +209,9 @@ static bool FindDalvikSystemDexFileAndLoaderForClass( hs.NewHandle(path_list_field->GetObject(h_class_loader.Get()))); CHECK(path_list.Get() != nullptr); CHECK(!self->IsExceptionPending()); - art::Handle<art::mirror::ObjectArray<art::mirror::Object>> dex_elements_list( - hs.NewHandle(art::down_cast<art::mirror::ObjectArray<art::mirror::Object>*>( - dex_path_list_element_field->GetObject(path_list.Get())))); + art::Handle<art::mirror::ObjectArray<art::mirror::Object>> dex_elements_list(hs.NewHandle( + dex_path_list_element_field->GetObject(path_list.Get())-> + AsObjectArray<art::mirror::Object>())); CHECK(!self->IsExceptionPending()); CHECK(dex_elements_list.Get() != nullptr); size_t num_elements = dex_elements_list->GetLength(); diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc index 43b0b3d4ff..1119ccfc80 100644 --- a/runtime/proxy_test.cc +++ b/runtime/proxy_test.cc @@ -180,7 +180,7 @@ TEST_F(ProxyTest, ProxyFieldHelper) { ArtField* field = &static_fields->At(0); EXPECT_STREQ("interfaces", field->GetName()); EXPECT_STREQ("[Ljava/lang/Class;", field->GetTypeDescriptor()); - EXPECT_EQ(interfacesFieldClass.Get(), field->GetType<true>()); + EXPECT_OBJ_PTR_EQ(MakeObjPtr(interfacesFieldClass.Get()), field->GetType<true>()); std::string temp; EXPECT_STREQ("L$Proxy1234;", field->GetDeclaringClass()->GetDescriptor(&temp)); EXPECT_FALSE(field->IsPrimitiveType()); @@ -189,7 +189,7 @@ TEST_F(ProxyTest, ProxyFieldHelper) { field = &static_fields->At(1); EXPECT_STREQ("throws", field->GetName()); EXPECT_STREQ("[[Ljava/lang/Class;", field->GetTypeDescriptor()); - EXPECT_EQ(throwsFieldClass.Get(), field->GetType<true>()); + EXPECT_OBJ_PTR_EQ(MakeObjPtr(throwsFieldClass.Get()), field->GetType<true>()); EXPECT_STREQ("L$Proxy1234;", field->GetDeclaringClass()->GetDescriptor(&temp)); EXPECT_FALSE(field->IsPrimitiveType()); } @@ -224,10 +224,10 @@ TEST_F(ProxyTest, CheckArtMirrorFieldsOfProxyStaticFields) { ASSERT_TRUE(static_fields1 != nullptr); ASSERT_EQ(2u, static_fields1->size()); - EXPECT_EQ(static_fields0->At(0).GetDeclaringClass(), proxyClass0.Get()); - EXPECT_EQ(static_fields0->At(1).GetDeclaringClass(), proxyClass0.Get()); - EXPECT_EQ(static_fields1->At(0).GetDeclaringClass(), proxyClass1.Get()); - EXPECT_EQ(static_fields1->At(1).GetDeclaringClass(), proxyClass1.Get()); + EXPECT_OBJ_PTR_EQ(static_fields0->At(0).GetDeclaringClass(), MakeObjPtr(proxyClass0.Get())); + EXPECT_OBJ_PTR_EQ(static_fields0->At(1).GetDeclaringClass(), MakeObjPtr(proxyClass0.Get())); + EXPECT_OBJ_PTR_EQ(static_fields1->At(0).GetDeclaringClass(), MakeObjPtr(proxyClass1.Get())); + EXPECT_OBJ_PTR_EQ(static_fields1->At(1).GetDeclaringClass(), MakeObjPtr(proxyClass1.Get())); ASSERT_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize); ASSERT_FALSE(Runtime::Current()->IsActiveTransaction()); diff --git a/runtime/quick/inline_method_analyser.cc b/runtime/quick/inline_method_analyser.cc index dc6f4ebc9c..b009b47195 100644 --- a/runtime/quick/inline_method_analyser.cc +++ b/runtime/quick/inline_method_analyser.cc @@ -738,8 +738,8 @@ bool InlineMethodAnalyser::ComputeSpecialAccessorInfo(ArtMethod* method, if (field == nullptr || field->IsStatic()) { return false; } - mirror::Class* method_class = method->GetDeclaringClass(); - mirror::Class* field_class = field->GetDeclaringClass(); + ObjPtr<mirror::Class> method_class = method->GetDeclaringClass(); + ObjPtr<mirror::Class> field_class = field->GetDeclaringClass(); if (!method_class->CanAccessResolvedField(field_class, field, dex_cache, field_idx) || (is_put && field->IsFinal() && method_class != field_class)) { return false; diff --git a/runtime/reflection.cc b/runtime/reflection.cc index b663b4c8ed..066bc1264c 100644 --- a/runtime/reflection.cc +++ b/runtime/reflection.cc @@ -244,13 +244,13 @@ class ArgArray { #define DO_FIRST_ARG(match_descriptor, get_fn, append) { \ if (LIKELY(arg != nullptr && arg->GetClass()->DescriptorEquals(match_descriptor))) { \ ArtField* primitive_field = arg->GetClass()->GetInstanceField(0); \ - append(primitive_field-> get_fn(arg.Decode())); + append(primitive_field-> get_fn(arg)); #define DO_ARG(match_descriptor, get_fn, append) \ } else if (LIKELY(arg != nullptr && \ arg->GetClass<>()->DescriptorEquals(match_descriptor))) { \ ArtField* primitive_field = arg->GetClass()->GetInstanceField(0); \ - append(primitive_field-> get_fn(arg.Decode())); + append(primitive_field-> get_fn(arg)); #define DO_FAIL(expected) \ } else { \ @@ -801,28 +801,28 @@ static bool UnboxPrimitive(ObjPtr<mirror::Object> o, ArtField* primitive_field = &klass->GetIFieldsPtr()->At(0); if (klass->DescriptorEquals("Ljava/lang/Boolean;")) { src_class = class_linker->FindPrimitiveClass('Z'); - boxed_value.SetZ(primitive_field->GetBoolean(o.Decode())); + boxed_value.SetZ(primitive_field->GetBoolean(o)); } else if (klass->DescriptorEquals("Ljava/lang/Byte;")) { src_class = class_linker->FindPrimitiveClass('B'); - boxed_value.SetB(primitive_field->GetByte(o.Decode())); + boxed_value.SetB(primitive_field->GetByte(o)); } else if (klass->DescriptorEquals("Ljava/lang/Character;")) { src_class = class_linker->FindPrimitiveClass('C'); - boxed_value.SetC(primitive_field->GetChar(o.Decode())); + boxed_value.SetC(primitive_field->GetChar(o)); } else if (klass->DescriptorEquals("Ljava/lang/Float;")) { src_class = class_linker->FindPrimitiveClass('F'); - boxed_value.SetF(primitive_field->GetFloat(o.Decode())); + boxed_value.SetF(primitive_field->GetFloat(o)); } else if (klass->DescriptorEquals("Ljava/lang/Double;")) { src_class = class_linker->FindPrimitiveClass('D'); - boxed_value.SetD(primitive_field->GetDouble(o.Decode())); + boxed_value.SetD(primitive_field->GetDouble(o)); } else if (klass->DescriptorEquals("Ljava/lang/Integer;")) { src_class = class_linker->FindPrimitiveClass('I'); - boxed_value.SetI(primitive_field->GetInt(o.Decode())); + boxed_value.SetI(primitive_field->GetInt(o)); } else if (klass->DescriptorEquals("Ljava/lang/Long;")) { src_class = class_linker->FindPrimitiveClass('J'); - boxed_value.SetJ(primitive_field->GetLong(o.Decode())); + boxed_value.SetJ(primitive_field->GetLong(o)); } else if (klass->DescriptorEquals("Ljava/lang/Short;")) { src_class = class_linker->FindPrimitiveClass('S'); - boxed_value.SetS(primitive_field->GetShort(o.Decode())); + boxed_value.SetS(primitive_field->GetShort(o)); } else { std::string temp; ThrowIllegalArgumentException( @@ -888,13 +888,13 @@ bool VerifyAccess(ObjPtr<mirror::Object> obj, } if ((access_flags & kAccProtected) != 0) { if (obj != nullptr && !obj->InstanceOf(calling_class) && - !declaring_class->IsInSamePackage(calling_class.Decode())) { + !declaring_class->IsInSamePackage(calling_class)) { return false; - } else if (declaring_class->IsAssignableFrom(calling_class.Decode())) { + } else if (declaring_class->IsAssignableFrom(calling_class)) { return true; } } - return declaring_class->IsInSamePackage(calling_class.Decode()); + return declaring_class->IsInSamePackage(calling_class); } void InvalidReceiverError(ObjPtr<mirror::Object> o, ObjPtr<mirror::Class> c) { diff --git a/runtime/thread-inl.h b/runtime/thread-inl.h index bb6eb790a2..d75a788e96 100644 --- a/runtime/thread-inl.h +++ b/runtime/thread-inl.h @@ -175,9 +175,7 @@ inline void Thread::PassActiveSuspendBarriers() { inline void Thread::TransitionFromRunnableToSuspended(ThreadState new_state) { AssertThreadSuspensionIsAllowable(); - if (kIsDebugBuild) { - PoisonObjectPointers(); - } + PoisonObjectPointersIfDebug(); DCHECK_EQ(this, Thread::Current()); // Change to non-runnable state, thereby appearing suspended to the system. TransitionToSuspendedAndRunCheckpoints(new_state); diff --git a/runtime/thread.cc b/runtime/thread.cc index ec1bb3fa13..b8c7096521 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -563,8 +563,8 @@ void Thread::CreateNativeThread(JNIEnv* env, jobject java_peer, size_t stack_siz ScopedObjectAccess soa(env); ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_name); - mirror::String* java_name = reinterpret_cast<mirror::String*>(f->GetObject( - soa.Decode<mirror::Object>(java_peer).Decode())); + ObjPtr<mirror::String> java_name = + f->GetObject(soa.Decode<mirror::Object>(java_peer))->AsString(); std::string thread_name; if (java_name != nullptr) { thread_name = java_name->ToModifiedUtf8(); @@ -845,11 +845,9 @@ void Thread::InitPeer(ScopedObjectAccess& soa, jboolean thread_is_daemon, jobjec soa.DecodeField(WellKnownClasses::java_lang_Thread_daemon)-> SetBoolean<kTransactionActive>(tlsPtr_.opeer, thread_is_daemon); soa.DecodeField(WellKnownClasses::java_lang_Thread_group)-> - SetObject<kTransactionActive>(tlsPtr_.opeer, - soa.Decode<mirror::Object>(thread_group).Decode()); + SetObject<kTransactionActive>(tlsPtr_.opeer, soa.Decode<mirror::Object>(thread_group)); soa.DecodeField(WellKnownClasses::java_lang_Thread_name)-> - SetObject<kTransactionActive>(tlsPtr_.opeer, - soa.Decode<mirror::Object>(thread_name).Decode()); + SetObject<kTransactionActive>(tlsPtr_.opeer, soa.Decode<mirror::Object>(thread_name)); soa.DecodeField(WellKnownClasses::java_lang_Thread_priority)-> SetInt<kTransactionActive>(tlsPtr_.opeer, thread_priority); } @@ -948,8 +946,11 @@ void Thread::Dump(std::ostream& os, bool dump_native_stack, BacktraceMap* backtr mirror::String* Thread::GetThreadName(const ScopedObjectAccessAlreadyRunnable& soa) const { ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_name); - return (tlsPtr_.opeer != nullptr) ? - reinterpret_cast<mirror::String*>(f->GetObject(tlsPtr_.opeer)) : nullptr; + if (tlsPtr_.opeer == nullptr) { + return nullptr; + } + ObjPtr<mirror::Object> name = f->GetObject(tlsPtr_.opeer); + return name == nullptr ? nullptr : name->AsString(); } void Thread::GetThreadName(std::string& name) const { @@ -1220,14 +1221,14 @@ void Thread::DumpState(std::ostream& os, const Thread* thread, pid_t tid) { is_daemon = soa.DecodeField(WellKnownClasses::java_lang_Thread_daemon) ->GetBoolean(thread->tlsPtr_.opeer); - mirror::Object* thread_group = + ObjPtr<mirror::Object> thread_group = soa.DecodeField(WellKnownClasses::java_lang_Thread_group)->GetObject(thread->tlsPtr_.opeer); if (thread_group != nullptr) { ArtField* group_name_field = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_name); - mirror::String* group_name_string = - reinterpret_cast<mirror::String*>(group_name_field->GetObject(thread_group)); + ObjPtr<mirror::String> group_name_string = + group_name_field->GetObject(thread_group)->AsString(); group_name = (group_name_string != nullptr) ? group_name_string->ToModifiedUtf8() : "<null>"; } } else { @@ -1711,7 +1712,7 @@ void Thread::Destroy() { // Thread.join() is implemented as an Object.wait() on the Thread.lock object. Signal anyone // who is waiting. - mirror::Object* lock = + ObjPtr<mirror::Object> lock = soa.DecodeField(WellKnownClasses::java_lang_Thread_lock)->GetObject(tlsPtr_.opeer); // (This conditional is only needed for tests, where Thread.lock won't have been set.) if (lock != nullptr) { @@ -1803,7 +1804,7 @@ void Thread::HandleUncaughtExceptions(ScopedObjectAccess& soa) { void Thread::RemoveFromThreadGroup(ScopedObjectAccess& soa) { // this.group.removeThread(this); // group can be null if we're in the compiler or a test. - mirror::Object* ogroup = soa.DecodeField(WellKnownClasses::java_lang_Thread_group) + ObjPtr<mirror::Object> ogroup = soa.DecodeField(WellKnownClasses::java_lang_Thread_group) ->GetObject(tlsPtr_.opeer); if (ogroup != nullptr) { ScopedLocalRef<jobject> group(soa.Env(), soa.AddLocalReference<jobject>(ogroup)); diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 87b6dc3a88..50466edc1b 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -4563,9 +4563,11 @@ ArtField* MethodVerifier::GetInstanceField(const RegType& obj_type, int field_id return nullptr; } else { std::string temp; - mirror::Class* klass = field->GetDeclaringClass(); + ObjPtr<mirror::Class> klass = field->GetDeclaringClass(); const RegType& field_klass = - FromClass(klass->GetDescriptor(&temp), klass, klass->CannotBeAssignedFromOtherTypes()); + FromClass(klass->GetDescriptor(&temp), + klass.Decode(), + klass->CannotBeAssignedFromOtherTypes()); if (obj_type.IsUninitializedTypes()) { // Field accesses through uninitialized references are only allowable for constructors where // the field is declared in this class. @@ -4662,10 +4664,11 @@ void MethodVerifier::VerifyISFieldAccess(const Instruction* inst, const RegType& } } - mirror::Class* field_type_class = + ObjPtr<mirror::Class> field_type_class = can_load_classes_ ? field->GetType<true>() : field->GetType<false>(); if (field_type_class != nullptr) { - field_type = &FromClass(field->GetTypeDescriptor(), field_type_class, + field_type = &FromClass(field->GetTypeDescriptor(), + field_type_class.Decode(), field_type_class->CannotBeAssignedFromOtherTypes()); } else { DCHECK(!can_load_classes_ || self_->IsExceptionPending()); @@ -4785,12 +4788,12 @@ void MethodVerifier::VerifyQuickFieldAccess(const Instruction* inst, const RegTy // Get the field type. const RegType* field_type; { - mirror::Class* field_type_class = can_load_classes_ ? field->GetType<true>() : + ObjPtr<mirror::Class> field_type_class = can_load_classes_ ? field->GetType<true>() : field->GetType<false>(); if (field_type_class != nullptr) { field_type = &FromClass(field->GetTypeDescriptor(), - field_type_class, + field_type_class.Decode(), field_type_class->CannotBeAssignedFromOtherTypes()); } else { Thread* self = Thread::Current(); diff --git a/runtime/verifier/reg_type-inl.h b/runtime/verifier/reg_type-inl.h index d93aaa193c..10f1be5109 100644 --- a/runtime/verifier/reg_type-inl.h +++ b/runtime/verifier/reg_type-inl.h @@ -44,7 +44,7 @@ inline bool RegType::CanAccess(const RegType& other) const { } } -inline bool RegType::CanAccessMember(mirror::Class* klass, uint32_t access_flags) const { +inline bool RegType::CanAccessMember(ObjPtr<mirror::Class> klass, uint32_t access_flags) const { if ((access_flags & kAccPublic) != 0) { return true; } diff --git a/runtime/verifier/reg_type.h b/runtime/verifier/reg_type.h index 9170bb1a68..472381dd9b 100644 --- a/runtime/verifier/reg_type.h +++ b/runtime/verifier/reg_type.h @@ -29,6 +29,7 @@ #include "base/stringpiece.h" #include "gc_root.h" #include "handle_scope.h" +#include "obj_ptr.h" #include "object_callbacks.h" #include "primitive.h" @@ -205,7 +206,7 @@ class RegType { REQUIRES_SHARED(Locks::mutator_lock_); // Can this type access a member with the given properties? - bool CanAccessMember(mirror::Class* klass, uint32_t access_flags) const + bool CanAccessMember(ObjPtr<mirror::Class> klass, uint32_t access_flags) const REQUIRES_SHARED(Locks::mutator_lock_); // Can this type be assigned by src? diff --git a/runtime/verifier/verifier_deps.cc b/runtime/verifier/verifier_deps.cc index 350c838717..3e1958f2ce 100644 --- a/runtime/verifier/verifier_deps.cc +++ b/runtime/verifier/verifier_deps.cc @@ -19,6 +19,7 @@ #include "compiler_callbacks.h" #include "leb128.h" #include "mirror/class-inl.h" +#include "obj_ptr-inl.h" #include "runtime.h" namespace art { @@ -107,10 +108,10 @@ std::string VerifierDeps::GetStringFromId(const DexFile& dex_file, uint32_t stri } } -bool VerifierDeps::IsInClassPath(mirror::Class* klass) { +bool VerifierDeps::IsInClassPath(ObjPtr<mirror::Class> klass) { DCHECK(klass != nullptr); - mirror::DexCache* dex_cache = klass->GetDexCache(); + ObjPtr<mirror::DexCache> dex_cache = klass->GetDexCache(); if (dex_cache == nullptr) { // This is a synthesized class, in this case always an array. They are not // defined in the compiled DEX files and therefore are part of the classpath. diff --git a/runtime/verifier/verifier_deps.h b/runtime/verifier/verifier_deps.h index dc8dfaf2f1..3223f6f7b9 100644 --- a/runtime/verifier/verifier_deps.h +++ b/runtime/verifier/verifier_deps.h @@ -26,6 +26,7 @@ #include "base/array_ref.h" #include "base/mutex.h" #include "method_resolution_kind.h" +#include "obj_ptr.h" #include "os.h" namespace art { @@ -176,7 +177,7 @@ class VerifierDeps { // Returns true if `klass` is null or not defined in any of dex files which // were reported as being compiled. - bool IsInClassPath(mirror::Class* klass) + bool IsInClassPath(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_); // Returns the index of `str`. If it is defined in `dex_file_`, this is the dex |