📄 soft.c
字号:
/* * soft.c * Soft instruction support. * * 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"#define TDBG(s)#include "config.h"#include "config-std.h"#include "config-math.h"#include "config-mem.h"#include <stdarg.h>#include "gtypes.h"#include "bytecode.h"#include "slots.h"#include "access.h"#include "object.h"#include "constants.h"#include "errors.h"#include "classMethod.h"#include "baseClasses.h"#include "lookup.h"#include "exception.h"#include "locks.h"#include "soft.h"#include "external.h"#include "thread.h"#include "baseClasses.h"#include "itypes.h"#include "machine.h"#include "fp.h"#include "jvmpi_kaffe.h"voidsoft_null_call(void){}/* * soft_new */void*soft_new(Hjava_lang_Class* c){ Hjava_lang_Object* obj; errorInfo info; if (c->state != CSTATE_COMPLETE && processClass(c, CSTATE_COMPLETE, &info) == false) { goto bad; } obj = newObjectChecked(c, &info); if (obj == 0) { goto bad; }DBG(NEWINSTR, dprintf("New object of type %s (%d,%p)\n", c->name->data, c->bfsize, obj); ) return (obj);bad: throwError(&info); return (0);}/* * soft_newarray */void*soft_newarray(jint type, jint size){ Hjava_lang_Object* obj; errorInfo info; if (size < 0) { throwException(NegativeArraySizeException); } obj = newArrayChecked(TYPE_CLASS(type), size, &info); if (obj == 0) { throwError(&info); }DBG(NEWINSTR, dprintf("New array of %s [%d] (%p)\n", TYPE_CLASS(type)->name->data, size, obj); ) return (obj);}/* * soft_anewarray */void*soft_anewarray(Hjava_lang_Class* elclass, jint size){ Hjava_lang_Object* obj; errorInfo info; if (size < 0) { throwException(NegativeArraySizeException); } obj = newArrayChecked(elclass, size, &info); if (obj == 0) { throwError(&info); }DBG(NEWINSTR, dprintf("New array object [%d] of %s (%p)\n", size, elclass->name->data, obj); ) return (obj);}/* * soft_multianewarray. */#define MAXDIMS 16#if defined(INTERPRETER)void*soft_multianewarray(Hjava_lang_Class* class, jint dims, slots* args){ errorInfo einfo; int array[MAXDIMS]; Hjava_lang_Object* obj; jint arg; int i; int* arraydims; if (dims < MAXDIMS) { arraydims = array; } else { arraydims = checkPtr(KCALLOC(dims+1, sizeof(int))); } /* stack grows up, so move to the first dimension */ args -= dims-1; /* Extract the dimensions into an array */ for (i = 0; i < dims; i++) { arg = args[i].v.tint; if (arg < 0) { throwException(NegativeArraySizeException); } arraydims[i] = arg; } arraydims[i] = -1; /* Mmm, okay now build the array using the wonders of recursion */ obj = newMultiArrayChecked(class, arraydims, &einfo); if (arraydims != array) { KFREE(arraydims); } if (!obj) { throwError(&einfo); } /* Return the base object */ return (obj);}#endif#if defined(TRANSLATOR)void*soft_vmultianewarray(Hjava_lang_Class* class, jint dims, va_list ap){ errorInfo einfo; int array[MAXDIMS]; int i; jint arg; Hjava_lang_Object* obj; int* arraydims; if (dims < MAXDIMS-1) { arraydims = array; } else { arraydims = checkPtr(KCALLOC(dims+1, sizeof(int))); } /* Extract the dimensions into an array */ for (i = 0; i < dims; i++) { arg = va_arg(ap, jint); if (arg < 0) { if (arraydims != array) { KFREE(arraydims); } throwException(NegativeArraySizeException); } arraydims[i] = arg; } arraydims[i] = -1; /* Mmm, okay now build the array using the wonders of recursion */ obj = newMultiArrayChecked(class, arraydims, &einfo); if (arraydims != array) { KFREE(arraydims); } if (!obj) { throwError(&einfo); } /* Return the base object */ return (obj);}void*soft_multianewarray(Hjava_lang_Class* class, jint dims, ...){ void* obj; va_list ap; va_start(ap, dims); obj = soft_vmultianewarray(class, dims, ap); va_end(ap); return (obj);}#endif/* * soft_lookupinterfacemethod. */void*soft_lookupinterfacemethod(Hjava_lang_Object* obj, Hjava_lang_Class* ifclass, int idx){ Hjava_lang_Class* cls; Method* meth; void* ncode; register int i; register short* implementors; cls = OBJECT_CLASS(obj); implementors = ifclass->implementors; i = cls->impl_index;#if 1 /* it should never be necessary to initialize the class here * cause we're invoking a method on an existing, created object */ assert (cls->state >= CSTATE_USABLE);#else /* initialize class if necessary */ if (cls->state < CSTATE_USABLE) { errorInfo info; if (processClass(cls, CSTATE_COMPLETE, &info) == false) { throwError(&info); } }#endif /* handle invocations on java.lang.Object methods via INVOKEINTERFACE */ if (implementors == 0 || i > implementors[0]) { goto notfound; } /* skip word at the beginning of itable2dtable */ ncode = cls->itable2dtable[implementors[i] + idx + 1]; /* This means this class does not implement this interface method * at all. This is something we detect at the time the interface * dispatch table is built. To avoid this test, we could instead * point at a nosuchmethod routine there. However, we would have * to find a way to pass along the information which methods it * is that's missing (or create multiple nosuch_method routines, * given that they should be rare---minus possible DoS.) */ if (ncode == (void *)-1) { goto notfound; } assert(ncode != NULL); return (ncode);notfound: /* * Compilers following the latest version of the JLS emit a * INVOKEINTERFACE instruction for methods that aren't defined in * an interface, but inherited from Object. * * In this case, the JVM must * a) check that the object really implements the interface given * b) find and invoke the method on object. * * The best way to jit that would be a checkcast <interface_type> * followed by an INVOKEVIRTUAL. * * For now, we simply detect the case where an object method is called * and find it by hand using its (name, signature). */ if (ifclass == ObjectClass) { Method* objm = CLASS_METHODS(ifclass) + idx; errorInfo info; meth = findMethod(cls, objm->name, METHOD_SIG(objm), &info); if (meth == 0) { throwError(&info); } return (METHOD_INDIRECTMETHOD(meth)); } meth = CLASS_METHODS(ifclass) + idx; soft_nosuchmethod(cls, meth->name, METHOD_SIG(meth)); return (0);}inlinejintinstanceof_class(Hjava_lang_Class* c, Hjava_lang_Class* oc){ Hjava_lang_Class* tc; /* Check for superclass matches */ for (tc = oc->superclass; tc != 0; tc = tc->superclass) { if (c == tc) { return (1); } } return (0);}inlinejintinstanceof_interface(Hjava_lang_Class* c, Hjava_lang_Class* oc){ int i; /* Check 'total' interface list */ for (i = oc->total_interface_len - 1; i >= 0; i--) { if (c == oc->interfaces[i]) { return (1); } } return (0);}inlinejintinstanceof_array(Hjava_lang_Class* c, Hjava_lang_Class* oc){ /* Skip as many arrays of arrays as we can. We stop when we find * a base class in either. */ while (CLASS_IS_ARRAY(c) && CLASS_IS_ARRAY(oc)) { c = CLASS_ELEMENT_TYPE(c); oc = CLASS_ELEMENT_TYPE(oc); } /* If we are still casting to an array then we have failed already */ if (CLASS_IS_ARRAY(c)) return (0); /* If a base type, they must match exact. */ if (CLASS_IS_PRIMITIVE(c)) { return (c == oc); } /* Casting to an object of some description. */ if (CLASS_IS_ARRAY(oc)) { /* The only thing we can cast an array to is java/lang/Object. * Checking this here willl save time. */ return (c == ObjectClass); } /* Cannot cast to a primitive class. */ if (CLASS_IS_PRIMITIVE(oc)) { return (0); } /* Casting one object to another. */ return (instanceof(c, oc));}jintinstanceof(Hjava_lang_Class* c, Hjava_lang_Class* oc){ /* Handle the simplest case first - they are the same */ if (c == oc) { return (1); } /* Else if an array check that */ else if (CLASS_IS_ARRAY(c)) { return (instanceof_array(c, oc)); } /* Else if an interface check that */ else if (CLASS_IS_INTERFACE(c)) { return (instanceof_interface(c, oc)); } /* Else is must to a class */ else { return (instanceof_class(c, oc)); }}/* * soft_instanceof. */jintsoft_instanceof(Hjava_lang_Class* c, Hjava_lang_Object* o){ /* Null object are never instances of anything */ if (o == 0) { return (0); } return (instanceof(c, OBJECT_CLASS(o)));}/* * soft_checkcast. */void*soft_checkcast(Hjava_lang_Class* c, Hjava_lang_Object* o){ if (o != 0 && !instanceof(c, OBJECT_CLASS(o))) { /* * Let's be a bit more informative as to why the class * cast exception happened. */ Hjava_lang_Throwable* ccexc; const char *fromtype = CLASS_CNAME(OBJECT_CLASS(o)); const char *totype = CLASS_CNAME(c); char *buf; if (c->loader != OBJECT_CLASS(o)->loader) { const char *toloader = c->loader?CLASS_CNAME(OBJECT_CLASS((Hjava_lang_Object *)c->loader)):"bootstrap"; const char *fromloader = OBJECT_CLASS(o)->loader?CLASS_CNAME(OBJECT_CLASS((Hjava_lang_Object *)OBJECT_CLASS(o)->loader)):"bootstrap"; char *format = "can't cast `%s' (%s@%p) to `%s' (%s@%p)"; buf = checkPtr(KMALLOC(strlen(fromtype) + 12 + strlen(fromloader)+ + strlen(totype) + 12 + strlen(toloader) + strlen(format))); sprintf(buf, format, fromtype, fromloader, OBJECT_CLASS(o)->loader, totype, toloader, c->loader); } else { char* format = "can't cast `%s' to `%s'"; buf = checkPtr(KMALLOC(strlen(fromtype)+strlen(totype)+strlen(format))); sprintf(buf, format, fromtype, totype); } ccexc = ClassCastException(buf); KFREE(buf); throwException(ccexc); } return (o);}/* * soft_athrow. */voidsoft_athrow(Hjava_lang_Object* o){ if (o == 0) { soft_nullpointer(); } else { /* NB: This will keep the stacktrace that was built * when the exception was constructed. * If you wanted a new stacktrace corresponding to the * site where the exception is thrown, you'd use * `throwException' instead. However, this would slow down * exceptions because two stacktrace have to be constructed. */ throwExternalException((Hjava_lang_Throwable*)o); }}/* * soft_badarrayindex. */voidsoft_badarrayindex(void){ throwException(ArrayIndexOutOfBoundsException);}/* * soft_nullpointer. */voidsoft_nullpointer(void){ throwException(NullPointerException);}/* * soft_divzero. */voidsoft_divzero(void){ throwException(ArithmeticException);}/* * soft_stackoverflow. */voidsoft_stackoverflow(void){ Hjava_lang_Throwable *th; errorInfo einfo; /* XXX Dear lord this sucks! */ jthread_relaxstack(1); th = (Hjava_lang_Throwable *) newObjectChecked(javaLangStackOverflowError, &einfo); jthread_relaxstack(0); throwException(th);}/* * soft_nosuchclass. */voidsoft_nosuchclass(Utf8Const* c){ char buf[256]; sprintf(buf, "%.80s", c->data); throwException(NoClassDefFoundError(buf));}/* * soft_nosuchmethod. */voidsoft_nosuchmethod(Hjava_lang_Class* c, Utf8Const* n, Utf8Const* s){ char buf[256]; sprintf(buf, "%.80s.%.80s%.80s", CLASS_CNAME(c), n->data, s->data); throwException(NoSuchMethodError(buf));}/* * soft_nosuchfield. */voidsoft_nosuchfield(Utf8Const* c, Utf8Const* n){ char buf[256]; sprintf(buf, "%.100s.%.100s", c->data, n->data); throwException(NoSuchFieldError(buf));}voidsoft_linkage(Utf8Const *c, Utf8Const* n){ char buf[256]; sprintf(buf, "%.100s.%.100s", c->data, n->data); throwException(LinkageError(buf));}voidsoft_illegalaccess(Utf8Const *c, Utf8Const* n){ char buf[256]; sprintf(buf, "%.100s.%.100s", c->data, n->data); throwException(IllegalAccessError(buf));}/* * soft_incompatibleclasschange. */voidsoft_incompatibleclasschange(Utf8Const *c, Utf8Const* n){ char buf[256]; sprintf(buf, "%.100s.%.100s", c->data, n->data); throwException(IncompatibleClassChangeError(buf));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -