diff options
| -rw-r--r-- | build/Android.gtest.mk | 3 | ||||
| -rw-r--r-- | runtime/mirror/class-inl.h | 34 | ||||
| -rw-r--r-- | runtime/mirror/class.h | 1 | ||||
| -rw-r--r-- | runtime/mirror/dex_cache_test.cc | 28 | ||||
| -rw-r--r-- | test/Android.run-test.mk | 4 | ||||
| -rw-r--r-- | test/Packages/Package1.java | 20 | ||||
| -rw-r--r-- | test/Packages/Package2.java | 20 |
7 files changed, 105 insertions, 5 deletions
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk index 43f917c983..8a6d52dc82 100644 --- a/build/Android.gtest.mk +++ b/build/Android.gtest.mk @@ -37,6 +37,7 @@ GTEST_DEX_DIRECTORIES := \ MyClassNatives \ Nested \ NonStaticLeafMethods \ + Packages \ ProtoCompare \ ProtoCompare2 \ ProfileTestMultiDex \ @@ -69,7 +70,7 @@ ART_GTEST_dex2oat_environment_tests_DEX_DEPS := Main MainStripped MultiDex Multi ART_GTEST_class_linker_test_DEX_DEPS := Interfaces MultiDex MyClass Nested Statics StaticsFromCode ART_GTEST_compiler_driver_test_DEX_DEPS := AbstractMethod StaticLeafMethods ProfileTestMultiDex -ART_GTEST_dex_cache_test_DEX_DEPS := Main +ART_GTEST_dex_cache_test_DEX_DEPS := Main Packages ART_GTEST_dex_file_test_DEX_DEPS := GetMethodSignature Main Nested ART_GTEST_dex2oat_test_DEX_DEPS := $(ART_GTEST_dex2oat_environment_tests_DEX_DEPS) Statics ART_GTEST_exception_test_DEX_DEPS := ExceptionHandle diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h index d1d8caab00..5a5f717530 100644 --- a/runtime/mirror/class-inl.h +++ b/runtime/mirror/class-inl.h @@ -371,8 +371,21 @@ inline bool Class::ResolvedFieldAccessTest(Class* access_to, ArtField* field, // class rather than the declaring class itself. 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, get it from the dex cache. - Class* dex_access_to = referrer_dex_cache->GetResolvedType(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 + // 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); + } DCHECK(dex_access_to != nullptr); if (UNLIKELY(!this->CanAccess(dex_access_to))) { if (throw_on_failure) { @@ -401,8 +414,21 @@ inline bool Class::ResolvedMethodAccessTest(Class* access_to, ArtMethod* method, // class rather than the declaring class itself. 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, get it from the dex cache. - Class* dex_access_to = referrer_dex_cache->GetResolvedType(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); + } DCHECK(dex_access_to != nullptr); if (UNLIKELY(!this->CanAccess(dex_access_to))) { if (throw_on_failure) { diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index 99b7769b03..548087e729 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -1505,6 +1505,7 @@ class MANAGED Class FINAL : public Object { // java.lang.Class static GcRoot<Class> java_lang_Class_; + ART_FRIEND_TEST(DexCacheTest, TestResolvedFieldAccess); // For ResolvedFieldAccessTest friend struct art::ClassOffsets; // for verifying offset information friend class Object; // For VisitReferences DISALLOW_IMPLICIT_CONSTRUCTORS(Class); diff --git a/runtime/mirror/dex_cache_test.cc b/runtime/mirror/dex_cache_test.cc index 175997c2dc..43ba362aca 100644 --- a/runtime/mirror/dex_cache_test.cc +++ b/runtime/mirror/dex_cache_test.cc @@ -64,5 +64,33 @@ TEST_F(DexCacheTest, LinearAlloc) { EXPECT_TRUE(linear_alloc->Contains(klass->GetDexCache()->GetResolvedMethods())); } +TEST_F(DexCacheTest, TestResolvedFieldAccess) { + ScopedObjectAccess soa(Thread::Current()); + jobject jclass_loader(LoadDex("Packages")); + ASSERT_TRUE(jclass_loader != nullptr); + Runtime* const runtime = Runtime::Current(); + ClassLinker* const class_linker = runtime->GetClassLinker(); + StackHandleScope<3> hs(soa.Self()); + Handle<mirror::ClassLoader> class_loader(hs.NewHandle( + soa.Decode<mirror::ClassLoader*>(jclass_loader))); + Handle<mirror::Class> klass1 = + hs.NewHandle(class_linker->FindClass(soa.Self(), "Lpackage1/Package1;", class_loader)); + ASSERT_TRUE(klass1.Get() != nullptr); + Handle<mirror::Class> klass2 = + hs.NewHandle(class_linker->FindClass(soa.Self(), "Lpackage2/Package2;", class_loader)); + ASSERT_TRUE(klass2.Get() != nullptr); + EXPECT_EQ(klass1->GetDexCache(), klass2->GetDexCache()); + + 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()))); + } +} + } // namespace mirror } // namespace art diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk index 75c4f34073..b554f59fb9 100644 --- a/test/Android.run-test.mk +++ b/test/Android.run-test.mk @@ -397,9 +397,11 @@ ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),ndebug,$(PREB # All these tests check that we have sane behavior if we don't have a patchoat or dex2oat. # Therefore we shouldn't run them in situations where we actually don't have these since they # explicitly test for them. These all also assume we have an image. +# 004-JniTest is disabled because @CriticalNative is unsupported by generic JNI b/31400248 # 147-stripped-dex-fallback is disabled because it requires --prebuild. # 554-jit-profile-file is disabled because it needs a primary oat file to know what it should save. TEST_ART_BROKEN_FALLBACK_RUN_TESTS := \ + 004-JniTest \ 116-nodex2oat \ 117-nopatchoat \ 118-noimage-dex2oat \ @@ -473,7 +475,9 @@ TEST_ART_BROKEN_INTERPRETER_RUN_TESTS := # Known broken tests for the JIT. # CFI unwinding expects managed frames, and the test does not iterate enough to even compile. JIT # also uses Generic JNI instead of the JNI compiler. +# 004-JniTest is disabled because @CriticalNative is unsupported by generic JNI b/31400248 TEST_ART_BROKEN_JIT_RUN_TESTS := \ + 004-JniTest \ 137-cfi ifneq (,$(filter jit,$(COMPILER_TYPES))) diff --git a/test/Packages/Package1.java b/test/Packages/Package1.java new file mode 100644 index 0000000000..6d58246961 --- /dev/null +++ b/test/Packages/Package1.java @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package package1; +class Package1 { + static int someField; +} diff --git a/test/Packages/Package2.java b/test/Packages/Package2.java new file mode 100644 index 0000000000..9ae370a165 --- /dev/null +++ b/test/Packages/Package2.java @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package package2; +class Package2 { + static int someField; +} |