1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <cutils/mspace.h> 182c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro#include <stdint.h> // for SIZE_MAX 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <sys/mman.h> 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <errno.h> 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h" 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/Heap.h" 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/HeapInternal.h" 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/HeapSource.h" 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/HeapBitmap.h" 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// TODO: find a real header file for these. 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectextern int dlmalloc_trim(size_t); 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectextern void dlmalloc_walk_free_pages(void(*)(void*, void*, void*), void*); 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void snapIdealFootprint(void); 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void setIdealFootprint(size_t max); 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define ALIGN_UP_TO_PAGE_SIZE(p) \ 3696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden (((size_t)(p) + (SYSTEM_PAGE_SIZE - 1)) & ~(SYSTEM_PAGE_SIZE - 1)) 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define ALIGN_DOWN_TO_PAGE_SIZE(p) \ 3896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden ((size_t)(p) & ~(SYSTEM_PAGE_SIZE - 1)) 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define HEAP_UTILIZATION_MAX 1024 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define DEFAULT_HEAP_UTILIZATION 512 // Range 1..HEAP_UTILIZATION_MAX 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define HEAP_IDEAL_FREE (2 * 1024 * 1024) 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define HEAP_MIN_FREE (HEAP_IDEAL_FREE / 4) 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 452c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro/* Start a concurrent collection when free memory falls under this 462c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro * many bytes. 472c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro */ 482c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro#define CONCURRENT_START (128 << 10) 492c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro 502c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro/* The next GC will not be concurrent when free memory after a GC is 512c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro * under this many bytes. 52ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro */ 532c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro#define CONCURRENT_MIN_FREE (CONCURRENT_START + (128 << 10)) 54ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define HS_BOILERPLATE() \ 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project do { \ 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(gDvm.gcHeap != NULL); \ 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(gDvm.gcHeap->heapSource != NULL); \ 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(gHs == gDvm.gcHeap->heapSource); \ 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } while (0) 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define DEBUG_HEAP_SOURCE 0 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DEBUG_HEAP_SOURCE 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define HSTRACE(...) LOG(LOG_INFO, LOG_TAG "-hs", __VA_ARGS__) 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define HSTRACE(...) /**/ 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project======================================================= 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project======================================================= 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project======================================================= 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectHow will this be used? 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectallocating/freeing: Heap.c just wants to say "alloc(n)" and get a ptr 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project - if allocating in large doesn't work, try allocating from small 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectHeap.c will use HeapSource.h; HeapSource.c will do the right thing 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project between small and large 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project - some operations should be abstracted; put in a structure 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectHow do we manage the size trade-offs? 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project- keep mspace max footprint clamped to actual footprint 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project- if small-alloc returns null, adjust large vs. small ratio 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project - give small all available slack and retry 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project - success or fail, snap back to actual footprint and give rest to large 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectmanaged as "small actual" + "large actual" + "delta to allowed total footprint" 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project- when allocating from one source or the other, give the delta to the 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project active source, but snap back afterwards 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project- that may not work so great for a gc heap, because small will always consume. 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project - but we need to use the memory, and the current max is the amount we 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project need to fill before a GC. 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectFind a way to permanently steal pages from the middle of the heap 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project - segment tricks? 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectAllocate String and char[] in a separate heap? 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectMaybe avoid growing small heap, even if there's slack? Look at 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectlive ratio of small heap after a gc; scale it based on that. 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project======================================================= 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project======================================================= 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project======================================================= 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project*/ 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct { 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The mspace to allocate from. 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 11006f254ec0102b43fa4faed2483befd945bc12996Barry Hayes mspace msp; 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The largest size that this heap is allowed to grow to. 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t absoluteMaxSize; 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Number of bytes allocated from this mspace for objects, 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * including any overhead. This value is NOT exact, and 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * should only be used as an input for certain heuristics. 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t bytesAllocated; 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1222c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro /* Number of bytes allocated from this mspace at which a 1232c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro * concurrent garbage collection will be started. 124ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro */ 1252c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro size_t concurrentStartBytes; 126ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Number of objects currently allocated from this mspace. 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t objectsAllocated; 130f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro 131f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro /* 132f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro * The lowest address of this heap, inclusive. 133f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro */ 134f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro char *base; 135f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro 136f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro /* 137f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro * The highest address of this heap, exclusive. 138f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro */ 139f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro char *limit; 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} Heap; 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstruct HeapSource { 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Target ideal heap utilization ratio; range 1..HEAP_UTILIZATION_MAX 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t targetUtilization; 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Requested minimum heap size, or zero if there is no minimum. 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t minimumSize; 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The starting heap size. 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t startSize; 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The largest that the heap source as a whole is allowed to grow. 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t absoluteMaxSize; 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The desired max size of the heap source as a whole. 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t idealSize; 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The maximum number of bytes allowed to be allocated from the 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * active heap before a GC is forced. This is used to "shrink" the 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * heap in lieu of actual compaction. 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t softLimit; 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The heaps; heaps[0] is always the active heap, 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * which new objects should be allocated from. 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Heap heaps[HEAP_SOURCE_MAX_HEAP_COUNT]; 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The current number of heaps. 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t numHeaps; 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* External allocation count. 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t externalBytesAllocated; 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The maximum number of external bytes that may be allocated. 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t externalLimit; 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* True if zygote mode was active when the HeapSource was created. 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool sawZygote; 189a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro 190a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro /* 191a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro * The base address of the virtual memory reservation. 192a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro */ 193a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro char *heapBase; 194a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro 195a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro /* 196a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro * The length in bytes of the virtual memory reservation. 197a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro */ 198a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro size_t heapLength; 199f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro 200f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro /* 201d77f7fdc429c3aa5c8ff429278d0178392c760b5Carl Shapiro * The live object bitmap. 202f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro */ 203d77f7fdc429c3aa5c8ff429278d0178392c760b5Carl Shapiro HeapBitmap liveBits; 204f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro 205f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro /* 206f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro * The mark bitmap. 207f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro */ 208f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro HeapBitmap markBits; 209ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro 210ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro /* 211ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro * State for the GC daemon. 212ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro */ 213ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro bool hasGcThread; 214ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro pthread_t gcThread; 215ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro bool gcThreadShutdown; 216ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro pthread_mutex_t gcThreadMutex; 217ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro pthread_cond_t gcThreadCond; 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}; 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define hs2heap(hs_) (&((hs_)->heaps[0])) 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns true iff a soft limit is in effect for the active heap. 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline bool 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectsoftLimited(const HeapSource *hs) 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 2282c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro /* softLimit will be either SIZE_MAX or the limit for the 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * active mspace. idealSize can be greater than softLimit 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if there is more than one heap. If there is only one 2312c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro * heap, a non-SIZE_MAX softLimit should always be the same 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * as idealSize. 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return hs->softLimit <= hs->idealSize; 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2382c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro * Returns approximately the maximum number of bytes allowed to be 2392c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro * allocated from the active heap before a GC is forced. 2402c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro */ 2412c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapirostatic size_t 2422c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl ShapirogetAllocLimit(const HeapSource *hs) 2432c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro{ 2442c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro if (softLimited(hs)) { 2452c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro return hs->softLimit; 2462c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro } else { 2472c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro return mspace_max_allowed_footprint(hs2heap(hs)->msp); 2482c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro } 2492c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro} 2502c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro 2512c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro/* 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the current footprint of all heaps. If includeActive 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is false, don't count the heap at index 0. 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline size_t 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectoldHeapOverhead(const HeapSource *hs, bool includeActive) 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t footprint = 0; 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t i; 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (includeActive) { 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project i = 0; 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project i = 1; 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (/* i = i */; i < hs->numHeaps; i++) { 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: include size of bitmaps? If so, don't use bitsLen, listen to .max 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project footprint += mspace_footprint(hs->heaps[i].msp); 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return footprint; 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the heap that <ptr> could have come from, or NULL 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if it could not have come from any heap. 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline Heap * 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectptr2heap(const HeapSource *hs, const void *ptr) 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const size_t numHeaps = hs->numHeaps; 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t i; 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: unroll this to HEAP_SOURCE_MAX_HEAP_COUNT 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (ptr != NULL) { 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = 0; i < numHeaps; i++) { 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const Heap *const heap = &hs->heaps[i]; 287f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro 288f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro if ((const char *)ptr >= heap->base && (const char *)ptr < heap->limit) { 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return (Heap *)heap; 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Functions to update heapSource->bytesAllocated when an object 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is allocated or freed. mspace_usable_size() will give 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * us a much more accurate picture of heap utilization than 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the requested byte sizes would. 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * These aren't exact, and should not be treated as such. 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 304ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapirostatic void countAllocation(Heap *heap, const void *ptr, bool isObj) 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 306f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro HeapSource *hs; 307f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(heap->bytesAllocated < mspace_footprint(heap->msp)); 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project heap->bytesAllocated += mspace_usable_size(heap->msp, ptr) + 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HEAP_SOURCE_CHUNK_OVERHEAD; 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (isObj) { 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project heap->objectsAllocated++; 314f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro hs = gDvm.gcHeap->heapSource; 315d77f7fdc429c3aa5c8ff429278d0178392c760b5Carl Shapiro dvmHeapBitmapSetObjectBit(&hs->liveBits, ptr); 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(heap->bytesAllocated < mspace_footprint(heap->msp)); 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 3218881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapirostatic void countFree(Heap *heap, const void *ptr, size_t *numBytes) 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 323f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro HeapSource *hs; 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t delta; 325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project delta = mspace_usable_size(heap->msp, ptr) + HEAP_SOURCE_CHUNK_OVERHEAD; 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(delta > 0); 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (delta < heap->bytesAllocated) { 329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project heap->bytesAllocated -= delta; 330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project heap->bytesAllocated = 0; 332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 3338881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro hs = gDvm.gcHeap->heapSource; 3348881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro dvmHeapBitmapClearObjectBit(&hs->liveBits, ptr); 3358881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro if (heap->objectsAllocated > 0) { 3368881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro heap->objectsAllocated--; 337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 3388881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro *numBytes += delta; 339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic HeapSource *gHs = NULL; 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 34306f254ec0102b43fa4faed2483befd945bc12996Barry Hayesstatic mspace 344a199eb70871a8c142a723d76b1b08939286a3199Carl ShapirocreateMspace(void *base, size_t startSize, size_t absoluteMaxSize) 345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 34606f254ec0102b43fa4faed2483befd945bc12996Barry Hayes mspace msp; 347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Create an unlocked dlmalloc mspace to use as 349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a small-object heap source. 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We start off reserving heapSizeStart/2 bytes but 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * letting the heap grow to heapSizeStart. This saves 353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * memory in the case where a process uses even less 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * than the starting size. 355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV_HEAP("Creating VM heap of size %u\n", startSize); 357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project errno = 0; 358a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro msp = create_contiguous_mspace_with_base(startSize/2, 359a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro absoluteMaxSize, /*locked=*/false, base); 360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (msp != NULL) { 361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Don't let the heap grow past the starting size without 362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * our intervention. 363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mspace_set_max_allowed_footprint(msp, startSize); 365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* There's no guarantee that errno has meaning when the call 367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * fails, but it often does. 368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 369c5f53e2c1107e8a62638038bbff163731908da34Elliott Hughes LOGE_HEAP("Can't create VM heap of size (%u,%u): %s\n", 370c5f53e2c1107e8a62638038bbff163731908da34Elliott Hughes startSize/2, absoluteMaxSize, strerror(errno)); 371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return msp; 374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool 37706f254ec0102b43fa4faed2483befd945bc12996Barry HayesaddNewHeap(HeapSource *hs, mspace msp, size_t mspAbsoluteMaxSize) 378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Heap heap; 380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (hs->numHeaps >= HEAP_SOURCE_MAX_HEAP_COUNT) { 382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Attempt to create too many heaps (%zd >= %zd)\n", 383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs->numHeaps, HEAP_SOURCE_MAX_HEAP_COUNT); 384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memset(&heap, 0, sizeof(heap)); 389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (msp != NULL) { 391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project heap.msp = msp; 392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project heap.absoluteMaxSize = mspAbsoluteMaxSize; 3932c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro heap.concurrentStartBytes = SIZE_MAX; 394f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro heap.base = hs->heapBase; 395f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro heap.limit = hs->heapBase + heap.absoluteMaxSize; 396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 39788c57e189ecf7d5ed64d1073a37839b250874aa5Carl Shapiro void *sbrk0 = contiguous_mspace_sbrk0(hs->heaps[0].msp); 39888c57e189ecf7d5ed64d1073a37839b250874aa5Carl Shapiro char *base = (char *)ALIGN_UP_TO_PAGE_SIZE(sbrk0); 39988c57e189ecf7d5ed64d1073a37839b250874aa5Carl Shapiro size_t overhead = base - hs->heaps[0].base; 400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 40188c57e189ecf7d5ed64d1073a37839b250874aa5Carl Shapiro assert(((size_t)hs->heaps[0].base & (SYSTEM_PAGE_SIZE - 1)) == 0); 402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (overhead + HEAP_MIN_FREE >= hs->absoluteMaxSize) { 403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE_HEAP("No room to create any more heaps " 404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "(%zd overhead, %zd max)\n", 405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project overhead, hs->absoluteMaxSize); 406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 408d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro hs->heaps[0].absoluteMaxSize = overhead; 409f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro hs->heaps[0].limit = base; 41088c57e189ecf7d5ed64d1073a37839b250874aa5Carl Shapiro heap.absoluteMaxSize = hs->absoluteMaxSize - overhead; 411a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro heap.msp = createMspace(base, HEAP_MIN_FREE, heap.absoluteMaxSize); 4122c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro heap.concurrentStartBytes = HEAP_MIN_FREE - CONCURRENT_START; 413f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro heap.base = base; 414f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro heap.limit = heap.base + heap.absoluteMaxSize; 415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (heap.msp == NULL) { 416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Don't let the soon-to-be-old heap grow any further. 421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (hs->numHeaps > 0) { 42306f254ec0102b43fa4faed2483befd945bc12996Barry Hayes mspace msp = hs->heaps[0].msp; 424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mspace_set_max_allowed_footprint(msp, mspace_footprint(msp)); 425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Put the new heap in the list, at heaps[0]. 428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Shift existing heaps down. 429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memmove(&hs->heaps[1], &hs->heaps[0], hs->numHeaps * sizeof(hs->heaps[0])); 431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs->heaps[0] = heap; 432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs->numHeaps++; 433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 438ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro * The garbage collection daemon. Initiates a concurrent collection 439ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro * when signaled. 440ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro */ 441ec805eaed940e40212e85b58b163c7649feaca56Carl Shapirostatic void *gcDaemonThread(void* arg) 442ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro{ 443ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro dvmChangeStatus(NULL, THREAD_VMWAIT); 444ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro dvmLockMutex(&gHs->gcThreadMutex); 445ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro while (gHs->gcThreadShutdown != true) { 446ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro dvmWaitCond(&gHs->gcThreadCond, &gHs->gcThreadMutex); 447ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro dvmLockHeap(); 448ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro dvmChangeStatus(NULL, THREAD_RUNNING); 449ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro dvmCollectGarbageInternal(false, GC_CONCURRENT); 450ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro dvmChangeStatus(NULL, THREAD_VMWAIT); 451ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro dvmUnlockHeap(); 452ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro } 453ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro dvmChangeStatus(NULL, THREAD_RUNNING); 454ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro return NULL; 455ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro} 456ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro 457ec805eaed940e40212e85b58b163c7649feaca56Carl Shapirostatic bool gcDaemonStartup(void) 458ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro{ 459ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro dvmInitMutex(&gHs->gcThreadMutex); 460ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro pthread_cond_init(&gHs->gcThreadCond, NULL); 461ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro gHs->gcThreadShutdown = false; 462ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro gHs->hasGcThread = dvmCreateInternalThread(&gHs->gcThread, "GC", 463ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro gcDaemonThread, NULL); 464ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro return gHs->hasGcThread; 465ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro} 466ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro 467ec805eaed940e40212e85b58b163c7649feaca56Carl Shapirostatic void gcDaemonShutdown(void) 468ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro{ 469fe6087708cdeafecf223dd1d2d5e6606db70a4e1Carl Shapiro if (gHs->hasGcThread) { 470ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro dvmLockMutex(&gHs->gcThreadMutex); 471ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro gHs->gcThreadShutdown = true; 472ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro dvmSignalCond(&gHs->gcThreadCond); 473ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro dvmUnlockMutex(&gHs->gcThreadMutex); 4749e59477ceac80df2e00ee4a387df31c7c5e8d05fCarl Shapiro pthread_join(gHs->gcThread, NULL); 475ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro } 476ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro} 477ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro 478ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro/* 479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initializes the heap source; must be called before any other 480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * dvmHeapSource*() functions. Returns a GcHeap structure 481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * allocated from the heap source. 482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGcHeap * 484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdvmHeapSourceStartup(size_t startSize, size_t absoluteMaxSize) 485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GcHeap *gcHeap; 487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HeapSource *hs; 488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mspace msp; 489a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro size_t length; 490a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro void *base; 491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(gHs == NULL); 493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (startSize > absoluteMaxSize) { 495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Bad heap parameters (start=%d, max=%d)\n", 496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project startSize, absoluteMaxSize); 497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 500a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro /* 501a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro * Allocate a contiguous region of virtual memory to subdivided 502a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro * among the heaps managed by the garbage collector. 503a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro */ 504a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro length = ALIGN_UP_TO_PAGE_SIZE(absoluteMaxSize); 5056e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes base = dvmAllocRegion(length, PROT_NONE, "dalvik-heap"); 5066e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes if (base == NULL) { 507a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro return NULL; 508a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro } 509a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro 510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Create an unlocked dlmalloc mspace to use as 511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the small object heap source. 512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 513a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro msp = createMspace(base, startSize, absoluteMaxSize); 514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (msp == NULL) { 515a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro goto fail; 516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Allocate a descriptor from the heap we just created. 519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap = mspace_malloc(msp, sizeof(*gcHeap)); 521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gcHeap == NULL) { 522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE_HEAP("Can't allocate heap descriptor\n"); 523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto fail; 524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memset(gcHeap, 0, sizeof(*gcHeap)); 526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs = mspace_malloc(msp, sizeof(*hs)); 528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (hs == NULL) { 529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE_HEAP("Can't allocate heap source\n"); 530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto fail; 531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memset(hs, 0, sizeof(*hs)); 533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs->targetUtilization = DEFAULT_HEAP_UTILIZATION; 535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs->minimumSize = 0; 536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs->startSize = startSize; 537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs->absoluteMaxSize = absoluteMaxSize; 538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs->idealSize = startSize; 5392c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro hs->softLimit = SIZE_MAX; // no soft limit at first 540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs->numHeaps = 0; 541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs->sawZygote = gDvm.zygote; 542ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro hs->hasGcThread = false; 543a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro hs->heapBase = base; 544a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro hs->heapLength = length; 545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!addNewHeap(hs, msp, absoluteMaxSize)) { 546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE_HEAP("Can't add initial heap\n"); 547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto fail; 548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 549d77f7fdc429c3aa5c8ff429278d0178392c760b5Carl Shapiro if (!dvmHeapBitmapInit(&hs->liveBits, base, length, "dalvik-bitmap-1")) { 550d77f7fdc429c3aa5c8ff429278d0178392c760b5Carl Shapiro LOGE_HEAP("Can't create liveBits\n"); 551f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro goto fail; 552f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro } 553f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro if (!dvmHeapBitmapInit(&hs->markBits, base, length, "dalvik-bitmap-2")) { 554f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro LOGE_HEAP("Can't create markBits\n"); 555d77f7fdc429c3aa5c8ff429278d0178392c760b5Carl Shapiro dvmHeapBitmapDelete(&hs->liveBits); 556f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro goto fail; 557f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro } 558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 559f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro gcHeap->markContext.bitmap = &hs->markBits; 560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcHeap->heapSource = hs; 561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project countAllocation(hs2heap(hs), gcHeap, false); 563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project countAllocation(hs2heap(hs), hs, false); 564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gHs = hs; 566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return gcHeap; 567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfail: 569a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro munmap(base, length); 570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 573ec805eaed940e40212e85b58b163c7649feaca56Carl Shapirobool dvmHeapSourceStartupAfterZygote(void) 574ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro{ 575ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro return gDvm.concurrentMarkSweep ? gcDaemonStartup() : true; 576ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro} 577ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro 578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is called while in zygote mode, right before we fork() for the 580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * first time. We create a heap for all future zygote process allocations, 581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in an attempt to avoid touching pages in the zygote heap. (This would 582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * probably be unnecessary if we had a compacting GC -- the source of our 583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * troubles is small allocations filling in the gaps from larger ones.) 584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool 586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdvmHeapSourceStartupBeforeFork() 587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HeapSource *hs = gHs; // use a local to avoid the implicit "volatile" 589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HS_BOILERPLATE(); 591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(gDvm.zygote); 593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!gDvm.newZygoteHeapAllocated) { 595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Create a new heap for post-fork zygote allocations. We only 596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * try once, even if it fails. 597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 598dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden LOGV("Splitting out new zygote heap\n"); 599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.newZygoteHeapAllocated = true; 600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return addNewHeap(hs, NULL, 0); 601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 605ec805eaed940e40212e85b58b163c7649feaca56Carl Shapirovoid dvmHeapSourceThreadShutdown(void) 606ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro{ 607fe6087708cdeafecf223dd1d2d5e6606db70a4e1Carl Shapiro if (gDvm.gcHeap != NULL && gDvm.concurrentMarkSweep) { 608d7de450bfc47208409da7614e8f904a4a7cb20dcCarl Shapiro gcDaemonShutdown(); 609d7de450bfc47208409da7614e8f904a4a7cb20dcCarl Shapiro } 610ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro} 611ec805eaed940e40212e85b58b163c7649feaca56Carl Shapiro 612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 613a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro * Tears down the entire GcHeap structure and all of the substructures 614a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro * attached to it. This call has the side effect of setting the given 615a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro * gcHeap pointer and gHs to NULL. 616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid 618a199eb70871a8c142a723d76b1b08939286a3199Carl ShapirodvmHeapSourceShutdown(GcHeap **gcHeap) 619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 620a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro if (*gcHeap != NULL && (*gcHeap)->heapSource != NULL) { 621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HeapSource *hs; 622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 623a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro hs = (*gcHeap)->heapSource; 624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 625a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro assert((char *)*gcHeap >= hs->heapBase); 626a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro assert((char *)*gcHeap < hs->heapBase + hs->heapLength); 627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 628d77f7fdc429c3aa5c8ff429278d0178392c760b5Carl Shapiro dvmHeapBitmapDelete(&hs->liveBits); 629f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro dvmHeapBitmapDelete(&hs->markBits); 630a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro 631a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro munmap(hs->heapBase, hs->heapLength); 632a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro gHs = NULL; 633a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro *gcHeap = NULL; 634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 638b874ab98306a109c4988bb1cde687a24f4f8201fBarry Hayes * Gets the begining of the allocation for the HeapSource. 639b874ab98306a109c4988bb1cde687a24f4f8201fBarry Hayes */ 640b874ab98306a109c4988bb1cde687a24f4f8201fBarry Hayesvoid *dvmHeapSourceGetBase(void) 641b874ab98306a109c4988bb1cde687a24f4f8201fBarry Hayes{ 642b874ab98306a109c4988bb1cde687a24f4f8201fBarry Hayes return gHs->heapBase; 643b874ab98306a109c4988bb1cde687a24f4f8201fBarry Hayes} 644b874ab98306a109c4988bb1cde687a24f4f8201fBarry Hayes 645b874ab98306a109c4988bb1cde687a24f4f8201fBarry Hayes/* 646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the requested value. If the per-heap stats are requested, fill 647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * them as well. 648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Caller must hold the heap lock. 650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsize_t 652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdvmHeapSourceGetValue(enum HeapSourceValueSpec spec, size_t perHeapStats[], 653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t arrayLen) 654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HeapSource *hs = gHs; 656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t value = 0; 657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t total = 0; 658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t i; 659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HS_BOILERPLATE(); 661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (spec) { 663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case HS_EXTERNAL_BYTES_ALLOCATED: 664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return hs->externalBytesAllocated; 665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case HS_EXTERNAL_LIMIT: 666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return hs->externalLimit; 667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project default: 668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // look at all heaps. 669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ; 670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(arrayLen >= hs->numHeaps || perHeapStats == NULL); 673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = 0; i < hs->numHeaps; i++) { 674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Heap *const heap = &hs->heaps[i]; 675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (spec) { 677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case HS_FOOTPRINT: 678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project value = mspace_footprint(heap->msp); 679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case HS_ALLOWED_FOOTPRINT: 681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project value = mspace_max_allowed_footprint(heap->msp); 682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case HS_BYTES_ALLOCATED: 684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project value = heap->bytesAllocated; 685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case HS_OBJECTS_ALLOCATED: 687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project value = heap->objectsAllocated; 688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project default: 690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // quiet gcc 691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (perHeapStats) { 694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project perHeapStats[i] = value; 695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project total += value; 697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return total; 699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 701f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapirostatic void aliasBitmap(HeapBitmap *dst, HeapBitmap *src, 702f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro uintptr_t base, uintptr_t max) { 703f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro size_t offset; 704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 705f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro dst->base = base; 706f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro dst->max = max; 70773f3e6f5ef9eda738324bcd5634df172d9c6e977Barry Hayes dst->bitsLen = HB_OFFSET_TO_BYTE_INDEX(max - base) + sizeof(dst->bits); 70873f3e6f5ef9eda738324bcd5634df172d9c6e977Barry Hayes /* The exclusive limit from bitsLen is greater than the inclusive max. */ 70973f3e6f5ef9eda738324bcd5634df172d9c6e977Barry Hayes assert(base + HB_MAX_OFFSET(dst) > max); 7108a0b52386b1b34c132b11eba8e534ca26665077eBarry Hayes /* The exclusive limit is at most one word of bits beyond max. */ 7118a0b52386b1b34c132b11eba8e534ca26665077eBarry Hayes assert((base + HB_MAX_OFFSET(dst)) - max <= 71273f3e6f5ef9eda738324bcd5634df172d9c6e977Barry Hayes HB_OBJECT_ALIGNMENT * HB_BITS_PER_WORD); 713d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro dst->allocLen = dst->bitsLen; 714f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro offset = base - src->base; 715f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro assert(HB_OFFSET_TO_MASK(offset) == 1 << 31); 716f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro dst->bits = &src->bits[HB_OFFSET_TO_INDEX(offset)]; 717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 720f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro * Initializes a vector of object and mark bits to the object and mark 721e168ebd5a7cfc57936c16ff7d7f7063e967bdb9dBarry Hayes * bits of each heap. The bits are aliased to the heapsource 722f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro * object and mark bitmaps. This routine is used by the sweep code 723f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro * which needs to free each object in the correct heap. 724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 725d77f7fdc429c3aa5c8ff429278d0178392c760b5Carl Shapirovoid dvmHeapSourceGetObjectBitmaps(HeapBitmap liveBits[], HeapBitmap markBits[], 726f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro size_t numHeaps) 727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HeapSource *hs = gHs; 729f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro uintptr_t base, max; 730e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro size_t i; 731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HS_BOILERPLATE(); 733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 734f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro assert(numHeaps == hs->numHeaps); 735f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro for (i = 0; i < hs->numHeaps; ++i) { 736f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro base = (uintptr_t)hs->heaps[i].base; 73773f3e6f5ef9eda738324bcd5634df172d9c6e977Barry Hayes /* -1 because limit is exclusive but max is inclusive. */ 738e6a1b4dfc33732368bc6045501acd5e6e95f32a4Carl Shapiro max = MIN((uintptr_t)hs->heaps[i].limit - 1, hs->markBits.max); 739d77f7fdc429c3aa5c8ff429278d0178392c760b5Carl Shapiro aliasBitmap(&liveBits[i], &hs->liveBits, base, max); 740f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro aliasBitmap(&markBits[i], &hs->markBits, base, max); 741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 742f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro} 743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 744962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes/* 745962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes * Get the bitmap representing all live objects. 746962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes */ 747ec805eaed940e40212e85b58b163c7649feaca56Carl ShapiroHeapBitmap *dvmHeapSourceGetLiveBits(void) 748962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes{ 749962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes HS_BOILERPLATE(); 750962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes 751d77f7fdc429c3aa5c8ff429278d0178392c760b5Carl Shapiro return &gHs->liveBits; 752962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes} 753962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes 754f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapirovoid dvmHeapSourceSwapBitmaps(void) 755f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro{ 756f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro HeapBitmap tmp; 75781010a40820b7c74a09d11d612d12a19e0c0488dBarry Hayes 758d77f7fdc429c3aa5c8ff429278d0178392c760b5Carl Shapiro tmp = gHs->liveBits; 759d77f7fdc429c3aa5c8ff429278d0178392c760b5Carl Shapiro gHs->liveBits = gHs->markBits; 760f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro gHs->markBits = tmp; 76181010a40820b7c74a09d11d612d12a19e0c0488dBarry Hayes} 76281010a40820b7c74a09d11d612d12a19e0c0488dBarry Hayes 76381010a40820b7c74a09d11d612d12a19e0c0488dBarry Hayesvoid dvmHeapSourceZeroMarkBitmap(void) 76481010a40820b7c74a09d11d612d12a19e0c0488dBarry Hayes{ 76581010a40820b7c74a09d11d612d12a19e0c0488dBarry Hayes HS_BOILERPLATE(); 76681010a40820b7c74a09d11d612d12a19e0c0488dBarry Hayes 767f373efd3321307f54c102e02b3ee7eb922c4765cCarl Shapiro dvmHeapBitmapZero(&gHs->markBits); 768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 770425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayesvoid dvmMarkImmuneObjects(const char *immuneLimit) 771d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro{ 772d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro char *dst, *src; 773e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro size_t i, index, length; 774d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro 775d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro /* 776d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro * Copy the contents of the live bit vector for immune object 777d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro * range into the mark bit vector. 778d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro */ 779425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes /* The only values generated by dvmHeapSourceGetImmuneLimit() */ 780425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes assert(immuneLimit == gHs->heaps[0].base || 781425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes immuneLimit == NULL); 782d77f7fdc429c3aa5c8ff429278d0178392c760b5Carl Shapiro assert(gHs->liveBits.base == gHs->markBits.base); 783d77f7fdc429c3aa5c8ff429278d0178392c760b5Carl Shapiro assert(gHs->liveBits.bitsLen == gHs->markBits.bitsLen); 784425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes /* heap[0] is never immune */ 785425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes assert(gHs->heaps[0].base >= immuneLimit); 786425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes assert(gHs->heaps[0].limit > immuneLimit); 787425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes 788d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro for (i = 1; i < gHs->numHeaps; ++i) { 789425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes if (gHs->heaps[i].base < immuneLimit) { 790425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes assert(gHs->heaps[i].limit <= immuneLimit); 791425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes /* Compute the number of words to copy in the bitmap. */ 792425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes index = HB_OFFSET_TO_INDEX( 793425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes (uintptr_t)gHs->heaps[i].base - gHs->liveBits.base); 794425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes /* Compute the starting offset in the live and mark bits. */ 795425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes src = (char *)(gHs->liveBits.bits + index); 796425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes dst = (char *)(gHs->markBits.bits + index); 797425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes /* Compute the number of bytes of the live bitmap to copy. */ 798425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes length = HB_OFFSET_TO_BYTE_INDEX( 799425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes gHs->heaps[i].limit - gHs->heaps[i].base); 800425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes /* Do the copy. */ 801425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes memcpy(dst, src, length); 802425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes /* Make sure max points to the address of the highest set bit. */ 803425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes if (gHs->markBits.max < (uintptr_t)gHs->heaps[i].limit) { 804425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes gHs->markBits.max = (uintptr_t)gHs->heaps[i].limit; 805425848f6b64603f79c336c08b6e1cbca1a9f6048Barry Hayes } 806d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro } 807d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro } 808d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro} 809d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro 810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Allocates <n> bytes of zeroed data. 812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid * 814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdvmHeapSourceAlloc(size_t n) 815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HeapSource *hs = gHs; 817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Heap *heap; 818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void *ptr; 819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HS_BOILERPLATE(); 821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project heap = hs2heap(hs); 822ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro if (heap->bytesAllocated + n > hs->softLimit) { 823ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro /* 824ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro * This allocation would push us over the soft limit; act as 825ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro * if the heap is full. 826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV_HEAP("softLimit of %zd.%03zdMB hit for %zd-byte allocation\n", 828ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro FRACTIONAL_MB(hs->softLimit), n); 829ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro return NULL; 830ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro } 831ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro ptr = mspace_calloc(heap->msp, 1, n); 832ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro if (ptr == NULL) { 833ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro return NULL; 834ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro } 835ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro countAllocation(heap, ptr, true); 836ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro /* 837ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro * Check to see if a concurrent GC should be initiated. 838ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro */ 839ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro if (gDvm.gcHeap->gcRunning || !hs->hasGcThread) { 840ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro /* 841ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro * The garbage collector thread is already running or has yet 842ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro * to be started. Do nothing. 843ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro */ 844ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro return ptr; 845ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro } 8462c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro if (heap->bytesAllocated > heap->concurrentStartBytes) { 847ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro /* 8482c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro * We have exceeded the allocation threshold. Wake up the 849ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro * garbage collector. 850ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro */ 851ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro dvmSignalCond(&gHs->gcThreadCond); 852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return ptr; 854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Remove any hard limits, try to allocate, and shrink back down. 857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Last resort when trying to allocate an object. 858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void * 860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectheapAllocAndGrow(HeapSource *hs, Heap *heap, size_t n) 861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void *ptr; 863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t max; 864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Grow as much as possible, but don't let the real footprint 866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * plus external allocations go over the absolute max. 867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project max = heap->absoluteMaxSize; 869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (max > hs->externalBytesAllocated) { 870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project max -= hs->externalBytesAllocated; 871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mspace_set_max_allowed_footprint(heap->msp, max); 873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ptr = dvmHeapSourceAlloc(n); 874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Shrink back down as small as possible. Our caller may 876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * readjust max_allowed to a more appropriate value. 877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mspace_set_max_allowed_footprint(heap->msp, 879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mspace_footprint(heap->msp)); 880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ptr = NULL; 882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return ptr; 885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Allocates <n> bytes of zeroed data, growing as much as possible 889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if necessary. 890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid * 892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdvmHeapSourceAllocAndGrow(size_t n) 893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HeapSource *hs = gHs; 895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Heap *heap; 896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void *ptr; 897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t oldIdealSize; 898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HS_BOILERPLATE(); 900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project heap = hs2heap(hs); 901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ptr = dvmHeapSourceAlloc(n); 903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (ptr != NULL) { 904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return ptr; 905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project oldIdealSize = hs->idealSize; 908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (softLimited(hs)) { 909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* We're soft-limited. Try removing the soft limit to 910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * see if we can allocate without actually growing. 911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 9122c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro hs->softLimit = SIZE_MAX; 913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ptr = dvmHeapSourceAlloc(n); 914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (ptr != NULL) { 915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Removing the soft limit worked; fix things up to 916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * reflect the new effective ideal size. 917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project snapIdealFootprint(); 919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return ptr; 920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 9212c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro // softLimit intentionally left at SIZE_MAX. 922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* We're not soft-limited. Grow the heap to satisfy the request. 925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If this call fails, no footprints will have changed. 926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ptr = heapAllocAndGrow(hs, heap, n); 928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (ptr != NULL) { 929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The allocation succeeded. Fix up the ideal size to 930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * reflect any footprint modifications that had to happen. 931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project snapIdealFootprint(); 933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* We just couldn't do it. Restore the original ideal size, 935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * fixing up softLimit if necessary. 936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project setIdealFootprint(oldIdealSize); 938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return ptr; 940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 9438881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro * Frees the first numPtrs objects in the ptrs list and returns the 9448881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro * amount of reclaimed storage. The list must contain addresses all in 9458881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro * the same mspace, and must be in increasing order. This implies that 9468881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro * there are no duplicates, and no entries are NULL. 947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 9488881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapirosize_t dvmHeapSourceFreeList(size_t numPtrs, void **ptrs) 949dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes{ 950dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes Heap *heap; 9518881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro size_t numBytes; 952dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes 953dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes HS_BOILERPLATE(); 954dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes 955dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes if (numPtrs == 0) { 9568881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro return 0; 957dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes } 958dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes 959dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes assert(ptrs != NULL); 960dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes assert(*ptrs != NULL); 961dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes heap = ptr2heap(gHs, *ptrs); 9628881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro numBytes = 0; 963dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes if (heap != NULL) { 964dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes mspace *msp = heap->msp; 965dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes // Calling mspace_free on shared heaps disrupts sharing too 966dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes // much. For heap[0] -- the 'active heap' -- we call 967dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes // mspace_free, but on the other heaps we only do some 968dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes // accounting. 969dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes if (heap == gHs->heaps) { 970dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes // mspace_merge_objects takes two allocated objects, and 971dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes // if the second immediately follows the first, will merge 972dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes // them, returning a larger object occupying the same 973dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes // memory. This is a local operation, and doesn't require 974dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes // dlmalloc to manipulate any freelists. It's pretty 975dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes // inexpensive compared to free(). 976dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes 977dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes // ptrs is an array of objects all in memory order, and if 978dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes // client code has been allocating lots of short-lived 979dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes // objects, this is likely to contain runs of objects all 980dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes // now garbage, and thus highly amenable to this optimization. 981dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes 982dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes // Unroll the 0th iteration around the loop below, 983dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes // countFree ptrs[0] and initializing merged. 984dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes assert(ptrs[0] != NULL); 985dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes assert(ptr2heap(gHs, ptrs[0]) == heap); 9868881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro countFree(heap, ptrs[0], &numBytes); 987dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes void *merged = ptrs[0]; 988dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes 989dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes size_t i; 990dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes for (i = 1; i < numPtrs; i++) { 991dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes assert(merged != NULL); 992dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes assert(ptrs[i] != NULL); 993dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes assert((intptr_t)merged < (intptr_t)ptrs[i]); 994dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes assert(ptr2heap(gHs, ptrs[i]) == heap); 9958881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro countFree(heap, ptrs[i], &numBytes); 996dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes // Try to merge. If it works, merged now includes the 997dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes // memory of ptrs[i]. If it doesn't, free merged, and 998dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes // see if ptrs[i] starts a new run of adjacent 999dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes // objects to merge. 1000dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes if (mspace_merge_objects(msp, merged, ptrs[i]) == NULL) { 1001dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes mspace_free(msp, merged); 1002dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes merged = ptrs[i]; 1003dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes } 1004dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes } 1005dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes assert(merged != NULL); 1006dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes mspace_free(msp, merged); 1007dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes } else { 1008dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes // This is not an 'active heap'. Only do the accounting. 1009dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes size_t i; 1010dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes for (i = 0; i < numPtrs; i++) { 1011dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes assert(ptrs[i] != NULL); 1012dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes assert(ptr2heap(gHs, ptrs[i]) == heap); 10138881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro countFree(heap, ptrs[i], &numBytes); 1014dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes } 1015dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes } 1016dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes } 10178881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro return numBytes; 1018dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes} 1019dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes 1020dde8ab037540aaec554a471d67613b959cc0e9f4Barry Hayes/* 1021364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes * Returns true iff <ptr> is in the heap source. 1022364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes */ 1023364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayesbool 1024364f9d924cbd9d392744a66f80cc084c3d80caf0Barry HayesdvmHeapSourceContainsAddress(const void *ptr) 1025364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes{ 1026364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes HS_BOILERPLATE(); 1027364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes 1028364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes return (dvmHeapBitmapCoversAddress(&gHs->liveBits, ptr)); 1029364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes} 1030364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes 1031364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes/* 1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns true iff <ptr> was allocated from the heap source. 1033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool 1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdvmHeapSourceContains(const void *ptr) 1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HS_BOILERPLATE(); 1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1039364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes if (dvmHeapSourceContainsAddress(ptr)) { 1040d77f7fdc429c3aa5c8ff429278d0178392c760b5Carl Shapiro return dvmHeapBitmapIsObjectBitSet(&gHs->liveBits, ptr) != 0; 1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the value of the requested flag. 1047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool 1049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdvmHeapSourceGetPtrFlag(const void *ptr, enum HeapSourcePtrFlag flag) 1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (ptr == NULL) { 1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (flag == HS_CONTAINS) { 1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return dvmHeapSourceContains(ptr); 1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (flag == HS_ALLOCATED_IN_ZYGOTE) { 1058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HeapSource *hs = gHs; 1059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HS_BOILERPLATE(); 1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (hs->sawZygote) { 1063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Heap *heap; 1064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project heap = ptr2heap(hs, ptr); 1066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (heap != NULL) { 1067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* If the object is not in the active heap, we assume that 1068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it was allocated as part of zygote. 1069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return heap != hs->heaps; 1071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The pointer is outside of any known heap, or we are not 1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * running in zygote mode. 1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 1077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 1080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the number of usable bytes in an allocated chunk; the size 1084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * may be larger than the size passed to dvmHeapSourceAlloc(). 1085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsize_t 1087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdvmHeapSourceChunkSize(const void *ptr) 1088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Heap *heap; 1090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HS_BOILERPLATE(); 1092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project heap = ptr2heap(gHs, ptr); 1094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (heap != NULL) { 1095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return mspace_usable_size(heap->msp, ptr); 1096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return 0; 1098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the number of bytes that the heap source has allocated 1102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * from the system using sbrk/mmap, etc. 1103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Caller must hold the heap lock. 1105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsize_t 1107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdvmHeapSourceFootprint() 1108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HS_BOILERPLATE(); 1110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: include size of bitmaps? 1112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return oldHeapOverhead(gHs, true); 1113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Return the real bytes used by old heaps and external memory 1117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * plus the soft usage of the current heap. When a soft limit 1118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is in effect, this is effectively what it's compared against 1119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (though, in practice, it only looks at the current heap). 1120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic size_t 1122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectgetSoftFootprint(bool includeActive) 1123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HeapSource *hs = gHs; 1125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t ret; 1126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HS_BOILERPLATE(); 1128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ret = oldHeapOverhead(hs, false) + hs->externalBytesAllocated; 1130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (includeActive) { 1131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ret += hs->heaps[0].bytesAllocated; 1132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return ret; 1135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the maximum number of bytes that the heap source is allowed 1139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to allocate from the system. 1140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsize_t 1142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdvmHeapSourceGetIdealFootprint() 1143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HeapSource *hs = gHs; 1145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HS_BOILERPLATE(); 1147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return hs->idealSize; 1149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sets the soft limit, handling any necessary changes to the allowed 1153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * footprint of the active heap. 1154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void 1156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectsetSoftLimit(HeapSource *hs, size_t softLimit) 1157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Compare against the actual footprint, rather than the 1159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * max_allowed, because the heap may not have grown all the 1160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * way to the allowed size yet. 1161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 116206f254ec0102b43fa4faed2483befd945bc12996Barry Hayes mspace msp = hs->heaps[0].msp; 1163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t currentHeapSize = mspace_footprint(msp); 1164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (softLimit < currentHeapSize) { 1165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Don't let the heap grow any more, and impose a soft limit. 1166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mspace_set_max_allowed_footprint(msp, currentHeapSize); 1168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs->softLimit = softLimit; 1169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Let the heap grow to the requested max, and remove any 1171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * soft limit, if set. 1172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mspace_set_max_allowed_footprint(msp, softLimit); 11742c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro hs->softLimit = SIZE_MAX; 1175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sets the maximum number of bytes that the heap source is allowed 1180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to allocate from the system. Clamps to the appropriate maximum 1181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * value. 1182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void 1184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectsetIdealFootprint(size_t max) 1185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HeapSource *hs = gHs; 1187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DEBUG_HEAP_SOURCE 1188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HeapSource oldHs = *hs; 118906f254ec0102b43fa4faed2483befd945bc12996Barry Hayes mspace msp = hs->heaps[0].msp; 1190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t oldAllowedFootprint = 1191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mspace_max_allowed_footprint(msp); 1192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 1193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HS_BOILERPLATE(); 1195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (max > hs->absoluteMaxSize) { 1197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI_HEAP("Clamp target GC heap from %zd.%03zdMB to %u.%03uMB\n", 1198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project FRACTIONAL_MB(max), 1199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project FRACTIONAL_MB(hs->absoluteMaxSize)); 1200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project max = hs->absoluteMaxSize; 1201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (max < hs->minimumSize) { 1202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project max = hs->minimumSize; 1203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Convert max into a size that applies to the active heap. 1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Old heaps and external allocations will count against the ideal size. 1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t overhead = getSoftFootprint(false); 1209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t activeMax; 1210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (overhead < max) { 1211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project activeMax = max - overhead; 1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project activeMax = 0; 1214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project setSoftLimit(hs, activeMax); 1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs->idealSize = max; 1218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HSTRACE("IDEAL %zd->%zd (%d), soft %zd->%zd (%d), allowed %zd->%zd (%d), " 1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "ext %zd\n", 1221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project oldHs.idealSize, hs->idealSize, hs->idealSize - oldHs.idealSize, 1222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project oldHs.softLimit, hs->softLimit, hs->softLimit - oldHs.softLimit, 1223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project oldAllowedFootprint, mspace_max_allowed_footprint(msp), 1224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mspace_max_allowed_footprint(msp) - oldAllowedFootprint, 1225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs->externalBytesAllocated); 1226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Make the ideal footprint equal to the current footprint. 1231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void 1233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectsnapIdealFootprint() 1234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HS_BOILERPLATE(); 1236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project setIdealFootprint(getSoftFootprint(true)); 1238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the current ideal heap utilization, represented as a number 1242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * between zero and one. 1243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfloat dvmGetTargetHeapUtilization() 1245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HeapSource *hs = gHs; 1247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HS_BOILERPLATE(); 1249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return (float)hs->targetUtilization / (float)HEAP_UTILIZATION_MAX; 1251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sets the new ideal heap utilization, represented as a number 1255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * between zero and one. 1256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmSetTargetHeapUtilization(float newTarget) 1258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HeapSource *hs = gHs; 1260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HS_BOILERPLATE(); 1262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Clamp it to a reasonable range. 1264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // TODO: This may need some tuning. 1266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (newTarget < 0.2) { 1267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newTarget = 0.2; 1268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (newTarget > 0.8) { 1269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newTarget = 0.8; 1270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs->targetUtilization = 1273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (size_t)(newTarget * (float)HEAP_UTILIZATION_MAX); 1274de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro LOGV("Set heap target utilization to %zd/%d (%f)\n", 1275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs->targetUtilization, HEAP_UTILIZATION_MAX, newTarget); 1276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If set is true, sets the new minimum heap size to size; always 1280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * returns the current (or previous) size. If size is negative, 1281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * removes the current minimum constraint (if present). 1282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsize_t 1284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdvmMinimumHeapSize(size_t size, bool set) 1285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HeapSource *hs = gHs; 1287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t oldMinimumSize; 1288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* gHs caches an entry in gDvm.gcHeap; we need to hold the 1290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * heap lock if we're going to look at it. We also need the 1291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * lock for the call to setIdealFootprint(). 1292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLockHeap(); 1294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HS_BOILERPLATE(); 1296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project oldMinimumSize = hs->minimumSize; 1298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (set) { 1300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Don't worry about external allocations right now. 1301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * setIdealFootprint() will take them into account when 1302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * minimumSize is used, and it's better to hold onto the 1303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * intended minimumSize than to clamp it arbitrarily based 1304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on the current allocations. 1305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (size > hs->absoluteMaxSize) { 1307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size = hs->absoluteMaxSize; 1308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs->minimumSize = size; 1310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (size > hs->idealSize) { 1311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Force a snap to the minimum value, which we just set 1312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and which setIdealFootprint() will take into consideration. 1313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project setIdealFootprint(hs->idealSize); 1315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Otherwise we'll just keep it in mind the next time 1317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * setIdealFootprint() is called. 1318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmUnlockHeap(); 1322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return oldMinimumSize; 1324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Given the size of a live set, returns the ideal heap size given 1328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the current target utilization and MIN/MAX values. 1329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * targetUtilization is in the range 1..HEAP_UTILIZATION_MAX. 1331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic size_t 133398389d0893ad3d3e06cfb38296b01de39e52db31Carl ShapirogetUtilizationTarget(size_t liveSize, size_t targetUtilization) 1334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t targetSize; 1336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Use the current target utilization ratio to determine the 1338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ideal heap size based on the size of the live set. 1339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project targetSize = (liveSize / targetUtilization) * HEAP_UTILIZATION_MAX; 1341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Cap the amount of free space, though, so we don't end up 1343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * with, e.g., 8MB of free space when the live set size hits 8MB. 1344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (targetSize > liveSize + HEAP_IDEAL_FREE) { 1346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project targetSize = liveSize + HEAP_IDEAL_FREE; 1347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (targetSize < liveSize + HEAP_MIN_FREE) { 1348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project targetSize = liveSize + HEAP_MIN_FREE; 1349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return targetSize; 1351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Given the current contents of the active heap, increase the allowed 1355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * heap footprint to match the target utilization ratio. This 1356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * should only be called immediately after a full mark/sweep. 1357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmHeapSourceGrowForUtilization() 1359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HeapSource *hs = gHs; 1361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Heap *heap; 1362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t targetHeapSize; 1363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t currentHeapUsed; 1364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t oldIdealSize; 1365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t newHeapMax; 1366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t overhead; 13672c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro size_t freeBytes; 1368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HS_BOILERPLATE(); 1370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project heap = hs2heap(hs); 1371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Use the current target utilization ratio to determine the 1373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ideal heap size based on the size of the live set. 1374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note that only the active heap plays any part in this. 1375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Avoid letting the old heaps influence the target free size, 1377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because they may be full of objects that aren't actually 1378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in the working set. Just look at the allocated size of 1379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the current heap. 1380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project currentHeapUsed = heap->bytesAllocated; 1382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define LET_EXTERNAL_INFLUENCE_UTILIZATION 1 1383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LET_EXTERNAL_INFLUENCE_UTILIZATION 1384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* This is a hack to deal with the side-effects of moving 1385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * bitmap data out of the Dalvik heap. Since the amount 1386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of free space after a GC scales with the size of the 1387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * live set, many apps expected the large free space that 1388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * appeared along with megabytes' worth of bitmaps. When 1389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the bitmaps were removed, the free size shrank significantly, 1390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and apps started GCing constantly. This makes it so the 1391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * post-GC free space is the same size it would have been 1392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if the bitmaps were still in the Dalvik heap. 1393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project currentHeapUsed += hs->externalBytesAllocated; 1395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 1396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project targetHeapSize = 139798389d0893ad3d3e06cfb38296b01de39e52db31Carl Shapiro getUtilizationTarget(currentHeapUsed, hs->targetUtilization); 1398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LET_EXTERNAL_INFLUENCE_UTILIZATION 1399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project currentHeapUsed -= hs->externalBytesAllocated; 1400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project targetHeapSize -= hs->externalBytesAllocated; 1401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 1402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The ideal size includes the old heaps; add overhead so that 1404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it can be immediately subtracted again in setIdealFootprint(). 1405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the target heap size would exceed the max, setIdealFootprint() 1406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * will clamp it to a legal value. 1407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project overhead = getSoftFootprint(false); 1409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project oldIdealSize = hs->idealSize; 1410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project setIdealFootprint(targetHeapSize + overhead); 1411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 14122c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro freeBytes = getAllocLimit(hs); 14132c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro if (freeBytes < CONCURRENT_MIN_FREE) { 14142c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro /* Not enough free memory to allow a concurrent GC. */ 14152c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro heap->concurrentStartBytes = SIZE_MAX; 14162c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro } else { 14172c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro heap->concurrentStartBytes = freeBytes - CONCURRENT_START; 14182c81bdc3bb892d7d60855e14f61854f20a9f6cb8Carl Shapiro } 1419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newHeapMax = mspace_max_allowed_footprint(heap->msp); 1420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (softLimited(hs)) { 1421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("GC old usage %zd.%zd%%; now " 1422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "%zd.%03zdMB used / %zd.%03zdMB soft max " 1423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "(%zd.%03zdMB over, " 1424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "%zd.%03zdMB ext, " 1425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "%zd.%03zdMB real max)\n", 1426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project FRACTIONAL_PCT(currentHeapUsed, oldIdealSize), 1427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project FRACTIONAL_MB(currentHeapUsed), 1428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project FRACTIONAL_MB(hs->softLimit), 1429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project FRACTIONAL_MB(overhead), 1430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project FRACTIONAL_MB(hs->externalBytesAllocated), 1431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project FRACTIONAL_MB(newHeapMax)); 1432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("GC old usage %zd.%zd%%; now " 1434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "%zd.%03zdMB used / %zd.%03zdMB real max " 1435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "(%zd.%03zdMB over, " 1436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "%zd.%03zdMB ext)\n", 1437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project FRACTIONAL_PCT(currentHeapUsed, oldIdealSize), 1438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project FRACTIONAL_MB(currentHeapUsed), 1439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project FRACTIONAL_MB(newHeapMax), 1440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project FRACTIONAL_MB(overhead), 1441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project FRACTIONAL_MB(hs->externalBytesAllocated)); 1442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Return free pages to the system. 1447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: move this somewhere else, especially the native heap part. 1448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void releasePagesInRange(void *start, void *end, void *nbytes) 1451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Linux requires that the madvise() start address is page-aligned. 1453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We also align the end address. 1454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project start = (void *)ALIGN_UP_TO_PAGE_SIZE(start); 145696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden end = (void *)((size_t)end & ~(SYSTEM_PAGE_SIZE - 1)); 1457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (start < end) { 1458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t length = (char *)end - (char *)start; 1459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project madvise(start, length, MADV_DONTNEED); 1460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *(size_t *)nbytes += length; 1461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Return unused memory to the system if possible. 1466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid 1468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdvmHeapSourceTrim(size_t bytesTrimmed[], size_t arrayLen) 1469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HeapSource *hs = gHs; 1471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t nativeBytes, heapBytes; 1472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t i; 1473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HS_BOILERPLATE(); 1475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(arrayLen >= hs->numHeaps); 1477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project heapBytes = 0; 1479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = 0; i < hs->numHeaps; i++) { 1480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Heap *heap = &hs->heaps[i]; 1481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Return the wilderness chunk to the system. 1483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mspace_trim(heap->msp, 0); 1485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Return any whole free pages to the system. 1487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bytesTrimmed[i] = 0; 1489de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro mspace_walk_free_pages(heap->msp, releasePagesInRange, 1490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project &bytesTrimmed[i]); 1491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project heapBytes += bytesTrimmed[i]; 1492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Same for the native heap. 1495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dlmalloc_trim(0); 1497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project nativeBytes = 0; 1498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dlmalloc_walk_free_pages(releasePagesInRange, &nativeBytes); 1499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD_HEAP("madvised %zd (GC) + %zd (native) = %zd total bytes\n", 1501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project heapBytes, nativeBytes, heapBytes + nativeBytes); 1502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Walks over the heap source and passes every allocated and 1506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * free chunk to the callback. 1507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid 1509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdvmHeapSourceWalk(void(*callback)(const void *chunkptr, size_t chunklen, 1510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const void *userptr, size_t userlen, 1511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void *arg), 1512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void *arg) 1513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HeapSource *hs = gHs; 1515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t i; 1516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HS_BOILERPLATE(); 1518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Walk the heaps from oldest to newest. 1520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: do this in address order 1522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = hs->numHeaps; i > 0; --i) { 1523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mspace_walk_heap(hs->heaps[i-1].msp, callback, arg); 1524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the number of heaps available in the heap source. 1529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Caller must hold the heap lock, because gHs caches a field 1531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in gDvm.gcHeap. 1532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsize_t 1534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdvmHeapSourceGetNumHeaps() 1535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HeapSource *hs = gHs; 1537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HS_BOILERPLATE(); 1539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return hs->numHeaps; 1541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * External allocation tracking 1546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In some situations, memory outside of the heap is tied to the 1548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * lifetime of objects in the heap. Since that memory is kept alive 1549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * by heap objects, it should provide memory pressure that can influence 1550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * GCs. 1551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 15531c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro/* 15541c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro * Returns true if the requested number of bytes can be allocated from 15551c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro * available storage. 15561c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro */ 15571c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapirostatic bool externalBytesAvailable(const HeapSource *hs, size_t numBytes) 1558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const Heap *heap; 15601c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro size_t currentHeapSize, newHeapSize; 1561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Make sure that this allocation is even possible. 1563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Don't let the external size plus the actual heap size 1564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * go over the absolute max. This essentially treats 1565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * external allocations as part of the active heap. 1566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note that this will fail "mysteriously" if there's 1568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a small softLimit but a large heap footprint. 1569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project heap = hs2heap(hs); 1571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project currentHeapSize = mspace_max_allowed_footprint(heap->msp); 15721c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro newHeapSize = currentHeapSize + hs->externalBytesAllocated + numBytes; 15731c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro if (newHeapSize <= heap->absoluteMaxSize) { 1574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 1575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 15761c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro HSTRACE("externalBytesAvailable(): " 1577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "footprint %zu + extAlloc %zu + n %zu >= max %zu (space for %zu)\n", 15781c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro currentHeapSize, hs->externalBytesAllocated, numBytes, 1579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project heap->absoluteMaxSize, 1580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project heap->absoluteMaxSize - 1581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (currentHeapSize + hs->externalBytesAllocated)); 1582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 1583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define EXTERNAL_TARGET_UTILIZATION 820 // 80% 1586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Tries to update the internal count of externally-allocated memory. 1589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If there's enough room for that memory, returns true. If not, returns 1590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * false and does not update the count. 1591de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 15921c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro * The caller must ensure externalBytesAvailable(hs, n) == true. 1593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool 1595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectexternalAlloc(HeapSource *hs, size_t n, bool grow) 1596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(hs->externalLimit >= hs->externalBytesAllocated); 1598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HSTRACE("externalAlloc(%zd%s)\n", n, grow ? ", grow" : ""); 16001c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro assert(externalBytesAvailable(hs, n)); // The caller must ensure this. 1601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* External allocations have their own "free space" that they 1603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * can allocate from without causing a GC. 1604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (hs->externalBytesAllocated + n <= hs->externalLimit) { 1606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs->externalBytesAllocated += n; 16070d615c3ce5bf97ae65b9347ee77968f38620d5e8Andy McFadden#if PROFILE_EXTERNAL_ALLOCATIONS 1608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.allocProf.enabled) { 1609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* self = dvmThreadSelf(); 1610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.allocProf.externalAllocCount++; 1611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.allocProf.externalAllocSize += n; 1612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self != NULL) { 1613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->allocProf.externalAllocCount++; 1614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->allocProf.externalAllocSize += n; 1615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 1618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 1619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!grow) { 1621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 1622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* GROW */ 1625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs->externalBytesAllocated += n; 162698389d0893ad3d3e06cfb38296b01de39e52db31Carl Shapiro hs->externalLimit = getUtilizationTarget( 1627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs->externalBytesAllocated, EXTERNAL_TARGET_UTILIZATION); 1628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HSTRACE("EXTERNAL grow limit to %zd\n", hs->externalLimit); 1629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 1630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void 1633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectgcForExternalAlloc(bool collectSoftReferences) 1634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.allocProf.enabled) { 1636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* self = dvmThreadSelf(); 1637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.allocProf.gcCount++; 1638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self != NULL) { 1639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->allocProf.gcCount++; 1640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 16421b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayes dvmCollectGarbageInternal(collectSoftReferences, GC_EXTERNAL_ALLOC); 1643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 16461c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro * Returns true if there is enough unused storage to perform an 16471c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro * external allocation of the specified size. If there insufficient 16481c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro * free storage we try to releasing memory from external allocations 16491c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro * and trimming the heap. 16501c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro */ 16511c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapirostatic bool externalAllocPossible(const HeapSource *hs, size_t n) 16521c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro{ 1653812c1bed55e0ed9b092d320cb29d8adc17e5a10bCarl Shapiro size_t bytesTrimmed[HEAP_SOURCE_MAX_HEAP_COUNT]; 1654812c1bed55e0ed9b092d320cb29d8adc17e5a10bCarl Shapiro 16551c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro /* 16561c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro * If there is sufficient space return immediately. 16571c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro */ 16581c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro if (externalBytesAvailable(hs, n)) { 16591c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro return true; 16601c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro } 16611c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro /* 16621c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro * There is insufficient space. Wait for the garbage collector to 16631c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro * become inactive before proceeding. 16641c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro */ 16651c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro while (gDvm.gcHeap->gcRunning) { 16661c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro dvmWaitForConcurrentGcToComplete(); 16671c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro } 16681c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro /* 16691c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro * The heap may have grown or become trimmed while we were 16701c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro * waiting. 16711c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro */ 16721c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro if (externalBytesAvailable(hs, n)) { 16731c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro return true; 16741c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro } 16751c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro /* 1676e8edf08f04ecbe37f3e18a650a7c9002ceee4275Carl Shapiro * Try a garbage collection that clears soft references. This may 1677e8edf08f04ecbe37f3e18a650a7c9002ceee4275Carl Shapiro * make trimming more effective. 16781c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro */ 16791c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro gcForExternalAlloc(true); 16801c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro if (externalBytesAvailable(hs, n)) { 16811c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro return true; 16821c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro } 16831c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro /* 16841c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro * Try trimming the mspace to reclaim unused pages. 16851c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro */ 1686812c1bed55e0ed9b092d320cb29d8adc17e5a10bCarl Shapiro dvmHeapSourceTrim(bytesTrimmed, NELEM(bytesTrimmed)); 1687718509c35413c01a866c848d019d8ca28b425bf6Carl Shapiro snapIdealFootprint(); 16881c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro if (externalBytesAvailable(hs, n)) { 16891c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro return true; 16901c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro } 16911c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro /* 16921c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro * Nothing worked, return an error. 16931c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro */ 16941c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro return false; 16951c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro} 16961c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro 16971c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro/* 1698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Updates the internal count of externally-allocated memory. If there's 1699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * enough room for that memory, returns true. If not, returns false and 1700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * does not update the count. 1701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * May cause a GC as a side-effect. 1703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool 1705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdvmTrackExternalAllocation(size_t n) 1706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HeapSource *hs = gHs; 1708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool ret = false; 1709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* gHs caches an entry in gDvm.gcHeap; we need to hold the 1711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * heap lock if we're going to look at it. 1712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLockHeap(); 1714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HS_BOILERPLATE(); 1716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(hs->externalLimit >= hs->externalBytesAllocated); 1717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 17181c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro /* 17191c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro * The externalAlloc calls require the externalAllocPossible 17201c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro * invariant to be established. 17211c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro */ 1722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!externalAllocPossible(hs, n)) { 1723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE_HEAP("%zd-byte external allocation " 17241c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro "too large for this process.", n); 1725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto out; 1726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Try "allocating" using the existing "free space". 1729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HSTRACE("EXTERNAL alloc %zu (%zu < %zu)\n", 1731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project n, hs->externalBytesAllocated, hs->externalLimit); 1732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (externalAlloc(hs, n, false)) { 1733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ret = true; 1734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto out; 1735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 17361c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro /* 17371c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro * Wait until garbage collector is quiescent before proceeding. 17381c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro */ 17391c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro while (gDvm.gcHeap->gcRunning) { 1740ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro dvmWaitForConcurrentGcToComplete(); 1741ec47e2e081dcd43dca10d5e2c6856f73e94b0460Carl Shapiro } 17421c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro /* 17431c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro * Re-establish the invariant if it was lost while we were 17441c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro * waiting. 17451c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro */ 17461c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro if (!externalAllocPossible(hs, n)) { 17471c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro LOGE_HEAP("%zd-byte external allocation " 17481c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro "too large for this process.", n); 17491c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro goto out; 17501c9d0ab244da441d95a1f2abbb104a0b1015d5d5Carl Shapiro } 1751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The "allocation" failed. Free up some space by doing 1752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a full garbage collection. This may grow the heap source 1753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if the live set is sufficiently large. 1754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HSTRACE("EXTERNAL alloc %zd: GC 1\n", n); 1756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcForExternalAlloc(false); // don't collect SoftReferences 1757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (externalAlloc(hs, n, false)) { 1758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ret = true; 1759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto out; 1760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Even that didn't work; this is an exceptional state. 1763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Try harder, growing the heap source if necessary. 1764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HSTRACE("EXTERNAL alloc %zd: frag\n", n); 1766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ret = externalAlloc(hs, n, true); 1767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (ret) { 1768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto out; 1769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* We couldn't even grow enough to satisfy the request. 1772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Try one last GC, collecting SoftReferences this time. 1773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HSTRACE("EXTERNAL alloc %zd: GC 2\n", n); 1775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gcForExternalAlloc(true); // collect SoftReferences 1776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ret = externalAlloc(hs, n, true); 1777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!ret) { 1778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE_HEAP("Out of external memory on a %zu-byte allocation.\n", n); 1779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 17810d615c3ce5bf97ae65b9347ee77968f38620d5e8Andy McFadden#if PROFILE_EXTERNAL_ALLOCATIONS 1782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.allocProf.enabled) { 1783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* self = dvmThreadSelf(); 1784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.allocProf.failedExternalAllocCount++; 1785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.allocProf.failedExternalAllocSize += n; 1786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self != NULL) { 1787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->allocProf.failedExternalAllocCount++; 1788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->allocProf.failedExternalAllocSize += n; 1789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 1792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectout: 1794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmUnlockHeap(); 1795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return ret; 1797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Reduces the internal count of externally-allocated memory. 1801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid 1803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdvmTrackExternalFree(size_t n) 1804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HeapSource *hs = gHs; 1806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t newExternalLimit; 1807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t oldExternalBytesAllocated; 1808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HSTRACE("EXTERNAL free %zu (%zu < %zu)\n", 1810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project n, hs->externalBytesAllocated, hs->externalLimit); 1811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* gHs caches an entry in gDvm.gcHeap; we need to hold the 1813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * heap lock if we're going to look at it. 1814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLockHeap(); 1816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HS_BOILERPLATE(); 1818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(hs->externalLimit >= hs->externalBytesAllocated); 1819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project oldExternalBytesAllocated = hs->externalBytesAllocated; 1821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (n <= hs->externalBytesAllocated) { 1822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs->externalBytesAllocated -= n; 1823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project n = hs->externalBytesAllocated; 1825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs->externalBytesAllocated = 0; 1826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 18280d615c3ce5bf97ae65b9347ee77968f38620d5e8Andy McFadden#if PROFILE_EXTERNAL_ALLOCATIONS 1829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.allocProf.enabled) { 1830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* self = dvmThreadSelf(); 1831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.allocProf.externalFreeCount++; 1832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.allocProf.externalFreeSize += n; 1833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self != NULL) { 1834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->allocProf.externalFreeCount++; 1835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->allocProf.externalFreeSize += n; 1836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 1839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Shrink as quickly as we can. 1841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 184298389d0893ad3d3e06cfb38296b01de39e52db31Carl Shapiro newExternalLimit = getUtilizationTarget( 1843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs->externalBytesAllocated, EXTERNAL_TARGET_UTILIZATION); 1844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (newExternalLimit < oldExternalBytesAllocated) { 1845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Make sure that the remaining free space is at least 1846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * big enough to allocate something of the size that was 1847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * just freed. This makes it more likely that 1848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * externalFree(N); externalAlloc(N); 1849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * will work without causing a GC. 1850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HSTRACE("EXTERNAL free preserved %zu extra free bytes\n", 1852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project oldExternalBytesAllocated - newExternalLimit); 1853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newExternalLimit = oldExternalBytesAllocated; 1854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (newExternalLimit < hs->externalLimit) { 1856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hs->externalLimit = newExternalLimit; 1857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmUnlockHeap(); 1860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the number of externally-allocated bytes being tracked by 1864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * dvmTrackExternalAllocation/Free(). 1865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsize_t 1867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdvmGetExternalBytesAllocated() 1868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const HeapSource *hs = gHs; 1870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t ret; 1871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* gHs caches an entry in gDvm.gcHeap; we need to hold the 1873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * heap lock if we're going to look at it. We also need the 1874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * lock for the call to setIdealFootprint(). 1875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLockHeap(); 1877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HS_BOILERPLATE(); 1878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ret = hs->externalBytesAllocated; 1879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmUnlockHeap(); 1880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return ret; 1882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1883d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro 1884d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapirovoid *dvmHeapSourceGetImmuneLimit(GcMode mode) 1885d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro{ 1886d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro if (mode == GC_PARTIAL) { 1887d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro return hs2heap(gHs)->base; 1888d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro } else { 1889d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro return NULL; 1890d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro } 1891d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro} 1892