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