-/* 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 1456 2004-11-05 14:33: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"
-#ifndef STATIC_CLASSPATH
-#include <dlfcn.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
-/* in this tree we store all method addresses */
+#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 *********************************/
#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);
}
cd->xcastrefs = NULL;
cd->xdivrefs = NULL;
cd->xexceptionrefs = NULL;
+ cd->clinitrefs = NULL;
cd->linenumberreferences = NULL;
cd->linenumbertablesizepos = 0;
if (useinlining && id) {
if (id->cumextablelength > 0) {
cd->exceptiontablelength = id->cumextablelength;
- cd->exceptiontable = MNEW(exceptiontable, id->cumextablelength + 1);
+ cd->exceptiontable = DMNEW(exceptiontable, id->cumextablelength + 1);
}
} else if (id && (id->method->exceptiontablelength >0)) {
cd->exceptiontablelength = m->exceptiontablelength;
- cd->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength + 1);
+ cd->exceptiontable = DMNEW(exceptiontable, m->exceptiontablelength + 1);
}
if (id) {
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);
#endif
+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__
+#if defined(__I386__) || defined(__ALPHA__)
linenumberref *lr;
for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
/* 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;
}
#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, codegendata *cd, s4 mcodelen)
{
jumpref *jr;
- u1 *epoint;
+ functionptr epoint;
s4 extralen;
s4 alignedlen;
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;
+ *((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;
s4 *s4ptr;
s4 i;
- s4ptr = (s4 *) m->mcode;
+ s4ptr = (s4 *) (long) m->mcode;
printf(" --- dump of datasegment\n");
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
v->regoff = rd->argfltregs[v->varnum];
return(rd->argfltregs[v->varnum]);
}
- }
- else
+
+ } 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]);
}
+ }
+#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_resolve_native(methodinfo *m,void **insertionPoint,void *jmpTarget,void **jmpPatchTarget) {
- char *nativeName;
+ 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");
+ /*log_text("trying to resolve a native method");
utf_display(m->class->name);
- utf_display(m->name);
+ utf_display(m->name);*/
- void *lib=dlopen(0,RTLD_NOW | RTLD_GLOBAL);
- if (lib) {
+ 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);
- for (i=0;i<nativeLen;i++) {
- if (nativeName[i]=='/') nativeName[i]='_';
+ 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); */
- void *sym=dlsym(lib,nativeName);
+ /*try to find the symbal fo the function */
+ sym=dlsym(lib,nativeName);
if (sym) {
- ok=1;
- log_text("resolved");
+ ok=1; /* it worked, everything fine */
+ /*log_text("resolved");*/
MFREE(nativeName,char,nativeLen);
- } else {
+ } 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 ?)");
+ /*log_text("symbol not found,trying harder (overloaded member ?)");*/
sym=dlsym(lib,overloadedNative);
if (sym) {
MFREE(overloadedNative,char,overloadedNativeLen);
- ok=1;
- log_text("resolved");
+ 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;
#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