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 + -
显示快捷键?