static ObjectArray* listClasses(Env* env, Class* instanceofClazz, ClassLoader* classLoader, void* hash) { if (instanceofClazz && (CLASS_IS_ARRAY(instanceofClazz) || CLASS_IS_PRIMITIVE(instanceofClazz))) { return NULL; } ClassInfoHeader** base = getClassInfosBase(hash); uint32_t count = getClassInfosCount(hash); uint32_t i = 0; jint matches = count; TypeInfo* instanceofTypeInfo = instanceofClazz ? instanceofClazz->typeInfo : NULL; if (instanceofTypeInfo) { matches = 0; for (i = 0; i < count; i++) { ClassInfoHeader* header = base[i]; if ((header->flags & CI_ERROR) == 0) { if ((!CLASS_IS_INTERFACE(instanceofClazz) && rvmIsClassTypeInfoAssignable(env, header->typeInfo, instanceofTypeInfo)) || (CLASS_IS_INTERFACE(instanceofClazz) && rvmIsInterfaceTypeInfoAssignable(env, header->typeInfo, instanceofTypeInfo))) { matches++; } } } } if (matches == 0) return NULL; ObjectArray* result = rvmNewObjectArray(env, matches, java_lang_Class, NULL, NULL); if (!result) return NULL; jint j = 0; for (i = 0; i < count; i++) { ClassInfoHeader* header = base[i]; if ((header->flags & CI_ERROR) == 0) { if (!instanceofTypeInfo || ((!CLASS_IS_INTERFACE(instanceofClazz) && rvmIsClassTypeInfoAssignable(env, header->typeInfo, instanceofTypeInfo)) || (CLASS_IS_INTERFACE(instanceofClazz) && rvmIsInterfaceTypeInfoAssignable(env, header->typeInfo, instanceofTypeInfo)))) { result->values[j++] = (Object*) (header->clazz ? header->clazz : createClass(env, header, classLoader)); if (rvmExceptionOccurred(env)) return NULL; } } } return result; }
static ClassInfoHeader* lookupClassInfo(Env* env, const char* className, void* hash) { ClassInfoHeader** base = getClassInfosBase(hash); jint h = 0; MurmurHash3_x86_32(className, strlen(className) + 1, 0x1ce79e5c, &h); hash += sizeof(jint); // Skip count jint size = ((jshort*) hash)[0]; h &= size - 1; jint start = ((jshort*) hash)[h + 1]; jint end = ((jshort*) hash)[h + 1 + 1]; jint i; for (i = start; i < end; i++) { ClassInfoHeader* header = base[i]; if (header && !strcmp(header->className, className)) { return header; } } return NULL; }
static void iterateClassInfos(Env* env, jboolean (*callback)(Env*, ClassInfoHeader*, MethodInfo*, void*), void* hash, void* data) { ClassInfoHeader** base = getClassInfosBase(hash); jint count = getClassInfosCount(hash); jint i = 0; for (i = 0; i < count; i++) { ClassInfo ci; void* p = base[i]; readClassInfo(&p, &ci); skipInterfaceNames(&p, &ci); skipFieldInfos(&p, &ci); jint j; for (j = 0; j < ci.methodCount; j++) { MethodInfo mi; readMethodInfo(&p, &mi); if (!callback(env, base[i], &mi, data)) { break; } } } }
static ClassInfoHeader* lookupClassInfo(Env* env, const char* className, void* hash) { ClassInfoHeader** base = getClassInfosBase(hash); // Hash the class name uint32_t h = 0; MurmurHash3_x86_32(className, strlen(className) + 1, 0x1ce79e5c, &h); uint32_t size = ((uint32_t*) hash)[1]; h &= size - 1; // Get the start and end indexes hash += sizeof(uint32_t) + sizeof(uint32_t); // Skip count and size uint32_t start = ((uint32_t*) hash)[h]; uint32_t end = ((uint32_t*) hash)[h + 1]; // Iterate through the ClassInfoHeaders between start and end for (uint32_t i = start; i < end; i++) { ClassInfoHeader* header = base[i]; if (header && !strcmp(header->className, className)) { return header; } } return NULL; }