From afa48270228832ecd7df4506915354d1a41f374a Mon Sep 17 00:00:00 2001 From: Narayan Kamath Date: Wed, 3 Aug 2016 12:46:58 +0100 Subject: [PATCH] java.lang.invoke: Add mirror types for MethodHandle / MethodType. Bug: 30550796 Test: make test-art-host Change-Id: I096160464bc6e84f7e5ad021306a7e462cf3b0c5 --- runtime/Android.bp | 3 + runtime/class_linker.cc | 20 +++++++ runtime/class_linker.h | 3 + runtime/class_linker_test.cc | 25 +++++++++ runtime/mirror/method_handle_impl.cc | 43 ++++++++++++++ runtime/mirror/method_handle_impl.h | 88 +++++++++++++++++++++++++++++ runtime/mirror/method_type.cc | 84 +++++++++++++++++++++++++++ runtime/mirror/method_type.h | 95 +++++++++++++++++++++++++++++++ runtime/mirror/method_type_test.cc | 106 +++++++++++++++++++++++++++++++++++ runtime/runtime.cc | 4 ++ 10 files changed, 471 insertions(+) create mode 100644 runtime/mirror/method_handle_impl.cc create mode 100644 runtime/mirror/method_handle_impl.h create mode 100644 runtime/mirror/method_type.cc create mode 100644 runtime/mirror/method_type.h create mode 100644 runtime/mirror/method_type_test.cc diff --git a/runtime/Android.bp b/runtime/Android.bp index fd9b5b9d9..31f2490c2 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -126,6 +126,8 @@ cc_defaults { "mirror/executable.cc", "mirror/field.cc", "mirror/method.cc", + "mirror/method_handle_impl.cc", + "mirror/method_type.cc", "mirror/object.cc", "mirror/reference.cc", "mirror/stack_trace_element.cc", @@ -546,6 +548,7 @@ art_cc_test { "mem_map_test.cc", "memory_region_test.cc", "mirror/dex_cache_test.cc", + "mirror/method_type_test.cc", "mirror/object_test.cc", "monitor_pool_test.cc", "monitor_test.cc", diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 48550f321..5106aec31 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -73,6 +73,8 @@ #include "mirror/field.h" #include "mirror/iftable-inl.h" #include "mirror/method.h" +#include "mirror/method_type.h" +#include "mirror/method_handle_impl.h" #include "mirror/object-inl.h" #include "mirror/object_array-inl.h" #include "mirror/proxy.h" @@ -636,6 +638,18 @@ bool ClassLinker::InitWithoutImage(std::vector> b SetClassRoot(kJavaLangReflectMethodArrayClass, class_root); mirror::Method::SetArrayClass(class_root); + // Create java.lang.invoke.MethodType.class root + class_root = FindSystemClass(self, "Ljava/lang/invoke/MethodType;"); + CHECK(class_root != nullptr); + SetClassRoot(kJavaLangInvokeMethodType, class_root); + mirror::MethodType::SetClass(class_root); + + // Create java.lang.invoke.MethodHandleImpl.class root + class_root = FindSystemClass(self, "Ljava/lang/invoke/MethodHandleImpl;"); + CHECK(class_root != nullptr); + SetClassRoot(kJavaLangInvokeMethodHandleImpl, class_root); + mirror::MethodHandleImpl::SetClass(class_root); + // java.lang.ref classes need to be specially flagged, but otherwise are normal classes // finish initializing Reference class mirror::Class::SetStatus(java_lang_ref_Reference, mirror::Class::kStatusNotReady, self); @@ -1032,6 +1046,8 @@ bool ClassLinker::InitFromBootImage(std::string* error_msg) { mirror::Constructor::SetArrayClass(GetClassRoot(kJavaLangReflectConstructorArrayClass)); mirror::Method::SetClass(GetClassRoot(kJavaLangReflectMethod)); mirror::Method::SetArrayClass(GetClassRoot(kJavaLangReflectMethodArrayClass)); + mirror::MethodType::SetClass(GetClassRoot(kJavaLangInvokeMethodType)); + mirror::MethodHandleImpl::SetClass(GetClassRoot(kJavaLangInvokeMethodHandleImpl)); mirror::Reference::SetClass(GetClassRoot(kJavaLangRefReference)); mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass)); mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass)); @@ -2032,6 +2048,8 @@ ClassLinker::~ClassLinker() { mirror::IntArray::ResetArrayClass(); mirror::LongArray::ResetArrayClass(); mirror::ShortArray::ResetArrayClass(); + mirror::MethodType::ResetClass(); + mirror::MethodHandleImpl::ResetClass(); Thread* const self = Thread::Current(); for (const ClassLoaderData& data : class_loaders_) { DeleteClassLoader(self, data); @@ -8071,6 +8089,8 @@ const char* ClassLinker::GetClassRootDescriptor(ClassRoot class_root) { "[Ljava/lang/reflect/Constructor;", "[Ljava/lang/reflect/Field;", "[Ljava/lang/reflect/Method;", + "Ljava/lang/invoke/MethodHandleImpl;", + "Ljava/lang/invoke/MethodType;", "Ljava/lang/ClassLoader;", "Ljava/lang/Throwable;", "Ljava/lang/ClassNotFoundException;", diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 954af76b9..8f7051e3f 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -51,6 +51,7 @@ namespace mirror { class DexCachePointerArray; class DexCacheTest_Open_Test; class IfTable; + class MethodType; template class ObjectArray; class StackTraceElement; } // namespace mirror @@ -99,6 +100,8 @@ class ClassLinker { kJavaLangReflectConstructorArrayClass, kJavaLangReflectFieldArrayClass, kJavaLangReflectMethodArrayClass, + kJavaLangInvokeMethodHandleImpl, + kJavaLangInvokeMethodType, kJavaLangClassLoader, kJavaLangThrowable, kJavaLangClassNotFoundException, diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index 7023081ce..4f7321863 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -33,6 +33,8 @@ #include "mirror/dex_cache.h" #include "mirror/executable.h" #include "mirror/field.h" +#include "mirror/method_type.h" +#include "mirror/method_handle_impl.h" #include "mirror/object-inl.h" #include "mirror/object_array-inl.h" #include "mirror/proxy.h" @@ -708,6 +710,27 @@ struct ExecutableOffsets : public CheckOffsets { }; }; +struct MethodTypeOffsets : public CheckOffsets { + MethodTypeOffsets() : CheckOffsets( + false, "Ljava/lang/invoke/MethodType;") { + addOffset(OFFSETOF_MEMBER(mirror::MethodType, form_), "form"); + addOffset(OFFSETOF_MEMBER(mirror::MethodType, method_descriptor_), "methodDescriptor"); + addOffset(OFFSETOF_MEMBER(mirror::MethodType, p_types_), "ptypes"); + addOffset(OFFSETOF_MEMBER(mirror::MethodType, r_type_), "rtype"); + addOffset(OFFSETOF_MEMBER(mirror::MethodType, wrap_alt_), "wrapAlt"); + } +}; + +struct MethodHandleImplOffsets : public CheckOffsets { + MethodHandleImplOffsets() : CheckOffsets( + false, "Ljava/lang/invoke/MethodHandle;") { + addOffset(OFFSETOF_MEMBER(mirror::MethodHandleImpl, art_field_or_method_), "artFieldOrMethod"); + addOffset(OFFSETOF_MEMBER(mirror::MethodHandleImpl, as_type_cache_), "asTypeCache"); + addOffset(OFFSETOF_MEMBER(mirror::MethodHandleImpl, handle_kind_), "handleKind"); + addOffset(OFFSETOF_MEMBER(mirror::MethodHandleImpl, method_type_), "type"); + } +}; + // C++ fields must exactly match the fields in the Java classes. If this fails, // reorder the fields in the C++ class. Managed class fields are ordered by // ClassLinker::LinkFields. @@ -726,6 +749,8 @@ TEST_F(ClassLinkerTest, ValidateFieldOrderOfJavaCppUnionClasses) { EXPECT_TRUE(AccessibleObjectOffsets().Check()); EXPECT_TRUE(FieldOffsets().Check()); EXPECT_TRUE(ExecutableOffsets().Check()); + EXPECT_TRUE(MethodTypeOffsets().Check()); + EXPECT_TRUE(MethodHandleImplOffsets().Check()); } TEST_F(ClassLinkerTest, FindClassNonexistent) { diff --git a/runtime/mirror/method_handle_impl.cc b/runtime/mirror/method_handle_impl.cc new file mode 100644 index 000000000..fdfaaa8ca --- /dev/null +++ b/runtime/mirror/method_handle_impl.cc @@ -0,0 +1,43 @@ +/* + * 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. + */ + +#include "method_handle_impl.h" + +#include "class-inl.h" +#include "gc_root-inl.h" + +namespace art { +namespace mirror { + +GcRoot MethodHandleImpl::static_class_; + +void MethodHandleImpl::SetClass(Class* klass) { + CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass; + CHECK(klass != nullptr); + static_class_ = GcRoot(klass); +} + +void MethodHandleImpl::ResetClass() { + CHECK(!static_class_.IsNull()); + static_class_ = GcRoot(nullptr); +} + +void MethodHandleImpl::VisitRoots(RootVisitor* visitor) { + static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass)); +} + +} // namespace mirror +} // namespace art diff --git a/runtime/mirror/method_handle_impl.h b/runtime/mirror/method_handle_impl.h new file mode 100644 index 000000000..a0aae3cdb --- /dev/null +++ b/runtime/mirror/method_handle_impl.h @@ -0,0 +1,88 @@ +/* + * 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. + */ + +#ifndef ART_RUNTIME_MIRROR_METHOD_HANDLE_IMPL_H_ +#define ART_RUNTIME_MIRROR_METHOD_HANDLE_IMPL_H_ + +#include "class.h" +#include "gc_root.h" +#include "object.h" +#include "method_type.h" + +namespace art { + +struct MethodHandleImplOffsets; + +namespace mirror { + +// C++ mirror of java.lang.invoke.MethodHandle +class MANAGED MethodHandle : public Object { + public: + mirror::MethodType* GetMethodType() REQUIRES_SHARED(Locks::mutator_lock_) { + return GetFieldObject(OFFSET_OF_OBJECT_MEMBER(MethodHandle, method_type_)); + } + + ArtMethod* GetTargetMethod() REQUIRES_SHARED(Locks::mutator_lock_) { + return reinterpret_cast( + GetField64(OFFSET_OF_OBJECT_MEMBER(MethodHandle, art_field_or_method_))); + } + + private: + HeapReference as_type_cache_; + HeapReference method_type_; + uint64_t art_field_or_method_; + uint32_t handle_kind_; + + private: + static MemberOffset AsTypeCacheOffset() { + return MemberOffset(OFFSETOF_MEMBER(MethodHandle, as_type_cache_)); + } + static MemberOffset MethodTypeOffset() { + return MemberOffset(OFFSETOF_MEMBER(MethodHandle, method_type_)); + } + static MemberOffset ArtFieldOrMethodOffset() { + return MemberOffset(OFFSETOF_MEMBER(MethodHandle, art_field_or_method_)); + } + static MemberOffset HandleKindOffset() { + return MemberOffset(OFFSETOF_MEMBER(MethodHandle, handle_kind_)); + } + + friend struct art::MethodHandleImplOffsets; // for verifying offset information + DISALLOW_IMPLICIT_CONSTRUCTORS(MethodHandle); +}; + +// C++ mirror of java.lang.invoke.MethodHandleImpl +class MANAGED MethodHandleImpl : public MethodHandle { + public: + static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) { + return static_class_.Read(); + } + + static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_); + static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_); + static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_); + + private: + static GcRoot static_class_; // java.lang.invoke.MethodHandleImpl.class + + friend struct art::MethodHandleImplOffsets; // for verifying offset information + DISALLOW_IMPLICIT_CONSTRUCTORS(MethodHandleImpl); +}; + +} // namespace mirror +} // namespace art + +#endif // ART_RUNTIME_MIRROR_METHOD_HANDLE_IMPL_H_ diff --git a/runtime/mirror/method_type.cc b/runtime/mirror/method_type.cc new file mode 100644 index 000000000..ba6ea5e4f --- /dev/null +++ b/runtime/mirror/method_type.cc @@ -0,0 +1,84 @@ +/* + * 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. + */ + +#include "method_type.h" + +#include "class-inl.h" +#include "gc_root-inl.h" + +namespace art { +namespace mirror { + +GcRoot MethodType::static_class_; + +mirror::MethodType* MethodType::Create(Thread* const self, + Handle return_type, + Handle> param_types) { + StackHandleScope<1> hs(self); + Handle mt( + hs.NewHandle(static_cast(StaticClass()->AllocObject(self)))); + + // TODO: Do we ever create a MethodType during a transaction ? There doesn't + // seem like a good reason to do a polymorphic invoke that results in the + // resolution of a method type in an unstarted runtime. + mt->SetFieldObject(FormOffset(), nullptr); + mt->SetFieldObject(MethodDescriptorOffset(), nullptr); + mt->SetFieldObject(RTypeOffset(), return_type.Get()); + mt->SetFieldObject(PTypesOffset(), param_types.Get()); + mt->SetFieldObject(WrapAltOffset(), nullptr); + + return mt.Get(); +} + +bool MethodType::IsExactMatch(mirror::MethodType* other) REQUIRES_SHARED(Locks::mutator_lock_) { + if (GetRType() != other->GetRType()) { + return false; + } + + mirror::ObjectArray* const p_types = GetPTypes(); + const int32_t params_length = p_types->GetLength(); + + mirror::ObjectArray* const other_p_types = other->GetPTypes(); + if (params_length != other_p_types->GetLength()) { + return false; + } + + for (int32_t i = 0; i < params_length; ++i) { + if (p_types->GetWithoutChecks(i) != other_p_types->GetWithoutChecks(i)) { + return false; + } + } + + return true; +} + +void MethodType::SetClass(Class* klass) { + CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass; + CHECK(klass != nullptr); + static_class_ = GcRoot(klass); +} + +void MethodType::ResetClass() { + CHECK(!static_class_.IsNull()); + static_class_ = GcRoot(nullptr); +} + +void MethodType::VisitRoots(RootVisitor* visitor) { + static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass)); +} + +} // namespace mirror +} // namespace art diff --git a/runtime/mirror/method_type.h b/runtime/mirror/method_type.h new file mode 100644 index 000000000..5b50409cb --- /dev/null +++ b/runtime/mirror/method_type.h @@ -0,0 +1,95 @@ +/* + * 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. + */ + +#ifndef ART_RUNTIME_MIRROR_METHOD_TYPE_H_ +#define ART_RUNTIME_MIRROR_METHOD_TYPE_H_ + +#include "object.h" +#include "string.h" +#include "mirror/object_array.h" +#include "utils.h" + +namespace art { + +struct MethodTypeOffsets; + +namespace mirror { + +// C++ mirror of java.lang.invoke.MethodType +class MANAGED MethodType : public Object { + public: + static mirror::MethodType* Create(Thread* const self, + Handle return_type, + Handle> param_types) + REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_); + + static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) { + return static_class_.Read(); + } + + ObjectArray* GetPTypes() REQUIRES_SHARED(Locks::mutator_lock_) { + return GetFieldObject>(OFFSET_OF_OBJECT_MEMBER(MethodType, p_types_)); + } + + Class* GetRType() REQUIRES_SHARED(Locks::mutator_lock_) { + return GetFieldObject(OFFSET_OF_OBJECT_MEMBER(MethodType, r_type_)); + } + + static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_); + static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_); + static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_); + + // Returns true iff. |other| is an exact match for this method type, i.e + // iff. they have the same return types and parameter types. + bool IsExactMatch(mirror::MethodType* other) REQUIRES_SHARED(Locks::mutator_lock_); + + private: + static MemberOffset FormOffset() { + return MemberOffset(OFFSETOF_MEMBER(MethodType, form_)); + } + + static MemberOffset MethodDescriptorOffset() { + return MemberOffset(OFFSETOF_MEMBER(MethodType, method_descriptor_)); + } + + static MemberOffset PTypesOffset() { + return MemberOffset(OFFSETOF_MEMBER(MethodType, p_types_)); + } + + static MemberOffset RTypeOffset() { + return MemberOffset(OFFSETOF_MEMBER(MethodType, r_type_)); + } + + static MemberOffset WrapAltOffset() { + return MemberOffset(OFFSETOF_MEMBER(MethodType, wrap_alt_)); + } + + HeapReference form_; // Unused in the runtime + HeapReference method_descriptor_; // Unused in the runtime + HeapReference> p_types_; + HeapReference r_type_; + HeapReference wrap_alt_; // Unused in the runtime + + static GcRoot static_class_; // java.lang.invoke.MethodType.class + + friend struct art::MethodTypeOffsets; // for verifying offset information + DISALLOW_IMPLICIT_CONSTRUCTORS(MethodType); +}; + +} // namespace mirror +} // namespace art + +#endif // ART_RUNTIME_MIRROR_METHOD_TYPE_H_ diff --git a/runtime/mirror/method_type_test.cc b/runtime/mirror/method_type_test.cc new file mode 100644 index 000000000..a968bff84 --- /dev/null +++ b/runtime/mirror/method_type_test.cc @@ -0,0 +1,106 @@ +/* + * 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. + */ + +#include "method_type.h" + +#include +#include + +#include "class_linker.h" +#include "common_runtime_test.h" +#include "handle_scope-inl.h" +#include "runtime/mirror/class.h" +#include "runtime/mirror/class_loader.h" +#include "scoped_thread_state_change.h" + +namespace art { +namespace mirror { + +class MethodTypeTest : public CommonRuntimeTest {}; + +static std::string FullyQualifiedType(const std::string& shorthand) { + return "Ljava/lang/" + shorthand + ";"; +} + +static mirror::MethodType* CreateMethodType(const std::string& return_type, + const std::vector& param_types) { + CHECK_LT(param_types.size(), 3u); + + Runtime* const runtime = Runtime::Current(); + ClassLinker* const class_linker = runtime->GetClassLinker(); + Thread* const self = Thread::Current(); + + ScopedObjectAccess soa(self); + StackHandleScope<5> hs(soa.Self()); + + Handle boot_class_loader = hs.NewHandle(nullptr); + + Handle return_clazz = hs.NewHandle(class_linker->FindClass( + soa.Self(), FullyQualifiedType(return_type).c_str(), boot_class_loader)); + CHECK(return_clazz.Get() != nullptr); + + mirror::Class* class_type = mirror::Class::GetJavaLangClass(); + mirror::Class* class_array_type = class_linker->FindArrayClass(self, &class_type); + Handle> param_classes = hs.NewHandle( + mirror::ObjectArray::Alloc(self, class_array_type, param_types.size())); + + for (uint32_t i = 0; i < param_types.size(); ++i) { + Handle param = hs.NewHandle(class_linker->FindClass( + soa.Self(), FullyQualifiedType(param_types[i]).c_str(), boot_class_loader)); + param_classes->Set(i, param.Get()); + } + + return mirror::MethodType::Create(self, return_clazz, param_classes); +} + + +TEST_F(MethodTypeTest, IsExactMatch) { + ScopedObjectAccess soa(Thread::Current()); + { + StackHandleScope<2> hs(soa.Self()); + Handle mt1 = hs.NewHandle(CreateMethodType("String", { "Integer" })); + Handle mt2 = hs.NewHandle(CreateMethodType("String", { "Integer" })); + ASSERT_TRUE(mt1->IsExactMatch(mt2.Get())); + } + + // Mismatched return type. + { + StackHandleScope<2> hs(soa.Self()); + Handle mt1 = hs.NewHandle(CreateMethodType("String", { "Integer" })); + Handle mt2 = hs.NewHandle(CreateMethodType("Integer", { "Integer" })); + ASSERT_FALSE(mt1->IsExactMatch(mt2.Get())); + } + + // Mismatched param types. + { + StackHandleScope<2> hs(soa.Self()); + Handle mt1 = hs.NewHandle(CreateMethodType("String", { "Integer" })); + Handle mt2 = hs.NewHandle(CreateMethodType("String", { "String" })); + ASSERT_FALSE(mt1->IsExactMatch(mt2.Get())); + } + + // Wrong number of param types. + { + StackHandleScope<2> hs(soa.Self()); + Handle mt1 = hs.NewHandle( + CreateMethodType("String", { "String", "String" })); + Handle mt2 = hs.NewHandle(CreateMethodType("String", { "String" })); + ASSERT_FALSE(mt1->IsExactMatch(mt2.Get())); + } +} + +} // namespace mirror +} // namespace art diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 5bb38f5af..65b894f05 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -88,6 +88,8 @@ #include "mirror/class_loader.h" #include "mirror/field.h" #include "mirror/method.h" +#include "mirror/method_handle_impl.h" +#include "mirror/method_type.h" #include "mirror/stack_trace_element.h" #include "mirror/throwable.h" #include "monitor.h" @@ -1547,6 +1549,8 @@ void Runtime::VisitConstantRoots(RootVisitor* visitor) { mirror::String::VisitRoots(visitor); mirror::Throwable::VisitRoots(visitor); mirror::Field::VisitRoots(visitor); + mirror::MethodType::VisitRoots(visitor); + mirror::MethodHandleImpl::VisitRoots(visitor); // Visit all the primitive array types classes. mirror::PrimitiveArray::VisitRoots(visitor); // BooleanArray mirror::PrimitiveArray::VisitRoots(visitor); // ByteArray -- 2.11.0