📄 gcj-class.cc
字号:
static voidfillInFieldInfo(neutralFieldInfo *info, _Jv_Field *fld){ info->name = fld->name->data; if (fld->isResolved()) { info->type = fld->type; } else { info->type = ((_Jv_Utf8Const*)fld->type)->data; } info->flags = fld->flags; info->bsize = fld->bsize; info->u.boffset = fld->u.boffset; info->u.addr = fld->u.addr;}/* * */static struct Hjava_lang_Class* constructSurrogate(java::lang::Class *clazz, struct _errorInfo *einfo){ neutralClassInfo cinfo; struct Hjava_lang_Class *kclass = GCJ2KAFFE(clazz); if (kclass != 0) { return (kclass); }DBG(GCJ, dprintf("%s: creating surrogate for class `%s'\n", __FUNCTION__, clazz->name->data); ) fillInClassInfo(&cinfo, clazz); kclass = kenvMakeClass(&cinfo, einfo);DBG(GCJ, dprintf("%s: surrogate for class `%s' is @%p\n", __FUNCTION__, clazz->name->data, kclass); ) GCJ2KAFFE(clazz) = kclass; return (kclass);}static boolmakeFields(java::lang::Class *clazz, struct Hjava_lang_Class *kclass, struct _errorInfo *einfo){ for (int i = 0; i < clazz->field_count; i++) { neutralFieldInfo finfo; fillInFieldInfo(&finfo, clazz->fields + i); finfo.idx = clazz->field_count - i - 1; if (kenvMakeField(&finfo, kclass, einfo) == false) { return (false); } } return (true);}static boolmakeMethods(java::lang::Class *clazz, struct Hjava_lang_Class *kclass, struct _errorInfo *einfo){ int vidx = 0; // virtual index int minusone = -1; for (int i = 0; i < clazz->method_count; i++) { neutralMethodInfo minfo; _Jv_Method *meth = clazz->methods + i; fillInMethodInfo(&minfo, meth); /* A final classes's methods are automatically final and * so are private methods. */ using namespace java::lang::reflect; if ((clazz->accflags & Modifier::FINAL) || (meth->accflags & Modifier::STATIC) || (meth->accflags & Modifier::FINAL) || (meth->accflags & Modifier::PRIVATE) || !strcmp(meth->name->data, "<init>")) { minfo.idx = &minusone; } else { minfo.idx = &vidx; } /* kenvMakeMethod will increase vidx as appropriate */ if (kenvMakeMethod(&minfo, kclass, einfo) == false) { return (false); } } return (true);}extern "C" struct Hjava_lang_Class*gcjFindClassByAddress(void *clazz, struct _errorInfo *einfo){ java::lang::Class* ptr; for (ptr = preCList; ptr != 0; ptr = ptr->next) { if (ptr == clazz) {DBG(GCJ, dprintf("%s: found class by j.l.C `%s'\n", __FUNCTION__, ptr->name->data); ) return (constructSurrogate(ptr, einfo)); } } /* XXX fill in einfo here!? */ return (0);}extern "C" boolcomparePath2ClassName(const char *cname, const char *pname) { register unsigned int a, b; while ((a = *cname++), (b = *pname++), a && b) { if (a == b || a == '/' && b == '.') { continue; } return (false); } return (!(a || b));}/* * This method finds a gcj class by its utf8 name. * We find the gcj, remove it from the list of gcj classes, * and create the surrogate kaffe class which we return. */extern "C" struct Hjava_lang_Class*gcjFindClassByUtf8Name(const char* utf8name, struct _errorInfo *einfo){ java::lang::Class* ptr; for (ptr = preCList; ptr != 0; ptr = ptr->next) { if (comparePath2ClassName(utf8name, ptr->name->data)) {DBG(GCJ, dprintf("%s: found class by name `%s'\n", __FUNCTION__, utf8name); ) return (constructSurrogate(ptr, einfo)); } } kenvPostClassNotFound(utf8name, einfo); return (0);}/* * Process a prebuilt class. * We must perform the same steps that the gcj-compiled code expects the * libjava/libgcj run-time to do. * * This is the construction of the kaffe surrogate fields and methods * and the resolution of constant pool entries. The latter is done * in gcjProcessClassConstants which is invoked at a later processing * stage for bootstrapping reasons. */boolgcjProcessClass(struct Hjava_lang_Class* kclazz, void *gcjClass, struct _errorInfo *einfo){ java::lang::Class *clazz = (java::lang::Class*)gcjClass; if (makeMethods(clazz, kclazz, einfo) == false) { return (false); } if (makeFields(clazz, kclazz, einfo) == false) { return (false); } return (true);}boolgcjProcessClassConstants(struct Hjava_lang_Class* kclazz, void *gcjClass, struct _errorInfo *einfo){ java::lang::Class *clazz = (java::lang::Class*)gcjClass;DBG(GCJ, dprintf("GCJ: ProcessClassConstants `%s'\n", clazz->name->data); ) /* from libjava/java/lang/natClassLoader.cc: _Jv_PrepareCompiledClass */ _Jv_Constants *pool = &clazz->constants; /* gcj starts its constant pool at index 1 */ for (int index = 1; index < pool->size; ++index) { switch (pool->tags[index]) { case JV_CONSTANT_Class: { _Jv_Utf8Const *name = pool->data[index].utf8; struct Hjava_lang_Class *kclass; kclass = kenvFindClass(name->data, einfo); if (kclass == 0) { return (false); } jclass gcjcls; gcjcls = (jclass)kenvMalloc(sizeof(java::lang::Class), einfo); if (gcjcls == 0) { return (false); } /* prep up our fake gcjclass --- it better not be used * for anything but to extract the kaffe surrogate */ gcjcls->name = name; GCJ2KAFFE(gcjcls) = kclass; /* XXX set gcjPeer in kclass maybe? */ /* XXX set gcjcls->vtable here? */ pool->data[index].clazz = gcjcls; pool->tags[index] |= JV_CONSTANT_ResolvedFlag; break; } case JV_CONSTANT_String: { void *str; _Jv_Utf8Const *u = pool->data[index].utf8; str = kenvMakeJavaString(u->data, u->length, u->hash); pool->data[index].o = (jstring)str; pool->tags[index] |= JV_CONSTANT_ResolvedFlag; break; } default: fprintf(stderr, "GCJ: Cannot handle constant pool item %d yet\n", (int)pool->tags[index]); } } return (true);}/* * Given a pointer as passed in libgcj's exception matcher, return * the kaffe class against which we should match. */struct Hjava_lang_Class *gcjFindMatchClass(void *minfo, struct _errorInfo *einfo){ /* libgcj's exception.cc says: // The match_info is either a (java::lang::Class*) or // match_info is one more than a (Utf8Const*). And then they code in ugly GNU style: if (sizeof(void*) != sizeof(size_t)) abort(); size_t mi = (size_t) match_info; if ((mi & 1) != 0) match_info = _Jv_FindClass ((Utf8Const*) (mi - 1), NULL); if (! _Jv_IsInstanceOf ((jobject) info->value, (jclass) match_info)) return NULL; */ /* is it the class's utf8 name */ if ((((int)minfo) & 1) != 0) { _Jv_Utf8Const *utf8 = (_Jv_Utf8Const *)((int)minfo - 1); return (gcjFindClassByUtf8Name(utf8->data, einfo)); } /* else it's a pointer to the class itself */ return (kenvFindClassByAddress2(minfo, einfo));}/* * Initialise kaffe surrogate type for primitive gcj classes. * See libgcj/libjava/prims.cc for what libgcj does. * We simply set aside some sizeof(java::lang::Class) space * and initialize the GCJ2KAFFE and the name field. * We also put them in the list of preloaded classes in order for * lookup functions to work. */class _Jv_PrimClass { int _dummy[sizeof(java::lang::Class)/sizeof(int)];} _Jv_intClass, _Jv_longClass, _Jv_booleanClass, _Jv_charClass, _Jv_floatClass, _Jv_doubleClass, _Jv_byteClass, _Jv_shortClass, _Jv_voidClass;#define TYPENAME(type) type##ClassName = { 0, sizeof #type, #type }static struct { /* must match _Jv_Utf8Const */ _Jv_ushort hash; _Jv_ushort len; char data[10];} TYPENAME(int), TYPENAME(long), TYPENAME(boolean), TYPENAME(char), TYPENAME(float), TYPENAME(double), TYPENAME(byte), TYPENAME(short), TYPENAME(void);#undef TYPENAMEvoid gcjInitPrimitiveClasses(void){#define KCLASS(type) { \ java::lang::Class* c = (java::lang::Class*)&_Jv_##type##Class; \ GCJ2KAFFE(c) = type##Class; \ c->name = (_Jv_Utf8Const*)&type##ClassName; \ _Jv_RegisterClass(c); \} KCLASS(int) KCLASS(long) KCLASS(boolean) KCLASS(char) KCLASS(float) KCLASS(double) KCLASS(byte) KCLASS(short) KCLASS(void)#undef KCLASS /* check that these flag values are still the same */ assert (FIELD_UNRESOLVED_FLAG == _Jv_FIELD_UNRESOLVED_FLAG); assert (FIELD_CONSTANT_VALUE == _Jv_FIELD_CONSTANT_VALUE);}/* * Find a primitive classes name. */static char *findPrimitiveClass(void *symbol){#define I(type) \ if (symbol == &_Jv_##type##Class) { \ return (";" #type); \ } I(int) else I(long) else I(boolean) else I(char) else I(float) else I(double) else I(byte) else I(short) else I(void) else { return (0); }#undef I}#endif /* HAVE_GCJ_SUPPORT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -