Implement finalization.

Also make System.gc no longer a no-op. This replaces some of the
MemberOffsets exposed by Heap with intention-revealing functions
that we'll want to share between all the actual GC implementations,
but there's still more to be done.

Change-Id: I57ba26c0416fbbfe20142b7b6e27108684add7f9
diff --git a/src/heap.h b/src/heap.h
index 76e33b5..1eb3b16 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -112,37 +112,23 @@
     return mark_bitmap_;
   }
 
+  static void SetWellKnownClasses(Class* java_lang_ref_FinalizerReference,
+      Class* java_lang_ref_ReferenceQueue);
+
   static void SetReferenceOffsets(MemberOffset reference_referent_offset,
                                   MemberOffset reference_queue_offset,
                                   MemberOffset reference_queueNext_offset,
                                   MemberOffset reference_pendingNext_offset,
-                                  MemberOffset finalizer_reference_zombie_offset) {
-    CHECK_NE(reference_referent_offset.Uint32Value(), 0U);
-    CHECK_NE(reference_queue_offset.Uint32Value(), 0U);
-    CHECK_NE(reference_queueNext_offset.Uint32Value(), 0U);
-    CHECK_NE(reference_pendingNext_offset.Uint32Value(), 0U);
-    CHECK_NE(finalizer_reference_zombie_offset.Uint32Value(), 0U);
-    reference_referent_offset_ = reference_referent_offset;
-    reference_queue_offset_ = reference_queue_offset;
-    reference_queueNext_offset_ = reference_queueNext_offset;
-    reference_pendingNext_offset_ = reference_pendingNext_offset;
-    finalizer_reference_zombie_offset_ = finalizer_reference_zombie_offset;
-  }
+                                  MemberOffset finalizer_reference_zombie_offset);
 
-  static MemberOffset GetReferenceReferentOffset() {
-    DCHECK_NE(reference_referent_offset_.Uint32Value(), 0U);
-    return reference_referent_offset_;
-  }
+  static Object* GetReferenceReferent(Object* reference);
+  static void ClearReferenceReferent(Object* reference);
 
-  static MemberOffset GetReferenceQueueOffset() {
-    DCHECK_NE(reference_queue_offset_.Uint32Value(), 0U);
-    return reference_queue_offset_;
-  }
-
-  static MemberOffset GetReferenceQueueNextOffset() {
-    DCHECK_NE(reference_queueNext_offset_.Uint32Value(), 0U);
-    return reference_queueNext_offset_;
-  }
+  // Returns true if the reference object has not yet been enqueued.
+  static bool IsEnqueuable(const Object* ref);
+  static void EnqueueReference(Object* ref, Object** list);
+  static void EnqueuePendingReference(Object* ref, Object** list);
+  static Object* DequeuePendingReference(Object** list);
 
   static MemberOffset GetReferencePendingNextOffset() {
     DCHECK_NE(reference_pendingNext_offset_.Uint32Value(), 0U);
@@ -174,11 +160,16 @@
 #endif
   }
 
+  static void AddFinalizerReference(Object* object);
+
  private:
   // Allocates uninitialized storage.
   static Object* AllocateLocked(size_t num_bytes);
   static Object* AllocateLocked(Space* space, size_t num_bytes);
 
+  // Pushes a list of cleared references out to the managed heap.
+  static void EnqueueClearedReferences(Object** cleared_references);
+
   static void RecordAllocationLocked(Space* space, const Object* object);
   static void RecordImageAllocations(Space* space);
 
@@ -215,6 +206,9 @@
   // free.
   static size_t num_objects_allocated_;
 
+  static Class* java_lang_ref_FinalizerReference_;
+  static Class* java_lang_ref_ReferenceQueue_;
+
   // offset of java.lang.ref.Reference.referent
   static MemberOffset reference_referent_offset_;