47999c1aa33f584b3678ea477e89072e117bdbc5
[cacao.git] / src / vm / jit / codegen-common.c
1 /* src/vm/jit/codegen-common.c - architecture independent code generator stuff
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
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.
14
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.
19
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., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    All functions assume the following code area / data area layout:
26
27    +-----------+
28    |           |
29    | code area | code area grows to higher addresses
30    |           |
31    +-----------+ <-- start of procedure
32    |           |
33    | data area | data area grows to lower addresses
34    |           |
35    +-----------+
36
37    The functions first write into a temporary code/data area allocated by
38    "codegen_init". "codegen_finish" copies the code and data area into permanent
39    memory. All functions writing values into the data area return the offset
40    relative the begin of the code area (start of procedure).    
41
42    $Id: codegen-common.c 7489 2007-03-08 17:12:56Z michi $
43
44 */
45
46
47 #include "config.h"
48
49 #include <assert.h>
50 #include <string.h>
51
52 #include "vm/types.h"
53
54 #if defined(ENABLE_JIT)
55 /* this is required PATCHER_CALL_SIZE */
56 # include "codegen.h"
57 #endif
58
59 #if defined(__ARM__)
60 /* this is required for REG_SPLIT */
61 # include "md-abi.h"
62 #endif
63
64 #include "mm/memory.h"
65
66 #include "toolbox/avl.h"
67 #include "toolbox/list.h"
68 #include "toolbox/logging.h"
69
70 #include "native/jni.h"
71 #include "native/native.h"
72
73 #if defined(ENABLE_THREADS)
74 # include "threads/native/threads.h"
75 #endif
76
77 #include "vm/exceptions.h"
78 #include "vm/stringlocal.h"
79
80 #include "vm/jit/abi.h"
81 #include "vm/jit/asmpart.h"
82 #include "vm/jit/codegen-common.h"
83
84 #if defined(ENABLE_DISASSEMBLER)
85 # include "vm/jit/disass.h"
86 #endif
87
88 #include "vm/jit/dseg.h"
89 #include "vm/jit/jit.h"
90 #include "vm/jit/md.h"
91 #include "vm/jit/replace.h"
92 #include "vm/jit/stacktrace.h"
93
94 #if defined(ENABLE_INTRP)
95 #include "vm/jit/intrp/intrp.h"
96 #endif
97
98 #include "vmcore/method.h"
99 #include "vmcore/options.h"
100
101 #if defined(ENABLE_STATISTICS)
102 # include "vmcore/statistics.h"
103 #endif
104
105
106 /* in this tree we store all method addresses *********************************/
107
108 static avl_tree *methodtree = NULL;
109 static s4 methodtree_comparator(const void *pc, const void *element);
110
111
112 /* codegen_init ****************************************************************
113
114    TODO
115
116 *******************************************************************************/
117
118 void codegen_init(void)
119 {
120         /* this tree is global, not method specific */
121
122         if (!methodtree) {
123 #if defined(ENABLE_JIT)
124                 methodtree_element *mte;
125 #endif
126
127                 methodtree = avl_create(&methodtree_comparator);
128
129 #if defined(ENABLE_JIT)
130                 /* insert asm_vm_call_method */
131
132                 mte = NEW(methodtree_element);
133
134                 mte->startpc = (u1 *) (ptrint) asm_vm_call_method;
135                 mte->endpc   = (u1 *) ((ptrint) asm_call_jit_compiler - 1);
136
137                 avl_insert(methodtree, mte);
138 #endif /* defined(ENABLE_JIT) */
139         }
140 }
141
142
143 /* codegen_setup ***************************************************************
144
145    Allocates and initialises code area, data area and references.
146
147 *******************************************************************************/
148
149 void codegen_setup(jitdata *jd)
150 {
151         methodinfo  *m;
152         codegendata *cd;
153
154         /* get required compiler data */
155
156         m  = jd->m;
157         cd = jd->cd;
158
159         cd->mcodebase = DMNEW(u1, MCODEINITSIZE);
160         cd->mcodeend  = cd->mcodebase + MCODEINITSIZE;
161         cd->mcodesize = MCODEINITSIZE;
162
163         /* initialize mcode variables */
164
165         cd->mcodeptr     = cd->mcodebase;
166         cd->lastmcodeptr = cd->mcodebase;
167
168 #if defined(ENABLE_INTRP)
169         /* native dynamic superinstructions variables */
170
171         if (opt_intrp) {
172                 cd->ncodebase = DMNEW(u1, NCODEINITSIZE);
173                 cd->ncodesize = NCODEINITSIZE;
174
175                 /* initialize ncode variables */
176         
177                 cd->ncodeptr = cd->ncodebase;
178
179                 cd->lastinstwithoutdispatch = ~0; /* no inst without dispatch */
180                 cd->superstarts = NULL;
181         }
182 #endif
183
184         cd->dseg           = NULL;
185         cd->dseglen        = 0;
186
187         cd->jumpreferences = NULL;
188
189 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
190         cd->datareferences = NULL;
191 #endif
192
193         cd->exceptionrefs  = NULL;
194 /*      cd->patchrefs      = list_create_dump(OFFSET(patchref, linkage)); */
195         cd->patchrefs      = NULL;
196
197         cd->linenumberreferences = NULL;
198         cd->linenumbertablesizepos = 0;
199         cd->linenumbertablestartpos = 0;
200         cd->linenumbertab = 0;
201         
202         cd->method = m;
203
204         cd->maxstack = m->maxstack;
205
206 #if defined(ENABLE_THREADS)
207         cd->threadcritcurrent.next = NULL;
208         cd->threadcritcount = 0;
209 #endif
210 }
211
212
213 /* codegen_close ***************************************************************
214
215    TODO
216
217 *******************************************************************************/
218
219 void codegen_close(void)
220 {
221         /* TODO: release avl tree on i386 and x86_64 */
222 }
223
224
225 /* codegen_increase ************************************************************
226
227    Doubles code area.
228
229 *******************************************************************************/
230
231 void codegen_increase(codegendata *cd)
232 {
233         u1 *oldmcodebase;
234
235         /* save old mcodebase pointer */
236
237         oldmcodebase = cd->mcodebase;
238
239         /* reallocate to new, doubled memory */
240
241         cd->mcodebase = DMREALLOC(cd->mcodebase,
242                                                           u1,
243                                                           cd->mcodesize,
244                                                           cd->mcodesize * 2);
245         cd->mcodesize *= 2;
246         cd->mcodeend   = cd->mcodebase + cd->mcodesize;
247
248         /* set new mcodeptr */
249
250         cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
251
252 #if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(ENABLE_INTRP)
253         /* adjust the pointer to the last patcher position */
254
255         if (cd->lastmcodeptr != NULL)
256                 cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
257 #endif
258 }
259
260
261 /* codegen_ncode_increase ******************************************************
262
263    Doubles code area.
264
265 *******************************************************************************/
266
267 #if defined(ENABLE_INTRP)
268 u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
269 {
270         u1 *oldncodebase;
271
272         /* save old ncodebase pointer */
273
274         oldncodebase = cd->ncodebase;
275
276         /* reallocate to new, doubled memory */
277
278         cd->ncodebase = DMREALLOC(cd->ncodebase,
279                                                           u1,
280                                                           cd->ncodesize,
281                                                           cd->ncodesize * 2);
282         cd->ncodesize *= 2;
283
284         /* return the new ncodeptr */
285
286         return (cd->ncodebase + (ncodeptr - oldncodebase));
287 }
288 #endif
289
290
291 /* codegen_add_branch_ref ******************************************************
292
293    Prepends an branch to the list.
294
295 *******************************************************************************/
296
297 void codegen_add_branch_ref(codegendata *cd, basicblock *target)
298 {
299         s4 branchmpc;
300
301         /* calculate the mpc of the branch instruction */
302
303         branchmpc = cd->mcodeptr - cd->mcodebase;
304
305 #if defined(ENABLE_JIT)
306         /* Check if the target basicblock has already a start pc, so the
307            jump is backward and we can resolve it immediately. */
308
309         if ((target->mpc >= 0)
310 # if defined(ENABLE_INTRP)
311                 /* The interpreter uses absolute branches, so we do branch
312                    resolving after the code and data segment move. */
313
314                 && !opt_intrp
315 # endif
316                 )
317         {
318                 md_codegen_patch_branch(cd, branchmpc, target->mpc);
319         }
320         else
321 #endif
322         {
323                 branchref *br = DNEW(branchref);
324
325                 br->branchpos = branchmpc;
326                 br->next      = target->branchrefs;
327
328                 target->branchrefs = br;
329         }
330 }
331
332
333 /* codegen_resolve_branchrefs **************************************************
334
335    Resolves and patches the branch references of a given basic block.
336
337 *******************************************************************************/
338
339 void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
340 {
341         branchref *br;
342         s4         branchmpc;
343         s4         targetmpc;
344
345         /* set target */
346
347         targetmpc = bptr->mpc;
348
349         for (br = bptr->branchrefs; br != NULL; br = br->next) {
350                 branchmpc = br->branchpos;
351
352                 md_codegen_patch_branch(cd, branchmpc, targetmpc);
353         }
354 }
355
356
357 /* codegen_add_exception_ref ***************************************************
358
359    Prepends an exception branch to the list.
360
361 *******************************************************************************/
362
363 static void codegen_add_exception_ref(codegendata *cd, s4 reg,
364                                                                           functionptr function)
365 {
366         s4            branchmpc;
367         exceptionref *er;
368
369         branchmpc = cd->mcodeptr - cd->mcodebase;
370
371         er = DNEW(exceptionref);
372
373         er->branchpos = branchmpc;
374         er->reg       = reg;
375         er->function  = function;
376
377         er->next      = cd->exceptionrefs;
378
379         cd->exceptionrefs = er;
380 }
381
382
383 /* codegen_add_arithmeticexception_ref *****************************************
384
385    Adds an ArithmeticException branch to the list.
386
387 *******************************************************************************/
388
389 void codegen_add_arithmeticexception_ref(codegendata *cd)
390 {
391         codegen_add_exception_ref(cd, -1, STACKTRACE_inline_arithmeticexception);
392 }
393
394
395 /* codegen_add_arrayindexoutofboundsexception_ref ******************************
396
397    Adds an ArrayIndexOutOfBoundsException branch to the list.
398
399 *******************************************************************************/
400
401 void codegen_add_arrayindexoutofboundsexception_ref(codegendata *cd, s4 reg)
402 {
403         codegen_add_exception_ref(cd, reg,
404                                                           STACKTRACE_inline_arrayindexoutofboundsexception);
405 }
406
407
408 /* codegen_add_arraystoreexception_ref *****************************************
409
410    Adds an ArrayStoreException branch to the list.
411
412 *******************************************************************************/
413
414 void codegen_add_arraystoreexception_ref(codegendata *cd)
415 {
416         codegen_add_exception_ref(cd, -1, STACKTRACE_inline_arraystoreexception);
417 }
418
419
420 /* codegen_add_classcastexception_ref ******************************************
421
422    Adds an ClassCastException branch to the list.
423
424 *******************************************************************************/
425
426 void codegen_add_classcastexception_ref(codegendata *cd, s4 reg)
427 {
428         codegen_add_exception_ref(cd, reg, STACKTRACE_inline_classcastexception);
429 }
430
431
432 /* codegen_add_nullpointerexception_ref ****************************************
433
434    Adds an NullPointerException branch to the list.
435
436 *******************************************************************************/
437
438 void codegen_add_nullpointerexception_ref(codegendata *cd)
439 {
440         codegen_add_exception_ref(cd, -1, STACKTRACE_inline_nullpointerexception);
441 }
442
443
444 /* codegen_add_fillinstacktrace_ref ********************************************
445
446    Adds a fillInStackTrace branch to the list.
447
448 *******************************************************************************/
449
450 void codegen_add_fillinstacktrace_ref(codegendata *cd)
451 {
452         codegen_add_exception_ref(cd, -1, STACKTRACE_inline_fillInStackTrace);
453 }
454
455
456 /* codegen_add_patch_ref *******************************************************
457
458    Appends a new patcher reference to the list of patching positions.
459
460 *******************************************************************************/
461
462 void codegen_add_patch_ref(codegendata *cd, functionptr patcher, voidptr ref,
463                                                    s4 disp)
464 {
465         patchref *pr;
466         s4        branchmpc;
467
468         branchmpc = cd->mcodeptr - cd->mcodebase;
469
470         pr = DNEW(patchref);
471
472         pr->branchpos = branchmpc;
473         pr->disp      = disp;
474         pr->patcher   = patcher;
475         pr->ref       = ref;
476
477 /*      list_add_first(cd->patchrefs, pr); */
478         pr->next      = cd->patchrefs;
479         cd->patchrefs = pr;
480
481 #if defined(ENABLE_JIT) && (defined(__ALPHA__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__SPARC_64__) || defined(__X86_64__) ||  defined(__S390__))
482         /* Generate NOPs for opt_shownops. */
483
484         if (opt_shownops)
485                 PATCHER_NOPS;
486 #endif
487
488 #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__MIPS__) || defined(__X86_64__))
489         /* On some architectures the patcher stub call instruction might
490            be longer than the actual instruction generated.  On this
491            architectures we store the last patcher call position and after
492            the basic block code generation is completed, we check the
493            range and maybe generate some nop's. */
494
495         cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
496 #endif
497 }
498
499
500 /* methodtree_comparator *******************************************************
501
502    Comparator function used for the AVL tree of methods.
503
504 *******************************************************************************/
505
506 static s4 methodtree_comparator(const void *pc, const void *element)
507 {
508         methodtree_element *mte;
509         methodtree_element *mtepc;
510
511         mte = (methodtree_element *) element;
512         mtepc = (methodtree_element *) pc;
513
514         /* compare both startpc and endpc of pc, even if they have the same value,
515            otherwise the avl_probe sometimes thinks the element is already in the
516            tree */
517
518 #ifdef __S390__
519         /* On S390 addresses are 31 bit. Compare only 31 bits of value.
520          */
521 #       define ADDR_MASK(a) ((a) & 0x7FFFFFFF)
522 #else
523 #       define ADDR_MASK(a) (a)
524 #endif
525
526         if (ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->startpc) &&
527                 ADDR_MASK((long) mtepc->startpc) <= ADDR_MASK((long) mte->endpc) &&
528                 ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->endpc) &&
529                 ADDR_MASK((long) mtepc->endpc) <= ADDR_MASK((long) mte->endpc)) {
530                 return 0;
531
532         } else if (ADDR_MASK((long) mtepc->startpc) < ADDR_MASK((long) mte->startpc)) {
533                 return -1;
534
535         } else {
536                 return 1;
537         }
538
539 #       undef ADDR_MASK
540 }
541
542
543 /* codegen_insertmethod ********************************************************
544
545    Insert the machine code range of a method into the AVL tree of methods.
546
547 *******************************************************************************/
548
549 void codegen_insertmethod(u1 *startpc, u1 *endpc)
550 {
551         methodtree_element *mte;
552
553         /* allocate new method entry */
554
555         mte = NEW(methodtree_element);
556
557         mte->startpc = startpc;
558         mte->endpc   = endpc;
559
560         /* this function does not return an error, but asserts for
561            duplicate entries */
562
563         avl_insert(methodtree, mte);
564 }
565
566
567 /* codegen_get_pv_from_pc ******************************************************
568
569    Find the PV for the given PC by searching in the AVL tree of
570    methods.
571
572 *******************************************************************************/
573
574 u1 *codegen_get_pv_from_pc(u1 *pc)
575 {
576         methodtree_element  mtepc;
577         methodtree_element *mte;
578
579         /* allocation of the search structure on the stack is much faster */
580
581         mtepc.startpc = pc;
582         mtepc.endpc   = pc;
583
584         mte = avl_find(methodtree, &mtepc);
585
586         if (mte == NULL) {
587                 /* No method was found.  Let's dump a stacktrace. */
588
589                 log_println("We received a SIGSEGV and tried to handle it, but we were");
590                 log_println("unable to find a Java method at:");
591                 log_println("");
592 #if SIZEOF_VOID_P == 8
593                 log_println("PC=0x%016lx", pc);
594 #else
595                 log_println("PC=0x%08x", pc);
596 #endif
597                 log_println("");
598                 log_println("Dumping the current stacktrace:");
599
600                 stacktrace_dump_trace(THREADOBJECT);
601
602                 vm_abort("Exiting...");
603         }
604
605         return mte->startpc;
606 }
607
608
609 /* codegen_get_pv_from_pc_nocheck **********************************************
610
611    Find the PV for the given PC by searching in the AVL tree of
612    methods.  This method does not check the return value and is used
613    by the profiler.
614
615 *******************************************************************************/
616
617 u1 *codegen_get_pv_from_pc_nocheck(u1 *pc)
618 {
619         methodtree_element  mtepc;
620         methodtree_element *mte;
621
622         /* allocation of the search structure on the stack is much faster */
623
624         mtepc.startpc = pc;
625         mtepc.endpc   = pc;
626
627         mte = avl_find(methodtree, &mtepc);
628
629         if (mte == NULL)
630                 return NULL;
631         else
632                 return mte->startpc;
633 }
634
635
636 /* codegen_set_replacement_point_notrap ****************************************
637
638    Record the position of a non-trappable replacement point.
639
640 *******************************************************************************/
641
642 #if defined(ENABLE_REPLACEMENT)
643 #if !defined(NDEBUG)
644 void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
645 #else
646 void codegen_set_replacement_point_notrap(codegendata *cd)
647 #endif
648 {
649         assert(cd->replacementpoint);
650         assert(cd->replacementpoint->type == type);
651         assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
652
653         cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
654
655         cd->replacementpoint++;
656 }
657 #endif /* defined(ENABLE_REPLACEMENT) */
658
659
660 /* codegen_set_replacement_point ***********************************************
661
662    Record the position of a trappable replacement point.
663
664 *******************************************************************************/
665
666 #if defined(ENABLE_REPLACEMENT)
667 #if !defined(NDEBUG)
668 void codegen_set_replacement_point(codegendata *cd, s4 type)
669 #else
670 void codegen_set_replacement_point(codegendata *cd)
671 #endif
672 {
673         assert(cd->replacementpoint);
674         assert(cd->replacementpoint->type == type);
675         assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
676
677         cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
678
679         cd->replacementpoint++;
680
681         /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
682
683         cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
684 }
685 #endif /* defined(ENABLE_REPLACEMENT) */
686
687
688 /* codegen_finish **************************************************************
689
690    Finishes the code generation. A new memory, large enough for both
691    data and code, is allocated and data and code are copied together
692    to their final layout, unresolved jumps are resolved, ...
693
694 *******************************************************************************/
695
696 void codegen_finish(jitdata *jd)
697 {
698         codeinfo    *code;
699         codegendata *cd;
700         s4           mcodelen;
701 #if defined(ENABLE_INTRP)
702         s4           ncodelen;
703 #endif
704         s4           alignedmcodelen;
705         jumpref     *jr;
706         u1          *epoint;
707         s4           extralen;
708         s4           alignedlen;
709
710         /* get required compiler data */
711
712         code = jd->code;
713         cd   = jd->cd;
714
715         /* prevent compiler warning */
716
717 #if defined(ENABLE_INTRP)
718         ncodelen = 0;
719 #endif
720
721         /* calculate the code length */
722
723         mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
724
725 #if defined(ENABLE_THREADS)
726         extralen = sizeof(critical_section_node_t) * cd->threadcritcount;
727 #else
728         extralen = 0;
729 #endif
730
731 #if defined(ENABLE_STATISTICS)
732         if (opt_stat) {
733                 count_code_len += mcodelen;
734                 count_data_len += cd->dseglen;
735         }
736 #endif
737
738         alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
739
740 #if defined(ENABLE_INTRP)
741         if (opt_intrp)
742                 ncodelen = cd->ncodeptr - cd->ncodebase;
743         else {
744                 ncodelen = 0; /* avoid compiler warning */
745         }
746 #endif
747
748         cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
749         alignedlen = alignedmcodelen + cd->dseglen;
750
751 #if defined(ENABLE_INTRP)
752         if (opt_intrp) {
753                 alignedlen += ncodelen;
754         }
755 #endif
756
757         /* allocate new memory */
758
759         code->mcodelength = mcodelen + cd->dseglen;
760         code->mcode       = CNEW(u1, alignedlen + extralen);
761
762         /* set the entrypoint of the method */
763         
764         assert(code->entrypoint == NULL);
765         code->entrypoint = epoint = (code->mcode + cd->dseglen);
766
767         /* fill the data segment (code->entrypoint must already be set!) */
768
769         dseg_finish(jd);
770
771         /* copy code to the new location */
772
773         MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
774
775 #if defined(ENABLE_INTRP)
776         /* relocate native dynamic superinstruction code (if any) */
777
778         if (opt_intrp) {
779                 cd->mcodebase = code->entrypoint;
780
781                 if (ncodelen > 0) {
782                         u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
783
784                         MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
785
786                         /* flush the instruction and data caches */
787
788                         md_cacheflush(ncodebase, ncodelen);
789
790                         /* set some cd variables for dynamic_super_rerwite */
791
792                         cd->ncodebase = ncodebase;
793
794                 } else {
795                         cd->ncodebase = NULL;
796                 }
797
798                 dynamic_super_rewrite(cd);
799         }
800 #endif
801
802         /* jump table resolving */
803
804         for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
805                 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
806                         (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
807
808         /* line number table resolving */
809         {
810                 linenumberref *lr;
811                 ptrint lrtlen = 0;
812                 ptrint target;
813
814                 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
815                         lrtlen++;
816                         target = lr->targetmpc;
817                         /* if the entry contains an mcode pointer (normal case), resolve it */
818                         /* (see doc/inlining_stacktrace.txt for details)                    */
819                         if (lr->linenumber >= -2) {
820                             target += (ptrint) epoint;
821                         }
822                         *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) = 
823                                 (functionptr) target;
824                 }
825                 
826                 *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
827                         (functionptr) ((ptrint) epoint + cd->linenumbertab);
828
829                 *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
830         }
831
832 #if defined(ENABLE_REPLACEMENT)
833         /* replacement point resolving */
834         {
835                 int i;
836                 rplpoint *rp;
837
838                 code->replacementstubs += (ptrint) epoint;
839
840                 rp = code->rplpoints;
841                 for (i=0; i<code->rplpointcount; ++i, ++rp) {
842                         rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
843                 }
844         }
845 #endif /* defined(ENABLE_REPLACEMENT) */
846
847         /* add method into methodtree to find the entrypoint */
848
849         codegen_insertmethod(code->entrypoint, code->entrypoint + mcodelen);
850
851 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
852         /* resolve data segment references */
853
854         dseg_resolve_datareferences(jd);
855 #endif
856
857 #if defined(ENABLE_THREADS)
858         {
859                 critical_section_node_t *n = (critical_section_node_t *) ((ptrint) code->mcode + alignedlen);
860                 s4 i;
861                 codegen_critical_section_t *nt = cd->threadcrit;
862
863                 for (i = 0; i < cd->threadcritcount; i++) {
864                         n->mcodebegin = (u1 *) (ptrint) code->mcode + nt->mcodebegin;
865                         n->mcodeend = (u1 *) (ptrint) code->mcode + nt->mcodeend;
866                         n->mcoderestart = (u1 *) (ptrint) code->mcode + nt->mcoderestart;
867                         critical_register_critical_section(n);
868                         n++;
869                         nt = nt->next;
870                 }
871         }
872 #endif
873
874         /* flush the instruction and data caches */
875
876         md_cacheflush(code->mcode, code->mcodelength);
877 }
878
879
880 /* codegen_createnativestub ****************************************************
881
882    Wrapper for createnativestub.
883
884    Returns:
885        the codeinfo representing the stub code.
886
887 *******************************************************************************/
888
889 codeinfo *codegen_createnativestub(functionptr f, methodinfo *m)
890 {
891         jitdata     *jd;
892         codeinfo    *code;
893         s4           dumpsize;
894         methoddesc  *md;
895         methoddesc  *nmd;       
896         s4           nativeparams;
897
898         /* mark dump memory */
899
900         dumpsize = dump_size();
901
902         jd = DNEW(jitdata);
903
904         jd->m     = m;
905         jd->cd    = DNEW(codegendata);
906         jd->rd    = DNEW(registerdata);
907         jd->flags = 0;
908
909         /* Allocate codeinfo memory from the heap as we need to keep them. */
910
911         jd->code  = code_codeinfo_new(m); /* XXX check allocation */
912
913         /* get required compiler data */
914
915         code = jd->code;
916
917         /* set the flags for the current JIT run */
918
919 #if defined(ENABLE_PROFILING)
920         if (opt_prof)
921                 jd->flags |= JITDATA_FLAG_INSTRUMENT;
922 #endif
923
924         if (opt_verbosecall)
925                 jd->flags |= JITDATA_FLAG_VERBOSECALL;
926
927         /* setup code generation stuff */
928
929 #if defined(ENABLE_JIT)
930 # if defined(ENABLE_INTRP)
931         if (!opt_intrp)
932 # endif
933                 reg_setup(jd);
934 #endif
935
936         codegen_setup(jd);
937
938         /* create new method descriptor with additional native parameters */
939
940         md = m->parseddesc;
941         nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
942         
943         nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
944                                                            md->paramcount * sizeof(typedesc) +
945                                                            nativeparams * sizeof(typedesc));
946
947         nmd->paramcount = md->paramcount + nativeparams;
948
949         nmd->params = DMNEW(paramdesc, nmd->paramcount);
950
951         nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer            */
952
953         if (m->flags & ACC_STATIC)
954                 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer              */
955
956         MCOPY(nmd->paramtypes + nativeparams, md->paramtypes, typedesc,
957                   md->paramcount);
958
959 #if defined(ENABLE_JIT)
960 # if defined(ENABLE_INTRP)
961         if (!opt_intrp)
962 # endif
963                 /* pre-allocate the arguments for the native ABI */
964
965                 md_param_alloc_native(nmd);
966 #endif
967
968         /* generate the code */
969
970 #if defined(ENABLE_JIT)
971 # if defined(ENABLE_INTRP)
972         if (opt_intrp)
973                 code->entrypoint = intrp_createnativestub(f, jd, nmd);
974         else
975 # endif
976                 code->entrypoint = createnativestub(f, jd, nmd);
977 #else
978         code->entrypoint = intrp_createnativestub(f, jd, nmd);
979 #endif
980
981 #if defined(ENABLE_STATISTICS)
982         if (opt_stat)
983                 count_nstub_len += code->mcodelength;
984 #endif
985
986 #if !defined(NDEBUG)
987         /* disassemble native stub */
988
989         if (opt_shownativestub) {
990 #if defined(ENABLE_DISASSEMBLER)
991                 codegen_disassemble_nativestub(m,
992                                                                            (u1 *) (ptrint) code->entrypoint,
993                                                                            (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
994 #endif
995
996                 /* show data segment */
997
998                 if (opt_showddatasegment)
999                         dseg_display(jd);
1000         }
1001 #endif /* !defined(NDEBUG) */
1002
1003         /* release memory */
1004
1005         dump_release(dumpsize);
1006
1007         /* return native stub code */
1008
1009         return code;
1010 }
1011
1012
1013 /* codegen_disassemble_nativestub **********************************************
1014
1015    Disassembles the generated native stub.
1016
1017 *******************************************************************************/
1018
1019 #if defined(ENABLE_DISASSEMBLER)
1020 void codegen_disassemble_nativestub(methodinfo *m, u1 *start, u1 *end)
1021 {
1022         printf("Native stub: ");
1023         utf_fprint_printable_ascii_classname(stdout, m->class->name);
1024         printf(".");
1025         utf_fprint_printable_ascii(stdout, m->name);
1026         utf_fprint_printable_ascii(stdout, m->descriptor);
1027         printf("\n\nLength: %d\n\n", (s4) (end - start));
1028
1029         DISASSEMBLE(start, end);
1030 }
1031 #endif
1032
1033
1034 /* codegen_start_native_call ***************************************************
1035
1036    Prepares the stuff required for a native (JNI) function call:
1037
1038    - adds a stackframe info structure to the chain, for stacktraces
1039    - prepares the local references table on the stack
1040
1041    The layout of the native stub stackframe should look like this:
1042
1043    +---------------------------+ <- SP (of parent Java function)
1044    | return address            |
1045    +---------------------------+
1046    |                           |
1047    | stackframe info structure |
1048    |                           |
1049    +---------------------------+
1050    |                           |
1051    | local references table    |
1052    |                           |
1053    +---------------------------+
1054    |                           |
1055    | arguments (if any)        |
1056    |                           |
1057    +---------------------------+ <- SP (native stub)
1058
1059 *******************************************************************************/
1060
1061 void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
1062 {
1063         stackframeinfo *sfi;
1064         localref_table *lrt;
1065
1066         /* get data structures from stack */
1067
1068         sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1069         lrt = (localref_table *) (datasp - sizeof(stackframeinfo) - 
1070                                                           sizeof(localref_table));
1071
1072         /* add a stackframeinfo to the chain */
1073
1074         stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
1075
1076 #if defined(ENABLE_JAVASE)
1077         /* add current JNI local references table to this thread */
1078
1079         lrt->capacity    = LOCALREFTABLE_CAPACITY;
1080         lrt->used        = 0;
1081         lrt->localframes = 1;
1082         lrt->prev        = LOCALREFTABLE;
1083
1084         /* clear the references array (memset is faster the a for-loop) */
1085
1086         MSET(lrt->refs, 0, java_objectheader*, LOCALREFTABLE_CAPACITY);
1087
1088         LOCALREFTABLE = lrt;
1089 #endif
1090
1091 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1092         /* set the native world flag */
1093
1094         THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE;
1095 #endif
1096 }
1097
1098
1099 /* codegen_finish_native_call **************************************************
1100
1101    Removes the stuff required for a native (JNI) function call.
1102    Additionally it checks for an exceptions and in case, get the
1103    exception object and clear the pointer.
1104
1105 *******************************************************************************/
1106
1107 java_objectheader *codegen_finish_native_call(u1 *datasp)
1108 {
1109         stackframeinfo     *sfi;
1110         stackframeinfo    **psfi;
1111         localref_table     *lrt;
1112         localref_table     *plrt;
1113         s4                  localframes;
1114         java_objectheader  *e;
1115
1116         /* get data structures from stack */
1117
1118         sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1119         lrt = (localref_table *) (datasp - sizeof(stackframeinfo) - 
1120                                                           sizeof(localref_table));
1121
1122 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1123         /* clear the native world flag */
1124
1125         THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE;
1126 #endif
1127
1128         /* remove current stackframeinfo from chain */
1129
1130         psfi = STACKFRAMEINFO;
1131
1132         *psfi = sfi->prev;
1133
1134 #if defined(ENABLE_JAVASE)
1135         /* release JNI local references tables for this thread */
1136
1137         lrt = LOCALREFTABLE;
1138
1139         /* release all current local frames */
1140
1141         for (localframes = lrt->localframes; localframes >= 1; localframes--) {
1142                 /* get previous frame */
1143
1144                 plrt = lrt->prev;
1145
1146                 /* Clear all reference entries (only for tables allocated on
1147                    the Java heap). */
1148
1149                 if (localframes > 1)
1150                         MSET(&lrt->refs[0], 0, java_objectheader*, lrt->capacity);
1151
1152                 lrt->prev = NULL;
1153
1154                 /* set new local references table */
1155
1156                 lrt = plrt;
1157         }
1158
1159         /* now store the previous local frames in the thread structure */
1160
1161         LOCALREFTABLE = lrt;
1162 #endif
1163
1164         /* get the exception and return it */
1165
1166         e = exceptions_get_and_clear_exception();
1167
1168         return e;
1169 }
1170
1171
1172 /* removecompilerstub **********************************************************
1173
1174    Deletes a compilerstub from memory (simply by freeing it).
1175
1176 *******************************************************************************/
1177
1178 void removecompilerstub(u1 *stub)
1179 {
1180         /* pass size 1 to keep the intern function happy */
1181
1182         CFREE((void *) stub, 1);
1183 }
1184
1185
1186 /* removenativestub ************************************************************
1187
1188    Removes a previously created native-stub from memory.
1189     
1190 *******************************************************************************/
1191
1192 void removenativestub(u1 *stub)
1193 {
1194         /* pass size 1 to keep the intern function happy */
1195
1196         CFREE((void *) stub, 1);
1197 }
1198
1199
1200 /* codegen_reg_of_var **********************************************************
1201
1202    This function determines a register, to which the result of an
1203    operation should go, when it is ultimatively intended to store the
1204    result in pseudoregister v.  If v is assigned to an actual
1205    register, this register will be returned.  Otherwise (when v is
1206    spilled) this function returns tempregnum.  If not already done,
1207    regoff and flags are set in the stack location.
1208        
1209    On ARM we have to check if a long/double variable is splitted
1210    across reg/stack (HIGH_REG == REG_SPLIT). We return the actual
1211    register of v for LOW_REG and the tempregnum for HIGH_REG in such
1212    cases.  (michi 2005/07/24)
1213
1214 *******************************************************************************/
1215
1216 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
1217 {
1218
1219 #if 0
1220         /* Do we have to generate a conditional move?  Yes, then always
1221            return the temporary register.  The real register is identified
1222            during the store. */
1223
1224         if (opcode & ICMD_CONDITION_MASK)
1225                 return tempregnum;
1226 #endif
1227
1228         if (!(v->flags & INMEMORY)) {
1229 #if defined(__ARM__) && defined(__ARMEL__)
1230                 if (IS_2_WORD_TYPE(v->type) && (GET_HIGH_REG(v->vv.regoff) == REG_SPLIT))
1231                         return PACK_REGS(GET_LOW_REG(v->vv.regoff),
1232                                                          GET_HIGH_REG(tempregnum));
1233 #endif
1234 #if defined(__ARM__) && defined(__ARMEB__)
1235                 if (IS_2_WORD_TYPE(v->type) && (GET_LOW_REG(v->vv.regoff) == REG_SPLIT))
1236                         return PACK_REGS(GET_LOW_REG(tempregnum),
1237                                                          GET_HIGH_REG(v->vv.regoff));
1238 #endif
1239                 return v->vv.regoff;
1240         }
1241
1242 #if defined(ENABLE_STATISTICS)
1243         if (opt_stat)
1244                 count_spills_read++;
1245 #endif
1246
1247         return tempregnum;
1248 }
1249
1250 /* codegen_reg_of_dst **********************************************************
1251
1252    This function determines a register, to which the result of an
1253    operation should go, when it is ultimatively intended to store the
1254    result in iptr->dst.var.  If dst.var is assigned to an actual
1255    register, this register will be returned.  Otherwise (when it is
1256    spilled) this function returns tempregnum.  If not already done,
1257    regoff and flags are set in the stack location.
1258        
1259    On ARM we have to check if a long/double variable is splitted
1260    across reg/stack (HIGH_REG == REG_SPLIT). We return the actual
1261    register of dst.var for LOW_REG and the tempregnum for HIGH_REG in such
1262    cases.  (michi 2005/07/24)
1263
1264 *******************************************************************************/
1265
1266 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
1267 {
1268         return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
1269 }
1270
1271
1272 #if defined(ENABLE_THREADS)
1273 void codegen_threadcritrestart(codegendata *cd, int offset)
1274 {
1275         cd->threadcritcurrent.mcoderestart = offset;
1276 }
1277
1278
1279 void codegen_threadcritstart(codegendata *cd, int offset)
1280 {
1281         cd->threadcritcurrent.mcodebegin = offset;
1282 }
1283
1284
1285 void codegen_threadcritstop(codegendata *cd, int offset)
1286 {
1287         cd->threadcritcurrent.next = cd->threadcrit;
1288         cd->threadcritcurrent.mcodeend = offset;
1289         cd->threadcrit = DNEW(codegen_critical_section_t);
1290         *(cd->threadcrit) = cd->threadcritcurrent;
1291         cd->threadcritcount++;
1292 }
1293 #endif
1294
1295
1296 /*
1297  * These are local overrides for various environment variables in Emacs.
1298  * Please do not remove this and leave it at the end of the file, where
1299  * Emacs will automagically detect them.
1300  * ---------------------------------------------------------------------
1301  * Local variables:
1302  * mode: c
1303  * indent-tabs-mode: t
1304  * c-basic-offset: 4
1305  * tab-width: 4
1306  * End:
1307  * vim:noexpandtab:sw=4:ts=4:
1308  */