lookup.c
来自「kaffe Java 解释器语言,源码,Java的子集系统,开放源代码」· C语言 代码 · 共 377 行
C
377 行
/* * 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 "kaffe/jtypes.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"static void throwAbstractMethodError(void);/* * 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 loadClass, 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 = 0; call->method = 0; call->signature = 0; call->name = 0; call->cname = 0; pool = CLASS_CONSTANTS(this); 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); name = WORD2UTF(pool->data[NAMEANDTYPE_NAME(ni, pool)]); sig = WORD2UTF(pool->data[NAMEANDTYPE_SIGNATURE(ni, pool)]); call->name = name; call->signature = sig; if (loadClass == 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 = 0; /* Find method - we don't use findMethod(...) yet since this * will initialise our class (and we don't want to do that). */ mptr = 0; for (; class != 0; class = class->superclass) { mptr = findMethodLocal(class, name, sig); if (mptr != NULL) { call->method = mptr; break; } } /* If we've not found anything and we're searching interfaces, * search them too. */ if (mptr == 0 && isSpecial == 2) { class = call->class; for (i = class->total_interface_len - 1; i >= 0; i--) { mptr = findMethodLocal(class->interfaces[i], name, sig); if (mptr != 0) { call->method = mptr; break; } } } } /* Calculate in's and out's */ countInsAndOuts(sig->data, &call->in, &call->out, &call->rettype);DBG(MLOOKUP, if (loadClass) 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; int iLockRoot; pool = CLASS_CONSTANTS(this); 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; } 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 isStatic, fieldInfo* ret, errorInfo *einfo){ constants* pool; constIndex ci; constIndex ni; Field* field; Hjava_lang_Class* class; ret->field = 0; ret->class = 0; 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->cname = WORD2UTF(pool->data[ci]); 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) { 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); ) field = lookupClassField(class, WORD2UTF(pool->data[NAMEANDTYPE_NAME(ni, pool)]), isStatic, 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 = CLASS_METHODS(class); --n >= 0; ++mptr) { if (utf8ConstEqual (name, mptr->name) && utf8ConstEqual (signature, METHOD_SIG(mptr))) { if ((mptr->accflags & ACC_ABSTRACT) != 0 && !CLASS_IS_INTERFACE(mptr->class)) {#if defined(TRANSLATOR) if(GC_getObjectIndex(main_collector, METHOD_NATIVECODE(mptr)) == GC_ALLOC_DISPATCHTABLE) { /* 'nc' is workaround for GCC 2.7.2 ?: bug */ void *nc; nc = METHOD_NATIVECODE(mptr); KFREE(nc); }#endif SET_METHOD_NATIVECODE(mptr, (void*)throwAbstractMethodError); mptr->accflags |= ACC_NATIVE; }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 (0); } /* * Lookup method - this could be alot more efficient but never mind. * Also there is no attempt to honour PUBLIC, PRIVATE, etc. */ for (; class != 0; class = class->superclass) { Method* mptr = findMethodLocal(class, name, signature); if (mptr != NULL) { return mptr; } } postExceptionMessage(einfo, JAVA_LANG(NoSuchMethodError), "%s", name->data); return (0);}staticvoidthrowAbstractMethodError(void){ throwException(AbstractMethodError);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?