summaryrefslogtreecommitdiff
path: root/runtime/mirror/class_ext.cc
diff options
context:
space:
mode:
author Alex Light <allight@google.com> 2016-11-15 10:43:06 -0800
committer Alex Light <allight@google.com> 2016-11-30 10:23:47 -0800
commita01de59eef990c07df9815376cd3c675e3acd481 (patch)
tree86f6ef41c13de572dc134956c836dd94c35d9d64 /runtime/mirror/class_ext.cc
parent424c03aac25835febbf5c695b943206bc40ef335 (diff)
Infrastructure for obsolete methods
This adds some of the structures and functions needed to eventually support obsolete methods. Specifically this adds the code to create and iterate through the obsolete dex-cache maps of classes and re-organizes the redefinition code to be more sensible and extensible. Bug: 32369913 Test: ./test/run-test --host 902 Test: mma -j40 test-art-host Change-Id: I93d60fa66e7512e8b059cdf42af8a56e93ef4bd7
Diffstat (limited to 'runtime/mirror/class_ext.cc')
-rw-r--r--runtime/mirror/class_ext.cc65
1 files changed, 65 insertions, 0 deletions
diff --git a/runtime/mirror/class_ext.cc b/runtime/mirror/class_ext.cc
index cc208e49dd..259bbbe174 100644
--- a/runtime/mirror/class_ext.cc
+++ b/runtime/mirror/class_ext.cc
@@ -34,6 +34,71 @@ namespace mirror {
GcRoot<Class> ClassExt::dalvik_system_ClassExt_;
+void ClassExt::SetObsoleteArrays(ObjPtr<PointerArray> methods,
+ ObjPtr<ObjectArray<DexCache>> dex_caches) {
+ DCHECK_EQ(GetLockOwnerThreadId(), Thread::Current()->GetThreadId())
+ << "Obsolete arrays are set without synchronization!";
+ CHECK_EQ(methods.IsNull(), dex_caches.IsNull());
+ auto obsolete_dex_cache_off = OFFSET_OF_OBJECT_MEMBER(ClassExt, obsolete_dex_caches_);
+ auto obsolete_methods_off = OFFSET_OF_OBJECT_MEMBER(ClassExt, obsolete_methods_);
+ DCHECK(!Runtime::Current()->IsActiveTransaction());
+ SetFieldObject<false>(obsolete_dex_cache_off, dex_caches.Ptr());
+ SetFieldObject<false>(obsolete_methods_off, methods.Ptr());
+}
+
+// TODO We really need to be careful how we update this. If we ever in the future make it so that
+// these arrays are written into without all threads being suspended we have a race condition!
+bool ClassExt::ExtendObsoleteArrays(Thread* self, uint32_t increase) {
+ DCHECK_EQ(GetLockOwnerThreadId(), Thread::Current()->GetThreadId())
+ << "Obsolete arrays are set without synchronization!";
+ StackHandleScope<5> hs(self);
+ Handle<ClassExt> h_this(hs.NewHandle(this));
+ Handle<PointerArray> old_methods(hs.NewHandle(h_this->GetObsoleteMethods()));
+ Handle<ObjectArray<DexCache>> old_dex_caches(hs.NewHandle(h_this->GetObsoleteDexCaches()));
+ ClassLinker* cl = Runtime::Current()->GetClassLinker();
+ size_t new_len;
+ if (old_methods.Get() == nullptr) {
+ CHECK(old_dex_caches.Get() == nullptr);
+ new_len = increase;
+ } else {
+ CHECK_EQ(old_methods->GetLength(), old_dex_caches->GetLength());
+ new_len = increase + old_methods->GetLength();
+ }
+ Handle<PointerArray> new_methods(hs.NewHandle<PointerArray>(
+ cl->AllocPointerArray(self, new_len)));
+ if (new_methods.IsNull()) {
+ // Fail.
+ self->AssertPendingOOMException();
+ return false;
+ }
+ Handle<ObjectArray<DexCache>> new_dex_caches(hs.NewHandle<ObjectArray<DexCache>>(
+ ObjectArray<DexCache>::Alloc(self,
+ cl->FindClass(self,
+ "[Ljava/lang/DexCache;",
+ ScopedNullHandle<ClassLoader>()),
+ new_len)));
+ if (new_dex_caches.IsNull()) {
+ // Fail.
+ self->AssertPendingOOMException();
+ return false;
+ }
+
+ if (!old_methods.IsNull()) {
+ // Copy the old contents.
+ new_methods->Memcpy(0,
+ old_methods.Get(),
+ 0,
+ old_methods->GetLength(),
+ cl->GetImagePointerSize());
+ new_dex_caches->AsObjectArray<Object>()->AssignableCheckingMemcpy<false>(
+ 0, old_dex_caches->AsObjectArray<Object>(), 0, old_dex_caches->GetLength(), false);
+ }
+ // Set the fields.
+ h_this->SetObsoleteArrays(new_methods.Get(), new_dex_caches.Get());
+
+ return true;
+}
+
ClassExt* ClassExt::Alloc(Thread* self) {
DCHECK(dalvik_system_ClassExt_.Read() != nullptr);
return down_cast<ClassExt*>(dalvik_system_ClassExt_.Read()->AllocObject(self).Ptr());