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