📄 methodcalls.c
字号:
/* * methodcalls.c * Implementation of method calls * * Copyright (c) 1996, 1997 * Transvirtual Technologies, Inc. All rights reserved. * * Copyright (c) 2004 * The kaffe.org's developers. See ChangeLog for details. * * See the file "license.terms" for information on usage and redistribution * of this file. */#include "config.h"#if defined(HAVE_LIBFFI)#include "sysdepCallMethod-ffi.h"#else#define NEED_sysdepCallMethod 1#endif#include "machine.h"#include "methodcalls.h"#include "thread.h"#include "callKaffeException.h"#define TDBG(s)/* * Trampolines come in here - do the translation and replace the trampoline. */nativecode*soft_fixup_trampoline(FIXUP_TRAMPOLINE_DECL){ Method* meth; void **where; void *tramp; errorInfo info; /* FIXUP_TRAMPOLINE_INIT sets tramp and where */ FIXUP_TRAMPOLINE_INIT; tramp = *where;DBG(MOREJIT, dprintf("soft_fixup_trampoline(): meth %p, where %p, native code %p\n", meth, where, PMETHOD_NATIVECODE(meth)); ); /* If this class needs initializing, do it now. */ if (meth->class->state != CSTATE_COMPLETE && processClass(meth->class, CSTATE_COMPLETE, &info) == false) { throwError(&info); } /* Generate code on demand. */ if (!METHOD_TRANSLATED(meth)) { if (!translate(meth, &info)) { throwError(&info); } } /* * Update the origin of the trampoline and free it if necessary. * Another thread might have jumped through the same trampoline * while we were translating the method, so we have to make this * atomic. */#if defined(COMPARE_AND_EXCHANGE) if (COMPARE_AND_EXCHANGE(where, tramp, METHOD_NATIVECODE(meth))) { ; }#elif defined(ATOMIC_EXCHANGE) { void *tmp = METHOD_NATIVECODE(meth); ATOMIC_EXCHANGE(where, tmp); }#else#error "You have to define either COMPARE_AND_EXCHANGE or ATOMIC_EXCHANGE"#endif#if 0 if (METHOD_PRE_COMPILED(meth)) { nativecode* ncode = METHOD_TRUE_NCODE(meth); nativecode* ocode = METHOD_NATIVECODE(meth); METHOD_NATIVECODE(meth) = ncode; /* Update the dtable entries for all classes if this isn't a static method. */ if (meth->idx >= 0 && ocode != ncode) { meth->class->dtable->method[meth->idx] = ncode; } SET_METHOD_PRE_COMPILED(meth, 0); }#endifTDBG( dprintf("Calling %s:%s%s @ %p\n", meth->class->name->data, meth->name->data, METHOD_SIGD(meth), METHOD_NATIVECODE(meth)); )DBG(MOREJIT, dprintf("soft_fixup_trampoline(): return %p\n", METHOD_NATIVECODE(meth)); ); return (METHOD_NATIVECODE(meth));}/* * When do we need a trampoline? * * NB: this method is invoked for *all* methods a class defines or * inherits. */static boolmethodNeedsTrampoline(Method *meth){ /* A gcj class's native virtual methods always need a trampoline * since the gcj trampoline doesn't work for them. By using a * trampoline, we can fix the vtable the first time it is invoked. * * NB: If we'll ever support CNI, revisit this. */ if (CLASS_GCJ((meth)->class) && (meth->accflags & ACC_NATIVE) && meth->idx != -1) return (true); /* If the method hasn't been translated, we need a trampoline * NB: we assume the TRANSLATED flag for abstract methods produced * by gcj is cleared. */ if (!METHOD_TRANSLATED(meth)) return (true); /* We also need one if it's a static method and the class * hasn't been initialized, because such method invocation * would constitute a first active use, requiring the initializer * to be run. */ if ((meth->accflags & ACC_STATIC) && meth->class->state < CSTATE_DOING_INIT) { /* Exception: gcj's classes don't need trampolines for two * reasons: * a) call _Jv_InitClass before invoking any static method. * b) they're not compiled as indirect invocations anyway */ if (!CLASS_GCJ(meth->class)) { return (true); } } return (false);}void *engine_buildTrampoline (Method *meth, void **where, errorInfo *einfo){ void *ret; methodTrampoline *tramp; if (methodNeedsTrampoline(meth)) { /* XXX don't forget to pick those up at class gc time */ tramp = (methodTrampoline*)gc_malloc(sizeof(methodTrampoline), KGC_ALLOC_TRAMPOLINE); if (tramp == NULL) { postOutOfMemory(einfo); return (NULL); } FILL_IN_TRAMPOLINE(tramp, meth, where); /* a disadvantage of building trampolines individually---as * opposed to allocating them in a contiguous region---is that * we have flush the dcache individually for each trampoline */ FLUSH_DCACHE(tramp, tramp+1); /* for native gcj methods, we do override their * anchors so we can patch them up before they're invoked. */ if (!(CLASS_GCJ((meth)->class) && (meth->accflags & ACC_NATIVE))) { assert(*where == NULL || !!!"Cannot override trampoline anchor"); } ret = tramp; // gc_add_ref(tramp); } else { if (CLASS_GCJ((meth)->class)) { _SET_METHOD_NATIVECODE(meth, meth->ncode); } assert(METHOD_NATIVECODE(meth) != NULL); ret = METHOD_NATIVECODE(meth); } *where = ret; return ret;}voidengine_callMethod (callMethodInfo *call){ /* Clear the long value to clear the all return value. */ if (call->ret != NULL) call->ret->j = 0; sysdepCallMethod (call);}voidengine_dispatchException (uintp framePointer, uintp handler, struct Hjava_lang_Throwable *throwable){ /* I do not like the following line. I think that the interpreter * can be adapted so that we do not need to include that line in the JIT. */ THREAD_DATA()->exceptObj = NULL; CALL_KAFFE_EXCEPTION(framePointer, handler, throwable);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -