/* src/vm/jit/powerpc64/codegen.c - machine code generator for 64-bit PowerPC
- 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 "native/localref.h"
#include "native/native.h"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/jit/builtin.hpp"
+#include "vm/exceptions.hpp"
#include "vm/global.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
+#include "vm/loader.hpp"
+#include "vm/options.h"
+#include "vm/vm.hpp"
#include "vm/jit/abi.h"
#include "vm/jit/abi-asm.h"
-#include "vm/jit/md.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
#include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/linenumbertable.hpp"
#include "vm/jit/parse.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/patcher-common.hpp"
#include "vm/jit/reg.h"
-#include "vm/jit/replace.h"
-#include "vm/jit/stacktrace.h"
-
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
+#include "vm/jit/replace.hpp"
+#include "vm/jit/stacktrace.hpp"
+#include "vm/jit/trap.h"
#if defined(ENABLE_LSRA)
# include "vm/jit/allocator/lsra.h"
varinfo *var;
basicblock *bptr;
instruction *iptr;
- exception_entry *ex;
u2 currentline;
methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
unresolved_method *um;
/* monitor_exit. The stack position for the argument can not be shared */
/* with place to save the return register on PPC64, since both values */
/* reside in R3 */
- if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+ if (checksync && code_is_synchronized(code)) {
/* reserve 2 slots for long/double return values for monitorexit */
cd->stackframesize += 2;
}
(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 */
- else
-#endif
- (void) dseg_add_unique_s4(cd, 0); /* IsSync */
-
- (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 */
+ code->synchronizedoffset = rd->memuse * 8;
- dseg_addlinenumbertablesize(cd);
+ /* REMOVEME: We still need it for exception handling in assembler. */
- (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
+ if (code_is_leafmethod(code))
+ (void) dseg_add_unique_s4(cd, 1);
+ else
+ (void) dseg_add_unique_s4(cd, 0);
- /* create exception table */
+ (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
+ (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
- 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 (!jd->isleafmethod) {
+ if (!code_is_leafmethod(code)) {
M_MFLR(REG_ZERO);
M_AST(REG_ZERO, REG_SP, LA_LR_OFFSET);
}
#if defined(ENABLE_THREADS)
- if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+ if (checksync && code_is_synchronized(code)) {
/* stackoffset for argument used for LOCK_monitor_exit */
s1 = rd->memuse;
/* get or test the lock object */
if (m->flags & ACC_STATIC) {
- p = dseg_add_address(cd, &m->class->object.header);
+ p = dseg_add_address(cd, &m->clazz->object.header);
M_ALD(REG_A0, REG_PV, p);
}
else {
M_TST(REG_A0);
M_BNE(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); /* rd->memuse * 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 */
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, disp);
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
+ patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, 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, disp);
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
+ patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, disp);
}
}
M_ALD(REG_ITMP2, REG_PV, disp);
M_MTCTR(REG_ITMP2);
- if (jd->isleafmethod) M_MFLR(REG_ITMP3); /* save LR */
+ if (code_is_leafmethod(code))
+ M_MFLR(REG_ITMP3); /* save LR */
+
M_BL(0); /* get current PC */
M_MFLR(REG_ITMP2_XPC);
- if (jd->isleafmethod) M_MTLR(REG_ITMP3); /* restore LR */
- M_RTS; /* jump to CTR */
+ if (code_is_leafmethod(code))
+ M_MTLR(REG_ITMP3); /* restore LR */
+
+ M_RTS; /* jump to CTR */
ALIGNCODENOP;
break;
#endif
#if defined(ENABLE_THREADS)
- if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+ if (checksync && code_is_synchronized(code)) {
disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
M_ALD(REG_ITMP3, REG_PV, disp);
M_ALD(REG_ITMP3, REG_ITMP3, 0); /* TOC */
/* restore return address */
- if (!jd->isleafmethod) {
+ if (!code_is_leafmethod(code)) {
/* ATTENTION: Don't use REG_ZERO (r0) here, as M_ALD
may have a displacement overflow. */
} 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 */
superindex = super->index;
}
- if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
- CODEGEN_CRITICAL_SECTION_NEW;
- }
-
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
/* if class is not resolved, check which code to call */
M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_ALD(REG_ITMP2, REG_PV, disp);
if (s1 != REG_ITMP1) {
M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
M_SUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
M_EXTSW(REG_ITMP3, REG_ITMP3);
} else {
M_EXTSW(REG_ITMP3, REG_ITMP3);
M_ALD(REG_ITMP2, REG_PV, disp);
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
-
- CODEGEN_CRITICAL_SECTION_END;
-
}
M_CMPU(REG_ITMP3, REG_ITMP2);
emit_classcast_check(cd, iptr, BRANCH_GT, REG_ITMP3, s1);
superindex = super->index;
}
- if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
- CODEGEN_CRITICAL_SECTION_NEW;
- }
-
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
if (s1 == d) {
M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
M_ALD(REG_ITMP2, REG_PV, disp);
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
M_EXTSW(REG_ITMP1, REG_ITMP1);
M_CMPU(REG_ITMP1, REG_ITMP2);
} /* if (bptr -> flags >= BBREACHED) */
} /* for basic block */
- dseg_createlinenumbertable(cd);
-
/* generate traps */
emit_patcher_traps(jd);
methoddesc *md;
s4 i, j;
s4 t;
- s4 s1, s2, disp;
- s4 funcdisp;
+ int s1, s2;
+ int disp;
/* get required compiler data */
code = jd->code;
cd = jd->cd;
+ /* Sanity check. */
+
+ assert(!code_is_leafmethod(code));
+
/* set some variables */
md = m->parseddesc;
/* calculate stackframe size */
cd->stackframesize =
- sizeof(stackframeinfo) / SIZEOF_VOID_P +
+ sizeof(stackframeinfo_t) / SIZEOF_VOID_P +
sizeof(localref_table) / SIZEOF_VOID_P +
4 + /* 4 stackframeinfo arguments (darwin)*/
nmd->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 */
+ (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); /* IsLeaf */
+ (void) dseg_add_unique_s4(cd, 0); /* IntSave */
+ (void) dseg_add_unique_s4(cd, 0); /* FltSave */
/* generate code */
M_AST_INTERN(REG_ZERO, REG_SP, LA_LR_OFFSET);
M_STDU(REG_SP, REG_SP, -(cd->stackframesize * 8));
- /* 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);
-
/* save integer and float argument registers */
for (i = 0; i < md->paramcount; i++) {
M_MOV(REG_SP, REG_A0);
M_MOV(REG_PV, REG_A1);
disp = dseg_add_functionptr(cd, codegen_start_native_call);
-
M_ALD(REG_ITMP1, REG_PV, disp);
M_ALD(REG_ITMP1, REG_ITMP1, 0); /* TOC */
M_MTCTR(REG_ITMP1);
/* put env into first argument register */
- disp = dseg_add_unique_address(cd, _Jv_env);
+ disp = dseg_add_unique_address(cd, VM_get_jnienv());
M_ALD(REG_A0, REG_PV, disp);
}
- /* generate the actual native call */
+ /* Call the native function. */
/* native functions have a different TOC for sure */
M_AST(REG_TOC, REG_SP, 40); /* save old TOC */
- M_ALD(REG_ITMP3, REG_PV, funcdisp);
+ disp = dseg_add_functionptr(cd, f);
+ M_ALD(REG_ITMP3, REG_PV, disp);
M_ALD(REG_TOC, REG_ITMP3, 8); /* load TOC from func. descriptor */
M_ALD(REG_ITMP3, REG_ITMP3, 0);
M_MTCTR(REG_ITMP3);
M_ALD(REG_ITMP3, REG_PV, disp);
M_MTCTR(REG_ITMP3);
M_RTS;
-
- /* generate patcher traps */
-
- emit_patcher_traps(jd);
}
-
-
/*
* These are local overrides for various environment variables in Emacs.
* Please do not remove this and leave it at the end of the file, where