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 1759 2004-12-14 13:16:11Z twisti $
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"
82 /* in this tree we store all method addresses *********************************/
84 #if defined(__I386__) || defined(__X86_64__)
85 static struct avl_table *methodtree = NULL;
86 static int methodtree_comparator(const void *pc, const void *element,
91 /* codegen_init ****************************************************************
95 *******************************************************************************/
99 #if defined(__I386__) || defined(__X86_64__)
100 /* this tree is global, not method specific */
102 methodtree_element *mte;
104 methodtree = avl_create(methodtree_comparator, NULL, NULL);
106 mte = NEW(methodtree_element);
108 mte->startpc = (functionptr) asm_calljavafunction;
109 mte->endpc = (functionptr) ((long) asm_calljavafunction2 - 1);
111 avl_insert(methodtree, mte);
113 mte = NEW(methodtree_element);
115 mte->startpc = (functionptr) asm_calljavafunction2;
116 mte->endpc = (functionptr) ((long) asm_call_jit_compiler - 1);
118 avl_insert(methodtree, mte);
124 /* codegen_setup **************************************************************
126 allocates and initialises code area, data area and references
128 *******************************************************************************/
130 void codegen_setup(methodinfo *m, codegendata *cd, t_inlining_globals *id)
132 cd->mcodebase = MNEW(u1, MCODEINITSIZE);
133 cd->mcodesize = MCODEINITSIZE;
135 cd->dsegtop = MNEW(u1, DSEGINITSIZE);
136 cd->dsegsize = DSEGINITSIZE;
137 cd->dsegtop += cd->dsegsize;
140 cd->jumpreferences = NULL;
141 cd->datareferences = NULL;
142 cd->xboundrefs = NULL;
143 cd->xcheckarefs = NULL;
144 cd->xnullrefs = NULL;
145 cd->xcastrefs = NULL;
147 cd->xexceptionrefs = NULL;
148 cd->clinitrefs = NULL;
150 cd->linenumberreferences = NULL;
151 cd->linenumbertablesizepos = 0;
152 cd->linenumbertablestartpos = 0;
153 cd->linenumbertab = 0;
156 cd->exceptiontable = 0;
157 cd->exceptiontablelength = 0;
159 if (useinlining && id) {
160 if (id->cumextablelength > 0) {
161 cd->exceptiontablelength = id->cumextablelength;
162 cd->exceptiontable = DMNEW(exceptiontable, id->cumextablelength + 1);
165 } else if (id && (id->method->exceptiontablelength >0)) {
166 cd->exceptiontablelength = m->exceptiontablelength;
167 cd->exceptiontable = DMNEW(exceptiontable, m->exceptiontablelength + 1);
171 cd->maxstack = id->cummaxstack;
172 cd->maxlocals = id->cumlocals;
174 cd->maxstack = m->maxstack;
175 cd->maxlocals = m->maxlocals;
178 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
179 cd->threadcritcurrent.next = NULL;
180 cd->threadcritcount = 0;
185 /* codegen_free ****************************************************************
187 releases temporary code and data area
189 *******************************************************************************/
191 void codegen_free(methodinfo *m, codegendata *cd)
195 if (cd->exceptiontablelength) {
196 cd->exceptiontablelength = m->exceptiontablelength;
197 MFREE(cd->exceptiontable, exceptiontable, cd->exceptiontablelength + 1);
198 cd->exceptiontable = 0;
199 cd->exceptiontablelength = 0;
204 MFREE(cd->mcodebase, u1, cd->mcodesize);
205 cd->mcodebase = NULL;
209 MFREE(cd->dsegtop - cd->dsegsize, u1, cd->dsegsize);
216 /* codegen_close ***************************************************************
220 *******************************************************************************/
224 /* TODO: release avl tree on i386 and x86_64 */
228 /* codegen_increase doubles code area */
230 static s4 *codegen_increase(codegendata *cd, u1 *codeptr)
234 len = codeptr - cd->mcodebase;
235 cd->mcodebase = MREALLOC(cd->mcodebase,
240 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
242 return (s4 *) (cd->mcodebase + len);
246 /* desg_increase doubles data area */
248 static void dseg_increase(codegendata *cd)
252 newstorage = MNEW(u1, cd->dsegsize * 2);
254 memcpy(newstorage + cd->dsegsize, cd->dsegtop - cd->dsegsize, cd->dsegsize);
255 MFREE(cd->dsegtop - cd->dsegsize, u1, cd->dsegsize);
257 cd->dsegtop = newstorage;
259 cd->dsegtop += cd->dsegsize;
263 static s4 dseg_adds4_increase(codegendata *cd, s4 value)
267 *((s4 *) (cd->dsegtop - cd->dseglen)) = value;
269 return -(cd->dseglen);
273 static s4 dseg_adds4(codegendata *cd, s4 value)
278 dataptr = (s4 *) (cd->dsegtop - cd->dseglen);
280 if (cd->dseglen > cd->dsegsize)
281 return dseg_adds4_increase(cd, value);
285 return -(cd->dseglen);
289 #if !defined(__I386__)
290 static s4 dseg_adds8_increase(codegendata *cd, s8 value)
294 *((s8 *) (cd->dsegtop - cd->dseglen)) = value;
296 return -(cd->dseglen);
300 static s4 dseg_adds8(codegendata *cd, s8 value)
304 cd->dseglen = ALIGN(cd->dseglen + 8, 8);
305 dataptr = (s8 *) (cd->dsegtop - cd->dseglen);
307 if (cd->dseglen > cd->dsegsize)
308 return dseg_adds8_increase(cd, value);
312 return -(cd->dseglen);
317 static s4 dseg_addfloat_increase(codegendata *cd, float value)
321 *((float *) (cd->dsegtop - cd->dseglen)) = value;
323 return -(cd->dseglen);
327 static s4 dseg_addfloat(codegendata *cd, float value)
332 dataptr = (float *) (cd->dsegtop - cd->dseglen);
334 if (cd->dseglen > cd->dsegsize)
335 return dseg_addfloat_increase(cd, value);
339 return -(cd->dseglen);
343 static s4 dseg_adddouble_increase(codegendata *cd, double value)
347 *((double *) (cd->dsegtop - cd->dseglen)) = value;
349 return -(cd->dseglen);
353 static s4 dseg_adddouble(codegendata *cd, double value)
357 cd->dseglen = ALIGN(cd->dseglen + 8, 8);
358 dataptr = (double *) (cd->dsegtop - cd->dseglen);
360 if (cd->dseglen > cd->dsegsize)
361 return dseg_adddouble_increase(cd, value);
365 return -(cd->dseglen);
369 static void dseg_addtarget(codegendata *cd, basicblock *target)
374 jr->tablepos = dseg_addaddress(cd, NULL);
376 jr->next = cd->jumpreferences;
377 cd->jumpreferences = jr;
381 static void dseg_adddata(codegendata *cd, u1 *ptr)
386 dr->pos = (u1 *) (ptr - cd->mcodebase);
387 dr->next = cd->datareferences;
388 cd->datareferences = dr;
392 static void dseg_addlinenumbertablesize(codegendata *cd)
395 dseg_adds4(cd, 0); /*PADDING*/
397 cd->linenumbertablesizepos = dseg_addaddress(cd, NULL); /*it could be considered to use adds4 here, to avoid 1 double word padding on ALPHA */
399 cd->linenumbertablestartpos = dseg_addaddress(cd, NULL);
401 dseg_adds4(cd, 0); /*PADDING*/
406 static void dseg_addlinenumber(codegendata *cd, u2 linenumber, u1 *ptr)
410 lr = DNEW(linenumberref);
411 lr->linenumber = linenumber;
413 lr->targetmpc = (ptr - cd->mcodebase);
414 lr->next = cd->linenumberreferences;
415 cd->linenumberreferences = lr;
419 /* we need this function externally on i386 and x86_64, but keep the call fast
422 #if defined(__I386__) || defined(__X86_64__)
423 void codegen_addreference(codegendata *cd, basicblock *target, void *branchptr)
425 static void codegen_addreference(codegendata *cd, basicblock *target, void *branchptr)
430 branchpos = (u1 *) branchptr - cd->mcodebase;
432 if (target->mpc >= 0) {
433 gen_resolvebranch((u1 *) cd->mcodebase + branchpos,
438 branchref *br = DNEW(branchref);
440 br->branchpos = branchpos;
441 br->next = target->branchrefs;
442 target->branchrefs = br;
447 static void codegen_addxboundrefs(codegendata *cd, void *branchptr, s4 reg)
452 branchpos = (u1 *) branchptr - cd->mcodebase;
454 br = DNEW(branchref);
455 br->branchpos = branchpos;
457 br->next = cd->xboundrefs;
462 static void codegen_addxcheckarefs(codegendata *cd, void *branchptr)
467 branchpos = (u1 *) branchptr - cd->mcodebase;
469 br = DNEW(branchref);
470 br->branchpos = branchpos;
471 br->next = cd->xcheckarefs;
472 cd->xcheckarefs = br;
476 static void codegen_addxnullrefs(codegendata *cd, void *branchptr)
481 branchpos = (u1 *) branchptr - cd->mcodebase;
483 br = DNEW(branchref);
484 br->branchpos = branchpos;
485 br->next = cd->xnullrefs;
490 static void codegen_addxcastrefs(codegendata *cd, void *branchptr)
495 branchpos = (u1 *) branchptr - cd->mcodebase;
497 br = DNEW(branchref);
498 br->branchpos = branchpos;
499 br->next = cd->xcastrefs;
504 static void codegen_addxexceptionrefs(codegendata *cd, void *branchptr)
509 branchpos = (u1 *) branchptr - cd->mcodebase;
511 br = DNEW(branchref);
512 br->branchpos = branchpos;
513 br->next = cd->xexceptionrefs;
514 cd->xexceptionrefs = br;
518 #if defined(__I386__) || defined(__X86_64__)
519 static void codegen_addxdivrefs(codegendata *cd, void *branchptr)
524 branchpos = (u1 *) branchptr - cd->mcodebase;
526 br = DNEW(branchref);
527 br->branchpos = branchpos;
528 br->next = cd->xdivrefs;
534 static void codegen_addclinitref(codegendata *cd,
541 branchpos = (u1 *) branchptr - cd->mcodebase;
543 cr = DNEW(clinitref);
544 cr->branchpos = branchpos;
546 cr->next = cd->clinitrefs;
551 static void codegen_createlinenumbertable(codegendata *cd)
553 #if defined(__I386__) || defined(__ALPHA__)
556 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
557 lr->tablepos = dseg_addaddress(cd, NULL);
559 if (cd->linenumbertab == 0)
560 cd->linenumbertab = lr->tablepos;
562 dseg_addaddress(cd, lr->linenumber);
568 #if defined(__I386__) || defined(__X86_64__)
569 static int methodtree_comparator(const void *pc, const void *element, void *param)
571 methodtree_element *mte;
572 methodtree_element *mtepc;
574 mte = (methodtree_element *) element;
575 mtepc = (methodtree_element *) pc;
577 /* compare both startpc and endpc of pc, even if they have the same value,
578 otherwise the avl_probe sometimes thinks the element is already in the
580 if ((long) mte->startpc <= (long) mtepc->startpc &&
581 (long) mtepc->startpc <= (long) mte->endpc &&
582 (long) mte->startpc <= (long) mtepc->endpc &&
583 (long) mtepc->endpc <= (long) mte->endpc) {
586 } else if ((long) mtepc->startpc < (long) mte->startpc) {
596 void *codegen_findmethod1(void *pc)
598 void * retVal=findmethod(pc);
599 methodinfo **ma=(methodinfo**)retVal;
600 methodinfo *m=ma[-1];
603 utf_display(m->name);
606 else log_text("No methodinfo");
612 void codegen_insertmethod(functionptr startpc, functionptr endpc)
614 methodtree_element *mte;
616 #if defined(USE_THREADS)
617 #if defined(NATIVE_THREADS)
622 mte = NEW(methodtree_element);
623 mte->startpc = startpc;
626 if (avl_insert(methodtree, mte)) {
627 #if defined(USE_THREADS)
628 #if defined(NATIVE_THREADS)
632 throw_cacao_exception_exit(string_java_lang_InternalError,
636 #if defined(USE_THREADS)
637 #if defined(NATIVE_THREADS)
644 functionptr codegen_findmethod(functionptr pc)
646 methodtree_element *mtepc;
647 methodtree_element *mte;
649 #if defined(USE_THREADS)
650 #if defined(NATIVE_THREADS)
655 mtepc = NEW(methodtree_element);
659 mte = avl_find(methodtree, mtepc);
661 FREE(mtepc, methodtree_element);
664 #if defined(USE_THREADS)
665 #if defined(NATIVE_THREADS)
669 throw_cacao_exception_exit(string_java_lang_InternalError,
670 "cannot find function");
673 #if defined(USE_THREADS)
674 #if defined(NATIVE_THREADS)
683 #if defined(__ALPHA__)
684 /*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,
685 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)*/
686 void *codegen_findmethod(void *returnAdress)
691 d=*((s4*)returnAdress);
694 dataseg=returnAdress+d;
695 d=*(((s4*)returnAdress)+1);
699 d=*(((s4*)returnAdress)+1);
705 ldl t0,0(ra) /* load instruction LDA PV,xxx(RA) */
707 sra t0,48,t0 /* isolate offset */
708 addq t0,ra,pv /* compute update address */
709 ldl t0,4(ra) /* load instruction LDAH PV,xxx(PV) */
710 srl t0,16,t0 /* isolate instruction code */
711 lda t0,-0x177b(t0) /* test for LDAH */
713 ldl t0,4(ra) /* load instruction LDAH PV,xxx(RA) */
714 sll t0,16,t0 /* compute high offset */
715 addl t0,0,t0 /* sign extend high offset */
716 addq t0,pv,pv /* compute update address */
724 static void codegen_finish(methodinfo *m, codegendata *cd, s4 mcodelen)
731 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
732 extralen = sizeof(threadcritnode) * cd->threadcritcount;
737 #if defined(STATISTICS)
739 count_code_len += mcodelen;
740 count_data_len += cd->dseglen;
744 cd->dseglen = ALIGN(cd->dseglen, MAX_ALIGN);
745 alignedlen = ALIGN(mcodelen, MAX_ALIGN) + cd->dseglen;
747 m->mcodelength = mcodelen + cd->dseglen;
748 m->mcode = (functionptr) (long) CNEW(u1, alignedlen + extralen);
750 memcpy((void *) (long) m->mcode, cd->dsegtop - cd->dseglen, cd->dseglen);
751 memcpy((void *) ((long) m->mcode + cd->dseglen), cd->mcodebase, mcodelen);
753 m->entrypoint = epoint = (functionptr) ((long) m->mcode + cd->dseglen);
755 /* jump table resolving */
756 jr = cd->jumpreferences;
758 *((functionptr *) ((long) epoint + jr->tablepos)) =
759 (functionptr) ((long) epoint + (long) jr->target->mpc);
763 #if defined(__I386__) || defined(__ALPHA__)
764 /* line number table resolving */
773 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
775 *((functionptr *) ((long) epoint + (long) lr->tablepos)) =
776 (functionptr) ((long) epoint + (long) lr->targetmpc);
779 *((functionptr *) ((long) epoint + cd->linenumbertablestartpos)) =
780 (functionptr) ((long) epoint + cd->linenumbertab);
782 *((s8 *) ((s8) epoint + cd->linenumbertablesizepos)) = lrtlen;
784 *((s4 *) ((s4) epoint + cd->linenumbertablesizepos)) = lrtlen;
789 #if defined(__I386__) || defined(__X86_64__)
793 /* add method into methodtree to find the entrypoint */
794 codegen_insertmethod(m->entrypoint,
795 (functionptr) ((long) m->entrypoint + mcodelen));
797 /* data segment references resolving */
798 dr = cd->datareferences;
800 *((functionptr *) ((long) epoint + (long) dr->pos - POINTERSIZE)) =
807 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
809 threadcritnode *n = (threadcritnode *) ((long) m->mcode + alignedlen);
811 threadcritnodetemp *nt = cd->threadcrit;
813 for (i = 0; i < cd->threadcritcount; i++) {
814 n->mcodebegin = (u1 *) (long) m->mcode + nt->mcodebegin;
815 n->mcodeend = (u1 *) (long) m->mcode + nt->mcodeend;
816 n->mcoderestart = (u1 *) (long) m->mcode + nt->mcoderestart;
817 thread_registercritical(n);
826 void dseg_display(methodinfo *m, codegendata *cd)
831 s4ptr = (s4 *) (long) m->mcode;
833 printf(" --- dump of datasegment\n");
834 for (i = cd->dseglen; i > 0 ; i -= 4) {
835 printf("-%6x: %8x\n", i, (s4) (*s4ptr++));
837 printf(" --- begin of data segment: %p\n", (void *) s4ptr);
842 This function determines a register, to which the result of an operation
843 should go, when it is ultimatively intended to store the result in
845 If v is assigned to an actual register, this register will be returned.
846 Otherwise (when v is spilled) this function returns tempregnum.
847 If not already done, regoff and flags are set in the stack location.
850 static int reg_of_var(registerdata *rd, stackptr v, int tempregnum)
854 switch (v->varkind) {
856 if (!(v->flags & INMEMORY))
861 var = &(rd->interfaces[v->varnum][v->type]);
862 v->regoff = var->regoff;
863 if (!(var->flags & INMEMORY))
868 var = &(rd->locals[v->varnum][v->type]);
869 v->regoff = var->regoff;
870 if (!(var->flags & INMEMORY))
875 v->regoff = v->varnum;
876 if (IS_FLT_DBL_TYPE(v->type)) {
877 if (v->varnum < FLT_ARG_CNT) {
878 v->regoff = rd->argfltregs[v->varnum];
879 return(rd->argfltregs[v->varnum]);
882 #if defined(__POWERPC__)
885 v->regoff -= FLT_ARG_CNT;
889 #if defined(__POWERPC__)
890 if (v->varnum < INT_ARG_CNT - (IS_2_WORD_TYPE(v->type) != 0)) {
892 if (v->varnum < INT_ARG_CNT) {
894 v->regoff = rd->argintregs[v->varnum];
895 return (rd->argintregs[v->varnum]);
898 #if defined(__POWERPC__)
901 v->regoff -= INT_ARG_CNT;
907 v->flags |= INMEMORY;
912 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
913 static void codegen_threadcritrestart(codegendata *cd, int offset)
915 cd->threadcritcurrent.mcoderestart = offset;
919 static void codegen_threadcritstart(codegendata *cd, int offset)
921 cd->threadcritcurrent.mcodebegin = offset;
925 static void codegen_threadcritstop(codegendata *cd, int offset)
927 cd->threadcritcurrent.next = cd->threadcrit;
928 cd->threadcritcurrent.mcodeend = offset;
929 cd->threadcrit = DNEW(threadcritnodetemp);
930 *(cd->threadcrit) = cd->threadcritcurrent;
931 cd->threadcritcount++;
936 #ifndef STATIC_CLASSPATH
937 static size_t codegen_overloadPartLen(utf *desc) {
938 char *utf_ptr=desc->text;
941 while ((c=utf_nextu2(&utf_ptr))!=')') {
958 while ( (c=utf_nextu2(&utf_ptr)) != ';')
964 default: panic ("invalid method descriptor");
971 static void codegen_fillInOverloadPart(char *target,utf *desc) {
972 char *utf_ptr=desc->text;
974 char* insertpos=&target[strlen(target)];
977 while ((c=utf_nextu2(&utf_ptr))!=')') {
995 while ( (c=utf_nextu2(&utf_ptr)) != ';')
996 if ( ((c>='a') && (c<='z')) ||
997 ((c>='A') && (c<='Z')) ||
998 ((c>='0') && (c<='9')) )
1000 else *(insertpos++)='_';
1006 default: panic ("invalid method descriptor");
1013 static void codegen_resolve_native(methodinfo *m,void **insertionPoint,void *jmpTarget,void **jmpPatchTarget) {
1014 char *nativeName, *nativeNameEscape;
1020 builtin_monitorenter((java_objectheader*) m);
1021 #if defined(__X86_64__)
1022 if ((*((s4*)jmpPatchTarget))==((s4)jmpTarget)) {
1024 if ((*jmpPatchTarget)==jmpTarget) {
1026 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]=0;
1051 nativeName=nativeNameEscape;
1053 if (nativeName[i]=='/') nativeName[i]='_';
1057 /* printf("nativename: %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 MFREE(nativeName,char,nativeLen);
1065 } else { /* we didn't find the symbol yet, try to resolve an overlaoded function (having the types in it's name*/
1066 size_t overloadedNativeLen=nativeLen+codegen_overloadPartLen(m->descriptor);
1067 char *overloadedNative=MNEW(char,overloadedNativeLen);
1068 sprintf(overloadedNative,"%s",nativeName);
1069 MFREE(nativeName,char,nativeLen);
1070 codegen_fillInOverloadPart(overloadedNative,m->descriptor);
1071 /*log_text("symbol not found,trying harder (overloaded member ?)");*/
1072 sym=dlsym(lib,overloadedNative);
1074 MFREE(overloadedNative,char,overloadedNativeLen);
1075 ok=1; /* we eventually found the native function -> everything ok*/
1076 /*log_text("resolved");*/
1078 /* we failed to find the native function within the execution image (app + loaded libraries) -> will cause an exit*/
1079 MFREE(overloadedNative,char,overloadedNativeLen);
1080 log_text("It was not possible to find the native function implementation. Not even in overloading case");
1083 /* patch the address of the native function into the stub and make the stub jump over this function call in the future */
1085 (*insertionPoint)=sym;
1086 #if defined(__X86_64__)
1087 (*((s4*)jmpPatchTarget))=(s4)jmpTarget;
1089 (*jmpPatchTarget)=jmpTarget;
1091 builtin_monitorexit((java_objectheader *) m );
1095 } else log_text("library not found");
1097 /* There was an error, either the app image could not be opened or the native does not exist in the application and the
1098 loaded libraries. Show an additional error and exit the vm*/
1102 slen=2+strlen(m->class->name->text)+strlen(m->name->text)+strlen(m->descriptor->text);
1103 info=(char*)MNEW(char,slen);
1104 sprintf(info,"%s.%s%s",m->class->name->text,m->name->text,m->descriptor->text);
1106 builtin_monitorexit((java_objectheader *) m );
1107 throw_cacao_exception_exit(string_java_lang_LinkageError,
1118 * These are local overrides for various environment variables in Emacs.
1119 * Please do not remove this and leave it at the end of the file, where
1120 * Emacs will automagically detect them.
1121 * ---------------------------------------------------------------------
1124 * indent-tabs-mode: t