1 /* src/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 2507 2005-05-23 08:34:04Z twisti $
58 #if !defined(STATIC_CLASSPATH)
62 #include "mm/memory.h"
63 #include "toolbox/avl.h"
64 #include "toolbox/logging.h"
65 #include "native/native.h"
67 #if defined(USE_THREADS)
68 # if defined(NATIVE_THREADS)
69 # include "threads/native/threads.h"
71 # include "threads/green/threads.h"
75 #include "vm/exceptions.h"
76 #include "vm/options.h"
77 #include "vm/statistics.h"
78 #include "vm/jit/codegen.inc.h"
86 /* in this tree we store all method addresses *********************************/
88 #if defined(__I386__) || defined(__X86_64__)
89 static struct avl_table *methodtree = NULL;
90 static int methodtree_comparator(const void *pc, const void *element,
95 /* codegen_init ****************************************************************
99 *******************************************************************************/
103 #if defined(__I386__) || defined(__X86_64__)
104 /* this tree is global, not method specific */
106 methodtree_element *mte;
108 methodtree = avl_create(methodtree_comparator, NULL, NULL);
110 /* insert asm_calljavafunction */
112 mte = NEW(methodtree_element);
114 mte->startpc = (functionptr) asm_calljavafunction;
115 mte->endpc = (functionptr) ((ptrint) asm_calljavafunction2 - 1);
117 avl_insert(methodtree, mte);
119 /* insert asm_calljavafunction2 */
121 mte = NEW(methodtree_element);
123 mte->startpc = (functionptr) asm_calljavafunction2;
124 mte->endpc = (functionptr) ((ptrint) asm_call_jit_compiler - 1);
126 avl_insert(methodtree, mte);
132 /* codegen_setup **************************************************************
134 allocates and initialises code area, data area and references
136 *******************************************************************************/
138 void codegen_setup(methodinfo *m, codegendata *cd, t_inlining_globals *id)
140 cd->mcodebase = MNEW(u1, MCODEINITSIZE);
141 cd->mcodesize = MCODEINITSIZE;
143 cd->dsegtop = MNEW(u1, DSEGINITSIZE);
144 cd->dsegsize = DSEGINITSIZE;
145 cd->dsegtop += cd->dsegsize;
148 cd->jumpreferences = NULL;
149 cd->datareferences = NULL;
150 cd->xboundrefs = NULL;
151 cd->xcheckarefs = NULL;
152 cd->xnullrefs = NULL;
153 cd->xcastrefs = NULL;
155 cd->xexceptionrefs = NULL;
156 cd->patchrefs = NULL;
158 cd->linenumberreferences = NULL;
159 cd->linenumbertablesizepos = 0;
160 cd->linenumbertablestartpos = 0;
161 cd->linenumbertab = 0;
164 cd->exceptiontable = 0;
165 cd->exceptiontablelength = 0;
167 if (useinlining && id) {
168 if (id->cumextablelength > 0) {
169 cd->exceptiontablelength = id->cumextablelength;
170 cd->exceptiontable = DMNEW(exceptiontable, id->cumextablelength + 1);
173 } else if (id && (id->method->exceptiontablelength >0)) {
174 cd->exceptiontablelength = m->exceptiontablelength;
175 cd->exceptiontable = DMNEW(exceptiontable, m->exceptiontablelength + 1);
179 cd->maxstack = id->cummaxstack;
180 cd->maxlocals = id->cumlocals;
182 cd->maxstack = m->maxstack;
183 cd->maxlocals = m->maxlocals;
186 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
187 cd->threadcritcurrent.next = NULL;
188 cd->threadcritcount = 0;
193 /* codegen_free ****************************************************************
195 releases temporary code and data area
197 *******************************************************************************/
199 void codegen_free(methodinfo *m, codegendata *cd)
203 if (cd->exceptiontablelength) {
204 cd->exceptiontablelength = m->exceptiontablelength;
205 MFREE(cd->exceptiontable, exceptiontable, cd->exceptiontablelength + 1);
206 cd->exceptiontable = 0;
207 cd->exceptiontablelength = 0;
212 MFREE(cd->mcodebase, u1, cd->mcodesize);
213 cd->mcodebase = NULL;
217 MFREE(cd->dsegtop - cd->dsegsize, u1, cd->dsegsize);
224 /* codegen_close ***************************************************************
228 *******************************************************************************/
232 /* TODO: release avl tree on i386 and x86_64 */
236 /* codegen_increase doubles code area */
238 static s4 *codegen_increase(codegendata *cd, u1 *codeptr)
242 len = codeptr - cd->mcodebase;
243 cd->mcodebase = MREALLOC(cd->mcodebase,
248 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
250 return (s4 *) (cd->mcodebase + len);
254 /* desg_increase doubles data area */
256 static void dseg_increase(codegendata *cd)
260 newstorage = MNEW(u1, cd->dsegsize * 2);
262 memcpy(newstorage + cd->dsegsize, cd->dsegtop - cd->dsegsize, cd->dsegsize);
263 MFREE(cd->dsegtop - cd->dsegsize, u1, cd->dsegsize);
265 cd->dsegtop = newstorage;
267 cd->dsegtop += cd->dsegsize;
271 static s4 dseg_adds4_increase(codegendata *cd, s4 value)
275 *((s4 *) (cd->dsegtop - cd->dseglen)) = value;
277 return -(cd->dseglen);
281 static s4 dseg_adds4(codegendata *cd, s4 value)
286 dataptr = (s4 *) (cd->dsegtop - cd->dseglen);
288 if (cd->dseglen > cd->dsegsize)
289 return dseg_adds4_increase(cd, value);
293 return -(cd->dseglen);
297 #if !defined(__I386__)
298 static s4 dseg_adds8_increase(codegendata *cd, s8 value)
302 *((s8 *) (cd->dsegtop - cd->dseglen)) = value;
304 return -(cd->dseglen);
308 static s4 dseg_adds8(codegendata *cd, s8 value)
312 cd->dseglen = ALIGN(cd->dseglen + 8, 8);
313 dataptr = (s8 *) (cd->dsegtop - cd->dseglen);
315 if (cd->dseglen > cd->dsegsize)
316 return dseg_adds8_increase(cd, value);
320 return -(cd->dseglen);
325 #if !defined(__XDSPCORE__)
326 static s4 dseg_addfloat_increase(codegendata *cd, float value)
330 *((float *) (cd->dsegtop - cd->dseglen)) = value;
332 return -(cd->dseglen);
336 static s4 dseg_addfloat(codegendata *cd, float value)
341 dataptr = (float *) (cd->dsegtop - cd->dseglen);
343 if (cd->dseglen > cd->dsegsize)
344 return dseg_addfloat_increase(cd, value);
348 return -(cd->dseglen);
352 static s4 dseg_adddouble_increase(codegendata *cd, double value)
356 *((double *) (cd->dsegtop - cd->dseglen)) = value;
358 return -(cd->dseglen);
362 static s4 dseg_adddouble(codegendata *cd, double value)
366 cd->dseglen = ALIGN(cd->dseglen + 8, 8);
367 dataptr = (double *) (cd->dsegtop - cd->dseglen);
369 if (cd->dseglen > cd->dsegsize)
370 return dseg_adddouble_increase(cd, value);
374 return -(cd->dseglen);
376 #endif /* !defined(__XDSPCORE__) */
379 static void dseg_addtarget(codegendata *cd, basicblock *target)
384 jr->tablepos = dseg_addaddress(cd, NULL);
386 jr->next = cd->jumpreferences;
387 cd->jumpreferences = jr;
391 static void dseg_adddata(codegendata *cd, u1 *ptr)
396 dr->pos = (u1 *) (ptr - cd->mcodebase);
397 dr->next = cd->datareferences;
398 cd->datareferences = dr;
402 static void dseg_addlinenumbertablesize(codegendata *cd)
404 #if defined (__ALPHA__) || defined (__X86_64__)
405 dseg_adds4(cd, 0); /*PADDING*/
407 cd->linenumbertablesizepos = dseg_addaddress(cd, NULL); /*it could be considered to use adds4 here, to avoid 1 double word padding on ALPHA */
409 cd->linenumbertablestartpos = dseg_addaddress(cd, NULL);
410 #if defined(__ALPHA__) || defined (__X86_64__)
411 dseg_adds4(cd, 0); /*PADDING*/
416 static void dseg_addlinenumber(codegendata *cd, u2 linenumber, u1 *ptr)
420 lr = DNEW(linenumberref);
421 lr->linenumber = linenumber;
423 lr->targetmpc = (ptr - cd->mcodebase);
424 lr->next = cd->linenumberreferences;
425 cd->linenumberreferences = lr;
429 /* we need this function externally on i386 and x86_64, but keep the call fast
432 #if defined(__I386__) || defined(__X86_64__)
433 void codegen_addreference(codegendata *cd, basicblock *target, void *branchptr)
435 static void codegen_addreference(codegendata *cd, basicblock *target, void *branchptr)
440 branchpos = (u1 *) branchptr - cd->mcodebase;
442 /* Check if the target basicblock has already a start pc, so the jump is */
443 /* backward and we can resolve it immediately. */
445 if (target->mpc >= 0) {
446 gen_resolvebranch((u1 *) cd->mcodebase + branchpos,
451 branchref *br = DNEW(branchref);
453 br->branchpos = branchpos;
454 br->next = target->branchrefs;
455 target->branchrefs = br;
460 static void codegen_addxboundrefs(codegendata *cd, void *branchptr, s4 reg)
465 branchpos = (u1 *) branchptr - cd->mcodebase;
467 br = DNEW(branchref);
468 br->branchpos = branchpos;
470 br->next = cd->xboundrefs;
475 static void codegen_addxcheckarefs(codegendata *cd, void *branchptr)
480 branchpos = (u1 *) branchptr - cd->mcodebase;
482 br = DNEW(branchref);
483 br->branchpos = branchpos;
484 br->next = cd->xcheckarefs;
485 cd->xcheckarefs = br;
489 static void codegen_addxnullrefs(codegendata *cd, void *branchptr)
494 branchpos = (u1 *) branchptr - cd->mcodebase;
496 br = DNEW(branchref);
497 br->branchpos = branchpos;
498 br->next = cd->xnullrefs;
503 static void codegen_addxcastrefs(codegendata *cd, void *branchptr)
508 branchpos = (u1 *) branchptr - cd->mcodebase;
510 br = DNEW(branchref);
511 br->branchpos = branchpos;
512 br->next = cd->xcastrefs;
517 static void codegen_addxexceptionrefs(codegendata *cd, void *branchptr)
522 branchpos = (u1 *) branchptr - cd->mcodebase;
524 br = DNEW(branchref);
525 br->branchpos = branchpos;
526 br->next = cd->xexceptionrefs;
527 cd->xexceptionrefs = br;
531 #if defined(__I386__) || defined(__X86_64__)
532 static void codegen_addxdivrefs(codegendata *cd, void *branchptr)
537 branchpos = (u1 *) branchptr - cd->mcodebase;
539 br = DNEW(branchref);
540 br->branchpos = branchpos;
541 br->next = cd->xdivrefs;
547 static void codegen_addpatchref(codegendata *cd,
555 branchpos = (u1 *) branchptr - cd->mcodebase;
558 pr->branchpos = branchpos;
559 pr->patcher = patcher;
561 pr->next = cd->patchrefs;
566 static void codegen_createlinenumbertable(codegendata *cd)
568 #if defined(__I386__) || defined(__ALPHA__) || defined(__X86_64__)
571 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
572 lr->tablepos = dseg_addaddress(cd, NULL);
574 if (cd->linenumbertab == 0)
575 cd->linenumbertab = lr->tablepos;
577 dseg_addaddress(cd, lr->linenumber);
583 #if defined(__I386__) || defined(__X86_64__)
584 static int methodtree_comparator(const void *pc, const void *element, void *param)
586 methodtree_element *mte;
587 methodtree_element *mtepc;
589 mte = (methodtree_element *) element;
590 mtepc = (methodtree_element *) pc;
592 /* compare both startpc and endpc of pc, even if they have the same value,
593 otherwise the avl_probe sometimes thinks the element is already in the
595 if ((long) mte->startpc <= (long) mtepc->startpc &&
596 (long) mtepc->startpc <= (long) mte->endpc &&
597 (long) mte->startpc <= (long) mtepc->endpc &&
598 (long) mtepc->endpc <= (long) mte->endpc) {
601 } else if ((long) mtepc->startpc < (long) mte->startpc) {
610 void codegen_insertmethod(functionptr startpc, functionptr endpc)
612 methodtree_element *mte;
614 #if defined(USE_THREADS)
615 #if defined(NATIVE_THREADS)
620 mte = NEW(methodtree_element);
621 mte->startpc = startpc;
624 if (avl_insert(methodtree, mte)) {
625 #if defined(USE_THREADS)
626 #if defined(NATIVE_THREADS)
630 throw_cacao_exception_exit(string_java_lang_InternalError,
634 #if defined(USE_THREADS)
635 #if defined(NATIVE_THREADS)
642 functionptr codegen_findmethod(functionptr pc)
644 methodtree_element *mtepc;
645 methodtree_element *mte;
647 #if defined(USE_THREADS)
648 #if defined(NATIVE_THREADS)
653 mtepc = NEW(methodtree_element);
657 mte = avl_find(methodtree, mtepc);
659 FREE(mtepc, methodtree_element);
662 #if defined(USE_THREADS)
663 #if defined(NATIVE_THREADS)
670 fprintf(stderr,"backtrace:");
671 backtrace_symbols_fd(bt,5,2);
675 throw_cacao_exception_exit(string_java_lang_InternalError,
676 "Cannot find Java function at %p", pc);
679 #if defined(USE_THREADS)
680 #if defined(NATIVE_THREADS)
689 #if defined(__ALPHA__)
690 /*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,
691 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)*/
692 void *codegen_findmethod(void *returnAdress)
697 d=*((s4*)returnAdress);
700 dataseg=returnAdress+d;
701 d=*(((s4*)returnAdress)+1);
705 d=*(((s4*)returnAdress)+1);
711 ldl t0,0(ra) /* load instruction LDA PV,xxx(RA) */
713 sra t0,48,t0 /* isolate offset */
714 addq t0,ra,pv /* compute update address */
715 ldl t0,4(ra) /* load instruction LDAH PV,xxx(PV) */
716 srl t0,16,t0 /* isolate instruction code */
717 lda t0,-0x177b(t0) /* test for LDAH */
719 ldl t0,4(ra) /* load instruction LDAH PV,xxx(RA) */
720 sll t0,16,t0 /* compute high offset */
721 addl t0,0,t0 /* sign extend high offset */
722 addq t0,pv,pv /* compute update address */
730 static void codegen_finish(methodinfo *m, codegendata *cd, s4 mcodelen)
737 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
738 extralen = sizeof(threadcritnode) * cd->threadcritcount;
743 #if defined(STATISTICS)
745 count_code_len += mcodelen;
746 count_data_len += cd->dseglen;
750 cd->dseglen = ALIGN(cd->dseglen, MAX_ALIGN);
751 alignedlen = ALIGN(mcodelen, MAX_ALIGN) + cd->dseglen;
753 m->mcodelength = mcodelen + cd->dseglen;
754 m->mcode = (functionptr) (ptrint) CNEW(u1, alignedlen + extralen);
756 MCOPY((void *) m->mcode, cd->dsegtop - cd->dseglen, u1, cd->dseglen);
757 MCOPY((void *) ((ptrint) m->mcode + cd->dseglen), cd->mcodebase, u1, mcodelen);
759 m->entrypoint = epoint = (functionptr) ((ptrint) m->mcode + cd->dseglen);
761 /* jump table resolving */
763 jr = cd->jumpreferences;
765 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
766 (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
770 #if defined(__I386__) || defined(__ALPHA__) || defined(__X86_64__)
771 /* line number table resolving */
776 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
778 *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) =
779 (functionptr) ((ptrint) epoint + (ptrint) lr->targetmpc);
782 *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
783 (functionptr) ((ptrint) epoint + cd->linenumbertab);
785 *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
789 #if defined(__I386__) || defined(__X86_64__)
790 /* add method into methodtree to find the entrypoint */
792 codegen_insertmethod(m->entrypoint,
793 (functionptr) ((ptrint) m->entrypoint + mcodelen));
796 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__)
800 /* data segment references resolving */
802 dr = cd->datareferences;
804 *((functionptr *) ((ptrint) epoint + (ptrint) dr->pos - POINTERSIZE)) = epoint;
810 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
812 threadcritnode *n = (threadcritnode *) ((ptrint) m->mcode + alignedlen);
814 threadcritnodetemp *nt = cd->threadcrit;
816 for (i = 0; i < cd->threadcritcount; i++) {
817 n->mcodebegin = (u1 *) (ptrint) m->mcode + nt->mcodebegin;
818 n->mcodeend = (u1 *) (ptrint) m->mcode + nt->mcodeend;
819 n->mcoderestart = (u1 *) (ptrint) m->mcode + nt->mcoderestart;
820 thread_registercritical(n);
829 void dseg_display(methodinfo *m, codegendata *cd)
834 s4ptr = (s4 *) (ptrint) m->mcode;
836 printf(" --- dump of datasegment\n");
837 for (i = cd->dseglen; i > 0 ; i -= 4) {
838 #if defined(__I386__) || defined(__POWERPC__)
839 printf("0x%08x: -%6x (%6d): %8x\n",
840 (ptrint) s4ptr, i, i, (s4) *s4ptr);
842 printf("0x%016lx: -%6x (%6d): %8x\n",
843 (ptrint) s4ptr, i, i, (s4) *s4ptr);
848 printf(" --- begin of data segment: %p\n", (void *) s4ptr);
853 This function determines a register, to which the result of an operation
854 should go, when it is ultimatively intended to store the result in
856 If v is assigned to an actual register, this register will be returned.
857 Otherwise (when v is spilled) this function returns tempregnum.
858 If not already done, regoff and flags are set in the stack location.
861 static int reg_of_var(registerdata *rd, stackptr v, int tempregnum)
865 switch (v->varkind) {
867 if (!(v->flags & INMEMORY))
872 var = &(rd->interfaces[v->varnum][v->type]);
873 v->regoff = var->regoff;
874 if (!(var->flags & INMEMORY))
879 var = &(rd->locals[v->varnum][v->type]);
880 v->regoff = var->regoff;
881 if (!(var->flags & INMEMORY))
886 if (!(v->flags & INMEMORY))
894 v->flags |= INMEMORY;
899 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
900 static void codegen_threadcritrestart(codegendata *cd, int offset)
902 cd->threadcritcurrent.mcoderestart = offset;
906 static void codegen_threadcritstart(codegendata *cd, int offset)
908 cd->threadcritcurrent.mcodebegin = offset;
912 static void codegen_threadcritstop(codegendata *cd, int offset)
914 cd->threadcritcurrent.next = cd->threadcrit;
915 cd->threadcritcurrent.mcodeend = offset;
916 cd->threadcrit = DNEW(threadcritnodetemp);
917 *(cd->threadcrit) = cd->threadcritcurrent;
918 cd->threadcritcount++;
923 #ifndef STATIC_CLASSPATH
924 static size_t codegen_overloadPartLen(utf *desc) {
925 char *utf_ptr=desc->text;
928 while ((c=utf_nextu2(&utf_ptr))!=')') {
945 while ( (c=utf_nextu2(&utf_ptr)) != ';')
952 log_text("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++)='_';
996 log_text("invalid method descriptor");
1004 static void codegen_resolve_native(methodinfo *m,void **insertionPoint,void *jmpTarget,void **jmpPatchTarget) {
1005 char *nativeName, *nativeNameEscape;
1011 #if defined(USE_THREADS)
1012 builtin_monitorenter((java_objectheader*) m);
1015 #if defined(__X86_64__)
1016 if ((*((s4*)jmpPatchTarget))==((s4)jmpTarget)) {
1018 if ((*jmpPatchTarget)==jmpTarget) {
1021 #if defined(USE_THREADS)
1022 builtin_monitorexit((java_objectheader*) m);
1027 /*log_text("trying to resolve a native method");
1028 utf_display(m->class->name);
1029 utf_display(m->name);*/
1031 lib=dlopen(0,RTLD_NOW | RTLD_GLOBAL); /* open the application execution image */
1032 if (lib) { /* it did work -> good, otherwise fail with error*/
1034 /*generate the name of the native function in the form Java_package1_package2...._classname_methodname*/
1035 nativeLen=/*Java_*/5+strlen(m->class->name->text)+/*_*/1+strlen(m->name->text)+/*\0*/1;
1036 nativeName=MNEW(char,nativeLen);
1037 sprintf(nativeName,"Java_%s/%s",m->class->name->text,m->name->text);
1039 while (i<nativeLen) {
1040 if (nativeName[i]=='_') { /* escape underscore */
1041 nativeNameEscape = MNEW(char,nativeLen+1);
1042 memcpy(nativeNameEscape,nativeName,i+1);
1043 nativeNameEscape[i+1] = '1'; /* escape sequence for _ is _1 */
1044 memcpy(&nativeNameEscape[i+2],&nativeName[i+1],nativeLen-i-1);
1045 MFREE(nativeName,char,nativeLen);
1048 nativeNameEscape[nativeLen-1]=0;
1049 nativeName=nativeNameEscape;
1051 if (nativeName[i]=='/') nativeName[i]='_';
1055 /*printf("\nnativename: %s\n",nativeName);*/
1057 /*try to find the symbal fo the function */
1058 sym=dlsym(lib,nativeName);
1060 ok=1; /* it worked, everything fine */
1061 /*log_text("resolved");*/
1062 /*printf("strlen %d, nativeLen %d\n",strlen(nativeName),nativeLen);*/
1063 MFREE(nativeName,char,nativeLen);
1064 } else { /* we didn't find the symbol yet, try to resolve an overlaoded function (having the types in it's name*/
1065 size_t overloadedNativeLen=nativeLen+codegen_overloadPartLen(m->descriptor);
1066 char *overloadedNative=MNEW(char,overloadedNativeLen);
1067 sprintf(overloadedNative,"%s",nativeName);
1068 MFREE(nativeName,char,nativeLen);
1069 codegen_fillInOverloadPart(overloadedNative,m->descriptor);
1070 /*log_text("symbol not found,trying harder (overloaded member ?)");*/
1071 sym=dlsym(lib,overloadedNative);
1073 MFREE(overloadedNative,char,overloadedNativeLen);
1074 ok=1; /* we eventually found the native function -> everything ok*/
1075 /*log_text("resolved");*/
1077 /* we failed to find the native function within the execution image (app + loaded libraries) -> will cause an exit*/
1078 dolog("\nnative function not found: %s",overloadedNative);
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;
1092 #if defined(USE_THREADS)
1093 builtin_monitorexit((java_objectheader *) m );
1099 } else log_text("library not found");
1101 /* There was an error, either the app image could not be opened or the native does not exist in the application and the
1102 loaded libraries. Show an additional error and exit the vm*/
1106 slen=2+strlen(m->class->name->text)+strlen(m->name->text)+strlen(m->descriptor->text);
1107 info=(char*)MNEW(char,slen);
1108 sprintf(info,"%s.%s%s",m->class->name->text,m->name->text,m->descriptor->text);
1110 #if defined(USE_THREADS)
1111 builtin_monitorexit((java_objectheader *) m );
1114 throw_cacao_exception_exit(string_java_lang_LinkageError,
1123 * These are local overrides for various environment variables in Emacs.
1124 * Please do not remove this and leave it at the end of the file, where
1125 * Emacs will automagically detect them.
1126 * ---------------------------------------------------------------------
1129 * indent-tabs-mode: t