classmethod.c

来自「基于LWVCL开发的库」· C语言 代码 · 共 2,711 行 · 第 1/5 页

C
2,711
字号
	 * 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 + 1) * sizeof(short), KGC_ALLOC_CLASSMISC);	if (class->if2itable == 0) {		postOutOfMemory(einfo);		return (false);	}	/* first count how many indices we need. We need at least one entry to put	 * the pointer to the class.	 */	j = 1;	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;	}	/* This last entry is to specify the total length of the table. */	class->if2itable[class->total_interface_len] = j;	class->itable2dtable = gc_malloc(j * sizeof(void *), KGC_ALLOC_INTERFACE_TABLE);	if (class->itable2dtable == 0) {		postOutOfMemory(einfo);		return (false);	}	if (!gc_add_ref(class->itable2dtable)) {		postOutOfMemory(einfo);		return false;	}	class->itable2dtable[0] = class;	j = 1;	for (i = 0; i < class->total_interface_len; i++) {		int inm = CLASS_NMETHODS(class->interfaces[i]);		Method *imeth = Kaffe_get_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 = NULL;			/* 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 = Kaffe_get_class_methods(ncl);				for (; --k >= 0;  ++cmeth) {					if (utf8ConstEqual (cmeth->name,							    imeth->name) &&					     utf8ConstEqual (METHOD_SIG(cmeth),							     METHOD_SIG(imeth)))					{						goto found;					}				}			}			/* not found */			cmeth = NULL;		    found:;			/* constructors and static methods cannot implement			 * interface methods			 */			if (cmeth && (METHOD_IS_STATIC(cmeth) ||				      METHOD_IS_CONSTRUCTOR(cmeth)))			{				cmeth = NULL;			}			/* cmeth == 0 if			 * This class does not implement the interface at all.			 * Or if the class attempts to implement an interface			 * method with a static method or constructor.			 */			if (cmeth == 0) {				class->itable2dtable[j] = (void *)-1;			} else {				if (engine_buildTrampoline(cmeth,					    class->itable2dtable + j,					    einfo) == 0)				{					return (false);				}			}			j++;		}	}	return (true);}/* * Compute the interface implementation index for this class. * The impl_index is an index for each class that is used to index the * implementor table of the interface when dispatching an interface * method.  See soft_lookupinterfacemethod in soft.c * It points directly at the first itable2dtable index for the section * that describes the interface (which is what's now redundantly stored * in if2itable[x].) * * This allows interface lookup in constant time. */static boolcomputeInterfaceImplementationIndex(Hjava_lang_Class* clazz, errorInfo* einfo){	int j, k;	unsigned int i;	int found_i;	bool rc = false;	Hjava_lang_Class** ifcs;	/* find an impl_index for this class	 * Note that we only find a suitable impl_index with regard to the	 * interfaces this class implements, not a globally unique one.	 *	 * In other words, two classes implementing disjoint sets of	 * interfaces may end up with the same impl_index.  For this reason,	 * the impl_index at this point cannot be used to implement the	 * equivalent of instanceof <interface>	 *	 * We assume that a verifier design is possible that will ensure	 * that a run-time object indeed implements an interface at the	 * time when soft_lookupinterfacemethod is invoked.  We do not have	 * such a verifier at this point.	 */	if (clazz->total_interface_len == 0) {		return (true);	}	/* We are manipulating the implementor tables of all implemented	 * interfaces.  We must lock them.  To avoid deadlock, lets lock	 * them in ascending order.	 */	ifcs = KMALLOC(clazz->total_interface_len * sizeof(Hjava_lang_Class*));	memcpy(ifcs, clazz->interfaces,		clazz->total_interface_len * sizeof(Hjava_lang_Class*));	/* this is bubble-sort */	do {		k = 0;		for (j = 0; j < clazz->total_interface_len - 1; j++) {			Hjava_lang_Class* iface_j = ifcs[j];			Hjava_lang_Class* iface_j1 = ifcs[j+1];			if ((uintp)iface_j > (uintp)iface_j1) {				k = 1;				ifcs[j] = iface_j1;				ifcs[j+1] = iface_j;			}		}	} while (k);	for (j = 0; j < clazz->total_interface_len; j++) {		lockClass(ifcs[j]);	}	i = 0;	do {		found_i = 1;		for (j = 0; j < clazz->total_interface_len; j++) {			Hjava_lang_Class* iface = clazz->interfaces[j];	    		uintp len = 0;			if (iface->implementors != NULL) {				/* This is how many entries follow, so the				 * array has a[0] + 1 elements. We have to convert				 * the value from pointer type (which is at least 16 bits				 * as previously).				 */			        len = (uintp)iface->implementors[0];			}			if (i >= len || iface->implementors[i+1] == NULL) {				continue;	/* this one would work */			} else {				found_i = 0;				break;			}		}		i++;	} while (!found_i);	/* 'i' is a suitable index --- note we incremented i before leaving	 * the loop above.	 */	clazz->impl_index = i;	/* Now patch all interfaces to point back to their itable2dtable	 * regions in the dispatch table of this implementing class.	 */	for (j = 0; j < clazz->total_interface_len; j++) {		Hjava_lang_Class* iface = clazz->interfaces[j];		uintp len;		/* make sure the implementor table is big enough */		if (iface->implementors == NULL || i > (uintp)iface->implementors[0]) {			if (iface->implementors == NULL) {				len = (i + 1) + 4; /* 4 is slack only */				iface->implementors = (void ***)gc_malloc(len * sizeof(void **), KGC_ALLOC_CLASSMISC);			} else {				/* double in size */				len = (uintp)(iface->implementors[0] + 1) * 2;				if (len <= i) {					len = (i + 1) + 4;				}				iface->implementors = (void ***)gc_realloc(					iface->implementors,					len * sizeof(void **), KGC_ALLOC_CLASSMISC);			}			if (iface->implementors == NULL) {				postOutOfMemory(einfo);				goto done;			}			/* NB: we assume KMALLOC/KREALLOC zero memory out */			iface->implementors[0] = (void *)(len - 1);			/* New entries are magically marked as unused by the GC			 * as it fills the memory with 0.			 */		}		assert(i < (uintp)iface->implementors[0] + 1);		iface->implementors[i] = &(clazz->itable2dtable[clazz->if2itable[j]]);	}	rc = true;done:	for (j = clazz->total_interface_len - 1; j >= 0; j--) {		unlockClass(ifcs[j]);	}	KFREE(ifcs);	return (rc);}/* Check for undefined abstract methods if class is not abstract. * See "Java Language Specification" (1996) section 12.3.2. * * Returns true if the class is abstract or if no abstract methods were * found, false otherwise. */staticboolcheckForAbstractMethods(Hjava_lang_Class* class, errorInfo *einfo){	int i;	void **mtab = class->vtable->method;	if ((class->accflags & ACC_ABSTRACT) == 0) {		for (i = 0; i < class->msize; i++) {			if (mtab[i] == NULL) {				postException(einfo,					JAVA_LANG(AbstractMethodError));				return (false);			}		}	}	return (true);}/* * This functions simply assign indices to the virtual methods in an * interface. * * In addition, if the interface has a <clinit> method, it builds a * trampoline for it. */staticbool/* ARGSUSED */prepareInterface(Hjava_lang_Class* class, errorInfo *einfo){	Method* meth;	int i;	meth = Kaffe_get_class_methods(class);	class->msize = 0;	/* enumerate indices and store them in meth->idx */	for (i = 0; i < CLASS_NMETHODS(class); i++, meth++) {		if (meth->accflags & ACC_STATIC) {			meth->idx = -1;			/* Handle <clinit> */			if (utf8ConstEqual(meth->name, init_name)) {				void **where;				where = (void**)PMETHOD_NATIVECODE(meth);				if (engine_buildTrampoline(meth, where, einfo) == 0) {					return (false);				}			}		}		else {			meth->idx = class->msize++;		}	}	return (true);}/* * convert a CONSTANT_String entry in the constant poool * from utf8 to java.lang.String */Hjava_lang_String*resolveString(Hjava_lang_Class* clazz, int idx, errorInfo *info){	Utf8Const* utf8;	Hjava_lang_String* str = NULL;	constants* pool;	pool = CLASS_CONSTANTS(clazz);	lockClass(clazz);	switch (pool->tags[idx]) {	case CONSTANT_String:		utf8 = WORD2UTF(pool->data[idx]);		str = utf8Const2Java(utf8);		if (!str) {			postOutOfMemory(info);			break;		}		pool->data[idx] = (ConstSlot)str;		pool->tags[idx] = CONSTANT_ResolvedString;		utf8ConstRelease(utf8);		break;	case CONSTANT_ResolvedString:	/* somebody else resolved it */		str = (Hjava_lang_String*)pool->data[idx];		break;	default:		assert(!!!"Neither String nor ResolvedString?");	}	unlockClass(clazz);	return (str);}#undef EAGER_LOADING/* * Initialise the constants. * First we make sure all the constant strings are converted to java strings. * * This code removed: * There seems to be no need to be so eager in loading * referenced classes or even resolving strings. */staticboolresolveConstants(Hjava_lang_Class* class UNUSED, errorInfo *einfo UNUSED){	bool success = true;#ifdef EAGER_LOADING	iLock* lock;	int idx;	constants* pool;	Utf8Const* utf8;	lockClass(class);	/* Scan constant pool and convert any constant strings into true	 * java strings.	 */	pool = CLASS_CONSTANTS (class);	for (idx = 0; idx < pool->size; idx++) {		switch (pool->tags[idx]) {		case CONSTANT_String:			utf8 = WORD2UTF(pool->data[idx]);			/* XXX: unchecked malloc */			pool->data[idx] = (ConstSlot)utf8Const2Java(utf8);			pool->tags[idx] = CONSTANT_ResolvedString;			utf8ConstRelease(utf8);			break;		case CONSTANT_Class:			if (getClass(idx, class, einfo) == 0) {				success = false;				goto done;			}			break;		}	}done:	unlockClass(this);#endif	/* EAGER_LOADING */	return (success);}/* * Lookup a named field.  Do not search super classes. Do not resolve the field. */static Field*lookupClassFieldLocal(Hjava_lang_Class* clp, Utf8Const* name, bool isStatic){	Field* fptr;	int n;	/* Search down class for field name */	if (isStatic) {		fptr = CLASS_SFIELDS(clp);		n = CLASS_NSFIELDS(clp);	}	else {		fptr = CLASS_IFIELDS(clp);		n = CLASS_NIFIELDS(clp);	}	while (--n >= 0) {		if (utf8ConstEqual (name, fptr->name)) {			return (fptr);		}		fptr++;	}	return (NULL);}/* * Lookup a named field. Search superclasses and resolve the field. */Field*lookupClassField(Hjava_lang_Class* clp, Utf8Const* name, bool isStatic, errorInfo *einfo){	Field *fptr;	Hjava_lang_Class *c;	for (c = clp; c; c = c->superclass) {		fptr = lookupClassFieldLocal(c, name, isStatic);		if (fptr) {			/* Resolve field if necessary */			if (resolveFieldType(fptr, c, einfo) == 0) {				return (NULL);			}			return (fptr);		}	}	if (isStatic) {		int i = clp->total_interface_len;		Hjava_lang_Class **cp = &clp->interfaces[0];		while (--i >= 0) {			fptr = lookupClassFieldLocal (*cp, name, true);			if (fptr) {				if (resolveFieldType(fptr, *cp, einfo) == 0) {					return (NULL);				}				return (fptr);			}			cp++;		}		}DBG(RESERROR,	dprintf("lookupClassField for %s failed %s:%s\n",		isStatic?"static":"non-static",clp->name->data, name->data);    );	postExceptionMessage(einfo, JAVA_LANG(NoSuchFieldError), "%s", name->data);	return (NULL);}/* * Determine the number of arguments and return values from the * method signature. */voidcountInsAndOuts(const char* str, short* ins, short* outs, char* outtype){	*ins = sizeofSig(&str, false);	*outtype = str[0];	*outs = sizeofSig(&str, false);}/* * Calculate size (in words) of a signature item. */intsizeofSigChar(char ch, bool want_wide_refs){	switch (ch) {	case 'V':		return 0;	case 'I':	case 'Z':	case 'S':	case 'B':	case 'C':	case 'F':		return 1;		break;	case 'D':	case 'J':		return 2;		break;	case '[':	case 'L':		return want_wide_refs ? sizeof(void*) / sizeof(int32) : 1;	default:		break;	}	return -1;}/* * Calculate size (in words) of a signature item and move *strp so * that it points to the next element of the signature */intsizeofSigItem(const char** strp, bool want_wide_refs){	int count;	const char* str;	for (str = *strp; ; str++) {		count = sizeofSigChar(*str, want_wide_refs);		if (count == -1) {			switch (*s

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?