blob: bc54a821c2db2c6d3f02175689cff3d0655bfe3b [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 Shapirofc322c72011-07-27 00:20:01 -070011#include "scoped_ptr.h"
Carl Shapiro58551df2011-07-24 03:09:51 -070012#include "stl_util.h"
Carl Shapiro69759ea2011-07-21 18:13:35 -070013
14namespace art {
15
Carl Shapiro58551df2011-07-24 03:09:51 -070016std::vector<Space*> Heap::spaces_;
Carl Shapiro69759ea2011-07-21 18:13:35 -070017
18size_t Heap::startup_size_ = 0;
19
20size_t Heap::maximum_size_ = 0;
21
Carl Shapiro58551df2011-07-24 03:09:51 -070022size_t Heap::num_bytes_allocated_ = 0;
23
24size_t Heap::num_objects_allocated_ = 0;
25
Carl Shapiro69759ea2011-07-21 18:13:35 -070026bool Heap::is_gc_running_ = false;
27
28HeapBitmap* Heap::mark_bitmap_ = NULL;
29
30HeapBitmap* Heap::live_bitmap_ = NULL;
31
32bool Heap::Init(size_t startup_size, size_t maximum_size) {
Carl Shapiro58551df2011-07-24 03:09:51 -070033 Space* space = Space::Create(startup_size, maximum_size);
34 if (space == NULL) {
Carl Shapiro69759ea2011-07-21 18:13:35 -070035 return false;
36 }
37
Carl Shapiro58551df2011-07-24 03:09:51 -070038 byte* base = space->GetBase();
39 size_t num_bytes = space->Size();
Carl Shapiro69759ea2011-07-21 18:13:35 -070040
41 // Allocate the initial live bitmap.
42 scoped_ptr<HeapBitmap> live_bitmap(HeapBitmap::Create(base, num_bytes));
43 if (live_bitmap == NULL) {
44 return false;
45 }
46
47 // Allocate the initial mark bitmap.
48 scoped_ptr<HeapBitmap> mark_bitmap(HeapBitmap::Create(base, num_bytes));
49 if (mark_bitmap == NULL) {
50 return false;
51 }
52
Carl Shapiro58551df2011-07-24 03:09:51 -070053 spaces_.push_back(space);
Carl Shapiro69759ea2011-07-21 18:13:35 -070054 startup_size_ = startup_size;
55 maximum_size_ = maximum_size;
56 live_bitmap_ = live_bitmap.release();
57 mark_bitmap_ = mark_bitmap.release();
58
59 // TODO: allocate the card table
60
61 return true;
62}
63
64void Heap::Destroy() {
Carl Shapiro58551df2011-07-24 03:09:51 -070065 STLDeleteElements(&spaces_);
Carl Shapiro69759ea2011-07-21 18:13:35 -070066 delete mark_bitmap_;
67 delete live_bitmap_;
68}
69
Carl Shapiro58551df2011-07-24 03:09:51 -070070Object* Heap::AllocObject(Class* klass, size_t num_bytes) {
71 Object* obj = Allocate(num_bytes);
72 if (obj != NULL) {
73 obj->klass_ = klass;
74 }
75 return obj;
76}
77
78void Heap::RecordAllocation(Space* space, const Object* obj) {
79 size_t size = space->AllocationSize(obj);
80 DCHECK_NE(size, 0u);
81 num_bytes_allocated_ += size;
82 num_objects_allocated_ += 1;
83 live_bitmap_->Set(obj);
84}
85
86void Heap::RecordFree(Space* space, const Object* obj) {
87 size_t size = space->AllocationSize(obj);
88 DCHECK_NE(size, 0u);
89 if (size < num_bytes_allocated_) {
90 num_bytes_allocated_ -= size;
91 } else {
92 num_bytes_allocated_ = 0;
93 }
94 live_bitmap_->Clear(obj);
95 if (num_objects_allocated_ > 0) {
96 num_objects_allocated_ -= 1;
97 }
98}
99
Carl Shapiro69759ea2011-07-21 18:13:35 -0700100Object* Heap::Allocate(size_t size) {
Carl Shapiro58551df2011-07-24 03:09:51 -0700101 CHECK_EQ(spaces_.size(), 1u);
102 Space* space = spaces_[0];
103 Object* obj = Allocate(space, size);
104 if (obj != NULL) {
105 RecordAllocation(space, obj);
106 }
107 return obj;
108}
109
110Object* Heap::Allocate(Space* space, size_t size) {
Carl Shapiro69759ea2011-07-21 18:13:35 -0700111 // Fail impossible allocations. TODO: collect soft references.
112 if (size > maximum_size_) {
113 return NULL;
114 }
115
Carl Shapiro58551df2011-07-24 03:09:51 -0700116 Object* ptr = space->AllocWithoutGrowth(size);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700117 if (ptr != NULL) {
118 return ptr;
119 }
120
121 // The allocation failed. If the GC is running, block until it
122 // completes and retry.
123 if (is_gc_running_) {
124 // The GC is concurrently tracing the heap. Release the heap
125 // lock, wait for the GC to complete, and retrying allocating.
126 WaitForConcurrentGcToComplete();
Carl Shapiro58551df2011-07-24 03:09:51 -0700127 ptr = space->AllocWithoutGrowth(size);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700128 if (ptr != NULL) {
129 return ptr;
130 }
131 }
132
133 // Another failure. Our thread was starved or there may be too many
134 // live objects. Try a foreground GC. This will have no effect if
135 // the concurrent GC is already running.
Carl Shapiro58551df2011-07-24 03:09:51 -0700136 CollectGarbageInternal();
137 ptr = space->AllocWithoutGrowth(size);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700138 if (ptr != NULL) {
139 return ptr;
140 }
141
142 // Even that didn't work; this is an exceptional state.
143 // Try harder, growing the heap if necessary.
Carl Shapiro58551df2011-07-24 03:09:51 -0700144 ptr = space->AllocWithGrowth(size);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700145 if (ptr != NULL) {
146 //size_t new_footprint = dvmHeapSourceGetIdealFootprint();
Carl Shapiro58551df2011-07-24 03:09:51 -0700147 size_t new_footprint = space->MaxAllowedFootprint();
148 // TODO: may want to grow a little bit more so that the amount of
149 // free space is equal to the old free space + the
150 // utilization slop for the new allocation.
151 LOG(INFO) << "Grow heap (frag case) to " << new_footprint / MB
Carl Shapiro69759ea2011-07-21 18:13:35 -0700152 << "for " << size << "-byte allocation";
153 return ptr;
154 }
155
156 // Most allocations should have succeeded by now, so the heap is
157 // really full, really fragmented, or the requested size is really
158 // big. Do another GC, collecting SoftReferences this time. The VM
159 // spec requires that all SoftReferences have been collected and
160 // cleared before throwing an OOME.
161
Carl Shapiro58551df2011-07-24 03:09:51 -0700162 // TODO: wait for the finalizers from the previous GC to finish
Carl Shapiro69759ea2011-07-21 18:13:35 -0700163 LOG(INFO) << "Forcing collection of SoftReferences for "
164 << size << "-byte allocation";
Carl Shapiro58551df2011-07-24 03:09:51 -0700165 CollectGarbageInternal();
166 ptr = space->AllocWithGrowth(size);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700167 if (ptr != NULL) {
168 return ptr;
169 }
Carl Shapiro69759ea2011-07-21 18:13:35 -0700170
Carl Shapiro69759ea2011-07-21 18:13:35 -0700171 LOG(ERROR) << "Out of memory on a " << size << " byte allocation";
172
Carl Shapiro58551df2011-07-24 03:09:51 -0700173 // TODO: tell the HeapSource to dump its state
174 // TODO: dump stack traces for all threads
Carl Shapiro69759ea2011-07-21 18:13:35 -0700175
Carl Shapiro69759ea2011-07-21 18:13:35 -0700176 return NULL;
177}
178
Carl Shapiro69759ea2011-07-21 18:13:35 -0700179void Heap::CollectGarbage() {
Carl Shapiro58551df2011-07-24 03:09:51 -0700180 CollectGarbageInternal();
Carl Shapiro69759ea2011-07-21 18:13:35 -0700181}
182
183void Heap::CollectGarbageInternal() {
Carl Shapiro58551df2011-07-24 03:09:51 -0700184 // TODO: check that heap lock is held
185
186 // TODO: Suspend all threads
187 {
188 MarkSweep mark_sweep;
189
190 mark_sweep.Init();
191
192 mark_sweep.MarkRoots();
193
194 // Push marked roots onto the mark stack
195
196 // TODO: if concurrent
197 // unlock heap
198 // resume threads
199
200 mark_sweep.RecursiveMark();
201
202 // TODO: if concurrent
203 // lock heap
204 // suspend threads
205 // re-mark root set
206 // scan dirty objects
207
208 mark_sweep.ProcessReferences(false);
209
210 // TODO: swap bitmaps
211
212 mark_sweep.Sweep();
213 }
214
215 GrowForUtilization();
216
217 // TODO: Resume all threads
Carl Shapiro69759ea2011-07-21 18:13:35 -0700218}
219
220void Heap::WaitForConcurrentGcToComplete() {
221}
222
223// Given the current contents of the active heap, increase the allowed
224// heap footprint to match the target utilization ratio. This should
225// only be called immediately after a full garbage collection.
226void Heap::GrowForUtilization() {
Carl Shapiro58551df2011-07-24 03:09:51 -0700227 LOG(ERROR) << "Unimplemented";
Carl Shapiro69759ea2011-07-21 18:13:35 -0700228}
229
230} // namespace art