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