-/* jit/codegen.inc - architecture independent code generator
+/* vm/jit/codegen.inc - architecture independent code generator
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
- Institut f. Computersprachen, TU Wien
- R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
- S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
- J. Wenninger
+ 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
This file is part of CACAO.
Authors: Reinhard Grafl
Andreas Krall
- Changes: Michael Gschwind
- Christian Thalinger
+ Changes: Christian Thalinger
+ Joseph Wenninger
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.inc 1420 2004-10-27 16:05:14Z twisti $
+ $Id: codegen.inc 1735 2004-12-07 14:33:27Z twisti $
*/
+#ifndef _CODEGEN_INC_H_
+#define _CODEGEN_INC_H_
#include <string.h>
-#include "exceptions.h"
-#include "native.h"
-#include "options.h"
-#include "statistics.h"
-#include "jit/codegen.inc.h"
-#include "toolbox/memory.h"
-#include "toolbox/logging.h"
+
+#if !defined(STATIC_CLASSPATH)
+# include <dlfcn.h>
+#endif
+
+#include "mm/memory.h"
#include "toolbox/avl.h"
-#include "threads/thread.h"
+#include "toolbox/logging.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
+#endif
+#include "vm/exceptions.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
+#include "vm/jit/codegen.inc.h"
-/* in this tree we store all method addresses */
+
+/* in this tree we store all method addresses *********************************/
#if defined(__I386__) || defined(__X86_64__)
static struct avl_table *methodtree = NULL;
mte = NEW(methodtree_element);
- mte->startpc = asm_calljavafunction;
- mte->endpc = asm_calljavafunction2 - 1;
+ mte->startpc = (functionptr) asm_calljavafunction;
+ mte->endpc = (functionptr) ((long) asm_calljavafunction2 - 1);
avl_insert(methodtree, mte);
mte = NEW(methodtree_element);
- mte->startpc = asm_calljavafunction2;
- mte->endpc = asm_call_jit_compiler - 1;
+ mte->startpc = (functionptr) asm_calljavafunction2;
+ mte->endpc = (functionptr) ((long) asm_call_jit_compiler - 1);
avl_insert(methodtree, mte);
}
*******************************************************************************/
-void codegen_setup(methodinfo *m, t_inlining_globals * e)
+void codegen_setup(methodinfo *m, codegendata *cd, t_inlining_globals *id)
{
- codegendata *cd;
-
- m->codegendata = NEW(codegendata);
-
- /* keep code size smaller */
- cd = m->codegendata;
-
cd->mcodebase = MNEW(u1, MCODEINITSIZE);
cd->mcodesize = MCODEINITSIZE;
cd->xcastrefs = NULL;
cd->xdivrefs = NULL;
cd->xexceptionrefs = NULL;
+ cd->clinitrefs = NULL;
cd->linenumberreferences = NULL;
cd->linenumbertablesizepos = 0;
cd->linenumbertablestartpos = 0;
cd->linenumbertab = 0;
- cd->method=m;
- cd->exceptiontable=0;
- cd->exceptiontablelength=0;
- if (useinlining && e) {
- if (e->cumextablelength>0) {
- cd->exceptiontablelength=e->cumextablelength;
- cd->exceptiontable = MNEW(exceptiontable, e->cumextablelength + 1);
+ cd->method = m;
+ 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 (e && (e->method->exceptiontablelength >0)) {
- cd->exceptiontablelength=m->exceptiontablelength;
- cd->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength + 1);
+
+ } else if (id && (id->method->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;
}
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
}
-/* codegen_close releases temporary code and data area */
+/* codegen_free ****************************************************************
-void codegen_close(methodinfo *m)
-{
- codegendata *cd;
+ releases temporary code and data area
- cd = m->codegendata;
+*******************************************************************************/
+void codegen_free(methodinfo *m, codegendata *cd)
+{
if (cd) {
+#if 0
if (cd->exceptiontablelength) {
- cd->exceptiontablelength=m->exceptiontablelength;
+ cd->exceptiontablelength = m->exceptiontablelength;
MFREE(cd->exceptiontable, exceptiontable, cd->exceptiontablelength + 1);
- cd->exceptiontable=0;
- cd->exceptiontablelength=0;
+ cd->exceptiontable = 0;
+ cd->exceptiontablelength = 0;
}
+#endif
+
if (cd->mcodebase) {
MFREE(cd->mcodebase, u1, cd->mcodesize);
cd->mcodebase = NULL;
MFREE(cd->dsegtop - cd->dsegsize, u1, cd->dsegsize);
cd->dsegtop = NULL;
}
-
- FREE(m->codegendata, codegendata);
- m->codegendata = NULL;
}
}
+/* codegen_close ***************************************************************
+
+ TODO
+
+*******************************************************************************/
+
+void codegen_close()
+{
+ /* TODO: release avl tree on i386 and x86_64 */
+}
+
+
/* codegen_increase doubles code area */
-static s4 *codegen_increase(methodinfo *m, u1 *codeptr)
+static s4 *codegen_increase(codegendata *cd, u1 *codeptr)
{
- codegendata *cd;
long len;
- cd = m->codegendata;
-
len = codeptr - cd->mcodebase;
cd->mcodebase = MREALLOC(cd->mcodebase,
u1,
/* desg_increase doubles data area */
-static void dseg_increase(methodinfo *m)
+static void dseg_increase(codegendata *cd)
{
- codegendata *cd;
u1 *newstorage;
- cd = m->codegendata;
-
newstorage = MNEW(u1, cd->dsegsize * 2);
memcpy(newstorage + cd->dsegsize, cd->dsegtop - cd->dsegsize, cd->dsegsize);
}
-static s4 dseg_adds4_increase(methodinfo *m, s4 value)
+static s4 dseg_adds4_increase(codegendata *cd, s4 value)
{
- codegendata *cd;
-
- cd = m->codegendata;
-
- dseg_increase(m);
+ dseg_increase(cd);
*((s4 *) (cd->dsegtop - cd->dseglen)) = value;
}
-static s4 dseg_adds4(methodinfo *m, s4 value)
+static s4 dseg_adds4(codegendata *cd, s4 value)
{
- codegendata *cd;
s4 *dataptr;
- cd = m->codegendata;
-
cd->dseglen += 4;
dataptr = (s4 *) (cd->dsegtop - cd->dseglen);
if (cd->dseglen > cd->dsegsize)
- return dseg_adds4_increase(m, value);
+ return dseg_adds4_increase(cd, value);
*dataptr = value;
#if !defined(__I386__)
-static s4 dseg_adds8_increase(methodinfo *m, s8 value)
+static s4 dseg_adds8_increase(codegendata *cd, s8 value)
{
- codegendata *cd;
-
- cd = m->codegendata;
-
- dseg_increase(m);
+ dseg_increase(cd);
*((s8 *) (cd->dsegtop - cd->dseglen)) = value;
}
-static s4 dseg_adds8(methodinfo *m, s8 value)
+static s4 dseg_adds8(codegendata *cd, s8 value)
{
- codegendata *cd;
s8 *dataptr;
- cd = m->codegendata;
-
cd->dseglen = ALIGN(cd->dseglen + 8, 8);
dataptr = (s8 *) (cd->dsegtop - cd->dseglen);
if (cd->dseglen > cd->dsegsize)
- return dseg_adds8_increase(m, value);
+ return dseg_adds8_increase(cd, value);
*dataptr = value;
#endif
-static s4 dseg_addfloat_increase(methodinfo *m, float value)
+static s4 dseg_addfloat_increase(codegendata *cd, float value)
{
- codegendata *cd;
-
- cd = m->codegendata;
-
- dseg_increase(m);
+ dseg_increase(cd);
*((float *) (cd->dsegtop - cd->dseglen)) = value;
}
-static s4 dseg_addfloat(methodinfo *m, float value)
+static s4 dseg_addfloat(codegendata *cd, float value)
{
- codegendata *cd;
float *dataptr;
- cd = m->codegendata;
-
cd->dseglen += 4;
dataptr = (float *) (cd->dsegtop - cd->dseglen);
if (cd->dseglen > cd->dsegsize)
- return dseg_addfloat_increase(m, value);
+ return dseg_addfloat_increase(cd, value);
*dataptr = value;
}
-static s4 dseg_adddouble_increase(methodinfo *m, double value)
+static s4 dseg_adddouble_increase(codegendata *cd, double value)
{
- codegendata *cd;
-
- cd = m->codegendata;
-
- dseg_increase(m);
+ dseg_increase(cd);
*((double *) (cd->dsegtop - cd->dseglen)) = value;
}
-static s4 dseg_adddouble(methodinfo *m, double value)
+static s4 dseg_adddouble(codegendata *cd, double value)
{
- codegendata *cd;
double *dataptr;
- cd = m->codegendata;
-
cd->dseglen = ALIGN(cd->dseglen + 8, 8);
dataptr = (double *) (cd->dsegtop - cd->dseglen);
if (cd->dseglen > cd->dsegsize)
- return dseg_adddouble_increase(m, value);
+ return dseg_adddouble_increase(cd, value);
*dataptr = value;
}
-static void dseg_addtarget(methodinfo *m, basicblock *target)
+static void dseg_addtarget(codegendata *cd, basicblock *target)
{
- codegendata *cd;
jumpref *jr;
- cd = m->codegendata;
-
jr = DNEW(jumpref);
- jr->tablepos = dseg_addaddress(m, NULL);
+ jr->tablepos = dseg_addaddress(cd, NULL);
jr->target = target;
jr->next = cd->jumpreferences;
cd->jumpreferences = jr;
}
-static void dseg_adddata(methodinfo *m, u1 *ptr)
+static void dseg_adddata(codegendata *cd, u1 *ptr)
{
- codegendata *cd;
dataref *dr;
- cd = m->codegendata;
-
dr = DNEW(dataref);
dr->pos = (u1 *) (ptr - cd->mcodebase);
dr->next = cd->datareferences;
}
-static void dseg_addlinenumbertablesize(methodinfo *m)
+static void dseg_addlinenumbertablesize(codegendata *cd)
{
- codegendata *cd;
-
- cd = m->codegendata;
-
#ifdef __ALPHA__
- dseg_adds4(m, 0); /*PADDING*/
+ dseg_adds4(cd, 0); /*PADDING*/
#endif
- cd->linenumbertablesizepos = dseg_addaddress(m, NULL); /*it could be considered to use adds4 here, to avoid 1 double word padding on ALPHA */
+ cd->linenumbertablesizepos = dseg_addaddress(cd, NULL); /*it could be considered to use adds4 here, to avoid 1 double word padding on ALPHA */
- cd->linenumbertablestartpos = dseg_addaddress(m, NULL);
+ cd->linenumbertablestartpos = dseg_addaddress(cd, NULL);
#ifdef __ALPHA__
- dseg_adds4(m, 0); /*PADDING*/
+ dseg_adds4(cd, 0); /*PADDING*/
#endif
}
-static void dseg_addlinenumber(methodinfo *m, u2 linenumber, u1 *ptr)
+static void dseg_addlinenumber(codegendata *cd, u2 linenumber, u1 *ptr)
{
- codegendata *cd;
linenumberref *lr;
- cd = m->codegendata;
-
lr = DNEW(linenumberref);
lr->linenumber = linenumber;
lr->tablepos = 0;
on alpha... */
#if defined(__I386__) || defined(__X86_64__)
-void codegen_addreference(methodinfo *m, basicblock *target, void *branchptr)
+void codegen_addreference(codegendata *cd, basicblock *target, void *branchptr)
#else
-static void codegen_addreference(methodinfo *m, basicblock *target, void *branchptr)
+static void codegen_addreference(codegendata *cd, basicblock *target, void *branchptr)
#endif
{
- codegendata *cd;
s4 branchpos;
- cd = m->codegendata;
-
branchpos = (u1 *) branchptr - cd->mcodebase;
if (target->mpc >= 0) {
}
-static void codegen_addxboundrefs(methodinfo *m, void *branchptr, s4 reg)
+static void codegen_addxboundrefs(codegendata *cd, void *branchptr, s4 reg)
{
- codegendata *cd;
s4 branchpos;
branchref *br;
- cd = m->codegendata;
-
branchpos = (u1 *) branchptr - cd->mcodebase;
br = DNEW(branchref);
}
-static void codegen_addxcheckarefs(methodinfo *m, void *branchptr)
+static void codegen_addxcheckarefs(codegendata *cd, void *branchptr)
{
- codegendata *cd;
s4 branchpos;
branchref *br;
- cd = m->codegendata;
-
branchpos = (u1 *) branchptr - cd->mcodebase;
br = DNEW(branchref);
}
-static void codegen_addxnullrefs(methodinfo *m, void *branchptr)
+static void codegen_addxnullrefs(codegendata *cd, void *branchptr)
{
- codegendata *cd;
s4 branchpos;
branchref *br;
- cd = m->codegendata;
-
branchpos = (u1 *) branchptr - cd->mcodebase;
br = DNEW(branchref);
}
-
-static void codegen_addxcastrefs(methodinfo *m, void *branchptr)
+static void codegen_addxcastrefs(codegendata *cd, void *branchptr)
{
- codegendata *cd;
s4 branchpos;
branchref *br;
- cd = m->codegendata;
-
branchpos = (u1 *) branchptr - cd->mcodebase;
br = DNEW(branchref);
}
-static void codegen_addxexceptionrefs(methodinfo *m, void *branchptr)
+static void codegen_addxexceptionrefs(codegendata *cd, void *branchptr)
{
- codegendata *cd;
s4 branchpos;
branchref *br;
- cd = m->codegendata;
-
branchpos = (u1 *) branchptr - cd->mcodebase;
br = DNEW(branchref);
#if defined(__I386__) || defined(__X86_64__)
-static void codegen_addxdivrefs(methodinfo *m, void *branchptr)
+static void codegen_addxdivrefs(codegendata *cd, void *branchptr)
{
- codegendata *cd;
s4 branchpos;
branchref *br;
- cd = m->codegendata;
-
branchpos = (u1 *) branchptr - cd->mcodebase;
br = DNEW(branchref);
#endif
-static void codegen_createlinenumbertable(methodinfo *m)
+static void codegen_addclinitref(codegendata *cd,
+ void *branchptr,
+ classinfo *class)
{
-#ifdef __I386__
- codegendata *cd;
- linenumberref *lr;
+ s4 branchpos;
+ clinitref *cr;
- cd = m->codegendata;
+ branchpos = (u1 *) branchptr - cd->mcodebase;
+
+ cr = DNEW(clinitref);
+ cr->branchpos = branchpos;
+ cr->class = class;
+ cr->next = cd->clinitrefs;
+ cd->clinitrefs = cr;
+}
+
+
+static void codegen_createlinenumbertable(codegendata *cd)
+{
+#if defined(__I386__) || defined(__ALPHA__)
+ linenumberref *lr;
for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
- lr->tablepos = dseg_addaddress(m, NULL);
+ lr->tablepos = dseg_addaddress(cd, NULL);
if (cd->linenumbertab == 0)
cd->linenumbertab = lr->tablepos;
- dseg_addaddress(m, lr->linenumber);
+ dseg_addaddress(cd, lr->linenumber);
}
#endif
}
/* compare both startpc and endpc of pc, even if they have the same value,
otherwise the avl_probe sometimes thinks the element is already in the
tree */
- if (mte->startpc <= mtepc->startpc && mtepc->startpc <= mte->endpc &&
- mte->startpc <= mtepc->endpc && mtepc->endpc <= mte->endpc) {
+ if ((long) mte->startpc <= (long) mtepc->startpc &&
+ (long) mtepc->startpc <= (long) mte->endpc &&
+ (long) mte->startpc <= (long) mtepc->endpc &&
+ (long) mtepc->endpc <= (long) mte->endpc) {
return 0;
- } else if (mtepc->startpc < mte->startpc) {
+ } else if ((long) mtepc->startpc < (long) mte->startpc) {
return -1;
} else {
#endif
-void codegen_insertmethod(void *startpc, void *endpc)
+void codegen_insertmethod(functionptr startpc, functionptr endpc)
{
methodtree_element *mte;
}
-void *codegen_findmethod(void *pc)
+functionptr codegen_findmethod(functionptr pc)
{
methodtree_element *mtepc;
methodtree_element *mte;
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+ tables_lock();
+#endif
+#endif
+
mtepc = NEW(methodtree_element);
mtepc->startpc = pc;
mtepc->endpc = pc;
FREE(mtepc, methodtree_element);
- if (!mte)
+ if (!mte) {
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+ tables_unlock();
+#endif
+#endif
throw_cacao_exception_exit(string_java_lang_InternalError,
"cannot find function");
+ }
+
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+ tables_unlock();
+#endif
+#endif
return mte->startpc;
}
#endif
+#if defined(__ALPHA__)
+/*perhaps in the end I'll have to go for the tree version on alpha too, since this is insecure for eg segfault signals in native code,
+since it will still return an adress of a datasegment, but which will not be a valid one of a java method. This version is faster though (jowenn)*/
+void *codegen_findmethod(void *returnAdress)
+ {
+ void *result;
+ s8 d;
+ void *dataseg;
+ d=*((s4*)returnAdress);
+ d=d<<48;
+ d=d>>48;
+ dataseg=returnAdress+d;
+ d=*(((s4*)returnAdress)+1);
+ d=d>>16;
+ d=d-0x177b;
+ if (d==0) {
+ d=*(((s4*)returnAdress)+1);
+ d=d<<16;
+ dataseg=dataseg+d;
+ }
+ return dataseg;
+#if 0
+ ldl t0,0(ra) /* load instruction LDA PV,xxx(RA) */
+ sll t0,48,t0
+ sra t0,48,t0 /* isolate offset */
+ addq t0,ra,pv /* compute update address */
+ ldl t0,4(ra) /* load instruction LDAH PV,xxx(PV) */
+ srl t0,16,t0 /* isolate instruction code */
+ lda t0,-0x177b(t0) /* test for LDAH */
+ bne t0,ex_stack_loop
+ ldl t0,4(ra) /* load instruction LDAH PV,xxx(RA) */
+ sll t0,16,t0 /* compute high offset */
+ addl t0,0,t0 /* sign extend high offset */
+ addq t0,pv,pv /* compute update address */
+ br ex_stack_loop
+#endif
+}
+
+#endif
-static void codegen_finish(methodinfo *m, s4 mcodelen)
+
+static void codegen_finish(methodinfo *m, codegendata *cd, s4 mcodelen)
{
- codegendata *cd;
jumpref *jr;
- u1 *epoint;
- s4 extralen = 0;
+ functionptr epoint;
+ s4 extralen;
s4 alignedlen;
- cd = m->codegendata;
-
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
- extralen += sizeof(threadcritnode) * cd->threadcritcount;
+ extralen = sizeof(threadcritnode) * cd->threadcritcount;
+#else
+ extralen = 0;
#endif
#if defined(STATISTICS)
alignedlen = ALIGN(mcodelen, MAX_ALIGN) + cd->dseglen;
m->mcodelength = mcodelen + cd->dseglen;
- m->mcode = CNEW(u1, alignedlen + extralen);
+ m->mcode = (functionptr) (long) CNEW(u1, alignedlen + extralen);
- memcpy(m->mcode, cd->dsegtop - cd->dseglen, cd->dseglen);
- memcpy(m->mcode + cd->dseglen, cd->mcodebase, mcodelen);
+ memcpy((void *) (long) m->mcode, cd->dsegtop - cd->dseglen, cd->dseglen);
+ memcpy((void *) ((long) m->mcode + cd->dseglen), cd->mcodebase, mcodelen);
- m->entrypoint = epoint = (u1 *) (m->mcode + cd->dseglen);
+ m->entrypoint = epoint = (functionptr) ((long) m->mcode + cd->dseglen);
/* jump table resolving */
jr = cd->jumpreferences;
while (jr != NULL) {
- *((void**) (epoint + jr->tablepos)) = epoint + jr->target->mpc;
- jr = jr->next;
+ *((functionptr *) ((long) epoint + jr->tablepos)) =
+ (functionptr) ((long) epoint + (long) jr->target->mpc);
+ jr = jr->next;
}
-#ifdef __I386__
+#if defined(__I386__) || defined(__ALPHA__)
/* line number table resolving */
{
linenumberref *lr;
for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
lrtlen++;
- *((void**) (epoint + lr->tablepos)) = epoint + lr->targetmpc;
+ *((functionptr *) ((long) epoint + (long) lr->tablepos)) =
+ (functionptr) ((long) epoint + (long) lr->targetmpc);
}
- *((void**) (epoint + cd->linenumbertablestartpos)) =
- epoint + cd->linenumbertab;
+ *((functionptr *) ((long) epoint + cd->linenumbertablestartpos)) =
+ (functionptr) ((long) epoint + cd->linenumbertab);
#if POINTERSIZE == 8
- *((s8*) (epoint + cd->linenumbertablesizepos)) = lrtlen;
+ *((s8 *) ((s8) epoint + cd->linenumbertablesizepos)) = lrtlen;
#else
- *((s4*) (epoint + cd->linenumbertablesizepos)) = lrtlen;
+ *((s4 *) ((s4) epoint + cd->linenumbertablesizepos)) = lrtlen;
#endif
}
#endif
dataref *dr;
/* add method into methodtree to find the entrypoint */
- codegen_insertmethod(m->entrypoint, m->entrypoint + mcodelen);
+ codegen_insertmethod(m->entrypoint,
+ (functionptr) ((long) m->entrypoint + mcodelen));
/* data segment references resolving */
dr = cd->datareferences;
while (dr != NULL) {
- *((void**) ((long) epoint + (long) dr->pos - POINTERSIZE)) = epoint;
+ *((functionptr *) ((long) epoint + (long) dr->pos - POINTERSIZE)) =
+ epoint;
dr = dr->next;
}
}
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
{
- threadcritnode *n = (threadcritnode *) (m->mcode + alignedlen);
+ threadcritnode *n = (threadcritnode *) ((long) m->mcode + alignedlen);
s4 i;
threadcritnodetemp *nt = cd->threadcrit;
for (i = 0; i < cd->threadcritcount; i++) {
- n->mcodebegin = m->mcode + nt->mcodebegin;
- n->mcodeend = m->mcode + nt->mcodeend;
- n->mcoderestart = m->mcode + nt->mcoderestart;
+ n->mcodebegin = (u1 *) (long) m->mcode + nt->mcodebegin;
+ n->mcodeend = (u1 *) (long) m->mcode + nt->mcodeend;
+ n->mcoderestart = (u1 *) (long) m->mcode + nt->mcoderestart;
thread_registercritical(n);
n++;
nt = nt->next;
}
-void dseg_display(methodinfo *m)
+void dseg_display(methodinfo *m, codegendata *cd)
{
s4 *s4ptr;
s4 i;
- s4ptr = (s4 *) m->mcode;
+ s4ptr = (s4 *) (long) m->mcode;
printf(" --- dump of datasegment\n");
- for (i = m->codegendata->dseglen; i > 0 ; i -= 4) {
+ for (i = cd->dseglen; i > 0 ; i -= 4) {
printf("-%6x: %8x\n", i, (s4) (*s4ptr++));
}
- printf(" --- begin of data segment: %p\n", s4ptr);
+ printf(" --- begin of data segment: %p\n", (void *) s4ptr);
}
-#if !defined(__POWERPC__)
/* 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 result in
If not already done, regoff and flags are set in the stack location.
*/
-static int reg_of_var(methodinfo *m, stackptr v, int tempregnum)
+static int reg_of_var(registerdata *rd, stackptr v, int tempregnum)
{
varinfo *var;
return(v->regoff);
break;
case STACKVAR:
- var = &(m->registerdata->interfaces[v->varnum][v->type]);
+ var = &(rd->interfaces[v->varnum][v->type]);
v->regoff = var->regoff;
if (!(var->flags & INMEMORY))
return(var->regoff);
break;
case LOCALVAR:
- var = &(m->registerdata->locals[v->varnum][v->type]);
+ var = &(rd->locals[v->varnum][v->type]);
v->regoff = var->regoff;
if (!(var->flags & INMEMORY))
return(var->regoff);
case ARGVAR:
v->regoff = v->varnum;
if (IS_FLT_DBL_TYPE(v->type)) {
- if (v->varnum < m->registerdata->fltreg_argnum) {
- v->regoff = m->registerdata->argfltregs[v->varnum];
- return(m->registerdata->argfltregs[v->varnum]);
+ if (v->varnum < rd->fltreg_argnum) {
+ v->regoff = rd->argfltregs[v->varnum];
+ return(rd->argfltregs[v->varnum]);
}
- }
- else
- if (v->varnum < m->registerdata->intreg_argnum) {
- v->regoff = m->registerdata->argintregs[v->varnum];
- return(m->registerdata->argintregs[v->varnum]);
+
+ } else {
+#if defined(__POWERPC__)
+ if (v->varnum < rd->intreg_argnum - (IS_2_WORD_TYPE(v->type) != 0)) {
+#else
+ if (v->varnum < rd->intreg_argnum) {
+#endif
+ v->regoff = rd->argintregs[v->varnum];
+ return (rd->argintregs[v->varnum]);
}
- v->regoff -= m->registerdata->intreg_argnum;
+ }
+#if defined(__POWERPC__)
+ v->regoff += 6;
+#else
+ v->regoff -= rd->intreg_argnum;
+#endif
break;
}
v->flags |= INMEMORY;
return tempregnum;
}
-#endif
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-static void codegen_threadcritrestart(methodinfo *m, int offset)
+static void codegen_threadcritrestart(codegendata *cd, int offset)
{
- m->codegendata->threadcritcurrent.mcoderestart = offset;
+ cd->threadcritcurrent.mcoderestart = offset;
}
-static void codegen_threadcritstart(methodinfo *m, int offset)
-{
- m->codegendata->threadcritcurrent.mcodebegin = offset;
-}
-static void codegen_threadcritstop(methodinfo *m, int offset)
+static void codegen_threadcritstart(codegendata *cd, int offset)
{
- codegendata *cd;
+ cd->threadcritcurrent.mcodebegin = offset;
+}
- cd = m->codegendata;
+static void codegen_threadcritstop(codegendata *cd, int offset)
+{
cd->threadcritcurrent.next = cd->threadcrit;
cd->threadcritcurrent.mcodeend = offset;
cd->threadcrit = DNEW(threadcritnodetemp);
}
#endif
+
+#ifndef STATIC_CLASSPATH
+static size_t codegen_overloadPartLen(utf *desc) {
+ char *utf_ptr=desc->text;
+ u2 c;
+ size_t len=2;
+ while ((c=utf_nextu2(&utf_ptr))!=')') {
+ switch (c) {
+ case 'I':
+ case 'S':
+ case 'B':
+ case 'C':
+ case 'Z':
+ case 'J':
+ case 'F':
+ case 'D':
+ len ++;
+ break;
+ case '[':
+ len = len+2;
+ break;
+ case 'L':
+ len++;
+ while ( (c=utf_nextu2(&utf_ptr)) != ';')
+ len++;
+ len=len+2;
+ break;
+ case '(':
+ break;
+ default: panic ("invalid method descriptor");
+ }
+ }
+ return len;
+
+}
+
+static void codegen_fillInOverloadPart(char *target,utf *desc) {
+ char *utf_ptr=desc->text;
+ u2 c;
+ char* insertpos=&target[strlen(target)];
+ *(insertpos++)='_';
+ *(insertpos++)='_';
+ while ((c=utf_nextu2(&utf_ptr))!=')') {
+ switch (c) {
+ case 'I':
+ case 'S':
+ case 'B':
+ case 'C':
+ case 'Z':
+ case 'J':
+ case 'F':
+ case 'D':
+ *(insertpos++)=c;
+ break;
+ case '[':
+ *(insertpos++)='_';
+ *(insertpos++)='3';
+ break;
+ case 'L':
+ *(insertpos++)='L';
+ while ( (c=utf_nextu2(&utf_ptr)) != ';')
+ if ( ((c>='a') && (c<='z')) ||
+ ((c>='A') && (c<='Z')) ||
+ ((c>='0') && (c<='9')) )
+ *(insertpos++)=c;
+ else *(insertpos++)='_';
+ *(insertpos++)='_';
+ *(insertpos++)='2';
+ break;
+ case '(':
+ break;
+ default: panic ("invalid method descriptor");
+ }
+ }
+ *insertpos='\0';
+
+}
+
+static void codegen_resolve_native(methodinfo *m,void **insertionPoint,void *jmpTarget,void **jmpPatchTarget) {
+ char *nativeName, *nativeNameEscape;
+ size_t nativeLen;
+ size_t i;
+ void *lib;
+ void *sym;
+
+ builtin_monitorenter((java_objectheader*) m);
+#if defined(__X86_64__)
+ if ((*((s4*)jmpPatchTarget))==((s4)jmpTarget)) {
+#else
+ if ((*jmpPatchTarget)==jmpTarget) {
+#endif
+ builtin_monitorexit((java_objectheader*) m);
+ return;
+ }
+ /*log_text("trying to resolve a native method");
+ utf_display(m->class->name);
+ utf_display(m->name);*/
+
+ lib=dlopen(0,RTLD_NOW | RTLD_GLOBAL); /* open the application execution image */
+ if (lib) { /* it did work -> good, otherwise fail with error*/
+ int ok=0;
+ /*generate the name of the native function in the form Java_package1_package2...._classname_methodname*/
+ nativeLen=/*Java_*/5+strlen(m->class->name->text)+/*_*/1+strlen(m->name->text)+/*\0*/1;
+ nativeName=MNEW(char,nativeLen);
+ sprintf(nativeName,"Java_%s/%s",m->class->name->text,m->name->text);
+ i=5;
+ while (i<nativeLen) {
+ if (nativeName[i]=='_') { /* escape underscore */
+ nativeNameEscape = MNEW(char,nativeLen+1);
+ memcpy(nativeNameEscape,nativeName,i+1);
+ nativeNameEscape[i+1] = '1'; /* escape sequence for _ is _1 */
+ memcpy(&nativeNameEscape[i+2],&nativeName[i+1],nativeLen-i-1);
+ MFREE(nativeName,char,nativeLen);
+ i++;
+ nativeLen++;
+ nativeNameEscape[nativeLen]=0;
+ nativeName=nativeNameEscape;
+ }
+ if (nativeName[i]=='/') nativeName[i]='_';
+ i++;
+ }
+
+/* printf("nativename: %s\n",nativeName); */
+
+ /*try to find the symbal fo the function */
+ sym=dlsym(lib,nativeName);
+ if (sym) {
+ ok=1; /* it worked, everything fine */
+ /*log_text("resolved");*/
+ MFREE(nativeName,char,nativeLen);
+ } else { /* we didn't find the symbol yet, try to resolve an overlaoded function (having the types in it's name*/
+ size_t overloadedNativeLen=nativeLen+codegen_overloadPartLen(m->descriptor);
+ char *overloadedNative=MNEW(char,overloadedNativeLen);
+ sprintf(overloadedNative,"%s",nativeName);
+ MFREE(nativeName,char,nativeLen);
+ codegen_fillInOverloadPart(overloadedNative,m->descriptor);
+ /*log_text("symbol not found,trying harder (overloaded member ?)");*/
+ sym=dlsym(lib,overloadedNative);
+ if (sym) {
+ MFREE(overloadedNative,char,overloadedNativeLen);
+ ok=1; /* we eventually found the native function -> everything ok*/
+ /*log_text("resolved");*/
+ } else {
+ /* we failed to find the native function within the execution image (app + loaded libraries) -> will cause an exit*/
+ MFREE(overloadedNative,char,overloadedNativeLen);
+ log_text("It was not possible to find the native function implementation. Not even in overloading case");
+ }
+ }
+ /* patch the address of the native function into the stub and make the stub jump over this function call in the future */
+ if (ok) {
+ (*insertionPoint)=sym;
+#if defined(__X86_64__)
+ (*((s4*)jmpPatchTarget))=(s4)jmpTarget;
+#else
+ (*jmpPatchTarget)=jmpTarget;
+#endif
+ builtin_monitorexit((java_objectheader *) m );
+ return;
+ }
+
+ } else log_text("library not found");
+
+ /* There was an error, either the app image could not be opened or the native does not exist in the application and the
+ loaded libraries. Show an additional error and exit the vm*/
+ {
+ char *info;
+ size_t slen;
+ slen=2+strlen(m->class->name->text)+strlen(m->name->text)+strlen(m->descriptor->text);
+ info=(char*)MNEW(char,slen);
+ sprintf(info,"%s.%s%s",m->class->name->text,m->name->text,m->descriptor->text);
+
+ builtin_monitorexit((java_objectheader *) m );
+ throw_cacao_exception_exit(string_java_lang_LinkageError,
+ info);
+ }
+
+}
+#endif
+
+
+#endif
+
/*
* 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