extern "C" void* j3ResolveStaticStub() { JavaThread *th = JavaThread::get(); 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* caller = (JavaMethod*)FI->Metadata; // Lookup the method info in the constant pool of the caller. uint16 ctpIndex = caller->lookupCtpIndex(FI); assert(ctpIndex && "No constant pool index"); JavaConstantPool* ctpInfo = caller->classDef->getConstantPool(); CommonClass* cl = 0; const UTF8* utf8 = 0; Signdef* sign = 0; ctpInfo->resolveMethod(ctpIndex, cl, utf8, sign); UserClass* lookup = cl->isArray() ? cl->super : cl->asClass(); assert(lookup->isInitializing() && "Class not ready"); JavaMethod* callee = lookup->lookupMethod(utf8, sign->keyName, true, true, 0); // Compile the found method. result = callee->compiledPtr(); // Update the entry in the constant pool. ctpInfo->ctpRes[ctpIndex] = result; return result; }
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; }