Index: src/vm/immutable_heap.cc |
diff --git a/src/vm/immutable_heap.cc b/src/vm/immutable_heap.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4ef1ebca6514cf8565fbe22afdce99e906cce4f0 |
--- /dev/null |
+++ b/src/vm/immutable_heap.cc |
@@ -0,0 +1,100 @@ |
+// Copyright (c) 2015, the Fletch project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE.md file. |
+ |
+#include "src/vm/immutable_heap.h" |
+#include "src/vm/object_memory.h" |
+ |
+namespace fletch { |
+ |
+ImmutableHeap::ImmutableHeap() |
+ : number_of_hw_threads_(Platform::GetNumberOfHardwareThreads()), |
+ heap_mutex_(Platform::CreateMutex()), |
+ heap_(new Space(), reinterpret_cast<WeakPointer*>(NULL)), |
+ outstanding_parts_(0), |
+ unmerged_parts_(), |
+ ticks_(0) { |
+} |
+ |
+ImmutableHeap::~ImmutableHeap() { |
+ delete heap_mutex_; |
+ |
+ while (HasUnmergedParts()) { |
+ Heap* heap = RemoveUnmergedPart(); |
+ delete heap; |
+ } |
+} |
+ |
+void ImmutableHeap::AddUnmergedPart(Heap* heap) { |
+ unmerged_parts_ = new HeapPart(unmerged_parts_); |
+ unmerged_parts_->heap_part = heap; |
+} |
+ |
+Heap* ImmutableHeap::RemoveUnmergedPart() { |
+ HeapPart* part = unmerged_parts_; |
+ if (part == NULL) return NULL; |
+ |
+ Heap* heap = part->heap_part; |
+ unmerged_parts_ = part->next; |
+ delete part; |
+ return heap; |
+} |
+ |
+void ImmutableHeap::MergeParts() { |
+ ScopedLock locker(heap_mutex_); |
+ |
+ ASSERT(outstanding_parts_ == 0); |
+ while (HasUnmergedParts()) { |
+ Heap* heap_part = RemoveUnmergedPart(); |
+ heap_.MergeInOtherHeap(heap_part); |
+ delete heap_part; |
+ } |
+ |
+ ticks_ = 0; |
+} |
+ |
+void ImmutableHeap::IterateProgramPointers(PointerVisitor* visitor) { |
+ ASSERT(outstanding_parts_ == 0 && unmerged_parts_ == NULL); |
+ |
+ HeapObjectPointerVisitor heap_pointer_visitor(visitor); |
+ heap_.IterateObjects(&heap_pointer_visitor); |
+} |
+ |
+Heap* ImmutableHeap::AcquirePart() { |
+ ScopedLock locker(heap_mutex_); |
+ |
+ // Calculate new allocation budget we want to give out. |
+ Space* merged_space = heap_.space(); |
+ int size = 0; |
+ if (merged_space != NULL && !merged_space->is_empty()) { |
+ // We allow each thread to get the amount of live memory per |
+ // thread (i.e. a "2x of live memory" heap size strategy). |
+ size = merged_space->Used() / number_of_hw_threads_; |
+ } |
+ int budget = Utils::Maximum(size, Space::kDefaultChunkSize); |
+ |
+ Heap* part; |
+ if (HasUnmergedParts()) { |
+ part = RemoveUnmergedPart(); |
+ part->space()->SetAllocationBudget(budget); |
+ } else { |
+ part = new Heap(NULL, budget); |
+ } |
+ |
+ outstanding_parts_++; |
+ return part; |
+} |
+ |
+bool ImmutableHeap::ReleasePart(Heap* part) { |
+ ScopedLock locker(heap_mutex_); |
+ ASSERT(outstanding_parts_ > 0); |
+ outstanding_parts_--; |
+ |
+ part->Flush(); |
+ part->AdjustAllocationBudget(); |
+ AddUnmergedPart(part); |
+ |
+ return ticks_++ == number_of_hw_threads_; |
+} |
+ |
+} // namespace fletch |