1 /* vm/jit/codegen.inc - architecture independent code generator
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 Institut f. Computersprachen, TU Wien
5 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
6 S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
9 This file is part of CACAO.
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2, or (at
14 your option) any later version.
16 This program is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
26 Contact: cacao@complang.tuwien.ac.at
28 Authors: Reinhard Grafl
31 Changes: Christian Thalinger
34 All functions assume the following code area / data area layout:
38 | code area | code area grows to higher addresses
40 +-----------+ <-- start of procedure
42 | data area | data area grows to lower addresses
46 The functions first write into a temporary code/data area allocated by
47 "codegen_init". "codegen_finish" copies the code and data area into permanent
48 memory. All functions writing values into the data area return the offset
49 relative the begin of the code area (start of procedure).
51 $Id: codegen.inc 1683 2004-12-05 21:33:36Z jowenn $
55 #ifndef _CODEGEN_INC_H_
56 #define _CODEGEN_INC_H_
60 #if !defined(STATIC_CLASSPATH)
64 #include "mm/memory.h"
65 #include "toolbox/avl.h"
66 #include "toolbox/logging.h"
67 #include "native/native.h"
69 #if defined(USE_THREADS)
70 # if defined(NATIVE_THREADS)
71 # include "threads/native/threads.h"
73 # include "threads/green/threads.h"
77 #include "vm/exceptions.h"
78 #include "vm/options.h"
79 #include "vm/statistics.h"
80 #include "vm/jit/codegen.inc.h"
83 /* in this tree we store all method addresses *********************************/
85 #if defined(__I386__) || defined(__X86_64__)
86 static struct avl_table *methodtree = NULL;
87 static int methodtree_comparator(const void *pc, const void *element,
92 /* codegen_init ****************************************************************
96 *******************************************************************************/
100 #if defined(__I386__) || defined(__X86_64__)
101 /* this tree is global, not method specific */
103 methodtree_element *mte;
105 methodtree = avl_create(methodtree_comparator, NULL, NULL);
107 mte = NEW(methodtree_element);
109 mte->startpc = (functionptr) asm_calljavafunction;
110 mte->endpc = (functionptr) ((long) asm_calljavafunction2 - 1);
112 avl_insert(methodtree, mte);
114 mte = NEW(methodtree_element);
116 mte->startpc = (functionptr) asm_calljavafunction2;
117 mte->endpc = (functionptr) ((long) asm_call_jit_compiler - 1);
119 avl_insert(methodtree, mte);
125 /* codegen_setup **************************************************************
127 allocates and initialises code area, data area and references
129 *******************************************************************************/
131 void codegen_setup(methodinfo *m, codegendata *cd, t_inlining_globals *id)
133 cd->mcodebase = MNEW(u1, MCODEINITSIZE);
134 cd->mcodesize = MCODEINITSIZE;
136 cd->dsegtop = MNEW(u1, DSEGINITSIZE);
137 cd->dsegsize = DSEGINITSIZE;
138 cd->dsegtop += cd->dsegsize;
141 cd->jumpreferences = NULL;
142 cd->datareferences = NULL;
143 cd->xboundrefs = NULL;
144 cd->xcheckarefs = NULL;
145 cd->xnullrefs = NULL;
146 cd->xcastrefs = NULL;
148 cd->xexceptionrefs = NULL;
149 cd->clinitrefs = NULL;
151 cd->linenumberreferences = NULL;
152 cd->linenumbertablesizepos = 0;
153 cd->linenumbertablestartpos = 0;
154 cd->linenumbertab = 0;
157 cd->exceptiontable = 0;
158 cd->exceptiontablelength = 0;
160 if (useinlining && id) {
161 if (id->cumextablelength > 0) {
162 cd->exceptiontablelength = id->cumextablelength;
163 cd->exceptiontable = DMNEW(exceptiontable, id->cumextablelength + 1);
166 } else if (id && (id->method->exceptiontablelength >0)) {
167 cd->exceptiontablelength = m->exceptiontablelength;
168 cd->exceptiontable = DMNEW(exceptiontable, m->exceptiontablelength + 1);
172 cd->maxstack = id->cummaxstack;
173 cd->maxlocals = id->cumlocals;
175 cd->maxstack = m->maxstack;
176 cd->maxlocals = m->maxlocals;
179 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
180 cd->threadcritcurrent.next = NULL;
181 cd->threadcritcount = 0;
186 /* codegen_free ****************************************************************
188 releases temporary code and data area
190 *******************************************************************************/
192 void codegen_free(methodinfo *m, codegendata *cd)
196 if (cd->exceptiontablelength) {
197 cd->exceptiontablelength = m->exceptiontablelength;
198 MFREE(cd->exceptiontable, exceptiontable, cd->exceptiontablelength + 1);
199 cd->exceptiontable = 0;
200 cd->exceptiontablelength = 0;
205 MFREE(cd->mcodebase, u1, cd->mcodesize);
206 cd->mcodebase = NULL;
210 MFREE(cd->dsegtop - cd->dsegsize, u1, cd->dsegsize);
217 /* codegen_close ***************************************************************
221 *******************************************************************************/
225 /* TODO: release avl tree on i386 and x86_64 */
229 /* codegen_increase doubles code area */
231 static s4 *codegen_increase(codegendata *cd, u1 *codeptr)
235 len = codeptr - cd->mcodebase;
236 cd->mcodebase = MREALLOC(cd->mcodebase,
241 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
243 return (s4 *) (cd->mcodebase + len);
247 /* desg_increase doubles data area */
249 static void dseg_increase(codegendata *cd)
253 newstorage = MNEW(u1, cd->dsegsize * 2);
255 memcpy(newstorage + cd->dsegsize, cd->dsegtop - cd->dsegsize, cd->dsegsize);
256 MFREE(cd->dsegtop - cd->dsegsize, u1, cd->dsegsize);
258 cd->dsegtop = newstorage;
260 cd->dsegtop += cd->dsegsize;
264 static s4 dseg_adds4_increase(codegendata *cd, s4 value)
268 *((s4 *) (cd->dsegtop - cd->dseglen)) = value;
270 return -(cd->dseglen);
274 static s4 dseg_adds4(codegendata *cd, s4 value)
279 dataptr = (s4 *) (cd->dsegtop - cd->dseglen);
281 if (cd->dseglen > cd->dsegsize)
282 return dseg_adds4_increase(cd, value);
286 return -(cd->dseglen);
290 #if !defined(__I386__)
291 static s4 dseg_adds8_increase(codegendata *cd, s8 value)
295 *((s8 *) (cd->dsegtop - cd->dseglen)) = value;
297 return -(cd->dseglen);
301 static s4 dseg_adds8(codegendata *cd, s8 value)
305 cd->dseglen = ALIGN(cd->dseglen + 8, 8);
306 dataptr = (s8 *) (cd->dsegtop - cd->dseglen);
308 if (cd->dseglen > cd->dsegsize)
309 return dseg_adds8_increase(cd, value);
313 return -(cd->dseglen);
318 static s4 dseg_addfloat_increase(codegendata *cd, float value)
322 *((float *) (cd->dsegtop - cd->dseglen)) = value;
324 return -(cd->dseglen);
328 static s4 dseg_addfloat(codegendata *cd, float value)
333 dataptr = (float *) (cd->dsegtop - cd->dseglen);
335 if (cd->dseglen > cd->dsegsize)
336 return dseg_addfloat_increase(cd, value);
340 return -(cd->dseglen);
344 static s4 dseg_adddouble_increase(codegendata *cd, double value)
348 *((double *) (cd->dsegtop - cd->dseglen)) = value;
350 return -(cd->dseglen);
354 static s4 dseg_adddouble(codegendata *cd, double value)
358 cd->dseglen = ALIGN(cd->dseglen + 8, 8);
359 dataptr = (double *) (cd->dsegtop - cd->dseglen);
361 if (cd->dseglen > cd->dsegsize)
362 return dseg_adddouble_increase(cd, value);
366 return -(cd->dseglen);
370 static void dseg_addtarget(codegendata *cd, basicblock *target)
375 jr->tablepos = dseg_addaddress(cd, NULL);
377 jr->next = cd->jumpreferences;
378 cd->jumpreferences = jr;
382 static void dseg_adddata(codegendata *cd, u1 *ptr)
387 dr->pos = (u1 *) (ptr - cd->mcodebase);
388 dr->next = cd->datareferences;
389 cd->datareferences = dr;
393 static void dseg_addlinenumbertablesize(codegendata *cd)
396 dseg_adds4(cd, 0); /*PADDING*/
398 cd->linenumbertablesizepos = dseg_addaddress(cd, NULL); /*it could be considered to use adds4 here, to avoid 1 double word padding on ALPHA */
400 cd->linenumbertablestartpos = dseg_addaddress(cd, NULL);
402 dseg_adds4(cd, 0); /*PADDING*/
407 static void dseg_addlinenumber(codegendata *cd, u2 linenumber, u1 *ptr)
411 lr = DNEW(linenumberref);
412 lr->linenumber = linenumber;
414 lr->targetmpc = (ptr - cd->mcodebase);
415 lr->next = cd->linenumberreferences;
416 cd->linenumberreferences = lr;
420 /* we need this function externally on i386 and x86_64, but keep the call fast
423 #if defined(__I386__) || defined(__X86_64__)
424 void codegen_addreference(codegendata *cd, basicblock *target, void *branchptr)
426 static void codegen_addreference(codegendata *cd, basicblock *target, void *branchptr)
431 branchpos = (u1 *) branchptr - cd->mcodebase;
433 if (target->mpc >= 0) {
434 gen_resolvebranch((u1 *) cd->mcodebase + branchpos,
439 branchref *br = DNEW(branchref);
441 br->branchpos = branchpos;
442 br->next = target->branchrefs;
443 target->branchrefs = br;
448 static void codegen_addxboundrefs(codegendata *cd, void *branchptr, s4 reg)
453 branchpos = (u1 *) branchptr - cd->mcodebase;
455 br = DNEW(branchref);
456 br->branchpos = branchpos;
458 br->next = cd->xboundrefs;
463 static void codegen_addxcheckarefs(codegendata *cd, void *branchptr)
468 branchpos = (u1 *) branchptr - cd->mcodebase;
470 br = DNEW(branchref);
471 br->branchpos = branchpos;
472 br->next = cd->xcheckarefs;
473 cd->xcheckarefs = br;
477 static void codegen_addxnullrefs(codegendata *cd, void *branchptr)
482 branchpos = (u1 *) branchptr - cd->mcodebase;
484 br = DNEW(branchref);
485 br->branchpos = branchpos;
486 br->next = cd->xnullrefs;
491 static void codegen_addxcastrefs(codegendata *cd, void *branchptr)
496 branchpos = (u1 *) branchptr - cd->mcodebase;
498 br = DNEW(branchref);
499 br->branchpos = branchpos;
500 br->next = cd->xcastrefs;
505 static void codegen_addxexceptionrefs(codegendata *cd, void *branchptr)
510 branchpos = (u1 *) branchptr - cd->mcodebase;
512 br = DNEW(branchref);
513 br->branchpos = branchpos;
514 br->next = cd->xexceptionrefs;
515 cd->xexceptionrefs = br;
519 #if defined(__I386__) || defined(__X86_64__)
520 static void codegen_addxdivrefs(codegendata *cd, void *branchptr)
525 branchpos = (u1 *) branchptr - cd->mcodebase;
527 br = DNEW(branchref);
528 br->branchpos = branchpos;
529 br->next = cd->xdivrefs;
535 static void codegen_addclinitref(codegendata *cd,
542 branchpos = (u1 *) branchptr - cd->mcodebase;
544 cr = DNEW(clinitref);
545 cr->branchpos = branchpos;
547 cr->next = cd->clinitrefs;
552 static void codegen_createlinenumbertable(codegendata *cd)
554 #if defined(__I386__) || defined(__ALPHA__)
557 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
558 lr->tablepos = dseg_addaddress(cd, NULL);
560 if (cd->linenumbertab == 0)
561 cd->linenumbertab = lr->tablepos;
563 dseg_addaddress(cd, lr->linenumber);
569 #if defined(__I386__) || defined(__X86_64__)
570 static int methodtree_comparator(const void *pc, const void *element, void *param)
572 methodtree_element *mte;
573 methodtree_element *mtepc;
575 mte = (methodtree_element *) element;
576 mtepc = (methodtree_element *) pc;
578 /* compare both startpc and endpc of pc, even if they have the same value,
579 otherwise the avl_probe sometimes thinks the element is already in the
581 if ((long) mte->startpc <= (long) mtepc->startpc &&
582 (long) mtepc->startpc <= (long) mte->endpc &&
583 (long) mte->startpc <= (long) mtepc->endpc &&
584 (long) mtepc->endpc <= (long) mte->endpc) {
587 } else if ((long) mtepc->startpc < (long) mte->startpc) {
597 void *codegen_findmethod1(void *pc)
599 void * retVal=findmethod(pc);
600 methodinfo **ma=(methodinfo**)retVal;
601 methodinfo *m=ma[-1];
604 utf_display(m->name);
607 else log_text("No methodinfo");
613 void codegen_insertmethod(functionptr startpc, functionptr endpc)
615 methodtree_element *mte;
617 #if defined(USE_THREADS)
618 #if defined(NATIVE_THREADS)
623 mte = NEW(methodtree_element);
624 mte->startpc = startpc;
627 if (avl_insert(methodtree, mte)) {
628 #if defined(USE_THREADS)
629 #if defined(NATIVE_THREADS)
633 throw_cacao_exception_exit(string_java_lang_InternalError,
637 #if defined(USE_THREADS)
638 #if defined(NATIVE_THREADS)
645 functionptr codegen_findmethod(functionptr pc)
647 methodtree_element *mtepc;
648 methodtree_element *mte;
650 #if defined(USE_THREADS)
651 #if defined(NATIVE_THREADS)
656 mtepc = NEW(methodtree_element);
660 mte = avl_find(methodtree, mtepc);
662 FREE(mtepc, methodtree_element);
665 #if defined(USE_THREADS)
666 #if defined(NATIVE_THREADS)
670 throw_cacao_exception_exit(string_java_lang_InternalError,
671 "cannot find function");
674 #if defined(USE_THREADS)
675 #if defined(NATIVE_THREADS)
684 #if defined(__ALPHA__)
685 /*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,
686 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)*/
687 void *codegen_findmethod(void *returnAdress)
692 d=*((s4*)returnAdress);
695 dataseg=returnAdress+d;
696 d=*(((s4*)returnAdress)+1);
700 d=*(((s4*)returnAdress)+1);
706 ldl t0,0(ra) /* load instruction LDA PV,xxx(RA) */
708 sra t0,48,t0 /* isolate offset */
709 addq t0,ra,pv /* compute update address */
710 ldl t0,4(ra) /* load instruction LDAH PV,xxx(PV) */
711 srl t0,16,t0 /* isolate instruction code */
712 lda t0,-0x177b(t0) /* test for LDAH */
714 ldl t0,4(ra) /* load instruction LDAH PV,xxx(RA) */
715 sll t0,16,t0 /* compute high offset */
716 addl t0,0,t0 /* sign extend high offset */
717 addq t0,pv,pv /* compute update address */
725 static void codegen_finish(methodinfo *m, codegendata *cd, s4 mcodelen)
732 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
733 extralen = sizeof(threadcritnode) * cd->threadcritcount;
738 #if defined(STATISTICS)
740 count_code_len += mcodelen;
741 count_data_len += cd->dseglen;
745 cd->dseglen = ALIGN(cd->dseglen, MAX_ALIGN);
746 alignedlen = ALIGN(mcodelen, MAX_ALIGN) + cd->dseglen;
748 m->mcodelength = mcodelen + cd->dseglen;
749 m->mcode = (functionptr) (long) CNEW(u1, alignedlen + extralen);
751 memcpy((void *) (long) m->mcode, cd->dsegtop - cd->dseglen, cd->dseglen);
752 memcpy((void *) ((long) m->mcode + cd->dseglen), cd->mcodebase, mcodelen);
754 m->entrypoint = epoint = (functionptr) ((long) m->mcode + cd->dseglen);
756 /* jump table resolving */
757 jr = cd->jumpreferences;
759 *((functionptr *) ((long) epoint + jr->tablepos)) =
760 (functionptr) ((long) epoint + (long) jr->target->mpc);
764 #if defined(__I386__) || defined(__ALPHA__)
765 /* line number table resolving */
774 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
776 *((functionptr *) ((long) epoint + (long) lr->tablepos)) =
777 (functionptr) ((long) epoint + (long) lr->targetmpc);
780 *((functionptr *) ((long) epoint + cd->linenumbertablestartpos)) =
781 (functionptr) ((long) epoint + cd->linenumbertab);
783 *((s8 *) ((s8) epoint + cd->linenumbertablesizepos)) = lrtlen;
785 *((s4 *) ((s4) epoint + cd->linenumbertablesizepos)) = lrtlen;
790 #if defined(__I386__) || defined(__X86_64__)
794 /* add method into methodtree to find the entrypoint */
795 codegen_insertmethod(m->entrypoint,
796 (functionptr) ((long) m->entrypoint + mcodelen));
798 /* data segment references resolving */
799 dr = cd->datareferences;
801 *((functionptr *) ((long) epoint + (long) dr->pos - POINTERSIZE)) =
808 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
810 threadcritnode *n = (threadcritnode *) ((long) m->mcode + alignedlen);
812 threadcritnodetemp *nt = cd->threadcrit;
814 for (i = 0; i < cd->threadcritcount; i++) {
815 n->mcodebegin = (u1 *) (long) m->mcode + nt->mcodebegin;
816 n->mcodeend = (u1 *) (long) m->mcode + nt->mcodeend;
817 n->mcoderestart = (u1 *) (long) m->mcode + nt->mcoderestart;
818 thread_registercritical(n);
827 void dseg_display(methodinfo *m, codegendata *cd)
832 s4ptr = (s4 *) (long) m->mcode;
834 printf(" --- dump of datasegment\n");
835 for (i = cd->dseglen; i > 0 ; i -= 4) {
836 printf("-%6x: %8x\n", i, (s4) (*s4ptr++));
838 printf(" --- begin of data segment: %p\n", (void *) s4ptr);
843 This function determines a register, to which the result of an operation
844 should go, when it is ultimatively intended to store the result in
846 If v is assigned to an actual register, this register will be returned.
847 Otherwise (when v is spilled) this function returns tempregnum.
848 If not already done, regoff and flags are set in the stack location.
851 static int reg_of_var(registerdata *rd, stackptr v, int tempregnum)
855 switch (v->varkind) {
857 if (!(v->flags & INMEMORY))
861 var = &(rd->interfaces[v->varnum][v->type]);
862 v->regoff = var->regoff;
863 if (!(var->flags & INMEMORY))
867 var = &(rd->locals[v->varnum][v->type]);
868 v->regoff = var->regoff;
869 if (!(var->flags & INMEMORY))
873 v->regoff = v->varnum;
874 if (IS_FLT_DBL_TYPE(v->type)) {
875 if (v->varnum < rd->fltreg_argnum) {
876 v->regoff = rd->argfltregs[v->varnum];
877 return(rd->argfltregs[v->varnum]);
881 #if defined(__POWERPC__)
882 if (v->varnum < rd->intreg_argnum - (IS_2_WORD_TYPE(v->type) != 0)) {
884 if (v->varnum < rd->intreg_argnum) {
886 v->regoff = rd->argintregs[v->varnum];
887 return (rd->argintregs[v->varnum]);
890 #if defined(__POWERPC__)
893 v->regoff -= rd->intreg_argnum;
897 v->flags |= INMEMORY;
902 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
903 static void codegen_threadcritrestart(codegendata *cd, int offset)
905 cd->threadcritcurrent.mcoderestart = offset;
909 static void codegen_threadcritstart(codegendata *cd, int offset)
911 cd->threadcritcurrent.mcodebegin = offset;
915 static void codegen_threadcritstop(codegendata *cd, int offset)
917 cd->threadcritcurrent.next = cd->threadcrit;
918 cd->threadcritcurrent.mcodeend = offset;
919 cd->threadcrit = DNEW(threadcritnodetemp);
920 *(cd->threadcrit) = cd->threadcritcurrent;
921 cd->threadcritcount++;
926 #ifndef STATIC_CLASSPATH
927 static size_t codegen_overloadPartLen(utf *desc) {
928 char *utf_ptr=desc->text;
931 while ((c=utf_nextu2(&utf_ptr))!=')') {
948 while ( (c=utf_nextu2(&utf_ptr)) != ';')
954 default: panic ("invalid method descriptor");
961 static void codegen_fillInOverloadPart(char *target,utf *desc) {
962 char *utf_ptr=desc->text;
964 char* insertpos=&target[strlen(target)];
967 while ((c=utf_nextu2(&utf_ptr))!=')') {
985 while ( (c=utf_nextu2(&utf_ptr)) != ';')
986 if ( ((c>='a') && (c<='z')) ||
987 ((c>='A') && (c<='Z')) ||
988 ((c>='0') && (c<='9')) )
990 else *(insertpos++)='_';
996 default: panic ("invalid method descriptor");
1003 static void codegen_resolve_native(methodinfo *m,void **insertionPoint,void *jmpTarget,void **jmpPatchTarget) {
1004 char *nativeName, *nativeNameEscape;
1010 builtin_monitorenter((java_objectheader*) m);
1011 #if defined(__X86_64__)
1012 if ((*((s4*)jmpPatchTarget))==((s4)jmpTarget)) {
1014 if ((*jmpPatchTarget)==jmpTarget) {
1016 builtin_monitorexit((java_objectheader*) m);
1019 /*log_text("trying to resolve a native method");
1020 utf_display(m->class->name);
1021 utf_display(m->name);*/
1023 lib=dlopen(0,RTLD_NOW | RTLD_GLOBAL); /* open the application execution image */
1024 if (lib) { /* it did work -> good, otherwise fail with error*/
1026 /*generate the name of the native function in the form Java_package1_package2...._classname_methodname*/
1027 nativeLen=/*Java_*/5+strlen(m->class->name->text)+/*_*/1+strlen(m->name->text)+/*\0*/1;
1028 nativeName=MNEW(char,nativeLen);
1029 sprintf(nativeName,"Java_%s/%s",m->class->name->text,m->name->text);
1031 while (i<nativeLen) {
1032 if (nativeName[i]=='_') { /* escape underscore */
1033 nativeNameEscape = MNEW(char,nativeLen+1);
1034 memcpy(nativeNameEscape,nativeName,i+1);
1035 nativeNameEscape[i+1] = '1'; /* escape sequence for _ is _1 */
1036 memcpy(&nativeNameEscape[i+2],&nativeName[i+1],nativeLen-i-1);
1037 MFREE(nativeName,char,nativeLen);
1040 nativeNameEscape[nativeLen]=0;
1041 nativeName=nativeNameEscape;
1043 if (nativeName[i]=='/') nativeName[i]='_';
1047 /* printf("nativename: %s\n",nativeName); */
1049 /*try to find the symbal fo the function */
1050 sym=dlsym(lib,nativeName);
1052 ok=1; /* it worked, everything fine */
1053 /*log_text("resolved");*/
1054 MFREE(nativeName,char,nativeLen);
1055 } else { /* we didn't find the symbol yet, try to resolve an overlaoded function (having the types in it's name*/
1056 size_t overloadedNativeLen=nativeLen+codegen_overloadPartLen(m->descriptor);
1057 char *overloadedNative=MNEW(char,overloadedNativeLen);
1058 sprintf(overloadedNative,"%s",nativeName);
1059 MFREE(nativeName,char,nativeLen);
1060 codegen_fillInOverloadPart(overloadedNative,m->descriptor);
1061 /*log_text("symbol not found,trying harder (overloaded member ?)");*/
1062 sym=dlsym(lib,overloadedNative);
1064 MFREE(overloadedNative,char,overloadedNativeLen);
1065 ok=1; /* we eventually found the native function -> everything ok*/
1066 /*log_text("resolved");*/
1068 /* we failed to find the native function within the execution image (app + loaded libraries) -> will cause an exit*/
1069 MFREE(overloadedNative,char,overloadedNativeLen);
1070 log_text("It was not possible to find the native function implementation. Not even in overloading case");
1073 /* patch the address of the native function into the stub and make the stub jump over this function call in the future */
1075 (*insertionPoint)=sym;
1076 #if defined(__X86_64__)
1077 (*((s4*)jmpPatchTarget))=(s4)jmpTarget;
1079 (*jmpPatchTarget)=jmpTarget;
1081 builtin_monitorexit((java_objectheader *) m );
1085 } else log_text("library not found");
1087 /* There was an error, either the app image could not be opened or the native does not exist in the application and the
1088 loaded libraries. Show an additional error and exit the vm*/
1092 slen=2+strlen(m->class->name->text)+strlen(m->name->text)+strlen(m->descriptor->text);
1093 info=(char*)MNEW(char,slen);
1094 sprintf(info,"%s.%s%s",m->class->name->text,m->name->text,m->descriptor->text);
1096 builtin_monitorexit((java_objectheader *) m );
1097 throw_cacao_exception_exit(string_java_lang_LinkageError,
1108 * These are local overrides for various environment variables in Emacs.
1109 * Please do not remove this and leave it at the end of the file, where
1110 * Emacs will automagically detect them.
1111 * ---------------------------------------------------------------------
1114 * indent-tabs-mode: t