/* src/vm/jit/alpha/codegen.c - machine code generator for Alpha
- 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
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/dseg.h"
#include "vm/jit/emit-common.h"
#include "vm/jit/jit.h"
+#include "vm/jit/linenumbertable.h"
#include "vm/jit/parse.h"
#include "vm/jit/patcher-common.h"
#include "vm/jit/reg.h"
#include "vm/jit/replace.h"
#include "vm/jit/stacktrace.h"
+#include "vm/jit/trap.h"
-#if defined(ENABLE_LSRA)
+#if defined(ENABLE_SSA)
+# include "vm/jit/optimizing/lsra.h"
+# include "vm/jit/optimizing/ssa.h"
+#elif defined(ENABLE_LSRA)
# include "vm/jit/allocator/lsra.h"
#endif
varinfo *var;
basicblock *bptr;
instruction *iptr;
- exception_entry *ex;
u2 currentline;
methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
unresolved_method *um;
s4 i, p, t, l;
s4 savedregs_num;
- savedregs_num = (jd->isleafmethod) ? 0 : 1; /* space to save the RA */
+ savedregs_num = code_is_leafmethod(code) ? 0 : 1; /* space to save the RA */
/* space to save used callee saved registers */
cd->stackframesize = rd->memuse + savedregs_num;
#if defined(ENABLE_THREADS) /* space to save argument of monitor_enter */
- if (checksync && (m->flags & ACC_SYNCHRONIZED))
+ if (checksync && code_is_synchronized(code))
cd->stackframesize++;
#endif
(void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
(void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
-#if defined(ENABLE_THREADS)
- /* IsSync contains the offset relative to the stack pointer for the
- argument of monitor_exit used in the exception handler. Since the
- offset could be zero and give a wrong meaning of the flag it is
- offset by one.
- */
-
- if (checksync && (m->flags & ACC_SYNCHRONIZED))
- (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 8); /* IsSync */
+ code->synchronizedoffset = rd->memuse * 8;
+
+ /* REMOVEME: We still need it for exception handling in assembler. */
+
+ if (code_is_leafmethod(code))
+ (void) dseg_add_unique_s4(cd, 1);
else
-#endif
- (void) dseg_add_unique_s4(cd, 0); /* IsSync */
+ (void) dseg_add_unique_s4(cd, 0);
- (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
(void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
(void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
- dseg_addlinenumbertablesize(cd);
-
- (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
-
- /* create exception table */
-
- for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
- dseg_add_target(cd, ex->start);
- dseg_add_target(cd, ex->end);
- dseg_add_target(cd, ex->handler);
- (void) dseg_add_unique_address(cd, ex->catchtype.any);
- }
-
/* create stack frame (if necessary) */
if (cd->stackframesize)
/* save return address and used callee saved registers */
p = cd->stackframesize;
- if (!jd->isleafmethod) {
+ if (!code_is_leafmethod(code)) {
p--; M_AST(REG_RA, REG_SP, p * 8);
}
for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
/* call monitorenter function */
#if defined(ENABLE_THREADS)
- if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+ if (checksync && code_is_synchronized(code)) {
/* stack offset for monitor argument */
s1 = rd->memuse;
/* decide which monitor enter function to call */
if (m->flags & ACC_STATIC) {
- disp = dseg_add_address(cd, &m->class->object.header);
+ disp = dseg_add_address(cd, &m->clazz->object.header);
M_ALD(REG_A0, REG_PV, disp);
}
else {
M_BNEZ(REG_A0, 1);
- M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
+ M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
}
M_AST(REG_A0, REG_SP, s1 * 8);
for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
if (iptr->line != currentline) {
- dseg_addlinenumber(cd, iptr->line);
+ linenumbertable_list_entry_add(cd, iptr->line);
currentline = iptr->line;
}
case ICMD_INLINE_BODY:
REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
- dseg_addlinenumber_inline_start(cd, iptr);
- dseg_addlinenumber(cd, iptr->line);
+ linenumbertable_list_entry_add_inline_start(cd, iptr);
+ linenumbertable_list_entry_add(cd, iptr->line);
break;
case ICMD_INLINE_END:
- dseg_addlinenumber_inline_end(cd, iptr);
- dseg_addlinenumber(cd, iptr->line);
+ linenumbertable_list_entry_add_inline_end(cd, iptr);
+ linenumbertable_list_entry_add(cd, iptr->line);
break;
case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
case ICMD_L2F:
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- disp = dseg_add_unique_double(cd, 0.0);
+ disp = dseg_add_unique_double(cd, 0.0); /* FIXME Not thread safe! */
M_LST(s1, REG_PV, disp);
M_DLD(d, REG_PV, disp);
M_CVTLF(d, d);
case ICMD_L2D:
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- disp = dseg_add_unique_double(cd, 0.0);
+ disp = dseg_add_unique_double(cd, 0.0); /* FIXME Not thread safe! */
M_LST(s1, REG_PV, disp);
M_DLD(d, REG_PV, disp);
M_CVTLD(d, d);
case ICMD_D2I:
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- disp = dseg_add_unique_double(cd, 0.0);
+ disp = dseg_add_unique_double(cd, 0.0); /* FIXME Not thread safe! */
M_CVTDL_C(s1, REG_FTMP2);
M_CVTLI(REG_FTMP2, REG_FTMP3);
M_DST(REG_FTMP3, REG_PV, disp);
case ICMD_D2L:
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- disp = dseg_add_unique_double(cd, 0.0);
+ disp = dseg_add_unique_double(cd, 0.0); /* FIXME Not thread safe! */
M_CVTDL_C(s1, REG_FTMP2);
M_DST(REG_FTMP2, REG_PV, disp);
M_LLD(d, REG_PV, disp);
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
- patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class,
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+ patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz,
0);
}
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
- patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class,
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+ patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz,
0);
}
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
- patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class,
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+ patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz,
0);
}
#endif
#if defined(ENABLE_THREADS)
- if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+ if (checksync && code_is_synchronized(code)) {
M_ALD(REG_A0, REG_SP, rd->memuse * 8);
switch (iptr->opc) {
/* restore return address */
- if (!jd->isleafmethod) {
+ if (!code_is_leafmethod(code)) {
p--; M_LLD(REG_RA, REG_SP, p * 8);
}
REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr);
disp = (s4) (cd->mcodeptr - cd->mcodebase);
M_LDA(REG_PV, REG_RA, -disp);
-
- emit_exception_check(cd, iptr);
break;
case ICMD_INVOKESPECIAL:
}
else {
s1 = OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * lm->class->index;
+ sizeof(methodptr*) * lm->clazz->index;
- s2 = sizeof(methodptr) * (lm - lm->class->methods);
+ s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
}
/* implicit null-pointer check */
} /* if (bptr -> flags >= BBREACHED) */
} /* for basic block */
- dseg_createlinenumbertable(cd);
-
/* generate traps */
emit_patcher_traps(jd);
}
-/* codegen_emit_stub_compiler **************************************************
-
- Emits a stub routine which calls the compiler.
-
-*******************************************************************************/
-
-void codegen_emit_stub_compiler(jitdata *jd)
-{
- methodinfo *m;
- codegendata *cd;
-
- /* get required compiler data */
-
- m = jd->m;
- cd = jd->cd;
-
- /* code for the stub */
-
- M_ALD(REG_ITMP1, REG_PV, -2 * 8); /* load codeinfo pointer */
- M_ALD(REG_PV, REG_PV, -3 * 8); /* load pointer to the compiler */
- M_JMP(REG_ZERO, REG_PV); /* jump to the compiler */
-}
-
-
-/* codegen_emit_stub_builtin ***************************************************
-
- Emits a stub routine which calls a builtin function.
-
-*******************************************************************************/
-
-void codegen_emit_stub_builtin(jitdata *jd, builtintable_entry *bte)
-{
- codeinfo *code;
- codegendata *cd;
- methoddesc *md;
- s4 i;
- s4 disp;
- s4 s1;
-
- /* get required compiler data */
-
- code = jd->code;
- cd = jd->cd;
-
- /* set some variables */
-
- md = bte->md;
-
- /* calculate stack frame size */
-
- cd->stackframesize =
- 1 + /* return address */
- sizeof(stackframeinfo) / SIZEOF_VOID_P +
- md->paramcount;
-
- /* create method header */
-
- (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
- (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
- (void) dseg_add_unique_s4(cd, 0); /* IsSync */
- (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
- (void) dseg_add_unique_s4(cd, 0); /* IntSave */
- (void) dseg_add_unique_s4(cd, 0); /* FltSave */
- (void) dseg_addlinenumbertablesize(cd);
- (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
-
- /* generate stub code */
-
- M_LDA(REG_SP, REG_SP, -(cd->stackframesize * 8));
- M_AST(REG_RA, REG_SP, cd->stackframesize * 8 - SIZEOF_VOID_P);
-
-
-#if defined(ENABLE_GC_CACAO)
- /* Save callee saved integer registers in stackframeinfo (GC may
- need to recover them during a collection). */
-
- disp = cd->stackframesize * 8 - SIZEOF_VOID_P - sizeof(stackframeinfo) +
- OFFSET(stackframeinfo, intregs);
-
- for (i = 0; i < INT_SAV_CNT; i++)
- M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
-#endif
-
- /* save integer and float argument registers */
-
- for (i = 0; i < md->paramcount; i++) {
- if (!md->params[i].inmemory) {
- s1 = md->params[i].regoff;
-
- switch (md->paramtypes[i].type) {
- case TYPE_INT:
- case TYPE_LNG:
- case TYPE_ADR:
- M_LST(s1, REG_SP, i * 8);
- break;
- case TYPE_FLT:
- case TYPE_DBL:
- M_DST(s1, REG_SP, i * 8);
- break;
- }
- }
- }
-
- /* prepare data structures for native function call */
-
- M_LDA(REG_A0, REG_SP, cd->stackframesize * 8 - SIZEOF_VOID_P);
- M_MOV(REG_PV, REG_A1);
- M_LDA(REG_A2, REG_SP, cd->stackframesize * 8);
- M_ALD(REG_A3, REG_SP, cd->stackframesize * 8 - SIZEOF_VOID_P);
- disp = dseg_add_functionptr(cd, codegen_stub_builtin_enter);
- M_ALD(REG_PV, REG_PV, disp);
- M_JSR(REG_RA, REG_PV);
- disp = (s4) (cd->mcodeptr - cd->mcodebase);
- M_LDA(REG_PV, REG_RA, -disp);
-
- /* restore integer and float argument registers */
-
- for (i = 0; i < md->paramcount; i++) {
- if (!md->params[i].inmemory) {
- s1 = md->params[i].regoff;
-
- switch (md->paramtypes[i].type) {
- case TYPE_INT:
- case TYPE_LNG:
- case TYPE_ADR:
- M_LLD(s1, REG_SP, i * 8);
- break;
- case TYPE_FLT:
- case TYPE_DBL:
- M_DLD(s1, REG_SP, i * 8);
- break;
- }
- }
- }
-
- /* do the builtin function call */
-
- disp = dseg_add_functionptr(cd, bte->fp);
- M_ALD(REG_PV, REG_PV, disp);
- M_JSR(REG_RA, REG_PV);
- disp = (s4) (cd->mcodeptr - cd->mcodebase);
- M_LDA(REG_PV, REG_RA, -disp); /* recompute pv from ra */
-
- /* save return value */
-
- switch (md->returntype.type) {
- case TYPE_INT:
- case TYPE_LNG:
- case TYPE_ADR:
- M_LST(REG_RESULT, REG_SP, 0 * 8);
- break;
- case TYPE_FLT:
- case TYPE_DBL:
- M_DST(REG_FRESULT, REG_SP, 0 * 8);
- break;
- case TYPE_VOID:
- break;
- }
-
- /* remove native stackframe info */
-
- M_LDA(REG_A0, REG_SP, cd->stackframesize * 8 - SIZEOF_VOID_P);
- disp = dseg_add_functionptr(cd, codegen_stub_builtin_exit);
- M_ALD(REG_PV, REG_PV, disp);
- M_JSR(REG_RA, REG_PV);
- disp = (s4) (cd->mcodeptr - cd->mcodebase);
- M_LDA(REG_PV, REG_RA, -disp);
- M_MOV(REG_RESULT, REG_ITMP1_XPTR);
-
- /* restore return value */
-
- switch (md->returntype.type) {
- case TYPE_INT:
- case TYPE_LNG:
- case TYPE_ADR:
- M_LLD(REG_RESULT, REG_SP, 0 * 8);
- break;
- case TYPE_FLT:
- case TYPE_DBL:
- M_DLD(REG_FRESULT, REG_SP, 0 * 8);
- break;
- case TYPE_VOID:
- break;
- }
-
-#if defined(ENABLE_GC_CACAO)
- /* Restore callee saved integer registers from stackframeinfo (GC
- might have modified them during a collection). */
-
- disp = cd->stackframesize * 8 - SIZEOF_VOID_P - sizeof(stackframeinfo) +
- OFFSET(stackframeinfo, intregs);
-
- for (i = 0; i < INT_SAV_CNT; i++)
- M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
-#endif
-
- M_ALD(REG_RA, REG_SP, (cd->stackframesize - 1) * 8); /* get RA */
- M_LDA(REG_SP, REG_SP, cd->stackframesize * 8);
-
- M_RET(REG_ZERO, REG_RA); /* return to caller */
-}
-
-
/* codegen_emit_stub_native ****************************************************
Emits a stub routine which calls a native method.
*******************************************************************************/
-void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
+void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
{
methodinfo *m;
codeinfo *code;
codegendata *cd;
methoddesc *md;
- s4 nativeparams;
- s4 i, j; /* count variables */
- s4 t;
- s4 s1, s2, disp;
- s4 funcdisp; /* displacement of the function */
+ int i, j;
+ int t;
+ int s1, s2;
+ int disp;
/* get required compiler data */
/* initialize variables */
md = m->parseddesc;
- nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
/* calculate stack frame size */
cd->stackframesize =
1 + /* return address */
- sizeof(stackframeinfo) / SIZEOF_VOID_P +
+ sizeof(stackframeinfo_t) / SIZEOF_VOID_P +
sizeof(localref_table) / SIZEOF_VOID_P +
1 + /* methodinfo for call trace */
md->paramcount +
(void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
(void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
- (void) dseg_add_unique_s4(cd, 0); /* IsSync */
(void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
(void) dseg_add_unique_s4(cd, 0); /* IntSave */
(void) dseg_add_unique_s4(cd, 0); /* FltSave */
- (void) dseg_addlinenumbertablesize(cd);
- (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
/* generate stub code */
M_LDA(REG_SP, REG_SP, -(cd->stackframesize * 8));
M_AST(REG_RA, REG_SP, cd->stackframesize * 8 - SIZEOF_VOID_P);
- /* call trace function */
-
-#if !defined(NDEBUG)
- if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
- emit_verbosecall_enter(jd);
-#endif
-
- /* get function address (this must happen before the stackframeinfo) */
-
- funcdisp = dseg_add_functionptr(cd, f);
-
- if (f == NULL)
- patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, funcdisp);
-
#if defined(ENABLE_GC_CACAO)
/* Save callee saved integer registers in stackframeinfo (GC may
need to recover them during a collection). */
- disp = cd->stackframesize * 8 - SIZEOF_VOID_P - sizeof(stackframeinfo) +
- OFFSET(stackframeinfo, intregs);
+ disp = cd->stackframesize * 8 - SIZEOF_VOID_P - sizeof(stackframeinfo_t) +
+ OFFSET(stackframeinfo_t, intregs);
for (i = 0; i < INT_SAV_CNT; i++)
M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
M_LST(s1, REG_SP, i * 8);
break;
case TYPE_FLT:
+ M_FST(s1, REG_SP, i * 8);
+ break;
case TYPE_DBL:
M_DST(s1, REG_SP, i * 8);
break;
M_LLD(s1, REG_SP, i * 8);
break;
case TYPE_FLT:
+ M_FLD(s1, REG_SP, i * 8);
+ break;
case TYPE_DBL:
M_DLD(s1, REG_SP, i * 8);
break;
/* copy or spill arguments to new locations */
- for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
+ for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
t = md->paramtypes[i].type;
if (IS_INT_LNG_TYPE(t)) {
}
}
- /* put class into second argument register */
+ /* Handle native Java methods. */
- if (m->flags & ACC_STATIC)
- M_MOV(REG_ITMP3, REG_A1);
+ if (m->flags & ACC_NATIVE) {
+ /* put class into second argument register */
+
+ if (m->flags & ACC_STATIC)
+ M_MOV(REG_ITMP3, REG_A1);
- /* put env into first argument register */
+ /* put env into first argument register */
- disp = dseg_add_address(cd, _Jv_env);
- M_ALD(REG_A0, REG_PV, disp);
+ disp = dseg_add_address(cd, _Jv_env);
+ M_ALD(REG_A0, REG_PV, disp);
+ }
- /* do the native function call */
+ /* Call the native function. */
- M_ALD(REG_PV, REG_PV, funcdisp);
+ disp = dseg_add_functionptr(cd, f);
+ M_ALD(REG_PV, REG_PV, disp);
M_JSR(REG_RA, REG_PV); /* call native method */
disp = (s4) (cd->mcodeptr - cd->mcodebase);
M_LDA(REG_PV, REG_RA, -disp); /* recompute pv from ra */
M_LST(REG_RESULT, REG_SP, 0 * 8);
break;
case TYPE_FLT:
+ M_FST(REG_FRESULT, REG_SP, 0 * 8);
+ break;
case TYPE_DBL:
M_DST(REG_FRESULT, REG_SP, 0 * 8);
break;
break;
}
- /* call finished trace */
-
-#if !defined(NDEBUG)
- if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
- emit_verbosecall_exit(jd);
-#endif
-
/* remove native stackframe info */
- M_LDA(REG_A0, REG_SP, cd->stackframesize * 8 - SIZEOF_VOID_P);
+ M_MOV(REG_SP, REG_A0);
+ M_MOV(REG_PV, REG_A1);
disp = dseg_add_functionptr(cd, codegen_finish_native_call);
M_ALD(REG_PV, REG_PV, disp);
M_JSR(REG_RA, REG_PV);
M_LLD(REG_RESULT, REG_SP, 0 * 8);
break;
case TYPE_FLT:
+ M_FLD(REG_FRESULT, REG_SP, 0 * 8);
+ break;
case TYPE_DBL:
M_DLD(REG_FRESULT, REG_SP, 0 * 8);
break;
/* Restore callee saved integer registers from stackframeinfo (GC
might have modified them during a collection). */
- disp = cd->stackframesize * 8 - SIZEOF_VOID_P - sizeof(stackframeinfo) +
- OFFSET(stackframeinfo, intregs);
+ disp = cd->stackframesize * 8 - SIZEOF_VOID_P - sizeof(stackframeinfo_t) +
+ OFFSET(stackframeinfo_t, intregs);
for (i = 0; i < INT_SAV_CNT; i++)
M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
M_ALD(REG_ITMP3, REG_PV, disp); /* load asm exception handler address */
M_JMP(REG_ZERO, REG_ITMP3); /* jump to asm exception handler */
-
- /* generate patcher stubs */
-
- emit_patcher_traps(jd);
}