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