blob: 6ec6aac1d997685fff9a95b8c8be35c56e95ed71 [file] [log] [blame]
Carl Shapiro69759ea2011-07-21 18:13:35 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2// Author: cshapiro@google.com (Carl Shapiro)
3
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07004#include "heap.h"
Carl Shapiro58551df2011-07-24 03:09:51 -07005
6#include <vector>
7
8#include "mark_sweep.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07009#include "object.h"
10#include "space.h"
Carl Shapiro58551df2011-07-24 03:09:51 -070011#include "stl_util.h"
Carl Shapiro69759ea2011-07-21 18:13:35 -070012
13namespace art {
14
Carl Shapiro58551df2011-07-24 03:09:51 -070015std::vector<Space*> Heap::spaces_;
Carl Shapiro69759ea2011-07-21 18:13:35 -070016
17size_t Heap::startup_size_ = 0;
18
19size_t Heap::maximum_size_ = 0;
20
Carl Shapiro58551df2011-07-24 03:09:51 -070021size_t Heap::num_bytes_allocated_ = 0;
22
23size_t Heap::num_objects_allocated_ = 0;
24
Carl Shapiro69759ea2011-07-21 18:13:35 -070025bool Heap::is_gc_running_ = false;
26
27HeapBitmap* Heap::mark_bitmap_ = NULL;
28
29HeapBitmap* Heap::live_bitmap_ = NULL;
30
31bool Heap::Init(size_t startup_size, size_t maximum_size) {
Carl Shapiro58551df2011-07-24 03:09:51 -070032 Space* space = Space::Create(startup_size, maximum_size);
33 if (space == NULL) {
Carl Shapiro69759ea2011-07-21 18:13:35 -070034 return false;
35 }
36
Carl Shapiro58551df2011-07-24 03:09:51 -070037 byte* base = space->GetBase();
38 size_t num_bytes = space->Size();
Carl Shapiro69759ea2011-07-21 18:13:35 -070039
40 // Allocate the initial live bitmap.
41 scoped_ptr<HeapBitmap> live_bitmap(HeapBitmap::Create(base, num_bytes));
42 if (live_bitmap == NULL) {
43 return false;
44 }
45
46 // Allocate the initial mark bitmap.
47 scoped_ptr<HeapBitmap> mark_bitmap(HeapBitmap::Create(base, num_bytes));
48 if (mark_bitmap == NULL) {
49 return false;
50 }
51
Carl Shapiro58551df2011-07-24 03:09:51 -070052 spaces_.push_back(space);
Carl Shapiro69759ea2011-07-21 18:13:35 -070053 startup_size_ = startup_size;
54 maximum_size_ = maximum_size;
55 live_bitmap_ = live_bitmap.release();
56 mark_bitmap_ = mark_bitmap.release();
57
58 // TODO: allocate the card table
59
60 return true;
61}
62
63void Heap::Destroy() {
Carl Shapiro58551df2011-07-24 03:09:51 -070064 STLDeleteElements(&spaces_);
Carl Shapiro69759ea2011-07-21 18:13:35 -070065 delete mark_bitmap_;
66 delete live_bitmap_;
67}
68
Carl Shapiro58551df2011-07-24 03:09:51 -070069Object* Heap::AllocObject(Class* klass, size_t num_bytes) {
70 Object* obj = Allocate(num_bytes);
71 if (obj != NULL) {
72 obj->klass_ = klass;
73 }
74 return obj;
75}
76
77void Heap::RecordAllocation(Space* space, const Object* obj) {
78 size_t size = space->AllocationSize(obj);
79 DCHECK_NE(size, 0u);
80 num_bytes_allocated_ += size;
81 num_objects_allocated_ += 1;
82 live_bitmap_->Set(obj);
83}
84
85void Heap::RecordFree(Space* space, const Object* obj) {
86 size_t size = space->AllocationSize(obj);
87 DCHECK_NE(size, 0u);
88 if (size < num_bytes_allocated_) {
89 num_bytes_allocated_ -= size;
90 } else {
91 num_bytes_allocated_ = 0;
92 }
93 live_bitmap_->Clear(obj);
94 if (num_objects_allocated_ > 0) {
95 num_objects_allocated_ -= 1;
96 }
97}
98
Carl Shapiro69759ea2011-07-21 18:13:35 -070099Object* Heap::Allocate(size_t size) {
Carl Shapiro58551df2011-07-24 03:09:51 -0700100 CHECK_EQ(spaces_.size(), 1u);
101 Space* space = spaces_[0];
102 Object* obj = Allocate(space, size);
103 if (obj != NULL) {
104 RecordAllocation(space, obj);
105 }
106 return obj;
107}
108
109Object* Heap::Allocate(Space* space, size_t size) {
Carl Shapiro69759ea2011-07-21 18:13:35 -0700110 // Fail impossible allocations. TODO: collect soft references.
111 if (size > maximum_size_) {
112 return NULL;
113 }
114
Carl Shapiro58551df2011-07-24 03:09:51 -0700115 Object* ptr = space->AllocWithoutGrowth(size);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700116 if (ptr != NULL) {
117 return ptr;
118 }
119
120 // The allocation failed. If the GC is running, block until it
121 // completes and retry.
122 if (is_gc_running_) {
123 // The GC is concurrently tracing the heap. Release the heap
124 // lock, wait for the GC to complete, and retrying allocating.
125 WaitForConcurrentGcToComplete();
Carl Shapiro58551df2011-07-24 03:09:51 -0700126 ptr = space->AllocWithoutGrowth(size);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700127 if (ptr != NULL) {
128 return ptr;
129 }
130 }
131
132 // Another failure. Our thread was starved or there may be too many
133 // live objects. Try a foreground GC. This will have no effect if
134 // the concurrent GC is already running.
Carl Shapiro58551df2011-07-24 03:09:51 -0700135 CollectGarbageInternal();
136 ptr = space->AllocWithoutGrowth(size);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700137 if (ptr != NULL) {
138 return ptr;
139 }
140
141 // Even that didn't work; this is an exceptional state.
142 // Try harder, growing the heap if necessary.
Carl Shapiro58551df2011-07-24 03:09:51 -0700143 ptr = space->AllocWithGrowth(size);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700144 if (ptr != NULL) {
145 //size_t new_footprint = dvmHeapSourceGetIdealFootprint();
Carl Shapiro58551df2011-07-24 03:09:51 -0700146 size_t new_footprint = space->MaxAllowedFootprint();
147 // TODO: may want to grow a little bit more so that the amount of
148 // free space is equal to the old free space + the
149 // utilization slop for the new allocation.
150 LOG(INFO) << "Grow heap (frag case) to " << new_footprint / MB
Carl Shapiro69759ea2011-07-21 18:13:35 -0700151 << "for " << size << "-byte allocation";
152 return ptr;
153 }
154
155 // Most allocations should have succeeded by now, so the heap is
156 // really full, really fragmented, or the requested size is really
157 // big. Do another GC, collecting SoftReferences this time. The VM
158 // spec requires that all SoftReferences have been collected and
159 // cleared before throwing an OOME.
160
Carl Shapiro58551df2011-07-24 03:09:51 -0700161 // TODO: wait for the finalizers from the previous GC to finish
Carl Shapiro69759ea2011-07-21 18:13:35 -0700162 LOG(INFO) << "Forcing collection of SoftReferences for "
163 << size << "-byte allocation";
Carl Shapiro58551df2011-07-24 03:09:51 -0700164 CollectGarbageInternal();
165 ptr = space->AllocWithGrowth(size);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700166 if (ptr != NULL) {
167 return ptr;
168 }
Carl Shapiro69759ea2011-07-21 18:13:35 -0700169
Carl Shapiro69759ea2011-07-21 18:13:35 -0700170 LOG(ERROR) << "Out of memory on a " << size << " byte allocation";
171
Carl Shapiro58551df2011-07-24 03:09:51 -0700172 // TODO: tell the HeapSource to dump its state
173 // TODO: dump stack traces for all threads
Carl Shapiro69759ea2011-07-21 18:13:35 -0700174
Carl Shapiro69759ea2011-07-21 18:13:35 -0700175 return NULL;
176}
177
Carl Shapiro69759ea2011-07-21 18:13:35 -0700178void Heap::CollectGarbage() {
Carl Shapiro58551df2011-07-24 03:09:51 -0700179 CollectGarbageInternal();
Carl Shapiro69759ea2011-07-21 18:13:35 -0700180}
181
182void Heap::CollectGarbageInternal() {
Carl Shapiro58551df2011-07-24 03:09:51 -0700183 // TODO: check that heap lock is held
184
185 // TODO: Suspend all threads
186 {
187 MarkSweep mark_sweep;
188
189 mark_sweep.Init();
190
191 mark_sweep.MarkRoots();
192
193 // Push marked roots onto the mark stack
194
195 // TODO: if concurrent
196 // unlock heap
197 // resume threads
198
199 mark_sweep.RecursiveMark();
200
201 // TODO: if concurrent
202 // lock heap
203 // suspend threads
204 // re-mark root set
205 // scan dirty objects
206
207 mark_sweep.ProcessReferences(false);
208
209 // TODO: swap bitmaps
210
211 mark_sweep.Sweep();
212 }
213
214 GrowForUtilization();
215
216 // TODO: Resume all threads
Carl Shapiro69759ea2011-07-21 18:13:35 -0700217}
218
219void Heap::WaitForConcurrentGcToComplete() {
220}
221
222// Given the current contents of the active heap, increase the allowed
223// heap footprint to match the target utilization ratio. This should
224// only be called immediately after a full garbage collection.
225void Heap::GrowForUtilization() {
Carl Shapiro58551df2011-07-24 03:09:51 -0700226 LOG(ERROR) << "Unimplemented";
Carl Shapiro69759ea2011-07-21 18:13:35 -0700227}
228
229} // namespace art