-/* vm/jit/codegen.inc - architecture independent code generator
+/* src/vm/jit/codegen.inc - architecture independent code generator
Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
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 2189 2005-04-02 02:05:59Z edwin $
+ $Id: codegen.inc 2734 2005-06-17 13:01:06Z twisti $
*/
-#ifndef _CODEGEN_INC_H_
-#define _CODEGEN_INC_H_
+#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
+
+#ifdef JWDEBUG_X86
+#include <execinfo.h>
+#endif
/* in this tree we store all method addresses *********************************/
*******************************************************************************/
-void codegen_init()
+void codegen_init(void)
{
#if defined(__I386__) || defined(__X86_64__)
/* this tree is global, not method specific */
methodtree = avl_create(methodtree_comparator, NULL, NULL);
+ /* insert asm_calljavafunction */
+
mte = NEW(methodtree_element);
mte->startpc = (functionptr) asm_calljavafunction;
- mte->endpc = (functionptr) ((long) asm_calljavafunction2 - 1);
+ mte->endpc = (functionptr) ((ptrint) asm_calljavafunction2 - 1);
avl_insert(methodtree, mte);
+ /* insert asm_calljavafunction2 */
+
mte = NEW(methodtree_element);
mte->startpc = (functionptr) asm_calljavafunction2;
- mte->endpc = (functionptr) ((long) asm_call_jit_compiler - 1);
+ mte->endpc = (functionptr) ((ptrint) asm_call_jit_compiler - 1);
avl_insert(methodtree, mte);
}
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;
cd->xcastrefs = NULL;
cd->xdivrefs = NULL;
cd->xexceptionrefs = NULL;
- cd->clinitrefs = NULL;
+ cd->patchrefs = NULL;
cd->linenumberreferences = NULL;
cd->linenumbertablesizepos = 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)
{
-#ifdef __ALPHA__
+#if defined (__ALPHA__) || defined (__X86_64__)
dseg_adds4(cd, 0); /*PADDING*/
#endif
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(cd, NULL);
-#ifdef __ALPHA__
+#if defined(__ALPHA__) || defined (__X86_64__)
dseg_adds4(cd, 0); /*PADDING*/
#endif
}
branchpos = (u1 *) branchptr - cd->mcodebase;
+ /* Check if the target basicblock has already a start pc, so the jump is */
+ /* backward and we can resolve it immediately. */
+
if (target->mpc >= 0) {
gen_resolvebranch((u1 *) cd->mcodebase + branchpos,
branchpos,
#endif
-static void codegen_addclinitref(codegendata *cd,
- void *branchptr,
- classinfo *class)
+static void codegen_addpatchref(codegendata *cd,
+ voidptr branchptr,
+ functionptr patcher,
+ voidptr ref)
{
- s4 branchpos;
- clinitref *cr;
+ patchref *pr;
+ s4 branchpos;
branchpos = (u1 *) branchptr - cd->mcodebase;
- cr = DNEW(clinitref);
- cr->branchpos = branchpos;
- cr->class = class;
- cr->next = cd->clinitrefs;
- cd->clinitrefs = cr;
+ pr = DNEW(patchref);
+ pr->branchpos = branchpos;
+ pr->patcher = patcher;
+ pr->ref = ref;
+ pr->next = cd->patchrefs;
+ cd->patchrefs = pr;
}
static void codegen_createlinenumbertable(codegendata *cd)
{
-#if defined(__I386__) || defined(__ALPHA__)
+#if defined(__I386__) || defined(__ALPHA__) || defined(__X86_64__)
linenumberref *lr;
for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
}
-#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_insertmethod(functionptr startpc, functionptr endpc)
{
methodtree_element *mte;
tables_unlock();
#endif
#endif
+ assert(0);
throw_cacao_exception_exit(string_java_lang_InternalError,
"duplicate entry");
}
tables_unlock();
#endif
#endif
+#ifdef JWDEBUG_X86
+ {
+ void *bt[5];
+ fprintf(stderr,"backtrace:");
+ backtrace_symbols_fd(bt,5,2);
+ }
+#endif
+ assert(0);
throw_cacao_exception_exit(string_java_lang_InternalError,
- "cannot find function");
+ "Cannot find Java function at %p", pc);
}
#if defined(USE_THREADS)
#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) (long) CNEW(u1, alignedlen + extralen);
+ m->mcode = (functionptr) (ptrint) CNEW(u1, alignedlen + extralen);
+
+ /* copy data and code to their new location */
- memcpy((void *) (long) m->mcode, cd->dsegtop - cd->dseglen, cd->dseglen);
- memcpy((void *) ((long) m->mcode + cd->dseglen), cd->mcodebase, mcodelen);
+ 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) ((long) m->mcode + cd->dseglen);
+ m->entrypoint = epoint = (functionptr) ((ptrint) m->mcode + cd->dseglen);
/* jump table resolving */
+
jr = cd->jumpreferences;
while (jr != NULL) {
- *((functionptr *) ((long) epoint + jr->tablepos)) =
- (functionptr) ((long) epoint + (long) jr->target->mpc);
+ *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
+ (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
jr = jr->next;
}
-#if defined(__I386__) || defined(__ALPHA__)
+#if defined(__I386__) || defined(__ALPHA__) || defined(__X86_64__)
/* line number table resolving */
{
linenumberref *lr;
-#if POINTERSIZE == 8
- s8 lrtlen = 0;
-#else
- s4 lrtlen = 0;
-#endif
+ ptrint lrtlen = 0;
for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
lrtlen++;
- *((functionptr *) ((long) epoint + (long) lr->tablepos)) =
- (functionptr) ((long) epoint + (long) lr->targetmpc);
+ *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) =
+ (functionptr) ((ptrint) epoint + (ptrint) lr->targetmpc);
}
- *((functionptr *) ((long) epoint + cd->linenumbertablestartpos)) =
- (functionptr) ((long) epoint + cd->linenumbertab);
-#if POINTERSIZE == 8
- *((s8 *) ((s8) epoint + cd->linenumbertablesizepos)) = lrtlen;
-#else
- *((s4 *) ((s4) epoint + cd->linenumbertablesizepos)) = lrtlen;
-#endif
+ *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
+ (functionptr) ((ptrint) epoint + cd->linenumbertab);
+
+ *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
}
#endif
#if defined(__I386__) || defined(__X86_64__)
+ /* add method into methodtree to find the entrypoint */
+
+ codegen_insertmethod(m->entrypoint,
+ (functionptr) ((ptrint) m->entrypoint + mcodelen));
+#endif
+
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__)
{
dataref *dr;
- /* add method into methodtree to find the entrypoint */
- codegen_insertmethod(m->entrypoint,
- (functionptr) ((long) m->entrypoint + mcodelen));
-
/* data segment references resolving */
+
dr = cd->datareferences;
while (dr != NULL) {
- *((functionptr *) ((long) epoint + (long) dr->pos - POINTERSIZE)) =
- epoint;
+ *((functionptr *) ((ptrint) epoint + (ptrint) dr->pos -
+ SIZEOF_VOID_P)) = epoint;
dr = dr->next;
}
}
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
{
- threadcritnode *n = (threadcritnode *) ((long) m->mcode + alignedlen);
+ threadcritnode *n = (threadcritnode *) ((ptrint) m->mcode + alignedlen);
s4 i;
threadcritnodetemp *nt = cd->threadcrit;
for (i = 0; i < cd->threadcritcount; i++) {
- n->mcodebegin = (u1 *) (long) m->mcode + nt->mcodebegin;
- n->mcodeend = (u1 *) (long) m->mcode + nt->mcodeend;
- n->mcoderestart = (u1 *) (long) m->mcode + nt->mcoderestart;
+ n->mcodebegin = (u1 *) (ptrint) m->mcode + nt->mcodebegin;
+ n->mcodeend = (u1 *) (ptrint) m->mcode + nt->mcodeend;
+ n->mcoderestart = (u1 *) (ptrint) m->mcode + nt->mcoderestart;
thread_registercritical(n);
n++;
nt = nt->next;
s4 *s4ptr;
s4 i;
- s4ptr = (s4 *) (long) m->mcode;
+ s4ptr = (s4 *) (ptrint) m->mcode;
printf(" --- dump of datasegment\n");
for (i = cd->dseglen; i > 0 ; i -= 4) {
- printf("-%6x: %8x\n", i, (s4) (*s4ptr++));
+#if SIZEOF_VOID_P == 8
+ printf("0x%016lx: -%6x (%6d): %8x\n",
+ (ptrint) s4ptr, i, i, (s4) *s4ptr);
+#else
+ printf("0x%08x: -%6x (%6d): %8x\n",
+ (ptrint) s4ptr, i, i, (s4) *s4ptr);
+#endif
+ s4ptr++;
}
+
printf(" --- begin of data segment: %p\n", (void *) 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
break;
case ARGVAR:
- v->regoff = v->varnum;
- if (IS_FLT_DBL_TYPE(v->type)) {
- if (v->varnum < FLT_ARG_CNT) {
- v->regoff = rd->argfltregs[v->varnum];
- return(rd->argfltregs[v->varnum]);
- }
-
-#if defined(__POWERPC__)
- v->regoff += 6;
-#else
- v->regoff -= FLT_ARG_CNT;
-#endif
-
- } else {
-#if defined(__POWERPC__)
- if (v->varnum < INT_ARG_CNT - (IS_2_WORD_TYPE(v->type) != 0)) {
-#else
- if (v->varnum < INT_ARG_CNT) {
-#endif
- v->regoff = rd->argintregs[v->varnum];
- return (rd->argintregs[v->varnum]);
- }
-
-#if defined(__POWERPC__)
- v->regoff += 6;
-#else
- v->regoff -= INT_ARG_CNT;
-#endif
- }
+ if (!(v->flags & INMEMORY))
+ return(v->regoff);
break;
}
#ifdef STATISTICS
#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;
-
-#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]=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*/
- 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
-
-
-#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