classmethod.c

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

C
2,775
字号
		postExceptionMessage(einfo,				     JAVA_LANG(ClassFormatError),				     "No signature for method: %s",				     WORD2UTF (pool->data[nc])->data);		return (0);	}	name = WORD2UTF (pool->data[nc]);	signature = WORD2UTF (pool->data[sc]);#ifdef KAFFE_VMDEBUG	/* Search down class for method name - don't allow duplicates */	for (ni = CLASS_NMETHODS(c), mt = CLASS_METHODS(c); --ni >= 0; ) {		assert(! utf8ConstEqual (name, mt->name)		       || ! utf8ConstEqual (signature, METHOD_SIG(mt)));	}#endifDBG(CLASSFILE,	dprintf("Adding method %s:%s%s (%x)\n", c->name->data, name->data, signature->data, access_flags);    )	mt = &CLASS_METHODS(c)[CLASS_NMETHODS(c)];	utf8ConstAssign(mt->name, name);	METHOD_PSIG(mt) = parseSignature(signature, einfo);	if (METHOD_PSIG(mt) == NULL) {		return NULL;	}	mt->class = c;	/* Warning: ACC_CONSTRUCTION match ACC_STRICT */	mt->accflags = access_flags & ACC_MASK;	mt->c.bcode.code = 0;	mt->stacksz = 0;	mt->localsz = 0;	mt->exception_table = 0;	mt->idx = -1;	/* Mark constructors as such */	if (utf8ConstEqual (name, constructor_name)) {		mt->accflags |= ACC_CONSTRUCTOR;	}	CLASS_NMETHODS(c)++;	return (mt);}Field*addField(Hjava_lang_Class* c,	 u2 access_flags,	 u2 name_index,	 u2 signature_index,	 errorInfo* einfo){	constIndex nc;	constIndex sc;	Field* ft;	constants* pool;	int index;	const char* sig;	pool = CLASS_CONSTANTS (c);	nc = name_index;	if (pool->tags[nc] != CONSTANT_Utf8) {DBG(RESERROR,	dprintf("addField: no field name.\n");			)		postExceptionMessage(einfo,				     JAVA_LANG(ClassFormatError),				     "No field name");		return (0);	}	--CLASS_FSIZE(c);	/* holds field count initially */	if (access_flags & ACC_STATIC) {		index = CLASS_NSFIELDS(c);	}	else {		index = CLASS_FSIZE(c) + CLASS_NSFIELDS(c);	}	ft = &CLASS_FIELDS(c)[index];	ft->clazz = c;	DBG(CLASSFILE,	dprintf("Adding field %s:%s\n",		CLASS_CNAME(c), CLASS_CONST_UTF8(c, nc)->data);    )	sc = signature_index;	if (pool->tags[sc] != CONSTANT_Utf8) {DBG(RESERROR,	dprintf("addField: no signature name.\n");		)		postExceptionMessage(einfo,				     JAVA_LANG(ClassFormatError),				     "No signature name for field: %s",				     CLASS_CONST_UTF8(c, nc)->data);		CLASS_NFIELDS(c)++;		return (0);	}	utf8ConstAssign(ft->name, WORD2UTF(pool->data[nc]));	utf8ConstAssign(ft->signature, CLASS_CONST_UTF8(c, sc));	ft->accflags = access_flags;	sig = ft->signature->data;	if (sig[0] == 'L' || sig[0] == '[') {		/* This `type' field is used to hold a utf8Const describing		 * the type of the field.  This utf8Const will be replaced		 * with a pointer to an actual class type in resolveFieldType		 * Between now and then, we add a reference to it.		 */		ft->accflags |= FIELD_UNRESOLVED_FLAG;		FIELD_SIZE(ft) = PTR_TYPE_SIZE;	}	else {		/* NB: since this class is primitive, getClassFromSignature		 * will not fail.  Hence it's okay to pass errorInfo as NULL		 */		FIELD_TYPE(ft) = getClassFromSignature(sig, 0, NULL);		FIELD_SIZE(ft) = TYPE_PRIM_SIZE(FIELD_TYPE(ft));	}	CLASS_NFIELDS(c)++;	if (access_flags & ACC_STATIC) {		CLASS_NSFIELDS(c)++;	}	return (ft);}voidsetFieldValue(Hjava_lang_Class* unused, Field* ft, u2 idx){	/* Set value index */	FIELD_CONSTIDX(ft) = idx;	ft->accflags |= FIELD_CONSTANT_VALUE;}intstartFields(Hjava_lang_Class* this, u2 fieldct, errorInfo *einfo){	CLASS_NFIELDS(this) = 0; /* updated in addField() */	CLASS_FSIZE(this) = fieldct;	if (fieldct == 0) {		CLASS_FIELDS(this) = (Field*)0;	}	else {		CLASS_FIELDS(this) = (Field*) gc_malloc(sizeof(Field) * fieldct,							GC_ALLOC_FIELD);		if (!CLASS_FIELDS(this)) {			postOutOfMemory(einfo);			return false;		}	}	GC_WRITE(this, CLASS_FIELDS(this)); /* XXX */		return true;}voidfinishFields(Hjava_lang_Class *cl){	Field tmp;	Field* fld;	int n;	/* Reverse the instance fields, so they are in "proper" order. */	fld = CLASS_IFIELDS(cl);	n = CLASS_NIFIELDS(cl);	while (n > 1) {		tmp = fld[0];		fld[0] = fld[n-1];		fld[n-1] = tmp;		fld++;		n -= 2;	}}voidaddMethodCode(Method* m, Code* c){	assert(m != 0);	assert(c != 0);	assert(c->code != 0);	assert(c->code_length != 0);		m->c.bcode.code = c->code;	m->c.bcode.codelen = c->code_length;	m->stacksz = c->max_stack;	m->localsz = c->max_locals;	m->exception_table = c->exception_table;}voidaddInterfaces(Hjava_lang_Class* c, u2 inr, Hjava_lang_Class** inf){	assert(c);	assert(inr > 0);        c->interfaces = inf;	c->interface_len = inr;	GC_WRITE(c, c->interfaces); /* XXX */}staticHjava_lang_Class *userLoadClass(classEntry *ce,				Hjava_lang_ClassLoader *loader,				errorInfo *einfo){	Hjava_lang_Class *retval = NULL;	JNIEnv *env = THREAD_JNIENV();	Hjava_lang_String *jname;	jthrowable excpending;	jmethodID meth;		/*	 * If an exception is already pending, for instance because we're	 * resolving one that has occurred, save it and clear it for the	 * upcall.	 */	excpending = (*env)->ExceptionOccurred(env);	(*env)->ExceptionClear(env);		if( (jname = utf8Const2JavaReplace(ce->name, '/', '.')) &&	    /*	     * We use JNI here so that all exceptions are caught and we'll	     * always return.	     */	    (meth = (*env)->GetMethodID(		env,		(*env)->GetObjectClass(env, loader),		"loadClass",		"(Ljava/lang/String;)Ljava/lang/Class;")) )	{		jthrowable excobj;				retval = (Hjava_lang_Class*)			(*env)->CallObjectMethod(env,						 loader,						 meth,						 jname);				/*		 * Check whether an exception occurred.  If one was pending,		 * the new exception will override this one.		 */		excobj = (*env)->ExceptionOccurred(env);		(*env)->ExceptionClear(env);				if( excobj != 0 )		{			/* There was an exception. */			einfo->type = KERR_RETHROW;			einfo->throwable = excobj;			if( soft_instanceof(javaLangClassNotFoundException,					    (Hjava_lang_Object *)					    einfo->throwable) )			{				/* Set this for the verifier. */				einfo->type |= KERR_NO_CLASS_FOUND;			}		}		else if( retval == NULL )		{			/* No class returned. */			postExceptionMessage(einfo,					     JAVA_LANG(ClassNotFoundException),					     "%s",					     ce->name->data);			/* Set this for the verifier. */			einfo->type |= KERR_NO_CLASS_FOUND;		}		else if( !utf8ConstEqual(retval->name, ce->name) )		{			/*			 * Its a valid class, but the name differs from the one			 * that was requested.			 */			postExceptionMessage(				einfo,				JAVA_LANG(ClassNotFoundException),				"Bad class name (expect: %s, get: %s)",				ce->name->data,				retval->name->data);			/* Set this for the verifier. */			einfo->type |= KERR_NO_CLASS_FOUND;			retval = NULL;		}		else		{			retval = classMappingLoaded(ce, retval);		}			}	else	{		postOutOfMemory(einfo);	}		/* rethrow pending exception */	if( excpending != NULL )	{		(*env)->Throw(env, excpending);	}	return( retval );}Hjava_lang_Class *loadClass(Utf8Const *name,			    Hjava_lang_ClassLoader *loader,			    errorInfo *einfo){	Hjava_lang_Class *retval = NULL;	classEntry *ce;	if( (ce = lookupClassEntry(name, loader, einfo)) )	{		if( classMappingSearch(ce, &retval, einfo) )		{			if( retval == NULL )			{				/* Loading is this thread's responsibility. */				if( loader )				{DBG(VMCLASSLOADER,	/* Announce when VM calls class loaders.. */	dprintf("Calling user-defined class loader %s - loadClass(%s)\n",		CLASS_CNAME(OBJECT_CLASS(&loader->base)),		ce->name->data);)					/* Use a user defined loader. */					retval = userLoadClass(ce,							       loader,							       einfo);				}				else				{DBG(VMCLASSLOADER,	/* Announce when VM calls class loaders.. */	dprintf("Calling internal class loader for %s\n",		ce->name->data);)					/* Use the primordial loader. */					retval = findClass(ce, einfo);				}			}			else			{				/* Class is already loaded. */			}			if( !retval )			{				/* No joy, update state. */				setClassMappingState(ce, NMS_EMPTY);			}			else if( processClass(retval, CSTATE_LINKED, einfo)				 == false )			{				retval = NULL;			}		}		else		{			/* Class circularity, or some other error. */		}	}	else	{		/* No memory? */	}	return( retval );}Hjava_lang_Class*loadArray(Utf8Const* name, Hjava_lang_ClassLoader* loader, errorInfo *einfo){	Hjava_lang_Class *clazz;	clazz = getClassFromSignature(&name->data[1], loader, einfo);	if (clazz != 0)	{		if( (clazz = lookupArray(clazz, einfo)) )		{			return( clazz );		}		else		{			/* XXX Is it always class not found? */			discardErrorInfo(einfo);			postExceptionMessage(einfo,					     JAVA_LANG(ClassNotFoundException),					     "%s",					     name->data);		}	}	else	{		discardErrorInfo(einfo);		postExceptionMessage(einfo,				     JAVA_LANG(ClassNotFoundException),				     "%s",				     name->data);	}	return (0);}/* * Load a class to whose Class object we refer globally. * This is used only for essential classes, so let's bail if this fails. */voidloadStaticClass(Hjava_lang_Class** class, const char* name){	Hjava_lang_Class *clazz;	errorInfo info;	Utf8Const *utf8;	classEntry* centry;	int iLockRoot;	utf8 = utf8ConstNew(name, -1);	if (!utf8) goto bad;	centry = lookupClassEntry(utf8, 0, &info);	if (!centry) goto bad;	utf8ConstRelease(utf8);	lockMutex(centry);	if (centry->data.cl == 0) {		centry->state = NMS_LOADING;DBG(VMCLASSLOADER,	/* Announce when VM calls class loaders.. */	dprintf("Calling internal class loader for startup class %s\n",		name);)		clazz = findClass(centry, &info);		if (clazz == 0) {			goto bad;		}		/* we won't ever want to lose these classes */		if (!gc_add_ref(clazz)) {			goto bad;		}		(*class) = centry->data.cl = clazz;	}	unlockMutex(centry);		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);	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 = utf8ConstNew(name, -1);	if (!utf8) {		postOutOfMemory(einfo);		return 0;	}	class = loadClass(utf8, loader, einfo);	utf8ConstRelease(utf8);	if (class != 0) {		if (processClass(class, CSTATE_COMPLETE, einfo) == true) {			return (class);		}	}	return (0);}/* * 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;	int iLockRoot;	/* 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);	return (clas);}staticboolresolveObjectFields(Hjava_lang_Class* class, errorInfo *einfo){	int fsize;	int align;	Field* fld;	int nbits, n;	int offset;	int maxalign;	int oldoffset;	int *map;	/* 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);	n = CLASS_NIFIELDS(class);	for (; --n >= 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;		}	}#if 0

⌨️ 快捷键说明

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