📄 gcj-glue.c
字号:
/* * gcj-glue.c * * Copyright (c) 1996, 1997, 1998, 1999 * Transvirtual Technologies, Inc. All rights reserved. * * See the file "license.terms" for information on usage and redistribution * of this file. * * Written by Godmar Back <gback@cs.utah.edu> */#include "config.h"#include "debug.h"#include "config-mem.h"#include "classMethod.h"#include "errors.h"#include "access.h"#include "lookup.h"#include "baseClasses.h"#include "stringSupport.h"#include "gcj.h"#include "jit3/machine.h"#include "object.h"#if defined(HAVE_GCJ_SUPPORT) && defined(JIT3) && defined(TRANSLATOR)/* * GCJ code wants to create an object. */Hjava_lang_Object *kenvCreateObject(struct Hjava_lang_Class *clazz, int size){ /* !? --- I think that may be i386 specific -- XXX optimize me */ assert(((CLASS_FSIZE(clazz)+3)&~3) == size); return (newObject(clazz));}/* Given a const char * type name as a class name, create a * pathname. I.e., makes a utf8const "[Ljava/lang/String;" from * [Ljava.lang.String */static Utf8Const *makePathUtf8FromClassChar(const char *name){ int n; char buf[256], *b = buf; Utf8Const *utf8; n = strlen(name); if (n > sizeof(buf) - 1) { b = KMALLOC(n + 1); } classname2pathname(name, b); utf8 = utf8ConstNew(b, n); if (b != buf) { KFREE(b); } return (utf8);}/* * cname is a qualified class name, like * [[I or Ljava.lang.String; or LHelloWorld; or [[[Ljava.lang.Object; * or a qualified path name where there's a slash instead of the dot */Hjava_lang_Class *kenvFindClass(char *cname, errorInfo *einfo){ char buf[1024]; /* XXX */ Utf8Const *name; Hjava_lang_Class *class; /* XXX handle classloaders -- but how? */ if (cname[0] == '[') { /* loadArray does want the "L...;" */ name = makePathUtf8FromClassChar(cname); class = loadArray(name, 0, einfo); } else { /* loadClass doesn't want the "L...;" */ if (*cname == 'L') { strcpy(buf, cname+1); assert(buf[strlen(buf) - 1] == ';'); buf[strlen(buf) - 1] = '\0'; } else { /* else could be a primitive class such as "long" */ strcpy(buf, cname); } name = makePathUtf8FromClassChar(buf); class = loadClass(name, 0, einfo); } utf8ConstRelease(name);DBG(GCJ, dprintf(__FUNCTION__": `%s' --> @%p\n", cname, class); ) return (class);}void kenvPostClassNotFound(const char *utf8name, errorInfo *einfo){ postNoClassDefFoundError(einfo, utf8name);}voidkenvProcessClass(struct Hjava_lang_Class *class){ errorInfo info;DBG(GCJ, dprintf("processing kaffe class for %s@%p from st=%d to %d...\n", CLASS_CNAME(class), class, class->state, CSTATE_COMPLETE); ) if (processClass(class, CSTATE_COMPLETE, &info) == false) { throwError(&info); }}/* * Create a kaffe class from the gcj info */Hjava_lang_Class*kenvMakeClass(neutralClassInfo *info, errorInfo *einfo){ int n; classEntry *centry; Hjava_lang_Class *class = newClass();DBG(GCJ, dprintf("making kaffe class for %s@%p vtab=%p gcj=%p...\n", info->name, class, info->vtable, info->gcjClass);) if (class == 0) { goto oom; } class->name = makePathUtf8FromClassChar(info->name); /* We must take care to not free some of these fields when unloading * fully or partially loaded gcj classes (if that'll ever be supported) * because they may still point in gcj-produced static data. */ /* We assume the same vtable layout here: first a pointer to the * class, then a zero, then the vtable */ class->dtable = info->vtable; /* write kaffe class in vtable.class field in gcj space if class has * a dtable --- interfaces don't have one. */ if (class->dtable) { class->dtable->class = class; } class->gcjPeer = info->gcjClass; class->accflags = info->accflags; class->msize = info->vTableCount; class->superclass = info->superclass; /* either null or pointer to other gcj class */ if (info->methodCount > 0) { Kaffe_set_class_methods(class->methods, gc_malloc(sizeof(Method) * info->methodCount, GC_ALLOC_METHOD)); if (Kaffe_get_class_methods(class) == NULL) { goto oom; } } if (info->fieldCount > 0) { class->fields = gc_malloc(sizeof(Field) * info->fieldCount, GC_ALLOC_FIELD); if (class->fields == 0) { goto oom; } } /* * I copy those such that resolveInterfaces can proceed the same * way it does for for kaffe classes. */ class->interface_len = info->interfaceCount; n = info->interfaceCount * sizeof(struct Hjava_lang_Class**); if (n > 0) { class->interfaces = (Hjava_lang_Class**)KMALLOC(n); memcpy(class->interfaces, info->interfaces, n); } class->state = CSTATE_PRELOADED; if (class->superclass == 0 && CLASS_IS_INTERFACE(class)) { /* gcj sets superclass to zero for interfaces, but we * set it to ObjectClass. */ class->superclass = ObjectClass; } SET_CLASS_GCJ(class); /* XXX: find a better place to do this: * If we're invoked via loadClass, the caller will anchor us after * we return. This gc_add_ref call is only necessary if we're * resolving a class referenced from gcj code via its address, * bypassing the usual name-based lookup path. XXX */ if (!gc_add_ref(class)) { goto oom; } /* make sure this class is registered with the class pool * Same caveat as for call to gc_add_ref above applies. */ centry = lookupClassEntry(class->name, 0, einfo); if (centry == 0) { return (0); } class->centry = centry; centry->class = class; return (class);oom: postOutOfMemory(einfo); return (0);}/* * Build a Kaffe Method* struct from a GCJ method description * * NB: It ain't pretty, and it duplicates a lot of code from * classMethod.c:addMethod() */boolkenvMakeMethod(neutralMethodInfo* info, Hjava_lang_Class *c, errorInfo *einfo){ Utf8Const *signature; static char buf[1024]; Method *mt = &(Kaffe_get_class_methods(c)[CLASS_NMETHODS(c)]); mt->name = utf8ConstFromString(info->name); classname2pathname(info->signature, buf); signature = utf8ConstFromString(buf); METHOD_PSIG(mt) = parseSignature(signature, einfo); utf8ConstRelease(signature); if (METHOD_PSIG(mt) == NULL) {DBG(GCJ, dprintf("could not parse signature %s.%s ...\n", info->name, info->signature); ) return (false); } mt->class = c; mt->accflags = info->accflags; mt->c.bcode.code = 0; mt->stacksz = 0; mt->localsz = 0; mt->exception_table = 0; if (*info->idx == -1) { mt->idx = -1; } else { int supermsize; /* avoid accessing superclass when mt->class == ObjectClass */ if (c == ObjectClass) { supermsize = 0; } else { supermsize = c->superclass->msize; } assert(c == ObjectClass || c->superclass != 0); /* assign a new method index unless this method was inherited */ if (c->superclass != 0 && getInheritedMethodIndex(c->superclass, mt) == false) { mt->idx = supermsize + (*info->idx)++; } } mt->ncode = info->ncode; /* Interfaces and abstract class don't have a vtable in gcj, but * their methods have non-zero indices. METHOD_NATIVECODE accesses * a location within the dtable if idx != 0. * * XXX: Fix this whole "METHOD_NATIVECODE" mess and come up with * a more viable abstraction instead. */ if (!CLASS_IS_INTERFACE(mt->class) && !CLASS_IS_ABSTRACT(mt->class)) { METHOD_NATIVECODE(mt) = mt->ncode; } /* Mark constructors as such */ if (utf8ConstEqual (mt->name, constructor_name)) { mt->kFlags |= KFLAG_CONSTRUCTOR; } /* Assumption 1: gcj always sets the 0x4000 ACC_TRANSLATED flag, * even in abstract methods. */ assert(mt->accflags & KFLAG_TRANSLATED); /* * We clear ACC_TRANSLATED flags for methods with no code, such as * abstract methods. */ if (info->ncode == 0 || (info->accflags & ACC_NATIVE)) { mt->kFlags &= ~KFLAG_TRANSLATED; } CLASS_NMETHODS(c)++;DBG(GCJ, dprintf("making kaffe method %s.%s @%p idx=%d m->ncode=%p...\n", mt->name->data, METHOD_SIGD(mt), mt, mt->idx, mt->ncode); ) return (true);}/* * Create a kaffe Field structure from GCJ field description * * compare addField in classMethod.c */boolkenvMakeField(neutralFieldInfo* info, Hjava_lang_Class *c, errorInfo *einfo){ Field *fld; Hjava_lang_Class *ftype; /* static fields start from the bottom, instance fields from the top */ if (info->flags & ACC_STATIC) { fld = &CLASS_FIELDS(c)[CLASS_NSFIELDS(c)]; } else { fld = &CLASS_FIELDS(c)[info->idx + CLASS_NSFIELDS(c)]; } fld->accflags = info->flags; fld->name = utf8ConstFromString(info->name); /* For now, that's true. However, see * http://sourceware.cygnus.com/ml/java-discuss/1999-q4/msg00379.html * http://sourceware.cygnus.com/ml/java-discuss/1999-q4/msg00380.html * for how things may change. */ assert(!(fld->accflags & FIELD_CONSTANT_VALUE)); /* The resolved flags have the same meaning as in Kaffe---note that * gcj only resolves types if it can do so at link/compile time. * Array types, for instance, are stored as unresolved field refs. */ if ((fld->accflags & FIELD_UNRESOLVED_FLAG) == 0) { /* can't use kenvFindClassByAddress2 here cause we must avoid * attempts to process this class---especially if the * field points to a type that is the type of its enclosing * object. */ ftype = gcjFindClassByAddress(info->type, einfo); if (!ftype) { char *name; name = gcjFindUnresolvedClassByAddress(info->type); if (name) { ftype = kenvFindClass(name, einfo);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -