summaryrefslogtreecommitdiff
path: root/runtime/mirror/class_ext.cc
diff options
context:
space:
mode:
author Alex Light <allight@google.com> 2016-11-30 23:01:31 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2016-11-30 23:01:32 +0000
commit0fd9a7d67878d1d88a74895c0d02c556b5de8e72 (patch)
tree1e10e3ad67ae8477db93e7bc9c35aaaa4ee9fa77 /runtime/mirror/class_ext.cc
parent07ab8831ff6025f91f927cc9e60c04801583666c (diff)
parenta01de59eef990c07df9815376cd3c675e3acd481 (diff)
Merge "Infrastructure for obsolete methods"
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());