* Removed all Id tags.
[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 */
43
44
45 #include "config.h"
46
47 #include <assert.h>
48 #include <string.h>
49
50 #include "vm/types.h"
51
52 #if defined(ENABLE_JIT)
53 /* this is required PATCHER_CALL_SIZE */
54 # include "codegen.h"
55 #endif
56
57 #include "mm/memory.h"
58
59 #include "toolbox/avl.h"
60 #include "toolbox/list.h"
61 #include "toolbox/logging.h"
62
63 #include "native/jni.h"
64 #include "native/localref.h"
65 #include "native/native.h"
66
67 #include "threads/threads-common.h"
68
69 #include "vm/exceptions.h"
70 #include "vm/stringlocal.h"
71
72 #include "vm/jit/abi.h"
73 #include "vm/jit/asmpart.h"
74 #include "vm/jit/codegen-common.h"
75
76 #if defined(ENABLE_DISASSEMBLER)
77 # include "vm/jit/disass.h"
78 #endif
79
80 #include "vm/jit/dseg.h"
81 #include "vm/jit/emit-common.h"
82 #include "vm/jit/jit.h"
83 #include "vm/jit/md.h"
84 #include "vm/jit/patcher-common.h"
85 #include "vm/jit/replace.h"
86 #if defined(ENABLE_SSA)
87 # include "vm/jit/optimizing/lsra.h"
88 # include "vm/jit/optimizing/ssa.h"
89 #endif
90 #include "vm/jit/stacktrace.h"
91
92 #if defined(ENABLE_INTRP)
93 #include "vm/jit/intrp/intrp.h"
94 #endif
95
96 #include "vmcore/method.h"
97 #include "vmcore/options.h"
98
99 # include "vmcore/statistics.h"
100
101 #if defined(ENABLE_VMLOG)
102 #include <vmlog_cacao.h>
103 #endif
104
105 #include "show.h"
106
107 /* in this tree we store all method addresses *********************************/
108
109 static avl_tree_t *methodtree = NULL;
110 static s4 methodtree_comparator(const void *treenode, const void *node);
111
112
113 /* codegen_init ****************************************************************
114
115    TODO
116
117 *******************************************************************************/
118
119 void codegen_init(void)
120 {
121         /* this tree is global, not method specific */
122
123         if (!methodtree) {
124 #if defined(ENABLE_JIT)
125                 methodtree_element *mte;
126 #endif
127
128                 methodtree = avl_create(&methodtree_comparator);
129
130 #if defined(ENABLE_JIT)
131                 /* insert asm_vm_call_method */
132
133                 mte = NEW(methodtree_element);
134
135                 mte->startpc = (u1 *) (ptrint) asm_vm_call_method;
136                 mte->endpc   = (u1 *) (ptrint) asm_vm_call_method_end;
137
138                 avl_insert(methodtree, mte);
139 #endif /* defined(ENABLE_JIT) */
140
141         }
142
143 }
144
145
146 /* codegen_setup ***************************************************************
147
148    Allocates and initialises code area, data area and references.
149
150 *******************************************************************************/
151
152 void codegen_setup(jitdata *jd)
153 {
154         methodinfo  *m;
155         codegendata *cd;
156
157         /* get required compiler data */
158
159         m  = jd->m;
160         cd = jd->cd;
161
162         /* initialize members */
163
164         cd->flags        = 0;
165
166         cd->mcodebase    = DMNEW(u1, MCODEINITSIZE);
167         cd->mcodeend     = cd->mcodebase + MCODEINITSIZE;
168         cd->mcodesize    = MCODEINITSIZE;
169
170         /* initialize mcode variables */
171
172         cd->mcodeptr     = cd->mcodebase;
173         cd->lastmcodeptr = cd->mcodebase;
174
175 #if defined(ENABLE_INTRP)
176         /* native dynamic superinstructions variables */
177
178         if (opt_intrp) {
179                 cd->ncodebase = DMNEW(u1, NCODEINITSIZE);
180                 cd->ncodesize = NCODEINITSIZE;
181
182                 /* initialize ncode variables */
183         
184                 cd->ncodeptr = cd->ncodebase;
185
186                 cd->lastinstwithoutdispatch = ~0; /* no inst without dispatch */
187                 cd->superstarts = NULL;
188         }
189 #endif
190
191         cd->dseg           = NULL;
192         cd->dseglen        = 0;
193
194         cd->jumpreferences = NULL;
195
196 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
197         cd->datareferences = NULL;
198 #endif
199
200 /*      cd->patchrefs      = list_create_dump(OFFSET(patchref, linkage)); */
201         cd->patchrefs      = NULL;
202         cd->brancheslabel  = list_create_dump(OFFSET(branch_label_ref_t, linkage));
203         cd->listcritical   = list_create_dump(OFFSET(critical_section_ref_t, linkage));
204
205         cd->linenumberreferences = NULL;
206         cd->linenumbertablesizepos = 0;
207         cd->linenumbertablestartpos = 0;
208         cd->linenumbertab = 0;
209 }
210
211
212 /* codegen_reset ***************************************************************
213
214    Resets the codegen data structure so we can recompile the method.
215
216 *******************************************************************************/
217
218 static void codegen_reset(jitdata *jd)
219 {
220         codeinfo    *code;
221         codegendata *cd;
222         basicblock  *bptr;
223
224         /* get required compiler data */
225
226         code = jd->code;
227         cd   = jd->cd;
228
229         /* reset error flag */
230
231         cd->flags          &= ~CODEGENDATA_FLAG_ERROR;
232
233         /* reset some members, we reuse the code memory already allocated
234            as this should have almost the correct size */
235
236         cd->mcodeptr        = cd->mcodebase;
237         cd->lastmcodeptr    = cd->mcodebase;
238
239         cd->dseg            = NULL;
240         cd->dseglen         = 0;
241
242         cd->jumpreferences  = NULL;
243
244 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
245         cd->datareferences  = NULL;
246 #endif
247
248 /*      cd->patchrefs       = list_create_dump(OFFSET(patchref, linkage)); */
249         cd->patchrefs       = NULL;
250         cd->brancheslabel   = list_create_dump(OFFSET(branch_label_ref_t, linkage));
251         cd->listcritical    = list_create_dump(OFFSET(critical_section_ref_t, linkage));
252
253         cd->linenumberreferences    = NULL;
254         cd->linenumbertablesizepos  = 0;
255         cd->linenumbertablestartpos = 0;
256         cd->linenumbertab           = 0;
257         
258         /* We need to clear the mpc and the branch references from all
259            basic blocks as they will definitely change. */
260
261         for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
262                 bptr->mpc        = -1;
263                 bptr->branchrefs = NULL;
264         }
265
266         /* We need to clear all the patcher references from the codeinfo
267            since they all will be regenerated */
268
269         patcher_list_reset(code);
270
271 #if defined(ENABLE_REPLACEMENT)
272         code->rplpoints     = NULL;
273         code->rplpointcount = 0;
274         code->regalloc      = NULL;
275         code->regalloccount = 0;
276         code->globalcount   = 0;
277 #endif
278 }
279
280
281 /* codegen_generate ************************************************************
282
283    Generates the code for the currently compiled method.
284
285 *******************************************************************************/
286
287 bool codegen_generate(jitdata *jd)
288 {
289         codegendata *cd;
290
291         /* get required compiler data */
292
293         cd = jd->cd;
294
295         /* call the machine-dependent code generation function */
296
297         if (!codegen_emit(jd))
298                 return false;
299
300         /* check for an error */
301
302         if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
303                 /* check for long-branches flag, if it is set we recompile the
304                    method */
305
306 #if !defined(NDEBUG)
307         if (compileverbose)
308             log_message_method("Re-generating code: ", jd->m);
309 #endif
310
311                 /* XXX maybe we should tag long-branches-methods for recompilation */
312
313                 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
314                         /* we have to reset the codegendata structure first */
315
316                         codegen_reset(jd);
317
318                         /* and restart the compiler run */
319
320                         if (!codegen_emit(jd))
321                                 return false;
322                 }
323                 else {
324                         vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
325                 }
326
327 #if !defined(NDEBUG)
328         if (compileverbose)
329             log_message_method("Re-generating code done: ", jd->m);
330 #endif
331         }
332
333         /* reallocate the memory and finish the code generation */
334
335         codegen_finish(jd);
336
337         /* everything's ok */
338
339         return true;
340 }
341
342
343 /* codegen_close ***************************************************************
344
345    TODO
346
347 *******************************************************************************/
348
349 void codegen_close(void)
350 {
351         /* TODO: release avl tree on i386 and x86_64 */
352 }
353
354
355 /* codegen_increase ************************************************************
356
357    Doubles code area.
358
359 *******************************************************************************/
360
361 void codegen_increase(codegendata *cd)
362 {
363         u1 *oldmcodebase;
364
365         /* save old mcodebase pointer */
366
367         oldmcodebase = cd->mcodebase;
368
369         /* reallocate to new, doubled memory */
370
371         cd->mcodebase = DMREALLOC(cd->mcodebase,
372                                                           u1,
373                                                           cd->mcodesize,
374                                                           cd->mcodesize * 2);
375         cd->mcodesize *= 2;
376         cd->mcodeend   = cd->mcodebase + cd->mcodesize;
377
378         /* set new mcodeptr */
379
380         cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
381
382 #if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(__M68K__) || defined(ENABLE_INTRP) \
383  || defined(__SPARC_64__)
384         /* adjust the pointer to the last patcher position */
385
386         if (cd->lastmcodeptr != NULL)
387                 cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
388 #endif
389 }
390
391
392 /* codegen_ncode_increase ******************************************************
393
394    Doubles code area.
395
396 *******************************************************************************/
397
398 #if defined(ENABLE_INTRP)
399 u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
400 {
401         u1 *oldncodebase;
402
403         /* save old ncodebase pointer */
404
405         oldncodebase = cd->ncodebase;
406
407         /* reallocate to new, doubled memory */
408
409         cd->ncodebase = DMREALLOC(cd->ncodebase,
410                                                           u1,
411                                                           cd->ncodesize,
412                                                           cd->ncodesize * 2);
413         cd->ncodesize *= 2;
414
415         /* return the new ncodeptr */
416
417         return (cd->ncodebase + (ncodeptr - oldncodebase));
418 }
419 #endif
420
421
422 /* codegen_add_branch_ref ******************************************************
423
424    Prepends an branch to the list.
425
426 *******************************************************************************/
427
428 void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
429 {
430         branchref *br;
431         s4         branchmpc;
432
433         STATISTICS(count_branches_unresolved++);
434
435         /* calculate the mpc of the branch instruction */
436
437         branchmpc = cd->mcodeptr - cd->mcodebase;
438
439         br = DNEW(branchref);
440
441         br->branchmpc = branchmpc;
442         br->condition = condition;
443         br->reg       = reg;
444         br->options   = options;
445         br->next      = target->branchrefs;
446
447         target->branchrefs = br;
448 }
449
450
451 /* codegen_resolve_branchrefs **************************************************
452
453    Resolves and patches the branch references of a given basic block.
454
455 *******************************************************************************/
456
457 void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
458 {
459         branchref *br;
460         u1        *mcodeptr;
461
462         /* Save the mcodeptr because in the branch emitting functions
463            we generate code somewhere inside already generated code,
464            but we're still in the actual code generation phase. */
465
466         mcodeptr = cd->mcodeptr;
467
468         /* just to make sure */
469
470         assert(bptr->mpc >= 0);
471
472         for (br = bptr->branchrefs; br != NULL; br = br->next) {
473                 /* temporary set the mcodeptr */
474
475                 cd->mcodeptr = cd->mcodebase + br->branchmpc;
476
477                 /* emit_bccz and emit_branch emit the correct code, even if we
478                    pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
479
480                 emit_bccz(cd, bptr, br->condition, br->reg, br->options);
481         }
482
483         /* restore mcodeptr */
484
485         cd->mcodeptr = mcodeptr;
486 }
487
488
489 /* codegen_branch_label_add ****************************************************
490
491    Append an branch to the label-branch list.
492
493 *******************************************************************************/
494
495 void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
496 {
497         list_t             *list;
498         branch_label_ref_t *br;
499         s4                  mpc;
500
501         /* get the label list */
502
503         list = cd->brancheslabel;
504         
505         /* calculate the current mpc */
506
507         mpc = cd->mcodeptr - cd->mcodebase;
508
509         br = DNEW(branch_label_ref_t);
510
511         br->mpc       = mpc;
512         br->label     = label;
513         br->condition = condition;
514         br->reg       = reg;
515         br->options   = options;
516
517         /* add the branch to the list */
518
519         list_add_last_unsynced(list, br);
520 }
521
522
523 /* codegen_add_patch_ref *******************************************************
524
525    Appends a new patcher reference to the list of patching positions.
526
527 *******************************************************************************/
528
529 void codegen_add_patch_ref(codegendata *cd, functionptr patcher, voidptr ref,
530                                                    s4 disp)
531 {
532         patchref *pr;
533         s4        branchmpc;
534
535         branchmpc = cd->mcodeptr - cd->mcodebase;
536
537         pr = DNEW(patchref);
538
539         pr->branchpos = branchmpc;
540         pr->disp      = disp;
541         pr->patcher   = patcher;
542         pr->ref       = ref;
543
544 /*      list_add_first(cd->patchrefs, pr); */
545         pr->next      = cd->patchrefs;
546         cd->patchrefs = pr;
547
548         /* Generate NOPs for opt_shownops. */
549
550         if (opt_shownops)
551                 PATCHER_NOPS;
552
553 #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__M68K__) || defined(__MIPS__) \
554  || defined(__SPARC_64__) || defined(__X86_64__))
555
556         /* On some architectures the patcher stub call instruction might
557            be longer than the actual instruction generated.  On this
558            architectures we store the last patcher call position and after
559            the basic block code generation is completed, we check the
560            range and maybe generate some nop's. */
561         /* The nops are generated in codegen_emit in each codegen */
562
563         cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
564 #endif
565 }
566
567
568 /* codegen_critical_section_new ************************************************
569
570    Allocates a new critical-section reference and adds it to the
571    critical-section list.
572
573 *******************************************************************************/
574
575 #if defined(ENABLE_THREADS)
576 void codegen_critical_section_new(codegendata *cd)
577 {
578         list_t                 *list;
579         critical_section_ref_t *csr;
580         s4                      mpc;
581
582         /* get the critical section list */
583
584         list = cd->listcritical;
585         
586         /* calculate the current mpc */
587
588         mpc = cd->mcodeptr - cd->mcodebase;
589
590         csr = DNEW(critical_section_ref_t);
591
592         /* We only can set restart right now, as start and end are set by
593            the following, corresponding functions. */
594
595         csr->start   = -1;
596         csr->end     = -1;
597         csr->restart = mpc;
598
599         /* add the branch to the list */
600
601         list_add_last_unsynced(list, csr);
602 }
603 #endif
604
605
606 /* codegen_critical_section_start **********************************************
607
608    Set the start-point of the current critical section (which is the
609    last element of the list).
610
611 *******************************************************************************/
612
613 #if defined(ENABLE_THREADS)
614 void codegen_critical_section_start(codegendata *cd)
615 {
616         list_t                 *list;
617         critical_section_ref_t *csr;
618         s4                      mpc;
619
620         /* get the critical section list */
621
622         list = cd->listcritical;
623         
624         /* calculate the current mpc */
625
626         mpc = cd->mcodeptr - cd->mcodebase;
627
628         /* get the current critical section */
629
630         csr = list_last_unsynced(list);
631
632         /* set the start point */
633
634         assert(csr->start == -1);
635
636         csr->start = mpc;
637 }
638 #endif
639
640
641 /* codegen_critical_section_end ************************************************
642
643    Set the end-point of the current critical section (which is the
644    last element of the list).
645
646 *******************************************************************************/
647
648 #if defined(ENABLE_THREADS)
649 void codegen_critical_section_end(codegendata *cd)
650 {
651         list_t                 *list;
652         critical_section_ref_t *csr;
653         s4                      mpc;
654
655         /* get the critical section list */
656
657         list = cd->listcritical;
658         
659         /* calculate the current mpc */
660
661         mpc = cd->mcodeptr - cd->mcodebase;
662
663         /* get the current critical section */
664
665         csr = list_last_unsynced(list);
666
667         /* set the end point */
668
669         assert(csr->end == -1);
670
671         csr->end = mpc;
672 }
673 #endif
674
675
676 /* codegen_critical_section_finish *********************************************
677
678    Finish the critical sections, create the critical section nodes for
679    the AVL tree and insert them into the tree.
680
681 *******************************************************************************/
682
683 #if defined(ENABLE_THREADS)
684 static void codegen_critical_section_finish(jitdata *jd)
685 {
686         codeinfo    *code;
687         codegendata *cd;
688         list_t                  *list;
689         critical_section_ref_t  *csr;
690         critical_section_node_t *csn;
691
692         /* get required compiler data */
693
694         code = jd->code;
695         cd   = jd->cd;
696
697         /* get the critical section list */
698
699         list = cd->listcritical;
700
701         /* iterate over all critical sections */
702
703         for (csr = list_first_unsynced(list); csr != NULL;
704                  csr = list_next_unsynced(list, csr)) {
705                 /* check if all points are set */
706
707                 assert(csr->start   != -1);
708                 assert(csr->end     != -1);
709                 assert(csr->restart != -1);
710
711                 /* allocate tree node */
712
713                 csn = NEW(critical_section_node_t);
714
715                 csn->start   = code->entrypoint + csr->start;
716                 csn->end     = code->entrypoint + csr->end;
717                 csn->restart = code->entrypoint + csr->restart;
718
719                 /* insert into the tree */
720
721                 critical_section_register(csn);
722         }
723 }
724 #endif
725
726
727 /* methodtree_comparator *******************************************************
728
729    Comparator function used for the AVL tree of methods.
730
731    ARGUMENTS:
732       treenode....the node from the tree
733       node........the node to compare to the tree-node
734
735 *******************************************************************************/
736
737 static s4 methodtree_comparator(const void *treenode, const void *node)
738 {
739         methodtree_element *mte;
740         methodtree_element *mtepc;
741
742         mte   = (methodtree_element *) treenode;
743         mtepc = (methodtree_element *) node;
744
745         /* compare both startpc and endpc of pc, even if they have the same value,
746            otherwise the avl_probe sometimes thinks the element is already in the
747            tree */
748
749 #ifdef __S390__
750         /* On S390 addresses are 31 bit. Compare only 31 bits of value.
751          */
752 #       define ADDR_MASK(a) ((a) & 0x7FFFFFFF)
753 #else
754 #       define ADDR_MASK(a) (a)
755 #endif
756
757         if (ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->startpc) &&
758                 ADDR_MASK((long) mtepc->startpc) <= ADDR_MASK((long) mte->endpc) &&
759                 ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->endpc) &&
760                 ADDR_MASK((long) mtepc->endpc) <= ADDR_MASK((long) mte->endpc)) {
761                 return 0;
762
763         } else if (ADDR_MASK((long) mtepc->startpc) < ADDR_MASK((long) mte->startpc)) {
764                 return -1;
765
766         } else {
767                 return 1;
768         }
769
770 #       undef ADDR_MASK
771 }
772
773
774 /* codegen_insertmethod ********************************************************
775
776    Insert the machine code range of a method into the AVL tree of methods.
777
778 *******************************************************************************/
779
780 void codegen_insertmethod(u1 *startpc, u1 *endpc)
781 {
782         methodtree_element *mte;
783
784         /* allocate new method entry */
785
786         mte = NEW(methodtree_element);
787
788         mte->startpc = startpc;
789         mte->endpc   = endpc;
790
791         /* this function does not return an error, but asserts for
792            duplicate entries */
793
794         avl_insert(methodtree, mte);
795 }
796
797
798 /* codegen_get_pv_from_pc ******************************************************
799
800    Find the PV for the given PC by searching in the AVL tree of
801    methods.
802
803 *******************************************************************************/
804
805 u1 *codegen_get_pv_from_pc(u1 *pc)
806 {
807         methodtree_element  mtepc;
808         methodtree_element *mte;
809
810         /* allocation of the search structure on the stack is much faster */
811
812         mtepc.startpc = pc;
813         mtepc.endpc   = pc;
814
815         mte = avl_find(methodtree, &mtepc);
816
817         if (mte == NULL) {
818                 /* No method was found.  Let's dump a stacktrace. */
819
820 #if defined(ENABLE_VMLOG)
821                 vmlog_cacao_signl("SIGSEGV");
822 #endif
823
824                 log_println("We received a SIGSEGV and tried to handle it, but we were");
825                 log_println("unable to find a Java method at:");
826                 log_println("");
827 #if SIZEOF_VOID_P == 8
828                 log_println("PC=0x%016lx", pc);
829 #else
830                 log_println("PC=0x%08x", pc);
831 #endif
832                 log_println("");
833                 assert(0);
834                 log_println("Dumping the current stacktrace:");
835
836 #if defined(ENABLE_THREADS)
837                 /* XXX michi: This should be available even without threads! */
838                 threads_print_stacktrace();
839 #endif
840
841                 vm_abort("Exiting...");
842         }
843
844         return mte->startpc;
845 }
846
847
848 /* codegen_get_pv_from_pc_nocheck **********************************************
849
850    Find the PV for the given PC by searching in the AVL tree of
851    methods.  This method does not check the return value and is used
852    by the profiler.
853
854 *******************************************************************************/
855
856 u1 *codegen_get_pv_from_pc_nocheck(u1 *pc)
857 {
858         methodtree_element  mtepc;
859         methodtree_element *mte;
860
861         /* allocation of the search structure on the stack is much faster */
862
863         mtepc.startpc = pc;
864         mtepc.endpc   = pc;
865
866         mte = avl_find(methodtree, &mtepc);
867
868         if (mte == NULL)
869                 return NULL;
870         else
871                 return mte->startpc;
872 }
873
874
875 /* codegen_set_replacement_point_notrap ****************************************
876
877    Record the position of a non-trappable replacement point.
878
879 *******************************************************************************/
880
881 #if defined(ENABLE_REPLACEMENT)
882 #if !defined(NDEBUG)
883 void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
884 #else
885 void codegen_set_replacement_point_notrap(codegendata *cd)
886 #endif
887 {
888         assert(cd->replacementpoint);
889         assert(cd->replacementpoint->type == type);
890         assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
891
892         cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
893
894         cd->replacementpoint++;
895 }
896 #endif /* defined(ENABLE_REPLACEMENT) */
897
898
899 /* codegen_set_replacement_point ***********************************************
900
901    Record the position of a trappable replacement point.
902
903 *******************************************************************************/
904
905 #if defined(ENABLE_REPLACEMENT)
906 #if !defined(NDEBUG)
907 void codegen_set_replacement_point(codegendata *cd, s4 type)
908 #else
909 void codegen_set_replacement_point(codegendata *cd)
910 #endif
911 {
912         assert(cd->replacementpoint);
913         assert(cd->replacementpoint->type == type);
914         assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
915
916         cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
917
918         cd->replacementpoint++;
919
920         /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
921
922         cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
923 }
924 #endif /* defined(ENABLE_REPLACEMENT) */
925
926
927 /* codegen_finish **************************************************************
928
929    Finishes the code generation. A new memory, large enough for both
930    data and code, is allocated and data and code are copied together
931    to their final layout, unresolved jumps are resolved, ...
932
933 *******************************************************************************/
934
935 void codegen_finish(jitdata *jd)
936 {
937         codeinfo    *code;
938         codegendata *cd;
939         s4           mcodelen;
940 #if defined(ENABLE_INTRP)
941         s4           ncodelen;
942 #endif
943         s4           alignedmcodelen;
944         jumpref     *jr;
945         patchref_t  *pr;
946         u1          *epoint;
947         s4           alignedlen;
948
949         /* get required compiler data */
950
951         code = jd->code;
952         cd   = jd->cd;
953
954         /* prevent compiler warning */
955
956 #if defined(ENABLE_INTRP)
957         ncodelen = 0;
958 #endif
959
960         /* calculate the code length */
961
962         mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
963
964 #if defined(ENABLE_STATISTICS)
965         if (opt_stat) {
966                 count_code_len += mcodelen;
967                 count_data_len += cd->dseglen;
968         }
969 #endif
970
971         alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
972
973 #if defined(ENABLE_INTRP)
974         if (opt_intrp)
975                 ncodelen = cd->ncodeptr - cd->ncodebase;
976         else {
977                 ncodelen = 0; /* avoid compiler warning */
978         }
979 #endif
980
981         cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
982         alignedlen = alignedmcodelen + cd->dseglen;
983
984 #if defined(ENABLE_INTRP)
985         if (opt_intrp) {
986                 alignedlen += ncodelen;
987         }
988 #endif
989
990         /* allocate new memory */
991
992         code->mcodelength = mcodelen + cd->dseglen;
993         code->mcode       = CNEW(u1, alignedlen);
994
995         /* set the entrypoint of the method */
996         
997         assert(code->entrypoint == NULL);
998         code->entrypoint = epoint = (code->mcode + cd->dseglen);
999
1000         /* fill the data segment (code->entrypoint must already be set!) */
1001
1002         dseg_finish(jd);
1003
1004         /* copy code to the new location */
1005
1006         MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
1007
1008 #if defined(ENABLE_INTRP)
1009         /* relocate native dynamic superinstruction code (if any) */
1010
1011         if (opt_intrp) {
1012                 cd->mcodebase = code->entrypoint;
1013
1014                 if (ncodelen > 0) {
1015                         u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
1016
1017                         MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
1018
1019                         /* flush the instruction and data caches */
1020
1021                         md_cacheflush(ncodebase, ncodelen);
1022
1023                         /* set some cd variables for dynamic_super_rerwite */
1024
1025                         cd->ncodebase = ncodebase;
1026
1027                 } else {
1028                         cd->ncodebase = NULL;
1029                 }
1030
1031                 dynamic_super_rewrite(cd);
1032         }
1033 #endif
1034
1035         /* jump table resolving */
1036
1037         for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
1038                 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
1039                         (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
1040
1041         /* line number table resolving */
1042         {
1043                 linenumberref *lr;
1044                 ptrint lrtlen = 0;
1045                 ptrint target;
1046
1047                 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
1048                         lrtlen++;
1049                         target = lr->targetmpc;
1050                         /* if the entry contains an mcode pointer (normal case), resolve it */
1051                         /* (see doc/inlining_stacktrace.txt for details)                    */
1052                         if (lr->linenumber >= -2) {
1053                             target += (ptrint) epoint;
1054                         }
1055                         *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) = 
1056                                 (functionptr) target;
1057                 }
1058                 
1059                 *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
1060                         (functionptr) ((ptrint) epoint + cd->linenumbertab);
1061
1062                 *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
1063         }
1064
1065         /* patcher resolving */
1066
1067         pr = list_first_unsynced(code->patchers);
1068         while (pr) {
1069                 pr->mpc += (ptrint) epoint;
1070                 pr->datap = (ptrint) (pr->disp + epoint);
1071                 pr = list_next_unsynced(code->patchers, pr);
1072         }
1073
1074 #if defined(ENABLE_REPLACEMENT)
1075         /* replacement point resolving */
1076         {
1077                 int i;
1078                 rplpoint *rp;
1079
1080                 rp = code->rplpoints;
1081                 for (i=0; i<code->rplpointcount; ++i, ++rp) {
1082                         rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
1083                 }
1084         }
1085 #endif /* defined(ENABLE_REPLACEMENT) */
1086
1087         /* add method into methodtree to find the entrypoint */
1088
1089         codegen_insertmethod(code->entrypoint, code->entrypoint + mcodelen);
1090
1091 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
1092         /* resolve data segment references */
1093
1094         dseg_resolve_datareferences(jd);
1095 #endif
1096
1097 #if defined(ENABLE_THREADS)
1098         /* create cirtical sections */
1099
1100         codegen_critical_section_finish(jd);
1101 #endif
1102
1103         /* flush the instruction and data caches */
1104
1105         md_cacheflush(code->mcode, code->mcodelength);
1106 }
1107
1108
1109 /* codegen_generate_stub_compiler **********************************************
1110
1111    Wrapper for codegen_emit_stub_compiler.
1112
1113    Returns:
1114        pointer to the compiler stub code.
1115
1116 *******************************************************************************/
1117
1118 u1 *codegen_generate_stub_compiler(methodinfo *m)
1119 {
1120         jitdata     *jd;
1121         codegendata *cd;
1122         ptrint      *d;                     /* pointer to data memory             */
1123         u1          *c;                     /* pointer to code memory             */
1124         s4           dumpsize;
1125
1126         /* mark dump memory */
1127
1128         dumpsize = dump_size();
1129
1130         /* allocate required data structures */
1131
1132         jd = DNEW(jitdata);
1133
1134         jd->m     = m;
1135         jd->cd    = DNEW(codegendata);
1136         jd->flags = 0;
1137
1138         /* get required compiler data */
1139
1140         cd = jd->cd;
1141
1142         /* allocate code memory */
1143
1144         c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1145
1146         /* set pointers correctly */
1147
1148         d = (ptrint *) c;
1149
1150         cd->mcodebase = c;
1151
1152         c = c + 3 * SIZEOF_VOID_P;
1153         cd->mcodeptr = c;
1154
1155         /* NOTE: The codeinfo pointer is actually a pointer to the
1156            methodinfo (this fakes a codeinfo structure). */
1157
1158         d[0] = (ptrint) asm_call_jit_compiler;
1159         d[1] = (ptrint) m;
1160         d[2] = (ptrint) &d[1];                                    /* fake code->m */
1161
1162         /* call the emit function */
1163
1164         codegen_emit_stub_compiler(jd);
1165
1166 #if defined(ENABLE_STATISTICS)
1167         if (opt_stat)
1168                 count_cstub_len += 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
1169 #endif
1170
1171         /* flush caches */
1172
1173         md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1174
1175         /* release dump memory */
1176
1177         dump_release(dumpsize);
1178
1179         /* return native stub code */
1180
1181         return c;
1182 }
1183
1184
1185 /* codegen_generate_stub_native ************************************************
1186
1187    Wrapper for codegen_emit_stub_native.
1188
1189    Returns:
1190        the codeinfo representing the stub code.
1191
1192 *******************************************************************************/
1193
1194 codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
1195 {
1196         jitdata     *jd;
1197         codeinfo    *code;
1198         s4           dumpsize;
1199         methoddesc  *md;
1200         methoddesc  *nmd;       
1201         s4           nativeparams;
1202
1203         /* mark dump memory */
1204
1205         dumpsize = dump_size();
1206
1207         jd = DNEW(jitdata);
1208
1209         jd->m     = m;
1210         jd->cd    = DNEW(codegendata);
1211         jd->rd    = DNEW(registerdata);
1212         jd->flags = 0;
1213
1214         /* Allocate codeinfo memory from the heap as we need to keep them. */
1215
1216         jd->code  = code_codeinfo_new(m); /* XXX check allocation */
1217
1218         /* get required compiler data */
1219
1220         code = jd->code;
1221
1222         /* set the flags for the current JIT run */
1223
1224 #if defined(ENABLE_PROFILING)
1225         if (opt_prof)
1226                 jd->flags |= JITDATA_FLAG_INSTRUMENT;
1227 #endif
1228
1229         if (opt_verbosecall)
1230                 jd->flags |= JITDATA_FLAG_VERBOSECALL;
1231
1232         /* setup code generation stuff */
1233
1234 #if defined(ENABLE_JIT)
1235 # if defined(ENABLE_INTRP)
1236         if (!opt_intrp)
1237 # endif
1238                 reg_setup(jd);
1239 #endif
1240
1241         codegen_setup(jd);
1242
1243         /* create new method descriptor with additional native parameters */
1244
1245         md = m->parseddesc;
1246         nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
1247         
1248         nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
1249                                                            md->paramcount * sizeof(typedesc) +
1250                                                            nativeparams * sizeof(typedesc));
1251
1252         nmd->paramcount = md->paramcount + nativeparams;
1253
1254         nmd->params = DMNEW(paramdesc, nmd->paramcount);
1255
1256         nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer            */
1257
1258         if (m->flags & ACC_STATIC)
1259                 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer              */
1260
1261         MCOPY(nmd->paramtypes + nativeparams, md->paramtypes, typedesc,
1262                   md->paramcount);
1263
1264 #if defined(ENABLE_JIT)
1265 # if defined(ENABLE_INTRP)
1266         if (!opt_intrp)
1267 # endif
1268                 /* pre-allocate the arguments for the native ABI */
1269
1270                 md_param_alloc_native(nmd);
1271 #endif
1272
1273         /* generate the code */
1274
1275 #if defined(ENABLE_JIT)
1276 # if defined(ENABLE_INTRP)
1277         if (opt_intrp)
1278                 intrp_createnativestub(f, jd, nmd);
1279         else
1280 # endif
1281                 codegen_emit_stub_native(jd, nmd, f);
1282 #else
1283         intrp_createnativestub(f, jd, nmd);
1284 #endif
1285
1286         /* reallocate the memory and finish the code generation */
1287
1288         codegen_finish(jd);
1289
1290 #if defined(ENABLE_STATISTICS)
1291         /* must be done after codegen_finish() */
1292
1293         if (opt_stat)
1294                 size_stub_native += code->mcodelength;
1295 #endif
1296
1297 #if !defined(NDEBUG)
1298         /* disassemble native stub */
1299
1300         if (opt_shownativestub) {
1301 #if defined(ENABLE_DEBUG_FILTER)
1302                 if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
1303 #endif
1304                 {
1305 #if defined(ENABLE_DISASSEMBLER)
1306                         codegen_disassemble_nativestub(m,
1307                                                                                    (u1 *) (ptrint) code->entrypoint,
1308                                                                                    (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
1309 #endif
1310
1311                         /* show data segment */
1312
1313                         if (opt_showddatasegment)
1314                                 dseg_display(jd);
1315                 }
1316         }
1317 #endif /* !defined(NDEBUG) */
1318
1319         /* release memory */
1320
1321         dump_release(dumpsize);
1322
1323         /* return native stub code */
1324
1325         return code;
1326 }
1327
1328
1329 /* codegen_disassemble_nativestub **********************************************
1330
1331    Disassembles the generated native stub.
1332
1333 *******************************************************************************/
1334
1335 #if defined(ENABLE_DISASSEMBLER)
1336 void codegen_disassemble_nativestub(methodinfo *m, u1 *start, u1 *end)
1337 {
1338         printf("Native stub: ");
1339         utf_fprint_printable_ascii_classname(stdout, m->class->name);
1340         printf(".");
1341         utf_fprint_printable_ascii(stdout, m->name);
1342         utf_fprint_printable_ascii(stdout, m->descriptor);
1343         printf("\n\nLength: %d\n\n", (s4) (end - start));
1344
1345         DISASSEMBLE(start, end);
1346 }
1347 #endif
1348
1349
1350 /* codegen_start_native_call ***************************************************
1351
1352    Prepares the stuff required for a native (JNI) function call:
1353
1354    - adds a stackframe info structure to the chain, for stacktraces
1355    - prepares the local references table on the stack
1356
1357    The layout of the native stub stackframe should look like this:
1358
1359    +---------------------------+ <- SP (of parent Java function)
1360    | return address            |
1361    +---------------------------+
1362    |                           |
1363    | stackframe info structure |
1364    |                           |
1365    +---------------------------+
1366    |                           |
1367    | local references table    |
1368    |                           |
1369    +---------------------------+
1370    |                           |
1371    | arguments (if any)        |
1372    |                           |
1373    +---------------------------+ <- SP (native stub)
1374
1375 *******************************************************************************/
1376
1377 void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
1378 {
1379         stackframeinfo *sfi;
1380         localref_table *lrt;
1381
1382         STATISTICS(count_calls_java_to_native++);
1383
1384         /* get data structures from stack */
1385
1386         sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1387         lrt = (localref_table *) (datasp - sizeof(stackframeinfo) - 
1388                                                           sizeof(localref_table));
1389
1390         /* add a stackframeinfo to the chain */
1391
1392         stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
1393
1394 #if defined(ENABLE_JNI)
1395         /* add current JNI local references table to this thread */
1396
1397         localref_table_add(lrt);
1398 #endif
1399 }
1400
1401
1402 /* codegen_finish_native_call **************************************************
1403
1404    Removes the stuff required for a native (JNI) function call.
1405    Additionally it checks for an exceptions and in case, get the
1406    exception object and clear the pointer.
1407
1408 *******************************************************************************/
1409
1410 java_object_t *codegen_finish_native_call(u1 *datasp)
1411 {
1412         stackframeinfo  *sfi;
1413         stackframeinfo **psfi;
1414         java_handle_t   *e;
1415
1416         /* get data structures from stack */
1417
1418         sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1419
1420         /* remove current stackframeinfo from chain */
1421
1422         psfi = &STACKFRAMEINFO;
1423
1424         *psfi = sfi->prev;
1425
1426 #if defined(ENABLE_JNI)
1427         /* release JNI local references table for this thread */
1428
1429         localref_frame_pop_all();
1430         localref_table_remove();
1431 #endif
1432
1433         /* get the exception and return it */
1434
1435         e = exceptions_get_and_clear_exception();
1436
1437         return e;
1438 }
1439
1440
1441 /* removecompilerstub **********************************************************
1442
1443    Deletes a compilerstub from memory (simply by freeing it).
1444
1445 *******************************************************************************/
1446
1447 void removecompilerstub(u1 *stub)
1448 {
1449         /* pass size 1 to keep the intern function happy */
1450
1451         CFREE((void *) stub, 1);
1452 }
1453
1454
1455 /* removenativestub ************************************************************
1456
1457    Removes a previously created native-stub from memory.
1458     
1459 *******************************************************************************/
1460
1461 void removenativestub(u1 *stub)
1462 {
1463         /* pass size 1 to keep the intern function happy */
1464
1465         CFREE((void *) stub, 1);
1466 }
1467
1468
1469 /* codegen_reg_of_var **********************************************************
1470
1471    This function determines a register, to which the result of an
1472    operation should go, when it is ultimatively intended to store the
1473    result in pseudoregister v.  If v is assigned to an actual
1474    register, this register will be returned.  Otherwise (when v is
1475    spilled) this function returns tempregnum.  If not already done,
1476    regoff and flags are set in the stack location.
1477        
1478 *******************************************************************************/
1479
1480 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
1481 {
1482
1483 #if 0
1484         /* Do we have to generate a conditional move?  Yes, then always
1485            return the temporary register.  The real register is identified
1486            during the store. */
1487
1488         if (opcode & ICMD_CONDITION_MASK)
1489                 return tempregnum;
1490 #endif
1491
1492         if (!(v->flags & INMEMORY))
1493                 return v->vv.regoff;
1494
1495         return tempregnum;
1496 }
1497
1498
1499 /* codegen_reg_of_dst **********************************************************
1500
1501    This function determines a register, to which the result of an
1502    operation should go, when it is ultimatively intended to store the
1503    result in iptr->dst.var.  If dst.var is assigned to an actual
1504    register, this register will be returned.  Otherwise (when it is
1505    spilled) this function returns tempregnum.  If not already done,
1506    regoff and flags are set in the stack location.
1507        
1508 *******************************************************************************/
1509
1510 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
1511 {
1512         return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
1513 }
1514
1515
1516 /* codegen_emit_phi_moves ****************************************************
1517
1518    Emits phi moves at the end of the basicblock.
1519
1520 *******************************************************************************/
1521
1522 #if defined(ENABLE_SSA)
1523 void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
1524 {
1525         int lt_d,lt_s,i;
1526         lsradata *ls;
1527         codegendata *cd;
1528         varinfo *s, *d;
1529         instruction tmp_i;
1530
1531         cd = jd->cd;
1532         ls = jd->ls;
1533
1534         MCODECHECK(512);
1535
1536         /* Moves from phi functions with highest indices have to be */
1537         /* inserted first, since this is the order as is used for   */
1538         /* conflict resolution */
1539
1540         for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
1541                 lt_d = ls->phi_moves[bptr->nr][i][0];
1542                 lt_s = ls->phi_moves[bptr->nr][i][1];
1543 #if defined(SSA_DEBUG_VERBOSE)
1544                 if (compileverbose)
1545                         printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
1546 #endif
1547                 if (lt_s == UNUSED) {
1548 #if defined(SSA_DEBUG_VERBOSE)
1549                 if (compileverbose)
1550                         printf(" ... not processed \n");
1551 #endif
1552                         continue;
1553                 }
1554                         
1555                 d = VAR(ls->lifetime[lt_d].v_index);
1556                 s = VAR(ls->lifetime[lt_s].v_index);
1557                 
1558
1559                 if (d->type == -1) {
1560 #if defined(SSA_DEBUG_VERBOSE)
1561                         if (compileverbose)
1562                                 printf("...returning - phi lifetimes where joined\n");
1563 #endif
1564                         return;
1565                 }
1566
1567                 if (s->type == -1) {
1568 #if defined(SSA_DEBUG_VERBOSE)
1569                         if (compileverbose)
1570                                 printf("...returning - phi lifetimes where joined\n");
1571 #endif
1572                         return;
1573                 }
1574
1575                 tmp_i.opc = 0;
1576                 tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
1577                 tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
1578                 emit_copy(jd, &tmp_i);
1579
1580 #if defined(SSA_DEBUG_VERBOSE)
1581                 if (compileverbose) {
1582                         if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
1583                                 /* mem -> mem */
1584                                 printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1585                         }
1586                         else if (IS_INMEMORY(s->flags)) {
1587                                 /* mem -> reg */
1588                                 printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1589                         }
1590                         else if (IS_INMEMORY(d->flags)) {
1591                                 /* reg -> mem */
1592                                 printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1593                         }
1594                         else {
1595                                 /* reg -> reg */
1596                                 printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1597                         }
1598                         printf("\n");
1599                 }
1600 #endif /* defined(SSA_DEBUG_VERBOSE) */
1601         }
1602 }
1603 #endif /* defined(ENABLE_SSA) */
1604
1605
1606
1607 /*
1608  * These are local overrides for various environment variables in Emacs.
1609  * Please do not remove this and leave it at the end of the file, where
1610  * Emacs will automagically detect them.
1611  * ---------------------------------------------------------------------
1612  * Local variables:
1613  * mode: c
1614  * indent-tabs-mode: t
1615  * c-basic-offset: 4
1616  * tab-width: 4
1617  * End:
1618  * vim:noexpandtab:sw=4:ts=4:
1619  */