classmethod.c
来自「基于LWVCL开发的库」· C语言 代码 · 共 2,711 行 · 第 1/5 页
C
2,711 行
clazz = findClass(centry, &info); if (clazz == NULL) { goto bad; } /* we won't ever want to lose these classes */ refAdded = gc_add_ref(clazz); if (!refAdded) { goto bad; } (*class) = centry->data.cl = clazz; } unlockStaticMutex(¢ry->slock); if (!(*class)) (*class) = centry->data.cl; if (processClass(centry->data.cl, CSTATE_LINKED, &info) == true) { assert(centry->state == NMS_DONE); return; }bad: dprintf("Couldn't find or load essential class `%s' %s %s\n", name, info.classname, (char*)info.mess); KAFFEVM_ABORT();}/* * Look a class up by name. */Hjava_lang_Class*lookupClass(const char* name, Hjava_lang_ClassLoader* loader, errorInfo *einfo){ Hjava_lang_Class* class; Utf8Const *utf8; utf8 = utf8ConstFromString(name); if (!utf8) { postOutOfMemory(einfo); return NULL; } class = loadClass(utf8, loader, einfo); utf8ConstRelease(utf8); if (class != NULL) { if (processClass(class, CSTATE_COMPLETE, einfo) == true) { return (class); } } return (NULL);}/* * Return FIELD_TYPE(FLD), but if !FIELD_RESOLVED, resolve the field first. */Hjava_lang_Class*resolveFieldType(Field *fld, Hjava_lang_Class* this, errorInfo *einfo){ Hjava_lang_Class* clas; const char* name; /* Avoid locking if we can */ if (FIELD_RESOLVED(fld)) { return (FIELD_TYPE(fld)); } /* We must lock the class while we retrieve the field name and * while we resolve it - or we may release the utf8's field type twice */ lockClass(this); if (FIELD_RESOLVED(fld)) { unlockClass(this); return (FIELD_TYPE(fld)); } name = fld->signature->data; if( (clas = getClassFromSignature(name, this->loader, einfo)) ) { FIELD_TYPE(fld) = clas; fld->accflags &= ~FIELD_UNRESOLVED_FLAG; } unlockClass(this);#if defined(KAFFE_XDEBUGGING) if( machine_debug_file ) { addDebugInfo(machine_debug_file, DIA_Class, this, DIA_DONE); }#endif return (clas);}staticboolresolveObjectFields(Hjava_lang_Class* class, errorInfo *einfo){ int fsize; int align; Field* fld; int nbits, nifields; int offset; int maxalign; int oldoffset; int *map; jboolean is_reference; /* Find start of new fields in this object. If start is zero, we must * allow for the object headers. */ offset = CLASS_FSIZE(class); oldoffset = offset; /* remember initial offset */ if (offset == 0) { offset = sizeof(Hjava_lang_Object); } /* Find the largest alignment in this class */ maxalign = 1; fld = CLASS_IFIELDS(class); nifields = CLASS_NIFIELDS(class); for (; --nifields >= 0; fld++) { fsize = FIELD_SIZE(fld); /* Work out alignment for this size entity */ fsize = ALIGNMENT_OF_SIZE(fsize); /* If field is bigger than biggest alignment, change * biggest alignment */ if (fsize > maxalign) { maxalign = fsize; } } /* Now work out where to put each field */ fld = CLASS_IFIELDS(class); nifields = CLASS_NIFIELDS(class); for (; --nifields >= 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; /* Check whether the class is java.lang.ref.Reference */ is_reference = (strcmp(CLASS_CNAME(class), "java/lang/ref/Reference") == 0); /* 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, KGC_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; nbits = offset/ALIGNMENTOF_VOIDP;DBG(GCPRECISE, dprintf("GCLayout for %s:\n", CLASS_CNAME(class)); ); /* Now work out the gc layout */ fld = CLASS_IFIELDS(class); nifields = CLASS_NIFIELDS(class); for (; --nifields >= 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) && (!is_reference || strcmp(FIELD_NAME(fld), "referent") != 0)) { 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; } assert(offset > 0); /* Allocate memory required */ mem = gc_malloc((unsigned int)offset, KGC_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; unsigned 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; default: break; } } } return true;}/* * 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 = Kaffe_get_class_methods(super); for (; --j >= 0; ++mt) { /* skip methods that are private or static */ if ((mt->accflags & (ACC_PRIVATE|ACC_STATIC)) != 0) continue; /* skip inaccessible methods */ if (!checkAccess (meth->class, super, mt->accflags)) continue; if (utf8ConstEqual (mt->name, meth->name) && utf8ConstEqual (METHOD_SIG(mt), METHOD_SIG(meth))) { meth->idx = mt->idx; return (true); } } } return (false);}/** * Get start of native code of a method * * @param method a method * @return pointer to start of code */jitCodeHeader*getMethodCodeStart(Method * method) { return method->c.ncode.ncode_start;}/** * Set start of native code of a method * * @param method a method * @param start pointer to start of code */voidsetMethodCodeStart(Method * method, jitCodeHeader* start){ method->c.ncode.ncode_start = start;}staticboolbuildDispatchTable(Hjava_lang_Class* class, errorInfo *einfo){ Method* meth; void** mtab; int i; Hjava_lang_Class *cc; if (class->superclass != NULL) { class->msize = getSuperclass(class)->msize; } else { class->msize = 0; } meth = Kaffe_get_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->vtable = (dispatchTable*)gc_malloc(sizeof(dispatchTable) + class->msize * sizeof(void*), KGC_ALLOC_DISPATCHTABLE); if (class->vtable == 0) { postOutOfMemory(einfo); return (false); } class->vtable->class = class; mtab = class->vtable->method; /* now build a trampoline for each and every method */ meth = Kaffe_get_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 (engine_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 = Kaffe_get_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 (engine_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.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?