diff options
-rw-r--r-- | compiler/driver/compiler_driver-inl.h | 16 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.h | 9 | ||||
-rw-r--r-- | runtime/entrypoints/entrypoint_utils-inl.h | 27 | ||||
-rw-r--r-- | runtime/entrypoints/entrypoint_utils.h | 5 | ||||
-rw-r--r-- | runtime/entrypoints/quick/quick_trampoline_entrypoints.cc | 4 | ||||
-rw-r--r-- | runtime/mirror/class-inl.h | 53 | ||||
-rw-r--r-- | runtime/mirror/class.h | 21 | ||||
-rw-r--r-- | runtime/mirror/dex_cache_test.cc | 12 |
8 files changed, 77 insertions, 70 deletions
diff --git a/compiler/driver/compiler_driver-inl.h b/compiler/driver/compiler_driver-inl.h index a04349e392..db95bd6e03 100644 --- a/compiler/driver/compiler_driver-inl.h +++ b/compiler/driver/compiler_driver-inl.h @@ -103,16 +103,16 @@ inline std::pair<bool, bool> CompilerDriver::IsFastInstanceField( } inline ArtMethod* CompilerDriver::ResolveMethod( - ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, - Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit, - uint32_t method_idx, InvokeType invoke_type, bool check_incompatible_class_change) { + ScopedObjectAccess& soa, + Handle<mirror::DexCache> dex_cache, + Handle<mirror::ClassLoader> class_loader, + const DexCompilationUnit* mUnit, + uint32_t method_idx, + InvokeType invoke_type) { DCHECK_EQ(class_loader.Get(), mUnit->GetClassLoader().Get()); ArtMethod* resolved_method = - check_incompatible_class_change - ? mUnit->GetClassLinker()->ResolveMethod<ClassLinker::kForceICCECheck>( - *dex_cache->GetDexFile(), method_idx, dex_cache, class_loader, nullptr, invoke_type) - : mUnit->GetClassLinker()->ResolveMethod<ClassLinker::kNoICCECheckForCache>( - *dex_cache->GetDexFile(), method_idx, dex_cache, class_loader, nullptr, invoke_type); + mUnit->GetClassLinker()->ResolveMethod<ClassLinker::kForceICCECheck>( + *dex_cache->GetDexFile(), method_idx, dex_cache, class_loader, nullptr, invoke_type); if (UNLIKELY(resolved_method == nullptr)) { DCHECK(soa.Self()->IsExceptionPending()); // Clean up any exception left by type resolution. diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index cd4f400ff4..e9e73787e4 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -254,9 +254,12 @@ class CompilerDriver { // Resolve a method. Returns null on failure, including incompatible class change. ArtMethod* ResolveMethod( - ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, - Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit, - uint32_t method_idx, InvokeType invoke_type, bool check_incompatible_class_change = true) + ScopedObjectAccess& soa, + Handle<mirror::DexCache> dex_cache, + Handle<mirror::ClassLoader> class_loader, + const DexCompilationUnit* mUnit, + uint32_t method_idx, + InvokeType invoke_type) REQUIRES_SHARED(Locks::mutator_lock_); void ProcessedInstanceField(bool resolved); diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h index 37734e8afb..6547299853 100644 --- a/runtime/entrypoints/entrypoint_utils-inl.h +++ b/runtime/entrypoints/entrypoint_utils-inl.h @@ -376,6 +376,7 @@ inline ArtField* FindFieldFromCode(uint32_t field_idx, mirror::Class* referring_class = referrer->GetDeclaringClass(); if (UNLIKELY(!referring_class->CheckResolvedFieldAccess(fields_class, resolved_field, + referrer->GetDexCache(), field_idx))) { DCHECK(self->IsExceptionPending()); // Throw exception and unwind. return nullptr; // Failure. @@ -461,9 +462,11 @@ inline ArtMethod* FindMethodFromCode(uint32_t method_idx, } else if (access_check) { mirror::Class* methods_class = resolved_method->GetDeclaringClass(); bool can_access_resolved_method = - referrer->GetDeclaringClass()->CheckResolvedMethodAccess<type>(methods_class, - resolved_method, - method_idx); + referrer->GetDeclaringClass()->CheckResolvedMethodAccess(methods_class, + resolved_method, + referrer->GetDexCache(), + method_idx, + type); if (UNLIKELY(!can_access_resolved_method)) { DCHECK(self->IsExceptionPending()); // Throw exception and unwind. return nullptr; // Failure. @@ -662,7 +665,7 @@ inline ArtField* FindFieldFast(uint32_t field_idx, ArtMethod* referrer, FindFiel return nullptr; } } - mirror::Class* referring_class = referrer->GetDeclaringClass(); + ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass(); if (UNLIKELY(!referring_class->CanAccess(fields_class) || !referring_class->CanAccessMember(fields_class, resolved_field->GetAccessFlags()) || (is_set && resolved_field->IsFinal() && (fields_class != referring_class)))) { @@ -677,18 +680,17 @@ inline ArtField* FindFieldFast(uint32_t field_idx, ArtMethod* referrer, FindFiel } // Fast path method resolution that can't throw exceptions. +template <InvokeType type, bool access_check> inline ArtMethod* FindMethodFast(uint32_t method_idx, ObjPtr<mirror::Object> this_object, - ArtMethod* referrer, - bool access_check, - InvokeType type) { + ArtMethod* referrer) { ScopedAssertNoThreadSuspension ants(__FUNCTION__); if (UNLIKELY(this_object == nullptr && type != kStatic)) { return nullptr; } - mirror::Class* referring_class = referrer->GetDeclaringClass(); - ArtMethod* resolved_method = - referrer->GetDexCache()->GetResolvedMethod(method_idx, kRuntimePointerSize); + ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass(); + ObjPtr<mirror::DexCache> dex_cache = referrer->GetDexCache(); + ArtMethod* resolved_method = dex_cache->GetResolvedMethod(method_idx, kRuntimePointerSize); if (UNLIKELY(resolved_method == nullptr)) { return nullptr; } @@ -698,7 +700,7 @@ inline ArtMethod* FindMethodFast(uint32_t method_idx, if (UNLIKELY(icce)) { return nullptr; } - mirror::Class* methods_class = resolved_method->GetDeclaringClass(); + ObjPtr<mirror::Class> methods_class = resolved_method->GetDeclaringClass(); if (UNLIKELY(!referring_class->CanAccess(methods_class) || !referring_class->CanAccessMember(methods_class, resolved_method->GetAccessFlags()))) { @@ -713,7 +715,6 @@ inline ArtMethod* FindMethodFast(uint32_t method_idx, return resolved_method; } else if (type == kSuper) { // TODO This lookup is rather slow. - ObjPtr<mirror::DexCache> dex_cache = referrer->GetDexCache(); dex::TypeIndex method_type_idx = dex_cache->GetDexFile()->GetMethodId(method_idx).class_idx_; ObjPtr<mirror::Class> method_reference_class = ClassLinker::LookupResolvedType( method_type_idx, dex_cache, referrer->GetClassLoader()); @@ -727,7 +728,7 @@ inline ArtMethod* FindMethodFast(uint32_t method_idx, if (!method_reference_class->IsAssignableFrom(referring_class)) { return nullptr; } - mirror::Class* super_class = referring_class->GetSuperClass(); + ObjPtr<mirror::Class> super_class = referring_class->GetSuperClass(); if (resolved_method->GetMethodIndex() >= super_class->GetVTableLength()) { // The super class does not have the method. return nullptr; diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h index eed08aabad..fe85887f05 100644 --- a/runtime/entrypoints/entrypoint_utils.h +++ b/runtime/entrypoints/entrypoint_utils.h @@ -137,11 +137,10 @@ inline ArtField* FindFieldFast(uint32_t field_idx, REQUIRES_SHARED(Locks::mutator_lock_); // Fast path method resolution that can't throw exceptions. +template <InvokeType type, bool access_check> inline ArtMethod* FindMethodFast(uint32_t method_idx, ObjPtr<mirror::Object> this_object, - ArtMethod* referrer, - bool access_check, - InvokeType type) + ArtMethod* referrer) REQUIRES_SHARED(Locks::mutator_lock_); inline mirror::Class* ResolveVerifyAndClinit(dex::TypeIndex type_idx, diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc index 2c99aeba88..36885d8a1f 100644 --- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc @@ -2363,7 +2363,7 @@ extern "C" uint64_t artQuickGenericJniEndTrampoline(Thread* self, // It is valid to use this, as at the usage points here (returns from C functions) we are assuming // to hold the mutator lock (see REQUIRES_SHARED(Locks::mutator_lock_) annotations). -template<InvokeType type, bool access_check> +template <InvokeType type, bool access_check> static TwoWordReturn artInvokeCommon(uint32_t method_idx, ObjPtr<mirror::Object> this_object, Thread* self, @@ -2371,7 +2371,7 @@ static TwoWordReturn artInvokeCommon(uint32_t method_idx, ScopedQuickEntrypointChecks sqec(self); DCHECK_EQ(*sp, Runtime::Current()->GetCalleeSaveMethod(CalleeSaveType::kSaveRefsAndArgs)); ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethod(sp); - ArtMethod* method = FindMethodFast(method_idx, this_object, caller_method, access_check, type); + ArtMethod* method = FindMethodFast<type, access_check>(method_idx, this_object, caller_method); if (UNLIKELY(method == nullptr)) { const DexFile* dex_file = caller_method->GetDeclaringClass()->GetDexCache()->GetDexFile(); uint32_t shorty_len; diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h index 12baf387d2..419a4db0fc 100644 --- a/runtime/mirror/class-inl.h +++ b/runtime/mirror/class-inl.h @@ -99,7 +99,7 @@ inline DexCache* Class::GetDexCache() { inline uint32_t Class::GetCopiedMethodsStartOffset() { // Object::GetFieldShort returns an int16_t value, but // Class::copied_methods_offset_ is an uint16_t value; cast the - // latter to int16_t before returning it as an uint32_t value, so + // latter to uint16_t before returning it as an uint32_t value, so // that uint16_t values between 2^15 and 2^16-1 are correctly // handled. return static_cast<uint16_t>( @@ -113,7 +113,7 @@ inline uint32_t Class::GetDirectMethodsStartOffset() { inline uint32_t Class::GetVirtualMethodsStartOffset() { // Object::GetFieldShort returns an int16_t value, but // Class::virtual_method_offset_ is an uint16_t value; cast the - // latter to int16_t before returning it as an uint32_t value, so + // latter to uint16_t before returning it as an uint32_t value, so // that uint16_t values between 2^15 and 2^16-1 are correctly // handled. return static_cast<uint16_t>( @@ -410,25 +410,24 @@ inline bool Class::IsAssignableFromArray(ObjPtr<Class> src) { return IsArrayAssignableFromArray(src); } -template <bool throw_on_failure, bool use_referrers_cache> +template <bool throw_on_failure> 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); + ObjPtr<DexCache> dex_cache, + uint32_t field_idx) { + DCHECK(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. - ObjPtr<DexCache> referrer_dex_cache = use_referrers_cache ? this->GetDexCache() : dex_cache; - dex::TypeIndex class_idx = referrer_dex_cache->GetDexFile()->GetFieldId(field_idx).class_idx_; + dex::TypeIndex class_idx = 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. 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. ObjPtr<Class> dex_access_to = Runtime::Current()->GetClassLinker()->LookupResolvedType( - *referrer_dex_cache->GetDexFile(), + *dex_cache->GetDexFile(), class_idx, - referrer_dex_cache, + dex_cache, access_to->GetClassLoader()); DCHECK(dex_access_to != nullptr); if (UNLIKELY(!this->CanAccess(dex_access_to))) { @@ -447,25 +446,25 @@ inline bool Class::ResolvedFieldAccessTest(ObjPtr<Class> access_to, return false; } -template <bool throw_on_failure, bool use_referrers_cache, InvokeType throw_invoke_type> +template <bool throw_on_failure> inline bool Class::ResolvedMethodAccessTest(ObjPtr<Class> access_to, ArtMethod* method, + ObjPtr<DexCache> dex_cache, 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); + InvokeType throw_invoke_type) { + DCHECK(throw_on_failure || throw_invoke_type == kStatic); + DCHECK(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. - ObjPtr<DexCache> referrer_dex_cache = use_referrers_cache ? this->GetDexCache() : dex_cache; - dex::TypeIndex class_idx = referrer_dex_cache->GetDexFile()->GetMethodId(method_idx).class_idx_; + dex::TypeIndex class_idx = 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. ObjPtr<Class> dex_access_to = Runtime::Current()->GetClassLinker()->LookupResolvedType( - *referrer_dex_cache->GetDexFile(), + *dex_cache->GetDexFile(), class_idx, - referrer_dex_cache, + dex_cache, access_to->GetClassLoader()); DCHECK(dex_access_to != nullptr); if (UNLIKELY(!this->CanAccess(dex_access_to))) { @@ -491,30 +490,30 @@ 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); + return ResolvedFieldAccessTest<false>(access_to, field, dex_cache, field_idx); } inline bool Class::CheckResolvedFieldAccess(ObjPtr<Class> access_to, ArtField* field, + ObjPtr<DexCache> dex_cache, uint32_t field_idx) { - return ResolvedFieldAccessTest<true, true>(access_to, field, field_idx, nullptr); + return ResolvedFieldAccessTest<true>(access_to, field, dex_cache, field_idx); } inline bool Class::CanAccessResolvedMethod(ObjPtr<Class> access_to, ArtMethod* method, ObjPtr<DexCache> dex_cache, uint32_t method_idx) { - return ResolvedMethodAccessTest<false, false, kStatic>(access_to, method, method_idx, dex_cache); + return ResolvedMethodAccessTest<false>(access_to, method, dex_cache, method_idx, kStatic); } -template <InvokeType throw_invoke_type> inline bool Class::CheckResolvedMethodAccess(ObjPtr<Class> access_to, ArtMethod* method, - uint32_t method_idx) { - return ResolvedMethodAccessTest<true, true, throw_invoke_type>(access_to, - method, - method_idx, - nullptr); + ObjPtr<DexCache> dex_cache, + uint32_t method_idx, + InvokeType throw_invoke_type) { + return ResolvedMethodAccessTest<true>( + access_to, method, dex_cache, method_idx, throw_invoke_type); } inline bool Class::IsSubClass(ObjPtr<Class> klass) { diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index 61d6e05416..00498bc30a 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -643,7 +643,10 @@ class MANAGED Class FINAL : public Object { ObjPtr<DexCache> dex_cache, uint32_t field_idx) REQUIRES_SHARED(Locks::mutator_lock_); - bool CheckResolvedFieldAccess(ObjPtr<Class> access_to, ArtField* field, uint32_t field_idx) + bool CheckResolvedFieldAccess(ObjPtr<Class> access_to, + ArtField* field, + ObjPtr<DexCache> dex_cache, + uint32_t field_idx) REQUIRES_SHARED(Locks::mutator_lock_); // Can this class access a resolved method? @@ -654,10 +657,11 @@ class MANAGED Class FINAL : public Object { ObjPtr<DexCache> dex_cache, uint32_t method_idx) REQUIRES_SHARED(Locks::mutator_lock_); - template <InvokeType throw_invoke_type> bool CheckResolvedMethodAccess(ObjPtr<Class> access_to, ArtMethod* resolved_method, - uint32_t method_idx) + ObjPtr<DexCache> dex_cache, + uint32_t method_idx, + InvokeType throw_invoke_type) REQUIRES_SHARED(Locks::mutator_lock_); bool IsSubClass(ObjPtr<Class> klass) REQUIRES_SHARED(Locks::mutator_lock_); @@ -1352,18 +1356,19 @@ class MANAGED Class FINAL : public Object { uint32_t end_offset) REQUIRES_SHARED(Locks::mutator_lock_); - template <bool throw_on_failure, bool use_referrers_cache> + template <bool throw_on_failure> bool ResolvedFieldAccessTest(ObjPtr<Class> access_to, ArtField* field, - uint32_t field_idx, - ObjPtr<DexCache> dex_cache) + ObjPtr<DexCache> dex_cache, + uint32_t field_idx) REQUIRES_SHARED(Locks::mutator_lock_); - template <bool throw_on_failure, bool use_referrers_cache, InvokeType throw_invoke_type> + template <bool throw_on_failure> bool ResolvedMethodAccessTest(ObjPtr<Class> access_to, ArtMethod* resolved_method, + ObjPtr<DexCache> dex_cache, uint32_t method_idx, - ObjPtr<DexCache> dex_cache) + InvokeType throw_invoke_type) REQUIRES_SHARED(Locks::mutator_lock_); bool Implements(ObjPtr<Class> klass) REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/runtime/mirror/dex_cache_test.cc b/runtime/mirror/dex_cache_test.cc index a110ed7f6b..5b1ba8d010 100644 --- a/runtime/mirror/dex_cache_test.cc +++ b/runtime/mirror/dex_cache_test.cc @@ -106,12 +106,12 @@ TEST_F(DexCacheTest, TestResolvedFieldAccess) { EXPECT_NE(klass1->NumStaticFields(), 0u); for (ArtField& field : klass2->GetSFields()) { - EXPECT_FALSE(( - klass1->ResolvedFieldAccessTest</*throw_on_failure*/ false, - /*use_referrers_cache*/ false>(klass2.Get(), - &field, - field.GetDexFieldIndex(), - klass1->GetDexCache()))); + EXPECT_FALSE( + klass1->ResolvedFieldAccessTest</*throw_on_failure*/ false>( + klass2.Get(), + &field, + klass1->GetDexCache(), + field.GetDexFieldIndex())); } } |