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 1735 2004-12-07 14:33:27Z 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))
860 var = &(rd->interfaces[v->varnum][v->type]);
861 v->regoff = var->regoff;
862 if (!(var->flags & INMEMORY))
866 var = &(rd->locals[v->varnum][v->type]);
867 v->regoff = var->regoff;
868 if (!(var->flags & INMEMORY))
872 v->regoff = v->varnum;
873 if (IS_FLT_DBL_TYPE(v->type)) {
874 if (v->varnum < rd->fltreg_argnum) {
875 v->regoff = rd->argfltregs[v->varnum];
876 return(rd->argfltregs[v->varnum]);
880 #if defined(__POWERPC__)
881 if (v->varnum < rd->intreg_argnum - (IS_2_WORD_TYPE(v->type) != 0)) {
883 if (v->varnum < rd->intreg_argnum) {
885 v->regoff = rd->argintregs[v->varnum];
886 return (rd->argintregs[v->varnum]);
889 #if defined(__POWERPC__)
892 v->regoff -= rd->intreg_argnum;
896 v->flags |= INMEMORY;
901 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
902 static void codegen_threadcritrestart(codegendata *cd, int offset)
904 cd->threadcritcurrent.mcoderestart = offset;
908 static void codegen_threadcritstart(codegendata *cd, int offset)
910 cd->threadcritcurrent.mcodebegin = offset;
914 static void codegen_threadcritstop(codegendata *cd, int offset)
916 cd->threadcritcurrent.next = cd->threadcrit;
917 cd->threadcritcurrent.mcodeend = offset;
918 cd->threadcrit = DNEW(threadcritnodetemp);
919 *(cd->threadcrit) = cd->threadcritcurrent;
920 cd->threadcritcount++;
925 #ifndef STATIC_CLASSPATH
926 static size_t codegen_overloadPartLen(utf *desc) {
927 char *utf_ptr=desc->text;
930 while ((c=utf_nextu2(&utf_ptr))!=')') {
947 while ( (c=utf_nextu2(&utf_ptr)) != ';')
953 default: panic ("invalid method descriptor");
960 static void codegen_fillInOverloadPart(char *target,utf *desc) {
961 char *utf_ptr=desc->text;
963 char* insertpos=&target[strlen(target)];
966 while ((c=utf_nextu2(&utf_ptr))!=')') {
984 while ( (c=utf_nextu2(&utf_ptr)) != ';')
985 if ( ((c>='a') && (c<='z')) ||
986 ((c>='A') && (c<='Z')) ||
987 ((c>='0') && (c<='9')) )
989 else *(insertpos++)='_';
995 default: panic ("invalid method descriptor");
1002 static void codegen_resolve_native(methodinfo *m,void **insertionPoint,void *jmpTarget,void **jmpPatchTarget) {
1003 char *nativeName, *nativeNameEscape;
1009 builtin_monitorenter((java_objectheader*) m);
1010 #if defined(__X86_64__)
1011 if ((*((s4*)jmpPatchTarget))==((s4)jmpTarget)) {
1013 if ((*jmpPatchTarget)==jmpTarget) {
1015 builtin_monitorexit((java_objectheader*) m);
1018 /*log_text("trying to resolve a native method");
1019 utf_display(m->class->name);
1020 utf_display(m->name);*/
1022 lib=dlopen(0,RTLD_NOW | RTLD_GLOBAL); /* open the application execution image */
1023 if (lib) { /* it did work -> good, otherwise fail with error*/
1025 /*generate the name of the native function in the form Java_package1_package2...._classname_methodname*/
1026 nativeLen=/*Java_*/5+strlen(m->class->name->text)+/*_*/1+strlen(m->name->text)+/*\0*/1;
1027 nativeName=MNEW(char,nativeLen);
1028 sprintf(nativeName,"Java_%s/%s",m->class->name->text,m->name->text);
1030 while (i<nativeLen) {
1031 if (nativeName[i]=='_') { /* escape underscore */
1032 nativeNameEscape = MNEW(char,nativeLen+1);
1033 memcpy(nativeNameEscape,nativeName,i+1);
1034 nativeNameEscape[i+1] = '1'; /* escape sequence for _ is _1 */
1035 memcpy(&nativeNameEscape[i+2],&nativeName[i+1],nativeLen-i-1);
1036 MFREE(nativeName,char,nativeLen);
1039 nativeNameEscape[nativeLen]=0;
1040 nativeName=nativeNameEscape;
1042 if (nativeName[i]=='/') nativeName[i]='_';
1046 /* printf("nativename: %s\n",nativeName); */
1048 /*try to find the symbal fo the function */
1049 sym=dlsym(lib,nativeName);
1051 ok=1; /* it worked, everything fine */
1052 /*log_text("resolved");*/
1053 MFREE(nativeName,char,nativeLen);
1054 } else { /* we didn't find the symbol yet, try to resolve an overlaoded function (having the types in it's name*/
1055 size_t overloadedNativeLen=nativeLen+codegen_overloadPartLen(m->descriptor);
1056 char *overloadedNative=MNEW(char,overloadedNativeLen);
1057 sprintf(overloadedNative,"%s",nativeName);
1058 MFREE(nativeName,char,nativeLen);
1059 codegen_fillInOverloadPart(overloadedNative,m->descriptor);
1060 /*log_text("symbol not found,trying harder (overloaded member ?)");*/
1061 sym=dlsym(lib,overloadedNative);
1063 MFREE(overloadedNative,char,overloadedNativeLen);
1064 ok=1; /* we eventually found the native function -> everything ok*/
1065 /*log_text("resolved");*/
1067 /* we failed to find the native function within the execution image (app + loaded libraries) -> will cause an exit*/
1068 MFREE(overloadedNative,char,overloadedNativeLen);
1069 log_text("It was not possible to find the native function implementation. Not even in overloading case");
1072 /* patch the address of the native function into the stub and make the stub jump over this function call in the future */
1074 (*insertionPoint)=sym;
1075 #if defined(__X86_64__)
1076 (*((s4*)jmpPatchTarget))=(s4)jmpTarget;
1078 (*jmpPatchTarget)=jmpTarget;
1080 builtin_monitorexit((java_objectheader *) m );
1084 } else log_text("library not found");
1086 /* There was an error, either the app image could not be opened or the native does not exist in the application and the
1087 loaded libraries. Show an additional error and exit the vm*/
1091 slen=2+strlen(m->class->name->text)+strlen(m->name->text)+strlen(m->descriptor->text);
1092 info=(char*)MNEW(char,slen);
1093 sprintf(info,"%s.%s%s",m->class->name->text,m->name->text,m->descriptor->text);
1095 builtin_monitorexit((java_objectheader *) m );
1096 throw_cacao_exception_exit(string_java_lang_LinkageError,
1107 * These are local overrides for various environment variables in Emacs.
1108 * Please do not remove this and leave it at the end of the file, where
1109 * Emacs will automagically detect them.
1110 * ---------------------------------------------------------------------
1113 * indent-tabs-mode: t