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