diff options
-rw-r--r-- | build/Android.gtest.mk | 1 | ||||
-rw-r--r-- | runtime/dex_file_test.cc | 9 | ||||
-rw-r--r-- | runtime/interpreter/unstarted_runtime.cc | 36 | ||||
-rw-r--r-- | runtime/interpreter/unstarted_runtime_list.h | 2 | ||||
-rw-r--r-- | runtime/interpreter/unstarted_runtime_test.cc | 59 | ||||
-rw-r--r-- | test/Nested/Nested.java | 2 |
6 files changed, 106 insertions, 3 deletions
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk index bc0838435c..e5258087db 100644 --- a/build/Android.gtest.mk +++ b/build/Android.gtest.mk @@ -113,6 +113,7 @@ ART_GTEST_runtime_callbacks_test_DEX_DEPS := XandY ART_GTEST_stub_test_DEX_DEPS := AllFields ART_GTEST_transaction_test_DEX_DEPS := Transaction ART_GTEST_type_lookup_table_test_DEX_DEPS := Lookup +ART_GTEST_unstarted_runtime_test_DEX_DEPS := Nested ART_GTEST_verifier_deps_test_DEX_DEPS := VerifierDeps MultiDex ART_GTEST_dex_to_dex_decompiler_test_DEX_DEPS := VerifierDeps DexToDexDecompiler diff --git a/runtime/dex_file_test.cc b/runtime/dex_file_test.cc index 0fec856865..9dca4c0621 100644 --- a/runtime/dex_file_test.cc +++ b/runtime/dex_file_test.cc @@ -338,13 +338,16 @@ TEST_F(DexFileTest, ClassDefs) { ScopedObjectAccess soa(Thread::Current()); std::unique_ptr<const DexFile> raw(OpenTestDexFile("Nested")); ASSERT_TRUE(raw.get() != nullptr); - EXPECT_EQ(2U, raw->NumClassDefs()); + EXPECT_EQ(3U, raw->NumClassDefs()); const DexFile::ClassDef& c0 = raw->GetClassDef(0); - EXPECT_STREQ("LNested$Inner;", raw->GetClassDescriptor(c0)); + EXPECT_STREQ("LNested$1;", raw->GetClassDescriptor(c0)); const DexFile::ClassDef& c1 = raw->GetClassDef(1); - EXPECT_STREQ("LNested;", raw->GetClassDescriptor(c1)); + EXPECT_STREQ("LNested$Inner;", raw->GetClassDescriptor(c1)); + + const DexFile::ClassDef& c2 = raw->GetClassDef(2); + EXPECT_STREQ("LNested;", raw->GetClassDescriptor(c2)); } TEST_F(DexFileTest, GetMethodSignature) { diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc index feb6e0857a..371e2f1e65 100644 --- a/runtime/interpreter/unstarted_runtime.cc +++ b/runtime/interpreter/unstarted_runtime.cc @@ -401,6 +401,25 @@ void UnstartedRuntime::UnstartedClassGetDeclaredConstructor( result->SetL(constructor); } +void UnstartedRuntime::UnstartedClassGetDeclaringClass( + Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) { + StackHandleScope<1> hs(self); + Handle<mirror::Class> klass(hs.NewHandle( + reinterpret_cast<mirror::Class*>(shadow_frame->GetVRegReference(arg_offset)))); + if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) { + result->SetL(nullptr); + return; + } + // Return null for anonymous classes. + JValue is_anon_result; + UnstartedClassIsAnonymousClass(self, shadow_frame, &is_anon_result, arg_offset); + if (is_anon_result.GetZ() != 0) { + result->SetL(nullptr); + return; + } + result->SetL(annotations::GetDeclaringClass(klass)); +} + void UnstartedRuntime::UnstartedClassGetEnclosingClass( Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) { StackHandleScope<1> hs(self); @@ -420,6 +439,23 @@ void UnstartedRuntime::UnstartedClassGetInnerClassFlags( result->SetI(mirror::Class::GetInnerClassFlags(klass, default_value)); } +void UnstartedRuntime::UnstartedClassIsAnonymousClass( + Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) { + StackHandleScope<1> hs(self); + Handle<mirror::Class> klass(hs.NewHandle( + reinterpret_cast<mirror::Class*>(shadow_frame->GetVRegReference(arg_offset)))); + if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) { + result->SetZ(false); + return; + } + mirror::String* class_name = nullptr; + if (!annotations::GetInnerClass(klass, &class_name)) { + result->SetZ(false); + return; + } + result->SetZ(class_name == nullptr); +} + static std::unique_ptr<MemMap> FindAndExtractEntry(const std::string& jar_file, const char* entry_name, size_t* size, diff --git a/runtime/interpreter/unstarted_runtime_list.h b/runtime/interpreter/unstarted_runtime_list.h index b8553b5771..96b35e4e9c 100644 --- a/runtime/interpreter/unstarted_runtime_list.h +++ b/runtime/interpreter/unstarted_runtime_list.h @@ -28,8 +28,10 @@ V(ClassGetDeclaredField, "java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String)") \ V(ClassGetDeclaredMethod, "java.lang.reflect.Method java.lang.Class.getDeclaredMethodInternal(java.lang.String, java.lang.Class[])") \ V(ClassGetDeclaredConstructor, "java.lang.reflect.Constructor java.lang.Class.getDeclaredConstructorInternal(java.lang.Class[])") \ + V(ClassGetDeclaringClass, "java.lang.Class java.lang.Class.getDeclaringClass()") \ V(ClassGetEnclosingClass, "java.lang.Class java.lang.Class.getEnclosingClass()") \ V(ClassGetInnerClassFlags, "int java.lang.Class.getInnerClassFlags(int)") \ + V(ClassIsAnonymousClass, "boolean java.lang.Class.isAnonymousClass()") \ V(ClassLoaderGetResourceAsStream, "java.io.InputStream java.lang.ClassLoader.getResourceAsStream(java.lang.String)") \ V(VmClassLoaderFindLoadedClass, "java.lang.Class java.lang.VMClassLoader.findLoadedClass(java.lang.ClassLoader, java.lang.String)") \ V(VoidLookupType, "java.lang.Class java.lang.Void.lookupType()") \ diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc index b190c81aff..ae55f4c2ef 100644 --- a/runtime/interpreter/unstarted_runtime_test.cc +++ b/runtime/interpreter/unstarted_runtime_test.cc @@ -885,5 +885,64 @@ TEST_F(UnstartedRuntimeTest, Pow) { ShadowFrame::DeleteDeoptimizedFrame(tmp); } +TEST_F(UnstartedRuntimeTest, IsAnonymousClass) { + Thread* self = Thread::Current(); + ScopedObjectAccess soa(self); + + JValue result; + ShadowFrame* shadow_frame = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0); + + mirror::Class* class_klass = mirror::Class::GetJavaLangClass(); + shadow_frame->SetVRegReference(0, class_klass); + UnstartedClassIsAnonymousClass(self, shadow_frame, &result, 0); + EXPECT_EQ(result.GetZ(), 0); + + jobject class_loader = LoadDex("Nested"); + StackHandleScope<1> hs(soa.Self()); + Handle<mirror::ClassLoader> loader( + hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); + mirror::Class* c = class_linker_->FindClass(soa.Self(), "LNested$1;", loader); + ASSERT_TRUE(c != nullptr); + shadow_frame->SetVRegReference(0, c); + UnstartedClassIsAnonymousClass(self, shadow_frame, &result, 0); + EXPECT_EQ(result.GetZ(), 1); + + ShadowFrame::DeleteDeoptimizedFrame(shadow_frame); +} + +TEST_F(UnstartedRuntimeTest, GetDeclaringClass) { + Thread* self = Thread::Current(); + ScopedObjectAccess soa(self); + + JValue result; + ShadowFrame* shadow_frame = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0); + + jobject class_loader = LoadDex("Nested"); + StackHandleScope<4> hs(self); + Handle<mirror::ClassLoader> loader( + hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); + + Handle<mirror::Class> nested_klass(hs.NewHandle( + class_linker_->FindClass(soa.Self(), "LNested;", loader))); + Handle<mirror::Class> inner_klass(hs.NewHandle( + class_linker_->FindClass(soa.Self(), "LNested$Inner;", loader))); + Handle<mirror::Class> anon_klass(hs.NewHandle( + class_linker_->FindClass(soa.Self(), "LNested$1;", loader))); + + shadow_frame->SetVRegReference(0, nested_klass.Get()); + UnstartedClassGetDeclaringClass(self, shadow_frame, &result, 0); + EXPECT_EQ(result.GetL(), nullptr); + + shadow_frame->SetVRegReference(0, inner_klass.Get()); + UnstartedClassGetDeclaringClass(self, shadow_frame, &result, 0); + EXPECT_EQ(result.GetL(), nested_klass.Get()); + + shadow_frame->SetVRegReference(0, anon_klass.Get()); + UnstartedClassGetDeclaringClass(self, shadow_frame, &result, 0); + EXPECT_EQ(result.GetL(), nullptr); + + ShadowFrame::DeleteDeoptimizedFrame(shadow_frame); +} + } // namespace interpreter } // namespace art diff --git a/test/Nested/Nested.java b/test/Nested/Nested.java index 78b273bec0..f493989268 100644 --- a/test/Nested/Nested.java +++ b/test/Nested/Nested.java @@ -17,4 +17,6 @@ class Nested { class Inner { } + Object x = new Object() { + }; } |