UserClass* JnjvmClassLoader::internalLoad(const UTF8* name, bool doResolve, JavaString* strName) { JavaObject* obj = 0; llvm_gcroot(strName, 0); llvm_gcroot(obj, 0); UserCommonClass* cl = lookupClass(name); if (!cl) { UserClass* forCtp = loadClass; if (strName == NULL) { strName = JavaString::internalToJava(name, isolate); } obj = loadClassMethod->invokeJavaObjectVirtual(isolate, forCtp, javaLoader, &strName, doResolve); cl = JavaObjectClass::getClass(((JavaObjectClass*)obj)); } if (cl) { assert(!cl->isArray()); if (doResolve) cl->asClass()->resolveClass(); } return (UserClass*)cl; }
// Throws if the field is not found. extern "C" void* j3VirtualFieldLookup(UserClass* caller, uint32 index) { void* res = 0; UserConstantPool* ctpInfo = caller->getConstantPool(); if (ctpInfo->ctpRes[index]) { res = ctpInfo->ctpRes[index]; } else { UserCommonClass* cl = 0; const UTF8* utf8 = 0; Typedef* sign = 0; ctpInfo->resolveField(index, cl, utf8, sign); UserClass* lookup = cl->isArray() ? cl->super : cl->asClass(); JavaField* field = lookup->lookupField(utf8, sign->keyName, false, true, 0); ctpInfo->ctpRes[index] = (void*)(intptr_t)field->ptrOffset; res = (void*)(intptr_t)field->ptrOffset; } return res; }
// Throws if the method is not found. extern "C" uint32 j3VirtualTableLookup(UserClass* caller, uint32 index, uint32* offset, JavaObject* obj) { llvm_gcroot(obj, 0); uint32 res = 0; UserCommonClass* cl = 0; const UTF8* utf8 = 0; Signdef* sign = 0; caller->getConstantPool()->resolveMethod(index, cl, utf8, sign); UserClass* lookup = cl->isArray() ? cl->super : cl->asClass(); JavaMethod* dmeth = lookup->lookupMethodDontThrow(utf8, sign->keyName, false, true, 0); if (!dmeth) { assert((JavaObject::getClass(obj)->isClass() && JavaObject::getClass(obj)->asClass()->isInitializing()) && "Class not ready in a virtual lookup."); // Arg, the bytecode is buggy! Perform the lookup on the object class // and do not update offset. lookup = JavaObject::getClass(obj)->isArray() ? JavaObject::getClass(obj)->super : JavaObject::getClass(obj)->asClass(); dmeth = lookup->lookupMethod(utf8, sign->keyName, false, true, 0); } else { *offset = dmeth->offset; } assert(dmeth->classDef->isInitializing() && "Class not ready in a virtual lookup."); res = dmeth->offset; return res; }
extern "C" uint8 Java_java_lang_Class_isArray__(JavaObjectClass* klass) { llvm_gcroot(klass, 0); UserCommonClass* cl = 0; BEGIN_NATIVE_EXCEPTION(0) cl = JavaObjectClass::getClass(klass); END_NATIVE_EXCEPTION return (uint8)cl->isArray(); }
UserClass* JnjvmBootstrapLoader::internalLoad(const UTF8* name, bool doResolve, JavaString* strName) { ClassBytes* bytes = NULL; llvm_gcroot(strName, 0); UserCommonClass* cl = lookupClass(name); if (!cl) { bytes = openName(name); if (bytes != NULL) { cl = constructClass(name, bytes); } } if (cl) { assert(!cl->isArray()); if (doResolve) cl->asClass()->resolveClass(); } if (cl) { // If we don't have knowledge of the package containing this class, // add it to the set of packages defined in this classLoader UTF8Buffer buffer(name); const char * cname = buffer.cString(); const char * slash = strrchr(cname, '/'); if (slash) { int packagelen = slash - cname; const UTF8 * package = name->extract(hashUTF8, 0, packagelen); //classes->lock.lock(); lock.lock(); packages.insert(package); lock.unlock(); //classes->lock.unlock(); } } return (UserClass*)cl; }
UserClass* JnjvmBootstrapLoader::internalLoad(const UTF8* name, bool doResolve, JavaString* strName) { ArrayUInt8* bytes = NULL; llvm_gcroot(bytes, 0); llvm_gcroot(strName, 0); UserCommonClass* cl = lookupClass(name); if (!cl) { bytes = openName(name); if (bytes != NULL) { cl = constructClass(name, bytes); } } if (cl) { assert(!cl->isArray()); if (doResolve) cl->asClass()->resolveClass(); } return (UserClass*)cl; }
extern "C" void* j3ResolveVirtualStub(JavaObject* obj) { llvm_gcroot(obj, 0); JavaThread *th = JavaThread::get(); UserCommonClass* cl = JavaObject::getClass(obj); void* result = NULL; // Lookup the caller of this class. vmkit::StackWalker Walker(th); ++Walker; // Remove the stub. vmkit::FrameInfo* FI = Walker.get(); assert(FI->Metadata != NULL && "Wrong stack trace"); JavaMethod* meth = (JavaMethod*)FI->Metadata; // Lookup the method info in the constant pool of the caller. uint16 ctpIndex = meth->lookupCtpIndex(FI); assert(ctpIndex && "No constant pool index"); JavaConstantPool* ctpInfo = meth->classDef->getConstantPool(); CommonClass* ctpCl = 0; const UTF8* utf8 = 0; Signdef* sign = 0; JavaMethod* origMeth = 0; ctpInfo->infoOfMethod(ctpIndex, ACC_VIRTUAL, ctpCl, origMeth); ctpInfo->resolveMethod(ctpIndex, ctpCl, utf8, sign); assert(cl->isSubclassOf(ctpCl) && "Wrong call object"); UserClass* lookup = cl->isArray() ? cl->super : cl->asClass(); JavaMethod* Virt = lookup->lookupMethod(utf8, sign->keyName, false, true, 0); if (isAbstract(Virt->access)) { JavaThread::get()->getJVM()->abstractMethodError(Virt->classDef, Virt->name); } // Compile the found method. result = Virt->compiledPtr(lookup); // Update the virtual table. assert(lookup->isResolved() && "Class not resolved"); assert(lookup->isInitializing() && "Class not ready"); assert(lookup->virtualVT && "Class has no VT"); assert(lookup->virtualTableSize > Virt->offset && "The method's offset is greater than the virtual table size"); ((void**)obj->getVirtualTable())[Virt->offset] = result; if (isInterface(origMeth->classDef->access)) { InterfaceMethodTable* IMT = cl->virtualVT->IMT; uint32_t index = InterfaceMethodTable::getIndex(Virt->name, Virt->type); if ((IMT->contents[index] & 1) == 0) { IMT->contents[index] = (word_t)result; } else { JavaMethod* Imeth = ctpCl->asClass()->lookupInterfaceMethodDontThrow(utf8, sign->keyName); assert(Imeth && "Method not in hierarchy?"); word_t* table = (word_t*)(IMT->contents[index] & ~1); uint32 i = 0; while (table[i] != (word_t)Imeth) { i += 2; } table[i + 1] = (word_t)result; } } return result; }