Refactor the compilers out of libart.
This builds three separate compilers and dynamically links with the right one
at runtime.
Change-Id: I59d22b9884f41de733c09f97e29ee290236d5f4b
diff --git a/src/mark_sweep.cc b/src/mark_sweep.cc
index 952bf85..e5e0835 100644
--- a/src/mark_sweep.cc
+++ b/src/mark_sweep.cc
@@ -38,8 +38,10 @@
void MarkSweep::Init() {
mark_stack_ = MarkStack::Create();
- mark_bitmap_ = Heap::GetMarkBits();
- live_bitmap_ = Heap::GetLiveBits();
+
+ heap_ = Runtime::Current()->GetHeap();
+ mark_bitmap_ = heap_->GetMarkBits();
+ live_bitmap_ = heap_->GetLiveBits();
// TODO: if concurrent, clear the card table.
@@ -100,8 +102,8 @@
// Marks all objects that are in images and have been touched by the mutator
void MarkSweep::ScanDirtyImageRoots() {
- const std::vector<Space*>& spaces = Heap::GetSpaces();
- CardTable* card_table = Heap::GetCardTable();
+ const std::vector<Space*>& spaces = heap_->GetSpaces();
+ CardTable* card_table = heap_->GetCardTable();
for (size_t i = 0; i < spaces.size(); ++i) {
if (spaces[i]->IsImageSpace()) {
byte* begin = spaces[i]->Begin();
@@ -135,7 +137,7 @@
CHECK(cleared_reference_list_ == NULL);
void* arg = reinterpret_cast<void*>(this);
- const std::vector<Space*>& spaces = Heap::GetSpaces();
+ const std::vector<Space*>& spaces = heap_->GetSpaces();
for (size_t i = 0; i < spaces.size(); ++i) {
#ifndef NDEBUG
uintptr_t begin = reinterpret_cast<uintptr_t>(spaces[i]->Begin());
@@ -181,11 +183,18 @@
SweepJniWeakGlobals();
}
+struct SweepCallbackContext {
+ Heap* heap;
+ AllocSpace* space;
+};
+
void MarkSweep::SweepCallback(size_t num_ptrs, Object** ptrs, void* arg) {
// TODO: lock heap if concurrent
size_t freed_objects = num_ptrs;
size_t freed_bytes = 0;
- AllocSpace* space = static_cast<AllocSpace*>(arg);
+ SweepCallbackContext* context = static_cast<SweepCallbackContext*>(arg);
+ Heap* heap = context->heap;
+ AllocSpace* space = context->space;
// Use a bulk free, that merges consecutive objects before freeing or free per object?
// Documentation suggests better free performance with merging, but this may be at the expensive
// of allocation.
@@ -195,7 +204,7 @@
for (size_t i = 0; i < num_ptrs; ++i) {
Object* obj = static_cast<Object*>(ptrs[i]);
freed_bytes += space->AllocationSize(obj);
- Heap::GetLiveBits()->Clear(obj);
+ heap->GetLiveBits()->Clear(obj);
}
// AllocSpace::FreeList clears the value in ptrs, so perform after clearing the live bit
space->FreeList(num_ptrs, ptrs);
@@ -203,25 +212,27 @@
for (size_t i = 0; i < num_ptrs; ++i) {
Object* obj = static_cast<Object*>(ptrs[i]);
freed_bytes += space->AllocationSize(obj);
- Heap::GetLiveBits()->Clear(obj);
+ heap->GetLiveBits()->Clear(obj);
space->Free(obj);
}
}
- Heap::RecordFreeLocked(freed_objects, freed_bytes);
+ heap->RecordFreeLocked(freed_objects, freed_bytes);
// TODO: unlock heap if concurrent
}
void MarkSweep::Sweep() {
SweepSystemWeaks();
- const std::vector<Space*>& spaces = Heap::GetSpaces();
+ const std::vector<Space*>& spaces = heap_->GetSpaces();
+ SweepCallbackContext scc;
+ scc.heap = heap_;
for (size_t i = 0; i < spaces.size(); ++i) {
if (!spaces[i]->IsImageSpace()) {
uintptr_t begin = reinterpret_cast<uintptr_t>(spaces[i]->Begin());
uintptr_t end = reinterpret_cast<uintptr_t>(spaces[i]->End());
- void* arg = static_cast<void*>(spaces[i]);
+ scc.space = spaces[i]->AsAllocSpace();
HeapBitmap::SweepWalk(*live_bitmap_, *mark_bitmap_, begin, end,
- &MarkSweep::SweepCallback, arg);
+ &MarkSweep::SweepCallback, reinterpret_cast<void*>(&scc));
}
}
}
@@ -283,7 +294,7 @@
}
inline void MarkSweep::CheckReference(const Object* obj, const Object* ref, MemberOffset offset, bool is_static) {
- AllocSpace* alloc_space = Heap::GetAllocSpace();
+ AllocSpace* alloc_space = heap_->GetAllocSpace();
if (alloc_space->Contains(ref)) {
bool is_marked = mark_bitmap_->Test(ref);
if(!is_marked) {
@@ -292,7 +303,7 @@
<< "' (" << (void*)ref << ") in '" << PrettyTypeOf(obj)
<< "' (" << (void*)obj << ") at offset "
<< (void*)offset.Int32Value() << " wasn't marked";
- bool obj_marked = Heap::GetCardTable()->IsDirty(obj);
+ bool obj_marked = heap_->GetCardTable()->IsDirty(obj);
if (!obj_marked) {
LOG(WARNING) << "Object '" << PrettyTypeOf(obj) << "' (" << (void*)obj
<< ") contains references to the alloc space, but wasn't card marked";
@@ -386,8 +397,8 @@
Class* klass = obj->GetClass();
DCHECK(klass != NULL);
DCHECK(klass->IsReferenceClass());
- Object* pending = obj->GetFieldObject<Object*>(Heap::GetReferencePendingNextOffset(), false);
- Object* referent = Heap::GetReferenceReferent(obj);
+ Object* pending = obj->GetFieldObject<Object*>(heap_->GetReferencePendingNextOffset(), false);
+ Object* referent = heap_->GetReferenceReferent(obj);
if (pending == NULL && referent != NULL && !IsMarked(referent)) {
Object** list = NULL;
if (klass->IsSoftReferenceClass()) {
@@ -400,7 +411,7 @@
list = &phantom_reference_list_;
}
DCHECK(list != NULL) << PrettyClass(klass) << " " << std::hex << klass->GetAccessFlags();
- Heap::EnqueuePendingReference(obj, list);
+ heap_->EnqueuePendingReference(obj, list);
}
}
@@ -452,7 +463,7 @@
// Scan anything that's on the mark stack.
void MarkSweep::ProcessMarkStack() {
- Space* alloc_space = Heap::GetAllocSpace();
+ Space* alloc_space = heap_->GetAllocSpace();
while (!mark_stack_->IsEmpty()) {
const Object* obj = mark_stack_->Pop();
if (alloc_space->Contains(obj)) {
@@ -474,8 +485,8 @@
Object* clear = NULL;
size_t counter = 0;
while (*list != NULL) {
- Object* ref = Heap::DequeuePendingReference(list);
- Object* referent = Heap::GetReferenceReferent(ref);
+ Object* ref = heap_->DequeuePendingReference(list);
+ Object* referent = heap_->GetReferenceReferent(ref);
if (referent == NULL) {
// Referent was cleared by the user during marking.
continue;
@@ -488,7 +499,7 @@
}
if (!is_marked) {
// Referent is white, queue it for clearing.
- Heap::EnqueuePendingReference(ref, &clear);
+ heap_->EnqueuePendingReference(ref, &clear);
}
}
*list = clear;
@@ -503,13 +514,13 @@
void MarkSweep::ClearWhiteReferences(Object** list) {
DCHECK(list != NULL);
while (*list != NULL) {
- Object* ref = Heap::DequeuePendingReference(list);
- Object* referent = Heap::GetReferenceReferent(ref);
+ Object* ref = heap_->DequeuePendingReference(list);
+ Object* referent = heap_->GetReferenceReferent(ref);
if (referent != NULL && !IsMarked(referent)) {
// Referent is white, clear it.
- Heap::ClearReferenceReferent(ref);
- if (Heap::IsEnqueuable(ref)) {
- Heap::EnqueueReference(ref, &cleared_reference_list_);
+ heap_->ClearReferenceReferent(ref);
+ if (heap_->IsEnqueuable(ref)) {
+ heap_->EnqueueReference(ref, &cleared_reference_list_);
}
}
}
@@ -521,18 +532,18 @@
// referent field is cleared.
void MarkSweep::EnqueueFinalizerReferences(Object** list) {
DCHECK(list != NULL);
- MemberOffset zombie_offset = Heap::GetFinalizerReferenceZombieOffset();
+ MemberOffset zombie_offset = heap_->GetFinalizerReferenceZombieOffset();
bool has_enqueued = false;
while (*list != NULL) {
- Object* ref = Heap::DequeuePendingReference(list);
- Object* referent = Heap::GetReferenceReferent(ref);
+ Object* ref = heap_->DequeuePendingReference(list);
+ Object* referent = heap_->GetReferenceReferent(ref);
if (referent != NULL && !IsMarked(referent)) {
MarkObject(referent);
// If the referent is non-null the reference must queuable.
- DCHECK(Heap::IsEnqueuable(ref));
+ DCHECK(heap_->IsEnqueuable(ref));
ref->SetFieldObject(zombie_offset, referent, false);
- Heap::ClearReferenceReferent(ref);
- Heap::EnqueueReference(ref, &cleared_reference_list_);
+ heap_->ClearReferenceReferent(ref);
+ heap_->EnqueueReference(ref, &cleared_reference_list_);
has_enqueued = true;
}
}