classmethod.c
来自「kaffe Java 解释器语言,源码,Java的子集系统,开放源代码」· C语言 代码 · 共 2,775 行 · 第 1/5 页
C
2,775 行
/* Align start of this class's data */ if (oldoffset == 0) { offset = ((offset + maxalign - 1) / maxalign) * maxalign; }#endif /* Now work out where to put each field */ fld = CLASS_IFIELDS(class); n = CLASS_NIFIELDS(class); for (; --n >= 0; fld++) { fsize = FIELD_SIZE(fld); /* Align field */ align = ALIGNMENT_OF_SIZE(fsize); offset = ((offset + align - 1) / align) * align; FIELD_BOFFSET(fld) = offset; offset += fsize; } CLASS_FSIZE(class) = offset; /* recall old offset */ offset = oldoffset; /* Now that we know how big that object is going to be, create * a bitmap to help the gc scan the object. The first part is * inherited from the superclass. */ map = BITMAP_NEW(CLASS_FSIZE(class)/ALIGNMENTOF_VOIDP, GC_ALLOC_CLASSMISC); if (map == 0) { postOutOfMemory(einfo); return (false); } if (offset > 0) { nbits = offset/ALIGNMENTOF_VOIDP; BITMAP_COPY(map, class->gc_layout, nbits); } else { /* The walkObject routine marks the class object explicitly. * We assume that the header does not contain anything ELSE * that must be marked. */ offset = sizeof(Hjava_lang_Object); nbits = offset/ALIGNMENTOF_VOIDP; } class->gc_layout = map;#if 0 /* Find and align start of object */ if (oldoffset == 0) { offset = ((offset + maxalign - 1) / maxalign) * maxalign; }#endif nbits = offset/ALIGNMENTOF_VOIDP;DBG(GCPRECISE, dprintf("GCLayout for %s:\n", CLASS_CNAME(class)); ) /* Now work out the gc layout */ fld = CLASS_IFIELDS(class); n = CLASS_NIFIELDS(class); for (; --n >= 0; fld++) { fsize = FIELD_SIZE(fld); /* Align field */ align = ALIGNMENT_OF_SIZE(fsize); offset += (align - (offset % align)) % align; nbits = offset/ALIGNMENTOF_VOIDP; /* paranoia */ assert(FIELD_BOFFSET(fld) == offset); /* Set bit if this field is a reference type, except if * it's a kaffe.util.Ptr (PTRCLASS). */ if (!FIELD_RESOLVED(fld)) { Utf8Const *sig = fld->signature; if ((sig->data[0] == 'L' || sig->data[0] == '[') && strcmp(sig->data, PTRCLASSSIG)) { BITMAP_SET(map, nbits); } } else { if (FIELD_ISREF(fld)) { BITMAP_SET(map, nbits); } }DBG(GCPRECISE, dprintf(" offset=%3d nbits=%2d ", offset, nbits); BITMAP_DUMP(map, nbits+1) dprintf(" fsize=%3d (%s)\n", fsize, fld->name->data); ) offset += fsize; } return (true);}/* * Allocate the space for the static class data. */staticboolallocStaticFields(Hjava_lang_Class* class, errorInfo *einfo){ int fsize; int align; uint8* mem; int offset; int n; Field* fld; /* No static fields */ if (CLASS_NSFIELDS(class) == 0) { return (true); } /* Calculate size and position of static data */ offset = 0; n = CLASS_NSFIELDS(class); fld = CLASS_SFIELDS(class); for (; --n >= 0; fld++) { fsize = FIELD_SIZE(fld); /* Align field offset */ align = ALIGNMENT_OF_SIZE(fsize); offset = ((offset + align - 1) / align) * align; FIELD_SIZE(fld) = offset; offset += fsize; } /* Allocate memory required */ mem = gc_malloc(offset, GC_ALLOC_STATICDATA); if (mem == NULL) { postOutOfMemory(einfo); return (false); } CLASS_STATICDATA(class) = mem; /* Rewalk the fields, pointing them at the relevant memory and/or * setting any constant values. */ fld = CLASS_SFIELDS(class); n = CLASS_NSFIELDS(class); for (; --n >= 0; fld++) { offset = FIELD_SIZE(fld); FIELD_SIZE(fld) = FIELD_CONSTIDX(fld); /* Keep idx in size */#if defined(HAVE_GCJ_SUPPORT) /* Check whether gcj code refers to this field. If so, * we'll have storage for this field in a fixup module. * gcjGetFieldAddr retrieves the address for the storage * * NB: Don't confuse this with the case where class is a gcj * class. In that case, this function is not even invoked! */ FIELD_ADDRESS(fld) = gcjGetFieldAddr(CLASS_CNAME(class), fld->name->data); /* not a field for which gcj provides storage */ if (FIELD_ADDRESS(fld) == 0) { FIELD_ADDRESS(fld) = mem + offset; }#else FIELD_ADDRESS(fld) = mem + offset;#endif } return (true);}staticboolresolveStaticFields(Hjava_lang_Class* class, errorInfo *einfo){ uint8* mem; constants* pool; Utf8Const* utf8; Field* fld; int idx; int n; /* No locking here, assume class is already locked. */ pool = CLASS_CONSTANTS(class); fld = CLASS_SFIELDS(class); n = CLASS_NSFIELDS(class); for (; --n >= 0; fld++) { if ((fld->accflags & FIELD_CONSTANT_VALUE) != 0) { mem = FIELD_ADDRESS(fld); idx = FIELD_SIZE(fld); switch (CONST_TAG(idx, pool)) { case CONSTANT_Integer: if (FIELD_TYPE(fld) == booleanClass || FIELD_TYPE(fld) == byteClass) { *(jbyte*)mem = CLASS_CONST_INT(class, idx); FIELD_SIZE(fld) = TYPE_PRIM_SIZE(byteClass); } else if (FIELD_TYPE(fld) == charClass || FIELD_TYPE(fld) == shortClass) { *(jshort*)mem = CLASS_CONST_INT(class, idx); FIELD_SIZE(fld) = TYPE_PRIM_SIZE(shortClass); } else { *(jint*)mem = CLASS_CONST_INT(class, idx); FIELD_SIZE(fld) = TYPE_PRIM_SIZE(intClass); } break; case CONSTANT_Float: *(jint*)mem = CLASS_CONST_INT(class, idx); FIELD_SIZE(fld) = TYPE_PRIM_SIZE(floatClass); break; case CONSTANT_Long: case CONSTANT_Double: *(jlong*)mem = CLASS_CONST_LONG(class, idx); FIELD_SIZE(fld) = TYPE_PRIM_SIZE(longClass); break; case CONSTANT_String: { Hjava_lang_String *st; utf8 = WORD2UTF(pool->data[idx]); st = utf8Const2Java(utf8); utf8ConstRelease(utf8); if (!st) { postOutOfMemory(einfo); return false; } pool->data[idx] = (ConstSlot)st; pool->tags[idx] = CONSTANT_ResolvedString; } /* ... fall through ... */ case CONSTANT_ResolvedString: *(jref*)mem = (jref)CLASS_CONST_DATA(class, idx); FIELD_SIZE(fld) = PTR_TYPE_SIZE; break; } } } return true;}#if defined(TRANSLATOR)/* * When do we need a trampoline? * * NB: this method is invoked for *all* methods a class defines or * inherits. */static boolmethodNeedsTrampoline(Method *meth){ /* A gcj class's native virtual methods always need a trampoline * since the gcj trampoline doesn't work for them. By using a * trampoline, we can fix the vtable the first time it is invoked. * * NB: If we'll ever support CNI, revisit this. */ if (CLASS_GCJ((meth)->class) && (meth->accflags & ACC_NATIVE) && meth->idx != -1) return (true); /* If the method hasn't been translated, we need a trampoline * NB: we assume the TRANSLATED flag for abstract methods produced * by gcj is cleared. */ if (!METHOD_TRANSLATED(meth)) return (true); /* We also need one if it's a static method and the class * hasn't been initialized, because such method invocation * would constitute a first active use, requiring the initializer * to be run. */ if ((meth->accflags & ACC_STATIC) && meth->class->state < CSTATE_DOING_INIT) { /* Exception: gcj's classes don't need trampolines for two * reasons: * a) call _Jv_InitClass before invoking any static method. * b) they're not compiled as indirect invocations anyway */ if (!CLASS_GCJ(meth->class)) { return (true); } } return (false);}#endif /* TRANSLATOR *//* * Build a trampoline if necessary, return the address of the native code * to either the trampoline or the translated or native code. * * Sets *where to the address of the native code. * * Return the address of the native code or 0 on failure */static void */* ARGSUSED */buildTrampoline(Method *meth, void **where, errorInfo *einfo){ void *ret;#if defined(TRANSLATOR) methodTrampoline *tramp; if (methodNeedsTrampoline(meth)) { /* XXX don't forget to pick those up at class gc time */ tramp = (methodTrampoline*)gc_malloc(sizeof(methodTrampoline), GC_ALLOC_TRAMPOLINE); if (tramp == 0) { postOutOfMemory(einfo); return (0); } FILL_IN_TRAMPOLINE(tramp, meth, where); /* a disadvantage of building trampolines individually---as * opposed to allocating them in a contiguous region---is that * we have flush the dcache individually for each trampoline */ FLUSH_DCACHE(tramp, tramp+1); /* for native gcj methods, we do override their * anchors so we can patch them up before they're invoked. */ if (!(CLASS_GCJ((meth)->class) && (meth->accflags & ACC_NATIVE))) { assert(*where == 0 || !!!"Cannot override trampoline anchor"); } ret = tramp; } else { if (CLASS_GCJ((meth)->class)) { METHOD_NATIVECODE(meth) = meth->ncode; } assert(METHOD_NATIVECODE(meth) != 0); ret = METHOD_NATIVECODE(meth); }#else ret = meth;#endif *where = ret; return (ret);}/* * Check whether there exists a method with the same name and signature * ``meth'' in class ``clazz'' or any of its superclasses. * If so, return set the ``meth'''s index to its index and return true. * Otherwise return false. */boolgetInheritedMethodIndex(Hjava_lang_Class *super, Method *meth){ /* Search superclasses for equivalent method name. * If found extract its index nr. */ for (; super != NULL; super = super->superclass) { int j = CLASS_NMETHODS(super); Method* mt = CLASS_METHODS(super); for (; --j >= 0; ++mt) { if (utf8ConstEqual (mt->name, meth->name) && utf8ConstEqual (METHOD_SIG(mt), METHOD_SIG(meth))) { meth->idx = mt->idx; return (true); } } } return (false);}staticboolbuildDispatchTable(Hjava_lang_Class* class, errorInfo *einfo){ Method* meth; void** mtab; int i; Hjava_lang_Class *cc; if (class->superclass != NULL) { class->msize = class->superclass->msize; } else { class->msize = 0; } meth = CLASS_METHODS(class); i = CLASS_NMETHODS(class); for (; --i >= 0; meth++) { Hjava_lang_Class* super = class->superclass; /* Do not assign dtable indices for static, private * and constructor methods. */ if (METHOD_IS_STATIC(meth) || METHOD_IS_PRIVATE(meth) || utf8ConstEqual(meth->name, constructor_name)) { meth->idx = -1; continue; } /* Search superclasses for equivalent method name. * If found extract its index nr. */ if (getInheritedMethodIndex(super, meth) == false) { /* No match found so allocate a new index number --- * except if the method or class is final in which * case it doesn't need one. */ if (METHOD_IS_FINAL(meth) || CLASS_IS_FINAL(class)) { meth->idx = -1; } else { meth->idx = class->msize++; } } } class->dtable = (dispatchTable*)gc_malloc(sizeof(dispatchTable) + class->msize * sizeof(void*), GC_ALLOC_DISPATCHTABLE); if (class->dtable == 0) { postOutOfMemory(einfo); return (false); } class->dtable->class = class; mtab = class->dtable->method; /* now build a trampoline for each and every method */ meth = CLASS_METHODS(class); i = CLASS_NMETHODS(class); for (; --i >= 0; meth++) { void **where; /* * Build trampoline and set the method's native code to * point to this trampoline. */ where = (void**)PMETHOD_NATIVECODE(meth); if (buildTrampoline(meth, where, einfo) == 0) { return (false); } } /* trampolines are also needed for all virtual inherited * methods so they can be patched up independently */ for (cc = class->superclass; cc != 0; cc = cc->superclass) { meth = CLASS_METHODS(cc); i = CLASS_NMETHODS(cc); for (; --i >= 0; meth++) { void **where; /* skip static and overridden methods */ if (meth->idx < 0 || mtab[meth->idx] != 0) { continue; } /* else it's an inherited method. Build a trampoline, * but do not update METHOD_NATIVECODE. */ where = &mtab[meth->idx]; if (buildTrampoline(meth, where, einfo) == 0) { return (false); } } } return (true);}/* * Build the table used by this class for dispatching the interfaces * it implements. */staticboolbuildInterfaceDispatchTable(Hjava_lang_Class* class, errorInfo *einfo){ int i, j; /* Construct two tables: * This first table maps interfaces to indices in itable. * The itable maps the indices for each interface method to the * index in the dispatch table that corresponds to this interface * method. If a class does not implement an interface it declared, * or if it attempts to implement it with improper methods, the * dispatch table will have a 0xffffffff index. * (XXX is this 64bit safe?) * * This will cause a NoSuchMethodError * to be thrown later, in soft_lookupinterfacemethod. */ /* don't bother if we don't implement any interfaces */ if (class->total_interface_len == 0) { return (true); } class->if2itable = gc_malloc(class->total_interface_len * sizeof(short), GC_ALLOC_CLASSMISC); if (class->if2itable == 0) { postOutOfMemory(einfo); return (false); } /* first count how many indices we need */ j = 0; for (i = 0; i < class->total_interface_len; i++) { class->if2itable[i] = j; j += 1; /* add one word to store interface class */ j += class->interfaces[i]->msize; } class->itable2dtable = gc_malloc(j * sizeof(void *), GC_ALLOC_CLASSMISC); if (class->itable2dtable == 0) { postOutOfMemory(einfo); return (false); } j = 0; for (i = 0; i < class->total_interface_len; i++) { int inm = CLASS_NMETHODS(class->interfaces[i]); Method *imeth = CLASS_METHODS(class->interfaces[i]); /* store interface as first word for type inclusion test */ class->itable2dtable[j++] = class->interfaces[i]; for (; inm--; imeth++) { Hjava_lang_Class* ncl; Method *cmeth = 0; /* ignore static methods in interface --- can an * interface have any beside <clinit>? */ if (imeth->accflags & ACC_STATIC) { continue; } /* Search the actual method that implements this * interface method by name. */ for (ncl = class; ncl != NULL; ncl = ncl->superclass) { int k = CLASS_NMETHODS(ncl); cmeth = CLASS_METHODS(ncl); for (; --k >= 0; ++cmeth) { if (utf8ConstEqual (cmeth->name, imeth->name) && utf8ConstEqual (METHOD_SIG(cmeth), METHOD_SIG(imeth))) { goto found; } } }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?