Visit.cpp revision e4c3b5ef3b418ea50f577a850bdbdfaf97718601
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2010 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "Dalvik.h"
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "alloc/HeapInternal.h"
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "alloc/Visit.h"
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "alloc/VisitInlines.h"
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Visits all of the reference locations in an object.
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid dvmVisitObject(Visitor *visitor, Object *obj, void *arg)
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(visitor != NULL);
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(obj != NULL);
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(obj->clazz != NULL);
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    visitObject(visitor, obj, arg);
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Applies a verification function to all present values in the hash table.
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void visitHashTable(RootVisitor *visitor, HashTable *table,
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                           RootType type, void *arg)
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int i;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(visitor != NULL);
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(table != NULL);
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    dvmHashTableLock(table);
44a833cbbed087bf6869905a43166757a6436ad34fDave Bort    for (i = 0; i < table->tableSize; ++i) {
45a833cbbed087bf6869905a43166757a6436ad34fDave Bort        HashEntry *entry = &table->pEntries[i];
46a833cbbed087bf6869905a43166757a6436ad34fDave Bort        if (entry->data != NULL && entry->data != HASH_TOMBSTONE) {
47a833cbbed087bf6869905a43166757a6436ad34fDave Bort            (*visitor)(&entry->data, 0, type, arg);
48a833cbbed087bf6869905a43166757a6436ad34fDave Bort        }
49a833cbbed087bf6869905a43166757a6436ad34fDave Bort    }
50a833cbbed087bf6869905a43166757a6436ad34fDave Bort    dvmHashTableUnlock(table);
51a833cbbed087bf6869905a43166757a6436ad34fDave Bort}
52a833cbbed087bf6869905a43166757a6436ad34fDave Bort
53a833cbbed087bf6869905a43166757a6436ad34fDave Bort/*
54a833cbbed087bf6869905a43166757a6436ad34fDave Bort * Applies a verification function to all elements in the array.
55a833cbbed087bf6869905a43166757a6436ad34fDave Bort */
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void visitArray(RootVisitor *visitor, Object **array, size_t length,
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                       RootType type, void *arg)
58c1e8aa4c448807fc3ee9d21e8b67bb886fa065aaMike Lockwood{
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t i;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(visitor != NULL);
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(array != NULL);
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (i = 0; i < length; ++i) {
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        (*visitor)(&array[i], 0, type, arg);
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
68dace230043314d6fab1c5ced4b031eaccd814c25Dianne Hackborn/*
69603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * Visits all entries in the reference table.
70603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana */
71603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintanastatic void visitReferenceTable(RootVisitor *visitor, ReferenceTable *table,
72603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                                u4 threadId, RootType type, void *arg)
73b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn{
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Object **entry;
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(visitor != NULL);
77b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn    assert(table != NULL);
78d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    for (entry = table->table; entry < table->nextEntry; ++entry) {
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        assert(entry != NULL);
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        (*visitor)(entry, threadId, type, arg);
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
828d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert}
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef USE_INDIRECT_REF
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Visits all entries in the indirect reference table.
878cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn */
888cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackbornstatic void visitIndirectRefTable(RootVisitor *visitor, IndirectRefTable *table,
89487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate                                  u4 threadId, RootType type, void *arg)
907d562ec393d54dd9ef387c49d1283243bfdbd2b1Christopher Tate{
918c850b792f2d371fd8a4aff146d9d757ee982539Christopher Tate    assert(visitor != NULL);
92bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    assert(table != NULL);
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Object **entry = table->table;
9416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly    int numEntries = dvmIndirectRefTableEntries(table);
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int i;
963f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu    for (i = 0; i < numEntries; ++i) {
97b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn        (*visitor)(&entry[i], threadId, type, arg);
981ccac75e1f1b97eccb916a8de04fc1012b30f6e5Suchi Amalapurapu    }
991ccac75e1f1b97eccb916a8de04fc1012b30f6e5Suchi Amalapurapu}
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
102b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn/*
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Visits a large heap reference table.  These objects are list heads.
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * As such, it is valid for table to be NULL.
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void visitLargeHeapRefTable(RootVisitor *visitor,
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                   LargeHeapRefTable *table,
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                   RootType type, void *arg)
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(visitor != NULL);
1114d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    for (; table != NULL; table = table->next) {
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        visitReferenceTable(visitor, &table->refs, 0, type, arg);
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1154270e1ea74c57f1c65620e9f5ecaa8c2a5daf0e1San Mehat
116873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat/*
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Visits all stack slots except those belonging to native method
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * arguments.
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void visitThreadStack(RootVisitor *visitor, Thread *thread, void *arg)
1218ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn{
1223a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    const StackSaveArea *saveArea;
12345948fd407da525e6c8721ba75cfc8b356fc7e0fPatrick Scott    u4 *fp;
12445948fd407da525e6c8721ba75cfc8b356fc7e0fPatrick Scott    u4 threadId;
1254c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
1264c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    assert(visitor != NULL);
1278cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    assert(thread != NULL);
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    threadId = thread->threadId;
12975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    fp = (u4 *)thread->curFrame;
13075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    for (; fp != NULL; fp = (u4 *)saveArea->prevFrame) {
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Method *method;
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        saveArea = SAVEAREA_FROM_FP(fp);
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        method = (Method *)saveArea->method;
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (method != NULL && !dvmIsNativeMethod(method)) {
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const RegisterMap* pMap = dvmGetExpandedRegisterMap(method);
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const u1* regVector = NULL;
137361ec7711aa689aa70c5473348f4a1bc91bc1c06Alex Gruenstein            size_t i;
138361ec7711aa689aa70c5473348f4a1bc91bc1c06Alex Gruenstein
139f85aa5a4d4e6f1ef7e07638568e27d709b8085c6Charles Chen            if (pMap != NULL) {
140f85aa5a4d4e6f1ef7e07638568e27d709b8085c6Charles Chen                /* found map, get registers for this address */
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int addr = saveArea->xtra.currentPc - method->insns;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                regVector = dvmRegisterMapGetLine(pMap, addr);
143c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu            }
144c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            if (regVector == NULL) {
145c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                /*
146487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate                 * Either there was no register map or there is no
147f18a01c77e78209b74e34d05cfb352fa4a92db5fDan Egnor                 * info for the current PC.  Perform a conservative
148c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                 * scan.
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                 */
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (i = 0; i < method->registersSize; ++i) {
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (dvmIsValidObject((Object *)fp[i])) {
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        (*visitor)(&fp[i], threadId, ROOT_JAVA_FRAME, arg);
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
156a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood                /*
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                 * Precise scan.  v0 is at the lowest address on the
15815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                 * interpreted stack, and is the first bit in the
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                 * register vector, so we can walk through the
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                 * register map and memory in the same direction.
161c1e8aa4c448807fc3ee9d21e8b67bb886fa065aaMike Lockwood                 *
16222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie                 * A '1' bit indicates a live reference.
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                 */
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                u2 bits = 1 << 1;
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (i = 0; i < method->registersSize; ++i) {
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    bits >>= 1;
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (bits == 1) {
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        /* set bit 9 so we can tell when we're empty */
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        bits = *regVector++ | 0x0100;
17004e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville                    }
17104e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville                    if ((bits & 0x1) != 0) {
172e91bc680b731a5d97f066b2e6c9c99b3c7dd5c58John Wang                        /*
1739207b1e7c8ad4bbef3530d2b047bf6587f2988c4Raphael                         * Register is marked as live, it's a valid root.
17455567efca99de7242b118cf7bf13cc773b01941cHung-ying Tyan                         */
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if WITH_EXTRA_GC_CHECKS
17645e6dbf90b24543c90f8c6b0426e9b70c934838dDoug Zongker                        if (fp[i] != 0 && !dvmIsValidObject((Object *)fp[i])) {
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            /* this is very bad */
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            LOGE("PGC: invalid ref in reg %d: %#x",
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                 method->registersSize - 1 - i, fp[i]);
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            LOGE("PGC: %s.%s addr %#x",
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                 method->clazz->descriptor, method->name,
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                 saveArea->xtra.currentPc - method->insns);
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            continue;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        (*visitor)(&fp[i], threadId, ROOT_JAVA_FRAME, arg);
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dvmReleaseRegisterMapLine(pMap, regVector);
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Don't fall into an infinite loop if things get corrupted.
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        assert((uintptr_t)saveArea->prevFrame > (uintptr_t)fp ||
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               saveArea->prevFrame == NULL);
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Visits all roots associated with a thread.
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void visitThread(RootVisitor *visitor, Thread *thread, void *arg)
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    u4 threadId;
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(visitor != NULL);
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(thread != NULL);
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    threadId = thread->threadId;
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    (*visitor)(&thread->threadObj, threadId, ROOT_THREAD_OBJECT, arg);
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    (*visitor)(&thread->exception, threadId, ROOT_NATIVE_STACK, arg);
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    visitReferenceTable(visitor, &thread->internalLocalRefTable, threadId, ROOT_NATIVE_STACK, arg);
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef USE_INDIRECT_REF
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    visitIndirectRefTable(visitor, &thread->jniLocalRefTable, threadId, ROOT_JNI_LOCAL, arg);
215603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana#else
216603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    visitReferenceTable(visitor, &thread->jniLocalRefTable, threadId, ROOT_JNI_LOCAL, arg);
217603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana#endif
218603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    if (thread->jniMonitorRefTable.table != NULL) {
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        visitReferenceTable(visitor, &thread->jniMonitorRefTable, threadId, ROOT_JNI_MONITOR, arg);
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
221459ba8639a8d1a9b0fb7ff4ada68bf1fe262eaaaNick Pelly    visitThreadStack(visitor, thread, arg);
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2241ccac75e1f1b97eccb916a8de04fc1012b30f6e5Suchi Amalapurapu/*
225c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana * Visits all threads on the thread list.
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void visitThreads(RootVisitor *visitor, void *arg)
228c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project{
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Thread *thread;
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
231f18a01c77e78209b74e34d05cfb352fa4a92db5fDan Egnor    assert(visitor != NULL);
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    dvmLockThreadList(dvmThreadSelf());
233aef439e6f825c0cb99a2ac08c8207f48b7a9fe10Nick Pelly    thread = gDvm.threadList;
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (thread) {
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        visitThread(visitor, thread, arg);
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        thread = thread->next;
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    dvmUnlockThreadList();
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Visits roots.  TODO: visit cached global references.
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid dvmVisitRoots(RootVisitor *visitor, void *arg)
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(visitor != NULL);
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    visitHashTable(visitor, gDvm.loadedClasses, ROOT_STICKY_CLASS, arg);
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    visitArray(visitor, (Object **)gDvm.primitiveClass, NELEM(gDvm.primitiveClass), ROOT_STICKY_CLASS, arg);
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (gDvm.dbgRegistry != NULL) {
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        visitHashTable(visitor, gDvm.dbgRegistry, ROOT_DEBUGGER, arg);
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
252d8b51a2ba8ee82be81414c0e80158e82b2c361d9Raphael    if (gDvm.literalStrings != NULL) {
25355567efca99de7242b118cf7bf13cc773b01941cHung-ying Tyan        visitHashTable(visitor, gDvm.literalStrings, ROOT_INTERNED_STRING, arg);
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    dvmLockMutex(&gDvm.jniGlobalRefLock);
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef USE_INDIRECT_REF
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    visitIndirectRefTable(visitor, &gDvm.jniGlobalRefTable, 0, ROOT_JNI_GLOBAL, arg);
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    visitReferenceTable(visitor, &gDvm.jniGlobalRefTable, 0, ROOT_JNI_GLOBAL, arg);
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    dvmUnlockMutex(&gDvm.jniGlobalRefLock);
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    dvmLockMutex(&gDvm.jniPinRefLock);
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    visitReferenceTable(visitor, &gDvm.jniPinRefTable, 0, ROOT_VM_INTERNAL, arg);
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    dvmUnlockMutex(&gDvm.jniPinRefLock);
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    visitLargeHeapRefTable(visitor, gDvm.gcHeap->referenceOperations, ROOT_REFERENCE_CLEANUP, arg);
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    visitLargeHeapRefTable(visitor, gDvm.gcHeap->pendingFinalizationRefs, ROOT_FINALIZING, arg);
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    visitThreads(visitor, arg);
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    (*visitor)(&gDvm.outOfMemoryObj, 0, ROOT_VM_INTERNAL, arg);
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    (*visitor)(&gDvm.internalErrorObj, 0, ROOT_VM_INTERNAL, arg);
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    (*visitor)(&gDvm.noClassDefFoundErrorObj, 0, ROOT_VM_INTERNAL, arg);
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project