* src/vm/jit/m68k/md.c (md_codegen_patch_branch): Removed.
[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 *currentsp, u1 *pv)
1531 {
1532         stackframeinfo *sfi;
1533         localref_table *lrt;
1534         codeinfo       *code;
1535         methodinfo     *m;
1536         int32_t         framesize;
1537
1538         uint8_t  *datasp;
1539         uint8_t  *javasp;
1540         uint8_t  *javara;
1541         uint64_t *arg_regs;
1542         uint64_t *arg_stack;
1543
1544         STATISTICS(count_calls_java_to_native++);
1545
1546         /* get information from method header */
1547
1548         code      = *((codeinfo **) (pv + CodeinfoPointer));
1549         framesize = *((int32_t *)   (pv + FrameSize));
1550         assert(code);
1551         assert(framesize >= sizeof(stackframeinfo) + sizeof(localref_table));
1552
1553         /* get the methodinfo */
1554
1555         m = code->m;
1556         assert(m);
1557
1558         /* calculate needed values */
1559
1560 #if defined(__ALPHA__) || defined(__ARM__)
1561         datasp    = currentsp + framesize - SIZEOF_VOID_P;
1562         javasp    = currentsp + framesize;
1563         javara    = *((uint8_t **) datasp);
1564         arg_regs  = (uint64_t *) currentsp;
1565         arg_stack = (uint64_t *) javasp;
1566 #elif defined(__MIPS__)
1567         /* MIPS always uses 8 bytes to store the RA */
1568         datasp    = currentsp + framesize - 8;
1569         javasp    = currentsp + framesize;
1570         javara    = *((uint8_t **) datasp);
1571 #elif defined(__S390__)
1572         datasp    = currentsp + framesize - 8;
1573         javasp    = currentsp + framesize;
1574         javara    = *((uint8_t **) datasp);
1575         arg_regs  = (uint64_t *) (currentsp + 96);
1576         arg_stack = (uint64_t *) javasp;
1577 #elif defined(__I386__) || defined(__M68K__) || defined(__X86_64__)
1578         datasp    = currentsp + framesize;
1579         javasp    = currentsp + framesize + SIZEOF_VOID_P;
1580         javara    = *((uint8_t **) datasp);
1581         arg_regs  = (uint64_t *) currentsp;
1582         arg_stack = (uint64_t *) javasp;
1583 #elif defined(__POWERPC__)
1584         datasp    = currentsp + framesize;
1585         javasp    = currentsp + framesize;
1586         javara    = *((uint8_t **) (datasp + LA_LR_OFFSET));
1587         arg_regs  = (uint64_t *) (currentsp + LA_SIZE + 4 * SIZEOF_VOID_P);
1588         arg_stack = (uint64_t *) javasp;
1589 #elif defined(__POWERPC64__)
1590         datasp    = currentsp + framesize;
1591         javasp    = currentsp + framesize;
1592         javara    = *((uint8_t **) (datasp + LA_LR_OFFSET));
1593         arg_regs  = (uint64_t *) (currentsp + PA_SIZE + LA_SIZE + 4 * SIZEOF_VOID_P);
1594         arg_stack = (uint64_t *) javasp;
1595 #else
1596         /* XXX is was unable to do this port for SPARC64, sorry. (-michi) */
1597         /* XXX maybe we need to pass the RA as argument there */
1598         vm_abort("codegen_start_native_call: unsupported architecture");
1599 #endif
1600
1601         /* get data structures from stack */
1602
1603         sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1604         lrt = (localref_table *) (datasp - sizeof(stackframeinfo) - 
1605                                                           sizeof(localref_table));
1606
1607 #if defined(ENABLE_JNI)
1608         /* add current JNI local references table to this thread */
1609
1610         localref_table_add(lrt);
1611 #endif
1612
1613 #if !defined(NDEBUG)
1614 # if defined(__ALPHA__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__X86_64__) || defined(__S390__)
1615         /* print the call-trace if necesarry */
1616         /* BEFORE: filling the local reference table */
1617
1618         if (opt_TraceJavaCalls)
1619                 trace_java_call_enter(m, arg_regs, arg_stack);
1620 # endif
1621 #endif
1622
1623 #if defined(ENABLE_HANDLES)
1624         /* place all references into the local reference table */
1625         /* BEFORE: creating stackframeinfo */
1626
1627         localref_native_enter(m, arg_regs, arg_stack);
1628 #endif
1629
1630         /* add a stackframeinfo to the chain */
1631
1632         stacktrace_create_native_stackframeinfo(sfi, pv, javasp, javara);
1633
1634         /* return a wrapped classinfo for static native methods */
1635
1636         if (m->flags & ACC_STATIC)
1637                 return LLNI_classinfo_wrap(m->class);
1638         else
1639                 return NULL;
1640 }
1641
1642
1643 /* codegen_finish_native_call **************************************************
1644
1645    Removes the stuff required for a native (JNI) function call.
1646    Additionally it checks for an exceptions and in case, get the
1647    exception object and clear the pointer.
1648
1649 *******************************************************************************/
1650
1651 java_object_t *codegen_finish_native_call(u1 *currentsp, u1 *pv)
1652 {
1653         stackframeinfo *sfi;
1654         java_handle_t  *e;
1655         java_object_t  *o;
1656         codeinfo       *code;
1657         methodinfo     *m;
1658         int32_t         framesize;
1659
1660         uint8_t  *datasp;
1661         uint64_t *ret_regs;
1662
1663         /* get information from method header */
1664
1665         code      = *((codeinfo **) (pv + CodeinfoPointer));
1666         framesize = *((int32_t *)   (pv + FrameSize));
1667         assert(code);
1668
1669         /* get the methodinfo */
1670
1671         m = code->m;
1672         assert(m);
1673
1674         /* calculate needed values */
1675
1676 #if defined(__ALPHA__) || defined(__ARM__)
1677         datasp   = currentsp + framesize - SIZEOF_VOID_P;
1678         ret_regs = (uint64_t *) currentsp;
1679 #elif defined(__MIPS__)
1680         /* MIPS always uses 8 bytes to store the RA */
1681         datasp   = currentsp + framesize - 8;
1682 #elif defined(__S390__)
1683         datasp   = currentsp + framesize - 8;
1684         ret_regs = (uint64_t *) (currentsp + 96);
1685 #elif defined(__I386__)
1686         datasp   = currentsp + framesize;
1687         ret_regs = (uint64_t *) (currentsp + 2 * SIZEOF_VOID_P);
1688 #elif defined(__M68K__) || defined(__X86_64__)
1689         datasp   = currentsp + framesize;
1690         ret_regs = (uint64_t *) currentsp;
1691 #elif defined(__POWERPC__)
1692         datasp   = currentsp + framesize;
1693         ret_regs = (uint64_t *) (currentsp + LA_SIZE + 2 * SIZEOF_VOID_P);
1694 #elif defined(__POWERPC64__)
1695         datasp   = currentsp + framesize;
1696         ret_regs = (uint64_t *) (currentsp + PA_SIZE + LA_SIZE + 2 * SIZEOF_VOID_P);
1697 #else
1698         vm_abort("codegen_finish_native_call: unsupported architecture");
1699 #endif
1700
1701         /* get data structures from stack */
1702
1703         sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1704
1705         /* remove current stackframeinfo from chain */
1706
1707         stacktrace_remove_stackframeinfo(sfi);
1708
1709 #if defined(ENABLE_HANDLES)
1710         /* unwrap the return value from the local reference table */
1711         /* AFTER: removing the stackframeinfo */
1712         /* BEFORE: releasing the local reference table */
1713
1714         localref_native_exit(m, ret_regs);
1715 #endif
1716
1717         /* get and unwrap the exception */
1718         /* AFTER: removing the stackframe info */
1719         /* BEFORE: releasing the local reference table */
1720
1721         e = exceptions_get_and_clear_exception();
1722         o = LLNI_UNWRAP(e);
1723
1724 #if defined(ENABLE_JNI)
1725         /* release JNI local references table for this thread */
1726
1727         localref_frame_pop_all();
1728         localref_table_remove();
1729 #endif
1730
1731 #if !defined(NDEBUG)
1732 # if defined(__ALPHA__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__X86_64__) || defined(__S390__)
1733         /* print the call-trace if necesarry */
1734         /* AFTER: unwrapping the return value */
1735
1736         if (opt_TraceJavaCalls)
1737                 trace_java_call_exit(m, ret_regs);
1738 # endif
1739 #endif
1740
1741         return o;
1742 }
1743
1744
1745 /* removecompilerstub **********************************************************
1746
1747    Deletes a compilerstub from memory (simply by freeing it).
1748
1749 *******************************************************************************/
1750
1751 void removecompilerstub(u1 *stub)
1752 {
1753         /* pass size 1 to keep the intern function happy */
1754
1755         CFREE((void *) stub, 1);
1756 }
1757
1758
1759 /* removenativestub ************************************************************
1760
1761    Removes a previously created native-stub from memory.
1762     
1763 *******************************************************************************/
1764
1765 void removenativestub(u1 *stub)
1766 {
1767         /* pass size 1 to keep the intern function happy */
1768
1769         CFREE((void *) stub, 1);
1770 }
1771
1772
1773 /* codegen_reg_of_var **********************************************************
1774
1775    This function determines a register, to which the result of an
1776    operation should go, when it is ultimatively intended to store the
1777    result in pseudoregister v.  If v is assigned to an actual
1778    register, this register will be returned.  Otherwise (when v is
1779    spilled) this function returns tempregnum.  If not already done,
1780    regoff and flags are set in the stack location.
1781        
1782 *******************************************************************************/
1783
1784 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
1785 {
1786
1787 #if 0
1788         /* Do we have to generate a conditional move?  Yes, then always
1789            return the temporary register.  The real register is identified
1790            during the store. */
1791
1792         if (opcode & ICMD_CONDITION_MASK)
1793                 return tempregnum;
1794 #endif
1795
1796         if (!(v->flags & INMEMORY))
1797                 return v->vv.regoff;
1798
1799         return tempregnum;
1800 }
1801
1802
1803 /* codegen_reg_of_dst **********************************************************
1804
1805    This function determines a register, to which the result of an
1806    operation should go, when it is ultimatively intended to store the
1807    result in iptr->dst.var.  If dst.var is assigned to an actual
1808    register, this register will be returned.  Otherwise (when it is
1809    spilled) this function returns tempregnum.  If not already done,
1810    regoff and flags are set in the stack location.
1811        
1812 *******************************************************************************/
1813
1814 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
1815 {
1816         return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
1817 }
1818
1819
1820 /* codegen_emit_phi_moves ****************************************************
1821
1822    Emits phi moves at the end of the basicblock.
1823
1824 *******************************************************************************/
1825
1826 #if defined(ENABLE_SSA)
1827 void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
1828 {
1829         int lt_d,lt_s,i;
1830         lsradata *ls;
1831         codegendata *cd;
1832         varinfo *s, *d;
1833         instruction tmp_i;
1834
1835         cd = jd->cd;
1836         ls = jd->ls;
1837
1838         MCODECHECK(512);
1839
1840         /* Moves from phi functions with highest indices have to be */
1841         /* inserted first, since this is the order as is used for   */
1842         /* conflict resolution */
1843
1844         for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
1845                 lt_d = ls->phi_moves[bptr->nr][i][0];
1846                 lt_s = ls->phi_moves[bptr->nr][i][1];
1847 #if defined(SSA_DEBUG_VERBOSE)
1848                 if (compileverbose)
1849                         printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
1850 #endif
1851                 if (lt_s == UNUSED) {
1852 #if defined(SSA_DEBUG_VERBOSE)
1853                 if (compileverbose)
1854                         printf(" ... not processed \n");
1855 #endif
1856                         continue;
1857                 }
1858                         
1859                 d = VAR(ls->lifetime[lt_d].v_index);
1860                 s = VAR(ls->lifetime[lt_s].v_index);
1861                 
1862
1863                 if (d->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                 if (s->type == -1) {
1872 #if defined(SSA_DEBUG_VERBOSE)
1873                         if (compileverbose)
1874                                 printf("...returning - phi lifetimes where joined\n");
1875 #endif
1876                         return;
1877                 }
1878
1879                 tmp_i.opc = 0;
1880                 tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
1881                 tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
1882                 emit_copy(jd, &tmp_i);
1883
1884 #if defined(SSA_DEBUG_VERBOSE)
1885                 if (compileverbose) {
1886                         if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
1887                                 /* mem -> mem */
1888                                 printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1889                         }
1890                         else if (IS_INMEMORY(s->flags)) {
1891                                 /* mem -> reg */
1892                                 printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1893                         }
1894                         else if (IS_INMEMORY(d->flags)) {
1895                                 /* reg -> mem */
1896                                 printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1897                         }
1898                         else {
1899                                 /* reg -> reg */
1900                                 printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1901                         }
1902                         printf("\n");
1903                 }
1904 #endif /* defined(SSA_DEBUG_VERBOSE) */
1905         }
1906 }
1907 #endif /* defined(ENABLE_SSA) */
1908
1909
1910
1911 /*
1912  * These are local overrides for various environment variables in Emacs.
1913  * Please do not remove this and leave it at the end of the file, where
1914  * Emacs will automagically detect them.
1915  * ---------------------------------------------------------------------
1916  * Local variables:
1917  * mode: c
1918  * indent-tabs-mode: t
1919  * c-basic-offset: 4
1920  * tab-width: 4
1921  * End:
1922  * vim:noexpandtab:sw=4:ts=4:
1923  */