OSDN Git Service

Add finalizer references from the entrypoints.
authorMathieu Chartier <mathieuc@google.com>
Thu, 24 Apr 2014 23:48:11 +0000 (16:48 -0700)
committerMathieu Chartier <mathieuc@google.com>
Fri, 2 May 2014 00:46:45 +0000 (17:46 -0700)
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
compiler/driver/compiler_driver.cc
compiler/driver/compiler_driver.h
runtime/entrypoints/entrypoint_utils.h
runtime/gc/heap.cc
runtime/gc/heap.h
runtime/mirror/class-inl.h
runtime/mirror/class.h
runtime/mirror/object.cc
runtime/oat.cc

index 8b9a686..3cc2ba0 100644 (file)
@@ -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);
index 0ad30be..bde0fae 100644 (file)
@@ -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.
index d7d40d5..6ac9cf7 100644 (file)
@@ -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)
index 05912bf..e52a8fb 100644 (file)
@@ -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<kInstrumented>(self, heap->GetCurrentAllocator());
+    return klass->Alloc<kInstrumented>(self, Runtime::Current()->GetHeap()->GetCurrentAllocator());
   }
   DCHECK(klass != nullptr);
   return klass->Alloc<kInstrumented>(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<kInstrumented>(self, heap->GetCurrentAllocator());
+    // Pass in false since the object can not be finalizable.
+    return klass->Alloc<kInstrumented, false>(self, heap->GetCurrentAllocator());
   }
-  return klass->Alloc<kInstrumented>(self, allocator_type);
+  // Pass in false since the object can not be finalizable.
+  return klass->Alloc<kInstrumented, false>(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<kInstrumented>(self, allocator_type);
+  // Pass in false since the object can not be finalizable.
+  return klass->Alloc<kInstrumented, false>(self, allocator_type);
 }
 
 
index 5d517bb..ee1b21e 100644 (file)
@@ -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<jobject> arg(self->GetJniEnv(), soa.AddLocalReference<jobject>(object));
+  ScopedLocalRef<jobject> arg(self->GetJniEnv(), soa.AddLocalReference<jobject>(*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<mirror::Object*>(arg.get());
 }
 
 void Heap::EnqueueClearedReferences() {
index d3b5cdc..53f9d5f 100644 (file)
@@ -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 {
index 8a1f383..8499a0d 100644 (file)
@@ -470,12 +470,21 @@ inline void Class::CheckObjectAlloc() {
   DCHECK_GE(this->object_size_, sizeof(Object));
 }
 
-template <bool kIsInstrumented>
+template<bool kIsInstrumented, bool kCheckAddFinalizer>
 inline Object* Class::Alloc(Thread* self, gc::AllocatorType allocator_type) {
   CheckObjectAlloc();
   gc::Heap* heap = Runtime::Current()->GetHeap();
-  return heap->AllocObjectWithAllocator<kIsInstrumented, false>(self, this, this->object_size_,
-                                                                allocator_type, VoidFunctor());
+  const bool add_finalizer = kCheckAddFinalizer && IsFinalizable();
+  if (!kCheckAddFinalizer) {
+    DCHECK(!IsFinalizable());
+  }
+  mirror::Object* obj =
+      heap->AllocObjectWithAllocator<kIsInstrumented, false>(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) {
index 23211c2..21ecf5f 100644 (file)
@@ -412,7 +412,7 @@ class MANAGED Class : public Object {
   }
 
   // Creates a raw object instance but does not invoke the default constructor.
-  template <bool kIsInstrumented>
+  template<bool kIsInstrumented, bool kCheckAddFinalizer = true>
   ALWAYS_INLINE Object* Alloc(Thread* self, gc::AllocatorType allocator_type)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
index 2cd71a0..2f775bc 100644 (file)
@@ -92,9 +92,7 @@ static Object* CopyObject(Thread* self, mirror::Object* dest, mirror::Object* sr
     heap->WriteBarrierEveryFieldOf(dest);
   }
   if (c->IsFinalizable()) {
-    SirtRef<Object> sirt_dest(self, dest);
-    heap->AddFinalizerReference(self, dest);
-    return sirt_dest.get();
+    heap->AddFinalizerReference(self, &dest);
   }
   return dest;
 }
index c1a48e9..4b4b3d0 100644 (file)
@@ -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));