blob: 06ebb68bceb30697b50c09da69386d9a397b432d [file] [log] [blame]
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <cutils/mspace.h>
Carl Shapiro2c81bdc2010-09-07 16:19:01 -070018#include <stdint.h> // for SIZE_MAX
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080019#include <sys/mman.h>
20#include <errno.h>
21
22#include "Dalvik.h"
23#include "alloc/Heap.h"
24#include "alloc/HeapInternal.h"
25#include "alloc/HeapSource.h"
26#include "alloc/HeapBitmap.h"
27
28// TODO: find a real header file for these.
29extern int dlmalloc_trim(size_t);
30extern void dlmalloc_walk_free_pages(void(*)(void*, void*, void*), void*);
31
32static void snapIdealFootprint(void);
33static void setIdealFootprint(size_t max);
34
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080035#define ALIGN_UP_TO_PAGE_SIZE(p) \
Andy McFadden96516932009-10-28 17:39:02 -070036 (((size_t)(p) + (SYSTEM_PAGE_SIZE - 1)) & ~(SYSTEM_PAGE_SIZE - 1))
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080037#define ALIGN_DOWN_TO_PAGE_SIZE(p) \
Andy McFadden96516932009-10-28 17:39:02 -070038 ((size_t)(p) & ~(SYSTEM_PAGE_SIZE - 1))
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080039
40#define HEAP_UTILIZATION_MAX 1024
41#define DEFAULT_HEAP_UTILIZATION 512 // Range 1..HEAP_UTILIZATION_MAX
42#define HEAP_IDEAL_FREE (2 * 1024 * 1024)
43#define HEAP_MIN_FREE (HEAP_IDEAL_FREE / 4)
44
Carl Shapiro2c81bdc2010-09-07 16:19:01 -070045/* Start a concurrent collection when free memory falls under this
46 * many bytes.
Carl Shapiroec805ea2010-06-28 16:28:26 -070047 */
Carl Shapiro2c81bdc2010-09-07 16:19:01 -070048#define CONCURRENT_START (128 << 10)
49
50/* The next GC will not be concurrent when free memory after a GC is
51 * under this many bytes.
52 */
53#define CONCURRENT_MIN_FREE (CONCURRENT_START + (128 << 10))
Carl Shapiroec805ea2010-06-28 16:28:26 -070054
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080055#define HS_BOILERPLATE() \
56 do { \
57 assert(gDvm.gcHeap != NULL); \
58 assert(gDvm.gcHeap->heapSource != NULL); \
59 assert(gHs == gDvm.gcHeap->heapSource); \
60 } while (0)
61
62#define DEBUG_HEAP_SOURCE 0
63#if DEBUG_HEAP_SOURCE
64#define HSTRACE(...) LOG(LOG_INFO, LOG_TAG "-hs", __VA_ARGS__)
65#else
66#define HSTRACE(...) /**/
67#endif
68
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080069typedef struct {
70 /* The mspace to allocate from.
71 */
Barry Hayes06f254e2009-12-16 16:51:04 -080072 mspace msp;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080073
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080074 /* The largest size that this heap is allowed to grow to.
75 */
Carl Shapiro23966772011-01-16 14:05:53 -080076 size_t maximumSize;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080077
78 /* Number of bytes allocated from this mspace for objects,
79 * including any overhead. This value is NOT exact, and
80 * should only be used as an input for certain heuristics.
81 */
82 size_t bytesAllocated;
83
Carl Shapiro2c81bdc2010-09-07 16:19:01 -070084 /* Number of bytes allocated from this mspace at which a
85 * concurrent garbage collection will be started.
Carl Shapiroec805ea2010-06-28 16:28:26 -070086 */
Carl Shapiro2c81bdc2010-09-07 16:19:01 -070087 size_t concurrentStartBytes;
Carl Shapiroec805ea2010-06-28 16:28:26 -070088
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080089 /* Number of objects currently allocated from this mspace.
90 */
91 size_t objectsAllocated;
Carl Shapirof373efd2010-02-19 00:46:33 -080092
93 /*
94 * The lowest address of this heap, inclusive.
95 */
96 char *base;
97
98 /*
99 * The highest address of this heap, exclusive.
100 */
101 char *limit;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800102} Heap;
103
104struct HeapSource {
105 /* Target ideal heap utilization ratio; range 1..HEAP_UTILIZATION_MAX
106 */
107 size_t targetUtilization;
108
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800109 /* The starting heap size.
110 */
111 size_t startSize;
112
113 /* The largest that the heap source as a whole is allowed to grow.
114 */
Carl Shapiro23966772011-01-16 14:05:53 -0800115 size_t maximumSize;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800116
117 /* The desired max size of the heap source as a whole.
118 */
119 size_t idealSize;
120
121 /* The maximum number of bytes allowed to be allocated from the
122 * active heap before a GC is forced. This is used to "shrink" the
123 * heap in lieu of actual compaction.
124 */
125 size_t softLimit;
126
127 /* The heaps; heaps[0] is always the active heap,
128 * which new objects should be allocated from.
129 */
130 Heap heaps[HEAP_SOURCE_MAX_HEAP_COUNT];
131
132 /* The current number of heaps.
133 */
134 size_t numHeaps;
135
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800136 /* True if zygote mode was active when the HeapSource was created.
137 */
138 bool sawZygote;
Carl Shapiroa199eb72010-02-09 16:26:30 -0800139
140 /*
141 * The base address of the virtual memory reservation.
142 */
143 char *heapBase;
144
145 /*
146 * The length in bytes of the virtual memory reservation.
147 */
148 size_t heapLength;
Carl Shapirof373efd2010-02-19 00:46:33 -0800149
150 /*
Carl Shapirod77f7fd2010-04-05 19:23:31 -0700151 * The live object bitmap.
Carl Shapirof373efd2010-02-19 00:46:33 -0800152 */
Carl Shapirod77f7fd2010-04-05 19:23:31 -0700153 HeapBitmap liveBits;
Carl Shapirof373efd2010-02-19 00:46:33 -0800154
155 /*
156 * The mark bitmap.
157 */
158 HeapBitmap markBits;
Carl Shapiroec805ea2010-06-28 16:28:26 -0700159
160 /*
161 * State for the GC daemon.
162 */
163 bool hasGcThread;
164 pthread_t gcThread;
165 bool gcThreadShutdown;
166 pthread_mutex_t gcThreadMutex;
167 pthread_cond_t gcThreadCond;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800168};
169
170#define hs2heap(hs_) (&((hs_)->heaps[0]))
171
172/*
173 * Returns true iff a soft limit is in effect for the active heap.
174 */
Carl Shapiro88a4f792011-01-14 19:05:23 -0800175static bool isSoftLimited(const HeapSource *hs)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800176{
Carl Shapiro2c81bdc2010-09-07 16:19:01 -0700177 /* softLimit will be either SIZE_MAX or the limit for the
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800178 * active mspace. idealSize can be greater than softLimit
179 * if there is more than one heap. If there is only one
Carl Shapiro2c81bdc2010-09-07 16:19:01 -0700180 * heap, a non-SIZE_MAX softLimit should always be the same
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800181 * as idealSize.
182 */
183 return hs->softLimit <= hs->idealSize;
184}
185
186/*
Carl Shapiro2c81bdc2010-09-07 16:19:01 -0700187 * Returns approximately the maximum number of bytes allowed to be
188 * allocated from the active heap before a GC is forced.
189 */
190static size_t
191getAllocLimit(const HeapSource *hs)
192{
Carl Shapiro88a4f792011-01-14 19:05:23 -0800193 if (isSoftLimited(hs)) {
Carl Shapiro2c81bdc2010-09-07 16:19:01 -0700194 return hs->softLimit;
195 } else {
196 return mspace_max_allowed_footprint(hs2heap(hs)->msp);
197 }
198}
199
200/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800201 * Returns the current footprint of all heaps. If includeActive
202 * is false, don't count the heap at index 0.
203 */
Carl Shapiro0f403d52011-01-16 17:20:49 -0800204static size_t oldHeapOverhead(const HeapSource *hs, bool includeActive)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800205{
206 size_t footprint = 0;
207 size_t i;
208
209 if (includeActive) {
210 i = 0;
211 } else {
212 i = 1;
213 }
214 for (/* i = i */; i < hs->numHeaps; i++) {
215//TODO: include size of bitmaps? If so, don't use bitsLen, listen to .max
216 footprint += mspace_footprint(hs->heaps[i].msp);
217 }
218 return footprint;
219}
220
221/*
222 * Returns the heap that <ptr> could have come from, or NULL
223 * if it could not have come from any heap.
224 */
Carl Shapiro0f403d52011-01-16 17:20:49 -0800225static Heap *ptr2heap(const HeapSource *hs, const void *ptr)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800226{
227 const size_t numHeaps = hs->numHeaps;
228 size_t i;
229
230//TODO: unroll this to HEAP_SOURCE_MAX_HEAP_COUNT
231 if (ptr != NULL) {
232 for (i = 0; i < numHeaps; i++) {
233 const Heap *const heap = &hs->heaps[i];
Carl Shapirof373efd2010-02-19 00:46:33 -0800234
235 if ((const char *)ptr >= heap->base && (const char *)ptr < heap->limit) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800236 return (Heap *)heap;
237 }
238 }
239 }
240 return NULL;
241}
242
243/*
244 * Functions to update heapSource->bytesAllocated when an object
245 * is allocated or freed. mspace_usable_size() will give
246 * us a much more accurate picture of heap utilization than
247 * the requested byte sizes would.
248 *
249 * These aren't exact, and should not be treated as such.
250 */
Carl Shapiroec47e2e2010-07-01 17:44:46 -0700251static void countAllocation(Heap *heap, const void *ptr, bool isObj)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800252{
Carl Shapirof373efd2010-02-19 00:46:33 -0800253 HeapSource *hs;
254
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800255 assert(heap->bytesAllocated < mspace_footprint(heap->msp));
256
257 heap->bytesAllocated += mspace_usable_size(heap->msp, ptr) +
258 HEAP_SOURCE_CHUNK_OVERHEAD;
259 if (isObj) {
260 heap->objectsAllocated++;
Carl Shapirof373efd2010-02-19 00:46:33 -0800261 hs = gDvm.gcHeap->heapSource;
Carl Shapirod77f7fd2010-04-05 19:23:31 -0700262 dvmHeapBitmapSetObjectBit(&hs->liveBits, ptr);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800263 }
264
265 assert(heap->bytesAllocated < mspace_footprint(heap->msp));
266}
267
Carl Shapiro8881a802010-08-10 15:55:45 -0700268static void countFree(Heap *heap, const void *ptr, size_t *numBytes)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800269{
Carl Shapirof373efd2010-02-19 00:46:33 -0800270 HeapSource *hs;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800271 size_t delta;
272
273 delta = mspace_usable_size(heap->msp, ptr) + HEAP_SOURCE_CHUNK_OVERHEAD;
274 assert(delta > 0);
275 if (delta < heap->bytesAllocated) {
276 heap->bytesAllocated -= delta;
277 } else {
278 heap->bytesAllocated = 0;
279 }
Carl Shapiro8881a802010-08-10 15:55:45 -0700280 hs = gDvm.gcHeap->heapSource;
281 dvmHeapBitmapClearObjectBit(&hs->liveBits, ptr);
282 if (heap->objectsAllocated > 0) {
283 heap->objectsAllocated--;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800284 }
Carl Shapiro8881a802010-08-10 15:55:45 -0700285 *numBytes += delta;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800286}
287
288static HeapSource *gHs = NULL;
289
Barry Hayes06f254e2009-12-16 16:51:04 -0800290static mspace
Carl Shapiro23966772011-01-16 14:05:53 -0800291createMspace(void *base, size_t startSize, size_t maximumSize)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800292{
Barry Hayes06f254e2009-12-16 16:51:04 -0800293 mspace msp;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800294
295 /* Create an unlocked dlmalloc mspace to use as
Carl Shapiroff1c0e82011-01-11 16:33:53 -0800296 * a heap source.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800297 *
298 * We start off reserving heapSizeStart/2 bytes but
299 * letting the heap grow to heapSizeStart. This saves
300 * memory in the case where a process uses even less
301 * than the starting size.
302 */
Carl Shapiro7ed3c872011-01-13 15:56:42 -0800303 LOGV_HEAP("Creating VM heap of size %zu\n", startSize);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800304 errno = 0;
Carl Shapiroa199eb72010-02-09 16:26:30 -0800305 msp = create_contiguous_mspace_with_base(startSize/2,
Carl Shapiro23966772011-01-16 14:05:53 -0800306 maximumSize, /*locked=*/false, base);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800307 if (msp != NULL) {
308 /* Don't let the heap grow past the starting size without
309 * our intervention.
310 */
311 mspace_set_max_allowed_footprint(msp, startSize);
312 } else {
313 /* There's no guarantee that errno has meaning when the call
314 * fails, but it often does.
315 */
Carl Shapiro7ed3c872011-01-13 15:56:42 -0800316 LOGE_HEAP("Can't create VM heap of size (%zu,%zu): %s\n",
Carl Shapiro23966772011-01-16 14:05:53 -0800317 startSize/2, maximumSize, strerror(errno));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800318 }
319
320 return msp;
321}
322
323static bool
Barry Hayes06f254e2009-12-16 16:51:04 -0800324addNewHeap(HeapSource *hs, mspace msp, size_t mspAbsoluteMaxSize)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800325{
326 Heap heap;
327
328 if (hs->numHeaps >= HEAP_SOURCE_MAX_HEAP_COUNT) {
329 LOGE("Attempt to create too many heaps (%zd >= %zd)\n",
330 hs->numHeaps, HEAP_SOURCE_MAX_HEAP_COUNT);
331 dvmAbort();
332 return false;
333 }
334
335 memset(&heap, 0, sizeof(heap));
336
337 if (msp != NULL) {
338 heap.msp = msp;
Carl Shapiro23966772011-01-16 14:05:53 -0800339 heap.maximumSize = mspAbsoluteMaxSize;
Carl Shapiro2c81bdc2010-09-07 16:19:01 -0700340 heap.concurrentStartBytes = SIZE_MAX;
Carl Shapirof373efd2010-02-19 00:46:33 -0800341 heap.base = hs->heapBase;
Carl Shapiro23966772011-01-16 14:05:53 -0800342 heap.limit = hs->heapBase + heap.maximumSize;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800343 } else {
Carl Shapiro88c57e12010-10-10 18:50:22 -0700344 void *sbrk0 = contiguous_mspace_sbrk0(hs->heaps[0].msp);
345 char *base = (char *)ALIGN_UP_TO_PAGE_SIZE(sbrk0);
346 size_t overhead = base - hs->heaps[0].base;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800347
Carl Shapiro88c57e12010-10-10 18:50:22 -0700348 assert(((size_t)hs->heaps[0].base & (SYSTEM_PAGE_SIZE - 1)) == 0);
Carl Shapiro23966772011-01-16 14:05:53 -0800349 if (overhead + HEAP_MIN_FREE >= hs->maximumSize) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800350 LOGE_HEAP("No room to create any more heaps "
351 "(%zd overhead, %zd max)\n",
Carl Shapiro23966772011-01-16 14:05:53 -0800352 overhead, hs->maximumSize);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800353 return false;
354 }
Carl Shapiro23966772011-01-16 14:05:53 -0800355 hs->heaps[0].maximumSize = overhead;
Carl Shapirof373efd2010-02-19 00:46:33 -0800356 hs->heaps[0].limit = base;
Carl Shapiro23966772011-01-16 14:05:53 -0800357 heap.maximumSize = hs->maximumSize - overhead;
358 heap.msp = createMspace(base, HEAP_MIN_FREE, heap.maximumSize);
Carl Shapiro2c81bdc2010-09-07 16:19:01 -0700359 heap.concurrentStartBytes = HEAP_MIN_FREE - CONCURRENT_START;
Carl Shapirof373efd2010-02-19 00:46:33 -0800360 heap.base = base;
Carl Shapiro23966772011-01-16 14:05:53 -0800361 heap.limit = heap.base + heap.maximumSize;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800362 if (heap.msp == NULL) {
363 return false;
364 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800365 }
366
367 /* Don't let the soon-to-be-old heap grow any further.
368 */
369 if (hs->numHeaps > 0) {
Barry Hayes06f254e2009-12-16 16:51:04 -0800370 mspace msp = hs->heaps[0].msp;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800371 mspace_set_max_allowed_footprint(msp, mspace_footprint(msp));
372 }
373
374 /* Put the new heap in the list, at heaps[0].
375 * Shift existing heaps down.
376 */
377 memmove(&hs->heaps[1], &hs->heaps[0], hs->numHeaps * sizeof(hs->heaps[0]));
378 hs->heaps[0] = heap;
379 hs->numHeaps++;
380
381 return true;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800382}
383
384/*
Carl Shapiroec805ea2010-06-28 16:28:26 -0700385 * The garbage collection daemon. Initiates a concurrent collection
386 * when signaled.
387 */
388static void *gcDaemonThread(void* arg)
389{
390 dvmChangeStatus(NULL, THREAD_VMWAIT);
391 dvmLockMutex(&gHs->gcThreadMutex);
392 while (gHs->gcThreadShutdown != true) {
393 dvmWaitCond(&gHs->gcThreadCond, &gHs->gcThreadMutex);
394 dvmLockHeap();
395 dvmChangeStatus(NULL, THREAD_RUNNING);
396 dvmCollectGarbageInternal(false, GC_CONCURRENT);
397 dvmChangeStatus(NULL, THREAD_VMWAIT);
398 dvmUnlockHeap();
399 }
400 dvmChangeStatus(NULL, THREAD_RUNNING);
401 return NULL;
402}
403
404static bool gcDaemonStartup(void)
405{
406 dvmInitMutex(&gHs->gcThreadMutex);
407 pthread_cond_init(&gHs->gcThreadCond, NULL);
408 gHs->gcThreadShutdown = false;
409 gHs->hasGcThread = dvmCreateInternalThread(&gHs->gcThread, "GC",
410 gcDaemonThread, NULL);
411 return gHs->hasGcThread;
412}
413
414static void gcDaemonShutdown(void)
415{
Carl Shapirofe608772010-07-28 19:33:46 -0700416 if (gHs->hasGcThread) {
Carl Shapiroec805ea2010-06-28 16:28:26 -0700417 dvmLockMutex(&gHs->gcThreadMutex);
418 gHs->gcThreadShutdown = true;
419 dvmSignalCond(&gHs->gcThreadCond);
Carl Shapiroec805ea2010-06-28 16:28:26 -0700420 dvmUnlockMutex(&gHs->gcThreadMutex);
Carl Shapiro9e594772010-06-28 17:24:17 -0700421 pthread_join(gHs->gcThread, NULL);
Carl Shapiroec805ea2010-06-28 16:28:26 -0700422 }
423}
424
425/*
Carl Shapirofdf80522010-11-09 14:27:02 -0800426 * Create a stack big enough for the worst possible case, where the
427 * heap is perfectly full of the smallest object.
428 * TODO: be better about memory usage; use a smaller stack with
429 * overflow detection and recovery.
430 */
431static bool allocMarkStack(GcMarkStack *stack, size_t maximumSize)
432{
433 const char *name = "dalvik-mark-stack";
434 void *addr;
435
436 assert(stack != NULL);
437 stack->length = maximumSize * sizeof(Object*) /
438 (sizeof(Object) + HEAP_SOURCE_CHUNK_OVERHEAD);
439 addr = dvmAllocRegion(stack->length, PROT_READ | PROT_WRITE, name);
440 if (addr == NULL) {
441 return false;
442 }
443 stack->base = (const Object **)addr;
444 stack->limit = (const Object **)((char *)addr + stack->length);
445 stack->top = NULL;
446 madvise(stack->base, stack->length, MADV_DONTNEED);
447 return true;
448}
449
450static void freeMarkStack(GcMarkStack *stack)
451{
452 assert(stack != NULL);
453 munmap(stack->base, stack->length);
454 memset(stack, 0, sizeof(*stack));
455}
456
457/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800458 * Initializes the heap source; must be called before any other
459 * dvmHeapSource*() functions. Returns a GcHeap structure
460 * allocated from the heap source.
461 */
462GcHeap *
Carl Shapiro23966772011-01-16 14:05:53 -0800463dvmHeapSourceStartup(size_t startSize, size_t maximumSize)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800464{
465 GcHeap *gcHeap;
466 HeapSource *hs;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800467 mspace msp;
Carl Shapiroa199eb72010-02-09 16:26:30 -0800468 size_t length;
469 void *base;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800470
471 assert(gHs == NULL);
472
Carl Shapiro23966772011-01-16 14:05:53 -0800473 if (startSize > maximumSize) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800474 LOGE("Bad heap parameters (start=%d, max=%d)\n",
Carl Shapiro23966772011-01-16 14:05:53 -0800475 startSize, maximumSize);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800476 return NULL;
477 }
478
Carl Shapiroa199eb72010-02-09 16:26:30 -0800479 /*
480 * Allocate a contiguous region of virtual memory to subdivided
481 * among the heaps managed by the garbage collector.
482 */
Carl Shapiro23966772011-01-16 14:05:53 -0800483 length = ALIGN_UP_TO_PAGE_SIZE(maximumSize);
Barry Hayes6e5cf602010-06-22 12:32:59 -0700484 base = dvmAllocRegion(length, PROT_NONE, "dalvik-heap");
485 if (base == NULL) {
Carl Shapiroa199eb72010-02-09 16:26:30 -0800486 return NULL;
487 }
Carl Shapiroa199eb72010-02-09 16:26:30 -0800488
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800489 /* Create an unlocked dlmalloc mspace to use as
Carl Shapiroff1c0e82011-01-11 16:33:53 -0800490 * a heap source.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800491 */
Carl Shapiro23966772011-01-16 14:05:53 -0800492 msp = createMspace(base, startSize, maximumSize);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800493 if (msp == NULL) {
Carl Shapiroa199eb72010-02-09 16:26:30 -0800494 goto fail;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800495 }
496
497 /* Allocate a descriptor from the heap we just created.
498 */
499 gcHeap = mspace_malloc(msp, sizeof(*gcHeap));
500 if (gcHeap == NULL) {
501 LOGE_HEAP("Can't allocate heap descriptor\n");
502 goto fail;
503 }
504 memset(gcHeap, 0, sizeof(*gcHeap));
505
506 hs = mspace_malloc(msp, sizeof(*hs));
507 if (hs == NULL) {
508 LOGE_HEAP("Can't allocate heap source\n");
509 goto fail;
510 }
511 memset(hs, 0, sizeof(*hs));
512
513 hs->targetUtilization = DEFAULT_HEAP_UTILIZATION;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800514 hs->startSize = startSize;
Carl Shapiro23966772011-01-16 14:05:53 -0800515 hs->maximumSize = maximumSize;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800516 hs->idealSize = startSize;
Carl Shapiro2c81bdc2010-09-07 16:19:01 -0700517 hs->softLimit = SIZE_MAX; // no soft limit at first
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800518 hs->numHeaps = 0;
519 hs->sawZygote = gDvm.zygote;
Carl Shapiroec805ea2010-06-28 16:28:26 -0700520 hs->hasGcThread = false;
Carl Shapiroa199eb72010-02-09 16:26:30 -0800521 hs->heapBase = base;
522 hs->heapLength = length;
Carl Shapiro23966772011-01-16 14:05:53 -0800523 if (!addNewHeap(hs, msp, maximumSize)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800524 LOGE_HEAP("Can't add initial heap\n");
525 goto fail;
526 }
Carl Shapirod77f7fd2010-04-05 19:23:31 -0700527 if (!dvmHeapBitmapInit(&hs->liveBits, base, length, "dalvik-bitmap-1")) {
528 LOGE_HEAP("Can't create liveBits\n");
Carl Shapirof373efd2010-02-19 00:46:33 -0800529 goto fail;
530 }
531 if (!dvmHeapBitmapInit(&hs->markBits, base, length, "dalvik-bitmap-2")) {
532 LOGE_HEAP("Can't create markBits\n");
Carl Shapirod77f7fd2010-04-05 19:23:31 -0700533 dvmHeapBitmapDelete(&hs->liveBits);
Carl Shapirof373efd2010-02-19 00:46:33 -0800534 goto fail;
535 }
Carl Shapiro23966772011-01-16 14:05:53 -0800536 if (!allocMarkStack(&gcHeap->markContext.stack, hs->maximumSize)) {
Carl Shapirofdf80522010-11-09 14:27:02 -0800537 LOGE("Can't create markStack");
538 dvmHeapBitmapDelete(&hs->markBits);
539 dvmHeapBitmapDelete(&hs->liveBits);
540 goto fail;
541 }
Carl Shapirof373efd2010-02-19 00:46:33 -0800542 gcHeap->markContext.bitmap = &hs->markBits;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800543 gcHeap->heapSource = hs;
544
545 countAllocation(hs2heap(hs), gcHeap, false);
546 countAllocation(hs2heap(hs), hs, false);
547
548 gHs = hs;
549 return gcHeap;
550
551fail:
Carl Shapiroa199eb72010-02-09 16:26:30 -0800552 munmap(base, length);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800553 return NULL;
554}
555
Carl Shapiroec805ea2010-06-28 16:28:26 -0700556bool dvmHeapSourceStartupAfterZygote(void)
557{
558 return gDvm.concurrentMarkSweep ? gcDaemonStartup() : true;
559}
560
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800561/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800562 * This is called while in zygote mode, right before we fork() for the
563 * first time. We create a heap for all future zygote process allocations,
564 * in an attempt to avoid touching pages in the zygote heap. (This would
565 * probably be unnecessary if we had a compacting GC -- the source of our
566 * troubles is small allocations filling in the gaps from larger ones.)
567 */
568bool
569dvmHeapSourceStartupBeforeFork()
570{
571 HeapSource *hs = gHs; // use a local to avoid the implicit "volatile"
572
573 HS_BOILERPLATE();
574
575 assert(gDvm.zygote);
576
577 if (!gDvm.newZygoteHeapAllocated) {
578 /* Create a new heap for post-fork zygote allocations. We only
579 * try once, even if it fails.
580 */
Andy McFaddendced7942009-11-17 13:13:34 -0800581 LOGV("Splitting out new zygote heap\n");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800582 gDvm.newZygoteHeapAllocated = true;
583 return addNewHeap(hs, NULL, 0);
584 }
585 return true;
586}
587
Carl Shapiroec805ea2010-06-28 16:28:26 -0700588void dvmHeapSourceThreadShutdown(void)
589{
Carl Shapirofe608772010-07-28 19:33:46 -0700590 if (gDvm.gcHeap != NULL && gDvm.concurrentMarkSweep) {
Carl Shapirod7de4502010-07-15 11:26:26 -0700591 gcDaemonShutdown();
592 }
Carl Shapiroec805ea2010-06-28 16:28:26 -0700593}
594
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800595/*
Carl Shapiroa199eb72010-02-09 16:26:30 -0800596 * Tears down the entire GcHeap structure and all of the substructures
597 * attached to it. This call has the side effect of setting the given
598 * gcHeap pointer and gHs to NULL.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800599 */
600void
Carl Shapiroa199eb72010-02-09 16:26:30 -0800601dvmHeapSourceShutdown(GcHeap **gcHeap)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800602{
Carl Shapiroa199eb72010-02-09 16:26:30 -0800603 if (*gcHeap != NULL && (*gcHeap)->heapSource != NULL) {
Carl Shapirofdf80522010-11-09 14:27:02 -0800604 HeapSource *hs = (*gcHeap)->heapSource;
Carl Shapiroa199eb72010-02-09 16:26:30 -0800605 assert((char *)*gcHeap >= hs->heapBase);
606 assert((char *)*gcHeap < hs->heapBase + hs->heapLength);
Carl Shapirod77f7fd2010-04-05 19:23:31 -0700607 dvmHeapBitmapDelete(&hs->liveBits);
Carl Shapirof373efd2010-02-19 00:46:33 -0800608 dvmHeapBitmapDelete(&hs->markBits);
Carl Shapirofdf80522010-11-09 14:27:02 -0800609 freeMarkStack(&(*gcHeap)->markContext.stack);
Carl Shapiroa199eb72010-02-09 16:26:30 -0800610 munmap(hs->heapBase, hs->heapLength);
611 gHs = NULL;
612 *gcHeap = NULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800613 }
614}
615
616/*
Barry Hayesb874ab92010-07-14 08:13:18 -0700617 * Gets the begining of the allocation for the HeapSource.
618 */
619void *dvmHeapSourceGetBase(void)
620{
621 return gHs->heapBase;
622}
623
624/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800625 * Returns the requested value. If the per-heap stats are requested, fill
626 * them as well.
627 *
628 * Caller must hold the heap lock.
629 */
630size_t
631dvmHeapSourceGetValue(enum HeapSourceValueSpec spec, size_t perHeapStats[],
632 size_t arrayLen)
633{
634 HeapSource *hs = gHs;
635 size_t value = 0;
636 size_t total = 0;
637 size_t i;
638
639 HS_BOILERPLATE();
640
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800641 assert(arrayLen >= hs->numHeaps || perHeapStats == NULL);
642 for (i = 0; i < hs->numHeaps; i++) {
643 Heap *const heap = &hs->heaps[i];
644
645 switch (spec) {
646 case HS_FOOTPRINT:
647 value = mspace_footprint(heap->msp);
648 break;
649 case HS_ALLOWED_FOOTPRINT:
650 value = mspace_max_allowed_footprint(heap->msp);
651 break;
652 case HS_BYTES_ALLOCATED:
653 value = heap->bytesAllocated;
654 break;
655 case HS_OBJECTS_ALLOCATED:
656 value = heap->objectsAllocated;
657 break;
658 default:
659 // quiet gcc
660 break;
661 }
662 if (perHeapStats) {
663 perHeapStats[i] = value;
664 }
665 total += value;
666 }
667 return total;
668}
669
Carl Shapirof373efd2010-02-19 00:46:33 -0800670static void aliasBitmap(HeapBitmap *dst, HeapBitmap *src,
671 uintptr_t base, uintptr_t max) {
672 size_t offset;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800673
Carl Shapirof373efd2010-02-19 00:46:33 -0800674 dst->base = base;
675 dst->max = max;
Barry Hayes73f3e6f2010-07-15 08:58:10 -0700676 dst->bitsLen = HB_OFFSET_TO_BYTE_INDEX(max - base) + sizeof(dst->bits);
677 /* The exclusive limit from bitsLen is greater than the inclusive max. */
678 assert(base + HB_MAX_OFFSET(dst) > max);
Barry Hayes8a0b5232010-07-21 11:22:04 -0700679 /* The exclusive limit is at most one word of bits beyond max. */
680 assert((base + HB_MAX_OFFSET(dst)) - max <=
Barry Hayes73f3e6f2010-07-15 08:58:10 -0700681 HB_OBJECT_ALIGNMENT * HB_BITS_PER_WORD);
Carl Shapirod25566d2010-03-11 20:39:47 -0800682 dst->allocLen = dst->bitsLen;
Carl Shapirof373efd2010-02-19 00:46:33 -0800683 offset = base - src->base;
684 assert(HB_OFFSET_TO_MASK(offset) == 1 << 31);
685 dst->bits = &src->bits[HB_OFFSET_TO_INDEX(offset)];
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800686}
687
688/*
Carl Shapirof373efd2010-02-19 00:46:33 -0800689 * Initializes a vector of object and mark bits to the object and mark
Barry Hayese168ebd2010-05-07 09:19:46 -0700690 * bits of each heap. The bits are aliased to the heapsource
Carl Shapirof373efd2010-02-19 00:46:33 -0800691 * object and mark bitmaps. This routine is used by the sweep code
692 * which needs to free each object in the correct heap.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800693 */
Carl Shapirod77f7fd2010-04-05 19:23:31 -0700694void dvmHeapSourceGetObjectBitmaps(HeapBitmap liveBits[], HeapBitmap markBits[],
Carl Shapirof373efd2010-02-19 00:46:33 -0800695 size_t numHeaps)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800696{
697 HeapSource *hs = gHs;
Carl Shapirof373efd2010-02-19 00:46:33 -0800698 uintptr_t base, max;
Carl Shapiroe3c01da2010-05-20 22:54:18 -0700699 size_t i;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800700
701 HS_BOILERPLATE();
702
Carl Shapirof373efd2010-02-19 00:46:33 -0800703 assert(numHeaps == hs->numHeaps);
704 for (i = 0; i < hs->numHeaps; ++i) {
705 base = (uintptr_t)hs->heaps[i].base;
Barry Hayes73f3e6f2010-07-15 08:58:10 -0700706 /* -1 because limit is exclusive but max is inclusive. */
Carl Shapiroe6a1b4d2010-08-17 18:33:56 -0700707 max = MIN((uintptr_t)hs->heaps[i].limit - 1, hs->markBits.max);
Carl Shapirod77f7fd2010-04-05 19:23:31 -0700708 aliasBitmap(&liveBits[i], &hs->liveBits, base, max);
Carl Shapirof373efd2010-02-19 00:46:33 -0800709 aliasBitmap(&markBits[i], &hs->markBits, base, max);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800710 }
Carl Shapirof373efd2010-02-19 00:46:33 -0800711}
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800712
Barry Hayes962adba2010-03-17 12:12:39 -0700713/*
714 * Get the bitmap representing all live objects.
715 */
Carl Shapiroec805ea2010-06-28 16:28:26 -0700716HeapBitmap *dvmHeapSourceGetLiveBits(void)
Barry Hayes962adba2010-03-17 12:12:39 -0700717{
718 HS_BOILERPLATE();
719
Carl Shapirod77f7fd2010-04-05 19:23:31 -0700720 return &gHs->liveBits;
Barry Hayes962adba2010-03-17 12:12:39 -0700721}
722
Carl Shapirof373efd2010-02-19 00:46:33 -0800723void dvmHeapSourceSwapBitmaps(void)
724{
725 HeapBitmap tmp;
Barry Hayes81010a42010-07-19 14:07:01 -0700726
Carl Shapirod77f7fd2010-04-05 19:23:31 -0700727 tmp = gHs->liveBits;
728 gHs->liveBits = gHs->markBits;
Carl Shapirof373efd2010-02-19 00:46:33 -0800729 gHs->markBits = tmp;
Barry Hayes81010a42010-07-19 14:07:01 -0700730}
731
732void dvmHeapSourceZeroMarkBitmap(void)
733{
734 HS_BOILERPLATE();
735
Carl Shapirof373efd2010-02-19 00:46:33 -0800736 dvmHeapBitmapZero(&gHs->markBits);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800737}
738
Barry Hayes425848f2010-05-04 13:32:12 -0700739void dvmMarkImmuneObjects(const char *immuneLimit)
Carl Shapirod25566d2010-03-11 20:39:47 -0800740{
741 char *dst, *src;
Carl Shapiroe3c01da2010-05-20 22:54:18 -0700742 size_t i, index, length;
Carl Shapirod25566d2010-03-11 20:39:47 -0800743
744 /*
745 * Copy the contents of the live bit vector for immune object
746 * range into the mark bit vector.
747 */
Barry Hayes425848f2010-05-04 13:32:12 -0700748 /* The only values generated by dvmHeapSourceGetImmuneLimit() */
749 assert(immuneLimit == gHs->heaps[0].base ||
750 immuneLimit == NULL);
Carl Shapirod77f7fd2010-04-05 19:23:31 -0700751 assert(gHs->liveBits.base == gHs->markBits.base);
752 assert(gHs->liveBits.bitsLen == gHs->markBits.bitsLen);
Barry Hayes425848f2010-05-04 13:32:12 -0700753 /* heap[0] is never immune */
754 assert(gHs->heaps[0].base >= immuneLimit);
755 assert(gHs->heaps[0].limit > immuneLimit);
756
Carl Shapirod25566d2010-03-11 20:39:47 -0800757 for (i = 1; i < gHs->numHeaps; ++i) {
Barry Hayes425848f2010-05-04 13:32:12 -0700758 if (gHs->heaps[i].base < immuneLimit) {
759 assert(gHs->heaps[i].limit <= immuneLimit);
Barry Hayes425848f2010-05-04 13:32:12 -0700760 /* Compute the number of words to copy in the bitmap. */
761 index = HB_OFFSET_TO_INDEX(
762 (uintptr_t)gHs->heaps[i].base - gHs->liveBits.base);
763 /* Compute the starting offset in the live and mark bits. */
764 src = (char *)(gHs->liveBits.bits + index);
765 dst = (char *)(gHs->markBits.bits + index);
766 /* Compute the number of bytes of the live bitmap to copy. */
767 length = HB_OFFSET_TO_BYTE_INDEX(
768 gHs->heaps[i].limit - gHs->heaps[i].base);
769 /* Do the copy. */
770 memcpy(dst, src, length);
771 /* Make sure max points to the address of the highest set bit. */
772 if (gHs->markBits.max < (uintptr_t)gHs->heaps[i].limit) {
773 gHs->markBits.max = (uintptr_t)gHs->heaps[i].limit;
774 }
Carl Shapirod25566d2010-03-11 20:39:47 -0800775 }
776 }
777}
778
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800779/*
780 * Allocates <n> bytes of zeroed data.
781 */
782void *
783dvmHeapSourceAlloc(size_t n)
784{
785 HeapSource *hs = gHs;
786 Heap *heap;
787 void *ptr;
788
789 HS_BOILERPLATE();
790 heap = hs2heap(hs);
Carl Shapiroec47e2e2010-07-01 17:44:46 -0700791 if (heap->bytesAllocated + n > hs->softLimit) {
792 /*
793 * This allocation would push us over the soft limit; act as
794 * if the heap is full.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800795 */
796 LOGV_HEAP("softLimit of %zd.%03zdMB hit for %zd-byte allocation\n",
Carl Shapiroec47e2e2010-07-01 17:44:46 -0700797 FRACTIONAL_MB(hs->softLimit), n);
798 return NULL;
799 }
800 ptr = mspace_calloc(heap->msp, 1, n);
801 if (ptr == NULL) {
802 return NULL;
803 }
804 countAllocation(heap, ptr, true);
805 /*
806 * Check to see if a concurrent GC should be initiated.
807 */
808 if (gDvm.gcHeap->gcRunning || !hs->hasGcThread) {
809 /*
810 * The garbage collector thread is already running or has yet
811 * to be started. Do nothing.
812 */
813 return ptr;
814 }
Carl Shapiro2c81bdc2010-09-07 16:19:01 -0700815 if (heap->bytesAllocated > heap->concurrentStartBytes) {
Carl Shapiroec47e2e2010-07-01 17:44:46 -0700816 /*
Carl Shapiro2c81bdc2010-09-07 16:19:01 -0700817 * We have exceeded the allocation threshold. Wake up the
Carl Shapiroec47e2e2010-07-01 17:44:46 -0700818 * garbage collector.
819 */
820 dvmSignalCond(&gHs->gcThreadCond);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800821 }
822 return ptr;
823}
824
825/* Remove any hard limits, try to allocate, and shrink back down.
826 * Last resort when trying to allocate an object.
827 */
828static void *
829heapAllocAndGrow(HeapSource *hs, Heap *heap, size_t n)
830{
831 void *ptr;
832 size_t max;
833
834 /* Grow as much as possible, but don't let the real footprint
Carl Shapiroe7bdd8b2010-12-17 15:34:52 -0800835 * go over the absolute max.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800836 */
Carl Shapiro23966772011-01-16 14:05:53 -0800837 max = heap->maximumSize;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800838
Carl Shapiroe7bdd8b2010-12-17 15:34:52 -0800839 mspace_set_max_allowed_footprint(heap->msp, max);
840 ptr = dvmHeapSourceAlloc(n);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800841
Carl Shapiroe7bdd8b2010-12-17 15:34:52 -0800842 /* Shrink back down as small as possible. Our caller may
843 * readjust max_allowed to a more appropriate value.
844 */
845 mspace_set_max_allowed_footprint(heap->msp,
846 mspace_footprint(heap->msp));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800847 return ptr;
848}
849
850/*
851 * Allocates <n> bytes of zeroed data, growing as much as possible
852 * if necessary.
853 */
854void *
855dvmHeapSourceAllocAndGrow(size_t n)
856{
857 HeapSource *hs = gHs;
858 Heap *heap;
859 void *ptr;
860 size_t oldIdealSize;
861
862 HS_BOILERPLATE();
863 heap = hs2heap(hs);
864
865 ptr = dvmHeapSourceAlloc(n);
866 if (ptr != NULL) {
867 return ptr;
868 }
869
870 oldIdealSize = hs->idealSize;
Carl Shapiro88a4f792011-01-14 19:05:23 -0800871 if (isSoftLimited(hs)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800872 /* We're soft-limited. Try removing the soft limit to
873 * see if we can allocate without actually growing.
874 */
Carl Shapiro2c81bdc2010-09-07 16:19:01 -0700875 hs->softLimit = SIZE_MAX;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800876 ptr = dvmHeapSourceAlloc(n);
877 if (ptr != NULL) {
878 /* Removing the soft limit worked; fix things up to
879 * reflect the new effective ideal size.
880 */
881 snapIdealFootprint();
882 return ptr;
883 }
Carl Shapiro2c81bdc2010-09-07 16:19:01 -0700884 // softLimit intentionally left at SIZE_MAX.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800885 }
886
887 /* We're not soft-limited. Grow the heap to satisfy the request.
888 * If this call fails, no footprints will have changed.
889 */
890 ptr = heapAllocAndGrow(hs, heap, n);
891 if (ptr != NULL) {
892 /* The allocation succeeded. Fix up the ideal size to
893 * reflect any footprint modifications that had to happen.
894 */
895 snapIdealFootprint();
896 } else {
897 /* We just couldn't do it. Restore the original ideal size,
898 * fixing up softLimit if necessary.
899 */
900 setIdealFootprint(oldIdealSize);
901 }
902 return ptr;
903}
904
905/*
Carl Shapiro8881a802010-08-10 15:55:45 -0700906 * Frees the first numPtrs objects in the ptrs list and returns the
907 * amount of reclaimed storage. The list must contain addresses all in
908 * the same mspace, and must be in increasing order. This implies that
909 * there are no duplicates, and no entries are NULL.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800910 */
Carl Shapiro8881a802010-08-10 15:55:45 -0700911size_t dvmHeapSourceFreeList(size_t numPtrs, void **ptrs)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800912{
913 Heap *heap;
Carl Shapiro8881a802010-08-10 15:55:45 -0700914 size_t numBytes;
Barry Hayesdde8ab02009-05-20 12:10:36 -0700915
916 HS_BOILERPLATE();
917
918 if (numPtrs == 0) {
Carl Shapiro8881a802010-08-10 15:55:45 -0700919 return 0;
Barry Hayesdde8ab02009-05-20 12:10:36 -0700920 }
921
922 assert(ptrs != NULL);
923 assert(*ptrs != NULL);
924 heap = ptr2heap(gHs, *ptrs);
Carl Shapiro8881a802010-08-10 15:55:45 -0700925 numBytes = 0;
Barry Hayesdde8ab02009-05-20 12:10:36 -0700926 if (heap != NULL) {
927 mspace *msp = heap->msp;
928 // Calling mspace_free on shared heaps disrupts sharing too
929 // much. For heap[0] -- the 'active heap' -- we call
930 // mspace_free, but on the other heaps we only do some
931 // accounting.
932 if (heap == gHs->heaps) {
933 // mspace_merge_objects takes two allocated objects, and
934 // if the second immediately follows the first, will merge
935 // them, returning a larger object occupying the same
936 // memory. This is a local operation, and doesn't require
937 // dlmalloc to manipulate any freelists. It's pretty
938 // inexpensive compared to free().
939
940 // ptrs is an array of objects all in memory order, and if
941 // client code has been allocating lots of short-lived
942 // objects, this is likely to contain runs of objects all
943 // now garbage, and thus highly amenable to this optimization.
944
945 // Unroll the 0th iteration around the loop below,
946 // countFree ptrs[0] and initializing merged.
947 assert(ptrs[0] != NULL);
948 assert(ptr2heap(gHs, ptrs[0]) == heap);
Carl Shapiro8881a802010-08-10 15:55:45 -0700949 countFree(heap, ptrs[0], &numBytes);
Barry Hayesdde8ab02009-05-20 12:10:36 -0700950 void *merged = ptrs[0];
951
952 size_t i;
953 for (i = 1; i < numPtrs; i++) {
954 assert(merged != NULL);
955 assert(ptrs[i] != NULL);
956 assert((intptr_t)merged < (intptr_t)ptrs[i]);
957 assert(ptr2heap(gHs, ptrs[i]) == heap);
Carl Shapiro8881a802010-08-10 15:55:45 -0700958 countFree(heap, ptrs[i], &numBytes);
Barry Hayesdde8ab02009-05-20 12:10:36 -0700959 // Try to merge. If it works, merged now includes the
960 // memory of ptrs[i]. If it doesn't, free merged, and
961 // see if ptrs[i] starts a new run of adjacent
962 // objects to merge.
963 if (mspace_merge_objects(msp, merged, ptrs[i]) == NULL) {
964 mspace_free(msp, merged);
965 merged = ptrs[i];
966 }
967 }
968 assert(merged != NULL);
969 mspace_free(msp, merged);
970 } else {
971 // This is not an 'active heap'. Only do the accounting.
972 size_t i;
973 for (i = 0; i < numPtrs; i++) {
974 assert(ptrs[i] != NULL);
975 assert(ptr2heap(gHs, ptrs[i]) == heap);
Carl Shapiro8881a802010-08-10 15:55:45 -0700976 countFree(heap, ptrs[i], &numBytes);
Barry Hayesdde8ab02009-05-20 12:10:36 -0700977 }
978 }
979 }
Carl Shapiro8881a802010-08-10 15:55:45 -0700980 return numBytes;
Barry Hayesdde8ab02009-05-20 12:10:36 -0700981}
982
983/*
Barry Hayes364f9d92010-06-11 16:12:47 -0700984 * Returns true iff <ptr> is in the heap source.
985 */
986bool
987dvmHeapSourceContainsAddress(const void *ptr)
988{
989 HS_BOILERPLATE();
990
991 return (dvmHeapBitmapCoversAddress(&gHs->liveBits, ptr));
992}
993
994/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800995 * Returns true iff <ptr> was allocated from the heap source.
996 */
997bool
998dvmHeapSourceContains(const void *ptr)
999{
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001000 HS_BOILERPLATE();
1001
Barry Hayes364f9d92010-06-11 16:12:47 -07001002 if (dvmHeapSourceContainsAddress(ptr)) {
Carl Shapirod77f7fd2010-04-05 19:23:31 -07001003 return dvmHeapBitmapIsObjectBitSet(&gHs->liveBits, ptr) != 0;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001004 }
1005 return false;
1006}
1007
1008/*
1009 * Returns the value of the requested flag.
1010 */
1011bool
1012dvmHeapSourceGetPtrFlag(const void *ptr, enum HeapSourcePtrFlag flag)
1013{
1014 if (ptr == NULL) {
1015 return false;
1016 }
1017
1018 if (flag == HS_CONTAINS) {
1019 return dvmHeapSourceContains(ptr);
1020 } else if (flag == HS_ALLOCATED_IN_ZYGOTE) {
1021 HeapSource *hs = gHs;
1022
1023 HS_BOILERPLATE();
1024
1025 if (hs->sawZygote) {
1026 Heap *heap;
1027
1028 heap = ptr2heap(hs, ptr);
1029 if (heap != NULL) {
1030 /* If the object is not in the active heap, we assume that
1031 * it was allocated as part of zygote.
1032 */
1033 return heap != hs->heaps;
1034 }
1035 }
1036 /* The pointer is outside of any known heap, or we are not
1037 * running in zygote mode.
1038 */
1039 return false;
1040 }
1041
1042 return false;
1043}
1044
1045/*
1046 * Returns the number of usable bytes in an allocated chunk; the size
1047 * may be larger than the size passed to dvmHeapSourceAlloc().
1048 */
1049size_t
1050dvmHeapSourceChunkSize(const void *ptr)
1051{
1052 Heap *heap;
1053
1054 HS_BOILERPLATE();
1055
1056 heap = ptr2heap(gHs, ptr);
1057 if (heap != NULL) {
1058 return mspace_usable_size(heap->msp, ptr);
1059 }
1060 return 0;
1061}
1062
1063/*
1064 * Returns the number of bytes that the heap source has allocated
1065 * from the system using sbrk/mmap, etc.
1066 *
1067 * Caller must hold the heap lock.
1068 */
1069size_t
1070dvmHeapSourceFootprint()
1071{
1072 HS_BOILERPLATE();
1073
1074//TODO: include size of bitmaps?
1075 return oldHeapOverhead(gHs, true);
1076}
1077
1078/*
Carl Shapiroe7bdd8b2010-12-17 15:34:52 -08001079 * Return the real bytes used by old heaps plus the soft usage of the
1080 * current heap. When a soft limit is in effect, this is effectively
1081 * what it's compared against (though, in practice, it only looks at
1082 * the current heap).
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001083 */
1084static size_t
1085getSoftFootprint(bool includeActive)
1086{
1087 HeapSource *hs = gHs;
1088 size_t ret;
1089
1090 HS_BOILERPLATE();
1091
Carl Shapiroe7bdd8b2010-12-17 15:34:52 -08001092 ret = oldHeapOverhead(hs, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001093 if (includeActive) {
1094 ret += hs->heaps[0].bytesAllocated;
1095 }
1096
1097 return ret;
1098}
1099
1100/*
1101 * Gets the maximum number of bytes that the heap source is allowed
1102 * to allocate from the system.
1103 */
1104size_t
1105dvmHeapSourceGetIdealFootprint()
1106{
1107 HeapSource *hs = gHs;
1108
1109 HS_BOILERPLATE();
1110
1111 return hs->idealSize;
1112}
1113
1114/*
1115 * Sets the soft limit, handling any necessary changes to the allowed
1116 * footprint of the active heap.
1117 */
1118static void
1119setSoftLimit(HeapSource *hs, size_t softLimit)
1120{
1121 /* Compare against the actual footprint, rather than the
1122 * max_allowed, because the heap may not have grown all the
1123 * way to the allowed size yet.
1124 */
Barry Hayes06f254e2009-12-16 16:51:04 -08001125 mspace msp = hs->heaps[0].msp;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001126 size_t currentHeapSize = mspace_footprint(msp);
1127 if (softLimit < currentHeapSize) {
1128 /* Don't let the heap grow any more, and impose a soft limit.
1129 */
1130 mspace_set_max_allowed_footprint(msp, currentHeapSize);
1131 hs->softLimit = softLimit;
1132 } else {
1133 /* Let the heap grow to the requested max, and remove any
1134 * soft limit, if set.
1135 */
1136 mspace_set_max_allowed_footprint(msp, softLimit);
Carl Shapiro2c81bdc2010-09-07 16:19:01 -07001137 hs->softLimit = SIZE_MAX;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001138 }
1139}
1140
1141/*
1142 * Sets the maximum number of bytes that the heap source is allowed
1143 * to allocate from the system. Clamps to the appropriate maximum
1144 * value.
1145 */
1146static void
1147setIdealFootprint(size_t max)
1148{
1149 HeapSource *hs = gHs;
1150#if DEBUG_HEAP_SOURCE
1151 HeapSource oldHs = *hs;
Barry Hayes06f254e2009-12-16 16:51:04 -08001152 mspace msp = hs->heaps[0].msp;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001153 size_t oldAllowedFootprint =
1154 mspace_max_allowed_footprint(msp);
1155#endif
1156
1157 HS_BOILERPLATE();
1158
Carl Shapiro23966772011-01-16 14:05:53 -08001159 if (max > hs->maximumSize) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001160 LOGI_HEAP("Clamp target GC heap from %zd.%03zdMB to %u.%03uMB\n",
1161 FRACTIONAL_MB(max),
Carl Shapiro23966772011-01-16 14:05:53 -08001162 FRACTIONAL_MB(hs->maximumSize));
1163 max = hs->maximumSize;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001164 }
1165
1166 /* Convert max into a size that applies to the active heap.
Carl Shapiroe7bdd8b2010-12-17 15:34:52 -08001167 * Old heaps will count against the ideal size.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001168 */
1169 size_t overhead = getSoftFootprint(false);
1170 size_t activeMax;
1171 if (overhead < max) {
1172 activeMax = max - overhead;
1173 } else {
1174 activeMax = 0;
1175 }
1176
1177 setSoftLimit(hs, activeMax);
1178 hs->idealSize = max;
1179
1180 HSTRACE("IDEAL %zd->%zd (%d), soft %zd->%zd (%d), allowed %zd->%zd (%d), "
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001181 oldHs.idealSize, hs->idealSize, hs->idealSize - oldHs.idealSize,
1182 oldHs.softLimit, hs->softLimit, hs->softLimit - oldHs.softLimit,
1183 oldAllowedFootprint, mspace_max_allowed_footprint(msp),
Carl Shapiroe7bdd8b2010-12-17 15:34:52 -08001184 mspace_max_allowed_footprint(msp) - oldAllowedFootprint);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001185
1186}
1187
1188/*
1189 * Make the ideal footprint equal to the current footprint.
1190 */
1191static void
1192snapIdealFootprint()
1193{
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001194 HS_BOILERPLATE();
1195
1196 setIdealFootprint(getSoftFootprint(true));
1197}
1198
1199/*
1200 * Gets the current ideal heap utilization, represented as a number
1201 * between zero and one.
1202 */
1203float dvmGetTargetHeapUtilization()
1204{
1205 HeapSource *hs = gHs;
1206
1207 HS_BOILERPLATE();
1208
1209 return (float)hs->targetUtilization / (float)HEAP_UTILIZATION_MAX;
1210}
1211
1212/*
1213 * Sets the new ideal heap utilization, represented as a number
1214 * between zero and one.
1215 */
1216void dvmSetTargetHeapUtilization(float newTarget)
1217{
1218 HeapSource *hs = gHs;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001219
1220 HS_BOILERPLATE();
1221
1222 /* Clamp it to a reasonable range.
1223 */
1224 // TODO: This may need some tuning.
1225 if (newTarget < 0.2) {
1226 newTarget = 0.2;
1227 } else if (newTarget > 0.8) {
1228 newTarget = 0.8;
1229 }
1230
1231 hs->targetUtilization =
1232 (size_t)(newTarget * (float)HEAP_UTILIZATION_MAX);
Carl Shapirode750892010-06-08 16:37:12 -07001233 LOGV("Set heap target utilization to %zd/%d (%f)\n",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001234 hs->targetUtilization, HEAP_UTILIZATION_MAX, newTarget);
1235}
1236
1237/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001238 * Given the size of a live set, returns the ideal heap size given
1239 * the current target utilization and MIN/MAX values.
1240 *
1241 * targetUtilization is in the range 1..HEAP_UTILIZATION_MAX.
1242 */
1243static size_t
Carl Shapiro98389d02010-02-14 23:11:47 -08001244getUtilizationTarget(size_t liveSize, size_t targetUtilization)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001245{
1246 size_t targetSize;
1247
1248 /* Use the current target utilization ratio to determine the
1249 * ideal heap size based on the size of the live set.
1250 */
1251 targetSize = (liveSize / targetUtilization) * HEAP_UTILIZATION_MAX;
1252
1253 /* Cap the amount of free space, though, so we don't end up
1254 * with, e.g., 8MB of free space when the live set size hits 8MB.
1255 */
1256 if (targetSize > liveSize + HEAP_IDEAL_FREE) {
1257 targetSize = liveSize + HEAP_IDEAL_FREE;
1258 } else if (targetSize < liveSize + HEAP_MIN_FREE) {
1259 targetSize = liveSize + HEAP_MIN_FREE;
1260 }
1261 return targetSize;
1262}
1263
1264/*
1265 * Given the current contents of the active heap, increase the allowed
1266 * heap footprint to match the target utilization ratio. This
1267 * should only be called immediately after a full mark/sweep.
1268 */
1269void dvmHeapSourceGrowForUtilization()
1270{
1271 HeapSource *hs = gHs;
1272 Heap *heap;
1273 size_t targetHeapSize;
1274 size_t currentHeapUsed;
1275 size_t oldIdealSize;
1276 size_t newHeapMax;
1277 size_t overhead;
Carl Shapiro2c81bdc2010-09-07 16:19:01 -07001278 size_t freeBytes;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001279
1280 HS_BOILERPLATE();
1281 heap = hs2heap(hs);
1282
1283 /* Use the current target utilization ratio to determine the
1284 * ideal heap size based on the size of the live set.
1285 * Note that only the active heap plays any part in this.
1286 *
1287 * Avoid letting the old heaps influence the target free size,
1288 * because they may be full of objects that aren't actually
1289 * in the working set. Just look at the allocated size of
1290 * the current heap.
1291 */
1292 currentHeapUsed = heap->bytesAllocated;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001293 targetHeapSize =
Carl Shapiro98389d02010-02-14 23:11:47 -08001294 getUtilizationTarget(currentHeapUsed, hs->targetUtilization);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001295
1296 /* The ideal size includes the old heaps; add overhead so that
1297 * it can be immediately subtracted again in setIdealFootprint().
1298 * If the target heap size would exceed the max, setIdealFootprint()
1299 * will clamp it to a legal value.
1300 */
1301 overhead = getSoftFootprint(false);
1302 oldIdealSize = hs->idealSize;
1303 setIdealFootprint(targetHeapSize + overhead);
1304
Carl Shapiro2c81bdc2010-09-07 16:19:01 -07001305 freeBytes = getAllocLimit(hs);
1306 if (freeBytes < CONCURRENT_MIN_FREE) {
1307 /* Not enough free memory to allow a concurrent GC. */
1308 heap->concurrentStartBytes = SIZE_MAX;
1309 } else {
1310 heap->concurrentStartBytes = freeBytes - CONCURRENT_START;
1311 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001312 newHeapMax = mspace_max_allowed_footprint(heap->msp);
Carl Shapiro88a4f792011-01-14 19:05:23 -08001313 if (isSoftLimited(hs)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001314 LOGD_HEAP("GC old usage %zd.%zd%%; now "
1315 "%zd.%03zdMB used / %zd.%03zdMB soft max "
1316 "(%zd.%03zdMB over, "
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001317 "%zd.%03zdMB real max)\n",
1318 FRACTIONAL_PCT(currentHeapUsed, oldIdealSize),
1319 FRACTIONAL_MB(currentHeapUsed),
1320 FRACTIONAL_MB(hs->softLimit),
1321 FRACTIONAL_MB(overhead),
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001322 FRACTIONAL_MB(newHeapMax));
1323 } else {
1324 LOGD_HEAP("GC old usage %zd.%zd%%; now "
1325 "%zd.%03zdMB used / %zd.%03zdMB real max "
Carl Shapiroe7bdd8b2010-12-17 15:34:52 -08001326 "(%zd.%03zdMB over)\n",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001327 FRACTIONAL_PCT(currentHeapUsed, oldIdealSize),
1328 FRACTIONAL_MB(currentHeapUsed),
1329 FRACTIONAL_MB(newHeapMax),
Carl Shapiroe7bdd8b2010-12-17 15:34:52 -08001330 FRACTIONAL_MB(overhead));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001331 }
1332}
1333
1334/*
1335 * Return free pages to the system.
1336 * TODO: move this somewhere else, especially the native heap part.
1337 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001338static void releasePagesInRange(void *start, void *end, void *nbytes)
1339{
1340 /* Linux requires that the madvise() start address is page-aligned.
1341 * We also align the end address.
1342 */
1343 start = (void *)ALIGN_UP_TO_PAGE_SIZE(start);
Andy McFadden96516932009-10-28 17:39:02 -07001344 end = (void *)((size_t)end & ~(SYSTEM_PAGE_SIZE - 1));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001345 if (start < end) {
1346 size_t length = (char *)end - (char *)start;
1347 madvise(start, length, MADV_DONTNEED);
1348 *(size_t *)nbytes += length;
1349 }
1350}
1351
1352/*
1353 * Return unused memory to the system if possible.
1354 */
1355void
1356dvmHeapSourceTrim(size_t bytesTrimmed[], size_t arrayLen)
1357{
1358 HeapSource *hs = gHs;
1359 size_t nativeBytes, heapBytes;
1360 size_t i;
1361
1362 HS_BOILERPLATE();
1363
1364 assert(arrayLen >= hs->numHeaps);
1365
1366 heapBytes = 0;
1367 for (i = 0; i < hs->numHeaps; i++) {
1368 Heap *heap = &hs->heaps[i];
1369
1370 /* Return the wilderness chunk to the system.
1371 */
1372 mspace_trim(heap->msp, 0);
1373
1374 /* Return any whole free pages to the system.
1375 */
1376 bytesTrimmed[i] = 0;
Carl Shapirode750892010-06-08 16:37:12 -07001377 mspace_walk_free_pages(heap->msp, releasePagesInRange,
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001378 &bytesTrimmed[i]);
1379 heapBytes += bytesTrimmed[i];
1380 }
1381
1382 /* Same for the native heap.
1383 */
1384 dlmalloc_trim(0);
1385 nativeBytes = 0;
1386 dlmalloc_walk_free_pages(releasePagesInRange, &nativeBytes);
1387
1388 LOGD_HEAP("madvised %zd (GC) + %zd (native) = %zd total bytes\n",
1389 heapBytes, nativeBytes, heapBytes + nativeBytes);
1390}
1391
1392/*
1393 * Walks over the heap source and passes every allocated and
1394 * free chunk to the callback.
1395 */
1396void
1397dvmHeapSourceWalk(void(*callback)(const void *chunkptr, size_t chunklen,
1398 const void *userptr, size_t userlen,
1399 void *arg),
1400 void *arg)
1401{
1402 HeapSource *hs = gHs;
1403 size_t i;
1404
1405 HS_BOILERPLATE();
1406
1407 /* Walk the heaps from oldest to newest.
1408 */
1409//TODO: do this in address order
1410 for (i = hs->numHeaps; i > 0; --i) {
1411 mspace_walk_heap(hs->heaps[i-1].msp, callback, arg);
1412 }
1413}
1414
1415/*
1416 * Gets the number of heaps available in the heap source.
1417 *
1418 * Caller must hold the heap lock, because gHs caches a field
1419 * in gDvm.gcHeap.
1420 */
1421size_t
1422dvmHeapSourceGetNumHeaps()
1423{
1424 HeapSource *hs = gHs;
1425
1426 HS_BOILERPLATE();
1427
1428 return hs->numHeaps;
1429}
1430
Carl Shapirod25566d2010-03-11 20:39:47 -08001431void *dvmHeapSourceGetImmuneLimit(GcMode mode)
1432{
1433 if (mode == GC_PARTIAL) {
1434 return hs2heap(gHs)->base;
1435 } else {
1436 return NULL;
1437 }
1438}