diff options
author | 2016-11-30 23:01:31 +0000 | |
---|---|---|
committer | 2016-11-30 23:01:32 +0000 | |
commit | 0fd9a7d67878d1d88a74895c0d02c556b5de8e72 (patch) | |
tree | 1e10e3ad67ae8477db93e7bc9c35aaaa4ee9fa77 /runtime/mirror/class_ext.cc | |
parent | 07ab8831ff6025f91f927cc9e60c04801583666c (diff) | |
parent | a01de59eef990c07df9815376cd3c675e3acd481 (diff) |
Merge "Infrastructure for obsolete methods"
Diffstat (limited to 'runtime/mirror/class_ext.cc')
-rw-r--r-- | runtime/mirror/class_ext.cc | 65 |
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()); |