dynamic native library loading, some inlining changes
[cacao.git] / src / vm / jit / codegen.inc
1 /* jit/codegen.inc - architecture independent code generator
2
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,
7    J. Wenninger
8
9    This file is part of CACAO.
10
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.
15
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.
20
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
24    02111-1307, USA.
25
26    Contact: cacao@complang.tuwien.ac.at
27
28    Authors: Reinhard Grafl
29             Andreas  Krall
30
31    Changes: Michael Gschwind
32             Christian Thalinger
33
34    All functions assume the following code area / data area layout:
35
36    +-----------+
37    |           |
38    | code area | code area grows to higher addresses
39    |           |
40    +-----------+ <-- start of procedure
41    |           |
42    | data area | data area grows to lower addresses
43    |           |
44    +-----------+
45
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).    
50
51    $Id: codegen.inc 1429 2004-11-02 08:58:26Z jowenn $
52
53 */
54
55
56 #include <string.h>
57 #include "exceptions.h"
58 #include "native.h"
59 #include "options.h"
60 #include "statistics.h"
61 #include "jit/codegen.inc.h"
62 #include "toolbox/memory.h"
63 #include "toolbox/logging.h"
64 #include "toolbox/avl.h"
65 #include "threads/thread.h"
66 #ifndef STATIC_CLASSPATH
67 #include <dlfcn.h>
68 #endif
69
70 /* in this tree we store all method addresses */
71
72 #if defined(__I386__) || defined(__X86_64__)
73 static struct avl_table *methodtree = NULL;
74 static int methodtree_comparator(const void *pc, const void *element,
75                                                                  void *param);
76 #endif
77
78
79 /* codegen_init ****************************************************************
80
81    TODO
82
83 *******************************************************************************/
84
85 void codegen_init()
86 {
87 #if defined(__I386__) || defined(__X86_64__)
88         /* this tree is global, not method specific */
89         if (!methodtree) {
90                 methodtree_element *mte;
91
92                 methodtree = avl_create(methodtree_comparator, NULL, NULL);
93
94                 mte = NEW(methodtree_element);
95
96                 mte->startpc = asm_calljavafunction;
97                 mte->endpc = asm_calljavafunction2 - 1;
98
99                 avl_insert(methodtree, mte);
100
101                 mte = NEW(methodtree_element);
102
103                 mte->startpc = asm_calljavafunction2;
104                 mte->endpc = asm_call_jit_compiler - 1;
105
106                 avl_insert(methodtree, mte);
107         }
108 #endif
109 }
110
111
112 /* codegen_setup **************************************************************
113
114    allocates and initialises code area, data area and references
115
116 *******************************************************************************/
117
118 void codegen_setup(methodinfo *m, t_inlining_globals * e)
119 {
120         codegendata *cd;
121
122         m->codegendata = NEW(codegendata);
123
124         /* keep code size smaller */
125         cd = m->codegendata;
126
127         cd->mcodebase = MNEW(u1, MCODEINITSIZE);
128         cd->mcodesize = MCODEINITSIZE;
129         
130         cd->dsegtop = MNEW(u1, DSEGINITSIZE);
131         cd->dsegsize = DSEGINITSIZE;
132         cd->dsegtop += cd->dsegsize;
133         cd->dseglen = 0;
134
135         cd->jumpreferences = NULL;
136         cd->datareferences = NULL;
137         cd->xboundrefs = NULL;
138         cd->xcheckarefs = NULL;
139         cd->xnullrefs = NULL;
140         cd->xcastrefs = NULL;
141         cd->xdivrefs = NULL;
142         cd->xexceptionrefs = NULL;
143
144         cd->linenumberreferences = NULL;
145         cd->linenumbertablesizepos = 0;
146         cd->linenumbertablestartpos = 0;
147         cd->linenumbertab = 0;
148         
149         cd->method=m;
150         cd->exceptiontable=0;
151         cd->exceptiontablelength=0;
152         if (useinlining && e) {
153                 if (e->cumextablelength>0) {
154                         cd->exceptiontablelength=e->cumextablelength;
155                         cd->exceptiontable  = MNEW(exceptiontable, e->cumextablelength + 1);
156                 }
157         } else if (e && (e->method->exceptiontablelength >0)) {
158                         cd->exceptiontablelength=m->exceptiontablelength;
159                         cd->exceptiontable  = MNEW(exceptiontable, m->exceptiontablelength + 1);
160         }
161         if (e) {
162           cd->maxstack=e->cummaxstack;
163           cd->maxlocals=e->cumlocals;
164         } else {
165           cd->maxstack=m->maxstack;
166           cd->maxlocals=m->maxlocals;
167         }
168 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
169         cd->threadcritcurrent.next = NULL;
170         cd->threadcritcount = 0;
171 #endif
172 }
173
174
175 /* codegen_close releases temporary code and data area                        */
176
177 void codegen_close(methodinfo *m)
178 {
179         codegendata *cd;
180
181         cd = m->codegendata;
182
183         if (cd) {
184                 if (cd->exceptiontablelength) {
185                         cd->exceptiontablelength=m->exceptiontablelength;
186                         MFREE(cd->exceptiontable, exceptiontable, cd->exceptiontablelength + 1);
187                         cd->exceptiontable=0;
188                         cd->exceptiontablelength=0;
189                 }
190                 if (cd->mcodebase) {
191                         MFREE(cd->mcodebase, u1, cd->mcodesize);
192                         cd->mcodebase = NULL;
193                 }
194
195                 if (cd->dsegtop) {
196                         MFREE(cd->dsegtop - cd->dsegsize, u1, cd->dsegsize);
197                         cd->dsegtop = NULL;
198                 }
199
200                 FREE(m->codegendata, codegendata);
201                 m->codegendata = NULL;
202         }
203 }
204
205
206 /* codegen_increase doubles code area                                         */
207
208 static s4 *codegen_increase(methodinfo *m, u1 *codeptr)
209 {
210         codegendata *cd;
211         long len;
212
213         cd = m->codegendata;
214
215         len = codeptr - cd->mcodebase;
216         cd->mcodebase = MREALLOC(cd->mcodebase,
217                                                          u1,
218                                                          cd->mcodesize,
219                                                          cd->mcodesize * 2);
220         cd->mcodesize *= 2;
221         cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
222
223         return (s4 *) (cd->mcodebase + len);
224 }
225
226
227 /* desg_increase doubles data area                                            */
228
229 static void dseg_increase(methodinfo *m)
230 {
231         codegendata *cd;
232         u1 *newstorage;
233
234         cd = m->codegendata;
235
236         newstorage = MNEW(u1, cd->dsegsize * 2);
237
238         memcpy(newstorage + cd->dsegsize, cd->dsegtop - cd->dsegsize, cd->dsegsize);
239         MFREE(cd->dsegtop - cd->dsegsize, u1, cd->dsegsize);
240
241         cd->dsegtop = newstorage;
242         cd->dsegsize *= 2;
243         cd->dsegtop += cd->dsegsize;
244 }
245
246
247 static s4 dseg_adds4_increase(methodinfo *m, s4 value)
248 {
249         codegendata *cd;
250
251         cd = m->codegendata;
252
253         dseg_increase(m);
254
255         *((s4 *) (cd->dsegtop - cd->dseglen)) = value;
256
257         return -(cd->dseglen);
258 }
259
260
261 static s4 dseg_adds4(methodinfo *m, s4 value)
262 {
263         codegendata *cd;
264         s4 *dataptr;
265
266         cd = m->codegendata;
267
268         cd->dseglen += 4;
269         dataptr = (s4 *) (cd->dsegtop - cd->dseglen);
270
271         if (cd->dseglen > cd->dsegsize)
272                 return dseg_adds4_increase(m, value);
273
274         *dataptr = value;
275
276         return -(cd->dseglen);
277 }
278
279
280 #if !defined(__I386__)
281 static s4 dseg_adds8_increase(methodinfo *m, s8 value)
282 {
283         codegendata *cd;
284
285         cd = m->codegendata;
286
287         dseg_increase(m);
288
289         *((s8 *) (cd->dsegtop - cd->dseglen)) = value;
290
291         return -(cd->dseglen);
292 }
293
294
295 static s4 dseg_adds8(methodinfo *m, s8 value)
296 {
297         codegendata *cd;
298         s8 *dataptr;
299
300         cd = m->codegendata;
301
302         cd->dseglen = ALIGN(cd->dseglen + 8, 8);
303         dataptr = (s8 *) (cd->dsegtop - cd->dseglen);
304
305         if (cd->dseglen > cd->dsegsize)
306                 return dseg_adds8_increase(m, value);
307
308         *dataptr = value;
309
310         return -(cd->dseglen);
311 }
312 #endif
313
314
315 static s4 dseg_addfloat_increase(methodinfo *m, float value)
316 {
317         codegendata *cd;
318
319         cd = m->codegendata;
320
321         dseg_increase(m);
322
323         *((float *) (cd->dsegtop - cd->dseglen)) = value;
324
325         return -(cd->dseglen);
326 }
327
328
329 static s4 dseg_addfloat(methodinfo *m, float value)
330 {
331         codegendata *cd;
332         float *dataptr;
333
334         cd = m->codegendata;
335
336         cd->dseglen += 4;
337         dataptr = (float *) (cd->dsegtop - cd->dseglen);
338
339         if (cd->dseglen > cd->dsegsize)
340                 return dseg_addfloat_increase(m, value);
341
342         *dataptr = value;
343
344         return -(cd->dseglen);
345 }
346
347
348 static s4 dseg_adddouble_increase(methodinfo *m, double value)
349 {
350         codegendata *cd;
351
352         cd = m->codegendata;
353
354         dseg_increase(m);
355
356         *((double *) (cd->dsegtop - cd->dseglen)) = value;
357
358         return -(cd->dseglen);
359 }
360
361
362 static s4 dseg_adddouble(methodinfo *m, double value)
363 {
364         codegendata *cd;
365         double *dataptr;
366
367         cd = m->codegendata;
368
369         cd->dseglen = ALIGN(cd->dseglen + 8, 8);
370         dataptr = (double *) (cd->dsegtop - cd->dseglen);
371
372         if (cd->dseglen > cd->dsegsize)
373                 return dseg_adddouble_increase(m, value);
374
375         *dataptr = value;
376
377         return -(cd->dseglen);
378 }
379
380
381 static void dseg_addtarget(methodinfo *m, basicblock *target)
382 {
383         codegendata *cd;
384         jumpref *jr;
385
386         cd = m->codegendata;
387         
388         jr = DNEW(jumpref);
389         jr->tablepos = dseg_addaddress(m, NULL);
390         jr->target = target;
391         jr->next = cd->jumpreferences;
392         cd->jumpreferences = jr;
393 }
394
395
396 static void dseg_adddata(methodinfo *m, u1 *ptr)
397 {
398         codegendata *cd;
399         dataref *dr;
400
401         cd = m->codegendata;
402
403         dr = DNEW(dataref);
404         dr->pos = (u1 *) (ptr - cd->mcodebase);
405         dr->next = cd->datareferences;
406         cd->datareferences = dr;
407 }
408
409
410 static void dseg_addlinenumbertablesize(methodinfo *m)
411 {
412         codegendata *cd;
413
414         cd = m->codegendata;
415
416 #ifdef __ALPHA__
417         dseg_adds4(m, 0); /*PADDING*/
418 #endif
419         cd->linenumbertablesizepos = dseg_addaddress(m, NULL); /*it could be considered to use adds4 here, to avoid 1 double word padding on ALPHA */
420
421         cd->linenumbertablestartpos = dseg_addaddress(m, NULL);
422 #ifdef __ALPHA__
423         dseg_adds4(m, 0); /*PADDING*/
424 #endif
425 }
426
427
428 static void dseg_addlinenumber(methodinfo *m, u2 linenumber, u1 *ptr)
429 {
430         codegendata *cd;
431         linenumberref *lr;
432
433         cd = m->codegendata;
434
435         lr = DNEW(linenumberref);
436         lr->linenumber = linenumber;
437         lr->tablepos = 0;
438         lr->targetmpc = (ptr - cd->mcodebase);
439         lr->next = cd->linenumberreferences;
440         cd->linenumberreferences = lr;
441 }
442
443
444 /* we need this function externally on i386 and x86_64, but keep the call fast
445    on alpha... */
446
447 #if defined(__I386__) || defined(__X86_64__)
448 void codegen_addreference(methodinfo *m, basicblock *target, void *branchptr)
449 #else
450 static void codegen_addreference(methodinfo *m, basicblock *target, void *branchptr)
451 #endif
452 {
453         codegendata *cd;
454         s4 branchpos;
455
456         cd = m->codegendata;
457
458         branchpos = (u1 *) branchptr - cd->mcodebase;
459
460         if (target->mpc >= 0) {
461                 gen_resolvebranch((u1 *) cd->mcodebase + branchpos,
462                                                   branchpos,
463                                                   target->mpc);
464
465         } else {
466                 branchref *br = DNEW(branchref);
467
468                 br->branchpos = branchpos;
469                 br->next = target->branchrefs;
470                 target->branchrefs = br;
471         }
472 }
473
474
475 static void codegen_addxboundrefs(methodinfo *m, void *branchptr, s4 reg)
476 {
477         codegendata *cd;
478         s4 branchpos;
479         branchref *br;
480
481         cd = m->codegendata;
482
483         branchpos = (u1 *) branchptr - cd->mcodebase;
484
485         br = DNEW(branchref);
486         br->branchpos = branchpos;
487         br->reg = reg;
488         br->next = cd->xboundrefs;
489         cd->xboundrefs = br;
490 }
491
492
493 static void codegen_addxcheckarefs(methodinfo *m, void *branchptr)
494 {
495         codegendata *cd;
496         s4 branchpos;
497         branchref *br;
498
499         cd = m->codegendata;
500
501         branchpos = (u1 *) branchptr - cd->mcodebase;
502
503         br = DNEW(branchref);
504         br->branchpos = branchpos;
505         br->next = cd->xcheckarefs;
506         cd->xcheckarefs = br;
507 }
508
509
510 static void codegen_addxnullrefs(methodinfo *m, void *branchptr)
511 {
512         codegendata *cd;
513         s4 branchpos;
514         branchref *br;
515
516         cd = m->codegendata;
517
518         branchpos = (u1 *) branchptr - cd->mcodebase;
519
520         br = DNEW(branchref);
521         br->branchpos = branchpos;
522         br->next = cd->xnullrefs;
523         cd->xnullrefs = br;
524 }
525
526
527
528 static void codegen_addxcastrefs(methodinfo *m, void *branchptr)
529 {
530         codegendata *cd;
531         s4 branchpos;
532         branchref *br;
533
534         cd = m->codegendata;
535
536         branchpos = (u1 *) branchptr - cd->mcodebase;
537
538         br = DNEW(branchref);
539         br->branchpos = branchpos;
540         br->next = cd->xcastrefs;
541         cd->xcastrefs = br;
542 }
543
544
545 static void codegen_addxexceptionrefs(methodinfo *m, void *branchptr)
546 {
547         codegendata *cd;
548         s4 branchpos;
549         branchref *br;
550
551         cd = m->codegendata;
552
553         branchpos = (u1 *) branchptr - cd->mcodebase;
554
555         br = DNEW(branchref);
556         br->branchpos = branchpos;
557         br->next = cd->xexceptionrefs;
558         cd->xexceptionrefs = br;
559 }
560
561
562 #if defined(__I386__) || defined(__X86_64__)
563 static void codegen_addxdivrefs(methodinfo *m, void *branchptr)
564 {
565         codegendata *cd;
566         s4 branchpos;
567         branchref *br;
568
569         cd = m->codegendata;
570
571         branchpos = (u1 *) branchptr - cd->mcodebase;
572
573         br = DNEW(branchref);
574         br->branchpos = branchpos;
575         br->next = cd->xdivrefs;
576         cd->xdivrefs = br;
577 }
578 #endif
579
580
581 static void codegen_createlinenumbertable(methodinfo *m)
582 {
583 #ifdef __I386__
584         codegendata *cd;
585         linenumberref *lr;
586
587         cd = m->codegendata;
588
589         for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
590                 lr->tablepos = dseg_addaddress(m, NULL);
591
592                 if (cd->linenumbertab == 0)
593                         cd->linenumbertab = lr->tablepos;
594
595                 dseg_addaddress(m, lr->linenumber);
596         }
597 #endif
598 }
599
600
601 #if defined(__I386__) || defined(__X86_64__)
602 static int methodtree_comparator(const void *pc, const void *element, void *param)
603 {
604         methodtree_element *mte;
605         methodtree_element *mtepc;
606
607         mte = (methodtree_element *) element;
608         mtepc = (methodtree_element *) pc;
609
610         /* compare both startpc and endpc of pc, even if they have the same value,
611            otherwise the avl_probe sometimes thinks the element is already in the
612            tree */
613         if (mte->startpc <= mtepc->startpc && mtepc->startpc <= mte->endpc &&
614                 mte->startpc <= mtepc->endpc   && mtepc->endpc   <= mte->endpc) {
615                 return 0;
616
617         } else if (mtepc->startpc < mte->startpc) {
618                 return -1;
619
620         } else {
621                 return 1;
622         }
623 }
624
625
626 #if 0
627 void *codegen_findmethod1(void *pc)
628 {
629         void * retVal=findmethod(pc);
630         methodinfo **ma=(methodinfo**)retVal;
631         methodinfo *m=ma[-1];
632         if (m)
633                 if (m->name)
634                         utf_display(m->name);
635                 else 
636                         log_text("No Name");
637         else log_text("No methodinfo");
638         return retVal;
639 }
640 #endif
641
642
643 void codegen_insertmethod(void *startpc, void *endpc)
644 {
645         methodtree_element *mte;
646
647 #if defined(USE_THREADS)
648 #if defined(NATIVE_THREADS)
649         tables_lock();
650 #endif
651 #endif
652
653         mte = NEW(methodtree_element);
654         mte->startpc = startpc;
655         mte->endpc = endpc;
656
657         if (avl_insert(methodtree, mte)) {
658 #if defined(USE_THREADS)
659 #if defined(NATIVE_THREADS)
660                 tables_unlock();
661 #endif
662 #endif
663                 throw_cacao_exception_exit(string_java_lang_InternalError,
664                                                                    "duplicate entry");
665         }
666
667 #if defined(USE_THREADS)
668 #if defined(NATIVE_THREADS)
669         tables_unlock();
670 #endif
671 #endif
672 }
673
674
675 void *codegen_findmethod(void *pc)
676 {
677         methodtree_element *mtepc;
678         methodtree_element *mte;
679
680         mtepc = NEW(methodtree_element);
681         mtepc->startpc = pc;
682         mtepc->endpc = pc;
683
684         mte = avl_find(methodtree, mtepc);
685
686         FREE(mtepc, methodtree_element);
687
688         if (!mte)
689                 throw_cacao_exception_exit(string_java_lang_InternalError,
690                                                                    "cannot find function");
691
692         return mte->startpc;
693 }
694 #endif
695
696
697 static void codegen_finish(methodinfo *m, s4 mcodelen)
698 {
699         codegendata *cd;
700         jumpref *jr;
701         u1 *epoint;
702         s4 extralen = 0;
703         s4 alignedlen;
704
705         cd = m->codegendata;
706
707 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
708         extralen += sizeof(threadcritnode) * cd->threadcritcount;
709 #endif
710
711 #if defined(STATISTICS)
712         if (opt_stat) {
713                 count_code_len += mcodelen;
714                 count_data_len += cd->dseglen;
715         }
716 #endif
717
718         cd->dseglen = ALIGN(cd->dseglen, MAX_ALIGN);
719         alignedlen = ALIGN(mcodelen, MAX_ALIGN) + cd->dseglen;
720
721         m->mcodelength = mcodelen + cd->dseglen;
722         m->mcode = CNEW(u1, alignedlen + extralen);
723
724         memcpy(m->mcode, cd->dsegtop - cd->dseglen, cd->dseglen);
725         memcpy(m->mcode + cd->dseglen, cd->mcodebase, mcodelen);
726
727         m->entrypoint = epoint = (u1 *) (m->mcode + cd->dseglen);
728
729         /* jump table resolving */
730         jr = cd->jumpreferences;
731         while (jr != NULL) {
732             *((void**) (epoint + jr->tablepos)) = epoint + jr->target->mpc;
733             jr = jr->next;
734         }
735
736 #ifdef __I386__
737         /* line number table resolving */
738         {
739                 linenumberref *lr;
740 #if POINTERSIZE == 8
741                 s8 lrtlen = 0;
742 #else
743                 s4 lrtlen = 0;
744 #endif
745
746                 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
747                         lrtlen++;
748                         *((void**) (epoint + lr->tablepos)) = epoint + lr->targetmpc;
749                 }
750                 
751                 *((void**) (epoint + cd->linenumbertablestartpos)) =
752                         epoint + cd->linenumbertab;
753 #if POINTERSIZE == 8
754                 *((s8*) (epoint + cd->linenumbertablesizepos)) = lrtlen;
755 #else
756                 *((s4*) (epoint + cd->linenumbertablesizepos)) = lrtlen;
757 #endif
758         }
759 #endif
760
761 #if defined(__I386__) || defined(__X86_64__)
762         {
763                 dataref *dr;
764
765                 /* add method into methodtree to find the entrypoint */
766                 codegen_insertmethod(m->entrypoint, m->entrypoint + mcodelen);
767
768                 /* data segment references resolving */
769                 dr = cd->datareferences;
770                 while (dr != NULL) {
771                         *((void**) ((long) epoint + (long) dr->pos - POINTERSIZE)) = epoint;
772                         dr = dr->next;
773                 }
774         }
775 #endif
776
777 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
778         {
779                 threadcritnode *n = (threadcritnode *) (m->mcode + alignedlen);
780                 s4 i;
781                 threadcritnodetemp *nt = cd->threadcrit;
782
783                 for (i = 0; i < cd->threadcritcount; i++) {
784                         n->mcodebegin = m->mcode + nt->mcodebegin;
785                         n->mcodeend = m->mcode + nt->mcodeend;
786                         n->mcoderestart = m->mcode + nt->mcoderestart;
787                         thread_registercritical(n);
788                         n++;
789                         nt = nt->next;
790                 }
791         }
792 #endif
793 }
794
795
796 void dseg_display(methodinfo *m)
797 {
798         s4 *s4ptr;
799         s4 i;
800         
801         s4ptr = (s4 *) m->mcode;
802
803         printf("  --- dump of datasegment\n");
804         for (i = m->codegendata->dseglen; i > 0 ; i -= 4) {
805                 printf("-%6x: %8x\n", i, (s4) (*s4ptr++));
806         }
807         printf("  --- begin of data segment: %p\n", s4ptr);
808 }
809
810
811 #if !defined(__POWERPC__)
812 /* reg_of_var:
813     This function determines a register, to which the result of an operation
814     should go, when it is ultimatively intended to store the result in
815     pseudoregister v.
816     If v is assigned to an actual register, this register will be returned.
817     Otherwise (when v is spilled) this function returns tempregnum.
818     If not already done, regoff and flags are set in the stack location.
819 */        
820
821 static int reg_of_var(methodinfo *m, stackptr v, int tempregnum)
822 {
823         varinfo *var;
824
825         switch (v->varkind) {
826         case TEMPVAR:
827                 if (!(v->flags & INMEMORY))
828                         return(v->regoff);
829                 break;
830         case STACKVAR:
831                 var = &(m->registerdata->interfaces[v->varnum][v->type]);
832                 v->regoff = var->regoff;
833                 if (!(var->flags & INMEMORY))
834                         return(var->regoff);
835                 break;
836         case LOCALVAR:
837                 var = &(m->registerdata->locals[v->varnum][v->type]);
838                 v->regoff = var->regoff;
839                 if (!(var->flags & INMEMORY))
840                         return(var->regoff);
841                 break;
842         case ARGVAR:
843                 v->regoff = v->varnum;
844                 if (IS_FLT_DBL_TYPE(v->type)) {
845                         if (v->varnum < m->registerdata->fltreg_argnum) {
846                                 v->regoff = m->registerdata->argfltregs[v->varnum];
847                                 return(m->registerdata->argfltregs[v->varnum]);
848                         }
849                 }
850                 else
851                         if (v->varnum < m->registerdata->intreg_argnum) {
852                                 v->regoff = m->registerdata->argintregs[v->varnum];
853                                 return(m->registerdata->argintregs[v->varnum]);
854                         }
855                 v->regoff -= m->registerdata->intreg_argnum;
856                 break;
857         }
858         v->flags |= INMEMORY;
859         return tempregnum;
860 }
861 #endif
862
863
864 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
865 static void codegen_threadcritrestart(methodinfo *m, int offset)
866 {
867         m->codegendata->threadcritcurrent.mcoderestart = offset;
868 }
869
870 static void codegen_threadcritstart(methodinfo *m, int offset)
871 {
872         m->codegendata->threadcritcurrent.mcodebegin = offset;
873 }
874
875 static void codegen_threadcritstop(methodinfo *m, int offset)
876 {
877         codegendata *cd;
878
879         cd = m->codegendata;
880
881         cd->threadcritcurrent.next = cd->threadcrit;
882         cd->threadcritcurrent.mcodeend = offset;
883         cd->threadcrit = DNEW(threadcritnodetemp);
884         *(cd->threadcrit) = cd->threadcritcurrent;
885         cd->threadcritcount++;
886 }
887 #endif
888
889 #ifndef STATIC_CLASSPATH
890 static size_t codegen_overloadPartLen(utf *desc) {
891         char *utf_ptr=desc->text;
892         u2 c;
893         size_t len=2;
894         while ((c=utf_nextu2(&utf_ptr))!=')') {
895                 switch (c) {
896                         case 'I':
897                         case 'S':
898                         case 'B':
899                         case 'C':
900                         case 'Z':
901                         case 'J':
902                         case 'F':
903                         case 'D':
904                                 len ++;
905                                 break;
906                         case '[':
907                                 len = len+2;
908                                 break;
909                         case 'L':
910                                 len++;
911                                 while ( (c=utf_nextu2(&utf_ptr)) != ';')
912                                         len++;
913                                 len=len+2;
914                                 break;
915                         case '(':
916                                 break;
917                         default: panic ("invalid method descriptor");
918                 }
919         }
920         return len;
921
922 }
923
924 static void codegen_fillInOverloadPart(char *target,utf *desc) {
925         char *utf_ptr=desc->text;
926         u2 c;
927         char* insertpos=&target[strlen(target)];
928         *(insertpos++)='_';
929         *(insertpos++)='_';
930         while ((c=utf_nextu2(&utf_ptr))!=')') {
931                 switch (c) {
932                         case 'I':
933                         case 'S':
934                         case 'B':
935                         case 'C':
936                         case 'Z':
937                         case 'J':
938                         case 'F':
939                         case 'D':
940                                 *(insertpos++)=c;
941                                 break;
942                         case '[':
943                                 *(insertpos++)='_';
944                                 *(insertpos++)='3';
945                                 break;
946                         case 'L':
947                                 *(insertpos++)='L';
948                                 while ( (c=utf_nextu2(&utf_ptr)) != ';')
949                                         if ( ((c>='a') && (c<='z'))  ||
950                                                 ((c>='A') && (c<='Z')) ||
951                                                 ((c>='0') && (c<='9')) )
952                                                         *(insertpos++)=c;
953                                         else *(insertpos++)='_';
954                                 *(insertpos++)='_';
955                                 *(insertpos++)='2';
956                                 break;
957                         case '(':
958                                 break;
959                         default: panic ("invalid method descriptor");
960                 }
961         }
962         *insertpos='\0';
963
964 }
965
966 static void codegen_resolve_native(methodinfo *m,void **insertionPoint,void *jmpTarget,void **jmpPatchTarget) {
967   char *nativeName;
968   size_t nativeLen;
969   size_t i;
970
971   builtin_monitorenter((java_objectheader*) m);
972   if ((*jmpPatchTarget)==jmpTarget) {
973     builtin_monitorexit((java_objectheader*) m);
974     return;
975   }
976   log_text("trying to resolve a native method");
977   utf_display(m->class->name);
978   utf_display(m->name);
979   
980   void *lib=dlopen(0,RTLD_NOW | RTLD_GLOBAL);
981   if (lib) {
982     int ok=0;
983     /*generate the name of the native function in the form Java_package1_package2...._classname_methodname*/
984     nativeLen=/*Java_*/5+strlen(m->class->name->text)+/*_*/1+strlen(m->name->text)+/*\0*/1;
985     nativeName=MNEW(char,nativeLen);
986     sprintf(nativeName,"Java_%s_%s",m->class->name->text,m->name->text);
987     for (i=0;i<nativeLen;i++) {
988       if (nativeName[i]=='/') nativeName[i]='_';
989     } 
990
991
992     void *sym=dlsym(lib,nativeName);
993     if (sym) {
994       ok=1;
995       log_text("resolved");
996       MFREE(nativeName,char,nativeLen);
997     } else {
998       size_t overloadedNativeLen=nativeLen+codegen_overloadPartLen(m->descriptor);
999       char *overloadedNative=MNEW(char,overloadedNativeLen);
1000       sprintf(overloadedNative,"%s",nativeName);
1001       MFREE(nativeName,char,nativeLen);
1002       codegen_fillInOverloadPart(overloadedNative,m->descriptor);
1003       log_text("symbol not found,trying harder (overloaded member ?)");
1004       sym=dlsym(lib,overloadedNative);
1005       if (sym) {
1006         MFREE(overloadedNative,char,overloadedNativeLen);
1007         ok=1;
1008         log_text("resolved");
1009       } else { 
1010          MFREE(overloadedNative,char,overloadedNativeLen);
1011          log_text("It was not possible to find the native function implementation. Not even in overloading case");
1012       }
1013    }
1014     if (ok) {
1015       (*insertionPoint)=sym;
1016       (*jmpPatchTarget)=jmpTarget;
1017       builtin_monitorexit((java_objectheader *) m );
1018       return;
1019     }
1020
1021   } else log_text("library not found");
1022   
1023
1024   {
1025     char *info;
1026     size_t slen;
1027     slen=2+strlen(m->class->name->text)+strlen(m->name->text)+strlen(m->descriptor->text);
1028     info=(char*)MNEW(char,slen);
1029     sprintf(info,"%s.%s%s",m->class->name->text,m->name->text,m->descriptor->text);
1030     
1031     builtin_monitorexit((java_objectheader *) m );
1032     throw_cacao_exception_exit(string_java_lang_LinkageError,
1033                                                        info);
1034   }
1035   
1036 }
1037 #endif
1038
1039 /*
1040  * These are local overrides for various environment variables in Emacs.
1041  * Please do not remove this and leave it at the end of the file, where
1042  * Emacs will automagically detect them.
1043  * ---------------------------------------------------------------------
1044  * Local variables:
1045  * mode: c
1046  * indent-tabs-mode: t
1047  * c-basic-offset: 4
1048  * tab-width: 4
1049  * End:
1050  */