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