blob: e2a32abd04c745928c8dcd10ff9fd632fb481d1b [file] [log] [blame]
//===-------------------- JavaRuntimeJIT.cpp ------------------------------===//
//=== ---- Runtime functions called by code compiled by the JIT -----------===//
//
// The VMKit project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "ClasspathReflect.h"
#include "JavaArray.h"
#include "JavaClass.h"
#include "JavaConstantPool.h"
#include "JavaString.h"
#include "JavaThread.h"
#include "JavaTypes.h"
#include "Jnjvm.h"
#include "j3/OpcodeNames.def"
#include <cstdarg>
using namespace j3;
extern "C" void* j3InterfaceLookup(UserClass* caller, uint32 index) {
void* res = 0;
BEGIN_NATIVE_EXCEPTION(1)
UserConstantPool* ctpInfo = caller->getConstantPool();
if (ctpInfo->ctpRes[index]) {
res = ctpInfo->ctpRes[index];
} else {
UserCommonClass* cl = 0;
const UTF8* utf8 = 0;
Signdef* sign = 0;
ctpInfo->resolveMethod(index, cl, utf8, sign);
assert(cl->isClass() && isInterface(cl->access) && "Wrong type of method");
res = cl->asClass()->lookupInterfaceMethodDontThrow(utf8, sign->keyName);
assert(res && "Can not found method");
ctpInfo->ctpRes[index] = (void*)res;
}
END_NATIVE_EXCEPTION
// Since the function is marked readnone, LLVM may move it after the
// exception check. Therefore, we trick LLVM to check the return value of the
// function.
JavaObject* obj = JavaThread::get()->pendingException;
if (obj) return (JavaMethod*)obj;
return res;
}
// Throws if the field is not found.
extern "C" void* j3VirtualFieldLookup(UserClass* caller, uint32 index) {
void* res = 0;
BEGIN_NATIVE_EXCEPTION(1)
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*)field->ptrOffset;
res = (void*)field->ptrOffset;
}
END_NATIVE_EXCEPTION
// Since the function is marked readnone, LLVM may move it after the
// exception check. Therefore, we trick LLVM to check the return value of the
// function.
JavaObject* obj = JavaThread::get()->pendingException;
if (obj) return (void*)obj;
return res;
}
// Throws if the field or its class is not found.
extern "C" void* j3StaticFieldLookup(UserClass* caller, uint32 index) {
void* res = 0;
BEGIN_NATIVE_EXCEPTION(1)
UserConstantPool* ctpInfo = caller->getConstantPool();
if (ctpInfo->ctpRes[index]) {
res = ctpInfo->ctpRes[index];
} else {
UserCommonClass* cl = 0;
UserClass* fieldCl = 0;
const UTF8* utf8 = 0;
Typedef* sign = 0;
ctpInfo->resolveField(index, cl, utf8, sign);
assert(cl->asClass() && "Lookup a field of something not an array");
JavaField* field = cl->asClass()->lookupField(utf8, sign->keyName, true,
true, &fieldCl);
fieldCl->initialiseClass(JavaThread::get()->getJVM());
void* obj = ((UserClass*)fieldCl)->getStaticInstance();
assert(obj && "No static instance in static field lookup");
void* ptr = (void*)((uint64)obj + field->ptrOffset);
ctpInfo->ctpRes[index] = ptr;
res = ptr;
}
END_NATIVE_EXCEPTION
// Since the function is marked readnone, LLVM may move it after the
// exception check. Therefore, we trick LLVM to check the return value of the
// function.
JavaObject* obj = JavaThread::get()->pendingException;
if (obj) return (void*)obj;
return res;
}
#ifndef WITHOUT_VTABLE
// 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;
BEGIN_NATIVE_EXCEPTION(1)
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((obj->getClass()->isClass() &&
obj->getClass()->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 = obj->getClass()->isArray() ? obj->getClass()->super :
obj->getClass()->asClass();
dmeth = lookup->lookupMethod(utf8, sign->keyName, false, true, 0);
} else {
*offset = dmeth->offset;
}
#if !defined(ISOLATE_SHARING) && !defined(SERVICE)
assert(dmeth->classDef->isInitializing() &&
"Class not ready in a virtual lookup.");
#endif
res = dmeth->offset;
END_NATIVE_EXCEPTION
return res;
}
#endif
// Throws if the class is not found.
extern "C" void* j3ClassLookup(UserClass* caller, uint32 index) {
void* res = 0;
BEGIN_NATIVE_EXCEPTION(1)
UserConstantPool* ctpInfo = caller->getConstantPool();
UserClass* cl = (UserClass*)ctpInfo->loadClass(index);
// We can not initialize here, because bytecodes such as CHECKCAST
// or classes used in catch clauses do not trigger class initialization.
// This is really sad, because we need to insert class initialization checks
// in the LLVM code.
assert(cl && "No cl after class lookup");
res = (void*)cl;
END_NATIVE_EXCEPTION
// Since the function is marked readnone, LLVM may move it after the
// exception check. Therefore, we trick LLVM to check the return value of the
// function.
JavaObject* obj = JavaThread::get()->pendingException;
if (obj) return (void*)obj;
return res;
}
// Calls Java code.
// Throws if initializing the class throws an exception.
extern "C" UserCommonClass* j3RuntimeInitialiseClass(UserClass* cl) {
BEGIN_NATIVE_EXCEPTION(1)
cl->resolveClass();
cl->initialiseClass(JavaThread::get()->getJVM());
END_NATIVE_EXCEPTION
// Since the function is marked readnone, LLVM may move it after the
// exception check. Therefore, we trick LLVM to check the return value of the
// function.
JavaObject* obj = JavaThread::get()->pendingException;
if (obj) return (UserCommonClass*)obj;
return cl;
}
// Calls Java code.
extern "C" JavaObject* j3RuntimeDelegatee(UserCommonClass* cl) {
JavaObject* res = 0;
llvm_gcroot(res, 0);
BEGIN_NATIVE_EXCEPTION(1)
Jnjvm* vm = JavaThread::get()->getJVM();
res = cl->getClassDelegatee(vm);
END_NATIVE_EXCEPTION
// Since the function is marked readnone, LLVM may move it after the
// exception check. Therefore, we trick LLVM to check the return value of the
// function.
JavaObject* obj = JavaThread::get()->pendingException;
if (obj) return obj;
return res;
}
// Throws if one of the dimension is negative.
static JavaArray* multiCallNewIntern(UserClassArray* cl, uint32 len,
sint32* dims, Jnjvm* vm) {
assert(len > 0 && "Negative size given by VMKit");
JavaArray* _res = cl->doNew(dims[0], vm);
ArrayObject* res = 0;
llvm_gcroot(_res, 0);
llvm_gcroot(res, 0);
if (len > 1) {
res = (ArrayObject*)_res;
UserCommonClass* _base = cl->baseClass();
assert(_base->isArray() && "Base class not an array");
UserClassArray* base = (UserClassArray*)_base;
if (dims[0] > 0) {
for (sint32 i = 0; i < dims[0]; ++i) {
res->elements[i] = multiCallNewIntern(base, (len - 1),
&dims[1], vm);
}
} else {
for (uint32 i = 1; i < len; ++i) {
sint32 p = dims[i];
if (p < 0) JavaThread::get()->getJVM()->negativeArraySizeException(p);
}
}
}
return _res;
}
// Throws if one of the dimension is negative.
extern "C" JavaArray* j3MultiCallNew(UserClassArray* cl, uint32 len, ...) {
JavaArray* res = 0;
llvm_gcroot(res, 0);
BEGIN_NATIVE_EXCEPTION(1)
va_list ap;
va_start(ap, len);
sint32* dims = (sint32*)alloca(sizeof(sint32) * len);
for (uint32 i = 0; i < len; ++i){
dims[i] = va_arg(ap, int);
}
Jnjvm* vm = JavaThread::get()->getJVM();
res = multiCallNewIntern(cl, len, dims, vm);
END_NATIVE_EXCEPTION
return res;
}
// Throws if the class can not be resolved.
extern "C" UserClassArray* j3GetArrayClass(UserCommonClass* cl,
UserClassArray** dcl) {
UserClassArray* res = 0;
BEGIN_NATIVE_EXCEPTION(1)
JnjvmClassLoader* JCL = cl->classLoader;
if (cl->asClass()) cl->asClass()->resolveClass();
const UTF8* arrayName = JCL->constructArrayName(1, cl->getName());
res = JCL->constructArray(arrayName);
if (dcl) *dcl = res;
END_NATIVE_EXCEPTION
// Since the function is marked readnone, LLVM may move it after the
// exception check. Therefore, we trick LLVM to check the return value of the
// function.
JavaObject* obj = JavaThread::get()->pendingException;
if (obj) return (UserClassArray*)obj;
return res;
}
// Does not call Java code. Can not yield a GC.
extern "C" void j3EndJNI(uint32** oldLRN) {
JavaThread* th = JavaThread::get();
// We're going back to Java
th->endJNI();
// Update the number of references.
th->currentAddedReferences = *oldLRN;
}
extern "C" void* j3StartJNI(uint32* localReferencesNumber,
uint32** oldLocalReferencesNumber,
mvm::KnownFrame* Frame)
__attribute__((noinline));
// Never throws. Does not call Java code. Can not yied a GC.
extern "C" void* j3StartJNI(uint32* localReferencesNumber,
uint32** oldLocalReferencesNumber,
mvm::KnownFrame* Frame) {
JavaThread* th = JavaThread::get();
*oldLocalReferencesNumber = th->currentAddedReferences;
th->currentAddedReferences = localReferencesNumber;
th->startKnownFrame(*Frame);
th->startJNI(1);
return Frame->currentFP;
}
// Never throws.
extern "C" void j3JavaObjectAquire(JavaObject* obj) {
BEGIN_NATIVE_EXCEPTION(1)
llvm_gcroot(obj, 0);
obj->acquire();
END_NATIVE_EXCEPTION
}
// Never throws.
extern "C" void j3JavaObjectRelease(JavaObject* obj) {
BEGIN_NATIVE_EXCEPTION(1)
llvm_gcroot(obj, 0);
obj->release();
END_NATIVE_EXCEPTION
}
// Does not call any Java code. Can not yield a GC.
extern "C" void j3ThrowException(JavaObject* obj) {
return JavaThread::get()->throwException(obj);
}
// Never throws.
extern "C" void j3OverflowThinLock(JavaObject* obj) {
obj->overflowThinLock();
}
// Creates a Java object and then throws it.
extern "C" JavaObject* j3NullPointerException() {
JavaObject *exc = 0;
JavaThread *th = JavaThread::get();
BEGIN_NATIVE_EXCEPTION(1)
exc = th->getJVM()->CreateNullPointerException();
END_NATIVE_EXCEPTION
#ifdef DWARF_EXCEPTIONS
th->throwException(exc);
#else
th->pendingException = exc;
#endif
return exc;
}
// Creates a Java object and then throws it.
extern "C" JavaObject* j3NegativeArraySizeException(sint32 val) {
JavaObject *exc = 0;
JavaThread *th = JavaThread::get();
BEGIN_NATIVE_EXCEPTION(1)
exc = th->getJVM()->CreateNegativeArraySizeException();
END_NATIVE_EXCEPTION
#ifdef DWARF_EXCEPTIONS
th->throwException(exc);
#else
th->pendingException = exc;
#endif
return exc;
}
// Creates a Java object and then throws it.
extern "C" JavaObject* j3OutOfMemoryError(sint32 val) {
JavaObject *exc = 0;
JavaThread *th = JavaThread::get();
BEGIN_NATIVE_EXCEPTION(1)
exc = th->getJVM()->CreateOutOfMemoryError();
END_NATIVE_EXCEPTION
#ifdef DWARF_EXCEPTIONS
th->throwException(exc);
#else
th->pendingException = exc;
#endif
return exc;
}
// Creates a Java object and then throws it.
extern "C" JavaObject* j3StackOverflowError() {
JavaObject *exc = 0;
JavaThread *th = JavaThread::get();
BEGIN_NATIVE_EXCEPTION(1)
exc = th->getJVM()->CreateStackOverflowError();
END_NATIVE_EXCEPTION
#ifdef DWARF_EXCEPTIONS
th->throwException(exc);
#else
th->pendingException = exc;
#endif
return exc;
}
// Creates a Java object and then throws it.
extern "C" JavaObject* j3ArithmeticException() {
JavaObject *exc = 0;
JavaThread *th = JavaThread::get();
BEGIN_NATIVE_EXCEPTION(1)
exc = th->getJVM()->CreateArithmeticException();
END_NATIVE_EXCEPTION
#ifdef DWARF_EXCEPTIONS
th->throwException(exc);
#else
th->pendingException = exc;
#endif
return exc;
}
// Creates a Java object and then throws it.
extern "C" JavaObject* j3ClassCastException(JavaObject* obj,
UserCommonClass* cl) {
JavaObject *exc = 0;
llvm_gcroot(obj, 0);
llvm_gcroot(exc, 0);
JavaThread *th = JavaThread::get();
BEGIN_NATIVE_EXCEPTION(1)
exc = th->getJVM()->CreateClassCastException(obj, cl);
END_NATIVE_EXCEPTION
#ifdef DWARF_EXCEPTIONS
th->throwException(exc);
#else
th->pendingException = exc;
#endif
return exc;
}
// Creates a Java object and then throws it.
extern "C" JavaObject* j3IndexOutOfBoundsException(JavaObject* obj,
sint32 index) {
JavaObject *exc = 0;
llvm_gcroot(obj, 0);
llvm_gcroot(exc, 0);
JavaThread *th = JavaThread::get();
BEGIN_NATIVE_EXCEPTION(1)
exc = th->getJVM()->CreateIndexOutOfBoundsException(index);
END_NATIVE_EXCEPTION
#ifdef DWARF_EXCEPTIONS
th->throwException(exc);
#else
th->pendingException = exc;
#endif
return exc;
}
// Creates a Java object and then throws it.
extern "C" JavaObject* j3ArrayStoreException(JavaVirtualTable* VT) {
JavaObject *exc = 0;
JavaThread *th = JavaThread::get();
BEGIN_NATIVE_EXCEPTION(1)
exc = th->getJVM()->CreateArrayStoreException(VT);
END_NATIVE_EXCEPTION
#ifdef DWARF_EXCEPTIONS
th->throwException(exc);
#else
th->pendingException = exc;
#endif
return exc;
}
// Create an exception then throws it.
extern "C" void j3ThrowExceptionFromJIT() {
JavaObject *exc = 0;
JavaThread *th = JavaThread::get();
BEGIN_NATIVE_EXCEPTION(1)
JavaMethod* meth = th->getCallingMethodLevel(0);
exc = th->getJVM()->CreateUnsatisfiedLinkError(meth);
END_NATIVE_EXCEPTION
#ifdef DWARF_EXCEPTIONS
th->throwException(exc);
#else
th->pendingException = exc;
#endif
}
extern "C" void* j3StringLookup(UserClass* cl, uint32 index) {
JavaString** str = 0;
BEGIN_NATIVE_EXCEPTION(1)
UserConstantPool* ctpInfo = cl->getConstantPool();
const UTF8* utf8 = ctpInfo->UTF8At(ctpInfo->ctpDef[index]);
str = cl->classLoader->UTF8ToStr(utf8);
#if defined(ISOLATE_SHARING) || !defined(ISOLATE)
ctpInfo->ctpRes[index] = str;
#endif
END_NATIVE_EXCEPTION
return (void*)str;
}
extern "C" void* j3ResolveVirtualStub(JavaObject* obj) {
llvm_gcroot(obj, 0);
JavaThread *th = JavaThread::get();
UserCommonClass* cl = obj->getClass();
void* result = NULL;
BEGIN_NATIVE_EXCEPTION(1)
// Lookup the caller of this class.
mvm::StackWalker Walker(th);
while (Walker.get()->MethodType != 1) ++Walker;
mvm::MethodInfo* MI = Walker.get();
JavaMethod* meth = (JavaMethod*)MI->getMetaInfo();
void* ip = *Walker;
// Lookup the method info in the constant pool of the caller.
uint16 ctpIndex = meth->lookupCtpIndex(reinterpret_cast<uintptr_t>(ip));
assert(ctpIndex && "No constant pool index");
JavaConstantPool* ctpInfo = meth->classDef->getConstantPool();
CommonClass* ctpCl = 0;
const UTF8* utf8 = 0;
Signdef* sign = 0;
ctpInfo->resolveMethod(ctpIndex, ctpCl, utf8, sign);
assert(cl->isAssignableFrom(ctpCl) && "Wrong call object");
UserClass* lookup = cl->isArray() ? cl->super : cl->asClass();
JavaMethod* Virt = lookup->lookupMethod(utf8, sign->keyName, false, true, 0);
// Compile the found method.
result = Virt->compiledPtr();
// Update the virtual table.
assert(lookup->isResolved() && "Class not resolved");
#if !defined(ISOLATE_SHARING) && !defined(SERVICE)
assert(lookup->isInitializing() && "Class not ready");
#endif
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 (ctpCl->isInterface()) {
InterfaceMethodTable* IMT = cl->virtualVT->IMT;
uint32_t index = InterfaceMethodTable::getIndex(Virt->name, Virt->type);
if ((IMT->contents[index] & 1) == 0) {
IMT->contents[index] = (uintptr_t)result;
} else {
JavaMethod* Imeth =
ctpCl->asClass()->lookupInterfaceMethodDontThrow(utf8, sign->keyName);
assert(Imeth && "Method not in hierarchy?");
uintptr_t* table = (uintptr_t*)(IMT->contents[index] & ~1);
uint32 i = 0;
while (table[i] != (uintptr_t)Imeth) { i += 2; }
table[i + 1] = (uintptr_t)result;
}
}
END_NATIVE_EXCEPTION
return result;
}
extern "C" void* j3ResolveStaticStub() {
JavaThread *th = JavaThread::get();
void* result = NULL;
BEGIN_NATIVE_EXCEPTION(1)
// Lookup the caller of this class.
mvm::StackWalker Walker(th);
while (Walker.get()->MethodType != 1) ++Walker;
mvm::MethodInfo* MI = Walker.get();
assert(MI->MethodType == 1 && "Wrong call to stub");
JavaMethod* caller = (JavaMethod*)MI->getMetaInfo();
void* ip = *Walker;
// Lookup the method info in the constant pool of the caller.
uint16 ctpIndex = caller->lookupCtpIndex(reinterpret_cast<uintptr_t>(ip));
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;
END_NATIVE_EXCEPTION
return result;
}
extern "C" void* j3ResolveSpecialStub() {
JavaThread *th = JavaThread::get();
void* result = NULL;
BEGIN_NATIVE_EXCEPTION(1)
// Lookup the caller of this class.
mvm::StackWalker Walker(th);
while (Walker.get()->MethodType != 1) ++Walker;
mvm::MethodInfo* MI = Walker.get();
assert(MI->MethodType == 1 && "Wrong call to stub");
JavaMethod* caller = (JavaMethod*)MI->getMetaInfo();
void* ip = *Walker;
// Lookup the method info in the constant pool of the caller.
uint16 ctpIndex = caller->lookupCtpIndex(reinterpret_cast<uintptr_t>(ip));
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->lookupSpecialMethodDontThrow(utf8, sign->keyName, caller->classDef);
if (!callee) {
th->getJVM()->abstractMethodError(lookup, utf8);
}
// Compile the found method.
result = callee->compiledPtr();
// Update the entry in the constant pool.
ctpInfo->ctpRes[ctpIndex] = result;
END_NATIVE_EXCEPTION
return result;
}
extern "C" void j3PrintMethodStart(JavaMethod* meth) {
fprintf(stderr, "[%p] executing %s.%s\n", (void*)mvm::Thread::get(),
UTF8Buffer(meth->classDef->name).cString(),
UTF8Buffer(meth->name).cString());
}
extern "C" void j3PrintMethodEnd(JavaMethod* meth) {
fprintf(stderr, "[%p] return from %s.%s\n", (void*)mvm::Thread::get(),
UTF8Buffer(meth->classDef->name).cString(),
UTF8Buffer(meth->name).cString());
}
extern "C" void j3PrintExecution(uint32 opcode, uint32 index,
JavaMethod* meth) {
fprintf(stderr, "[%p] executing %s.%s %s at %d\n", (void*)mvm::Thread::get(),
UTF8Buffer(meth->classDef->name).cString(),
UTF8Buffer(meth->name).cString(),
OpcodeNames[opcode], index);
}
#ifdef SERVICE
extern "C" void j3ServiceCallStart(Jnjvm* OldService,
Jnjvm* NewService) {
fprintf(stderr, "I have switched from %d to %d\n", OldService->IsolateID,
NewService->IsolateID);
fprintf(stderr, "Now the thread id is %d\n", mvm::Thread::get()->IsolateID);
}
extern "C" void j3ServiceCallStop(Jnjvm* OldService,
Jnjvm* NewService) {
fprintf(stderr, "End service call\n");
}
#endif
#ifdef ISOLATE_SHARING
extern "C" void* j3StaticCtpLookup(UserClass* cl, uint32 index) {
UserConstantPool* ctpInfo = cl->getConstantPool();
JavaConstantPool* shared = ctpInfo->getSharedPool();
uint32 clIndex = shared->getClassIndexFromMethod(index);
UserClass* refCl = (UserClass*)ctpInfo->loadClass(clIndex);
refCl->initialiseClass(JavaThread::get()->getJVM());
CommonClass* baseCl = 0;
const UTF8* utf8 = 0;
Signdef* sign = 0;
shared->resolveMethod(index, baseCl, utf8, sign);
UserClass* methodCl = 0;
refCl->lookupMethod(utf8, sign->keyName, true, true, &methodCl);
ctpInfo->ctpRes[index] = methodCl->getConstantPool();
shared->ctpRes[clIndex] = refCl->classDef;
return (void*)methodCl->getConstantPool();
}
extern "C" UserConstantPool* j3SpecialCtpLookup(UserConstantPool* ctpInfo,
uint32 index,
UserConstantPool** res) {
JavaConstantPool* shared = ctpInfo->getSharedPool();
uint32 clIndex = shared->getClassIndexFromMethod(index);
UserClass* refCl = (UserClass*)ctpInfo->loadClass(clIndex);
CommonClass* baseCl = 0;
const UTF8* utf8 = 0;
Signdef* sign = 0;
shared->resolveMethod(index, baseCl, utf8, sign);
UserClass* methodCl = 0;
refCl->lookupMethod(utf8, sign->keyName, false, true, &methodCl);
shared->ctpRes[clIndex] = refCl->classDef;
*res = methodCl->getConstantPool();
return methodCl->getConstantPool();
}
#endif