// 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; }
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 or its class is not found. extern "C" void* j3StaticFieldLookup(UserClass* caller, uint32 index) { void* res = 0; 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; } 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* JnjvmClassLoader::internalLoad(const UTF8* name, bool doResolve, JavaString* strName) { llvm_gcroot(strName, 0); UserCommonClass* cl = lookupClass(name); if (!cl) { cl = internalLoadCreateClass(name, strName); } if (cl && doResolve && cl->isClass()) { cl->asClass()->resolveClass(); } return (UserClass*)cl; }
// Throws if the class can not be resolved. extern "C" JavaVirtualTable* j3GetArrayClass(UserClass* caller, uint32 index, JavaVirtualTable** VT) { JavaVirtualTable* res = 0; assert(VT && "Incorrect call to j3GetArrayClass"); UserConstantPool* ctpInfo = caller->getConstantPool(); UserCommonClass* cl = ctpInfo->loadClass(index); JnjvmClassLoader* JCL = cl->classLoader; if (cl->asClass()) cl->asClass()->resolveClass(); const UTF8* arrayName = JCL->constructArrayName(1, cl->getName()); res = JCL->constructArray(arrayName)->virtualVT; *VT = res; return res; }
JavaObjectField* JavaObjectField::createFromInternalField(JavaField* field, int i) { JavaObjectField* ret = 0; JavaString* name = 0; ArraySInt8* ann = 0; llvm_gcroot(ret, 0); llvm_gcroot(name, 0); llvm_gcroot(ann, 0); // TODO: check parameter types Jnjvm* vm = JavaThread::get()->getJVM(); UserClass* Field = vm->upcalls->newField; ret = (JavaObjectField*)Field->doNew(vm); name = vm->internalUTF8ToStr(field->name); //type->Class JnjvmClassLoader* loader = field->classDef->classLoader; UserCommonClass * fieldCl = field->getSignature()->assocClass(loader); assert(fieldCl); JavaObject* const* type = fieldCl->getClassDelegateePtr(vm); JavaObject* const* Cl = field->classDef->getClassDelegateePtr(vm); JavaString** sig = getSignature(field); ann = getAnnotations(field); /* java.reflect.Field( * Class declaringClass, * String name, * Class type, * int modifiers, * int slot, * String signature, * byte[] annotations) */ vm->upcalls->initField->invokeIntSpecial(vm, Field, ret, Cl, &name, type, field->access, i, sig, &ann); return ret; }
extern "C" void* j3InterfaceLookup(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; Signdef* sign = 0; ctpInfo->resolveMethod(index, cl, utf8, sign); assert(cl->isClass() && isInterface(cl->access) && "Wrong type of method"); res = cl->asClass()->lookupInterfaceMethod(utf8, sign->keyName); ctpInfo->ctpRes[index] = (void*)res; } return res; }
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; }
// Throws if the class is not found. extern "C" void* j3ClassLookup(UserClass* caller, uint32 index) { void* res = 0; UserConstantPool* ctpInfo = caller->getConstantPool(); UserCommonClass* cl = 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; // Create the array class, in case we come from a ANEWARRAY. if (cl->isClass() && !cl->virtualVT->baseClassVT) { const UTF8* arrayName = cl->classLoader->constructArrayName(1, cl->getName()); cl->virtualVT->baseClassVT = cl->classLoader->constructArray(arrayName)->virtualVT; } return res; }
void JavaObject::decapsulePrimitive(JavaObject* obj, Jnjvm *vm, jvalue* buf, const Typedef* signature) { llvm_gcroot(obj, 0); if (!signature->isPrimitive()) { if (obj && !(getClass(obj)->isOfTypeName(signature->getName()))) { vm->illegalArgumentException("wrong type argument"); } return; } else if (obj == NULL) { vm->illegalArgumentException(""); } else { UserCommonClass* cl = getClass(obj); UserClassPrimitive* value = cl->toPrimitive(vm); const PrimitiveTypedef* prim = (const PrimitiveTypedef*)signature; if (value == 0) { vm->illegalArgumentException(""); } if (prim->isShort()) { if (value == vm->upcalls->OfShort) { (*buf).s = vm->upcalls->shortValue->getInstanceInt16Field(obj); return; } else if (value == vm->upcalls->OfByte) { (*buf).s = (sint16)vm->upcalls->byteValue->getInstanceInt8Field(obj); return; } else { vm->illegalArgumentException(""); } } else if (prim->isByte()) { if (value == vm->upcalls->OfByte) { (*buf).b = vm->upcalls->byteValue->getInstanceInt8Field(obj); return; } else { vm->illegalArgumentException(""); } } else if (prim->isBool()) { if (value == vm->upcalls->OfBool) { (*buf).z = vm->upcalls->boolValue->getInstanceInt8Field(obj); return; } else { vm->illegalArgumentException(""); } } else if (prim->isInt()) { if (value == vm->upcalls->OfInt) { (*buf).i = vm->upcalls->intValue->getInstanceInt32Field(obj); } else if (value == vm->upcalls->OfByte) { (*buf).i = (sint32)vm->upcalls->byteValue->getInstanceInt8Field(obj); } else if (value == vm->upcalls->OfChar) { (*buf).i = (uint32)vm->upcalls->charValue->getInstanceInt16Field(obj); } else if (value == vm->upcalls->OfShort) { (*buf).i = (sint32)vm->upcalls->shortValue->getInstanceInt16Field(obj); } else { vm->illegalArgumentException(""); } return; } else if (prim->isChar()) { if (value == vm->upcalls->OfChar) { (*buf).c = (uint16)vm->upcalls->charValue->getInstanceInt16Field(obj); } else { vm->illegalArgumentException(""); } return; } else if (prim->isFloat()) { if (value == vm->upcalls->OfFloat) { (*buf).f = (float)vm->upcalls->floatValue->getInstanceFloatField(obj); } else if (value == vm->upcalls->OfByte) { (*buf).f = (float)(sint32)vm->upcalls->byteValue->getInstanceInt8Field(obj); } else if (value == vm->upcalls->OfChar) { (*buf).f = (float)(uint32)vm->upcalls->charValue->getInstanceInt16Field(obj); } else if (value == vm->upcalls->OfShort) { (*buf).f = (float)(sint32)vm->upcalls->shortValue->getInstanceInt16Field(obj); } else if (value == vm->upcalls->OfInt) { (*buf).f = (float)(sint32)vm->upcalls->intValue->getInstanceInt32Field(obj); } else if (value == vm->upcalls->OfLong) { (*buf).f = (float)vm->upcalls->longValue->getInstanceLongField(obj); } else { vm->illegalArgumentException(""); } return; } else if (prim->isDouble()) { if (value == vm->upcalls->OfDouble) { (*buf).d = (double)vm->upcalls->doubleValue->getInstanceDoubleField(obj); } else if (value == vm->upcalls->OfFloat) { (*buf).d = (double)vm->upcalls->floatValue->getInstanceFloatField(obj); } else if (value == vm->upcalls->OfByte) { (*buf).d = (double)(sint64)vm->upcalls->byteValue->getInstanceInt8Field(obj); } else if (value == vm->upcalls->OfChar) { (*buf).d = (double)(uint64)vm->upcalls->charValue->getInstanceInt16Field(obj); } else if (value == vm->upcalls->OfShort) { (*buf).d = (double)(sint16)vm->upcalls->shortValue->getInstanceInt16Field(obj); } else if (value == vm->upcalls->OfInt) { (*buf).d = (double)(sint32)vm->upcalls->intValue->getInstanceInt32Field(obj); } else if (value == vm->upcalls->OfLong) { (*buf).d = (double)(sint64)vm->upcalls->longValue->getInstanceLongField(obj); } else { vm->illegalArgumentException(""); } return; } else if (prim->isLong()) { if (value == vm->upcalls->OfByte) { (*buf).j = (sint64)vm->upcalls->byteValue->getInstanceInt8Field(obj); } else if (value == vm->upcalls->OfChar) { (*buf).j = (sint64)(uint64)vm->upcalls->charValue->getInstanceInt16Field(obj); } else if (value == vm->upcalls->OfShort) { (*buf).j = (sint64)vm->upcalls->shortValue->getInstanceInt16Field(obj); } else if (value == vm->upcalls->OfInt) { (*buf).j = (sint64)vm->upcalls->intValue->getInstanceInt32Field(obj); } else if (value == vm->upcalls->OfLong) { (*buf).j = (sint64)vm->upcalls->intValue->getInstanceLongField(obj); } else { vm->illegalArgumentException(""); } return; } } // can not be here return; }
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; }
JavaMethod* JavaObjectMethod::getInternalMethod(JavaObjectMethod* self) { llvm_gcroot(self, 0); UserCommonClass* cls = JavaObjectClass::getClass(self->clazz); return &(cls->asClass()->virtualMethods[self->slot]); }