/* src/vm/jit/inline/inline.c - method inlining
- 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
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Edwin Steiner
-
- Changes:
-
- $Id: inline.c 7486 2007-03-08 13:50:07Z twisti $
-
*/
-#include "config.h"
-#include "vm/types.h"
+#include "config.h"
#include <assert.h>
+#include <limits.h>
#include <stdio.h>
#include <string.h>
-#include <limits.h>
+
+#include "vm/types.h"
#include "mm/memory.h"
+
+#include "threads/lock.hpp"
+#include "threads/mutex.hpp"
+#include "threads/thread.hpp"
+
#include "toolbox/logging.h"
-#include "vm/builtin.h"
-#include "vm/global.h"
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/parse.h"
-#include "vm/jit/inline/inline.h"
-#include "vm/jit/loop/loop.h"
-#include "vmcore/class.h"
-#include "vm/initialize.h"
-#include "vmcore/method.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/show.h"
+#include "vm/jit/builtin.hpp"
+#include "vm/class.hpp"
+#include "vm/global.h"
+#include "vm/initialize.hpp"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/parse.hpp"
#include "vm/jit/reg.h"
+#include "vm/jit/show.hpp"
#include "vm/jit/stack.h"
-#include "vm/jit/verify/typecheck.h"
+#include "vm/jit/inline/inline.h"
+#include "vm/jit/loop/loop.h"
-#if defined(ENABLE_THREADS)
-# include "threads/native/threads.h"
-#endif
+#include "vm/jit/verify/typecheck.h"
/* algorithm tuning constants *************************************************/
#if !defined(NDEBUG)
#define INLINE_VERBOSE
-#define DOLOG(code) do{ if (opt_inline_debug_log) { code; } }while(0)
+#define DOLOG(code) do{ if (opt_TraceInlining >= 2) { code; } }while(0)
+#define DOLOG_SHORT(code) do{ if (opt_TraceInlining >= 1) { code; } }while(0)
#else
#define DOLOG(code)
#endif
/* call parse pass */
- DOLOG( log_message_class("Parsing ", m->class) );
+ DOLOG( log_message_class("Parsing ", m->clazz) );
if (!parse(jd)) {
return false;
}
m = iln->m;
assert(m);
-#if defined(ENABLE_THREADS)
/* enter a monitor on the method */
- lock_monitor_enter((java_objectheader *) m);
-#endif
+
+ Mutex_lock(m->mutex);
/* allocate jitdata structure and fill it */
/* XXX do a pseudo setup */
jd->cd = DNEW(codegendata);
MZERO(jd->cd, codegendata, 1);
- jd->cd->maxstack = m->maxstack;
jd->cd->method = m;
/* XXX uses too much dump memory codegen_setup(jd); */
#endif
-#if defined(ENABLE_THREADS)
/* leave the monitor */
- lock_monitor_exit((java_objectheader *) m );
-#endif
+
+ Mutex_unlock(m->mutex);
return r;
}
{
s4 *varmap;
s4 i, t;
- s4 idx;
- s4 n_idx;
+ s4 varindex;
+ s4 n_javaindex;
s4 avail;
varinfo *v;
for (i=0; i<callee->m->maxlocals; ++i) {
for (t=0; t<5; ++t) {
- idx = callee->jd->local_map[5*i + t];
- if (idx == UNUSED)
+ varindex = callee->jd->local_map[5*i + t];
+ if (varindex == UNUSED)
continue;
- v = &(callee->jd->var[idx]);
+ v = &(callee->jd->var[varindex]);
assert(v->type == t || v->type == TYPE_VOID); /* XXX stack leaves VOID */
v->type = t; /* XXX restore if it is TYPE_VOID */
avail = callee->ctx->resultjd->local_map[5*(callee->localsoffset + i) + t];
if (avail == UNUSED) {
- avail = inline_new_variable_clone(callee->ctx->resultjd, callee->jd, idx);
+ avail = inline_new_variable_clone(callee->ctx->resultjd, callee->jd, varindex);
callee->ctx->resultjd->local_map[5*(callee->localsoffset + i) + t] = avail;
}
- varmap[idx] = avail;
+ varmap[varindex] = avail;
}
}
/* for synchronized instance methods we need an extra local */
if (callee->synchronize && !(callee->m->flags & ACC_STATIC)) {
- n_idx = callee->localsoffset - 1;
- assert(n_idx >= 0);
+ n_javaindex = callee->localsoffset - 1;
+ assert(n_javaindex >= 0);
assert(callee->parent);
- assert(n_idx == callee->parent->localsoffset + callee->parent->m->maxlocals);
+ assert(n_javaindex == callee->parent->localsoffset + callee->parent->m->maxlocals);
- avail = callee->ctx->resultjd->local_map[5*n_idx + TYPE_ADR];
+ avail = callee->ctx->resultjd->local_map[5*n_javaindex + TYPE_ADR];
if (avail == UNUSED) {
avail = inline_new_variable(callee->ctx->resultjd, TYPE_ADR, 0);
- callee->ctx->resultjd->local_map[5*n_idx + TYPE_ADR] = avail;
+ callee->ctx->resultjd->local_map[5*n_javaindex + TYPE_ADR] = avail;
}
callee->synclocal = avail;
#define INLINE_RETURN_REFERENCE(callee) \
( (basicblock *) (ptrint) (0x333 + (callee)->depth) )
-#define RETADDRNR_FROM_BLOCK(bptr) (UNUSED - 1 - (bptr)->nr)
-
static void inline_add_block_reference(inline_node *iln, basicblock **blockp)
{
}
+#if 0
static void inline_add_blocknr_reference(inline_node *iln, s4 *nrp)
{
inline_target_ref *ref;
ref->next = iln->refs;
iln->refs = ref;
}
+#endif
static void inline_block_translation(inline_node *iln, basicblock *o_bptr, basicblock *n_bptr)
prev = NULL;
for (ref = *refs; ref != NULL; ref = ref->next) {
if (ref->isnumber && !returnref) {
- if (*(ref->ref.nr) == RETADDRNR_FROM_BLOCK(o_bptr)) {
- *(ref->ref.nr) = RETADDRNR_FROM_BLOCK(n_bptr);
+ if (*(ref->ref.nr) == JAVALOCAL_FROM_RETADDR(o_bptr->nr)) {
+ *(ref->ref.nr) = JAVALOCAL_FROM_RETADDR(n_bptr->nr);
goto remove_ref;
}
}
syncvar = inline_new_temp_variable(iln->ctx->resultjd, TYPE_ADR);
n_ins = inline_instruction(iln, ICMD_ACONST, o_iptr);
- n_ins->sx.val.c.cls = callee->m->class;
+ n_ins->sx.val.c.cls = callee->m->clazz;
n_ins->dst.varindex = syncvar;
n_ins->flags.bits |= INS_FLAG_CLASS;
}
int type;
instruction *n_ins;
insinfo_inline *insinfo;
- s4 argvar;
+ s4 varindex;
assert(iln && callee && o_iptr);
/* translate the argument variable */
- argvar = varmap[o_iptr->sx.s23.s2.args[i]];
- assert(argvar != UNUSED);
+ varindex = varmap[o_iptr->sx.s23.s2.args[i]];
+ assert(varindex != UNUSED);
/* remove preallocation from the argument variable */
- iln->ctx->resultjd->var[argvar].flags &= ~(PREALLOC | INMEMORY);
+ iln->ctx->resultjd->var[varindex].flags &= ~(PREALLOC | INMEMORY);
/* check the instance slot against NULL */
/* we don't need that for <init> methods, as the verifier */
if (!callee->isstatic && i == 0 && calleem->name != utf_init) {
assert(type == TYPE_ADR);
n_ins = inline_instruction(iln, ICMD_CHECKNULL, o_iptr);
- n_ins->s1.varindex = argvar;
+ n_ins->s1.varindex = varindex;
n_ins->dst.varindex = n_ins->s1.varindex;
}
n_ins = inline_instruction(iln, ICMD_ISTORE + type, o_iptr);
n_ins->sx.s23.s3.javaindex = UNUSED;
}
- n_ins->s1.varindex = argvar;
+ n_ins->s1.varindex = varindex;
n_ins->dst.varindex = iln->ctx->resultjd->local_map[5*localindex + type];
assert(n_ins->dst.varindex != UNUSED);
}
/* this value is not used, pop it */
n_ins = inline_instruction(iln, ICMD_POP, o_iptr);
- n_ins->s1.varindex = argvar;
+ n_ins->s1.varindex = varindex;
}
DOLOG( printf("%sprolog: ", iln->indent);
n_ins = master->inlined_iinstr_cursor++;
if (iln->m->flags & ACC_STATIC) {
n_ins->opc = ICMD_ACONST;
- n_ins->sx.val.c.cls = iln->m->class;
+ n_ins->sx.val.c.cls = iln->m->clazz;
n_ins->flags.bits = INS_FLAG_CLASS;
}
else {
#if defined(INLINE_VERIFY_RESULT)
static int debug_verify_inlined_code = 1;
#endif
-#if defined(ENABLE_INLINING_DEBUG)
+#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
static int debug_counter = 0;
#endif
/* store created code in jitdata */
n_jd->basicblocks = iln->inlined_basicblocks;
- n_jd->basicblockindex = NULL;
n_jd->instructioncount = iln->cumul_instructioncount;
n_jd->instructions = iln->inlined_iinstr;
debug_verify_inlined_code = 0;
DOLOG( printf("VERIFYING INLINED RESULT...\n"); fflush(stdout); );
if (!typecheck(n_jd)) {
- *exceptionptr = NULL;
+ exceptions_clear_exception();
DOLOG( printf("XXX INLINED RESULT DID NOT PASS VERIFIER XXX\n") );
return false;
}
/* we need bigger free memory stacks (XXX these should not be allocated in reg_setup) */
n_jd->rd->freemem = DMNEW(s4, iln->ctx->maxinoutdepth + 1000) /* XXX max vars/block */;
-#if defined(HAS_4BYTE_STACKSLOT)
- n_jd->rd->freemem_2 = DMNEW(s4, iln->ctx->maxinoutdepth + 1000) /* XXX max vars/block */;
-#endif
#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
- if ( (n_jd->instructioncount >= opt_inline_debug_min_size)
- && (n_jd->instructioncount <= opt_inline_debug_max_size))
+ if ( (n_jd->instructioncount >= opt_InlineMinSize)
+ && (n_jd->instructioncount <= opt_InlineMaxSize))
{
- if (debug_counter <= opt_inline_debug_end_counter)
+ if (debug_counter < opt_InlineCount)
#endif /* defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG) */
{
/* install the inlined result */
#if !defined(NDEBUG)
inline_stat_roots++;
- DOLOG(
+ DOLOG_SHORT(
printf("==== %d.INLINE ==================================================================\n",
debug_counter);
printf("\ninline tree:\n");
static void inline_post_process(jitdata *jd)
{
+ codeinfo *code;
basicblock *bptr;
instruction *iptr;
instruction *iend;
methoddesc *md;
builtintable_entry *bte;
+ /* Get required compiler data. */
+
+ code = jd->code;
+
/* reset the SAVEDVAR flag of all variables */
for (i=0; i<jd->vartop; ++i)
POSTPROCESS_SRCOP(s1);
case DF_0_TO_0:
if (icmdt->flags & ICMDTABLE_CALLS) {
- jd->isleafmethod = false;
+ code_unflag_leafmethod(code);
MARK_ALL_SAVED;
}
break;
POSTPROCESS_SRCOP(s1);
case DF_0_TO_1:
if (icmdt->flags & ICMDTABLE_CALLS) {
- jd->isleafmethod = false;
+ code_unflag_leafmethod(code);
MARK_ALL_SAVED;
}
case DF_COPY:
POSTPROCESS_SRC(iptr->sx.s23.s2.args[i]);
}
if (icmdt->flags & ICMDTABLE_CALLS) {
- jd->isleafmethod = false;
+ code_unflag_leafmethod(code);
MARK_ALL_SAVED;
}
POSTPROCESS_DSTOP(dst);
case DF_INVOKE:
INSTRUCTION_GET_METHODDESC(iptr, md);
post_process_call:
- jd->isleafmethod = false;
+ code_unflag_leafmethod(code);
for (i=0; i<md->paramcount; ++i) {
POSTPROCESS_SRC(iptr->sx.s23.s2.args[i]);
}