summaryrefslogtreecommitdiffstats
path: root/vm/alloc/Heap.c
diff options
context:
space:
mode:
Diffstat (limited to 'vm/alloc/Heap.c')
-rw-r--r--vm/alloc/Heap.c98
1 files changed, 12 insertions, 86 deletions
diff --git a/vm/alloc/Heap.c b/vm/alloc/Heap.c
index 5d88bc395..f38eb121d 100644
--- a/vm/alloc/Heap.c
+++ b/vm/alloc/Heap.c
@@ -19,12 +19,10 @@
#include "Dalvik.h"
#include "alloc/HeapBitmap.h"
#include "alloc/Verify.h"
-#include "alloc/HeapTable.h"
#include "alloc/Heap.h"
#include "alloc/HeapInternal.h"
#include "alloc/DdmHeap.h"
#include "alloc/HeapSource.h"
-#include "alloc/HeapWorker.h"
#include "alloc/MarkSweep.h"
#include "utils/threads.h" // need Android thread priorities
@@ -91,9 +89,6 @@ bool dvmHeapStartup()
if (gcHeap == NULL) {
return false;
}
- gcHeap->heapWorkerCurrentObject = NULL;
- gcHeap->heapWorkerCurrentMethod = NULL;
- gcHeap->heapWorkerInterpStartTime = 0LL;
gcHeap->ddmHpifWhen = 0;
gcHeap->ddmHpsgWhen = 0;
gcHeap->ddmHpsgWhat = 0;
@@ -101,22 +96,15 @@ bool dvmHeapStartup()
gcHeap->ddmNhsgWhat = 0;
gDvm.gcHeap = gcHeap;
- /* Set up the lists and lock we'll use for finalizable
- * and reference objects.
+ /* Set up the lists we'll use for cleared reference objects.
*/
- dvmInitMutex(&gDvm.heapWorkerListLock);
- gcHeap->referenceOperations = NULL;
+ gcHeap->clearedReferences = NULL;
if (!dvmCardTableStartup(gDvm.heapMaximumSize)) {
LOGE_HEAP("card table startup failed.");
return false;
}
- /* Initialize the HeapWorker locks and other state
- * that the GC uses.
- */
- dvmInitializeHeapWorkerState();
-
return true;
}
@@ -130,13 +118,6 @@ void dvmHeapShutdown()
//TODO: make sure we're locked
if (gDvm.gcHeap != NULL) {
dvmCardTableShutdown();
- /* Tables are allocated on the native heap; they need to be
- * cleaned up explicitly. The process may stick around, so we
- * don't want to leak any native memory.
- */
- dvmHeapFreeLargeTable(gDvm.gcHeap->referenceOperations);
- gDvm.gcHeap->referenceOperations = NULL;
-
/* Destroy the heap. Any outstanding pointers will point to
* unmapped memory (unless/until someone else maps it). This
* frees gDvm.gcHeap as a side-effect.
@@ -177,33 +158,6 @@ void dvmUnlockHeap()
dvmUnlockMutex(&gDvm.gcHeapLock);
}
-/* Pop an object from the list of pending finalizations and
- * reference clears/enqueues, and return the object.
- * The caller must call dvmReleaseTrackedAlloc()
- * on the object when finished.
- *
- * Typically only called by the heap worker thread.
- */
-Object *dvmGetNextHeapWorkerObject()
-{
- Object *obj;
- GcHeap *gcHeap = gDvm.gcHeap;
-
- dvmLockMutex(&gDvm.heapWorkerListLock);
-
- obj = dvmHeapGetNextObjectFromLargeTable(&gcHeap->referenceOperations);
- if (obj != NULL) {
- /* Don't let the GC collect the object until the
- * worker thread is done with it.
- */
- dvmAddTrackedAlloc(obj, NULL);
- }
-
- dvmUnlockMutex(&gDvm.heapWorkerListLock);
-
- return obj;
-}
-
/* Do a full garbage collection, which may grow the
* heap as a side-effect if the live set is large.
*/
@@ -577,13 +531,6 @@ void dvmCollectGarbageInternal(const GcSpec* spec)
gcHeap->gcRunning = true;
- /*
- * Grab the heapWorkerLock to prevent the HeapWorker thread from
- * doing work. If it's executing a finalizer or an enqueue operation
- * it won't be holding the lock, so this should return quickly.
- */
- dvmLockMutex(&gDvm.heapWorkerLock);
-
rootSuspend = dvmGetRelativeTimeMsec();
dvmSuspendAllThreads(SUSPEND_FOR_GC);
rootStart = dvmGetRelativeTimeMsec();
@@ -596,21 +543,6 @@ void dvmCollectGarbageInternal(const GcSpec* spec)
if (!spec->isConcurrent) {
oldThreadPriority = raiseThreadPriority();
}
-
- /* Make sure that the HeapWorker thread hasn't become
- * wedged inside interp code. If it has, this call will
- * print a message and abort the VM.
- */
- dvmAssertHeapWorkerThreadRunning();
-
- /* Lock the pendingFinalizationRefs list.
- *
- * Acquire the lock after suspending so the finalizer
- * thread can't block in the RUNNING state while
- * we try to suspend.
- */
- dvmLockMutex(&gDvm.heapWorkerListLock);
-
if (gDvm.preVerify) {
LOGV_HEAP("Verifying roots and heap before GC");
verifyRootsAndHeap();
@@ -634,9 +566,11 @@ void dvmCollectGarbageInternal(const GcSpec* spec)
/* dvmHeapScanMarkedObjects() will build the lists of known
* instances of the Reference classes.
*/
- gcHeap->softReferences = NULL;
- gcHeap->weakReferences = NULL;
- gcHeap->phantomReferences = NULL;
+ assert(gcHeap->softReferences == NULL);
+ assert(gcHeap->weakReferences == NULL);
+ assert(gcHeap->finalizerReferences == NULL);
+ assert(gcHeap->phantomReferences == NULL);
+ assert(gcHeap->clearedReferences == NULL);
if (spec->isConcurrent) {
/*
@@ -747,25 +681,12 @@ void dvmCollectGarbageInternal(const GcSpec* spec)
currAllocated = dvmHeapSourceGetValue(HS_BYTES_ALLOCATED, NULL, 0);
currFootprint = dvmHeapSourceGetValue(HS_FOOTPRINT, NULL, 0);
- /* Now that we've freed up the GC heap, return any large
- * free chunks back to the system. They'll get paged back
- * in the next time they're used. Don't do it immediately,
- * though; if the process is still allocating a bunch of
- * memory, we'll be taking a ton of page faults that we don't
- * necessarily need to.
- *
- * Cancel any old scheduled trims, and schedule a new one.
- */
- dvmScheduleHeapSourceTrim(5); // in seconds
-
dvmMethodTraceGCEnd();
LOGV_HEAP("GC finished");
gcHeap->gcRunning = false;
LOGV_HEAP("Resuming threads");
- dvmUnlockMutex(&gDvm.heapWorkerListLock);
- dvmUnlockMutex(&gDvm.heapWorkerLock);
if (spec->isConcurrent) {
/*
@@ -787,6 +708,11 @@ void dvmCollectGarbageInternal(const GcSpec* spec)
}
}
+ /*
+ * Move queue of pending references back into Java.
+ */
+ dvmEnqueueClearedReferences(&gDvm.gcHeap->clearedReferences);
+
percentFree = 100 - (size_t)(100.0f * (float)currAllocated / currFootprint);
if (!spec->isConcurrent) {
u4 markSweepTime = dirtyEnd - rootStart;