/* src/vm/jit/codegen-common.c - architecture independent code generator stuff
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+ Copyright (C) 1996-2005, 2006, 2007 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
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- 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 5703 2006-10-05 20:21:04Z edwin $
+ $Id: codegen-common.c 7246 2007-01-29 18:49:05Z twisti $
*/
#include "vm/types.h"
#if defined(ENABLE_JIT)
-/* this is required for gen_resolvebranch and PATCHER_CALL_SIZE */
+/* this is required PATCHER_CALL_SIZE */
# include "codegen.h"
#endif
#endif
#include "mm/memory.h"
+
#include "toolbox/avl.h"
+#include "toolbox/list.h"
#include "toolbox/logging.h"
+
#include "native/jni.h"
#include "native/native.h"
#endif
#include "vm/exceptions.h"
-#include "vm/method.h"
-#include "vm/options.h"
-#include "vm/statistics.h"
#include "vm/stringlocal.h"
+
#include "vm/jit/asmpart.h"
#include "vm/jit/codegen-common.h"
#include "vm/jit/dseg.h"
#include "vm/jit/jit.h"
+#include "vm/jit/md.h"
#include "vm/jit/stacktrace.h"
#include "vm/jit/replace.h"
#include "vm/jit/intrp/intrp.h"
#endif
+#include "vmcore/method.h"
+#include "vmcore/options.h"
+
+#if defined(ENABLE_STATISTICS)
+# include "vmcore/statistics.h"
+#endif
+
/* in this tree we store all method addresses *********************************/
#endif
cd->exceptionrefs = NULL;
+/* cd->patchrefs = list_create_dump(OFFSET(patchref, linkage)); */
cd->patchrefs = NULL;
cd->linenumberreferences = NULL;
cd->linenumbertab = 0;
cd->method = m;
- cd->exceptiontable = 0;
- cd->exceptiontablelength = 0;
-
- if (m->exceptiontablelength > 0) {
- cd->exceptiontablelength = m->exceptiontablelength;
- cd->exceptiontable = DMNEW(exceptiontable, m->exceptiontablelength + 1);
- }
cd->maxstack = m->maxstack;
- cd->maxlocals = m->maxlocals;
#if defined(ENABLE_THREADS)
cd->threadcritcurrent.next = NULL;
#endif
-void codegen_addreference(codegendata *cd, basicblock *target)
+/* codegen_add_branch_ref ******************************************************
+
+ Prepends an branch to the list.
+
+*******************************************************************************/
+
+void codegen_add_branch_ref(codegendata *cd, basicblock *target)
{
- s4 branchpos;
+ s4 branchmpc;
+
+ /* calculate the mpc of the branch instruction */
- branchpos = (u1 *) cd->mcodeptr - cd->mcodebase;
+ branchmpc = cd->mcodeptr - cd->mcodebase;
#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. */
- /* 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)
+ /* The interpreter uses absolute branches, so we do branch
+ resolving after the code and data segment move. */
+
&& !opt_intrp
# endif
)
{
- gen_resolvebranch((u1 *) cd->mcodebase + branchpos,
- branchpos,
- target->mpc);
-
- } else
+ md_codegen_patch_branch(cd, branchmpc, target->mpc);
+ }
+ else
#endif
{
branchref *br = DNEW(branchref);
- br->branchpos = branchpos;
+ br->branchpos = branchmpc;
br->next = target->branchrefs;
target->branchrefs = br;
}
+/* codegen_resolve_branchrefs **************************************************
+
+ Resolves and patches the branch references of a given basic block.
+
+*******************************************************************************/
+
+void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
+{
+ branchref *br;
+ s4 branchmpc;
+ s4 targetmpc;
+
+ /* set target */
+
+ targetmpc = bptr->mpc;
+
+ for (br = bptr->branchrefs; br != NULL; br = br->next) {
+ branchmpc = br->branchpos;
+
+ md_codegen_patch_branch(cd, branchmpc, targetmpc);
+ }
+}
+
+
/* codegen_add_exception_ref ***************************************************
- Adds an exception branch to the list.
+ Prepends an exception branch to the list.
*******************************************************************************/
static void codegen_add_exception_ref(codegendata *cd, s4 reg,
functionptr function)
{
- s4 branchpos;
- exceptionref *eref;
+ s4 branchmpc;
+ exceptionref *er;
- branchpos = (u1 *) cd->mcodeptr - cd->mcodebase;
+ branchmpc = cd->mcodeptr - cd->mcodebase;
- eref = DNEW(exceptionref);
+ er = DNEW(exceptionref);
- eref->branchpos = branchpos;
- eref->reg = reg;
- eref->function = function;
- eref->next = cd->exceptionrefs;
+ er->branchpos = branchmpc;
+ er->reg = reg;
+ er->function = function;
- cd->exceptionrefs = eref;
+ er->next = cd->exceptionrefs;
+
+ cd->exceptionrefs = er;
}
}
-/* codegen_addpatchref *********************************************************
+/* codegen_add_patch_ref *******************************************************
- Adds a new patcher reference to the list of patching positions.
+ Appends a new patcher reference to the list of patching positions.
*******************************************************************************/
-void codegen_addpatchref(codegendata *cd, functionptr patcher, voidptr ref,
- s4 disp)
+void codegen_add_patch_ref(codegendata *cd, functionptr patcher, voidptr ref,
+ s4 disp)
{
patchref *pr;
- s4 branchpos;
+ s4 branchmpc;
- branchpos = cd->mcodeptr - cd->mcodebase;
+ branchmpc = cd->mcodeptr - cd->mcodebase;
pr = DNEW(patchref);
- pr->branchpos = branchpos;
+ pr->branchpos = branchmpc;
+ pr->disp = disp;
pr->patcher = patcher;
pr->ref = ref;
- pr->disp = disp;
+/* list_add_first(cd->patchrefs, pr); */
pr->next = cd->patchrefs;
cd->patchrefs = pr;
+#if defined(ENABLE_JIT) && (defined(__ALPHA__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__X86_64__))
+ /* Generate NOPs for opt_shownops. */
+
+ if (opt_shownops)
+ PATCHER_NOPS;
+#endif
+
#if defined(ENABLE_JIT) && (defined(__I386__) || defined(__MIPS__) || defined(__X86_64__))
/* On some architectures the patcher stub call instruction might
be longer than the actual instruction generated. On this
log_println("");
log_println("Dumping the current stacktrace:");
- stacktrace_dump_trace();
+ stacktrace_dump_trace(THREADOBJECT);
vm_abort("Exiting...");
}
}
+/* codegen_set_replacement_point_notrap ****************************************
+
+ Record the position of a non-trappable replacement point.
+
+*******************************************************************************/
+
+#if defined(ENABLE_REPLACEMENT)
+#if !defined(NDEBUG)
+void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
+#else
+void codegen_set_replacement_point_notrap(codegendata *cd)
+#endif
+{
+ assert(cd->replacementpoint);
+ assert(cd->replacementpoint->type == type);
+ assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
+
+ cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
+
+ cd->replacementpoint++;
+}
+#endif /* defined(ENABLE_REPLACEMENT) */
+
+
+/* codegen_set_replacement_point ***********************************************
+
+ Record the position of a trappable replacement point.
+
+*******************************************************************************/
+
+#if defined(ENABLE_REPLACEMENT)
+#if !defined(NDEBUG)
+void codegen_set_replacement_point(codegendata *cd, s4 type)
+#else
+void codegen_set_replacement_point(codegendata *cd)
+#endif
+{
+ assert(cd->replacementpoint);
+ assert(cd->replacementpoint->type == type);
+ assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
+
+ cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
+
+ cd->replacementpoint++;
+
+ /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
+
+ cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
+}
+#endif /* defined(ENABLE_REPLACEMENT) */
+
+
/* codegen_finish **************************************************************
Finishes the code generation. A new memory, large enough for both
}
#endif
- alignedmcodelen = ALIGN(mcodelen, MAX_ALIGN);
+ alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
#if defined(ENABLE_INTRP)
if (opt_intrp)
}
#endif
- cd->dseglen = ALIGN(cd->dseglen, MAX_ALIGN);
+ cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
alignedlen = alignedmcodelen + cd->dseglen;
#if defined(ENABLE_INTRP)
*((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
}
+#if defined(ENABLE_REPLACEMENT)
/* replacement point resolving */
{
int i;
rplpoint *rp;
+ code->replacementstubs += (ptrint) epoint;
+
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);
}
}
+#endif /* defined(ENABLE_REPLACEMENT) */
/* add method into methodtree to find the entrypoint */
jd->m = m;
jd->cd = DNEW(codegendata);
jd->rd = DNEW(registerdata);
+ jd->flags = 0;
/* Allocate codeinfo memory from the heap as we need to keep them. */
/* set the flags for the current JIT run */
+#if defined(ENABLE_PROFILING)
if (opt_prof)
jd->flags |= JITDATA_FLAG_INSTRUMENT;
+#endif
if (opt_verbosecall)
jd->flags |= JITDATA_FLAG_VERBOSECALL;
stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
+#if defined(ENABLE_JAVASE)
/* add current JNI local references table to this thread */
lrt->capacity = LOCALREFTABLE_CAPACITY;
MSET(lrt->refs, 0, java_objectheader*, LOCALREFTABLE_CAPACITY);
LOCALREFTABLE = lrt;
+#endif
}
*psfi = sfi->prev;
+#if defined(ENABLE_JAVASE)
/* release JNI local references tables for this thread */
lrt = LOCALREFTABLE;
/* now store the previous local frames in the thread structure */
LOCALREFTABLE = lrt;
+#endif
/* get the exception and return it */
*******************************************************************************/
-inline s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
+s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
{
#if 0