1adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro/*
2adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro * Copyright (C) 2010 The Android Open Source Project
3adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro *
4adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro * Licensed under the Apache License, Version 2.0 (the "License");
5adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro * you may not use this file except in compliance with the License.
6adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro * You may obtain a copy of the License at
7adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro *
8adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro *      http://www.apache.org/licenses/LICENSE-2.0
9adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro *
10adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro * Unless required by applicable law or agreed to in writing, software
11adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro * distributed under the License is distributed on an "AS IS" BASIS,
12adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro * See the License for the specific language governing permissions and
14adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro * limitations under the License.
15adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro */
16adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro
17adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro#include "Dalvik.h"
181fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro#include "alloc/HeapInternal.h"
19adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro#include "alloc/Visit.h"
20ddb0c1cfe13128de385123c52ca8c33efb1cb587Carl Shapiro#include "alloc/VisitInlines.h"
21adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro
22adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro/*
23ddb0c1cfe13128de385123c52ca8c33efb1cb587Carl Shapiro * Visits all of the reference locations in an object.
24adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro */
25056b9663171dc6f249a36faa49389142790965baCarl Shapirovoid dvmVisitObject(Visitor *visitor, Object *obj, void *arg)
26adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro{
27adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro    assert(visitor != NULL);
28adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro    assert(obj != NULL);
29899cdb783318da43e4e9c46ced3a29f2a62d5e9cBarry Hayes    assert(obj->clazz != NULL);
30ddb0c1cfe13128de385123c52ca8c33efb1cb587Carl Shapiro    visitObject(visitor, obj, arg);
31adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro}
321fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro
331fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro/*
341fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro * Applies a verification function to all present values in the hash table.
351fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro */
3607018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapirostatic void visitHashTable(RootVisitor *visitor, HashTable *table,
3707018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro                           RootType type, void *arg)
381fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro{
391fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    assert(visitor != NULL);
401fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    assert(table != NULL);
411fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    dvmHashTableLock(table);
42f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro    for (int i = 0; i < table->tableSize; ++i) {
431fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro        HashEntry *entry = &table->pEntries[i];
441fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro        if (entry->data != NULL && entry->data != HASH_TOMBSTONE) {
4507018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro            (*visitor)(&entry->data, 0, type, arg);
461fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro        }
471fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    }
481fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    dvmHashTableUnlock(table);
491fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro}
501fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro
511fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro/*
521fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro * Visits all entries in the reference table.
531fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro */
5407018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapirostatic void visitReferenceTable(RootVisitor *visitor, ReferenceTable *table,
5507018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro                                u4 threadId, RootType type, void *arg)
561fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro{
571fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    assert(visitor != NULL);
581fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    assert(table != NULL);
59f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro    for (Object **entry = table->table; entry < table->nextEntry; ++entry) {
601fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro        assert(entry != NULL);
6107018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro        (*visitor)(entry, threadId, type, arg);
621fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    }
631fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro}
641fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro
65e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro/*
66e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro * Visits all entries in the indirect reference table.
67e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro */
68e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapirostatic void visitIndirectRefTable(RootVisitor *visitor, IndirectRefTable *table,
69e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro                                  u4 threadId, RootType type, void *arg)
70e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro{
71e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro    assert(visitor != NULL);
72e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro    assert(table != NULL);
73259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes    typedef IndirectRefTable::iterator It; // TODO: C++0x auto
74259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes    for (It it = table->begin(), end = table->end(); it != end; ++it) {
75259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes        (*visitor)(*it, threadId, type, arg);
76e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro    }
77e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro}
78e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro
791fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro/*
806d4ce5e7162ae14638d1b094b44e60fb931c64eaCarl Shapiro * Visits all stack slots except those belonging to native method
816d4ce5e7162ae14638d1b094b44e60fb931c64eaCarl Shapiro * arguments.
821fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro */
8307018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapirostatic void visitThreadStack(RootVisitor *visitor, Thread *thread, void *arg)
841fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro{
851fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    assert(visitor != NULL);
861fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    assert(thread != NULL);
87f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro    u4 threadId = thread->threadId;
88f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro    const StackSaveArea *saveArea;
8930bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    for (u4 *fp = (u4 *)thread->interpSave.curFrame;
90f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro         fp != NULL;
91f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro         fp = (u4 *)saveArea->prevFrame) {
921fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro        Method *method;
9307018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro        saveArea = SAVEAREA_FROM_FP(fp);
941fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro        method = (Method *)saveArea->method;
951fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro        if (method != NULL && !dvmIsNativeMethod(method)) {
961fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro            const RegisterMap* pMap = dvmGetExpandedRegisterMap(method);
971fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro            const u1* regVector = NULL;
981fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro            if (pMap != NULL) {
991fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                /* found map, get registers for this address */
1001fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                int addr = saveArea->xtra.currentPc - method->insns;
1011fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                regVector = dvmRegisterMapGetLine(pMap, addr);
1021fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro            }
1031fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro            if (regVector == NULL) {
1041fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                /*
1051fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                 * Either there was no register map or there is no
1061fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                 * info for the current PC.  Perform a conservative
1071fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                 * scan.
1081fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                 */
109f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro                for (size_t i = 0; i < method->registersSize; ++i) {
11007018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro                    if (dvmIsValidObject((Object *)fp[i])) {
11107018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro                        (*visitor)(&fp[i], threadId, ROOT_JAVA_FRAME, arg);
1121fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                    }
1131fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                }
1141fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro            } else {
1151fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                /*
1161fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                 * Precise scan.  v0 is at the lowest address on the
1171fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                 * interpreted stack, and is the first bit in the
1181fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                 * register vector, so we can walk through the
1191fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                 * register map and memory in the same direction.
1201fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                 *
1211fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                 * A '1' bit indicates a live reference.
1221fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                 */
1231fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                u2 bits = 1 << 1;
124f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro                for (size_t i = 0; i < method->registersSize; ++i) {
1251fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                    bits >>= 1;
1261fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                    if (bits == 1) {
1271fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                        /* set bit 9 so we can tell when we're empty */
1281fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                        bits = *regVector++ | 0x0100;
1291fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                    }
1301fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                    if ((bits & 0x1) != 0) {
1311fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                        /*
1321fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                         * Register is marked as live, it's a valid root.
1331fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                         */
1346d4ce5e7162ae14638d1b094b44e60fb931c64eaCarl Shapiro#if WITH_EXTRA_GC_CHECKS
1356d4ce5e7162ae14638d1b094b44e60fb931c64eaCarl Shapiro                        if (fp[i] != 0 && !dvmIsValidObject((Object *)fp[i])) {
1366d4ce5e7162ae14638d1b094b44e60fb931c64eaCarl Shapiro                            /* this is very bad */
137c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block                            ALOGE("PGC: invalid ref in reg %d: %#x",
1386d4ce5e7162ae14638d1b094b44e60fb931c64eaCarl Shapiro                                 method->registersSize - 1 - i, fp[i]);
139c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block                            ALOGE("PGC: %s.%s addr %#x",
1406d4ce5e7162ae14638d1b094b44e60fb931c64eaCarl Shapiro                                 method->clazz->descriptor, method->name,
1416d4ce5e7162ae14638d1b094b44e60fb931c64eaCarl Shapiro                                 saveArea->xtra.currentPc - method->insns);
1426d4ce5e7162ae14638d1b094b44e60fb931c64eaCarl Shapiro                            continue;
1436d4ce5e7162ae14638d1b094b44e60fb931c64eaCarl Shapiro                        }
1446d4ce5e7162ae14638d1b094b44e60fb931c64eaCarl Shapiro#endif
14507018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro                        (*visitor)(&fp[i], threadId, ROOT_JAVA_FRAME, arg);
1461fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                    }
1471fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                }
1481fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro                dvmReleaseRegisterMapLine(pMap, regVector);
1491fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro            }
1501fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro        }
1511fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro        /*
1521fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro         * Don't fall into an infinite loop if things get corrupted.
1531fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro         */
15407018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro        assert((uintptr_t)saveArea->prevFrame > (uintptr_t)fp ||
1551fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro               saveArea->prevFrame == NULL);
1561fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    }
1571fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro}
1581fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro
1591fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro/*
1601fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro * Visits all roots associated with a thread.
1611fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro */
16207018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapirostatic void visitThread(RootVisitor *visitor, Thread *thread, void *arg)
1631fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro{
16407018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro    u4 threadId;
16507018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro
1661fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    assert(visitor != NULL);
1671fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    assert(thread != NULL);
16807018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro    threadId = thread->threadId;
16907018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro    (*visitor)(&thread->threadObj, threadId, ROOT_THREAD_OBJECT, arg);
17007018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro    (*visitor)(&thread->exception, threadId, ROOT_NATIVE_STACK, arg);
17107018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro    visitReferenceTable(visitor, &thread->internalLocalRefTable, threadId, ROOT_NATIVE_STACK, arg);
172e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro    visitIndirectRefTable(visitor, &thread->jniLocalRefTable, threadId, ROOT_JNI_LOCAL, arg);
17307018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro    if (thread->jniMonitorRefTable.table != NULL) {
17407018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro        visitReferenceTable(visitor, &thread->jniMonitorRefTable, threadId, ROOT_JNI_MONITOR, arg);
1751fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    }
1761fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    visitThreadStack(visitor, thread, arg);
1771fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro}
1781fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro
1791fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro/*
1801fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro * Visits all threads on the thread list.
1811fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro */
18207018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapirostatic void visitThreads(RootVisitor *visitor, void *arg)
1831fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro{
1841fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    Thread *thread;
1851fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro
1861fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    assert(visitor != NULL);
1871fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    dvmLockThreadList(dvmThreadSelf());
1881fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    thread = gDvm.threadList;
1891fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    while (thread) {
1901fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro        visitThread(visitor, thread, arg);
1911fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro        thread = thread->next;
1921fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    }
1931fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    dvmUnlockThreadList();
1941fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro}
1951fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro
196a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornsteinstatic void visitPrimitiveTypes(RootVisitor *visitor, void *arg)
197a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein{
19819007bb68e855759fb4326bb1d5e99d7d2c0a5e0Carl Shapiro    (*visitor)(&gDvm.typeVoid, 0, ROOT_STICKY_CLASS, arg);
199a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    (*visitor)(&gDvm.typeBoolean, 0, ROOT_STICKY_CLASS, arg);
20019007bb68e855759fb4326bb1d5e99d7d2c0a5e0Carl Shapiro    (*visitor)(&gDvm.typeByte, 0, ROOT_STICKY_CLASS, arg);
20119007bb68e855759fb4326bb1d5e99d7d2c0a5e0Carl Shapiro    (*visitor)(&gDvm.typeShort, 0, ROOT_STICKY_CLASS, arg);
20219007bb68e855759fb4326bb1d5e99d7d2c0a5e0Carl Shapiro    (*visitor)(&gDvm.typeChar, 0, ROOT_STICKY_CLASS, arg);
20319007bb68e855759fb4326bb1d5e99d7d2c0a5e0Carl Shapiro    (*visitor)(&gDvm.typeInt, 0, ROOT_STICKY_CLASS, arg);
20419007bb68e855759fb4326bb1d5e99d7d2c0a5e0Carl Shapiro    (*visitor)(&gDvm.typeLong, 0, ROOT_STICKY_CLASS, arg);
20519007bb68e855759fb4326bb1d5e99d7d2c0a5e0Carl Shapiro    (*visitor)(&gDvm.typeFloat, 0, ROOT_STICKY_CLASS, arg);
20619007bb68e855759fb4326bb1d5e99d7d2c0a5e0Carl Shapiro    (*visitor)(&gDvm.typeDouble, 0, ROOT_STICKY_CLASS, arg);
207a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein}
208a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein
2091fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro/*
21007018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro * Visits roots.  TODO: visit cached global references.
2111fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro */
21207018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapirovoid dvmVisitRoots(RootVisitor *visitor, void *arg)
2131fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro{
2141fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    assert(visitor != NULL);
21507018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro    visitHashTable(visitor, gDvm.loadedClasses, ROOT_STICKY_CLASS, arg);
216a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    visitPrimitiveTypes(visitor, arg);
217ca14ee3056973d3375e6db04555edbc66a1d9d58Carl Shapiro    if (gDvm.dbgRegistry != NULL) {
218ca14ee3056973d3375e6db04555edbc66a1d9d58Carl Shapiro        visitHashTable(visitor, gDvm.dbgRegistry, ROOT_DEBUGGER, arg);
219ca14ee3056973d3375e6db04555edbc66a1d9d58Carl Shapiro    }
2206d4ce5e7162ae14638d1b094b44e60fb931c64eaCarl Shapiro    if (gDvm.literalStrings != NULL) {
2216d4ce5e7162ae14638d1b094b44e60fb931c64eaCarl Shapiro        visitHashTable(visitor, gDvm.literalStrings, ROOT_INTERNED_STRING, arg);
2226d4ce5e7162ae14638d1b094b44e60fb931c64eaCarl Shapiro    }
2236d4ce5e7162ae14638d1b094b44e60fb931c64eaCarl Shapiro    dvmLockMutex(&gDvm.jniGlobalRefLock);
224e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro    visitIndirectRefTable(visitor, &gDvm.jniGlobalRefTable, 0, ROOT_JNI_GLOBAL, arg);
2256d4ce5e7162ae14638d1b094b44e60fb931c64eaCarl Shapiro    dvmUnlockMutex(&gDvm.jniGlobalRefLock);
2266d4ce5e7162ae14638d1b094b44e60fb931c64eaCarl Shapiro    dvmLockMutex(&gDvm.jniPinRefLock);
2271ec987e93d3df96a40cede2f5ecdc81d4de604c6Carl Shapiro    visitReferenceTable(visitor, &gDvm.jniPinRefTable, 0, ROOT_VM_INTERNAL, arg);
2286d4ce5e7162ae14638d1b094b44e60fb931c64eaCarl Shapiro    dvmUnlockMutex(&gDvm.jniPinRefLock);
2291fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    visitThreads(visitor, arg);
23007018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro    (*visitor)(&gDvm.outOfMemoryObj, 0, ROOT_VM_INTERNAL, arg);
23107018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro    (*visitor)(&gDvm.internalErrorObj, 0, ROOT_VM_INTERNAL, arg);
23207018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro    (*visitor)(&gDvm.noClassDefFoundErrorObj, 0, ROOT_VM_INTERNAL, arg);
2331fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro}
234