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