1 /* vm/jit/codegen.inc - architecture independent code generator
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
30 Changes: Christian Thalinger
33 All functions assume the following code area / data area layout:
37 | code area | code area grows to higher addresses
39 +-----------+ <-- start of procedure
41 | data area | data area grows to lower addresses
45 The functions first write into a temporary code/data area allocated by
46 "codegen_init". "codegen_finish" copies the code and data area into permanent
47 memory. All functions writing values into the data area return the offset
48 relative the begin of the code area (start of procedure).
50 $Id: codegen.inc 2424 2005-04-30 13:45:06Z jowenn $
54 #ifndef _CODEGEN_INC_H_
55 #define _CODEGEN_INC_H_
59 #if !defined(STATIC_CLASSPATH)
63 #include "mm/memory.h"
64 #include "toolbox/avl.h"
65 #include "toolbox/logging.h"
66 #include "native/native.h"
68 #if defined(USE_THREADS)
69 # if defined(NATIVE_THREADS)
70 # include "threads/native/threads.h"
72 # include "threads/green/threads.h"
76 #include "vm/exceptions.h"
77 #include "vm/options.h"
78 #include "vm/statistics.h"
79 #include "vm/jit/codegen.inc.h"
87 /* in this tree we store all method addresses *********************************/
89 #if defined(__I386__) || defined(__X86_64__)
90 static struct avl_table *methodtree = NULL;
91 static int methodtree_comparator(const void *pc, const void *element,
96 /* codegen_init ****************************************************************
100 *******************************************************************************/
104 #if defined(__I386__) || defined(__X86_64__)
105 /* this tree is global, not method specific */
107 methodtree_element *mte;
109 methodtree = avl_create(methodtree_comparator, NULL, NULL);
111 /* insert asm_calljavafunction */
113 mte = NEW(methodtree_element);
115 mte->startpc = (functionptr) asm_calljavafunction;
116 mte->endpc = (functionptr) ((ptrint) asm_calljavafunction2 - 1);
118 avl_insert(methodtree, mte);
120 /* insert asm_calljavafunction2 */
122 mte = NEW(methodtree_element);
124 mte->startpc = (functionptr) asm_calljavafunction2;
125 mte->endpc = (functionptr) ((ptrint) asm_call_jit_compiler - 1);
127 avl_insert(methodtree, mte);
133 /* codegen_setup **************************************************************
135 allocates and initialises code area, data area and references
137 *******************************************************************************/
139 void codegen_setup(methodinfo *m, codegendata *cd, t_inlining_globals *id)
141 cd->mcodebase = MNEW(u1, MCODEINITSIZE);
142 cd->mcodesize = MCODEINITSIZE;
144 cd->dsegtop = MNEW(u1, DSEGINITSIZE);
145 cd->dsegsize = DSEGINITSIZE;
146 cd->dsegtop += cd->dsegsize;
149 cd->jumpreferences = NULL;
150 cd->datareferences = NULL;
151 cd->xboundrefs = NULL;
152 cd->xcheckarefs = NULL;
153 cd->xnullrefs = NULL;
154 cd->xcastrefs = NULL;
156 cd->xexceptionrefs = NULL;
157 cd->patchrefs = NULL;
159 cd->linenumberreferences = NULL;
160 cd->linenumbertablesizepos = 0;
161 cd->linenumbertablestartpos = 0;
162 cd->linenumbertab = 0;
165 cd->exceptiontable = 0;
166 cd->exceptiontablelength = 0;
168 if (useinlining && id) {
169 if (id->cumextablelength > 0) {
170 cd->exceptiontablelength = id->cumextablelength;
171 cd->exceptiontable = DMNEW(exceptiontable, id->cumextablelength + 1);
174 } else if (id && (id->method->exceptiontablelength >0)) {
175 cd->exceptiontablelength = m->exceptiontablelength;
176 cd->exceptiontable = DMNEW(exceptiontable, m->exceptiontablelength + 1);
180 cd->maxstack = id->cummaxstack;
181 cd->maxlocals = id->cumlocals;
183 cd->maxstack = m->maxstack;
184 cd->maxlocals = m->maxlocals;
187 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
188 cd->threadcritcurrent.next = NULL;
189 cd->threadcritcount = 0;
194 /* codegen_free ****************************************************************
196 releases temporary code and data area
198 *******************************************************************************/
200 void codegen_free(methodinfo *m, codegendata *cd)
204 if (cd->exceptiontablelength) {
205 cd->exceptiontablelength = m->exceptiontablelength;
206 MFREE(cd->exceptiontable, exceptiontable, cd->exceptiontablelength + 1);
207 cd->exceptiontable = 0;
208 cd->exceptiontablelength = 0;
213 MFREE(cd->mcodebase, u1, cd->mcodesize);
214 cd->mcodebase = NULL;
218 MFREE(cd->dsegtop - cd->dsegsize, u1, cd->dsegsize);
225 /* codegen_close ***************************************************************
229 *******************************************************************************/
233 /* TODO: release avl tree on i386 and x86_64 */
237 /* codegen_increase doubles code area */
239 static s4 *codegen_increase(codegendata *cd, u1 *codeptr)
243 len = codeptr - cd->mcodebase;
244 cd->mcodebase = MREALLOC(cd->mcodebase,
249 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
251 return (s4 *) (cd->mcodebase + len);
255 /* desg_increase doubles data area */
257 static void dseg_increase(codegendata *cd)
261 newstorage = MNEW(u1, cd->dsegsize * 2);
263 memcpy(newstorage + cd->dsegsize, cd->dsegtop - cd->dsegsize, cd->dsegsize);
264 MFREE(cd->dsegtop - cd->dsegsize, u1, cd->dsegsize);
266 cd->dsegtop = newstorage;
268 cd->dsegtop += cd->dsegsize;
272 static s4 dseg_adds4_increase(codegendata *cd, s4 value)
276 *((s4 *) (cd->dsegtop - cd->dseglen)) = value;
278 return -(cd->dseglen);
282 static s4 dseg_adds4(codegendata *cd, s4 value)
287 dataptr = (s4 *) (cd->dsegtop - cd->dseglen);
289 if (cd->dseglen > cd->dsegsize)
290 return dseg_adds4_increase(cd, value);
294 return -(cd->dseglen);
298 #if !defined(__I386__)
299 static s4 dseg_adds8_increase(codegendata *cd, s8 value)
303 *((s8 *) (cd->dsegtop - cd->dseglen)) = value;
305 return -(cd->dseglen);
309 static s4 dseg_adds8(codegendata *cd, s8 value)
313 cd->dseglen = ALIGN(cd->dseglen + 8, 8);
314 dataptr = (s8 *) (cd->dsegtop - cd->dseglen);
316 if (cd->dseglen > cd->dsegsize)
317 return dseg_adds8_increase(cd, value);
321 return -(cd->dseglen);
326 #if !defined(__XDSPCORE__)
327 static s4 dseg_addfloat_increase(codegendata *cd, float value)
331 *((float *) (cd->dsegtop - cd->dseglen)) = value;
333 return -(cd->dseglen);
337 static s4 dseg_addfloat(codegendata *cd, float value)
342 dataptr = (float *) (cd->dsegtop - cd->dseglen);
344 if (cd->dseglen > cd->dsegsize)
345 return dseg_addfloat_increase(cd, value);
349 return -(cd->dseglen);
353 static s4 dseg_adddouble_increase(codegendata *cd, double value)
357 *((double *) (cd->dsegtop - cd->dseglen)) = value;
359 return -(cd->dseglen);
363 static s4 dseg_adddouble(codegendata *cd, double value)
367 cd->dseglen = ALIGN(cd->dseglen + 8, 8);
368 dataptr = (double *) (cd->dsegtop - cd->dseglen);
370 if (cd->dseglen > cd->dsegsize)
371 return dseg_adddouble_increase(cd, value);
375 return -(cd->dseglen);
377 #endif /* !defined(__XDSPCORE__) */
380 static void dseg_addtarget(codegendata *cd, basicblock *target)
385 jr->tablepos = dseg_addaddress(cd, NULL);
387 jr->next = cd->jumpreferences;
388 cd->jumpreferences = jr;
392 static void dseg_adddata(codegendata *cd, u1 *ptr)
397 dr->pos = (u1 *) (ptr - cd->mcodebase);
398 dr->next = cd->datareferences;
399 cd->datareferences = dr;
403 static void dseg_addlinenumbertablesize(codegendata *cd)
405 #if defined (__ALPHA__) || defined (__X86_64__)
406 dseg_adds4(cd, 0); /*PADDING*/
408 cd->linenumbertablesizepos = dseg_addaddress(cd, NULL); /*it could be considered to use adds4 here, to avoid 1 double word padding on ALPHA */
410 cd->linenumbertablestartpos = dseg_addaddress(cd, NULL);
411 #if defined(__ALPHA__) || defined (__X86_64__)
412 dseg_adds4(cd, 0); /*PADDING*/
417 static void dseg_addlinenumber(codegendata *cd, u2 linenumber, u1 *ptr)
421 lr = DNEW(linenumberref);
422 lr->linenumber = linenumber;
424 lr->targetmpc = (ptr - cd->mcodebase);
425 lr->next = cd->linenumberreferences;
426 cd->linenumberreferences = lr;
430 /* we need this function externally on i386 and x86_64, but keep the call fast
433 #if defined(__I386__) || defined(__X86_64__)
434 void codegen_addreference(codegendata *cd, basicblock *target, void *branchptr)
436 static void codegen_addreference(codegendata *cd, basicblock *target, void *branchptr)
441 branchpos = (u1 *) branchptr - cd->mcodebase;
443 if (target->mpc >= 0) {
444 gen_resolvebranch((u1 *) cd->mcodebase + branchpos,
449 branchref *br = DNEW(branchref);
451 br->branchpos = branchpos;
452 br->next = target->branchrefs;
453 target->branchrefs = br;
458 static void codegen_addxboundrefs(codegendata *cd, void *branchptr, s4 reg)
463 branchpos = (u1 *) branchptr - cd->mcodebase;
465 br = DNEW(branchref);
466 br->branchpos = branchpos;
468 br->next = cd->xboundrefs;
473 static void codegen_addxcheckarefs(codegendata *cd, void *branchptr)
478 branchpos = (u1 *) branchptr - cd->mcodebase;
480 br = DNEW(branchref);
481 br->branchpos = branchpos;
482 br->next = cd->xcheckarefs;
483 cd->xcheckarefs = br;
487 static void codegen_addxnullrefs(codegendata *cd, void *branchptr)
492 branchpos = (u1 *) branchptr - cd->mcodebase;
494 br = DNEW(branchref);
495 br->branchpos = branchpos;
496 br->next = cd->xnullrefs;
501 static void codegen_addxcastrefs(codegendata *cd, void *branchptr)
506 branchpos = (u1 *) branchptr - cd->mcodebase;
508 br = DNEW(branchref);
509 br->branchpos = branchpos;
510 br->next = cd->xcastrefs;
515 static void codegen_addxexceptionrefs(codegendata *cd, void *branchptr)
520 branchpos = (u1 *) branchptr - cd->mcodebase;
522 br = DNEW(branchref);
523 br->branchpos = branchpos;
524 br->next = cd->xexceptionrefs;
525 cd->xexceptionrefs = br;
529 #if defined(__I386__) || defined(__X86_64__)
530 static void codegen_addxdivrefs(codegendata *cd, void *branchptr)
535 branchpos = (u1 *) branchptr - cd->mcodebase;
537 br = DNEW(branchref);
538 br->branchpos = branchpos;
539 br->next = cd->xdivrefs;
545 static void codegen_addpatchref(codegendata *cd,
553 branchpos = (u1 *) branchptr - cd->mcodebase;
556 pr->branchpos = branchpos;
557 pr->patcher = patcher;
559 pr->next = cd->patchrefs;
564 static void codegen_createlinenumbertable(codegendata *cd)
566 #if defined(__I386__) || defined(__ALPHA__) || defined(__X86_64__)
569 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
570 lr->tablepos = dseg_addaddress(cd, NULL);
572 if (cd->linenumbertab == 0)
573 cd->linenumbertab = lr->tablepos;
575 dseg_addaddress(cd, lr->linenumber);
581 #if defined(__I386__) || defined(__X86_64__)
582 static int methodtree_comparator(const void *pc, const void *element, void *param)
584 methodtree_element *mte;
585 methodtree_element *mtepc;
587 mte = (methodtree_element *) element;
588 mtepc = (methodtree_element *) pc;
590 /* compare both startpc and endpc of pc, even if they have the same value,
591 otherwise the avl_probe sometimes thinks the element is already in the
593 if ((long) mte->startpc <= (long) mtepc->startpc &&
594 (long) mtepc->startpc <= (long) mte->endpc &&
595 (long) mte->startpc <= (long) mtepc->endpc &&
596 (long) mtepc->endpc <= (long) mte->endpc) {
599 } else if ((long) mtepc->startpc < (long) mte->startpc) {
608 void codegen_insertmethod(functionptr startpc, functionptr endpc)
610 methodtree_element *mte;
612 #if defined(USE_THREADS)
613 #if defined(NATIVE_THREADS)
618 mte = NEW(methodtree_element);
619 mte->startpc = startpc;
622 if (avl_insert(methodtree, mte)) {
623 #if defined(USE_THREADS)
624 #if defined(NATIVE_THREADS)
628 throw_cacao_exception_exit(string_java_lang_InternalError,
632 #if defined(USE_THREADS)
633 #if defined(NATIVE_THREADS)
640 functionptr codegen_findmethod(functionptr pc)
642 methodtree_element *mtepc;
643 methodtree_element *mte;
645 #if defined(USE_THREADS)
646 #if defined(NATIVE_THREADS)
651 mtepc = NEW(methodtree_element);
655 mte = avl_find(methodtree, mtepc);
657 FREE(mtepc, methodtree_element);
660 #if defined(USE_THREADS)
661 #if defined(NATIVE_THREADS)
669 fprintf(stderr,"backtrace:");
670 backtrace_symbols_fd(bt,5,2);
674 sprintf(msg,"cannot find function (%p)",pc);
675 throw_cacao_exception_exit(string_java_lang_InternalError,
680 #if defined(USE_THREADS)
681 #if defined(NATIVE_THREADS)
690 #if defined(__ALPHA__)
691 /*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,
692 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)*/
693 void *codegen_findmethod(void *returnAdress)
698 d=*((s4*)returnAdress);
701 dataseg=returnAdress+d;
702 d=*(((s4*)returnAdress)+1);
706 d=*(((s4*)returnAdress)+1);
712 ldl t0,0(ra) /* load instruction LDA PV,xxx(RA) */
714 sra t0,48,t0 /* isolate offset */
715 addq t0,ra,pv /* compute update address */
716 ldl t0,4(ra) /* load instruction LDAH PV,xxx(PV) */
717 srl t0,16,t0 /* isolate instruction code */
718 lda t0,-0x177b(t0) /* test for LDAH */
720 ldl t0,4(ra) /* load instruction LDAH PV,xxx(RA) */
721 sll t0,16,t0 /* compute high offset */
722 addl t0,0,t0 /* sign extend high offset */
723 addq t0,pv,pv /* compute update address */
731 static void codegen_finish(methodinfo *m, codegendata *cd, s4 mcodelen)
738 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
739 extralen = sizeof(threadcritnode) * cd->threadcritcount;
744 #if defined(STATISTICS)
746 count_code_len += mcodelen;
747 count_data_len += cd->dseglen;
751 cd->dseglen = ALIGN(cd->dseglen, MAX_ALIGN);
752 alignedlen = ALIGN(mcodelen, MAX_ALIGN) + cd->dseglen;
754 m->mcodelength = mcodelen + cd->dseglen;
755 m->mcode = (functionptr) (long) CNEW(u1, alignedlen + extralen);
757 memcpy((void *) (long) m->mcode, cd->dsegtop - cd->dseglen, cd->dseglen);
758 memcpy((void *) ((long) m->mcode + cd->dseglen), cd->mcodebase, mcodelen);
760 m->entrypoint = epoint = (functionptr) ((long) m->mcode + cd->dseglen);
762 /* jump table resolving */
763 jr = cd->jumpreferences;
765 *((functionptr *) ((long) epoint + jr->tablepos)) =
766 (functionptr) ((long) epoint + (long) jr->target->mpc);
770 #if defined(__I386__) || defined(__ALPHA__) || defined(__X86_64__)
771 /* line number table resolving */
779 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
781 *((functionptr *) ((long) epoint + (long) lr->tablepos)) =
782 (functionptr) ((long) epoint + (long) lr->targetmpc);
785 *((functionptr *) ((long) epoint + cd->linenumbertablestartpos)) =
786 (functionptr) ((long) epoint + cd->linenumbertab);
788 *((s8 *) ((s8) epoint + cd->linenumbertablesizepos)) = lrtlen;
790 *((s4 *) ((s4) epoint + cd->linenumbertablesizepos)) = lrtlen;
795 #if defined(__I386__) || defined(__X86_64__)
796 /* add method into methodtree to find the entrypoint */
798 codegen_insertmethod(m->entrypoint,
799 (functionptr) ((ptrint) m->entrypoint + mcodelen));
802 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__)
806 /* data segment references resolving */
808 dr = cd->datareferences;
810 *((functionptr *) ((ptrint) epoint + (ptrint) dr->pos - POINTERSIZE)) = epoint;
816 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
818 threadcritnode *n = (threadcritnode *) ((long) m->mcode + alignedlen);
820 threadcritnodetemp *nt = cd->threadcrit;
822 for (i = 0; i < cd->threadcritcount; i++) {
823 n->mcodebegin = (u1 *) (long) m->mcode + nt->mcodebegin;
824 n->mcodeend = (u1 *) (long) m->mcode + nt->mcodeend;
825 n->mcoderestart = (u1 *) (long) m->mcode + nt->mcoderestart;
826 thread_registercritical(n);
835 void dseg_display(methodinfo *m, codegendata *cd)
840 s4ptr = (s4 *) (ptrint) m->mcode;
842 printf(" --- dump of datasegment\n");
843 for (i = cd->dseglen; i > 0 ; i -= 4) {
844 #if defined(__I386__) || defined(__POWERPC__)
845 printf("0x%08x: -%6x (%6d): %8x\n",
846 (ptrint) s4ptr, i, i, (s4) *s4ptr);
848 printf("0x%016lx: -%6x (%6d): %8x\n",
849 (ptrint) s4ptr, i, i, (s4) *s4ptr);
854 printf(" --- begin of data segment: %p\n", (void *) s4ptr);
859 This function determines a register, to which the result of an operation
860 should go, when it is ultimatively intended to store the result in
862 If v is assigned to an actual register, this register will be returned.
863 Otherwise (when v is spilled) this function returns tempregnum.
864 If not already done, regoff and flags are set in the stack location.
867 static int reg_of_var(registerdata *rd, stackptr v, int tempregnum)
871 switch (v->varkind) {
873 if (!(v->flags & INMEMORY))
878 var = &(rd->interfaces[v->varnum][v->type]);
879 v->regoff = var->regoff;
880 if (!(var->flags & INMEMORY))
885 var = &(rd->locals[v->varnum][v->type]);
886 v->regoff = var->regoff;
887 if (!(var->flags & INMEMORY))
892 if (!(v->flags & INMEMORY))
900 v->flags |= INMEMORY;
905 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
906 static void codegen_threadcritrestart(codegendata *cd, int offset)
908 cd->threadcritcurrent.mcoderestart = offset;
912 static void codegen_threadcritstart(codegendata *cd, int offset)
914 cd->threadcritcurrent.mcodebegin = offset;
918 static void codegen_threadcritstop(codegendata *cd, int offset)
920 cd->threadcritcurrent.next = cd->threadcrit;
921 cd->threadcritcurrent.mcodeend = offset;
922 cd->threadcrit = DNEW(threadcritnodetemp);
923 *(cd->threadcrit) = cd->threadcritcurrent;
924 cd->threadcritcount++;
929 #ifndef STATIC_CLASSPATH
930 static size_t codegen_overloadPartLen(utf *desc) {
931 char *utf_ptr=desc->text;
934 while ((c=utf_nextu2(&utf_ptr))!=')') {
951 while ( (c=utf_nextu2(&utf_ptr)) != ';')
957 default: panic ("invalid method descriptor");
964 static void codegen_fillInOverloadPart(char *target,utf *desc) {
965 char *utf_ptr=desc->text;
967 char* insertpos=&target[strlen(target)];
970 while ((c=utf_nextu2(&utf_ptr))!=')') {
988 while ( (c=utf_nextu2(&utf_ptr)) != ';')
989 if ( ((c>='a') && (c<='z')) ||
990 ((c>='A') && (c<='Z')) ||
991 ((c>='0') && (c<='9')) )
993 else *(insertpos++)='_';
999 default: panic ("invalid method descriptor");
1006 static void codegen_resolve_native(methodinfo *m,void **insertionPoint,void *jmpTarget,void **jmpPatchTarget) {
1007 char *nativeName, *nativeNameEscape;
1013 #if defined(USE_THREADS)
1014 builtin_monitorenter((java_objectheader*) m);
1017 #if defined(__X86_64__)
1018 if ((*((s4*)jmpPatchTarget))==((s4)jmpTarget)) {
1020 if ((*jmpPatchTarget)==jmpTarget) {
1023 #if defined(USE_THREADS)
1024 builtin_monitorexit((java_objectheader*) m);
1029 /*log_text("trying to resolve a native method");
1030 utf_display(m->class->name);
1031 utf_display(m->name);*/
1033 lib=dlopen(0,RTLD_NOW | RTLD_GLOBAL); /* open the application execution image */
1034 if (lib) { /* it did work -> good, otherwise fail with error*/
1036 /*generate the name of the native function in the form Java_package1_package2...._classname_methodname*/
1037 nativeLen=/*Java_*/5+strlen(m->class->name->text)+/*_*/1+strlen(m->name->text)+/*\0*/1;
1038 nativeName=MNEW(char,nativeLen);
1039 sprintf(nativeName,"Java_%s/%s",m->class->name->text,m->name->text);
1041 while (i<nativeLen) {
1042 if (nativeName[i]=='_') { /* escape underscore */
1043 nativeNameEscape = MNEW(char,nativeLen+1);
1044 memcpy(nativeNameEscape,nativeName,i+1);
1045 nativeNameEscape[i+1] = '1'; /* escape sequence for _ is _1 */
1046 memcpy(&nativeNameEscape[i+2],&nativeName[i+1],nativeLen-i-1);
1047 MFREE(nativeName,char,nativeLen);
1050 nativeNameEscape[nativeLen-1]=0;
1051 nativeName=nativeNameEscape;
1053 if (nativeName[i]=='/') nativeName[i]='_';
1057 /*printf("\nnativename: %s\n",nativeName);*/
1059 /*try to find the symbal fo the function */
1060 sym=dlsym(lib,nativeName);
1062 ok=1; /* it worked, everything fine */
1063 /*log_text("resolved");*/
1064 /*printf("strlen %d, nativeLen %d\n",strlen(nativeName),nativeLen);*/
1065 MFREE(nativeName,char,nativeLen);
1066 } else { /* we didn't find the symbol yet, try to resolve an overlaoded function (having the types in it's name*/
1067 size_t overloadedNativeLen=nativeLen+codegen_overloadPartLen(m->descriptor);
1068 char *overloadedNative=MNEW(char,overloadedNativeLen);
1069 sprintf(overloadedNative,"%s",nativeName);
1070 MFREE(nativeName,char,nativeLen);
1071 codegen_fillInOverloadPart(overloadedNative,m->descriptor);
1072 /*log_text("symbol not found,trying harder (overloaded member ?)");*/
1073 sym=dlsym(lib,overloadedNative);
1075 MFREE(overloadedNative,char,overloadedNativeLen);
1076 ok=1; /* we eventually found the native function -> everything ok*/
1077 /*log_text("resolved");*/
1079 /* we failed to find the native function within the execution image (app + loaded libraries) -> will cause an exit*/
1080 dolog("\nnative function not found: %s",overloadedNative);
1081 MFREE(overloadedNative,char,overloadedNativeLen);
1082 log_text("It was not possible to find the native function implementation. Not even in overloading case");
1085 /* patch the address of the native function into the stub and make the stub jump over this function call in the future */
1087 (*insertionPoint)=sym;
1088 #if defined(__X86_64__)
1089 (*((s4*)jmpPatchTarget))=(s4)jmpTarget;
1091 (*jmpPatchTarget)=jmpTarget;
1094 #if defined(USE_THREADS)
1095 builtin_monitorexit((java_objectheader *) m );
1101 } else log_text("library not found");
1103 /* There was an error, either the app image could not be opened or the native does not exist in the application and the
1104 loaded libraries. Show an additional error and exit the vm*/
1108 slen=2+strlen(m->class->name->text)+strlen(m->name->text)+strlen(m->descriptor->text);
1109 info=(char*)MNEW(char,slen);
1110 sprintf(info,"%s.%s%s",m->class->name->text,m->name->text,m->descriptor->text);
1112 #if defined(USE_THREADS)
1113 builtin_monitorexit((java_objectheader *) m );
1116 throw_cacao_exception_exit(string_java_lang_LinkageError,
1127 * These are local overrides for various environment variables in Emacs.
1128 * Please do not remove this and leave it at the end of the file, where
1129 * Emacs will automagically detect them.
1130 * ---------------------------------------------------------------------
1133 * indent-tabs-mode: t