Add HeapTest and make GC work enough to pass it
Change-Id: If06eaef2921b64b3226bfd347acaec60ec993e67
diff --git a/src/mark_sweep.cc b/src/mark_sweep.cc
index eb81cf6..b803c48 100644
--- a/src/mark_sweep.cc
+++ b/src/mark_sweep.cc
@@ -10,17 +10,13 @@
#include "macros.h"
#include "mark_stack.h"
#include "object.h"
+#include "class_loader.h"
+#include "runtime.h"
#include "space.h"
#include "thread.h"
namespace art {
-size_t MarkSweep::reference_referent_offset_ = 0; // TODO
-size_t MarkSweep::reference_queue_offset_ = 0; // TODO
-size_t MarkSweep::reference_queueNext_offset_ = 0; // TODO
-size_t MarkSweep::reference_pendingNext_offset_ = 0; // TODO
-size_t MarkSweep::finalizer_reference_zombie_offset_ = 0; // TODO
-
bool MarkSweep::Init() {
mark_stack_ = MarkStack::Create();
if (mark_stack_ == NULL) {
@@ -65,9 +61,16 @@
}
}
+void MarkSweep::MarkObjectVisitor(Object* root, void* arg) {
+ DCHECK(root != NULL);
+ DCHECK(arg != NULL);
+ MarkSweep* mark_sweep = reinterpret_cast<MarkSweep*>(arg);
+ mark_sweep->MarkObject0(root, true);
+}
+
// Marks all objects in the root set.
void MarkSweep::MarkRoots() {
- UNIMPLEMENTED(FATAL);
+ Runtime::Current()->VisitRoots(MarkObjectVisitor, this);
}
void MarkSweep::ScanBitmapCallback(Object* obj, void* finger, void* arg) {
@@ -79,13 +82,21 @@
// Populates the mark stack based on the set of marked objects and
// recursively marks until the mark stack is emptied.
void MarkSweep::RecursiveMark() {
+
+ // RecursiveMark will build the lists of known instances of the Reference classes.
+ // See DelayReferenceReferent for details.
+ CHECK(soft_reference_list_ == NULL);
+ CHECK(weak_reference_list_ == NULL);
+ CHECK(finalizer_reference_list_ == NULL);
+ CHECK(phantom_reference_list_ == NULL);
+ CHECK(cleared_reference_list_ == NULL);
+
void* arg = reinterpret_cast<void*>(this);
const std::vector<Space*>& spaces = Heap::GetSpaces();
for (size_t i = 0; i < spaces.size(); ++i) {
if (spaces[i]->IsCondemned()) {
uintptr_t base = reinterpret_cast<uintptr_t>(spaces[i]->GetBase());
- uintptr_t limit = reinterpret_cast<uintptr_t>(spaces[i]->GetLimit());
- mark_bitmap_->ScanWalk(base, limit, &MarkSweep::ScanBitmapCallback, arg);
+ mark_bitmap_->ScanWalk(base, &MarkSweep::ScanBitmapCallback, arg);
}
}
finger_ = reinterpret_cast<Object*>(~0);
@@ -224,7 +235,7 @@
void MarkSweep::EnqueuePendingReference(Object* ref, Object** list) {
DCHECK(ref != NULL);
DCHECK(list != NULL);
- size_t offset = reference_pendingNext_offset_;
+ size_t offset = Heap::GetReferencePendingNextOffset();
if (*list == NULL) {
ref->SetFieldObject(offset, ref);
*list = ref;
@@ -238,7 +249,7 @@
Object* MarkSweep::DequeuePendingReference(Object** list) {
DCHECK(list != NULL);
DCHECK(*list != NULL);
- size_t offset = reference_pendingNext_offset_;
+ size_t offset = Heap::GetReferencePendingNextOffset();
Object* head = (*list)->GetFieldObject(offset);
Object* ref;
if (*list == head) {
@@ -258,19 +269,20 @@
// the gcHeap for later processing.
void MarkSweep::DelayReferenceReferent(Object* obj) {
DCHECK(obj != NULL);
- DCHECK(obj->GetClass() != NULL);
- DCHECK(obj->IsReference());
- Object* pending = obj->GetFieldObject(reference_pendingNext_offset_);
- Object* referent = obj->GetFieldObject(reference_referent_offset_);
+ Class* klass = obj->GetClass();
+ DCHECK(klass != NULL);
+ DCHECK(klass->IsReference());
+ Object* pending = obj->GetFieldObject(Heap::GetReferencePendingNextOffset());
+ Object* referent = obj->GetFieldObject(Heap::GetReferenceReferentOffset());
if (pending == NULL && referent != NULL && !IsMarked(referent)) {
Object** list = NULL;
- if (obj->IsSoftReference()) {
+ if (klass->IsSoftReference()) {
list = &soft_reference_list_;
- } else if (obj->IsWeakReference()) {
+ } else if (klass->IsWeakReference()) {
list = &weak_reference_list_;
- } else if (obj->IsFinalizerReference()) {
+ } else if (klass->IsFinalizerReference()) {
list = &finalizer_reference_list_;
- } else if (obj->IsPhantomReference()) {
+ } else if (klass->IsPhantomReference()) {
list = &phantom_reference_list_;
}
DCHECK(list != NULL);
@@ -283,10 +295,11 @@
// processing
void MarkSweep::ScanOther(const Object* obj) {
DCHECK(obj != NULL);
- DCHECK(obj->GetClass() != NULL);
- MarkObject(obj->GetClass());
+ Class* klass = obj->GetClass();
+ DCHECK(klass != NULL);
+ MarkObject(klass);
ScanInstanceFields(obj);
- if (obj->IsReference()) {
+ if (klass->IsReference()) {
DelayReferenceReferent(const_cast<Object*>(obj));
}
}
@@ -321,20 +334,20 @@
void MarkSweep::ClearReference(Object* ref) {
DCHECK(ref != NULL);
- ref->SetFieldObject(reference_referent_offset_, NULL);
+ ref->SetFieldObject(Heap::GetReferenceReferentOffset(), NULL);
}
bool MarkSweep::IsEnqueuable(const Object* ref) {
DCHECK(ref != NULL);
- const Object* queue = ref->GetFieldObject(reference_queue_offset_);
- const Object* queue_next = ref->GetFieldObject(reference_queueNext_offset_);
+ const Object* queue = ref->GetFieldObject(Heap::GetReferenceQueueOffset());
+ const Object* queue_next = ref->GetFieldObject(Heap::GetReferenceQueueNextOffset());
return (queue != NULL) && (queue_next == NULL);
}
void MarkSweep::EnqueueReference(Object* ref) {
DCHECK(ref != NULL);
- CHECK(ref->GetFieldObject(reference_queue_offset_) != NULL);
- CHECK(ref->GetFieldObject(reference_queueNext_offset_) == NULL);
+ CHECK(ref->GetFieldObject(Heap::GetReferenceQueueOffset()) != NULL);
+ CHECK(ref->GetFieldObject(Heap::GetReferenceQueueNextOffset()) == NULL);
EnqueuePendingReference(ref, &cleared_reference_list_);
}
@@ -348,7 +361,7 @@
size_t counter = 0;
while (*list != NULL) {
Object* ref = DequeuePendingReference(list);
- Object* referent = ref->GetFieldObject(reference_referent_offset_);
+ Object* referent = ref->GetFieldObject(Heap::GetReferenceReferentOffset());
if (referent == NULL) {
// Referent was cleared by the user during marking.
continue;
@@ -375,7 +388,7 @@
// scheduled for appending by the heap worker thread.
void MarkSweep::ClearWhiteReferences(Object** list) {
DCHECK(list != NULL);
- size_t offset = reference_referent_offset_;
+ size_t offset = Heap::GetReferenceReferentOffset();
while (*list != NULL) {
Object* ref = DequeuePendingReference(list);
Object* referent = ref->GetFieldObject(offset);
@@ -395,8 +408,8 @@
// referent field is cleared.
void MarkSweep::EnqueueFinalizerReferences(Object** list) {
DCHECK(list != NULL);
- size_t referent_offset = reference_referent_offset_;
- size_t zombie_offset = finalizer_reference_zombie_offset_;
+ size_t referent_offset = Heap::GetReferenceReferentOffset();
+ size_t zombie_offset = Heap::GetFinalizerReferenceZombieOffset();
bool has_enqueued = false;
while (*list != NULL) {
Object* ref = DequeuePendingReference(list);