📄 gcj-glue.c
字号:
} else { kenvPostClassNotFound(name, einfo); } } if (!ftype) { return (false); } FIELD_TYPE(fld) = ftype; if (CLASS_IS_PRIMITIVE(ftype)) { assert(info->bsize == TYPE_PRIM_SIZE(ftype)); } else { assert(info->bsize == PTR_TYPE_SIZE); } } else { const char *ksig = info->type; FIELD_TYPE(fld) = (Hjava_lang_Class*) makePathUtf8FromClassChar(ksig); if (ksig[0] == 'L' || ksig[0] == '[') { assert(info->bsize == PTR_TYPE_SIZE); } /* else unresolved primitive type */ } FIELD_SIZE(fld) = info->bsize; if (fld->accflags & ACC_STATIC) { FIELD_ADDRESS(fld) = info->u.addr; }DBG(GCJ, dprintf("making kaffe field #%d %s.%s @%p type=%p flags=0x%x addr=%p\n", info->idx, CLASS_CNAME(c), fld->name->data, fld, fld->type, fld->accflags, FIELD_ADDRESS(fld)); ) CLASS_NFIELDS(c)++; if (fld->accflags & ACC_STATIC) { CLASS_NSFIELDS(c)++; } /* Instance fields are inserted in opposite order, so let's switch * them here. This is what finishFields does. */ if (info->idx == 0) { finishFields(c); } return (true);}const char *kenvGetClassName(struct Hjava_lang_Class *clazz){ return (CLASS_CNAME(clazz));}void* kenvMakeJavaString(const char *utf8data, int utf8length, int utf8hash){ Utf8Const *u; Hjava_lang_String *s; u = utf8ConstNew(utf8data, utf8length); /* make sure kaffe and gcj computed the same hash --- unfortunately * gcj only stores the lower 16 bits. */ assert((u->hash & 0xffff) == utf8hash); s = utf8Const2Java(u); utf8ConstRelease(u); /* Nail these down for now because we do not walk a gcj class's * constant pool from which these strings may be referenced. */ if (!gc_add_ref(s)) { errorInfo info; postOutOfMemory(&info); throwError(&info); } return (s);}/* * Given a pointer to a java::lang::Class, return kaffe's surrogate class */Hjava_lang_Class*kenvFindClassByAddress2(void *clazz, errorInfo *einfo){ Hjava_lang_Class *kclass; /* Check if this class was preloaded. If so, a surrogate will * be constructed and returned. */ kclass = gcjFindClassByAddress(clazz, einfo); /* Either it wasn't preloaded or some other problem occurred * during processing. XXX think about what it would to do if * another problem occurred. * * If it's not a precompiled class, it could be an unresolved ref. */ if (kclass == 0 /* XXX: && error was class not found !? */) { /* It could be a kaffe class, which was an unresolved symbol * in the shared module, but for which there should be an entry * in the symbol table of the fixup module which we've loaded * by now. */ char *name; name = gcjFindUnresolvedClassByAddress(clazz); if (name) { kclass = kenvFindClass(name, einfo); } else { kenvPostClassNotFound(name, einfo); } } if (kclass && kclass->state < CSTATE_LINKED) { if (processClass(kclass, CSTATE_LINKED, einfo) == false) {DBG(GCJ, dprintf("gcjGetClass: failed to process class %s@%p\n", kclass); ) return (0); } }DBG(GCJ, dprintf("%s: %p -> %p %s\n", __FUNCTION__, clazz, kclass, kclass ? CLASS_CNAME(kclass) : "<nil>"); ) return (kclass);}Hjava_lang_Class*kenvFindClassByAddress(void *gcjclazz){ Hjava_lang_Class* kclass; errorInfo info; kclass = kenvFindClassByAddress2(gcjclazz, &info); if (kclass == 0) { dprintf("GCJ: Missing needed class @%p\n", gcjclazz); throwError(&info); } return (kclass);}/* * Find a method that implements an interface by its name and signature * Unfortunately, gcj doesn't use the constant-time method to lookup * interfaces yet. I hope they'll follow suit and implement the lookup * based on interface class and index. */#define HSIZE 1024struct mCacheEntry { Hjava_lang_Class *kclass; const char *mname; const char *msig; Method *meth;} mCache[HSIZE];#define MHASH(V) ((((uintp)(V) >> 2) ^ ((uintp)(V) >> 9))%HSIZE)/* Try to lookup a class/methodname/methodsignature combo in the cache, * return location to where Method can be found. If we have a cache miss, * clear that location. */static inlineMethod **tryCache(Hjava_lang_Class *kclass, const char *mname, const char *msig){ /* With this hash function, I'm getting these hit ratios: mpegaudio : 181945 hits, 28 misses db : 19297313 hits, 19 misses jack : 14507926 hits, 40 misses jess : 706127 hits, 139 misses compress : 184 hits, 15 misses */ int h = MHASH(kclass) ^ MHASH(mname); struct mCacheEntry *e = mCache + h; if (e->kclass != kclass || e->mname != mname || e->msig != msig) { e->kclass = kclass; e->mname = mname; e->msig = msig; e->meth = 0; } return (&(e->meth));}/* #define COUNT_CACHE 1 */#if COUNT_CACHEstatic long long cachehits;static long long cachemisses;void printInterfaceCacheStats() { dprintf("GCJ interface cache: %qd hits, %qd misses\n", cachehits, cachemisses);}#endifvoid* kenvFindMethod(Hjava_lang_Class *kclass, const char *mname, const char *msig){ Method *meth; Method **mptr; errorInfo info; mptr = tryCache(kclass, mname, msig); meth = *mptr; if (meth) {#if COUNT_CACHE cachehits++;#endif goto found; }#if COUNT_CACHE cachemisses++;#endif for (; kclass != 0; kclass = kclass->superclass) { int n = CLASS_NMETHODS(kclass); for (meth = Kaffe_get_class_methods(kclass); --n >= 0; ++meth) { /* Ouch. GCJ keeps signatures in dotted form, we * keep them in slashed form. */ if (!strcmp(mname, meth->name->data) && comparePath2ClassName( PSIG_DATA(METHOD_PSIG(meth)), msig)) { *mptr = meth; goto found; } } } postExceptionMessage(&info, JAVA_LANG(NoSuchMethodError), "%s", mname); throwError(&info); return (0);found:DBG(GCJ, dprintf("%s: %s.%s is at %p\n", __FUNCTION__, mname, msig, METHOD_NATIVECODE(meth)); ) assert(METHOD_NATIVECODE(meth)); return (METHOD_NATIVECODE(meth));}/* * A GCJ trampoline. * Invoked only once per method so can be expensive. * Note that the msig is only a partial signature: it doesn't have the * return type in it. */void *kenvTranslateMethod(const char *classname, const char *mname, const char *msig){ Method *meth; errorInfo info; Hjava_lang_Class *kclass, *cc; int msiglen = strlen(msig); kclass = kenvFindClass((char*)classname, &info); if (kclass == 0) { throwError(&info); } /* * GCJ invokes (static) native methods w/o calling Jv_InitClass * first. (Jv_InitClass is the first thing a gcj static method * does.) Hence, make sure the class's static initialized has * been invoked to ensure the static native method is even here. * * XXX need a different approach for static linking here! */ kenvProcessClass(kclass); for (cc = kclass; cc; cc = cc->superclass) { int nm = CLASS_NMETHODS(cc); meth = Kaffe_get_class_methods(cc); while (nm-- > 0) { if (!strcmp(mname, meth->name->data) && !strncmp(msig, METHOD_SIGD(meth), msiglen)) { goto found; } meth++; } }DBG(GCJ, dprintf("%s: NoSuchMethod %s.%s.%s\n", __FUNCTION__, classname, mname, msig); ) postExceptionMessage(&info, JAVA_LANG(NoSuchMethodError), "%s.%s.%s", classname, mname, msig); throwError(&info); return (0);found: assert(meth); if (!METHOD_TRANSLATED(meth)) { if (translate(meth, &info) == false) { throwError(&info); } } return (METHOD_NATIVECODE(meth));}/* * Find a class by its GCJ address. * Exception: if we're asked to find a class with the address * "ObjectClass", return the address of ObjectClass??? * * XXX this has only to do with interface/java.lang.Object * XXX CLEAN ME UP and possibly eliminate this function. */Hjava_lang_Class* gcjGetClass(void *jclazz, errorInfo *einfo){ Hjava_lang_Class* kclass; /* Both java.lang.Object and interfaces have their superclass field * set to null. To distinguish interfaces, we set their field to * ObjectClass in kenvMakeClass */ if (jclazz == (void*)ObjectClass) { return (ObjectClass); } kclass = kenvFindClassByAddress2(jclazz, einfo); if (kclass == 0) {DBG(GCJ, dprintf("gcjGetClass: class not found at %p\n", jclazz); ) return (0); } return (kclass);}void* kenvMalloc(int size, struct _errorInfo *einfo){ void *p = KMALLOC(size); if (p == 0) { postOutOfMemory(einfo); } return (p);}void kenvFree(void * ptr){ KFREE(ptr);}#endif /* HAVE_GCJ_SUPPORT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -