classmethod.c

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

C
2,711
字号
	readu2(&nr, fp);	if (nr == 0) {		return true;	}	if (! checkBufSize(fp, (u2)(nr*(2*4)), CLASS_CNAME(c), einfo))	    return false;	ic = gc_malloc(sizeof(innerClass) * nr, KGC_ALLOC_CLASSMISC);	if (!ic) {		postOutOfMemory(einfo);		return false;	}	c->nr_inner_classes = nr;	c->inner_classes = ic;	for (i = 0; i < nr; i++, ic++) {		u2 inner_name_index;		readu2(&ic->inner_class, fp);		readu2(&ic->outer_class, fp);		readu2(&inner_name_index, fp);		readu2(&ic->inner_class_accflags, fp);		if (inner_name_index != 0)		  c->kFlags |= KFLAG_ANONYMOUS;		if (c->this_index && ic->inner_class == c->this_index) {		    c->this_inner_index = i;		}	}	return true;}intstartMethods(Hjava_lang_Class* this, u2 methct, errorInfo *einfo){	if (methct == 0)	{		Kaffe_set_class_methods(this, NULL);	}	else	{		Kaffe_set_class_methods(this, 					gc_malloc(sizeof(Method)*(methct), 						  KGC_ALLOC_METHOD));		if (Kaffe_get_class_methods(this) == NULL)		{			postOutOfMemory(einfo);			return false;		}	}	KGC_WRITE(this, Kaffe_get_class_methods(this));	CLASS_NMETHODS(this) = 0; /* updated in addMethod */	return true;}Method*addMethod(Hjava_lang_Class* c,	  u2 access_flags,	  u2 name_index,	  u2 signature_index,	  errorInfo *einfo){	constIndex nc;	constIndex sc;	Method* mt;	constants* pool;	Utf8Const* name;	Utf8Const* signature;#ifdef KAFFE_VMDEBUG	int ni;#endif	pool = CLASS_CONSTANTS (c);	nc = name_index;	if (nc >= CLASS_CONST_SIZE (c)	    || pool->tags[nc] != CONSTANT_Utf8) {		/* XXX fill in einfo! */DBG(RESERROR,	dprintf("addMethod: no method name.\n");		);		postExceptionMessage(einfo,				     JAVA_LANG(ClassFormatError),				     "No method name");		return (NULL);	}	sc = signature_index;	if (sc >= CLASS_CONST_SIZE (c)	    || pool->tags[sc] != CONSTANT_Utf8) {		/* XXX fill in einfo! */DBG(RESERROR,	dprintf("addMethod: no signature name.\n");	);		postExceptionMessage(einfo,				     JAVA_LANG(ClassFormatError),				     "No signature for method: %s",				     WORD2UTF (pool->data[nc])->data);		return (NULL);	}	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 = Kaffe_get_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 = &(Kaffe_get_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;	mt->accflags = access_flags;	mt->c.bcode.code = NULL;	mt->stacksz = 0;	mt->localsz = 0;	mt->exception_table = NULL;	mt->idx = -1;	/* Mark constructors as such */	if (utf8ConstEqual (name, constructor_name)) {		mt->kFlags |= KFLAG_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 i;	const char* sig;	pool = CLASS_CONSTANTS (c);	nc = name_index;	if (nc >= CLASS_CONST_SIZE (c)	    || pool->tags[nc] != CONSTANT_Utf8) {DBG(RESERROR,	dprintf("addField: no field name.\n");			);		postExceptionMessage(einfo,				     JAVA_LANG(ClassFormatError),				     "No field name");		return (NULL);	}	--CLASS_FSIZE(c);	/* holds field count initially */	if (access_flags & ACC_STATIC) {		i = CLASS_NSFIELDS(c);	}	else {		i = CLASS_FSIZE(c) + CLASS_NSFIELDS(c);	}	ft = &CLASS_FIELDS(c)[i];	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	    || sc >=CLASS_CONST_SIZE(c)) {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 (NULL);	}	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, NULL, 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* this 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,							KGC_ALLOC_FIELD);		if (!CLASS_FIELDS(this)) {			postOutOfMemory(einfo);			return false;		}	}	KGC_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;	KGC_WRITE(c, c->interfaces); /* XXX */}staticHjava_lang_Class *userLoadClass(classEntry *ce,				Hjava_lang_ClassLoader *loader,				errorInfo *einfo){	Hjava_lang_Class *retval = NULL;	Hjava_lang_String *jname;	jthrowable excpending;	Method *meth;	Hjava_lang_Class *class_of_loader;		/*	 * 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 = THREAD_DATA()->exceptObj;	THREAD_DATA()->exceptObj = NULL;		class_of_loader = OBJECT_CLASS((Hjava_lang_Object *)loader);	if( (jname = utf8Const2JavaReplace(ce->name, '/', '.')) )	  {	    jvalue jretval;	    jvalue args[1];	    jthrowable excobj;	    /* If we fail to resolve loadClass then we just have to set retval to NULL.	     * einfo is already set.	     */	    if ((meth = lookupClassMethod(class_of_loader, "loadClass", 					 "(Ljava/lang/String;)Ljava/lang/Class;",					  false, einfo)) == NULL)	      {		retval = NULL;		goto userload_done;	      }	    	    if (METHOD_IS_STATIC(meth))	      {		postExceptionMessage(einfo, "java/lang/NoSuchMethodError",				     "loadClass is wrongly a static method in %s", CLASS_CNAME(class_of_loader));		retval = NULL;		goto userload_done;	      }	    /* ClassLoader is not an interface so we may use NATIVECODE directly. */	    args[0].l = jname;	    KaffeVM_safeCallMethodA(meth, METHOD_NATIVECODE(meth), loader, args, &jretval, false);	    retval = jretval.l;	    /*	     * Check whether an exception occurred.  If one was pending,	     * the new exception will override this one.	     */	    excobj = THREAD_DATA()->exceptObj;	    THREAD_DATA()->exceptObj = NULL;	    	    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;			}			/* We must clear the return value as safeCallMethod does not			 * handle this.			 */			retval = NULL;	      }	    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);	  }	 userload_done:	/* rethrow pending exception */	if( excpending != NULL )	{	  THREAD_DATA()->exceptObj = 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 (NULL);}/* * 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;	bool refAdded;	utf8 = utf8ConstFromString(name);	if (!utf8) goto bad;	centry = lookupClassEntry(utf8, NULL, &info);	if (!centry) goto bad;	utf8ConstRelease(utf8);	lockStaticMutex(&centry->slock);	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););

⌨️ 快捷键说明

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