lookup.c

来自「基于LWVCL开发的库」· C语言 代码 · 共 417 行

C
417
字号
/* * lookup.c * Various lookup calls for resolving objects, methods, exceptions, etc. * * Copyright (c) 1996, 1997 *	Transvirtual Technologies, Inc.  All rights reserved. * * See the file "license.terms" for information on usage and redistribution  * of this file.  */#include "debug.h"#include "config.h"#include "config-std.h"#include "config-mem.h"#include "jni_md.h"#include "errors.h"#include "gtypes.h"#include "access.h"#include "object.h"#include "constants.h"#include "classMethod.h"#include "lookup.h"#include "exception.h"#include "thread.h"#include "baseClasses.h"#include "stringSupport.h"#include "machine.h"#include "locks.h"#include "soft.h"/* * Lookup a method reference and get the various interesting bits. * * Return false if unsuccessful because of a malformed class file *	or if the class couldn't be found or processed. * Returns true otherwise.  * * Note that even if it returns true, the method may not be found. * call->method is set to NULL in this case. */boolgetMethodSignatureClass(constIndex idx, Hjava_lang_Class* this, bool shouldLoadClass, int isSpecial, callInfo* call, errorInfo *einfo){	constants* pool;	constIndex ci;	constIndex ni;	Hjava_lang_Class* class;	Utf8Const* name;	Utf8Const* sig;	Method* mptr;	int i;	call->class = NULL;	call->method = NULL;	call->signature = NULL;	call->name = NULL;	call->cname = NULL;	pool = CLASS_CONSTANTS(this);	if (idx >= CLASS_CONST_SIZE(this))	  {	    postExceptionMessage(einfo, JAVA_LANG(ClassFormatError), "invalid method name index");	    return false;	  }	if (pool->tags[idx] != CONSTANT_Methodref &&	    pool->tags[idx] != CONSTANT_InterfaceMethodref) {DBG(RESERROR,	dprintf("No Methodref found for idx=%d\n", idx);	);		/* shouldn't that be ClassFormatError or something? */		postExceptionMessage(einfo, JAVA_LANG(NoSuchMethodError),			"method name unknown, tag = %d",  pool->tags[idx]);                return (false);	}	ni = METHODREF_NAMEANDTYPE(idx, pool);	if (ni >= CLASS_CONST_SIZE(this))	  {	    postExceptionMessage(einfo, JAVA_LANG(ClassFormatError),				 "invalid method name index");	    return false;	  }	name = WORD2UTF(pool->data[NAMEANDTYPE_NAME(ni, pool)]);	sig = WORD2UTF(pool->data[NAMEANDTYPE_SIGNATURE(ni, pool)]);	call->name = name;	call->signature = sig;	if (shouldLoadClass == true) {		ci = METHODREF_CLASS(idx, pool);		class = getClass(ci, this, einfo);		if (class == NULL) {			call->cname = WORD2UTF(pool->data[ci]);			countInsAndOuts(sig->data, &call->in, &call->out, &call->rettype);			return (false);		}		assert(class->state >= CSTATE_DOING_LINK);                if (isSpecial == 1) {                        if (!utf8ConstEqual(name, constructor_name) &&			    class != this && instanceof(class, this)) {                                class = this->superclass;                        }                }		call->class = class;		call->cname = class->name;		call->method = NULL;		/* Find method - we don't use findMethod(...) yet since this		 * will initialise our class (and we don't want to do that).		 */		if (isSpecial != 2) {			/* method resolution for INVOKEVIRTUAL or INVOKESPECIAL.			 * Since we make sure that the dispatch table of a class			 * contains all methods of all implemented interfaces, we			 * don't need to search superinterfaces here.			 */			for (; class != NULL; class = class->superclass) {				mptr = findMethodLocal(class, name, sig);				if (mptr != NULL) {					call->method = mptr;					break;				}			}		} else {			/* method resolution for INVOKEINTERFACE. First search the			 * interface itself, then its superinterfaces and finally			 * java.lang.Object.			 */			class = call->class;			mptr = findMethodLocal(class, name, sig);			if (mptr == NULL) {				for (i = class->total_interface_len - 1; i >= 0; i--) {					mptr = findMethodLocal(class->interfaces[i], name, sig);					if (mptr != NULL) {						break;					}				}				if (mptr == NULL) {					mptr = findMethodLocal(call->class->superclass, name, sig);				}			}			call->method = mptr;		}	}	/* Calculate in's and out's */	countInsAndOuts(sig->data, &call->in, &call->out, &call->rettype);DBG(MLOOKUP,		if (shouldLoadClass) 		dprintf("getMethodSignatureClass(%s,%s,%s) -> %s\n",			call->class->name->data, name->data, sig->data, 			(call->method ? "success" : "failure"));	);	return (true);}/* * Get and link the class to which constant pool index idx in class this * refers.  The returned class object is at least LINKED. */Hjava_lang_Class*getClass(constIndex idx, Hjava_lang_Class* this, errorInfo *einfo){	constants* pool;	Utf8Const *name;	Hjava_lang_Class* class;	int tag;	pool = CLASS_CONSTANTS(this);	if (idx >= CLASS_CONST_SIZE(this))	  {	    postExceptionMessage(einfo, JAVA_LANG(ClassFormatError),				 "invalid class name index");	    return NULL;	  }	tag = pool->tags[idx];	switch (tag) {	case CONSTANT_ResolvedClass:		return (CLASS_CLASS(idx, pool));	case CONSTANT_Class:		/* The class may be resolved by another thread so we better		 * lock and get the tag & name again just in case.  If we		 * have been resolved then we just return the answer.		 */		lockClass(this);		tag = pool->tags[idx];		name = WORD2UTF(pool->data[idx]);		unlockClass(this);		if (tag == CONSTANT_ResolvedClass) {			return (CLASS_CLASS(idx, pool));		}		break;	default:		postExceptionMessage(einfo,				     JAVA_LANG(ClassFormatError),				     "%s (Invalid constant reference, %d, "				     "expecting class, likely an internal "				     "error)",				     this->name->data,				     tag);		return NULL;	}	/* Find the specified class.	 * NB: the name is *not* a signature.	 */	if (name->data[0] == '[') {		class = loadArray(name, this->loader, einfo);	}	else {		class = loadClass(name, this->loader, einfo);	}	if (class == 0) {		/*		 * Need to translate ClassNotFoundExceptions to		 * NoClassDefFoundErrors since thats what the		 * verifier/jitter/etc expect.		 */		switch( einfo->type & KERR_CODE_MASK )		{		case KERR_RETHROW:			if( soft_instanceof(javaLangClassNotFoundException,					    (Hjava_lang_Object *)					    einfo->throwable) )			{				discardErrorInfo(einfo);				postNoClassDefFoundError(einfo, name->data);			}			break;		case KERR_EXCEPTION:			if( strcmp(einfo->classname,				   JAVA_LANG(ClassNotFoundException)) == 0 )			{				errorInfo einfo_copy = *einfo;								postNoClassDefFoundError(einfo, einfo->mess);				discardErrorInfo(&einfo_copy);			}			break;		default:			break;		}		return NULL;	}	/* Lock the class while we update the constant pool.  Someone	 * may have done this already but we don't care.	 */	lockClass(this);	pool->data[idx] = (ConstSlot)class;	pool->tags[idx] = CONSTANT_ResolvedClass;	unlockClass(this);	return (class);}boolgetField(constIndex idx, Hjava_lang_Class* this, bool isStaticField, fieldInfo* ret, errorInfo *einfo){	constants* pool;	constIndex ci;	constIndex ni;	Field* field;	Hjava_lang_Class* class;	ret->field = NULL;	ret->class = NULL;		pool = CLASS_CONSTANTS(this);	if (pool->tags[idx] != CONSTANT_Fieldref) {DBG(RESERROR,	dprintf("No Fieldref found\n");				);		postExceptionMessage(einfo, JAVA_LANG(NoSuchFieldError),			"tag was %d", pool->tags[idx]);		return (false);	}	ci = FIELDREF_CLASS(idx, pool);	ni = FIELDREF_NAMEANDTYPE(idx, pool);	ret->name = WORD2UTF(pool->data[NAMEANDTYPE_NAME(ni, pool)]);	ret->signature = WORD2UTF(pool->data[NAMEANDTYPE_SIGNATURE(ni, pool)]);	class = getClass(ci, this, einfo);	if (class == NULL) {		ret->cname = WORD2UTF(pool->data[ci]);		return (false);	}DBG(FLOOKUP,	dprintf("*** getField(%s,%s,%s)\n",		class->name->data, 		WORD2UTF(pool->data[NAMEANDTYPE_NAME(ni, pool)])->data, 		WORD2UTF(pool->data[NAMEANDTYPE_SIGNATURE(ni, pool)])->data);    );	ret->cname = class->name;	field = lookupClassField(class, WORD2UTF(pool->data[NAMEANDTYPE_NAME(ni, pool)]), isStaticField, einfo);	if (field == 0) {		return (false);	}	if (!utf8ConstEqual(field->signature, ret->signature)) {		postExceptionMessage(einfo,				     JAVA_LANG(NoSuchFieldError),				     "%s.%s %s",				     ret->cname->data,				     ret->name->data,				     ret->signature->data);		return (false);	}	/* XXX Should we verify that ret->signature matches field? */	ret->field = field;	ret->class = field->clazz;	return (true);}/* * Lookup a method (and translate) in the specified class. */Method*findMethodLocal(Hjava_lang_Class* class, Utf8Const* name, Utf8Const* signature){	Method* mptr;	int n;	/*	 * Lookup method - this could be alot more efficient but never mind.	 * Also there is no attempt to honour PUBLIC, PRIVATE, etc.	 */	n = CLASS_NMETHODS(class);	for (mptr = Kaffe_get_class_methods(class); --n >= 0; ++mptr) {		if (utf8ConstEqual (name, mptr->name) && utf8ConstEqual (signature, METHOD_SIG(mptr))) {DBG(MLOOKUP,			dprintf("findMethodLocal(%s,%s,%s) -> %p\n",				class->name->data, name->data, signature->data, mptr); );			return (mptr);		}	}DBG(MLOOKUP,	dprintf("findMethodLocal(%s,%s,%s) -> NOT FOUND\n",		class->name->data, name->data, signature->data); );	return NULL;}/* * Lookup a method (and translate) in the specified class. */Method*findMethod(Hjava_lang_Class* class, Utf8Const* name, Utf8Const* signature, errorInfo *einfo){	bool success;	/*	 * Waz CSTATE_LINKED - Must resolve constants before we do any	 * translation.  Might not be right though ... XXX	 */	if (class->state < CSTATE_USABLE) {		success = processClass(class, CSTATE_COMPLETE, einfo);		if (!success)			return (NULL);	}	/*	 * Lookup method - this could be alot more efficient but never mind.	 * Also there is no attempt to honour PUBLIC, PRIVATE, etc.	 */	for (; class != NULL; class = class->superclass) {		Method* mptr = findMethodLocal(class, name, signature);		if (mptr != NULL) {			return mptr;		}	}	postExceptionMessage(einfo, JAVA_LANG(NoSuchMethodError), "%s", name->data);	return (NULL);}Method*KaffeVM_findDeclaredMethod(Hjava_lang_Class *class, Utf8Const *name, Utf8Const *signature, errorInfo *einfo){  Method *mptr;  bool success;  /*   * Waz CSTATE_LINKED - Must resolve constants before we do any   * translation.  Might not be right though ... XXX   */  if (class->state < CSTATE_USABLE) {    success = processClass(class, CSTATE_COMPLETE, einfo);    if (!success)      return (NULL);  }  /*   * Lookup method - this could be alot more efficient but never mind.   * Also there is no attempt to honour PUBLIC, PRIVATE, etc.   */  mptr = findMethodLocal(class, name, signature);  if (mptr != NULL)    return mptr;  postExceptionMessage(einfo, JAVA_LANG(NoSuchMethodError), "%s", name->data);  return NULL;}

⌨️ 快捷键说明

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