/* src/vm/jit/codegen-common.c - architecture independent code generator stuff
- Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+ C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+ E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+ J. Wenninger, Institut f. Computersprachen - TU Wien
This file is part of CACAO.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
- Contact: cacao@complang.tuwien.ac.at
+ Contact: cacao@cacaojvm.org
Authors: Reinhard Grafl
Andreas Krall
Changes: Christian Thalinger
Joseph Wenninger
+ Edwin Steiner
All functions assume the following code area / data area layout:
memory. All functions writing values into the data area return the offset
relative the begin of the code area (start of procedure).
- $Id: codegen-common.c 4194 2006-01-13 10:11:35Z twisti $
+ $Id: codegen-common.c 5404 2006-09-07 13:29:05Z christian $
*/
#include "native/jni.h"
#include "native/native.h"
-#if defined(USE_THREADS)
-# if defined(NATIVE_THREADS)
-# include "threads/native/threads.h"
-# else
-# include "threads/green/threads.h"
-# endif
+#if defined(ENABLE_THREADS)
+# include "threads/native/threads.h"
#endif
#include "vm/exceptions.h"
#include "vm/stringlocal.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/codegen-common.h"
-#include "vm/jit/disass.h"
+
+#if defined(ENABLE_DISASSEMBLER)
+# include "vm/jit/disass.h"
+#endif
+
#include "vm/jit/dseg.h"
#include "vm/jit/jit.h"
#include "vm/jit/stacktrace.h"
+#include "vm/jit/replace.h"
/* in this tree we store all method addresses *********************************/
-#if defined(__I386__) || defined(__X86_64__) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
static avl_tree *methodtree = NULL;
static s4 methodtree_comparator(const void *pc, const void *element);
-#endif
/* codegen_init ****************************************************************
void codegen_init(void)
{
-#if defined(__I386__) || defined(__X86_64__) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
/* this tree is global, not method specific */
if (!methodtree) {
methodtree = avl_create(&methodtree_comparator);
#if defined(ENABLE_JIT)
- /* insert asm_calljavafunction */
+ /* insert asm_vm_call_method */
mte = NEW(methodtree_element);
- mte->startpc = (u1 *) (ptrint) asm_calljavafunction;
- mte->endpc = (u1 *) ((ptrint) asm_calljavafunction2 - 1);
-
- avl_insert(methodtree, mte);
-
- /* insert asm_calljavafunction2 */
-
- mte = NEW(methodtree_element);
-
- mte->startpc = (u1 *) (ptrint) asm_calljavafunction2;
+ mte->startpc = (u1 *) (ptrint) asm_vm_call_method;
mte->endpc = (u1 *) ((ptrint) asm_call_jit_compiler - 1);
avl_insert(methodtree, mte);
#endif /* defined(ENABLE_JIT) */
}
-#endif /* defined(__I386__) || defined(__X86_64__) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
}
-/* codegen_setup **************************************************************
+/* codegen_setup ***************************************************************
- allocates and initialises code area, data area and references
+ Allocates and initialises code area, data area and references.
*******************************************************************************/
-void codegen_setup(methodinfo *m, codegendata *cd, t_inlining_globals *id)
+void codegen_setup(jitdata *jd)
{
+ methodinfo *m;
+ codegendata *cd;
+
+ /* get required compiler data */
+
+ m = jd->m;
+ cd = jd->cd;
+
cd->mcodebase = DMNEW(u1, MCODEINITSIZE);
+ cd->mcodeend = cd->mcodebase + MCODEINITSIZE;
cd->mcodesize = MCODEINITSIZE;
/* initialize mcode variables */
-
- cd->mcodeptr = cd->mcodebase;
- cd->mcodeend = (s4 *) (cd->mcodebase + MCODEINITSIZE);
+
+ cd->mcodeptr = cd->mcodebase;
+ cd->lastmcodeptr = cd->mcodebase;
#if defined(ENABLE_INTRP)
/* native dynamic superinstructions variables */
cd->superstarts = NULL;
}
#endif
-
- cd->dsegtop = DMNEW(u1, DSEGINITSIZE);
- cd->dsegsize = DSEGINITSIZE;
- cd->dsegtop += cd->dsegsize;
- cd->dseglen = 0;
+
+ cd->dseg = NULL;
+ cd->dseglen = 0;
cd->jumpreferences = NULL;
+
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
cd->datareferences = NULL;
- cd->xboundrefs = NULL;
- cd->xnullrefs = NULL;
- cd->xcastrefs = NULL;
- cd->xstorerefs = NULL;
- cd->xdivrefs = NULL;
- cd->xexceptionrefs = NULL;
- cd->patchrefs = NULL;
+#endif
+
+ cd->exceptionrefs = NULL;
+ cd->patchrefs = NULL;
cd->linenumberreferences = NULL;
cd->linenumbertablesizepos = 0;
cd->exceptiontable = 0;
cd->exceptiontablelength = 0;
- if (useinlining && id) {
- if (id->cumextablelength > 0) {
- cd->exceptiontablelength = id->cumextablelength;
- cd->exceptiontable =
- DMNEW(exceptiontable, id->cumextablelength + 1);
- }
-
- } else if (id && (id->method->exceptiontablelength > 0)) {
+ if (m->exceptiontablelength > 0) {
cd->exceptiontablelength = m->exceptiontablelength;
cd->exceptiontable = DMNEW(exceptiontable, m->exceptiontablelength + 1);
}
- if (id) {
- cd->maxstack = id->cummaxstack;
- cd->maxlocals = id->cumlocals;
- } else {
- cd->maxstack = m->maxstack;
- cd->maxlocals = m->maxlocals;
- }
+ cd->maxstack = m->maxstack;
+ cd->maxlocals = m->maxlocals;
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+#if defined(ENABLE_THREADS)
cd->threadcritcurrent.next = NULL;
cd->threadcritcount = 0;
#endif
}
-/* codegen_free ****************************************************************
-
- Releases temporary code and data area.
-
-*******************************************************************************/
-
-void codegen_free(methodinfo *m, codegendata *cd)
-{
-#if 0
- if (cd) {
- if (cd->mcodebase) {
- MFREE(cd->mcodebase, u1, cd->mcodesize);
- cd->mcodebase = NULL;
- }
-
- if (cd->dsegtop) {
- MFREE(cd->dsegtop - cd->dsegsize, u1, cd->dsegsize);
- cd->dsegtop = NULL;
- }
- }
-#endif
-}
-
-
/* codegen_close ***************************************************************
TODO
*******************************************************************************/
-s4 *codegen_increase(codegendata *cd, u1 *mcodeptr)
+void codegen_increase(codegendata *cd)
{
u1 *oldmcodebase;
cd->mcodesize,
cd->mcodesize * 2);
cd->mcodesize *= 2;
- cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
+ cd->mcodeend = cd->mcodebase + cd->mcodesize;
+
+ /* set new mcodeptr */
+
+ cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
#if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(ENABLE_INTRP)
/* adjust the pointer to the last patcher position */
if (cd->lastmcodeptr != NULL)
cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
#endif
-
- /* return the new mcodeptr */
-
- return (s4 *) (cd->mcodebase + (mcodeptr - oldmcodebase));
}
#endif
-void codegen_addreference(codegendata *cd, basicblock *target, void *branchptr)
+void codegen_addreference(codegendata *cd, basicblock *target)
{
s4 branchpos;
- branchpos = (u1 *) branchptr - cd->mcodebase;
+ branchpos = (u1 *) cd->mcodeptr - cd->mcodebase;
-#if !defined(ENABLE_INTRP)
- /* The interpreter uses absolute branches, so we do branch resolving */
- /* after the code and data segment move. */
+#if defined(ENABLE_JIT)
+ /* Check if the target basicblock has already a start pc, so the
+ jump is backward and we can resolve it immediately. */
- /* Check if the target basicblock has already a start pc, so the jump is */
- /* backward and we can resolve it immediately. */
+ /* The interpreter uses absolute branches, so we do branch
+ resolving after the code and data segment move. */
- if (target->mpc >= 0) {
+ if (target->mpc >= 0
+# if defined(ENABLE_INTRP)
+ && !opt_intrp
+# endif
+ )
+ {
gen_resolvebranch((u1 *) cd->mcodebase + branchpos,
branchpos,
target->mpc);
}
-/* codegen_addxboundrefs *******************************************************
+/* codegen_add_exception_ref ***************************************************
- Adds an ArrayIndexOutOfBoundsException branch to the list.
+ Adds an exception branch to the list.
*******************************************************************************/
-void codegen_addxboundrefs(codegendata *cd, void *branchptr, s4 reg)
+static void codegen_add_exception_ref(codegendata *cd, s4 reg,
+ functionptr function)
{
- s4 branchpos;
- branchref *br;
+ s4 branchpos;
+ exceptionref *eref;
- branchpos = (u1 *) branchptr - cd->mcodebase;
+ branchpos = (u1 *) cd->mcodeptr - cd->mcodebase;
- br = DNEW(branchref);
+ eref = DNEW(exceptionref);
- br->branchpos = branchpos;
- br->reg = reg;
- br->next = cd->xboundrefs;
+ eref->branchpos = branchpos;
+ eref->reg = reg;
+ eref->function = function;
+ eref->next = cd->exceptionrefs;
- cd->xboundrefs = br;
+ cd->exceptionrefs = eref;
}
-/* codegen_addxcastrefs ********************************************************
+/* codegen_add_arithmeticexception_ref *****************************************
- Adds an ClassCastException branch to the list.
+ Adds an ArithmeticException branch to the list.
*******************************************************************************/
-void codegen_addxcastrefs(codegendata *cd, void *branchptr)
+void codegen_add_arithmeticexception_ref(codegendata *cd)
{
- s4 branchpos;
- branchref *br;
-
- branchpos = (u1 *) branchptr - cd->mcodebase;
-
- br = DNEW(branchref);
-
- br->branchpos = branchpos;
- br->next = cd->xcastrefs;
-
- cd->xcastrefs = br;
+ codegen_add_exception_ref(cd, -1, STACKTRACE_inline_arithmeticexception);
}
-/* codegen_addxdivrefs *********************************************************
+/* codegen_add_arrayindexoutofboundsexception_ref ******************************
- Adds an ArithmeticException branch to the list.
+ Adds an ArrayIndexOutOfBoundsException branch to the list.
*******************************************************************************/
-void codegen_addxdivrefs(codegendata *cd, void *branchptr)
+void codegen_add_arrayindexoutofboundsexception_ref(codegendata *cd, s4 reg)
{
- s4 branchpos;
- branchref *br;
-
- branchpos = (u1 *) branchptr - cd->mcodebase;
-
- br = DNEW(branchref);
-
- br->branchpos = branchpos;
- br->next = cd->xdivrefs;
-
- cd->xdivrefs = br;
+ codegen_add_exception_ref(cd, reg,
+ STACKTRACE_inline_arrayindexoutofboundsexception);
}
-/* codegen_addxstorerefs *******************************************************
+/* codegen_add_arraystoreexception_ref *****************************************
Adds an ArrayStoreException branch to the list.
*******************************************************************************/
-void codegen_addxstorerefs(codegendata *cd, void *branchptr)
+void codegen_add_arraystoreexception_ref(codegendata *cd)
{
- s4 branchpos;
- branchref *br;
+ codegen_add_exception_ref(cd, -1, STACKTRACE_inline_arraystoreexception);
+}
- branchpos = (u1 *) branchptr - cd->mcodebase;
- br = DNEW(branchref);
+/* codegen_add_classcastexception_ref ******************************************
- br->branchpos = branchpos;
- br->next = cd->xstorerefs;
+ Adds an ClassCastException branch to the list.
+
+*******************************************************************************/
- cd->xstorerefs = br;
+void codegen_add_classcastexception_ref(codegendata *cd, s4 reg)
+{
+ codegen_add_exception_ref(cd, reg, STACKTRACE_inline_classcastexception);
}
-/* codegen_addxnullrefs ********************************************************
+/* codegen_add_nullpointerexception_ref ****************************************
Adds an NullPointerException branch to the list.
*******************************************************************************/
-void codegen_addxnullrefs(codegendata *cd, void *branchptr)
+void codegen_add_nullpointerexception_ref(codegendata *cd)
{
- s4 branchpos;
- branchref *br;
-
- branchpos = (u1 *) branchptr - cd->mcodebase;
-
- br = DNEW(branchref);
-
- br->branchpos = branchpos;
- br->next = cd->xnullrefs;
-
- cd->xnullrefs = br;
+ codegen_add_exception_ref(cd, -1, STACKTRACE_inline_nullpointerexception);
}
-/* codegen_addxexceptionsrefs **************************************************
+/* codegen_add_fillinstacktrace_ref ********************************************
- Adds an common exception branch to the list.
+ Adds a fillInStackTrace branch to the list.
*******************************************************************************/
-void codegen_addxexceptionrefs(codegendata *cd, void *branchptr)
+void codegen_add_fillinstacktrace_ref(codegendata *cd)
{
- s4 branchpos;
- branchref *br;
-
- branchpos = (u1 *) branchptr - cd->mcodebase;
-
- br = DNEW(branchref);
-
- br->branchpos = branchpos;
- br->next = cd->xexceptionrefs;
-
- cd->xexceptionrefs = br;
+ codegen_add_exception_ref(cd, -1, STACKTRACE_inline_fillInStackTrace);
}
*******************************************************************************/
-void codegen_addpatchref(codegendata *cd, voidptr branchptr,
- functionptr patcher, voidptr ref, s4 disp)
+void codegen_addpatchref(codegendata *cd, functionptr patcher, voidptr ref,
+ s4 disp)
{
patchref *pr;
s4 branchpos;
- branchpos = (u1 *) branchptr - cd->mcodebase;
+ branchpos = cd->mcodeptr - cd->mcodebase;
pr = DNEW(patchref);
the basic block code generation is completed, we check the
range and maybe generate some nop's. */
- cd->lastmcodeptr = ((u1 *) branchptr) + PATCHER_CALL_SIZE;
+ cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
#endif
}
-#if defined(__I386__) || defined(__X86_64__) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
/* methodtree_comparator *******************************************************
- XXX
+ Comparator function used for the AVL tree of methods.
*******************************************************************************/
/* codegen_insertmethod ********************************************************
- XXX
+ Insert the machine code range of a method into the AVL tree of methods.
*******************************************************************************/
}
-/* codegen_findmethod **********************************************************
+/* codegen_get_pv_from_pc ******************************************************
- XXX
+ Find the PV for the given PC by searching in the AVL tree of
+ methods.
*******************************************************************************/
-u1 *codegen_findmethod(u1 *pc)
+u1 *codegen_get_pv_from_pc(u1 *pc)
{
methodtree_element mtepc;
methodtree_element *mte;
mte = avl_find(methodtree, &mtepc);
- if (!mte) {
- printf("Cannot find Java function at %p\n", (void *) (ptrint) pc);
- assert(0);
+ if (mte == NULL) {
+ /* No method was found. Let's dump a stacktrace. */
+
+ log_println("We received a SIGSEGV and tried to handle it, but we were");
+ log_println("unable to find a Java method at:");
+ log_println("");
+#if SIZEOF_VOID_P == 8
+ log_println("PC=0x%016lx", pc);
+#else
+ log_println("PC=0x%08x", pc);
+#endif
+ log_println("");
+ log_println("Dumping the current stacktrace:");
+
+ stacktrace_dump_trace();
- throw_cacao_exception_exit(string_java_lang_InternalError,
- "Cannot find Java function at %p", pc);
+ vm_abort("Exiting...");
}
return mte->startpc;
}
-#endif /* defined(__I386__) || defined(__X86_64__) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
+
+
+/* codegen_get_pv_from_pc_nocheck **********************************************
+
+ Find the PV for the given PC by searching in the AVL tree of
+ methods. This method does not check the return value and is used
+ by the profiler.
+
+*******************************************************************************/
+
+u1 *codegen_get_pv_from_pc_nocheck(u1 *pc)
+{
+ methodtree_element mtepc;
+ methodtree_element *mte;
+
+ /* allocation of the search structure on the stack is much faster */
+
+ mtepc.startpc = pc;
+ mtepc.endpc = pc;
+
+ mte = avl_find(methodtree, &mtepc);
+
+ if (mte == NULL)
+ return NULL;
+ else
+ return mte->startpc;
+}
/* codegen_finish **************************************************************
*******************************************************************************/
-void codegen_finish(methodinfo *m, codegendata *cd, s4 mcodelen)
+void codegen_finish(jitdata *jd)
{
-#if 0
- s4 mcodelen;
+ codeinfo *code;
+ codegendata *cd;
+ s4 mcodelen;
+#if defined(ENABLE_INTRP)
+ s4 ncodelen;
#endif
+ s4 alignedmcodelen;
+ jumpref *jr;
+ u1 *epoint;
+ s4 extralen;
+ s4 alignedlen;
+
+ /* get required compiler data */
+
+ code = jd->code;
+ cd = jd->cd;
+
+ /* prevent compiler warning */
+
#if defined(ENABLE_INTRP)
- s4 ncodelen;
+ ncodelen = 0;
#endif
- s4 alignedmcodelen;
- jumpref *jr;
- u1 *epoint;
- s4 extralen;
- s4 alignedlen;
-
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
- extralen = sizeof(threadcritnode) * cd->threadcritcount;
+
+ /* calculate the code length */
+
+ mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
+
+#if defined(ENABLE_THREADS)
+ extralen = sizeof(critical_section_node_t) * cd->threadcritcount;
#else
extralen = 0;
#endif
}
#endif
-#if 0
- mcodelen = cd->mcodeptr - cd->mcodebase;
-#endif
alignedmcodelen = ALIGN(mcodelen, MAX_ALIGN);
#if defined(ENABLE_INTRP)
- if (opt_intrp) {
+ if (opt_intrp)
ncodelen = cd->ncodeptr - cd->ncodebase;
+ else {
+ ncodelen = 0; /* avoid compiler warning */
}
#endif
/* allocate new memory */
- m->mcodelength = mcodelen + cd->dseglen;
- m->mcode = CNEW(u1, alignedlen + extralen);
+ code->mcodelength = mcodelen + cd->dseglen;
+ code->mcode = CNEW(u1, alignedlen + extralen);
- /* copy data and code to their new location */
+ /* set the entrypoint of the method */
+
+ assert(code->entrypoint == NULL);
+ code->entrypoint = epoint = (code->mcode + cd->dseglen);
+
+ /* fill the data segment (code->entrypoint must already be set!) */
+
+ dseg_finish(jd);
- MCOPY((void *) m->mcode, cd->dsegtop - cd->dseglen, u1, cd->dseglen);
- MCOPY((void *) (m->mcode + cd->dseglen), cd->mcodebase, u1, mcodelen);
+ /* copy code to the new location */
- m->entrypoint = epoint = (m->mcode + cd->dseglen);
+ MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
#if defined(ENABLE_INTRP)
/* relocate native dynamic superinstruction code (if any) */
if (opt_intrp) {
- cd->mcodebase = m->entrypoint;
+ cd->mcodebase = code->entrypoint;
if (ncodelen > 0) {
- u1 *ncodebase = m->mcode + cd->dseglen + alignedmcodelen;
- MCOPY((void *)ncodebase, cd->ncodebase, u1, ncodelen);
+ u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
+
+ MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
+
+ /* flush the instruction and data caches */
+
+ md_cacheflush(ncodebase, ncodelen);
/* set some cd variables for dynamic_super_rerwite */
{
linenumberref *lr;
ptrint lrtlen = 0;
+ ptrint target;
for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
lrtlen++;
- *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) =
- (functionptr) ((ptrint) epoint + (ptrint) lr->targetmpc);
+ target = lr->targetmpc;
+ /* if the entry contains an mcode pointer (normal case), resolve it */
+ /* (see doc/inlining_stacktrace.txt for details) */
+ if (lr->linenumber >= -2) {
+ target += (ptrint) epoint;
+ }
+ *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) =
+ (functionptr) target;
}
*((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
*((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
}
-#if defined(__I386__) || defined(__X86_64__) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
- /* add method into methodtree to find the entrypoint */
+ /* replacement point resolving */
+ {
+ int i;
+ rplpoint *rp;
- codegen_insertmethod(m->entrypoint, m->entrypoint + mcodelen);
-#endif
+ rp = code->rplpoints;
+ for (i=0; i<code->rplpointcount; ++i, ++rp) {
+ rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
+ rp->outcode = (u1*) ((ptrint) epoint + (ptrint) rp->outcode);
+ }
+ }
-#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__)
- {
- dataref *dr;
+ /* add method into methodtree to find the entrypoint */
- /* data segment references resolving */
+ codegen_insertmethod(code->entrypoint, code->entrypoint + mcodelen);
- for (dr = cd->datareferences; dr != NULL; dr = dr->next)
- *((u1 **) (epoint + dr->datapos - SIZEOF_VOID_P)) = epoint;
- }
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
+ /* resolve data segment references */
+
+ dseg_resolve_datareferences(jd);
#endif
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+#if defined(ENABLE_THREADS)
{
- threadcritnode *n = (threadcritnode *) ((ptrint) m->mcode + alignedlen);
+ critical_section_node_t *n = (critical_section_node_t *) ((ptrint) code->mcode + alignedlen);
s4 i;
- threadcritnodetemp *nt = cd->threadcrit;
+ codegen_critical_section_t *nt = cd->threadcrit;
for (i = 0; i < cd->threadcritcount; i++) {
- n->mcodebegin = (u1 *) (ptrint) m->mcode + nt->mcodebegin;
- n->mcodeend = (u1 *) (ptrint) m->mcode + nt->mcodeend;
- n->mcoderestart = (u1 *) (ptrint) m->mcode + nt->mcoderestart;
- thread_registercritical(n);
+ n->mcodebegin = (u1 *) (ptrint) code->mcode + nt->mcodebegin;
+ n->mcodeend = (u1 *) (ptrint) code->mcode + nt->mcodeend;
+ n->mcoderestart = (u1 *) (ptrint) code->mcode + nt->mcoderestart;
+ critical_register_critical_section(n);
n++;
nt = nt->next;
}
}
#endif
+
+ /* flush the instruction and data caches */
+
+ md_cacheflush(code->mcode, code->mcodelength);
}
Wrapper for createnativestub.
+ Returns:
+ the codeinfo representing the stub code.
+
*******************************************************************************/
-u1 *codegen_createnativestub(functionptr f, methodinfo *m)
+codeinfo *codegen_createnativestub(functionptr f, methodinfo *m)
{
- codegendata *cd;
- registerdata *rd;
- t_inlining_globals *id;
- s4 dumpsize;
- methoddesc *md;
- methoddesc *nmd;
- s4 nativeparams;
+ jitdata *jd;
+ codeinfo *code;
+ s4 dumpsize;
+ methoddesc *md;
+ methoddesc *nmd;
+ s4 nativeparams;
/* mark dump memory */
dumpsize = dump_size();
- cd = DNEW(codegendata);
- rd = DNEW(registerdata);
- id = DNEW(t_inlining_globals);
+ jd = DNEW(jitdata);
- /* setup code generation stuff */
+ jd->m = m;
+ jd->cd = DNEW(codegendata);
+ jd->rd = DNEW(registerdata);
- inlining_setup(m, id);
+ /* Allocate codeinfo memory from the heap as we need to keep them. */
+
+ jd->code = code_codeinfo_new(m); /* XXX check allocation */
+
+ /* get required compiler data */
+
+ code = jd->code;
+
+ /* set the flags for the current JIT run */
+
+ if (opt_prof)
+ jd->flags |= JITDATA_FLAG_INSTRUMENT;
+
+ if (opt_verbosecall)
+ jd->flags |= JITDATA_FLAG_VERBOSECALL;
+
+ /* setup code generation stuff */
#if defined(ENABLE_JIT)
# if defined(ENABLE_INTRP)
if (!opt_intrp)
# endif
- reg_setup(m, rd, id);
+ reg_setup(jd);
#endif
- codegen_setup(m, cd, id);
-
+ codegen_setup(jd);
+
/* create new method descriptor with additional native parameters */
md = m->parseddesc;
#if defined(ENABLE_JIT)
# if defined(ENABLE_INTRP)
if (opt_intrp)
- m->entrypoint = intrp_createnativestub(f, m, cd, rd, nmd);
+ code->entrypoint = intrp_createnativestub(f, jd, nmd);
else
# endif
- m->entrypoint = createnativestub(f, m, cd, rd, nmd);
+ code->entrypoint = createnativestub(f, jd, nmd);
#else
- m->entrypoint = intrp_createnativestub(f, m, cd, rd, nmd);
+ code->entrypoint = intrp_createnativestub(f, jd, nmd);
#endif
#if defined(ENABLE_STATISTICS)
if (opt_stat)
- count_nstub_len += m->mcodelength;
+ count_nstub_len += code->mcodelength;
#endif
+#if !defined(NDEBUG)
/* disassemble native stub */
if (opt_shownativestub) {
+#if defined(ENABLE_DISASSEMBLER)
codegen_disassemble_nativestub(m,
- (u1 *) (ptrint) m->entrypoint,
- (u1 *) (ptrint) m->entrypoint + (m->mcodelength - cd->dseglen));
+ (u1 *) (ptrint) code->entrypoint,
+ (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
+#endif
/* show data segment */
if (opt_showddatasegment)
- dseg_display(m, cd);
+ dseg_display(jd);
}
+#endif /* !defined(NDEBUG) */
/* release memory */
dump_release(dumpsize);
- /* return native stub entry point */
+ /* return native stub code */
- return m->entrypoint;
+ return code;
}
*******************************************************************************/
+#if defined(ENABLE_DISASSEMBLER)
void codegen_disassemble_nativestub(methodinfo *m, u1 *start, u1 *end)
{
printf("Native stub: ");
- utf_fprint_classname(stdout, m->class->name);
+ utf_fprint_printable_ascii_classname(stdout, m->class->name);
printf(".");
- utf_fprint(stdout, m->name);
- utf_fprint(stdout, m->descriptor);
+ utf_fprint_printable_ascii(stdout, m->name);
+ utf_fprint_printable_ascii(stdout, m->descriptor);
printf("\n\nLength: %d\n\n", (s4) (end - start));
DISASSEMBLE(start, end);
}
+#endif
/* codegen_start_native_call ***************************************************
/* codegen_finish_native_call **************************************************
Removes the stuff required for a native (JNI) function call.
+ Additionally it checks for an exceptions and in case, get the
+ exception object and clear the pointer.
*******************************************************************************/
-void codegen_finish_native_call(u1 *datasp)
+java_objectheader *codegen_finish_native_call(u1 *datasp)
{
- stackframeinfo *sfi;
- stackframeinfo **psfi;
- localref_table *lrt;
- s4 localframes;
+ stackframeinfo *sfi;
+ stackframeinfo **psfi;
+ localref_table *lrt;
+ localref_table *plrt;
+ s4 localframes;
+ java_objectheader *e;
/* get data structures from stack */
lrt = LOCALREFTABLE;
- /* got through all current local frames */
+ /* release all current local frames */
for (localframes = lrt->localframes; localframes >= 1; localframes--) {
- lrt = lrt->prev;
+ /* get previous frame */
+
+ plrt = lrt->prev;
+
+ /* Clear all reference entries (only for tables allocated on
+ the Java heap). */
+
+ if (localframes > 1)
+ MSET(&lrt->refs[0], 0, java_objectheader*, lrt->capacity);
+
+ lrt->prev = NULL;
+
+ /* set new local references table */
+
+ lrt = plrt;
}
/* now store the previous local frames in the thread structure */
LOCALREFTABLE = lrt;
+
+ /* get the exception and return it */
+
+ e = exceptions_get_and_clear_exception();
+
+ return e;
}
}
-/* reg_of_var ******************************************************************
+/* codegen_reg_of_var **********************************************************
This function determines a register, to which the result of an
operation should go, when it is ultimatively intended to store the
*******************************************************************************/
-s4 reg_of_var(registerdata *rd, stackptr v, s4 tempregnum)
+#if defined(NEW_VAR)
+s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
+{
+
+#if 0
+ /* Do we have to generate a conditional move? Yes, then always
+ return the temporary register. The real register is identified
+ during the store. */
+
+ if (opcode & ICMD_CONDITION_MASK)
+ return tempregnum;
+#endif
+
+ if (!(v->flags & INMEMORY)) {
+#if defined(__ARM__) && defined(__ARMEL__)
+ if (IS_2_WORD_TYPE(v->type) && (GET_HIGH_REG(v->regoff) == REG_SPLIT))
+ return(PACK_REGS(GET_LOW_REG(var->regoff),
+ GET_HIGH_REG(tempregnum)));
+#endif
+#if defined(__ARM__) && defined(__ARMEB__)
+ if (IS_2_WORD_TYPE(v->type) && (GET_LOW_REG(v->regoff) == REG_SPLIT))
+ return(PACK_REGS(GET_LOW_REG(tempregnum),
+ GET_HIGH_REG(var->regoff)));
+#endif
+ return(v->regoff);
+ }
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_spills_read++;
+#endif
+
+ return tempregnum;
+}
+#else
+s4 codegen_reg_of_var(u2 opcode, stackptr v, s4 tempregnum)
{
varinfo *var;
+#if 0
+ /* Do we have to generate a conditional move? Yes, then always
+ return the temporary register. The real register is identified
+ during the store. */
+
+ if (opcode & ICMD_CONDITION_MASK)
+ return tempregnum;
+#endif
+
switch (v->varkind) {
case TEMPVAR:
if (!(v->flags & INMEMORY))
return tempregnum;
}
+#endif
+
+
+/* codegen_reg_of_dst **********************************************************
+
+ This function determines a register, to which the result of an
+ operation should go, when it is ultimatively intended to store the
+ result in iptr->dst.var. If dst.var is assigned to an actual
+ register, this register will be returned. Otherwise (when it is
+ spilled) this function returns tempregnum. If not already done,
+ regoff and flags are set in the stack location.
+
+ On ARM we have to check if a long/double variable is splitted
+ across reg/stack (HIGH_REG == REG_SPLIT). We return the actual
+ register of dst.var for LOW_REG and the tempregnum for HIGH_REG in such
+ cases. (michi 2005/07/24)
+
+*******************************************************************************/
+
+s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
+{
+ varinfo *v = &jd->var[iptr->dst.varindex];
+
+ if (!(v->flags & INMEMORY)) {
+
+#if defined(__ARM__) && defined(__ARMEL__)
+ if (IS_2_WORD_TYPE(v->type) && (GET_HIGH_REG(v->regoff) == REG_SPLIT))
+ return(PACK_REGS(GET_LOW_REG(v->regoff),
+ GET_HIGH_REG(tempregnum)));
+#endif
+#if defined(__ARM__) && defined(__ARMEB__)
+ if (IS_2_WORD_TYPE(v->type) && (GET_LOW_REG(v->regoff) == REG_SPLIT))
+ return(PACK_REGS(GET_LOW_REG(tempregnum),
+ GET_HIGH_REG(v->regoff)));
+#endif
+ return (v->regoff);
+ }
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_spills_read++;
+#endif
+
+ /* Not necessary anymore - either v is inmemory or not. Setting again */
+ /* won't change anything */
+ v->flags |= INMEMORY;
+
+ return tempregnum;
+}
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+#if defined(ENABLE_THREADS)
void codegen_threadcritrestart(codegendata *cd, int offset)
{
cd->threadcritcurrent.mcoderestart = offset;
{
cd->threadcritcurrent.next = cd->threadcrit;
cd->threadcritcurrent.mcodeend = offset;
- cd->threadcrit = DNEW(threadcritnodetemp);
+ cd->threadcrit = DNEW(codegen_critical_section_t);
*(cd->threadcrit) = cd->threadcritcurrent;
cd->threadcritcount++;
}
* c-basic-offset: 4
* tab-width: 4
* End:
+ * vim:noexpandtab:sw=4:ts=4:
*/