blob: 643d056b59897d753a0f5456fb39ed29ba2d7f7a [file] [log] [blame]
Carl Shapiro69759ea2011-07-21 18:13:35 -07001// Copyright 2011 Google Inc. All Rights Reserved.
Carl Shapiro69759ea2011-07-21 18:13:35 -07002
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07003#include "heap.h"
Carl Shapiro58551df2011-07-24 03:09:51 -07004
5#include <vector>
6
Brian Carlstrom9cff8e12011-08-18 16:47:29 -07007#include "image.h"
Carl Shapiro58551df2011-07-24 03:09:51 -07008#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
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070018Space* Heap::alloc_space_ = NULL;
Carl Shapiro69759ea2011-07-21 18:13:35 -070019
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
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070032bool Heap::Init(size_t initial_size, size_t maximum_size, const char* boot_image_file_name) {
33 Space* boot_space;
34 byte* requested_base;
35 if (boot_image_file_name == NULL) {
36 boot_space = NULL;
37 requested_base = NULL;
38 } else {
39 boot_space = Space::Create(boot_image_file_name);
40 if (boot_space == NULL) {
41 return false;
42 }
43 spaces_.push_back(boot_space);
44 requested_base = boot_space->GetBase() + RoundUp(boot_space->Size(), kPageSize);
45 }
46
47 Space* space = Space::Create(initial_size, maximum_size, requested_base);
Carl Shapiro58551df2011-07-24 03:09:51 -070048 if (space == NULL) {
Carl Shapiro69759ea2011-07-21 18:13:35 -070049 return false;
50 }
51
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070052 if (boot_space == NULL) {
53 boot_space = space;
54 }
55 byte* base = std::min(boot_space->GetBase(), space->GetBase());
56 byte* limit = std::max(boot_space->GetLimit(), space->GetLimit());
57 DCHECK_LT(base, limit);
58 size_t num_bytes = limit - base;
Carl Shapiro69759ea2011-07-21 18:13:35 -070059
60 // Allocate the initial live bitmap.
61 scoped_ptr<HeapBitmap> live_bitmap(HeapBitmap::Create(base, num_bytes));
62 if (live_bitmap == NULL) {
63 return false;
64 }
65
66 // Allocate the initial mark bitmap.
67 scoped_ptr<HeapBitmap> mark_bitmap(HeapBitmap::Create(base, num_bytes));
68 if (mark_bitmap == NULL) {
69 return false;
70 }
71
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070072 alloc_space_ = space;
Carl Shapiro58551df2011-07-24 03:09:51 -070073 spaces_.push_back(space);
Carl Shapiro69759ea2011-07-21 18:13:35 -070074 maximum_size_ = maximum_size;
75 live_bitmap_ = live_bitmap.release();
76 mark_bitmap_ = mark_bitmap.release();
77
78 // TODO: allocate the card table
79
Brian Carlstrom9cff8e12011-08-18 16:47:29 -070080 // Make objects in boot_space live (after live_bitmap_ is set)
81 if (boot_image_file_name != NULL) {
82 RecordImageAllocations(boot_space);
83 }
84
Carl Shapiro69759ea2011-07-21 18:13:35 -070085 return true;
86}
87
88void Heap::Destroy() {
Carl Shapiro58551df2011-07-24 03:09:51 -070089 STLDeleteElements(&spaces_);
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070090 if (mark_bitmap_ != NULL) {
91 delete mark_bitmap_;
92 mark_bitmap_ = NULL;
93 }
94 if (live_bitmap_ != NULL) {
95 delete live_bitmap_;
96 }
97 live_bitmap_ = NULL;
Carl Shapiro69759ea2011-07-21 18:13:35 -070098}
99
Carl Shapiro58551df2011-07-24 03:09:51 -0700100Object* Heap::AllocObject(Class* klass, size_t num_bytes) {
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700101 DCHECK(klass == NULL
Brian Carlstrom74eb46a2011-08-02 20:10:14 -0700102 || klass->descriptor_ == NULL
103 || (klass->object_size_ == (klass->IsArray() ? 0 : num_bytes)));
Carl Shapiro58551df2011-07-24 03:09:51 -0700104 Object* obj = Allocate(num_bytes);
105 if (obj != NULL) {
106 obj->klass_ = klass;
107 }
108 return obj;
109}
110
111void Heap::RecordAllocation(Space* space, const Object* obj) {
112 size_t size = space->AllocationSize(obj);
113 DCHECK_NE(size, 0u);
114 num_bytes_allocated_ += size;
115 num_objects_allocated_ += 1;
116 live_bitmap_->Set(obj);
117}
118
119void Heap::RecordFree(Space* space, const Object* obj) {
120 size_t size = space->AllocationSize(obj);
121 DCHECK_NE(size, 0u);
122 if (size < num_bytes_allocated_) {
123 num_bytes_allocated_ -= size;
124 } else {
125 num_bytes_allocated_ = 0;
126 }
127 live_bitmap_->Clear(obj);
128 if (num_objects_allocated_ > 0) {
129 num_objects_allocated_ -= 1;
130 }
131}
132
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700133void Heap::RecordImageAllocations(Space* space) {
134 CHECK(space != NULL);
135 CHECK(live_bitmap_ != NULL);
136 byte* current = space->GetBase() + RoundUp(sizeof(ImageHeader), 8);
137 while (current < space->GetLimit()) {
138 DCHECK(IsAligned(current, 8));
139 const Object* obj = reinterpret_cast<const Object*>(current);
140 live_bitmap_->Set(obj);
141 current += RoundUp(obj->SizeOf(), 8);
142 }
143}
144
Carl Shapiro69759ea2011-07-21 18:13:35 -0700145Object* Heap::Allocate(size_t size) {
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700146 DCHECK(alloc_space_ != NULL);
147 Space* space = alloc_space_;
Carl Shapiro58551df2011-07-24 03:09:51 -0700148 Object* obj = Allocate(space, size);
149 if (obj != NULL) {
150 RecordAllocation(space, obj);
151 }
152 return obj;
153}
154
155Object* Heap::Allocate(Space* space, size_t size) {
Carl Shapiro69759ea2011-07-21 18:13:35 -0700156 // Fail impossible allocations. TODO: collect soft references.
157 if (size > maximum_size_) {
158 return NULL;
159 }
160
Carl Shapiro58551df2011-07-24 03:09:51 -0700161 Object* ptr = space->AllocWithoutGrowth(size);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700162 if (ptr != NULL) {
163 return ptr;
164 }
165
166 // The allocation failed. If the GC is running, block until it
167 // completes and retry.
168 if (is_gc_running_) {
169 // The GC is concurrently tracing the heap. Release the heap
170 // lock, wait for the GC to complete, and retrying allocating.
171 WaitForConcurrentGcToComplete();
Carl Shapiro58551df2011-07-24 03:09:51 -0700172 ptr = space->AllocWithoutGrowth(size);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700173 if (ptr != NULL) {
174 return ptr;
175 }
176 }
177
178 // Another failure. Our thread was starved or there may be too many
179 // live objects. Try a foreground GC. This will have no effect if
180 // the concurrent GC is already running.
Carl Shapiro58551df2011-07-24 03:09:51 -0700181 CollectGarbageInternal();
182 ptr = space->AllocWithoutGrowth(size);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700183 if (ptr != NULL) {
184 return ptr;
185 }
186
187 // Even that didn't work; this is an exceptional state.
188 // Try harder, growing the heap if necessary.
Carl Shapiro58551df2011-07-24 03:09:51 -0700189 ptr = space->AllocWithGrowth(size);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700190 if (ptr != NULL) {
191 //size_t new_footprint = dvmHeapSourceGetIdealFootprint();
Carl Shapiro58551df2011-07-24 03:09:51 -0700192 size_t new_footprint = space->MaxAllowedFootprint();
193 // TODO: may want to grow a little bit more so that the amount of
194 // free space is equal to the old free space + the
195 // utilization slop for the new allocation.
196 LOG(INFO) << "Grow heap (frag case) to " << new_footprint / MB
Carl Shapiro69759ea2011-07-21 18:13:35 -0700197 << "for " << size << "-byte allocation";
198 return ptr;
199 }
200
201 // Most allocations should have succeeded by now, so the heap is
202 // really full, really fragmented, or the requested size is really
203 // big. Do another GC, collecting SoftReferences this time. The VM
204 // spec requires that all SoftReferences have been collected and
205 // cleared before throwing an OOME.
206
Carl Shapiro58551df2011-07-24 03:09:51 -0700207 // TODO: wait for the finalizers from the previous GC to finish
Carl Shapiro69759ea2011-07-21 18:13:35 -0700208 LOG(INFO) << "Forcing collection of SoftReferences for "
209 << size << "-byte allocation";
Carl Shapiro58551df2011-07-24 03:09:51 -0700210 CollectGarbageInternal();
211 ptr = space->AllocWithGrowth(size);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700212 if (ptr != NULL) {
213 return ptr;
214 }
Carl Shapiro69759ea2011-07-21 18:13:35 -0700215
Carl Shapiro69759ea2011-07-21 18:13:35 -0700216 LOG(ERROR) << "Out of memory on a " << size << " byte allocation";
217
Carl Shapiro58551df2011-07-24 03:09:51 -0700218 // TODO: tell the HeapSource to dump its state
219 // TODO: dump stack traces for all threads
Carl Shapiro69759ea2011-07-21 18:13:35 -0700220
Carl Shapiro69759ea2011-07-21 18:13:35 -0700221 return NULL;
222}
223
Carl Shapiro69759ea2011-07-21 18:13:35 -0700224void Heap::CollectGarbage() {
Carl Shapiro58551df2011-07-24 03:09:51 -0700225 CollectGarbageInternal();
Carl Shapiro69759ea2011-07-21 18:13:35 -0700226}
227
228void Heap::CollectGarbageInternal() {
Carl Shapiro58551df2011-07-24 03:09:51 -0700229 // TODO: check that heap lock is held
230
231 // TODO: Suspend all threads
232 {
233 MarkSweep mark_sweep;
234
235 mark_sweep.Init();
236
237 mark_sweep.MarkRoots();
238
239 // Push marked roots onto the mark stack
240
241 // TODO: if concurrent
242 // unlock heap
243 // resume threads
244
245 mark_sweep.RecursiveMark();
246
247 // TODO: if concurrent
248 // lock heap
249 // suspend threads
250 // re-mark root set
251 // scan dirty objects
252
253 mark_sweep.ProcessReferences(false);
254
255 // TODO: swap bitmaps
256
257 mark_sweep.Sweep();
258 }
259
260 GrowForUtilization();
261
262 // TODO: Resume all threads
Carl Shapiro69759ea2011-07-21 18:13:35 -0700263}
264
265void Heap::WaitForConcurrentGcToComplete() {
266}
267
268// Given the current contents of the active heap, increase the allowed
269// heap footprint to match the target utilization ratio. This should
270// only be called immediately after a full garbage collection.
271void Heap::GrowForUtilization() {
Elliott Hughes53b61312011-08-12 18:28:20 -0700272 UNIMPLEMENTED(ERROR);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700273}
274
275} // namespace art