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/class_linker.cc b/src/class_linker.cc
index 6ebc638..2c69651 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -474,16 +474,18 @@
// as the types of the field can't be resolved prior to the runtime being
// fully initialized
Class* java_lang_ref_Reference = FindSystemClass("Ljava/lang/ref/Reference;");
+ Class* java_lang_ref_ReferenceQueue = FindSystemClass("Ljava/lang/ref/ReferenceQueue;");
Class* java_lang_ref_FinalizerReference = FindSystemClass("Ljava/lang/ref/FinalizerReference;");
+ Heap::SetWellKnownClasses(java_lang_ref_FinalizerReference, java_lang_ref_ReferenceQueue);
+
Field* pendingNext = java_lang_ref_Reference->GetInstanceField(0);
CHECK(pendingNext->GetName()->Equals("pendingNext"));
CHECK_EQ(ResolveType(pendingNext->GetTypeIdx(), pendingNext), java_lang_ref_Reference);
Field* queue = java_lang_ref_Reference->GetInstanceField(1);
CHECK(queue->GetName()->Equals("queue"));
- CHECK_EQ(ResolveType(queue->GetTypeIdx(), queue),
- FindSystemClass("Ljava/lang/ref/ReferenceQueue;"));
+ CHECK_EQ(ResolveType(queue->GetTypeIdx(), queue), java_lang_ref_ReferenceQueue);
Field* queueNext = java_lang_ref_Reference->GetInstanceField(2);
CHECK(queueNext->GetName()->Equals("queueNext"));
@@ -2108,7 +2110,7 @@
CHECK_EQ(num_fields == 0, fields == NULL);
// we want a relatively stable order so that adding new fields
- // minimizes distruption of C++ version such as Class and Method.
+ // minimizes disruption of C++ version such as Class and Method.
std::deque<Field*> grouped_and_sorted_fields;
for (size_t i = 0; i < num_fields; i++) {
grouped_and_sorted_fields.push_back(fields->Get(i));
@@ -2175,6 +2177,15 @@
current_field++;
}
+ // We lie to the GC about the java.lang.ref.Reference.referent field, so it doesn't scan it.
+ if (instance && klass->GetDescriptor()->Equals("Ljava/lang/ref/Reference;")) {
+ // We know there are no non-reference fields in the Reference classes, and we know
+ // that 'referent' is alphabetically last, so this is easy...
+ CHECK_EQ(num_reference_fields, num_fields);
+ CHECK(fields->Get(num_fields - 1)->GetName()->Equals("referent"));
+ --num_reference_fields;
+ }
+
#ifndef NDEBUG
// Make sure that all reference fields appear before
// non-reference fields, and all double-wide fields are aligned.
@@ -2188,7 +2199,11 @@
<< " offset=" << field->GetField32(MemberOffset(Field::OffsetOffset()), false);
}
const Class* type = field->GetTypeDuringLinking();
- if (type != NULL && type->IsPrimitive()) {
+ bool is_primitive = (type != NULL && type->IsPrimitive());
+ if (klass->GetDescriptor()->Equals("Ljava/lang/ref/Reference;") && field->GetName()->Equals("referent")) {
+ is_primitive = true; // We lied above, so we have to expect a lie here.
+ }
+ if (is_primitive) {
if (!seen_non_ref) {
seen_non_ref = true;
DCHECK_EQ(num_reference_fields, i);