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 883 2004-01-14 12:42:52Z stefan $
+ $Id: codegen.inc 1116 2004-06-02 10:34:31Z twisti $
*/
#include <string.h>
#include "toolbox/memory.h"
-#include "toolbox/loging.h"
+#include "toolbox/logging.h"
+#include "toolbox/avl.h"
#include "threads/thread.h"
struct threadcritnodetemp {
struct threadcritnodetemp *next;
- int mcodebegin, mcodeend;
+ int mcodebegin, mcodeend, mcoderestart;
};
#define MCODEINITSIZE (1<<15) /* 32 Kbyte code area initialization size */
static branchref *xnullrefs; /* list of null check branches */
static branchref *xcastrefs; /* list of cast check branches */
static branchref *xdivrefs; /* list of divide by zero branches */
+static branchref *xexceptionrefs; /* list of exception branches */
+static linenumberref *linenumberreferences; /*list of line numbers and the program counters of their first instruction*/
+static s4 linenumbertablesizepos;
+static s4 linenumbertablestartpos;
+static s4 linenumbertab;
static struct threadcritnodetemp *threadcrit;
/* List of critical code regions */
/* updates branch references to code/data */
static s4 dseg_adds4(s4 value); /* adds an int to data area */
+
+#if !defined(__I386__)
static s4 dseg_adds8(s8 value); /* adds an long to data area */
+#endif
+
static s4 dseg_addfloat (float value); /* adds an float to data area */
static s4 dseg_adddouble(double value); /* adds an double to data area */
static void dseg_addtarget(basicblock *target);
static void dseg_adddata(u1 *ptr);
static void codegen_addreference(basicblock *target, void *branchptr);
-static void codegen_addxboundrefs(void *branchptr);
+static void codegen_addxboundrefs(void *branchptr, s4 reg);
static void codegen_addxnullrefs(void *branchptr);
static void codegen_addxcastrefs(void *branchptr);
static void codegen_addxdivrefs(void *branchptr);
+static void codegen_addxexceptionrefs(void *branchptr);
+static void codegen_threadcritrestart(int offset);
static void codegen_threadcritstart(int offset);
static void codegen_threadcritstop(int offset);
+#if defined(__I386__) || defined(__X86_64__)
+typedef struct _methodtree_element methodtree_element;
+
+struct _methodtree_element {
+ void *startpc;
+ void *endpc;
+};
+
+static struct avl_table *methodtree;
+static int methodtree_comparator(const void *pc, const void *element,
+ void *param);
+#endif
+
void dseg_display(s4 *s4ptr);
-/* codegen_init allocates and initialises code area, data area and references */
+/* codegen_init allocates and initialises code area, data area and references */
void codegen_init()
{
dseglen = 0;
+ linenumberreferences = NULL;
+ linenumbertablesizepos = 0;
+ linenumbertablestartpos = 0;
+ linenumbertab = 0;
jumpreferences = NULL;
datareferences = NULL;
xboundrefs = NULL;
+ xcheckarefs = NULL;
xnullrefs = NULL;
xcastrefs = NULL;
xdivrefs = NULL;
+ xexceptionrefs = NULL;
+
+#if defined(__I386__) || defined(__X86_64__)
+ methodtree = avl_create(methodtree_comparator, NULL, NULL);
+#endif
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
threadcritcurrent.next = NULL;
-/* codegen_close releases temporary code and data area */
+/* codegen_close releases temporary code and data area */
void codegen_close()
{
-/* codegen_increase doubles code area */
+/* codegen_increase doubles code area */
static s4 *codegen_increase(u1 *codeptr)
{
+#if !defined(__I386__)
static s4 dseg_adds8_increase(s8 value)
{
dseg_increase();
}
-
static s4 dseg_adds8(s8 value)
{
s8 *dataptr;
*dataptr = value;
return -dseglen;
}
-
+#endif
static s4 dseg_addfloat_increase(float value)
static void dseg_addtarget(basicblock *target)
{
jumpref *jr = DNEW(jumpref);
-
+
jr->tablepos = dseg_addaddress(NULL);
jr->target = target;
jr->next = jumpreferences;
datareferences = dr;
}
+static void dseg_addlinenumbertablesize() {
+#ifdef __ALPHA__
+ dseg_adds4(0); /*PADDING*/
+#endif
+ linenumbertablesizepos=dseg_addaddress(NULL); /*it could be considered to use adds4 here, to avoid 1 double word padding on ALPHA */
+
+ linenumbertablestartpos=dseg_addaddress(NULL);
+#ifdef __ALPHA__
+ dseg_adds4(0); /*PADDING*/
+#endif
+}
+static void dseg_addlinenumber(u2 linenumber,u1 *ptr) {
+ linenumberref *lr=DNEW(linenumberref);
+ lr->linenumber=linenumber;
+ lr->tablepos=0;
+ lr->targetmpc=(ptr-mcodebase);
+ lr->next=linenumberreferences;
+ linenumberreferences=lr;
+}
static void codegen_addreference(basicblock *target, void *branchptr)
{
-static void codegen_addxboundrefs(void *branchptr)
+static void codegen_addxboundrefs(void *branchptr, s4 reg)
{
s4 branchpos = (u1*) branchptr - mcodebase;
branchref *br = DNEW(branchref);
br->branchpos = branchpos;
+ br->reg = reg;
br->next = xboundrefs;
xboundrefs = br;
}
}
+static void codegen_addxexceptionrefs(void *branchptr)
+{
+ s4 branchpos = (u1*) branchptr - mcodebase;
+
+ branchref *br = DNEW(branchref);
+
+ br->branchpos = branchpos;
+ br->next = xexceptionrefs;
+ xexceptionrefs = br;
+}
+
static void codegen_addxdivrefs(void *branchptr)
{
}
+static void codegen_createlinenumbertable() {
+#ifdef __I386__
+ /*log_text("codegen_createlinnumbertable");*/
+ {
+ linenumberref *lr;
+ for (lr=linenumberreferences;lr!=NULL;lr=lr->next) {
+ /*log_text("Adding line number entry");*/
+ lr->tablepos=dseg_addaddress(NULL);
+ if (linenumbertab==0) linenumbertab=lr->tablepos;
+ dseg_addaddress(lr->linenumber);
+ }
+ }
+#endif
+}
+
+
+#if defined(__I386__) || defined(__X86_64__)
+static int methodtree_comparator(const void *pc, const void *element,
+ void *param)
+{
+ methodtree_element *mtepc;
+ methodtree_element *mte;
+
+ mtepc = (methodtree_element *) pc;
+ mte = (methodtree_element *) element;
+
+ if (mte->startpc <= mtepc->startpc && mtepc->startpc <= mte->endpc) {
+ return 0;
+
+ } else if (mtepc->startpc < mte->startpc) {
+ return -1;
+
+ } else {
+ return 1;
+ }
+}
+
+
+#if 0
+void *codegen_findmethod1(void *pc)
+{
+ void * retVal=findmethod(pc);
+ methodinfo **ma=(methodinfo**)retVal;
+ methodinfo *m=ma[-1];
+ if (m)
+ if (m->name)
+ utf_display(m->name);
+ else
+ log_text("No Name");
+ else log_text("No methodinfo");
+ return retVal;
+}
+#endif
+
+void *codegen_findmethod(void *pc)
+{
+#if 1
+ return findmethod(pc);
+#else
+ methodtree_element *mtepc;
+ methodtree_element *mte;
+
+ mtepc = NEW(methodtree_element);
+ mtepc->startpc = pc;
+
+ mte = avl_find(methodtree, mtepc);
+
+ FREE(mtepc, methodtree_element);
+
+/* if (!mte) */
+/* throw_cacao_exception_exit(string_java_lang_InternalError, "cannot find function"); */
+
+ fprintf(stderr, "mte=%p\n", mte);
+ fprintf(stderr, "startpc=%p, endpc=%p\n", mte->startpc, mte->endpc);
+
+ return mte->startpc;
+#endif
+}
+#endif
+
static void codegen_finish(int mcodelen)
{
dseglen = ALIGN(dseglen, MAX_ALIGN);
- method -> mcodelength = mcodelen + dseglen;
- method -> mcode = CNEW(u1, mcodelen + dseglen + extralen);
+ method->mcodelength = mcodelen + dseglen;
+ method->mcode = CNEW(u1, mcodelen + dseglen + extralen);
- memcpy ( method->mcode, dsegtop - dseglen, dseglen);
- memcpy ( method->mcode + dseglen, mcodebase, mcodelen);
+ memcpy(method->mcode, dsegtop - dseglen, dseglen);
+ memcpy(method->mcode + dseglen, mcodebase, mcodelen);
- method -> entrypoint = epoint = (u1*) (method->mcode + dseglen);
+ method->entrypoint = epoint = (u1 *) (method->mcode + dseglen);
/* jump table resolving */
jr = jumpreferences;
jr = jr->next;
}
+#ifdef __I386__
+ /* line number table resolving */
+ {
+ linenumberref *lr;
+ #if POINTERSIZE == 8
+ s8 lrtlen=0;
+ #else
+ s4 lrtlen=0;
+ #endif
+
+ for (lr=linenumberreferences;lr!=NULL;lr=lr->next) {
+ lrtlen++;
+ *((void**)(epoint+lr->tablepos))=epoint+lr->targetmpc;
+ /*log_text("resolving line number information");*/
+ }
+
+ *((void**)(epoint+linenumbertablestartpos))=epoint+linenumbertab;
+#if POINTERSIZE == 8
+ *((s8*)(epoint+linenumbertablesizepos))=lrtlen;
+#else
+ *((s4*)(epoint+linenumbertablesizepos))=lrtlen;
+#endif
+
+ }
+#endif
#if defined(__I386__) || defined(__X86_64__)
{
dataref *dr;
- /* add method into datastructure to find the entrypoint */
+#if 1
+ /* add method into methodtree to find the entrypoint */
addmethod(method->entrypoint, method->entrypoint + mcodelen);
-
+#else
+ methodtree_element *mte;
+ methodtree_element *p;
+
+ mte = NEW(methodtree_element);
+ mte->startpc = method->entrypoint;
+ mte->endpc = method->entrypoint + mcodelen;
+
+ p = avl_insert(methodtree, mte);
+ printf("p=%p\n", p);
+#endif
+
/* data segment references resolving */
dr = datareferences;
while (dr != NULL) {
}
#endif
+
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
{
threadcritnode *n = (threadcritnode*) (method->mcode + mcodelen + dseglen);
{
n->mcodebegin = method->mcode + nt->mcodebegin;
n->mcodeend = method->mcode + nt->mcodeend;
+ n->mcoderestart = method->mcode + nt->mcoderestart;
thread_registercritical(n);
n++;
nt = nt->next;
}
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+void codegen_threadcritrestart(int offset)
+{
+ threadcritcurrent.mcoderestart = offset;
+}
+
void codegen_threadcritstart(int offset)
{
threadcritcurrent.mcodebegin = offset;