Heap.c revision d25566d9278e6424e521f4b7148ac31480e60c5c
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 * Garbage-collecting memory allocator.
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h"
20962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes#include "alloc/HeapBitmap.h"
21962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes#include "alloc/Verify.h"
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/HeapTable.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/DdmHeap.h"
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/HeapSource.h"
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/MarkSweep.h"
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "utils/threads.h"      // need Android thread priorities
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define kInvalidPriority        10000
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
325a2056ca8c7e7c0ed9f51d68cedbee59cc936685San Mehat#include <cutils/sched_policy.h>
335a2056ca8c7e7c0ed9f51d68cedbee59cc936685San Mehat
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <sys/time.h>
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <sys/resource.h>
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <limits.h>
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <errno.h>
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define kNonCollectableRefDefault   16
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define kFinalizableRefDefault      128
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
421b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayesstatic const char* GcReasonStr[] = {
431b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayes    [GC_FOR_MALLOC] = "GC_FOR_MALLOC",
441b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayes    [GC_EXPLICIT] = "GC_EXPLICIT",
451b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayes    [GC_EXTERNAL_ALLOC] = "GC_EXTERNAL_ALLOC",
461b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayes    [GC_HPROF_DUMP_HEAP] = "GC_HPROF_DUMP_HEAP"
471b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayes};
481b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayes
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize the GC heap.
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns true if successful, false otherwise.
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmHeapStartup()
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GcHeap *gcHeap;
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if defined(WITH_ALLOC_LIMITS)
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.checkAllocLimits = false;
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.allocationLimit = -1;
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap = dvmHeapSourceStartup(gDvm.heapSizeStart, gDvm.heapSizeMax);
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gcHeap == NULL) {
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->heapWorkerCurrentObject = NULL;
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->heapWorkerCurrentMethod = NULL;
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->heapWorkerInterpStartTime = 0LL;
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->softReferenceCollectionState = SR_COLLECT_NONE;
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->softReferenceHeapSizeThreshold = gDvm.heapSizeStart;
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->ddmHpifWhen = 0;
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->ddmHpsgWhen = 0;
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->ddmHpsgWhat = 0;
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->ddmNhsgWhen = 0;
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->ddmNhsgWhat = 0;
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if WITH_HPROF
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->hprofDumpOnGc = false;
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->hprofContext = NULL;
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* This needs to be set before we call dvmHeapInitHeapRefTable().
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.gcHeap = gcHeap;
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Set up the table we'll use for ALLOC_NO_GC.
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmHeapInitHeapRefTable(&gcHeap->nonCollectableRefs,
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                           kNonCollectableRefDefault))
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE_HEAP("Can't allocate GC_NO_ALLOC table\n");
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto fail;
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Set up the lists and lock we'll use for finalizable
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * and reference objects.
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmInitMutex(&gDvm.heapWorkerListLock);
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->finalizableRefs = NULL;
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->pendingFinalizationRefs = NULL;
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->referenceOperations = NULL;
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Initialize the HeapWorker locks and other state
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that the GC uses.
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmInitializeHeapWorkerState();
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfail:
111a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro    dvmHeapSourceShutdown(&gcHeap);
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return false;
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
115c8e06c8dba30f01d3cf6506c553041c340b312afCarl Shapirovoid dvmHeapStartupAfterZygote()
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Update our idea of the last GC start time so that we
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * don't use the last time that Zygote happened to GC.
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.gcHeap->gcStartTime = dvmGetRelativeTimeUsec();
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmHeapShutdown()
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: make sure we're locked
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.gcHeap != NULL) {
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Tables are allocated on the native heap;
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * they need to be cleaned up explicitly.
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The process may stick around, so we don't
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * want to leak any native memory.
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
132a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro        dvmHeapFreeHeapRefTable(&gDvm.gcHeap->nonCollectableRefs);
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
134a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro        dvmHeapFreeLargeTable(gDvm.gcHeap->finalizableRefs);
135a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro        gDvm.gcHeap->finalizableRefs = NULL;
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
137a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro        dvmHeapFreeLargeTable(gDvm.gcHeap->pendingFinalizationRefs);
138a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro        gDvm.gcHeap->pendingFinalizationRefs = NULL;
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
140a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro        dvmHeapFreeLargeTable(gDvm.gcHeap->referenceOperations);
141a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro        gDvm.gcHeap->referenceOperations = NULL;
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Destroy the heap.  Any outstanding pointers
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * will point to unmapped memory (unless/until
145a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro         * someone else maps it).  This frees gDvm.gcHeap
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * as a side-effect.
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
148a199eb70871a8c142a723d76b1b08939286a3199Carl Shapiro        dvmHeapSourceShutdown(&gDvm.gcHeap);
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We've been asked to allocate something we can't, e.g. an array so
1546da743bfe7c60ad873df72a3b6412137c4ac71dcAndy McFadden * large that (length * elementWidth) is larger than 2^31.
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1566da743bfe7c60ad873df72a3b6412137c4ac71dcAndy McFadden * _The Java Programming Language_, 4th edition, says, "you can be sure
1576da743bfe7c60ad873df72a3b6412137c4ac71dcAndy McFadden * that all SoftReferences to softly reachable objects will be cleared
1586da743bfe7c60ad873df72a3b6412137c4ac71dcAndy McFadden * before an OutOfMemoryError is thrown."
1596da743bfe7c60ad873df72a3b6412137c4ac71dcAndy McFadden *
1606da743bfe7c60ad873df72a3b6412137c4ac71dcAndy McFadden * It's unclear whether that holds for all situations where an OOM can
1616da743bfe7c60ad873df72a3b6412137c4ac71dcAndy McFadden * be thrown, or just in the context of an allocation that fails due
1626da743bfe7c60ad873df72a3b6412137c4ac71dcAndy McFadden * to lack of heap space.  For simplicity we just throw the exception.
1636da743bfe7c60ad873df72a3b6412137c4ac71dcAndy McFadden *
1646da743bfe7c60ad873df72a3b6412137c4ac71dcAndy McFadden * (OOM due to actually running out of space is handled elsewhere.)
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmThrowBadAllocException(const char* msg)
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1686da743bfe7c60ad873df72a3b6412137c4ac71dcAndy McFadden    dvmThrowException("Ljava/lang/OutOfMemoryError;", msg);
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Grab the lock, but put ourselves into THREAD_VMWAIT if it looks like
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we're going to have to wait on the mutex.
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmLockHeap()
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
177980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro    if (dvmTryLockMutex(&gDvm.gcHeapLock) != 0) {
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Thread *self;
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ThreadStatus oldStatus;
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self = dvmThreadSelf();
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (self != NULL) {
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
18599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            LOGI("ODD: waiting on heap lock, no self\n");
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            oldStatus = -1; // shut up gcc
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
188980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro        dvmLockMutex(&gDvm.gcHeapLock);
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (self != NULL) {
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmChangeStatus(self, oldStatus);
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmUnlockHeap()
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockMutex(&gDvm.gcHeapLock);
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Pop an object from the list of pending finalizations and
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * reference clears/enqueues, and return the object.
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The caller must call dvmReleaseTrackedAlloc()
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on the object when finished.
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Typically only called by the heap worker thread.
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectObject *dvmGetNextHeapWorkerObject(HeapWorkerOperation *op)
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object *obj;
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GcHeap *gcHeap = gDvm.gcHeap;
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(op != NULL);
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    obj = NULL;
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLockMutex(&gDvm.heapWorkerListLock);
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* We must handle reference operations before finalizations.
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If:
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *     a) Someone subclasses WeakReference and overrides clear()
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *     b) A reference of this type is the last reference to
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *        a finalizable object
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * then we need to guarantee that the overridden clear() is called
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * on the reference before finalize() is called on the referent.
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Both of these operations will always be scheduled at the same
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * time, so handling reference operations first will guarantee
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the required order.
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    obj = dvmHeapGetNextObjectFromLargeTable(&gcHeap->referenceOperations);
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (obj != NULL) {
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        uintptr_t workBits;
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2356930a11fd75071fa2f04fcfe11c322e2518cf503Barry Hayes        workBits = (uintptr_t)obj & WORKER_ENQUEUE;
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(workBits != 0);
2376930a11fd75071fa2f04fcfe11c322e2518cf503Barry Hayes        obj = (Object *)((uintptr_t)obj & ~WORKER_ENQUEUE);
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *op = workBits;
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        obj = dvmHeapGetNextObjectFromLargeTable(
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                &gcHeap->pendingFinalizationRefs);
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (obj != NULL) {
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *op = WORKER_FINALIZE;
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (obj != NULL) {
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Don't let the GC collect the object until the
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * worker thread is done with it.
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * This call is safe;  it uses thread-local storage
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * and doesn't acquire any locks.
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAddTrackedAlloc(obj, NULL);
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockMutex(&gDvm.heapWorkerListLock);
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return obj;
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Used for a heap size change hysteresis to avoid collecting
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * SoftReferences when the heap only grows by a small amount.
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define SOFT_REFERENCE_GROWTH_SLACK (128 * 1024)
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Whenever the effective heap size may have changed,
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * this function must be called.
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmHeapSizeChanged()
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GcHeap *gcHeap = gDvm.gcHeap;
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t currentHeapSize;
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    currentHeapSize = dvmHeapSourceGetIdealFootprint();
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* See if the heap size has changed enough that we should care
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * about it.
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (currentHeapSize <= gcHeap->softReferenceHeapSizeThreshold -
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            4 * SOFT_REFERENCE_GROWTH_SLACK)
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* The heap has shrunk enough that we'll use this as a new
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * threshold.  Since we're doing better on space, there's
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * no need to collect any SoftReferences.
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * This is 4x the growth hysteresis because we don't want
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * to snap down so easily after a shrink.  If we just cleared
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * up a bunch of SoftReferences, we don't want to disallow
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * any new ones from being created.
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * TODO: determine if the 4x is important, needed, or even good
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gcHeap->softReferenceHeapSizeThreshold = currentHeapSize;
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gcHeap->softReferenceCollectionState = SR_COLLECT_NONE;
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else if (currentHeapSize >= gcHeap->softReferenceHeapSizeThreshold +
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            SOFT_REFERENCE_GROWTH_SLACK)
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* The heap has grown enough to warrant collecting SoftReferences.
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gcHeap->softReferenceHeapSizeThreshold = currentHeapSize;
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gcHeap->softReferenceCollectionState = SR_COLLECT_SOME;
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Do a full garbage collection, which may grow the
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * heap as a side-effect if the live set is large.
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void gcForMalloc(bool collectSoftReferences)
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_PROFILER
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.allocProf.enabled) {
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Thread* self = dvmThreadSelf();
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.allocProf.gcCount++;
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (self != NULL) {
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->allocProf.gcCount++;
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* This may adjust the soft limit as a side-effect.
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGD_HEAP("dvmMalloc initiating GC%s\n",
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            collectSoftReferences ? "(collect SoftReferences)" : "");
3251b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayes    dvmCollectGarbageInternal(collectSoftReferences, GC_FOR_MALLOC);
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Try as hard as possible to allocate some memory.
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3306343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapirostatic void *tryMalloc(size_t size)
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3326343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro    void *ptr;
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Don't try too hard if there's no way the allocation is
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * going to succeed.  We have to collect SoftReferences before
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * throwing an OOME, though.
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (size >= gDvm.heapSizeMax) {
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW_HEAP("dvmMalloc(%zu/0x%08zx): "
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "someone's allocating a huge buffer\n", size, size);
3416343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro        ptr = NULL;
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto collect_soft_refs;
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: figure out better heuristics
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//    There will be a lot of churn if someone allocates a bunch of
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//    big objects in a row, and we hit the frag case each time.
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//    A full GC for each.
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//    Maybe we grow the heap in bigger leaps
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//    Maybe we skip the GC if the size is large and we did one recently
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//      (number of allocations ago) (watch for thread effects)
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//    DeflateTest allocs a bunch of ~128k buffers w/in 0-5 allocs of each other
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//      (or, at least, there are only 0-5 objects swept each time)
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3556343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro    ptr = dvmHeapSourceAlloc(size);
3566343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro    if (ptr != NULL) {
3576343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro        return ptr;
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* The allocation failed.  Free up some space by doing
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * a full garbage collection.  This may grow the heap
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * if the live set is sufficiently large.
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcForMalloc(false);
3656343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro    ptr = dvmHeapSourceAlloc(size);
3666343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro    if (ptr != NULL) {
3676343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro        return ptr;
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Even that didn't work;  this is an exceptional state.
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Try harder, growing the heap if necessary.
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3736343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro    ptr = dvmHeapSourceAllocAndGrow(size);
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHeapSizeChanged();
3756343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro    if (ptr != NULL) {
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        size_t newHeapSize;
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newHeapSize = dvmHeapSourceGetIdealFootprint();
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: may want to grow a little bit more so that the amount of free
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//      space is equal to the old free space + the utilization slop for
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//      the new allocation.
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI_HEAP("Grow heap (frag case) to "
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "%zu.%03zuMB for %zu-byte allocation\n",
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                FRACTIONAL_MB(newHeapSize), size);
3856343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro        return ptr;
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Most allocations should have succeeded by now, so the heap
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * is really full, really fragmented, or the requested size is
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * really big.  Do another GC, collecting SoftReferences this
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * time.  The VM spec requires that all SoftReferences have
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * been collected and cleared before throwing an OOME.
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: wait for the finalizers from the previous GC to finish
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectcollect_soft_refs:
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGI_HEAP("Forcing collection of SoftReferences for %zu-byte allocation\n",
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            size);
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcForMalloc(true);
3996343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro    ptr = dvmHeapSourceAllocAndGrow(size);
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHeapSizeChanged();
4016343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro    if (ptr != NULL) {
4026343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro        return ptr;
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: maybe wait for finalizers and try one last time
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGE_HEAP("Out of memory on a %zd-byte allocation.\n", size);
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: tell the HeapSource to dump its state
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmDumpThread(dvmThreadSelf(), false);
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return NULL;
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Throw an OutOfMemoryError if there's a thread to attach it to.
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Avoid recursing.
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The caller must not be holding the heap lock, or else the allocations
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in dvmThrowException() will deadlock.
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void throwOOME()
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread *self;
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((self = dvmThreadSelf()) != NULL) {
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* If the current (failing) dvmMalloc() happened as part of thread
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * creation/attachment before the thread became part of the root set,
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * we can't rely on the thread-local trackedAlloc table, so
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * we can't keep track of a real allocated OOME object.  But, since
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * the thread is in the process of being created, it won't have
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * a useful stack anyway, so we may as well make things easier
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * by throwing the (stackless) pre-built OOME.
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsOnThreadList(self) && !self->throwingOOME) {
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Let ourselves know that we tried to throw an OOM
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * error in the normal way in case we run out of
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * memory trying to allocate it inside dvmThrowException().
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->throwingOOME = true;
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Don't include a description string;
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * one fewer allocation.
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/OutOfMemoryError;", NULL);
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * This thread has already tried to throw an OutOfMemoryError,
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * which probably means that we're running out of memory
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * while recursively trying to throw.
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * To avoid any more allocation attempts, "throw" a pre-built
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * OutOfMemoryError object (which won't have a useful stack trace).
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Note that since this call can't possibly allocate anything,
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * we don't care about the state of self->throwingOOME
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * (which will usually already be set).
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmSetException(self, gDvm.outOfMemoryObj);
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* We're done with the possible recursion.
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self->throwingOOME = false;
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Allocate storage on the GC heap.  We guarantee 8-byte alignment.
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The new storage is zeroed out.
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note that, in rare cases, this could get called while a GC is in
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * progress.  If a non-VM thread tries to attach itself through JNI,
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it will need to allocate some objects.  If this becomes annoying to
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * deal with, we can block it at the source, but holding the allocation
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * mutex should be enough.
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In rare circumstances (JNI AttachCurrentThread) we can be called
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * from a non-VM thread.
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We implement ALLOC_NO_GC by maintaining an internal list of objects
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that should not be collected.  This requires no actual flag storage in
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the object itself, which is good, but makes flag queries expensive.
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Use ALLOC_DONT_TRACK when we either don't want to track an allocation
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (because it's being done for the interpreter "new" operation and will
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * be part of the root set immediately) or we can't (because this allocation
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is for a brand new thread).
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns NULL and throws an exception on failure.
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: don't do a GC if the debugger thinks all threads are suspended
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid* dvmMalloc(size_t size, int flags)
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GcHeap *gcHeap = gDvm.gcHeap;
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void *ptr;
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* handy for spotting large allocations */
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (size >= 100000) {
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("dvmMalloc(%d):\n", size);
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmDumpThread(dvmThreadSelf(), false);
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if defined(WITH_ALLOC_LIMITS)
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * See if they've exceeded the allocation limit for this thread.
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * A limit value of -1 means "no limit".
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * This is enabled at compile time because it requires us to do a
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * TLS lookup for the Thread pointer.  This has enough of a performance
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * impact that we don't want to do it if we don't have to.  (Now that
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we're using gDvm.checkAllocLimits we may want to reconsider this,
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * but it's probably still best to just compile the check out of
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * production code -- one less thing to hit on every allocation.)
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.checkAllocLimits) {
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Thread* self = dvmThreadSelf();
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (self != NULL) {
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int count = self->allocLimit;
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (count > 0) {
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                self->allocLimit--;
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else if (count == 0) {
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* fail! */
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(!gDvm.initializing);
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                self->allocLimit = -1;
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmThrowException("Ldalvik/system/AllocationLimitError;",
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "thread allocation limit exceeded");
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return NULL;
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.allocationLimit >= 0) {
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!gDvm.initializing);
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.allocationLimit = -1;
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ldalvik/system/AllocationLimitError;",
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "global allocation limit exceeded");
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLockHeap();
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Try as hard as possible to allocate some memory.
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
5476343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro    ptr = tryMalloc(size);
5486343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro    if (ptr != NULL) {
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* We've got the memory.
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((flags & ALLOC_FINALIZABLE) != 0) {
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* This object is an instance of a class that
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * overrides finalize().  Add it to the finalizable list.
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Note that until DVM_OBJECT_INIT() is called on this
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * object, its clazz will be NULL.  Since the object is
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * in this table, it will be scanned as part of the root
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * set.  scanObject() explicitly deals with the NULL clazz.
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!dvmHeapAddRefToLargeTable(&gcHeap->finalizableRefs,
5616343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro                                    (Object *)ptr))
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGE_HEAP("dvmMalloc(): no room for any more "
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        "finalizable objects\n");
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmAbort();
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* The caller may not want us to collect this object.
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If not, throw it in the nonCollectableRefs table, which
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * will be added to the root set when we GC.
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Note that until DVM_OBJECT_INIT() is called on this
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * object, its clazz will be NULL.  Since the object is
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * in this table, it will be scanned as part of the root
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * set.  scanObject() explicitly deals with the NULL clazz.
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((flags & ALLOC_NO_GC) != 0) {
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!dvmHeapAddToHeapRefTable(&gcHeap->nonCollectableRefs, ptr)) {
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGE_HEAP("dvmMalloc(): no room for any more "
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        "ALLOC_NO_GC objects: %zd\n",
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        dvmHeapNumHeapRefTableEntries(
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                &gcHeap->nonCollectableRefs));
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmAbort();
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_PROFILER
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gDvm.allocProf.enabled) {
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Thread* self = dvmThreadSelf();
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm.allocProf.allocCount++;
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm.allocProf.allocSize += size;
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (self != NULL) {
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                self->allocProf.allocCount++;
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                self->allocProf.allocSize += size;
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* The allocation failed.
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_PROFILER
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gDvm.allocProf.enabled) {
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Thread* self = dvmThreadSelf();
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm.allocProf.failedAllocCount++;
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm.allocProf.failedAllocSize += size;
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (self != NULL) {
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                self->allocProf.failedAllocCount++;
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                self->allocProf.failedAllocSize += size;
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockHeap();
617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (ptr != NULL) {
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If this block is immediately GCable, and they haven't asked us not
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * to track it, add it to the internal tracking list.
622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If there's no "self" yet, we can't track it.  Calls made before
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * the Thread exists should use ALLOC_NO_GC.
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((flags & (ALLOC_DONT_TRACK | ALLOC_NO_GC)) == 0) {
627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAddTrackedAlloc(ptr, NULL);
628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
630c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng        /*
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The allocation failed; throw an OutOfMemoryError.
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throwOOME();
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return ptr;
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns true iff <obj> points to a valid allocated object.
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmIsValidObject(const Object* obj)
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Don't bother if it's NULL or not 8-byte aligned.
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
6466343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro    if (obj != NULL && ((uintptr_t)obj & (8-1)) == 0) {
647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Even if the heap isn't locked, this shouldn't return
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * any false negatives.  The only mutation that could
649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * be happening is allocation, which means that another
650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * thread could be in the middle of a read-modify-write
651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * to add a new bit for a new object.  However, that
652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * RMW will have completed by the time any other thread
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * could possibly see the new pointer, so there is no
654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * danger of dvmIsValidObject() being called on a valid
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * pointer whose bit isn't set.
656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Freeing will only happen during the sweep phase, which
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * only happens while the heap is locked.
659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
6606343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro        return dvmHeapSourceContains(obj);
661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return false;
663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Clear flags that were passed into dvmMalloc() et al.
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * e.g., ALLOC_NO_GC, ALLOC_DONT_TRACK.
668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmClearAllocFlags(Object *obj, int mask)
670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((mask & ALLOC_NO_GC) != 0) {
672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLockHeap();
673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsValidObject(obj)) {
674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!dvmHeapRemoveFromHeapRefTable(&gDvm.gcHeap->nonCollectableRefs,
675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                               obj))
676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGE_HEAP("dvmMalloc(): failed to remove ALLOC_NO_GC bit from "
678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        "object 0x%08x\n", (uintptr_t)obj);
679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmAbort();
680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: shrink if the table is very empty
682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmUnlockHeap();
684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((mask & ALLOC_DONT_TRACK) != 0) {
687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc(obj, NULL);
688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsize_t dvmObjectSizeInHeap(const Object *obj)
692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
6936343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro    return dvmHeapSourceChunkSize(obj);
694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
697962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes * Scan every live object in the heap, holding the locks.
698962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes */
699962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayesstatic void verifyHeap()
700962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes{
701962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes    // TODO: check the locks.
702962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes    HeapBitmap *liveBits = dvmHeapSourceGetLiveBits();
703962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes    dvmVerifyBitmap(liveBits);
704962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes}
705962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes
706962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes/*
707962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes * Suspend the VM as for a GC, and assert-fail if any object has any
708962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes * corrupt references.
709962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes */
710962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayesvoid dvmHeapSuspendAndVerify()
711962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes{
712962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes    /* Suspend the VM. */
713962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes    dvmSuspendAllThreads(SUSPEND_FOR_VERIFY);
714962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes    dvmLockMutex(&gDvm.heapWorkerLock);
715962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes    dvmAssertHeapWorkerThreadRunning();
716962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes    dvmLockMutex(&gDvm.heapWorkerListLock);
717962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes
718962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes    verifyHeap();
719962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes
720962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes    /* Resume the VM. */
721962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes    dvmUnlockMutex(&gDvm.heapWorkerListLock);
722962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes    dvmUnlockMutex(&gDvm.heapWorkerLock);
723962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes    dvmResumeAllThreads(SUSPEND_FOR_VERIFY);
724962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes}
725962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes
726962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes/*
727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initiate garbage collection.
728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTES:
730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - If we don't hold gDvm.threadListLock, it's possible for a thread to
731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   be added to the thread list while we work.  The thread should NOT
732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   start executing, so this is only interesting when we start chasing
733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   thread stacks.  (Before we do so, grab the lock.)
734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We are not allowed to GC when the debugger has suspended the VM, which
736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is awkward because debugger requests can cause allocations.  The easiest
737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * way to enforce this is to refuse to GC on an allocation made by the
738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * JDWP thread -- we have to expand the heap or fail.
739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
740d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapirovoid dvmCollectGarbageInternal(bool collectSoftReferences, GcReason reason)
741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GcHeap *gcHeap = gDvm.gcHeap;
743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object *softReferences;
744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object *weakReferences;
745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object *phantomReferences;
746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u8 now;
748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    s8 timeSinceLastGc;
749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    s8 gcElapsedTime;
750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int numFreed;
751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t sizeFreed;
752d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro    GcMode gcMode;
753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DVM_TRACK_HEAP_MARKING
755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Since weak and soft references are always cleared,
756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * they don't require any marking.
757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (Soft are lumped into strong when they aren't cleared.)
758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t strongMarkCount = 0;
760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t strongMarkSize = 0;
761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t finalizeMarkCount = 0;
762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t finalizeMarkSize = 0;
763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t phantomMarkCount = 0;
764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t phantomMarkSize = 0;
765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* The heap lock must be held.
768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gcHeap->gcRunning) {
771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW_HEAP("Attempted recursive GC\n");
772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
774d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro    gcMode = (reason == GC_FOR_MALLOC) ? GC_PARTIAL : GC_FULL;
775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->gcRunning = true;
776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    now = dvmGetRelativeTimeUsec();
777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gcHeap->gcStartTime != 0) {
778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        timeSinceLastGc = (now - gcHeap->gcStartTime) / 1000;
779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        timeSinceLastGc = 0;
781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->gcStartTime = now;
783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
7841b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayes    LOGV_HEAP("%s starting -- suspending threads\n", GcReasonStr[reason]);
785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmSuspendAllThreads(SUSPEND_FOR_GC);
787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Get the priority (the "nice" value) of the current thread.  The
789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * getpriority() call can legitimately return -1, so we have to
790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * explicitly test errno.
791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    errno = 0;
793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int oldThreadPriority = kInvalidPriority;
794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int priorityResult = getpriority(PRIO_PROCESS, 0);
795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (errno != 0) {
796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI_HEAP("getpriority(self) failed: %s\n", strerror(errno));
797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else if (priorityResult > ANDROID_PRIORITY_NORMAL) {
798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Current value is numerically greater than "normal", which
799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * in backward UNIX terms means lower priority.
800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
801256fc159a267859c18e11e1d15fd7d97a59757c6San Mehat
8023e371e2ebbeeefe176ba1357e6ff241bd13a711eSan Mehat        if (priorityResult >= ANDROID_PRIORITY_BACKGROUND) {
8035a2056ca8c7e7c0ed9f51d68cedbee59cc936685San Mehat            set_sched_policy(dvmGetSysThreadId(), SP_FOREGROUND);
804256fc159a267859c18e11e1d15fd7d97a59757c6San Mehat        }
805256fc159a267859c18e11e1d15fd7d97a59757c6San Mehat
806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL) != 0) {
807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI_HEAP("Unable to elevate priority from %d to %d\n",
808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                priorityResult, ANDROID_PRIORITY_NORMAL);
809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* priority elevated; save value so we can restore it later */
811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGD_HEAP("Elevating priority from %d to %d\n",
812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                priorityResult, ANDROID_PRIORITY_NORMAL);
813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            oldThreadPriority = priorityResult;
814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Wait for the HeapWorker thread to block.
818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (It may also already be suspended in interp code,
819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in which case it's not holding heapWorkerLock.)
820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLockMutex(&gDvm.heapWorkerLock);
822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Make sure that the HeapWorker thread hasn't become
824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * wedged inside interp code.  If it has, this call will
825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * print a message and abort the VM.
826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmAssertHeapWorkerThreadRunning();
828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Lock the pendingFinalizationRefs list.
830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Acquire the lock after suspending so the finalizer
832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * thread can't block in the RUNNING state while
833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we try to suspend.
834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLockMutex(&gDvm.heapWorkerListLock);
836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
837962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes    if (gDvm.preVerify) {
838962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes        LOGV_HEAP("Verifying heap before GC");
839962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes        verifyHeap();
840962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes    }
841962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes
842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_PROFILER
843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmMethodTraceGCBegin();
844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if WITH_HPROF
847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Set DUMP_HEAP_ON_DDMS_UPDATE to 1 to enable heap dumps
849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * whenever DDMS requests a heap update (HPIF chunk).
850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The output files will appear in /data/misc, which must
851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * already exist.
852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You must define "WITH_HPROF := true" in your buildspec.mk
853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and recompile libdvm for this to work.
854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * To enable stack traces for each allocation, define
856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "WITH_HPROF_STACK := true" in buildspec.mk.  This option slows down
857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * allocations and also requires 8 additional bytes per object on the
858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * GC heap.
859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define DUMP_HEAP_ON_DDMS_UPDATE 0
861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DUMP_HEAP_ON_DDMS_UPDATE
862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->hprofDumpOnGc |= (gcHeap->ddmHpifWhen != 0);
863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gcHeap->hprofDumpOnGc) {
866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char nameBuf[128];
867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
86899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        gcHeap->hprofResult = -1;
86999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gcHeap->hprofFileName == NULL) {
871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* no filename was provided; invent one */
872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(nameBuf, "/data/misc/heap-dump-tm%d-pid%d.hprof",
873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (int) time(NULL), (int) getpid());
874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gcHeap->hprofFileName = nameBuf;
875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
8766bf992c9d51f1e12aa37fe4c791c156402a9b79bAndy McFadden        gcHeap->hprofContext = hprofStartup(gcHeap->hprofFileName,
8776bf992c9d51f1e12aa37fe4c791c156402a9b79bAndy McFadden                gcHeap->hprofDirectToDdms);
878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gcHeap->hprofContext != NULL) {
879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            hprofStartHeapDump(gcHeap->hprofContext);
880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gcHeap->hprofDumpOnGc = false;
882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gcHeap->hprofFileName = NULL;
883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (timeSinceLastGc < 10000) {
887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGD_HEAP("GC! (%dms since last GC)\n",
888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (int)timeSinceLastGc);
889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGD_HEAP("GC! (%d sec since last GC)\n",
891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (int)(timeSinceLastGc / 1000));
892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DVM_TRACK_HEAP_MARKING
894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->markCount = 0;
895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->markSize = 0;
896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Set up the marking context.
899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
900d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro    if (!dvmHeapBeginMarkStep(gcMode)) {
90199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        LOGE_HEAP("dvmHeapBeginMarkStep failed; aborting\n");
90299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        dvmAbort();
90399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    }
904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Mark the set of objects that are strongly reachable from the roots.
906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGD_HEAP("Marking...");
908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHeapMarkRootSet();
909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* dvmHeapScanMarkedObjects() will build the lists of known
911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * instances of the Reference classes.
912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->softReferences = NULL;
914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->weakReferences = NULL;
915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->phantomReferences = NULL;
916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Make sure that we don't hard-mark the referents of Reference
918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * objects by default.
919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->markAllReferents = false;
921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Don't mark SoftReferences if our caller wants us to collect them.
923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * This has to be set before calling dvmHeapScanMarkedObjects().
924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (collectSoftReferences) {
926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gcHeap->softReferenceCollectionState = SR_COLLECT_ALL;
927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Recursively mark any objects that marked objects point to strongly.
930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we're not collecting soft references, soft-reachable
931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * objects will also be marked.
932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGD_HEAP("Recursing...");
934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHeapScanMarkedObjects();
935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DVM_TRACK_HEAP_MARKING
936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    strongMarkCount = gcHeap->markCount;
937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    strongMarkSize = gcHeap->markSize;
938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->markCount = 0;
939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->markSize = 0;
940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Latch these so that the other calls to dvmHeapScanMarkedObjects() don't
943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * mess with them.
944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    softReferences = gcHeap->softReferences;
946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    weakReferences = gcHeap->weakReferences;
947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    phantomReferences = gcHeap->phantomReferences;
948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* All strongly-reachable objects have now been marked.
950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gcHeap->softReferenceCollectionState != SR_COLLECT_NONE) {
952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGD_HEAP("Handling soft references...");
953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmHeapHandleReferences(softReferences, REF_SOFT);
954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // markCount always zero
955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Now that we've tried collecting SoftReferences,
957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * fall back to not collecting them.  If the heap
958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * grows, we will start collecting again.
959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gcHeap->softReferenceCollectionState = SR_COLLECT_NONE;
961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } // else dvmHeapScanMarkedObjects() already marked the soft-reachable set
962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGD_HEAP("Handling weak references...");
963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHeapHandleReferences(weakReferences, REF_WEAK);
964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // markCount always zero
965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Once all weak-reachable objects have been taken
967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * care of, any remaining unmarked objects can be finalized.
968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGD_HEAP("Finding finalizations...");
970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHeapScheduleFinalizations();
971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DVM_TRACK_HEAP_MARKING
972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    finalizeMarkCount = gcHeap->markCount;
973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    finalizeMarkSize = gcHeap->markSize;
974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->markCount = 0;
975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->markSize = 0;
976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Any remaining objects that are not pending finalization
979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * could be phantom-reachable.  This will mark any phantom-reachable
980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * objects, as well as enqueue their references.
981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGD_HEAP("Handling phantom references...");
983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHeapHandleReferences(phantomReferences, REF_PHANTOM);
984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DVM_TRACK_HEAP_MARKING
985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    phantomMarkCount = gcHeap->markCount;
986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    phantomMarkSize = gcHeap->markSize;
987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->markCount = 0;
988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->markSize = 0;
989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: take care of JNI weak global references
992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DVM_TRACK_HEAP_MARKING
994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGI_HEAP("Marked objects: %dB strong, %dB final, %dB phantom\n",
995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            strongMarkSize, finalizeMarkSize, phantomMarkSize);
996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmDumpMonitorInfo("before sweep");
1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGD_HEAP("Sweeping...");
1002d25566d9278e6424e521f4b7148ac31480e60c5cCarl Shapiro    dvmHeapSweepUnmarkedObjects(gcMode, &numFreed, &sizeFreed);
1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
1004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmDumpMonitorInfo("after sweep");
1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGD_HEAP("Cleaning up...");
1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHeapFinishMarkStep();
1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGD_HEAP("Done.");
1011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Now's a good time to adjust the heap size, since
1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we know what our utilization is.
1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * This doesn't actually resize any memory;
1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * it just lets the heap grow more when necessary.
1017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHeapSourceGrowForUtilization();
1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHeapSizeChanged();
1020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if WITH_HPROF
1022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gcHeap->hprofContext != NULL) {
1023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprofFinishHeapDump(gcHeap->hprofContext);
1024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: write a HEAP_SUMMARY record
102599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        if (hprofShutdown(gcHeap->hprofContext))
102699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            gcHeap->hprofResult = 0;    /* indicate success */
1027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gcHeap->hprofContext = NULL;
1028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Now that we've freed up the GC heap, return any large
1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * free chunks back to the system.  They'll get paged back
1033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in the next time they're used.  Don't do it immediately,
1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * though;  if the process is still allocating a bunch of
1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * memory, we'll be taking a ton of page faults that we don't
1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * necessarily need to.
1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Cancel any old scheduled trims, and schedule a new one.
1039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmScheduleHeapSourceTrim(5);  // in seconds
1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_PROFILER
1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmMethodTraceGCEnd();
1044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1045962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes    LOGV_HEAP("GC finished");
1046962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes
1047962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes    if (gDvm.postVerify) {
1048962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes        LOGV_HEAP("Verifying heap after GC");
1049962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes        verifyHeap();
1050962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes    }
1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcHeap->gcRunning = false;
1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1054962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes    LOGV_HEAP("Resuming threads");
1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockMutex(&gDvm.heapWorkerListLock);
1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockMutex(&gDvm.heapWorkerLock);
1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1058c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng#if defined(WITH_JIT)
1059c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng    /*
1060c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng     * Patching a chaining cell is very cheap as it only updates 4 words. It's
1061c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng     * the overhead of stopping all threads and synchronizing the I/D cache
1062c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng     * that makes it expensive.
1063c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng     *
1064c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng     * Therefore we batch those work orders in a queue and go through them
1065c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng     * when threads are suspended for GC.
1066c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng     */
1067c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng    dvmCompilerPerformSafePointChecks();
1068c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng#endif
1069c3b92b26df6416d3179e865adccb283ee4170ab1Ben Cheng
1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmResumeAllThreads(SUSPEND_FOR_GC);
1071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (oldThreadPriority != kInvalidPriority) {
1072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (setpriority(PRIO_PROCESS, 0, oldThreadPriority) != 0) {
1073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW_HEAP("Unable to reset priority to %d: %s\n",
1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                oldThreadPriority, strerror(errno));
1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGD_HEAP("Reset priority to %d\n", oldThreadPriority);
1077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1078256fc159a267859c18e11e1d15fd7d97a59757c6San Mehat
10793e371e2ebbeeefe176ba1357e6ff241bd13a711eSan Mehat        if (oldThreadPriority >= ANDROID_PRIORITY_BACKGROUND) {
10805a2056ca8c7e7c0ed9f51d68cedbee59cc936685San Mehat            set_sched_policy(dvmGetSysThreadId(), SP_BACKGROUND);
1081256fc159a267859c18e11e1d15fd7d97a59757c6San Mehat        }
1082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gcElapsedTime = (dvmGetRelativeTimeUsec() - gcHeap->gcStartTime) / 1000;
10843136413fae48cee04095236a945e41782d6d10bcBarry Hayes    LOGD("%s freed %d objects / %zd bytes in %dms\n",
10853136413fae48cee04095236a945e41782d6d10bcBarry Hayes         GcReasonStr[reason], numFreed, sizeFreed, (int)gcElapsedTime);
1086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLogGcStats(numFreed, sizeFreed, gcElapsedTime);
1087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gcHeap->ddmHpifWhen != 0) {
1089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGD_HEAP("Sending VM heap info to DDM\n");
1090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmDdmSendHeapInfo(gcHeap->ddmHpifWhen, false);
1091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gcHeap->ddmHpsgWhen != 0) {
1093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGD_HEAP("Dumping VM heap to DDM\n");
1094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmDdmSendHeapSegments(false, false);
1095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gcHeap->ddmNhsgWhen != 0) {
1097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGD_HEAP("Dumping native heap to DDM\n");
1098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmDdmSendHeapSegments(false, true);
1099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if WITH_HPROF
1103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Perform garbage collection, writing heap information to the specified file.
1105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "fileName" is NULL, a suitable name will be generated automatically.
110799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project *
110899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Returns 0 on success, or an error code on failure.
1109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
11106bf992c9d51f1e12aa37fe4c791c156402a9b79bAndy McFaddenint hprofDumpHeap(const char* fileName, bool directToDdms)
1111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
111299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    int result;
111399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
1114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLockMutex(&gDvm.gcHeapLock);
1115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.gcHeap->hprofDumpOnGc = true;
1117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.gcHeap->hprofFileName = fileName;
11186bf992c9d51f1e12aa37fe4c791c156402a9b79bAndy McFadden    gDvm.gcHeap->hprofDirectToDdms = directToDdms;
11191b9b4e4b89e1c682b6684ae5e2a637e4497a67e9Barry Hayes    dvmCollectGarbageInternal(false, GC_HPROF_DUMP_HEAP);
112099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    result = gDvm.gcHeap->hprofResult;
1121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockMutex(&gDvm.gcHeapLock);
112399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
112499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    return result;
1125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmHeapSetHprofGcScanState(hprof_heap_tag_t state, u4 threadSerialNumber)
1128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.gcHeap->hprofContext != NULL) {
1130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprofSetGcScanState(gDvm.gcHeap->hprofContext, state,
1131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                threadSerialNumber);
1132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1135