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 2507 2005-05-23 08:34:04Z twisti $
+ $Id: codegen.inc 2734 2005-06-17 13:01:06Z twisti $
*/
#include <assert.h>
#include <string.h>
-#if !defined(STATIC_CLASSPATH)
-# include <dlfcn.h>
-#endif
+#include "config.h"
+#include "types.h"
+
+#include "disass.h"
#include "mm/memory.h"
#include "toolbox/avl.h"
#endif
#include "vm/exceptions.h"
+#include "vm/method.h"
#include "vm/options.h"
#include "vm/statistics.h"
#include "vm/jit/codegen.inc.h"
+#include "vm/jit/jit.h"
#undef JWDEBUG_X86
*******************************************************************************/
-void codegen_init()
+void codegen_init(void)
{
#if defined(__I386__) || defined(__X86_64__)
/* this tree is global, not method specific */
void codegen_setup(methodinfo *m, codegendata *cd, t_inlining_globals *id)
{
- cd->mcodebase = MNEW(u1, MCODEINITSIZE);
+ cd->mcodebase = DMNEW(u1, MCODEINITSIZE);
cd->mcodesize = MCODEINITSIZE;
- cd->dsegtop = MNEW(u1, DSEGINITSIZE);
+ cd->dsegtop = DMNEW(u1, DSEGINITSIZE);
cd->dsegsize = DSEGINITSIZE;
cd->dsegtop += cd->dsegsize;
cd->dseglen = 0;
if (useinlining && id) {
if (id->cumextablelength > 0) {
cd->exceptiontablelength = id->cumextablelength;
- cd->exceptiontable = DMNEW(exceptiontable, id->cumextablelength + 1);
+ cd->exceptiontable =
+ DMNEW(exceptiontable, id->cumextablelength + 1);
}
- } else if (id && (id->method->exceptiontablelength >0)) {
+ } else if (id && (id->method->exceptiontablelength > 0)) {
cd->exceptiontablelength = m->exceptiontablelength;
- cd->exceptiontable = DMNEW(exceptiontable, m->exceptiontablelength + 1);
+ cd->exceptiontable = DMNEW(exceptiontable, m->exceptiontablelength + 1);
}
if (id) {
/* codegen_free ****************************************************************
- releases temporary code and data area
+ Releases temporary code and data area.
*******************************************************************************/
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) {
if (cd->mcodebase) {
MFREE(cd->mcodebase, u1, cd->mcodesize);
cd->mcodebase = NULL;
cd->dsegtop = NULL;
}
}
+#endif
}
*******************************************************************************/
-void codegen_close()
+void codegen_close(void)
{
/* TODO: release avl tree on i386 and x86_64 */
}
long len;
len = codeptr - cd->mcodebase;
- cd->mcodebase = MREALLOC(cd->mcodebase,
- u1,
- cd->mcodesize,
- cd->mcodesize * 2);
+ cd->mcodebase = DMREALLOC(cd->mcodebase,
+ u1,
+ cd->mcodesize,
+ cd->mcodesize * 2);
cd->mcodesize *= 2;
cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
{
u1 *newstorage;
- newstorage = MNEW(u1, cd->dsegsize * 2);
+ newstorage = DMNEW(u1, cd->dsegsize * 2);
- memcpy(newstorage + cd->dsegsize, cd->dsegtop - cd->dsegsize, cd->dsegsize);
- MFREE(cd->dsegtop - cd->dsegsize, u1, cd->dsegsize);
+ MCOPY(newstorage + cd->dsegsize, cd->dsegtop - cd->dsegsize, u1,
+ cd->dsegsize);
cd->dsegtop = newstorage;
cd->dsegsize *= 2;
}
-#if !defined(__I386__)
+#if !defined(__I386__) && !defined(__POWERPC__)
static s4 dseg_adds8_increase(codegendata *cd, s8 value)
{
dseg_increase(cd);
}
+#if defined(__I386__) || defined(__X86_64__)
static void dseg_adddata(codegendata *cd, u1 *ptr)
{
dataref *dr;
dr->next = cd->datareferences;
cd->datareferences = dr;
}
+#endif
static void dseg_addlinenumbertablesize(codegendata *cd)
tables_unlock();
#endif
#endif
+ assert(0);
throw_cacao_exception_exit(string_java_lang_InternalError,
"duplicate entry");
}
#endif
+/* codegen_finish **************************************************************
+
+ Finishes the code generation. A new memory, large enough for both
+ data and code, is allocated and data and code are copied together
+ to their final layout, unresolved jumps are resolved, ...
+
+*******************************************************************************/
+
static void codegen_finish(methodinfo *m, codegendata *cd, s4 mcodelen)
{
- jumpref *jr;
- functionptr epoint;
- s4 extralen;
- s4 alignedlen;
+ jumpref *jr;
+ functionptr epoint;
+ s4 extralen;
+ s4 alignedlen;
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
extralen = sizeof(threadcritnode) * cd->threadcritcount;
cd->dseglen = ALIGN(cd->dseglen, MAX_ALIGN);
alignedlen = ALIGN(mcodelen, MAX_ALIGN) + cd->dseglen;
+ /* allocate new memory */
+
m->mcodelength = mcodelen + cd->dseglen;
m->mcode = (functionptr) (ptrint) CNEW(u1, alignedlen + extralen);
- MCOPY((void *) m->mcode, cd->dsegtop - cd->dseglen, u1, cd->dseglen);
- MCOPY((void *) ((ptrint) m->mcode + cd->dseglen), cd->mcodebase, u1, mcodelen);
+ /* copy data and code to their new location */
+
+ MCOPY((void *) (ptrint) m->mcode, cd->dsegtop - cd->dseglen, u1,
+ cd->dseglen);
+ MCOPY((void *) ((ptrint) m->mcode + cd->dseglen), cd->mcodebase, u1,
+ mcodelen);
m->entrypoint = epoint = (functionptr) ((ptrint) m->mcode + cd->dseglen);
dr = cd->datareferences;
while (dr != NULL) {
- *((functionptr *) ((ptrint) epoint + (ptrint) dr->pos - POINTERSIZE)) = epoint;
+ *((functionptr *) ((ptrint) epoint + (ptrint) dr->pos -
+ SIZEOF_VOID_P)) = epoint;
dr = dr->next;
}
}
printf(" --- dump of datasegment\n");
for (i = cd->dseglen; i > 0 ; i -= 4) {
-#if defined(__I386__) || defined(__POWERPC__)
- printf("0x%08x: -%6x (%6d): %8x\n",
+#if SIZEOF_VOID_P == 8
+ printf("0x%016lx: -%6x (%6d): %8x\n",
(ptrint) s4ptr, i, i, (s4) *s4ptr);
#else
- printf("0x%016lx: -%6x (%6d): %8x\n",
+ printf("0x%08x: -%6x (%6d): %8x\n",
(ptrint) s4ptr, i, i, (s4) *s4ptr);
#endif
s4ptr++;
}
+
+/* codegen_createnativestub ****************************************************
+
+ Wrapper for createnativestub.
+
+*******************************************************************************/
+
+functionptr codegen_createnativestub(functionptr f, methodinfo *m)
+{
+ codegendata *cd;
+ registerdata *rd;
+ t_inlining_globals *id;
+ s4 dumpsize;
+
+ /* mark dump memory */
+
+ dumpsize = dump_size();
+
+ cd = DNEW(codegendata);
+ rd = DNEW(registerdata);
+ id = DNEW(t_inlining_globals);
+
+ /* setup code generation stuff */
+
+ inlining_setup(m, id);
+ reg_setup(m, rd, id);
+ codegen_setup(m, cd, id);
+
+ m->stubroutine = createnativestub(f, m, cd, rd);
+
+ /* entrypoint was set in codegen_finish, clear it */
+
+ m->entrypoint = NULL;
+
+#if defined(STATISTICS)
+ if (opt_stat)
+ count_nstub_len += m->mcodelength;
+#endif
+
+ /* release memory */
+
+ dump_release(dumpsize);
+
+
+ /* disassemble native stub */
+
+ if (showdisassemble)
+ codegen_disassemble_nativestub(m, (s4 *) (ptrint) m->stubroutine,
+ m->mcodelength - cd->dseglen);
+
+ /* show data segment */
+
+ if (showddatasegment)
+ dseg_display(m, cd);
+
+ /* return stubroutine entry point */
+
+ return m->stubroutine;
+}
+
+
+/* codegen_disassemble_nativestub **********************************************
+
+ Disassembles the generated native stub.
+
+*******************************************************************************/
+
+void codegen_disassemble_nativestub(methodinfo *m, s4 *code, s4 len)
+{
+ printf("Native stub: ");
+ utf_fprint_classname(stdout, m->class->name);
+ printf(".");
+ utf_fprint(stdout, m->name);
+ utf_fprint(stdout, m->descriptor);
+ printf("\n\nLength: %d\n\n", len);
+
+#if defined(__I386__) || defined(__X86_64__)
+ disassemble((u1 *) code, len);
+#else
+ disassemble(code, len);
+#endif
+}
+
+
+/* removecompilerstub **********************************************************
+
+ Deletes a compilerstub from memory (simply by freeing it).
+
+*******************************************************************************/
+
+void removecompilerstub(functionptr stub)
+{
+ CFREE(stub, 1);
+}
+
+
+/* removenativestub ************************************************************
+
+ Removes a previously created native-stub from memory.
+
+*******************************************************************************/
+
+void removenativestub(functionptr stub)
+{
+ CFREE(stub, 1);
+}
+
+
/* 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
#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:
- log_text("invalid method descriptor");
- assert(0);
- }
- }
- 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:
- log_text("invalid method descriptor");
- assert(0);
- }
- }
- *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;
-
-#if defined(USE_THREADS)
- builtin_monitorenter((java_objectheader*) m);
-#endif
-
-#if defined(__X86_64__)
- if ((*((s4*)jmpPatchTarget))==((s4)jmpTarget)) {
-#else
- if ((*jmpPatchTarget)==jmpTarget) {
-#endif
-
-#if defined(USE_THREADS)
- builtin_monitorexit((java_objectheader*) m);
-#endif
-
- 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-1]=0;
- nativeName=nativeNameEscape;
- }
- if (nativeName[i]=='/') nativeName[i]='_';
- i++;
- }
-
- /*printf("\nnativename: %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");*/
- /*printf("strlen %d, nativeLen %d\n",strlen(nativeName),nativeLen);*/
- 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*/
- dolog("\nnative function not found: %s",overloadedNative);
- 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
-
-#if defined(USE_THREADS)
- builtin_monitorexit((java_objectheader *) m );
-#endif
-
- 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);
-
-#if defined(USE_THREADS)
- builtin_monitorexit((java_objectheader *) m );
-#endif
-
- throw_cacao_exception_exit(string_java_lang_LinkageError,
- info);
- }
-
-}
-#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