From 8668c3cbdcf9471bd97e0da68a240051f2973074 Mon Sep 17 00:00:00 2001 From: Mathieu Chartier Date: Thu, 24 Apr 2014 16:48:11 -0700 Subject: [PATCH] Add finalizer references from the entrypoints. We now have an invariant where we never allocate finalizable objects with the Initialized or Resolved entrypoints. This speeds up allocation by only doing the check in the slow path. Before: MemAllocTest: 3625, 3707, 3641 EvaluateAndApplyChanges: 3448, 3421, 3413 After: MemAllocTest: 3164, 3109, 3135 EvaluateAndApplyChanges: 3272, 3299, 3353 Bug: 14078487 Change-Id: I2b0534af3e7c75ea5e5257cf3647744f7abfb74e --- compiler/dex/quick/gen_common.cc | 11 +++++++---- compiler/driver/compiler_driver.cc | 3 ++- compiler/driver/compiler_driver.h | 2 +- runtime/entrypoints/entrypoint_utils.h | 12 +++++++----- runtime/gc/heap.cc | 6 ++++-- runtime/gc/heap.h | 2 +- runtime/mirror/class-inl.h | 15 ++++++++++++--- runtime/mirror/class.h | 2 +- runtime/mirror/object.cc | 4 +--- runtime/oat.cc | 2 +- 10 files changed, 37 insertions(+), 22 deletions(-) diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc index 8b9a686ec..3cc2ba004 100644 --- a/compiler/dex/quick/gen_common.cc +++ b/compiler/dex/quick/gen_common.cc @@ -330,9 +330,10 @@ void Mir2Lir::GenNewArray(uint32_t type_idx, RegLocation rl_dest, bool is_type_initialized; // Ignored as an array does not have an initializer. bool use_direct_type_ptr; uintptr_t direct_type_ptr; + bool is_finalizable; if (kEmbedClassInCode && - driver->CanEmbedTypeInCode(*dex_file, type_idx, - &is_type_initialized, &use_direct_type_ptr, &direct_type_ptr)) { + driver->CanEmbedTypeInCode(*dex_file, type_idx, &is_type_initialized, &use_direct_type_ptr, + &direct_type_ptr, &is_finalizable)) { // The fast path. if (!use_direct_type_ptr) { LoadClassType(type_idx, kArg0); @@ -980,9 +981,11 @@ void Mir2Lir::GenNewInstance(uint32_t type_idx, RegLocation rl_dest) { bool is_type_initialized; bool use_direct_type_ptr; uintptr_t direct_type_ptr; + bool is_finalizable; if (kEmbedClassInCode && - driver->CanEmbedTypeInCode(*dex_file, type_idx, - &is_type_initialized, &use_direct_type_ptr, &direct_type_ptr)) { + driver->CanEmbedTypeInCode(*dex_file, type_idx, &is_type_initialized, &use_direct_type_ptr, + &direct_type_ptr, &is_finalizable) && + !is_finalizable) { // The fast path. if (!use_direct_type_ptr) { LoadClassType(type_idx, kArg0); diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 0ad30be3f..bde0fae83 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -905,13 +905,14 @@ bool CompilerDriver::CanAccessInstantiableTypeWithoutChecks(uint32_t referrer_id bool CompilerDriver::CanEmbedTypeInCode(const DexFile& dex_file, uint32_t type_idx, bool* is_type_initialized, bool* use_direct_type_ptr, - uintptr_t* direct_type_ptr) { + uintptr_t* direct_type_ptr, bool* out_is_finalizable) { ScopedObjectAccess soa(Thread::Current()); mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file); mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx); if (resolved_class == nullptr) { return false; } + *out_is_finalizable = resolved_class->IsFinalizable(); const bool compiling_boot = Runtime::Current()->GetHeap()->IsCompilingBoot(); if (compiling_boot) { // boot -> boot class pointers. diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index d7d40d554..6ac9cf751 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -210,7 +210,7 @@ class CompilerDriver { bool CanEmbedTypeInCode(const DexFile& dex_file, uint32_t type_idx, bool* is_type_initialized, bool* use_direct_type_ptr, - uintptr_t* direct_type_ptr); + uintptr_t* direct_type_ptr, bool* out_is_finalizable); // Get the DexCache for the mirror::DexCache* GetDexCache(const DexCompilationUnit* mUnit) diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h index 05912bfed..e52a8fbc3 100644 --- a/runtime/entrypoints/entrypoint_utils.h +++ b/runtime/entrypoints/entrypoint_utils.h @@ -132,8 +132,7 @@ ALWAYS_INLINE static inline mirror::Object* AllocObjectFromCode(uint32_t type_id if (klass == nullptr) { return nullptr; } - gc::Heap* heap = Runtime::Current()->GetHeap(); - return klass->Alloc(self, heap->GetCurrentAllocator()); + return klass->Alloc(self, Runtime::Current()->GetHeap()->GetCurrentAllocator()); } DCHECK(klass != nullptr); return klass->Alloc(self, allocator_type); @@ -155,9 +154,11 @@ ALWAYS_INLINE static inline mirror::Object* AllocObjectFromCodeResolved(mirror:: return nullptr; } gc::Heap* heap = Runtime::Current()->GetHeap(); - return klass->Alloc(self, heap->GetCurrentAllocator()); + // Pass in false since the object can not be finalizable. + return klass->Alloc(self, heap->GetCurrentAllocator()); } - return klass->Alloc(self, allocator_type); + // Pass in false since the object can not be finalizable. + return klass->Alloc(self, allocator_type); } // Given the context of a calling Method and an initialized class, create an instance. @@ -169,7 +170,8 @@ ALWAYS_INLINE static inline mirror::Object* AllocObjectFromCodeInitialized(mirro gc::AllocatorType allocator_type) NO_THREAD_SAFETY_ANALYSIS { DCHECK(klass != nullptr); - return klass->Alloc(self, allocator_type); + // Pass in false since the object can not be finalizable. + return klass->Alloc(self, allocator_type); } diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index 5d517bb72..ee1b21e93 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -2611,12 +2611,14 @@ void Heap::ClearGrowthLimit() { non_moving_space_->ClearGrowthLimit(); } -void Heap::AddFinalizerReference(Thread* self, mirror::Object* object) { +void Heap::AddFinalizerReference(Thread* self, mirror::Object** object) { ScopedObjectAccess soa(self); - ScopedLocalRef arg(self->GetJniEnv(), soa.AddLocalReference(object)); + ScopedLocalRef arg(self->GetJniEnv(), soa.AddLocalReference(*object)); jvalue args[1]; args[0].l = arg.get(); InvokeWithJValues(soa, nullptr, WellKnownClasses::java_lang_ref_FinalizerReference_add, args); + // Restore object in case it gets moved. + *object = soa.Decode(arg.get()); } void Heap::EnqueueClearedReferences() { diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h index d3b5cdc85..53f9d5f3c 100644 --- a/runtime/gc/heap.h +++ b/runtime/gc/heap.h @@ -380,7 +380,7 @@ class Heap { return card_table_.get(); } - void AddFinalizerReference(Thread* self, mirror::Object* object); + void AddFinalizerReference(Thread* self, mirror::Object** object); // Returns the number of bytes currently allocated. size_t GetBytesAllocated() const { diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h index 8a1f38385..8499a0d83 100644 --- a/runtime/mirror/class-inl.h +++ b/runtime/mirror/class-inl.h @@ -470,12 +470,21 @@ inline void Class::CheckObjectAlloc() { DCHECK_GE(this->object_size_, sizeof(Object)); } -template +template inline Object* Class::Alloc(Thread* self, gc::AllocatorType allocator_type) { CheckObjectAlloc(); gc::Heap* heap = Runtime::Current()->GetHeap(); - return heap->AllocObjectWithAllocator(self, this, this->object_size_, - allocator_type, VoidFunctor()); + const bool add_finalizer = kCheckAddFinalizer && IsFinalizable(); + if (!kCheckAddFinalizer) { + DCHECK(!IsFinalizable()); + } + mirror::Object* obj = + heap->AllocObjectWithAllocator(self, this, this->object_size_, + allocator_type, VoidFunctor()); + if (add_finalizer && LIKELY(obj != nullptr)) { + heap->AddFinalizerReference(self, &obj); + } + return obj; } inline Object* Class::AllocObject(Thread* self) { diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index 23211c205..21ecf5f8f 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -412,7 +412,7 @@ class MANAGED Class : public Object { } // Creates a raw object instance but does not invoke the default constructor. - template + template ALWAYS_INLINE Object* Alloc(Thread* self, gc::AllocatorType allocator_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc index 2cd71a041..2f775bc47 100644 --- a/runtime/mirror/object.cc +++ b/runtime/mirror/object.cc @@ -92,9 +92,7 @@ static Object* CopyObject(Thread* self, mirror::Object* dest, mirror::Object* sr heap->WriteBarrierEveryFieldOf(dest); } if (c->IsFinalizable()) { - SirtRef sirt_dest(self, dest); - heap->AddFinalizerReference(self, dest); - return sirt_dest.get(); + heap->AddFinalizerReference(self, &dest); } return dest; } diff --git a/runtime/oat.cc b/runtime/oat.cc index c1a48e913..4b4b3d003 100644 --- a/runtime/oat.cc +++ b/runtime/oat.cc @@ -22,7 +22,7 @@ namespace art { const uint8_t OatHeader::kOatMagic[] = { 'o', 'a', 't', '\n' }; -const uint8_t OatHeader::kOatVersion[] = { '0', '2', '2', '\0' }; +const uint8_t OatHeader::kOatVersion[] = { '0', '2', '3', '\0' }; OatHeader::OatHeader() { memset(this, 0, sizeof(*this)); -- 2.11.0