* src/vm/jit/codegen-common.c (codegen_start_native_call, codegen_finish_native_call...
[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         /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
936
937         cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
938 }
939 #endif /* defined(ENABLE_REPLACEMENT) */
940
941
942 /* codegen_finish **************************************************************
943
944    Finishes the code generation. A new memory, large enough for both
945    data and code, is allocated and data and code are copied together
946    to their final layout, unresolved jumps are resolved, ...
947
948 *******************************************************************************/
949
950 void codegen_finish(jitdata *jd)
951 {
952         codeinfo    *code;
953         codegendata *cd;
954         s4           mcodelen;
955 #if defined(ENABLE_INTRP)
956         s4           ncodelen;
957 #endif
958         s4           alignedmcodelen;
959         jumpref     *jr;
960         patchref_t  *pr;
961         u1          *epoint;
962         s4           alignedlen;
963
964         /* get required compiler data */
965
966         code = jd->code;
967         cd   = jd->cd;
968
969         /* prevent compiler warning */
970
971 #if defined(ENABLE_INTRP)
972         ncodelen = 0;
973 #endif
974
975         /* calculate the code length */
976
977         mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
978
979 #if defined(ENABLE_STATISTICS)
980         if (opt_stat) {
981                 count_code_len += mcodelen;
982                 count_data_len += cd->dseglen;
983         }
984 #endif
985
986         alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
987
988 #if defined(ENABLE_INTRP)
989         if (opt_intrp)
990                 ncodelen = cd->ncodeptr - cd->ncodebase;
991         else {
992                 ncodelen = 0; /* avoid compiler warning */
993         }
994 #endif
995
996         cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
997         alignedlen = alignedmcodelen + cd->dseglen;
998
999 #if defined(ENABLE_INTRP)
1000         if (opt_intrp) {
1001                 alignedlen += ncodelen;
1002         }
1003 #endif
1004
1005         /* allocate new memory */
1006
1007         code->mcodelength = mcodelen + cd->dseglen;
1008         code->mcode       = CNEW(u1, alignedlen);
1009
1010         /* set the entrypoint of the method */
1011         
1012         assert(code->entrypoint == NULL);
1013         code->entrypoint = epoint = (code->mcode + cd->dseglen);
1014
1015         /* fill the data segment (code->entrypoint must already be set!) */
1016
1017         dseg_finish(jd);
1018
1019         /* copy code to the new location */
1020
1021         MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
1022
1023 #if defined(ENABLE_INTRP)
1024         /* relocate native dynamic superinstruction code (if any) */
1025
1026         if (opt_intrp) {
1027                 cd->mcodebase = code->entrypoint;
1028
1029                 if (ncodelen > 0) {
1030                         u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
1031
1032                         MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
1033
1034                         /* flush the instruction and data caches */
1035
1036                         md_cacheflush(ncodebase, ncodelen);
1037
1038                         /* set some cd variables for dynamic_super_rerwite */
1039
1040                         cd->ncodebase = ncodebase;
1041
1042                 } else {
1043                         cd->ncodebase = NULL;
1044                 }
1045
1046                 dynamic_super_rewrite(cd);
1047         }
1048 #endif
1049
1050         /* jump table resolving */
1051
1052         for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
1053                 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
1054                         (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
1055
1056         /* line number table resolving */
1057         {
1058                 linenumberref *lr;
1059                 ptrint lrtlen = 0;
1060                 ptrint target;
1061
1062                 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
1063                         lrtlen++;
1064                         target = lr->targetmpc;
1065                         /* if the entry contains an mcode pointer (normal case), resolve it */
1066                         /* (see doc/inlining_stacktrace.txt for details)                    */
1067                         if (lr->linenumber >= -2) {
1068                             target += (ptrint) epoint;
1069                         }
1070                         *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) = 
1071                                 (functionptr) target;
1072                 }
1073                 
1074                 *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
1075                         (functionptr) ((ptrint) epoint + cd->linenumbertab);
1076
1077                 *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
1078         }
1079
1080         /* patcher resolving */
1081
1082         pr = list_first_unsynced(code->patchers);
1083         while (pr) {
1084                 pr->mpc += (ptrint) epoint;
1085                 pr->datap = (ptrint) (pr->disp + epoint);
1086                 pr = list_next_unsynced(code->patchers, pr);
1087         }
1088
1089 #if defined(ENABLE_REPLACEMENT)
1090         /* replacement point resolving */
1091         {
1092                 int i;
1093                 rplpoint *rp;
1094
1095                 rp = code->rplpoints;
1096                 for (i=0; i<code->rplpointcount; ++i, ++rp) {
1097                         rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
1098                 }
1099         }
1100 #endif /* defined(ENABLE_REPLACEMENT) */
1101
1102         /* add method into methodtree to find the entrypoint */
1103
1104         codegen_insertmethod(code->entrypoint, code->entrypoint + mcodelen);
1105
1106 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
1107         /* resolve data segment references */
1108
1109         dseg_resolve_datareferences(jd);
1110 #endif
1111
1112 #if defined(ENABLE_THREADS)
1113         /* create cirtical sections */
1114
1115         codegen_critical_section_finish(jd);
1116 #endif
1117
1118         /* flush the instruction and data caches */
1119
1120         md_cacheflush(code->mcode, code->mcodelength);
1121 }
1122
1123
1124 /* codegen_generate_stub_compiler **********************************************
1125
1126    Wrapper for codegen_emit_stub_compiler.
1127
1128    Returns:
1129        pointer to the compiler stub code.
1130
1131 *******************************************************************************/
1132
1133 u1 *codegen_generate_stub_compiler(methodinfo *m)
1134 {
1135         jitdata     *jd;
1136         codegendata *cd;
1137         ptrint      *d;                     /* pointer to data memory             */
1138         u1          *c;                     /* pointer to code memory             */
1139         s4           dumpsize;
1140
1141         /* mark dump memory */
1142
1143         dumpsize = dump_size();
1144
1145         /* allocate required data structures */
1146
1147         jd = DNEW(jitdata);
1148
1149         jd->m     = m;
1150         jd->cd    = DNEW(codegendata);
1151         jd->flags = 0;
1152
1153         /* get required compiler data */
1154
1155         cd = jd->cd;
1156
1157         /* allocate code memory */
1158
1159         c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1160
1161         /* set pointers correctly */
1162
1163         d = (ptrint *) c;
1164
1165         cd->mcodebase = c;
1166
1167         c = c + 3 * SIZEOF_VOID_P;
1168         cd->mcodeptr = c;
1169
1170         /* NOTE: The codeinfo pointer is actually a pointer to the
1171            methodinfo (this fakes a codeinfo structure). */
1172
1173         d[0] = (ptrint) asm_call_jit_compiler;
1174         d[1] = (ptrint) m;
1175         d[2] = (ptrint) &d[1];                                    /* fake code->m */
1176
1177         /* call the emit function */
1178
1179         codegen_emit_stub_compiler(jd);
1180
1181 #if defined(ENABLE_STATISTICS)
1182         if (opt_stat)
1183                 count_cstub_len += 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
1184 #endif
1185
1186         /* flush caches */
1187
1188         md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1189
1190         /* release dump memory */
1191
1192         dump_release(dumpsize);
1193
1194         /* return native stub code */
1195
1196         return c;
1197 }
1198
1199
1200 /* codegen_generate_stub_builtin ***********************************************
1201
1202    Wrapper for codegen_emit_stub_native.
1203
1204 *******************************************************************************/
1205
1206 void codegen_generate_stub_builtin(methodinfo *m, builtintable_entry *bte)
1207 {
1208         jitdata  *jd;
1209         codeinfo *code;
1210         int       skipparams;
1211         s4        dumpsize;
1212
1213         /* mark dump memory */
1214
1215         dumpsize = dump_size();
1216
1217         jd = DNEW(jitdata);
1218
1219         jd->m     = m;
1220         jd->cd    = DNEW(codegendata);
1221         jd->rd    = NULL;
1222         jd->flags = 0;
1223
1224         /* Allocate codeinfo memory from the heap as we need to keep them. */
1225
1226         jd->code  = code_codeinfo_new(m);
1227
1228         /* get required compiler data */
1229
1230         code = jd->code;
1231
1232         /* setup code generation stuff */
1233
1234         codegen_setup(jd);
1235
1236         /* Set the number of native arguments we need to skip. */
1237
1238         skipparams = 0;
1239
1240         /* generate the code */
1241
1242 #if defined(ENABLE_JIT)
1243 # if defined(ENABLE_INTRP)
1244         if (!opt_intrp) {
1245 # endif
1246                 assert(bte->fp != NULL);
1247                 codegen_emit_stub_native(jd, bte->md, bte->fp, skipparams);
1248 # if defined(ENABLE_INTRP)
1249         }
1250 # endif
1251 #endif
1252
1253         /* reallocate the memory and finish the code generation */
1254
1255         codegen_finish(jd);
1256
1257         /* set the stub entry point in the builtin table */
1258
1259         bte->stub = code->entrypoint;
1260
1261 #if defined(ENABLE_STATISTICS)
1262         if (opt_stat)
1263                 size_stub_native += code->mcodelength;
1264 #endif
1265
1266 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
1267         /* disassemble native stub */
1268
1269         if (opt_DisassembleStubs) {
1270                 codegen_disassemble_stub(m,
1271                                                                  (u1 *) (ptrint) code->entrypoint,
1272                                                                  (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
1273
1274                 /* show data segment */
1275
1276                 if (opt_showddatasegment)
1277                         dseg_display(jd);
1278         }
1279 #endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
1280
1281         /* release memory */
1282
1283         dump_release(dumpsize);
1284 }
1285
1286
1287 /* codegen_generate_stub_native ************************************************
1288
1289    Wrapper for codegen_emit_stub_native.
1290
1291    Returns:
1292        the codeinfo representing the stub code.
1293
1294 *******************************************************************************/
1295
1296 codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
1297 {
1298         jitdata     *jd;
1299         codeinfo    *code;
1300         s4           dumpsize;
1301         methoddesc  *md;
1302         methoddesc  *nmd;       
1303         int          skipparams;
1304
1305         /* mark dump memory */
1306
1307         dumpsize = dump_size();
1308
1309         jd = DNEW(jitdata);
1310
1311         jd->m     = m;
1312         jd->cd    = DNEW(codegendata);
1313         jd->rd    = DNEW(registerdata);
1314         jd->flags = 0;
1315
1316         /* Allocate codeinfo memory from the heap as we need to keep them. */
1317
1318         jd->code  = code_codeinfo_new(m);
1319
1320         /* get required compiler data */
1321
1322         code = jd->code;
1323
1324         /* set the flags for the current JIT run */
1325
1326 #if defined(ENABLE_PROFILING)
1327         if (opt_prof)
1328                 jd->flags |= JITDATA_FLAG_INSTRUMENT;
1329 #endif
1330
1331         if (opt_verbosecall)
1332                 jd->flags |= JITDATA_FLAG_VERBOSECALL;
1333
1334         /* setup code generation stuff */
1335
1336 #if defined(ENABLE_JIT)
1337 # if defined(ENABLE_INTRP)
1338         if (!opt_intrp)
1339 # endif
1340                 reg_setup(jd);
1341 #endif
1342
1343         codegen_setup(jd);
1344
1345         /* create new method descriptor with additional native parameters */
1346
1347         md = m->parseddesc;
1348
1349         /* Set the number of native arguments we need to skip. */
1350
1351         if (m->flags & ACC_STATIC)
1352                 skipparams = 2;
1353         else
1354                 skipparams = 1;
1355         
1356         nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
1357                                                            md->paramcount * sizeof(typedesc) +
1358                                                            skipparams * sizeof(typedesc));
1359
1360         nmd->paramcount = md->paramcount + skipparams;
1361
1362         nmd->params = DMNEW(paramdesc, nmd->paramcount);
1363
1364         nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer            */
1365
1366         if (m->flags & ACC_STATIC)
1367                 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer              */
1368
1369         MCOPY(nmd->paramtypes + skipparams, md->paramtypes, typedesc,
1370                   md->paramcount);
1371
1372 #if defined(ENABLE_JIT)
1373 # if defined(ENABLE_INTRP)
1374         if (!opt_intrp)
1375 # endif
1376                 /* pre-allocate the arguments for the native ABI */
1377
1378                 md_param_alloc_native(nmd);
1379 #endif
1380
1381         /* generate the code */
1382
1383 #if defined(ENABLE_JIT)
1384 # if defined(ENABLE_INTRP)
1385         if (opt_intrp)
1386                 intrp_createnativestub(f, jd, nmd);
1387         else
1388 # endif
1389                 codegen_emit_stub_native(jd, nmd, f, skipparams);
1390 #else
1391         intrp_createnativestub(f, jd, nmd);
1392 #endif
1393
1394         /* reallocate the memory and finish the code generation */
1395
1396         codegen_finish(jd);
1397
1398 #if defined(ENABLE_STATISTICS)
1399         /* must be done after codegen_finish() */
1400
1401         if (opt_stat)
1402                 size_stub_native += code->mcodelength;
1403 #endif
1404
1405 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
1406         /* disassemble native stub */
1407
1408         if (opt_DisassembleStubs) {
1409 # if defined(ENABLE_DEBUG_FILTER)
1410                 if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
1411 # endif
1412                 {
1413                         codegen_disassemble_stub(m,
1414                                                                          (u1 *) (ptrint) code->entrypoint,
1415                                                                          (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
1416
1417                         /* show data segment */
1418
1419                         if (opt_showddatasegment)
1420                                 dseg_display(jd);
1421                 }
1422         }
1423 #endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
1424
1425         /* release memory */
1426
1427         dump_release(dumpsize);
1428
1429         /* return native stub code */
1430
1431         return code;
1432 }
1433
1434
1435 /* codegen_disassemble_nativestub **********************************************
1436
1437    Disassembles the generated builtin or native stub.
1438
1439 *******************************************************************************/
1440
1441 #if defined(ENABLE_DISASSEMBLER)
1442 void codegen_disassemble_stub(methodinfo *m, u1 *start, u1 *end)
1443 {
1444         printf("Stub code: ");
1445         if (m->class != NULL)
1446                 utf_fprint_printable_ascii_classname(stdout, m->class->name);
1447         else
1448                 printf("NULL");
1449         printf(".");
1450         utf_fprint_printable_ascii(stdout, m->name);
1451         utf_fprint_printable_ascii(stdout, m->descriptor);
1452         printf("\nLength: %d\n\n", (s4) (end - start));
1453
1454         DISASSEMBLE(start, end);
1455 }
1456 #endif
1457
1458
1459 /* codegen_start_native_call ***************************************************
1460
1461    Prepares the stuff required for a native (JNI) function call:
1462
1463    - adds a stackframe info structure to the chain, for stacktraces
1464    - prepares the local references table on the stack
1465
1466    The layout of the native stub stackframe should look like this:
1467
1468    +---------------------------+ <- java SP (of parent Java function)
1469    | return address            |
1470    +---------------------------+ <- data SP
1471    |                           |
1472    | stackframe info structure |
1473    |                           |
1474    +---------------------------+
1475    |                           |
1476    | local references table    |
1477    |                           |
1478    +---------------------------+
1479    |                           |
1480    | saved registers (if any)  |
1481    |                           |
1482    +---------------------------+
1483    |                           |
1484    | arguments (if any)        |
1485    |                           |
1486    +---------------------------+ <- current SP (native stub)
1487
1488 *******************************************************************************/
1489
1490 java_handle_t *codegen_start_native_call(u1 *currentsp, u1 *pv)
1491 {
1492         stackframeinfo *sfi;
1493         localref_table *lrt;
1494         codeinfo       *code;
1495         methodinfo     *m;
1496         int32_t         framesize;
1497
1498         uint8_t  *datasp;
1499         uint8_t  *javasp;
1500         uint8_t  *javara;
1501         uint64_t *arg_regs;
1502         uint64_t *arg_stack;
1503
1504         STATISTICS(count_calls_java_to_native++);
1505
1506         /* get information from method header */
1507
1508         code      = *((codeinfo **) (pv + CodeinfoPointer));
1509         framesize = *((int32_t *)   (pv + FrameSize));
1510         assert(code);
1511         assert(framesize >= sizeof(stackframeinfo) + sizeof(localref_table));
1512
1513         /* get the methodinfo */
1514
1515         m = code->m;
1516         assert(m);
1517
1518         /* calculate needed values */
1519
1520 #if defined(__ALPHA__) || defined(__ARM__)
1521         datasp    = currentsp + framesize - SIZEOF_VOID_P;
1522         javasp    = currentsp + framesize;
1523         javara    = *((uint8_t **) datasp);
1524         arg_regs  = (uint64_t *) currentsp;
1525         arg_stack = (uint64_t *) javasp;
1526 #elif defined(__MIPS__)
1527         /* MIPS always uses 8 bytes to store the RA */
1528         datasp    = currentsp + framesize - 8;
1529         javasp    = currentsp + framesize;
1530         javara    = *((uint8_t **) datasp);
1531 #elif defined(__S390__)
1532         datasp    = currentsp + framesize - 8;
1533         javasp    = currentsp + framesize;
1534         javara    = *((uint8_t **) datasp);
1535         arg_regs  = (uint64_t *) (currentsp + 96);
1536         arg_stack = (uint64_t *) javasp;
1537 #elif defined(__I386__) || defined(__M68K__) || defined(__X86_64__)
1538         datasp    = currentsp + framesize;
1539         javasp    = currentsp + framesize + SIZEOF_VOID_P;
1540         javara    = *((uint8_t **) datasp);
1541         arg_regs  = (uint64_t *) currentsp;
1542         arg_stack = (uint64_t *) javasp;
1543 #elif defined(__POWERPC__)
1544         datasp    = currentsp + framesize;
1545         javasp    = currentsp + framesize;
1546         javara    = *((uint8_t **) (datasp + LA_LR_OFFSET));
1547         arg_regs  = (uint64_t *) (currentsp + LA_SIZE + 4 * SIZEOF_VOID_P);
1548         arg_stack = (uint64_t *) javasp;
1549 #elif defined(__POWERPC64__)
1550         datasp    = currentsp + framesize;
1551         javasp    = currentsp + framesize;
1552         javara    = *((uint8_t **) (datasp + LA_LR_OFFSET));
1553         arg_regs  = (uint64_t *) (currentsp + PA_SIZE + LA_SIZE + 4 * SIZEOF_VOID_P);
1554         arg_stack = (uint64_t *) javasp;
1555 #else
1556         /* XXX is was unable to do this port for SPARC64, sorry. (-michi) */
1557         /* XXX maybe we need to pass the RA as argument there */
1558         vm_abort("codegen_start_native_call: unsupported architecture");
1559 #endif
1560
1561 #if !defined(NDEBUG)
1562 # if defined(__ALPHA__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__X86_64__) || defined(__S390__)
1563         /* print the call-trace if necesarry */
1564
1565         if (opt_TraceJavaCalls)
1566                 trace_java_call_enter(m, arg_regs, arg_stack);
1567 # endif
1568 #endif
1569
1570         /* get data structures from stack */
1571
1572         sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1573         lrt = (localref_table *) (datasp - sizeof(stackframeinfo) - 
1574                                                           sizeof(localref_table));
1575
1576 #if defined(ENABLE_JNI)
1577         /* add current JNI local references table to this thread */
1578
1579         localref_table_add(lrt);
1580 #endif
1581
1582 #if defined(ENABLE_HANDLES)
1583         /* place all references into the local reference table */
1584
1585         localref_fill(m, arg_regs, arg_stack);
1586 #endif
1587
1588         /* add a stackframeinfo to the chain */
1589
1590         stacktrace_create_native_stackframeinfo(sfi, pv, javasp, javara);
1591
1592         /* return a wrapped classinfo for static native methods */
1593
1594         if (m->flags & ACC_STATIC)
1595                 return LLNI_classinfo_wrap(m->class);
1596         else
1597                 return NULL;
1598 }
1599
1600
1601 /* codegen_finish_native_call **************************************************
1602
1603    Removes the stuff required for a native (JNI) function call.
1604    Additionally it checks for an exceptions and in case, get the
1605    exception object and clear the pointer.
1606
1607 *******************************************************************************/
1608
1609 java_object_t *codegen_finish_native_call(u1 *currentsp, u1 *pv)
1610 {
1611         stackframeinfo *sfi;
1612         java_handle_t  *e;
1613         java_object_t  *o;
1614         codeinfo       *code;
1615         methodinfo     *m;
1616         int32_t         framesize;
1617
1618         uint8_t  *datasp;
1619         uint64_t *ret_regs;
1620
1621         /* get information from method header */
1622
1623         code      = *((codeinfo **) (pv + CodeinfoPointer));
1624         framesize = *((int32_t *)   (pv + FrameSize));
1625         assert(code);
1626
1627         /* get the methodinfo */
1628
1629         m = code->m;
1630         assert(m);
1631
1632         /* calculate needed values */
1633
1634 #if defined(__ALPHA__) || defined(__ARM__)
1635         datasp   = currentsp + framesize - SIZEOF_VOID_P;
1636         ret_regs = (uint64_t *) currentsp;
1637 #elif defined(__MIPS__)
1638         /* MIPS always uses 8 bytes to store the RA */
1639         datasp   = currentsp + framesize - 8;
1640 #elif defined(__S390__)
1641         datasp   = currentsp + framesize - 8;
1642         ret_regs = (uint64_t *) (currentsp + 96);
1643 #elif defined(__I386__)
1644         datasp   = currentsp + framesize;
1645         ret_regs = (uint64_t *) (currentsp + 2 * SIZEOF_VOID_P);
1646 #elif defined(__M68K__) || defined(__X86_64__)
1647         datasp   = currentsp + framesize;
1648         ret_regs = (uint64_t *) currentsp;
1649 #elif defined(__POWERPC__)
1650         datasp   = currentsp + framesize;
1651         ret_regs = (uint64_t *) (currentsp + LA_SIZE + 2 * SIZEOF_VOID_P);
1652 #elif defined(__POWERPC64__)
1653         datasp   = currentsp + framesize;
1654         ret_regs = (uint64_t *) (currentsp + PA_SIZE + LA_SIZE + 2 * SIZEOF_VOID_P);
1655 #else
1656         vm_abort("codegen_finish_native_call: unsupported architecture");
1657 #endif
1658
1659
1660 #if !defined(NDEBUG)
1661 # if defined(__ALPHA__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__X86_64__) || defined(__S390__)
1662         /* print the call-trace if necesarry */
1663
1664         if (opt_TraceJavaCalls)
1665                 trace_java_call_exit(m, ret_regs);
1666 # endif
1667 #endif
1668
1669         /* get data structures from stack */
1670
1671         sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1672
1673         /* remove current stackframeinfo from chain */
1674
1675         stacktrace_remove_stackframeinfo(sfi);
1676
1677         /* XXX unfill lrt here!!! */
1678
1679         /* get and unwrap the exception */
1680         /* ATTENTION: do the this _after_ the stackframeinfo was
1681        removed but _before_ the localref_table gets removed! */
1682
1683         e = exceptions_get_and_clear_exception();
1684         o = LLNI_UNWRAP(e);
1685
1686 #if defined(ENABLE_JNI)
1687         /* release JNI local references table for this thread */
1688
1689         localref_frame_pop_all();
1690         localref_table_remove();
1691 #endif
1692
1693         return o;
1694 }
1695
1696
1697 /* removecompilerstub **********************************************************
1698
1699    Deletes a compilerstub from memory (simply by freeing it).
1700
1701 *******************************************************************************/
1702
1703 void removecompilerstub(u1 *stub)
1704 {
1705         /* pass size 1 to keep the intern function happy */
1706
1707         CFREE((void *) stub, 1);
1708 }
1709
1710
1711 /* removenativestub ************************************************************
1712
1713    Removes a previously created native-stub from memory.
1714     
1715 *******************************************************************************/
1716
1717 void removenativestub(u1 *stub)
1718 {
1719         /* pass size 1 to keep the intern function happy */
1720
1721         CFREE((void *) stub, 1);
1722 }
1723
1724
1725 /* codegen_reg_of_var **********************************************************
1726
1727    This function determines a register, to which the result of an
1728    operation should go, when it is ultimatively intended to store the
1729    result in pseudoregister v.  If v is assigned to an actual
1730    register, this register will be returned.  Otherwise (when v is
1731    spilled) this function returns tempregnum.  If not already done,
1732    regoff and flags are set in the stack location.
1733        
1734 *******************************************************************************/
1735
1736 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
1737 {
1738
1739 #if 0
1740         /* Do we have to generate a conditional move?  Yes, then always
1741            return the temporary register.  The real register is identified
1742            during the store. */
1743
1744         if (opcode & ICMD_CONDITION_MASK)
1745                 return tempregnum;
1746 #endif
1747
1748         if (!(v->flags & INMEMORY))
1749                 return v->vv.regoff;
1750
1751         return tempregnum;
1752 }
1753
1754
1755 /* codegen_reg_of_dst **********************************************************
1756
1757    This function determines a register, to which the result of an
1758    operation should go, when it is ultimatively intended to store the
1759    result in iptr->dst.var.  If dst.var is assigned to an actual
1760    register, this register will be returned.  Otherwise (when it is
1761    spilled) this function returns tempregnum.  If not already done,
1762    regoff and flags are set in the stack location.
1763        
1764 *******************************************************************************/
1765
1766 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
1767 {
1768         return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
1769 }
1770
1771
1772 /* codegen_emit_phi_moves ****************************************************
1773
1774    Emits phi moves at the end of the basicblock.
1775
1776 *******************************************************************************/
1777
1778 #if defined(ENABLE_SSA)
1779 void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
1780 {
1781         int lt_d,lt_s,i;
1782         lsradata *ls;
1783         codegendata *cd;
1784         varinfo *s, *d;
1785         instruction tmp_i;
1786
1787         cd = jd->cd;
1788         ls = jd->ls;
1789
1790         MCODECHECK(512);
1791
1792         /* Moves from phi functions with highest indices have to be */
1793         /* inserted first, since this is the order as is used for   */
1794         /* conflict resolution */
1795
1796         for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
1797                 lt_d = ls->phi_moves[bptr->nr][i][0];
1798                 lt_s = ls->phi_moves[bptr->nr][i][1];
1799 #if defined(SSA_DEBUG_VERBOSE)
1800                 if (compileverbose)
1801                         printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
1802 #endif
1803                 if (lt_s == UNUSED) {
1804 #if defined(SSA_DEBUG_VERBOSE)
1805                 if (compileverbose)
1806                         printf(" ... not processed \n");
1807 #endif
1808                         continue;
1809                 }
1810                         
1811                 d = VAR(ls->lifetime[lt_d].v_index);
1812                 s = VAR(ls->lifetime[lt_s].v_index);
1813                 
1814
1815                 if (d->type == -1) {
1816 #if defined(SSA_DEBUG_VERBOSE)
1817                         if (compileverbose)
1818                                 printf("...returning - phi lifetimes where joined\n");
1819 #endif
1820                         return;
1821                 }
1822
1823                 if (s->type == -1) {
1824 #if defined(SSA_DEBUG_VERBOSE)
1825                         if (compileverbose)
1826                                 printf("...returning - phi lifetimes where joined\n");
1827 #endif
1828                         return;
1829                 }
1830
1831                 tmp_i.opc = 0;
1832                 tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
1833                 tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
1834                 emit_copy(jd, &tmp_i);
1835
1836 #if defined(SSA_DEBUG_VERBOSE)
1837                 if (compileverbose) {
1838                         if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
1839                                 /* mem -> mem */
1840                                 printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1841                         }
1842                         else if (IS_INMEMORY(s->flags)) {
1843                                 /* mem -> reg */
1844                                 printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1845                         }
1846                         else if (IS_INMEMORY(d->flags)) {
1847                                 /* reg -> mem */
1848                                 printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1849                         }
1850                         else {
1851                                 /* reg -> reg */
1852                                 printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1853                         }
1854                         printf("\n");
1855                 }
1856 #endif /* defined(SSA_DEBUG_VERBOSE) */
1857         }
1858 }
1859 #endif /* defined(ENABLE_SSA) */
1860
1861
1862
1863 /*
1864  * These are local overrides for various environment variables in Emacs.
1865  * Please do not remove this and leave it at the end of the file, where
1866  * Emacs will automagically detect them.
1867  * ---------------------------------------------------------------------
1868  * Local variables:
1869  * mode: c
1870  * indent-tabs-mode: t
1871  * c-basic-offset: 4
1872  * tab-width: 4
1873  * End:
1874  * vim:noexpandtab:sw=4:ts=4:
1875  */