classmethod.c

来自「kaffe Java 解释器语言,源码,Java的子集系统,开放源代码」· C语言 代码 · 共 2,775 行 · 第 1/5 页

C
2,775
字号
			/* not found */			cmeth = 0;		    found:;			/* constructors and static methods cannot implement			 * interface methods			 */			if (cmeth && (METHOD_IS_STATIC(cmeth) ||				      METHOD_IS_CONSTRUCTOR(cmeth)))			{				cmeth = 0;			}			/* 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 (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 i, j, k;	int found_i;	bool rc = false;	Hjava_lang_Class** ifcs;	int iLockRoot;	/* 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 (iface_j - iface_j1 > 0) {				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];	    		int len = 0;			if (iface->implementors != 0) {				/* This is how many entries follow, so the				 * array has a[0] + 1 elements				 */				len = iface->implementors[0];			}			if (i >= len || iface->implementors[i+1] == -1) {				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];		short len;		/* make sure the implementor table is big enough */		if (iface->implementors == NULL || i > iface->implementors[0]) {			short firstnewentry;			if (iface->implementors == NULL) {				len = (i + 1) + 4; /* 4 is slack only */				iface->implementors = gc_malloc(len * sizeof(short), GC_ALLOC_CLASSMISC);			} else {				/* double in size */				len = iface->implementors[0] * 2;				if (len <= i) {					len = i + 4;				}				iface->implementors = gc_realloc(					iface->implementors,					len * sizeof(short), GC_ALLOC_CLASSMISC);			}			if (iface->implementors == 0) {				postOutOfMemory(einfo);				goto done;			}			/* NB: we assume KMALLOC/KREALLOC zero memory out */			firstnewentry = iface->implementors[0] + 1;			iface->implementors[0] = len - 1;			/* mark new entries as unused */			for (k = firstnewentry; k < len; k++) {				iface->implementors[k] = -1;			}		}		assert(i < iface->implementors[0] + 1);		iface->implementors[i] = 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->dtable->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. */staticboolprepareInterface(Hjava_lang_Class* class, errorInfo *einfo){	Method* meth;	int i;	meth = 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;#if defined(TRANSLATOR)			/* Handle <clinit> */			if (utf8ConstEqual(meth->name, init_name)) {				void **where;				where = (void**)PMETHOD_NATIVECODE(meth);				if (buildTrampoline(meth, where, einfo) == 0) {					return (false);				}			}#endif		}		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 = 0;	constants* pool;	int iLockRoot;	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, errorInfo *einfo){	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 (0);}/* * 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 (0);}/* * 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;	}	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 (*str) {			case '(':				continue;			case 0:			case ')':				break;			default:				count = -1;	/* avoid compiler warning */				ABORT();			}		} else {			while (*str == '[')				++str;			if (*str == 'L') {				while (*str != ';') {					str++;				}			}		}		*strp = str + 1;		return (count);	}}/* * Calculate size of data item based on signature and move *strp so * that it points to the next element of the signature. */intsizeofSig(const char** strp, bool want_wide_refs){	int count;	int c;	count = 0;	for (;;) {		c = sizeofSigItem(strp, want_wide_refs);		if (c == -1) {			return (count);		}		count += c;	}}/* * Calculate size (in words) of a Class. */intsizeofSigClass(Hjava_lang_Class* clazz, bool want_wide_refs){	return sizeofSigChar(CLASS_IS_PRIMITIVE(clazz)			     ? CLASS_PRIM_SIG(clazz)			     : 'L', want_wide_refs);}/* * Calculate size (in words) of the signature of a Method. */intsizeofSigMethod(Method *meth, bool want_wide_refs){	int i = 0, args = METHOD_NARGS(meth), size = 0;	while (i < args) {		size += sizeofSigChar(*METHOD_ARG_TYPE(meth, i),				      want_wide_refs);		++i;	}	return (size);}/* * Count the number of arguments in a signature. */intcountArgsInSignature(const char *signature){	int nargs = 0;	while (sizeofSigItem(&signature, false) != -1) {		++nargs;	}	return (nargs);}/* * Parse a method signature and return an array of pointers to classes. */parsed_signature_t*parseSignature(Utf8Const *signature, errorInfo *einfo

⌨️ 快捷键说明

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