Add allocation and garbage collection infrastructure.
Change-Id: I4b04cdfdf18afb75a7b0df87b509e8156b4a932b
diff --git a/src/heap.cc b/src/heap.cc
new file mode 100644
index 0000000..bbdf80a
--- /dev/null
+++ b/src/heap.cc
@@ -0,0 +1,163 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+// Author: cshapiro@google.com (Carl Shapiro)
+
+#include "src/heap.h"
+#include "src/object.h"
+#include "src/space.h"
+
+namespace art {
+
+Space* Heap::space_ = NULL;
+
+size_t Heap::startup_size_ = 0;
+
+size_t Heap::maximum_size_ = 0;
+
+bool Heap::is_gc_running_ = false;
+
+HeapBitmap* Heap::mark_bitmap_ = NULL;
+
+HeapBitmap* Heap::live_bitmap_ = NULL;
+
+bool Heap::Init(size_t startup_size, size_t maximum_size) {
+ space_ = Space::Create(startup_size, maximum_size);
+ if (space_ == NULL) {
+ return false;
+ }
+
+ byte* base = space_->GetBase();
+ size_t num_bytes = space_->Size();
+
+ // Allocate the initial live bitmap.
+ scoped_ptr<HeapBitmap> live_bitmap(HeapBitmap::Create(base, num_bytes));
+ if (live_bitmap == NULL) {
+ return false;
+ }
+
+ // Allocate the initial mark bitmap.
+ scoped_ptr<HeapBitmap> mark_bitmap(HeapBitmap::Create(base, num_bytes));
+ if (mark_bitmap == NULL) {
+ return false;
+ }
+
+ startup_size_ = startup_size;
+ maximum_size_ = maximum_size;
+ live_bitmap_ = live_bitmap.release();
+ mark_bitmap_ = mark_bitmap.release();
+
+ // TODO: allocate the card table
+
+ return true;
+}
+
+void Heap::Destroy() {
+ delete space_;
+ delete mark_bitmap_;
+ delete live_bitmap_;
+}
+
+Object* Heap::Allocate(size_t size) {
+ // Fail impossible allocations. TODO: collect soft references.
+ if (size > maximum_size_) {
+ return NULL;
+ }
+
+ Object* ptr = space_->AllocWithoutGrowth(size);
+ if (ptr != NULL) {
+ return ptr;
+ }
+
+ // The allocation failed. If the GC is running, block until it
+ // completes and retry.
+ if (is_gc_running_) {
+ // The GC is concurrently tracing the heap. Release the heap
+ // lock, wait for the GC to complete, and retrying allocating.
+ WaitForConcurrentGcToComplete();
+ ptr = space_->AllocWithoutGrowth(size);
+ if (ptr != NULL) {
+ return ptr;
+ }
+ }
+
+ // Another failure. Our thread was starved or there may be too many
+ // live objects. Try a foreground GC. This will have no effect if
+ // the concurrent GC is already running.
+ CollectGarbage();
+ ptr = space_->AllocWithoutGrowth(size);
+ if (ptr != NULL) {
+ return ptr;
+ }
+
+ // Even that didn't work; this is an exceptional state.
+ // Try harder, growing the heap if necessary.
+ ptr = space_->AllocWithGrowth(size);
+ if (ptr != NULL) {
+ //size_t new_footprint = dvmHeapSourceGetIdealFootprint();
+ size_t new_footprint = space_->MaxAllowedFootprint();
+ //TODO: may want to grow a little bit more so that the amount of free
+ // space is equal to the old free space + the utilization slop for
+ // the new allocation.
+ // LOGI_HEAP("Grow heap (frag case) to "
+ // "%zu.%03zuMB for %zu-byte allocation",
+ // FRACTIONAL_MB(newHeapSize), size);
+ LOG(INFO) << "Grow heap (frag case) to " << new_footprint
+ << "for " << size << "-byte allocation";
+ return ptr;
+ }
+
+ // Most allocations should have succeeded by now, so the heap is
+ // really full, really fragmented, or the requested size is really
+ // big. Do another GC, collecting SoftReferences this time. The VM
+ // spec requires that all SoftReferences have been collected and
+ // cleared before throwing an OOME.
+
+ //TODO: wait for the finalizers from the previous GC to finish
+ //collect_soft_refs:
+ LOG(INFO) << "Forcing collection of SoftReferences for "
+ << size << "-byte allocation";
+ //gcForMalloc(true);
+ CollectGarbage();
+ ptr = space_->AllocWithGrowth(size);
+ if (ptr != NULL) {
+ return ptr;
+ }
+ //TODO: maybe wait for finalizers and try one last time
+
+ //LOGE_HEAP("Out of memory on a %zd-byte allocation.", size);
+ LOG(ERROR) << "Out of memory on a " << size << " byte allocation";
+
+ //TODO: tell the HeapSource to dump its state
+ //dvmDumpThread(dvmThreadSelf(), false);
+
+ // TODO: stack trace
+ return NULL;
+}
+
+String* Heap::AllocStringFromModifiedUtf8(Class* java_lang_String,
+ Class* char_array,
+ const char* data) {
+ String* string = AllocString(java_lang_String);
+ uint32_t count = strlen(data); // TODO
+ CharArray* array = AllocCharArray(char_array, count);
+ string->array_ = array;
+ string->count_ = count;
+ return string;
+}
+
+void Heap::CollectGarbage() {
+}
+
+void Heap::CollectGarbageInternal() {
+}
+
+void Heap::WaitForConcurrentGcToComplete() {
+}
+
+// Given the current contents of the active heap, increase the allowed
+// heap footprint to match the target utilization ratio. This should
+// only be called immediately after a full garbage collection.
+void Heap::GrowForUtilization() {
+ LOG(FATAL) << "Unimplemented";
+}
+
+} // namespace art