-/* 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
Authors: Reinhard Grafl
Andreas Krall
- Changes: Michael Gschwind
- Christian Thalinger
+ Changes: Christian Thalinger
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 1346 2004-07-21 23:29:21Z twisti $
+ $Id: codegen.inc 1680 2004-12-04 12:02:08Z jowenn $
*/
+#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)
+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 && id) {
+ if (id->cumextablelength > 0) {
+ cd->exceptiontablelength = id->cumextablelength;
+ cd->exceptiontable = DMNEW(exceptiontable, id->cumextablelength + 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)
cd->threadcritcurrent.next = NULL;
}
-/* 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;
+ MFREE(cd->exceptiontable, exceptiontable, cd->exceptiontablelength + 1);
+ 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)
+{
+ s4 branchpos;
+ clinitref *cr;
+
+ 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)
{
#ifdef __I386__
- codegendata *cd;
linenumberref *lr;
- cd = m->codegendata;
-
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
-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__
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 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;
#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