This commit introduces C++ wrapper classes for Java heap objects.
[cacao.git] / src / vm / jit / codegen-common.c
1 /* src/vm/jit/codegen-common.c - architecture independent code generator stuff
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    All functions assume the following code area / data area layout:
24
25    +-----------+
26    |           |
27    | code area | code area grows to higher addresses
28    |           |
29    +-----------+ <-- start of procedure
30    |           |
31    | data area | data area grows to lower addresses
32    |           |
33    +-----------+
34
35    The functions first write into a temporary code/data area allocated by
36    "codegen_init". "codegen_finish" copies the code and data area into permanent
37    memory. All functions writing values into the data area return the offset
38    relative the begin of the code area (start of procedure).    
39
40 */
41
42
43 #include "config.h"
44
45 #include <assert.h>
46 #include <string.h>
47
48 #include "vm/types.h"
49
50 #include "codegen.h"
51 #include "md.h"
52 #include "md-abi.h"
53
54 #include "mm/memory.h"
55
56 #include "toolbox/avl.h"
57 #include "toolbox/list.h"
58 #include "toolbox/logging.h"
59
60 #include "native/jni.h"
61 #include "native/llni.h"
62 #include "native/localref.h"
63 #include "native/native.h"
64
65 #include "threads/thread.hpp"
66
67 #include "vm/builtin.h"
68 #include "vm/exceptions.hpp"
69 #include "vm/string.hpp"
70
71 #include "vm/jit/abi.h"
72 #include "vm/jit/asmpart.h"
73 #include "vm/jit/code.h"
74 #include "vm/jit/codegen-common.h"
75
76 #if defined(ENABLE_DISASSEMBLER)
77 # include "vm/jit/disass.h"
78 #endif
79
80 #include "vm/jit/dseg.h"
81 #include "vm/jit/emit-common.h"
82 #include "vm/jit/jit.h"
83 #include "vm/jit/linenumbertable.h"
84 #include "vm/jit/methodheader.h"
85 #include "vm/jit/methodtree.h"
86 #include "vm/jit/patcher-common.h"
87 #include "vm/jit/replace.h"
88 #if defined(ENABLE_SSA)
89 # include "vm/jit/optimizing/lsra.h"
90 # include "vm/jit/optimizing/ssa.h"
91 #endif
92 #include "vm/jit/stacktrace.hpp"
93 #include "vm/jit/trace.hpp"
94
95 #if defined(ENABLE_INTRP)
96 #include "vm/jit/intrp/intrp.h"
97 #endif
98
99 #include "vmcore/method.h"
100 #include "vmcore/options.h"
101
102 # include "vmcore/statistics.h"
103
104 #if defined(ENABLE_VMLOG)
105 #include <vmlog_cacao.h>
106 #endif
107
108 #include "show.h"
109
110
111 /* codegen_init ****************************************************************
112
113    TODO
114
115 *******************************************************************************/
116
117 void codegen_init(void)
118 {
119 }
120
121
122 /* codegen_setup ***************************************************************
123
124    Allocates and initialises code area, data area and references.
125
126 *******************************************************************************/
127
128 void codegen_setup(jitdata *jd)
129 {
130         methodinfo  *m;
131         codegendata *cd;
132
133         /* get required compiler data */
134
135         m  = jd->m;
136         cd = jd->cd;
137
138         /* initialize members */
139
140         cd->flags        = 0;
141
142         cd->mcodebase    = DMNEW(u1, MCODEINITSIZE);
143         cd->mcodeend     = cd->mcodebase + MCODEINITSIZE;
144         cd->mcodesize    = MCODEINITSIZE;
145
146         /* initialize mcode variables */
147
148         cd->mcodeptr     = cd->mcodebase;
149         cd->lastmcodeptr = cd->mcodebase;
150
151 #if defined(ENABLE_INTRP)
152         /* native dynamic superinstructions variables */
153
154         if (opt_intrp) {
155                 cd->ncodebase = DMNEW(u1, NCODEINITSIZE);
156                 cd->ncodesize = NCODEINITSIZE;
157
158                 /* initialize ncode variables */
159         
160                 cd->ncodeptr = cd->ncodebase;
161
162                 cd->lastinstwithoutdispatch = ~0; /* no inst without dispatch */
163                 cd->superstarts = NULL;
164         }
165 #endif
166
167         cd->dseg           = NULL;
168         cd->dseglen        = 0;
169
170         cd->jumpreferences = NULL;
171
172 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
173         cd->datareferences = NULL;
174 #endif
175
176         cd->brancheslabel  = list_create_dump(OFFSET(branch_label_ref_t, linkage));
177         cd->linenumbers    = list_create_dump(OFFSET(linenumbertable_list_entry_t, linkage));
178 }
179
180
181 /* codegen_reset ***************************************************************
182
183    Resets the codegen data structure so we can recompile the method.
184
185 *******************************************************************************/
186
187 static void codegen_reset(jitdata *jd)
188 {
189         codeinfo    *code;
190         codegendata *cd;
191         basicblock  *bptr;
192
193         /* get required compiler data */
194
195         code = jd->code;
196         cd   = jd->cd;
197
198         /* reset error flag */
199
200         cd->flags          &= ~CODEGENDATA_FLAG_ERROR;
201
202         /* reset some members, we reuse the code memory already allocated
203            as this should have almost the correct size */
204
205         cd->mcodeptr        = cd->mcodebase;
206         cd->lastmcodeptr    = cd->mcodebase;
207
208         cd->dseg            = NULL;
209         cd->dseglen         = 0;
210
211         cd->jumpreferences  = NULL;
212
213 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
214         cd->datareferences  = NULL;
215 #endif
216
217         cd->brancheslabel   = list_create_dump(OFFSET(branch_label_ref_t, linkage));
218         cd->linenumbers     = list_create_dump(OFFSET(linenumbertable_list_entry_t, linkage));
219         
220         /* We need to clear the mpc and the branch references from all
221            basic blocks as they will definitely change. */
222
223         for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
224                 bptr->mpc        = -1;
225                 bptr->branchrefs = NULL;
226         }
227
228         /* We need to clear all the patcher references from the codeinfo
229            since they all will be regenerated */
230
231         patcher_list_reset(code);
232
233 #if defined(ENABLE_REPLACEMENT)
234         code->rplpoints     = NULL;
235         code->rplpointcount = 0;
236         code->regalloc      = NULL;
237         code->regalloccount = 0;
238         code->globalcount   = 0;
239 #endif
240 }
241
242
243 /* codegen_generate ************************************************************
244
245    Generates the code for the currently compiled method.
246
247 *******************************************************************************/
248
249 bool codegen_generate(jitdata *jd)
250 {
251         codegendata *cd;
252
253         /* get required compiler data */
254
255         cd = jd->cd;
256
257         /* call the machine-dependent code generation function */
258
259         if (!codegen_emit(jd))
260                 return false;
261
262         /* check for an error */
263
264         if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
265                 /* check for long-branches flag, if it is set we recompile the
266                    method */
267
268 #if !defined(NDEBUG)
269         if (compileverbose)
270             log_message_method("Re-generating code: ", jd->m);
271 #endif
272
273                 /* XXX maybe we should tag long-branches-methods for recompilation */
274
275                 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
276                         /* we have to reset the codegendata structure first */
277
278                         codegen_reset(jd);
279
280                         /* and restart the compiler run */
281
282                         if (!codegen_emit(jd))
283                                 return false;
284                 }
285                 else {
286                         vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
287                 }
288
289 #if !defined(NDEBUG)
290         if (compileverbose)
291             log_message_method("Re-generating code done: ", jd->m);
292 #endif
293         }
294
295         /* reallocate the memory and finish the code generation */
296
297         codegen_finish(jd);
298
299         /* everything's ok */
300
301         return true;
302 }
303
304
305 /* codegen_close ***************************************************************
306
307    TODO
308
309 *******************************************************************************/
310
311 void codegen_close(void)
312 {
313         /* TODO: release avl tree on i386 and x86_64 */
314 }
315
316
317 /* codegen_increase ************************************************************
318
319    Doubles code area.
320
321 *******************************************************************************/
322
323 void codegen_increase(codegendata *cd)
324 {
325         u1 *oldmcodebase;
326
327         /* save old mcodebase pointer */
328
329         oldmcodebase = cd->mcodebase;
330
331         /* reallocate to new, doubled memory */
332
333         cd->mcodebase = DMREALLOC(cd->mcodebase,
334                                                           u1,
335                                                           cd->mcodesize,
336                                                           cd->mcodesize * 2);
337         cd->mcodesize *= 2;
338         cd->mcodeend   = cd->mcodebase + cd->mcodesize;
339
340         /* set new mcodeptr */
341
342         cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
343
344 #if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(__M68K__) || defined(ENABLE_INTRP) \
345  || defined(__SPARC_64__)
346         /* adjust the pointer to the last patcher position */
347
348         if (cd->lastmcodeptr != NULL)
349                 cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
350 #endif
351 }
352
353
354 /* codegen_ncode_increase ******************************************************
355
356    Doubles code area.
357
358 *******************************************************************************/
359
360 #if defined(ENABLE_INTRP)
361 u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
362 {
363         u1 *oldncodebase;
364
365         /* save old ncodebase pointer */
366
367         oldncodebase = cd->ncodebase;
368
369         /* reallocate to new, doubled memory */
370
371         cd->ncodebase = DMREALLOC(cd->ncodebase,
372                                                           u1,
373                                                           cd->ncodesize,
374                                                           cd->ncodesize * 2);
375         cd->ncodesize *= 2;
376
377         /* return the new ncodeptr */
378
379         return (cd->ncodebase + (ncodeptr - oldncodebase));
380 }
381 #endif
382
383
384 /* codegen_add_branch_ref ******************************************************
385
386    Prepends an branch to the list.
387
388 *******************************************************************************/
389
390 void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
391 {
392         branchref *br;
393         s4         branchmpc;
394
395         STATISTICS(count_branches_unresolved++);
396
397         /* calculate the mpc of the branch instruction */
398
399         branchmpc = cd->mcodeptr - cd->mcodebase;
400
401         br = DNEW(branchref);
402
403         br->branchmpc = branchmpc;
404         br->condition = condition;
405         br->reg       = reg;
406         br->options   = options;
407         br->next      = target->branchrefs;
408
409         target->branchrefs = br;
410 }
411
412
413 /* codegen_resolve_branchrefs **************************************************
414
415    Resolves and patches the branch references of a given basic block.
416
417 *******************************************************************************/
418
419 void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
420 {
421         branchref *br;
422         u1        *mcodeptr;
423
424         /* Save the mcodeptr because in the branch emitting functions
425            we generate code somewhere inside already generated code,
426            but we're still in the actual code generation phase. */
427
428         mcodeptr = cd->mcodeptr;
429
430         /* just to make sure */
431
432         assert(bptr->mpc >= 0);
433
434         for (br = bptr->branchrefs; br != NULL; br = br->next) {
435                 /* temporary set the mcodeptr */
436
437                 cd->mcodeptr = cd->mcodebase + br->branchmpc;
438
439                 /* emit_bccz and emit_branch emit the correct code, even if we
440                    pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
441
442                 emit_bccz(cd, bptr, br->condition, br->reg, br->options);
443         }
444
445         /* restore mcodeptr */
446
447         cd->mcodeptr = mcodeptr;
448 }
449
450
451 /* codegen_branch_label_add ****************************************************
452
453    Append an branch to the label-branch list.
454
455 *******************************************************************************/
456
457 void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
458 {
459         list_t             *l;
460         branch_label_ref_t *br;
461         s4                  mpc;
462
463         /* Get the label list. */
464
465         l = cd->brancheslabel;
466         
467         /* calculate the current mpc */
468
469         mpc = cd->mcodeptr - cd->mcodebase;
470
471         br = DNEW(branch_label_ref_t);
472
473         br->mpc       = mpc;
474         br->label     = label;
475         br->condition = condition;
476         br->reg       = reg;
477         br->options   = options;
478
479         /* Add the branch to the list. */
480
481         list_add_last(l, br);
482 }
483
484
485 /* codegen_set_replacement_point_notrap ****************************************
486
487    Record the position of a non-trappable replacement point.
488
489 *******************************************************************************/
490
491 #if defined(ENABLE_REPLACEMENT)
492 #if !defined(NDEBUG)
493 void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
494 #else
495 void codegen_set_replacement_point_notrap(codegendata *cd)
496 #endif
497 {
498         assert(cd->replacementpoint);
499         assert(cd->replacementpoint->type == type);
500         assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
501
502         cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
503
504         cd->replacementpoint++;
505 }
506 #endif /* defined(ENABLE_REPLACEMENT) */
507
508
509 /* codegen_set_replacement_point ***********************************************
510
511    Record the position of a trappable replacement point.
512
513 *******************************************************************************/
514
515 #if defined(ENABLE_REPLACEMENT)
516 #if !defined(NDEBUG)
517 void codegen_set_replacement_point(codegendata *cd, s4 type)
518 #else
519 void codegen_set_replacement_point(codegendata *cd)
520 #endif
521 {
522         assert(cd->replacementpoint);
523         assert(cd->replacementpoint->type == type);
524         assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
525
526         cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
527
528         cd->replacementpoint++;
529
530 #if !defined(NDEBUG)
531         /* XXX actually we should use an own REPLACEMENT_NOPS here! */
532         if (opt_TestReplacement)
533                 PATCHER_NOPS;
534 #endif
535
536         /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
537
538         cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
539 }
540 #endif /* defined(ENABLE_REPLACEMENT) */
541
542
543 /* codegen_finish **************************************************************
544
545    Finishes the code generation. A new memory, large enough for both
546    data and code, is allocated and data and code are copied together
547    to their final layout, unresolved jumps are resolved, ...
548
549 *******************************************************************************/
550
551 void codegen_finish(jitdata *jd)
552 {
553         codeinfo    *code;
554         codegendata *cd;
555         s4           mcodelen;
556 #if defined(ENABLE_INTRP)
557         s4           ncodelen;
558 #endif
559         s4           alignedmcodelen;
560         jumpref     *jr;
561         u1          *epoint;
562         s4           alignedlen;
563
564         /* get required compiler data */
565
566         code = jd->code;
567         cd   = jd->cd;
568
569         /* prevent compiler warning */
570
571 #if defined(ENABLE_INTRP)
572         ncodelen = 0;
573 #endif
574
575         /* calculate the code length */
576
577         mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
578
579 #if defined(ENABLE_STATISTICS)
580         if (opt_stat) {
581                 count_code_len += mcodelen;
582                 count_data_len += cd->dseglen;
583         }
584 #endif
585
586         alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
587
588 #if defined(ENABLE_INTRP)
589         if (opt_intrp)
590                 ncodelen = cd->ncodeptr - cd->ncodebase;
591         else {
592                 ncodelen = 0; /* avoid compiler warning */
593         }
594 #endif
595
596         cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
597         alignedlen = alignedmcodelen + cd->dseglen;
598
599 #if defined(ENABLE_INTRP)
600         if (opt_intrp) {
601                 alignedlen += ncodelen;
602         }
603 #endif
604
605         /* allocate new memory */
606
607         code->mcodelength = mcodelen + cd->dseglen;
608         code->mcode       = CNEW(u1, alignedlen);
609
610         /* set the entrypoint of the method */
611         
612         assert(code->entrypoint == NULL);
613         code->entrypoint = epoint = (code->mcode + cd->dseglen);
614
615         /* fill the data segment (code->entrypoint must already be set!) */
616
617         dseg_finish(jd);
618
619         /* copy code to the new location */
620
621         MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
622
623 #if defined(ENABLE_INTRP)
624         /* relocate native dynamic superinstruction code (if any) */
625
626         if (opt_intrp) {
627                 cd->mcodebase = code->entrypoint;
628
629                 if (ncodelen > 0) {
630                         u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
631
632                         MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
633
634                         /* flush the instruction and data caches */
635
636                         md_cacheflush(ncodebase, ncodelen);
637
638                         /* set some cd variables for dynamic_super_rerwite */
639
640                         cd->ncodebase = ncodebase;
641
642                 } else {
643                         cd->ncodebase = NULL;
644                 }
645
646                 dynamic_super_rewrite(cd);
647         }
648 #endif
649
650         /* Create the exception table. */
651
652         exceptiontable_create(jd);
653
654         /* Create the linenumber table. */
655
656         linenumbertable_create(jd);
657
658         /* jump table resolving */
659
660         for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
661                 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
662                         (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
663
664         /* patcher resolving */
665
666         patcher_resolve(jd);
667
668 #if defined(ENABLE_REPLACEMENT)
669         /* replacement point resolving */
670         {
671                 int i;
672                 rplpoint *rp;
673
674                 rp = code->rplpoints;
675                 for (i=0; i<code->rplpointcount; ++i, ++rp) {
676                         rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
677                 }
678         }
679 #endif /* defined(ENABLE_REPLACEMENT) */
680
681         /* Insert method into methodtree to find the entrypoint. */
682
683         methodtree_insert(code->entrypoint, code->entrypoint + mcodelen);
684
685 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
686         /* resolve data segment references */
687
688         dseg_resolve_datareferences(jd);
689 #endif
690
691         /* flush the instruction and data caches */
692
693         md_cacheflush(code->mcode, code->mcodelength);
694 }
695
696
697 /* codegen_generate_stub_compiler **********************************************
698
699    Wrapper for codegen_emit_stub_compiler.
700
701    Returns:
702        pointer to the compiler stub code.
703
704 *******************************************************************************/
705
706 u1 *codegen_generate_stub_compiler(methodinfo *m)
707 {
708         jitdata     *jd;
709         codegendata *cd;
710         ptrint      *d;                     /* pointer to data memory             */
711         u1          *c;                     /* pointer to code memory             */
712         int32_t      dumpmarker;
713
714         /* mark dump memory */
715
716         DMARKER;
717
718         /* allocate required data structures */
719
720         jd = DNEW(jitdata);
721
722         jd->m     = m;
723         jd->cd    = DNEW(codegendata);
724         jd->flags = 0;
725
726         /* get required compiler data */
727
728         cd = jd->cd;
729
730 #if !defined(JIT_COMPILER_VIA_SIGNAL)
731         /* allocate code memory */
732
733         c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
734
735         /* set pointers correctly */
736
737         d = (ptrint *) c;
738
739         cd->mcodebase = c;
740
741         c = c + 3 * SIZEOF_VOID_P;
742         cd->mcodeptr = c;
743
744         /* NOTE: The codeinfo pointer is actually a pointer to the
745            methodinfo (this fakes a codeinfo structure). */
746
747         d[0] = (ptrint) asm_call_jit_compiler;
748         d[1] = (ptrint) m;
749         d[2] = (ptrint) &d[1];                                    /* fake code->m */
750
751         /* call the emit function */
752
753         codegen_emit_stub_compiler(jd);
754
755 #if defined(ENABLE_STATISTICS)
756         if (opt_stat)
757                 count_cstub_len += 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
758 #endif
759
760         /* flush caches */
761
762         md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
763 #else
764         /* Allocate code memory. */
765
766         c = CNEW(uint8_t, 2 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
767
768         /* Set pointers correctly. */
769
770         d = (ptrint *) c;
771
772         cd->mcodebase = c;
773
774         c = c + 2 * SIZEOF_VOID_P;
775         cd->mcodeptr = c;
776
777         /* NOTE: The codeinfo pointer is actually a pointer to the
778            methodinfo (this fakes a codeinfo structure). */
779
780         d[0] = (ptrint) m;
781         d[1] = (ptrint) &d[0];                                    /* fake code->m */
782
783         /* Emit the trap instruction. */
784
785         emit_trap_compiler(cd);
786
787 #if defined(ENABLE_STATISTICS)
788         if (opt_stat)
789                 count_cstub_len += 2 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
790 #endif
791
792         /* Flush caches. */
793
794         md_cacheflush(cd->mcodebase, 2 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
795 #endif
796
797         /* release dump memory */
798
799         DRELEASE;
800
801         /* return native stub code */
802
803         return c;
804 }
805
806
807 /* codegen_generate_stub_builtin ***********************************************
808
809    Wrapper for codegen_emit_stub_native.
810
811 *******************************************************************************/
812
813 void codegen_generate_stub_builtin(methodinfo *m, builtintable_entry *bte)
814 {
815         jitdata  *jd;
816         codeinfo *code;
817         int       skipparams;
818         int32_t   dumpmarker;
819
820         /* mark dump memory */
821
822         DMARKER;
823
824         /* Create JIT data structure. */
825
826         jd = jit_jitdata_new(m);
827
828         /* Get required compiler data. */
829
830         code = jd->code;
831
832         /* Stubs are non-leaf methods. */
833
834         code_unflag_leafmethod(code);
835
836         /* setup code generation stuff */
837
838         codegen_setup(jd);
839
840         /* Set the number of native arguments we need to skip. */
841
842         skipparams = 0;
843
844         /* generate the code */
845
846 #if defined(ENABLE_JIT)
847 # if defined(ENABLE_INTRP)
848         if (!opt_intrp) {
849 # endif
850                 assert(bte->fp != NULL);
851                 codegen_emit_stub_native(jd, bte->md, bte->fp, skipparams);
852 # if defined(ENABLE_INTRP)
853         }
854 # endif
855 #endif
856
857         /* reallocate the memory and finish the code generation */
858
859         codegen_finish(jd);
860
861         /* set the stub entry point in the builtin table */
862
863         bte->stub = code->entrypoint;
864
865 #if defined(ENABLE_STATISTICS)
866         if (opt_stat)
867                 size_stub_native += code->mcodelength;
868 #endif
869
870 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
871         /* disassemble native stub */
872
873         if (opt_DisassembleStubs) {
874                 codegen_disassemble_stub(m,
875                                                                  (u1 *) (ptrint) code->entrypoint,
876                                                                  (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
877
878                 /* show data segment */
879
880                 if (opt_showddatasegment)
881                         dseg_display(jd);
882         }
883 #endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
884
885         /* release memory */
886
887         DRELEASE;
888 }
889
890
891 /* codegen_generate_stub_native ************************************************
892
893    Wrapper for codegen_emit_stub_native.
894
895    Returns:
896        the codeinfo representing the stub code.
897
898 *******************************************************************************/
899
900 codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
901 {
902         jitdata     *jd;
903         codeinfo    *code;
904         methoddesc  *md;
905         methoddesc  *nmd;       
906         int          skipparams;
907         int32_t      dumpmarker;
908
909         /* mark dump memory */
910
911         DMARKER;
912
913         /* Create JIT data structure. */
914
915         jd = jit_jitdata_new(m);
916
917         /* Get required compiler data. */
918
919         code = jd->code;
920
921         /* Stubs are non-leaf methods. */
922
923         code_unflag_leafmethod(code);
924
925         /* set the flags for the current JIT run */
926
927 #if defined(ENABLE_PROFILING)
928         if (opt_prof)
929                 jd->flags |= JITDATA_FLAG_INSTRUMENT;
930 #endif
931
932         if (opt_verbosecall)
933                 jd->flags |= JITDATA_FLAG_VERBOSECALL;
934
935         /* setup code generation stuff */
936
937 #if defined(ENABLE_JIT)
938 # if defined(ENABLE_INTRP)
939         if (!opt_intrp)
940 # endif
941                 reg_setup(jd);
942 #endif
943
944         codegen_setup(jd);
945
946         /* create new method descriptor with additional native parameters */
947
948         md = m->parseddesc;
949
950         /* Set the number of native arguments we need to skip. */
951
952         if (m->flags & ACC_STATIC)
953                 skipparams = 2;
954         else
955                 skipparams = 1;
956         
957         nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
958                                                            md->paramcount * sizeof(typedesc) +
959                                                            skipparams * sizeof(typedesc));
960
961         nmd->paramcount = md->paramcount + skipparams;
962
963         nmd->params = DMNEW(paramdesc, nmd->paramcount);
964
965         nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer            */
966
967         if (m->flags & ACC_STATIC)
968                 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer              */
969
970         MCOPY(nmd->paramtypes + skipparams, md->paramtypes, typedesc,
971                   md->paramcount);
972
973 #if defined(ENABLE_JIT)
974 # if defined(ENABLE_INTRP)
975         if (!opt_intrp)
976 # endif
977                 /* pre-allocate the arguments for the native ABI */
978
979                 md_param_alloc_native(nmd);
980 #endif
981
982         /* generate the code */
983
984 #if defined(ENABLE_JIT)
985 # if defined(ENABLE_INTRP)
986         if (opt_intrp)
987                 intrp_createnativestub(f, jd, nmd);
988         else
989 # endif
990                 codegen_emit_stub_native(jd, nmd, f, skipparams);
991 #else
992         intrp_createnativestub(f, jd, nmd);
993 #endif
994
995         /* reallocate the memory and finish the code generation */
996
997         codegen_finish(jd);
998
999 #if defined(ENABLE_STATISTICS)
1000         /* must be done after codegen_finish() */
1001
1002         if (opt_stat)
1003                 size_stub_native += code->mcodelength;
1004 #endif
1005
1006 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
1007         /* disassemble native stub */
1008
1009         if (opt_DisassembleStubs) {
1010 # if defined(ENABLE_DEBUG_FILTER)
1011                 if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
1012 # endif
1013                 {
1014                         codegen_disassemble_stub(m,
1015                                                                          (u1 *) (ptrint) code->entrypoint,
1016                                                                          (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
1017
1018                         /* show data segment */
1019
1020                         if (opt_showddatasegment)
1021                                 dseg_display(jd);
1022                 }
1023         }
1024 #endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
1025
1026         /* release memory */
1027
1028         DRELEASE;
1029
1030         /* return native stub code */
1031
1032         return code;
1033 }
1034
1035
1036 /* codegen_disassemble_nativestub **********************************************
1037
1038    Disassembles the generated builtin or native stub.
1039
1040 *******************************************************************************/
1041
1042 #if defined(ENABLE_DISASSEMBLER)
1043 void codegen_disassemble_stub(methodinfo *m, u1 *start, u1 *end)
1044 {
1045         printf("Stub code: ");
1046         if (m->clazz != NULL)
1047                 utf_fprint_printable_ascii_classname(stdout, m->clazz->name);
1048         else
1049                 printf("NULL");
1050         printf(".");
1051         utf_fprint_printable_ascii(stdout, m->name);
1052         utf_fprint_printable_ascii(stdout, m->descriptor);
1053         printf("\nLength: %d\n\n", (s4) (end - start));
1054
1055         DISASSEMBLE(start, end);
1056 }
1057 #endif
1058
1059
1060 /* codegen_start_native_call ***************************************************
1061
1062    Prepares the stuff required for a native (JNI) function call:
1063
1064    - adds a stackframe info structure to the chain, for stacktraces
1065    - prepares the local references table on the stack
1066
1067    The layout of the native stub stackframe should look like this:
1068
1069    +---------------------------+ <- java SP (of parent Java function)
1070    | return address            |
1071    +---------------------------+ <- data SP
1072    |                           |
1073    | stackframe info structure |
1074    |                           |
1075    +---------------------------+
1076    |                           |
1077    | local references table    |
1078    |                           |
1079    +---------------------------+
1080    |                           |
1081    | saved registers (if any)  |
1082    |                           |
1083    +---------------------------+
1084    |                           |
1085    | arguments (if any)        |
1086    |                           |
1087    +---------------------------+ <- current SP (native stub)
1088
1089 *******************************************************************************/
1090
1091 java_handle_t *codegen_start_native_call(u1 *sp, u1 *pv)
1092 {
1093         stackframeinfo_t *sfi;
1094         localref_table   *lrt;
1095         methodinfo       *m;
1096         int32_t           framesize;
1097
1098         uint8_t  *datasp;
1099         uint8_t  *javasp;
1100         uint64_t *arg_regs;
1101         uint64_t *arg_stack;
1102
1103         STATISTICS(count_calls_java_to_native++);
1104
1105         /* Get the methodinfo. */
1106
1107         m = code_get_methodinfo_for_pv(pv);
1108
1109         assert(m);
1110
1111         framesize = *((int32_t *) (pv + FrameSize));
1112
1113         assert(framesize >= sizeof(stackframeinfo_t) + sizeof(localref_table));
1114
1115         /* calculate needed values */
1116
1117 #if defined(__ALPHA__) || defined(__ARM__)
1118         datasp    = sp + framesize - SIZEOF_VOID_P;
1119         javasp    = sp + framesize;
1120         arg_regs  = (uint64_t *) sp;
1121         arg_stack = (uint64_t *) javasp;
1122 #elif defined(__MIPS__)
1123         /* MIPS always uses 8 bytes to store the RA */
1124         datasp    = sp + framesize - 8;
1125         javasp    = sp + framesize;
1126 #elif defined(__S390__)
1127         datasp    = sp + framesize - 8;
1128         javasp    = sp + framesize;
1129         arg_regs  = (uint64_t *) (sp + 96);
1130         arg_stack = (uint64_t *) javasp;
1131 #elif defined(__I386__) || defined(__M68K__) || defined(__X86_64__)
1132         datasp    = sp + framesize;
1133         javasp    = sp + framesize + SIZEOF_VOID_P;
1134         arg_regs  = (uint64_t *) sp;
1135         arg_stack = (uint64_t *) javasp;
1136 #elif defined(__POWERPC__)
1137         datasp    = sp + framesize;
1138         javasp    = sp + framesize;
1139         arg_regs  = (uint64_t *) (sp + LA_SIZE + 4 * SIZEOF_VOID_P);
1140         arg_stack = (uint64_t *) javasp;
1141 #elif defined(__POWERPC64__)
1142         datasp    = sp + framesize;
1143         javasp    = sp + framesize;
1144         arg_regs  = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 4 * SIZEOF_VOID_P);
1145         arg_stack = (uint64_t *) javasp;
1146 #else
1147         /* XXX is was unable to do this port for SPARC64, sorry. (-michi) */
1148         /* XXX maybe we need to pass the RA as argument there */
1149         vm_abort("codegen_start_native_call: unsupported architecture");
1150 #endif
1151
1152         /* get data structures from stack */
1153
1154         sfi = (stackframeinfo_t *) (datasp - sizeof(stackframeinfo_t));
1155         lrt = (localref_table *)   (datasp - sizeof(stackframeinfo_t) - 
1156                                                                 sizeof(localref_table));
1157
1158 #if defined(ENABLE_JNI)
1159         /* add current JNI local references table to this thread */
1160
1161         localref_table_add(lrt);
1162 #endif
1163
1164 #if !defined(NDEBUG)
1165 # if defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__)
1166         /* print the call-trace if necesarry */
1167         /* BEFORE: filling the local reference table */
1168
1169         if (opt_TraceJavaCalls)
1170                 trace_java_call_enter(m, arg_regs, arg_stack);
1171 # endif
1172 #endif
1173
1174 #if defined(ENABLE_HANDLES)
1175         /* place all references into the local reference table */
1176         /* BEFORE: creating stackframeinfo */
1177
1178         localref_native_enter(m, arg_regs, arg_stack);
1179 #endif
1180
1181         /* Add a stackframeinfo for this native method.  We don't have RA
1182            and XPC here.  These are determined in
1183            stacktrace_stackframeinfo_add. */
1184
1185         stacktrace_stackframeinfo_add(sfi, pv, sp, NULL, NULL);
1186
1187         /* Return a wrapped classinfo for static methods. */
1188
1189         if (m->flags & ACC_STATIC)
1190                 return (java_handle_t *) LLNI_classinfo_wrap(m->clazz);
1191         else
1192                 return NULL;
1193 }
1194
1195
1196 /* codegen_finish_native_call **************************************************
1197
1198    Removes the stuff required for a native (JNI) function call.
1199    Additionally it checks for an exceptions and in case, get the
1200    exception object and clear the pointer.
1201
1202 *******************************************************************************/
1203
1204 java_object_t *codegen_finish_native_call(u1 *sp, u1 *pv)
1205 {
1206         stackframeinfo_t *sfi;
1207         java_handle_t    *e;
1208         java_object_t    *o;
1209         codeinfo         *code;
1210         methodinfo       *m;
1211         int32_t           framesize;
1212
1213         uint8_t  *datasp;
1214         uint64_t *ret_regs;
1215
1216         /* get information from method header */
1217
1218         code = code_get_codeinfo_for_pv(pv);
1219
1220         framesize = *((int32_t *) (pv + FrameSize));
1221
1222         assert(code);
1223
1224         /* get the methodinfo */
1225
1226         m = code->m;
1227         assert(m);
1228
1229         /* calculate needed values */
1230
1231 #if defined(__ALPHA__) || defined(__ARM__)
1232         datasp   = sp + framesize - SIZEOF_VOID_P;
1233         ret_regs = (uint64_t *) sp;
1234 #elif defined(__MIPS__)
1235         /* MIPS always uses 8 bytes to store the RA */
1236         datasp   = sp + framesize - 8;
1237 #elif defined(__S390__)
1238         datasp   = sp + framesize - 8;
1239         ret_regs = (uint64_t *) (sp + 96);
1240 #elif defined(__I386__)
1241         datasp   = sp + framesize;
1242         ret_regs = (uint64_t *) (sp + 2 * SIZEOF_VOID_P);
1243 #elif defined(__M68K__)
1244         datasp   = sp + framesize;
1245         ret_regs = (uint64_t *) (sp + 2 * 8);
1246 #elif defined(__X86_64__)
1247         datasp   = sp + framesize;
1248         ret_regs = (uint64_t *) sp;
1249 #elif defined(__POWERPC__)
1250         datasp   = sp + framesize;
1251         ret_regs = (uint64_t *) (sp + LA_SIZE + 2 * SIZEOF_VOID_P);
1252 #elif defined(__POWERPC64__)
1253         datasp   = sp + framesize;
1254         ret_regs = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 2 * SIZEOF_VOID_P);
1255 #else
1256         vm_abort("codegen_finish_native_call: unsupported architecture");
1257 #endif
1258
1259         /* get data structures from stack */
1260
1261         sfi = (stackframeinfo_t *) (datasp - sizeof(stackframeinfo_t));
1262
1263         /* Remove current stackframeinfo from chain. */
1264
1265         stacktrace_stackframeinfo_remove(sfi);
1266
1267 #if defined(ENABLE_HANDLES)
1268         /* unwrap the return value from the local reference table */
1269         /* AFTER: removing the stackframeinfo */
1270         /* BEFORE: releasing the local reference table */
1271
1272         localref_native_exit(m, ret_regs);
1273 #endif
1274
1275         /* get and unwrap the exception */
1276         /* AFTER: removing the stackframe info */
1277         /* BEFORE: releasing the local reference table */
1278
1279         e = exceptions_get_and_clear_exception();
1280         o = LLNI_UNWRAP(e);
1281
1282 #if defined(ENABLE_JNI)
1283         /* release JNI local references table for this thread */
1284
1285         localref_frame_pop_all();
1286         localref_table_remove();
1287 #endif
1288
1289 #if !defined(NDEBUG)
1290 # if defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__)
1291         /* print the call-trace if necesarry */
1292         /* AFTER: unwrapping the return value */
1293
1294         if (opt_TraceJavaCalls)
1295                 trace_java_call_exit(m, ret_regs);
1296 # endif
1297 #endif
1298
1299         return o;
1300 }
1301
1302
1303 /* removecompilerstub **********************************************************
1304
1305    Deletes a compilerstub from memory (simply by freeing it).
1306
1307 *******************************************************************************/
1308
1309 void removecompilerstub(u1 *stub)
1310 {
1311         /* pass size 1 to keep the intern function happy */
1312
1313         CFREE((void *) stub, 1);
1314 }
1315
1316
1317 /* removenativestub ************************************************************
1318
1319    Removes a previously created native-stub from memory.
1320     
1321 *******************************************************************************/
1322
1323 void removenativestub(u1 *stub)
1324 {
1325         /* pass size 1 to keep the intern function happy */
1326
1327         CFREE((void *) stub, 1);
1328 }
1329
1330
1331 /* codegen_reg_of_var **********************************************************
1332
1333    This function determines a register, to which the result of an
1334    operation should go, when it is ultimatively intended to store the
1335    result in pseudoregister v.  If v is assigned to an actual
1336    register, this register will be returned.  Otherwise (when v is
1337    spilled) this function returns tempregnum.  If not already done,
1338    regoff and flags are set in the stack location.
1339        
1340 *******************************************************************************/
1341
1342 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
1343 {
1344         if (!(v->flags & INMEMORY))
1345                 return v->vv.regoff;
1346
1347         return tempregnum;
1348 }
1349
1350
1351 /* codegen_reg_of_dst **********************************************************
1352
1353    This function determines a register, to which the result of an
1354    operation should go, when it is ultimatively intended to store the
1355    result in iptr->dst.var.  If dst.var is assigned to an actual
1356    register, this register will be returned.  Otherwise (when it is
1357    spilled) this function returns tempregnum.  If not already done,
1358    regoff and flags are set in the stack location.
1359        
1360 *******************************************************************************/
1361
1362 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
1363 {
1364         return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
1365 }
1366
1367
1368 /* codegen_emit_phi_moves ****************************************************
1369
1370    Emits phi moves at the end of the basicblock.
1371
1372 *******************************************************************************/
1373
1374 #if defined(ENABLE_SSA)
1375 void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
1376 {
1377         int lt_d,lt_s,i;
1378         lsradata *ls;
1379         codegendata *cd;
1380         varinfo *s, *d;
1381         instruction tmp_i;
1382
1383         cd = jd->cd;
1384         ls = jd->ls;
1385
1386         MCODECHECK(512);
1387
1388         /* Moves from phi functions with highest indices have to be */
1389         /* inserted first, since this is the order as is used for   */
1390         /* conflict resolution */
1391
1392         for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
1393                 lt_d = ls->phi_moves[bptr->nr][i][0];
1394                 lt_s = ls->phi_moves[bptr->nr][i][1];
1395 #if defined(SSA_DEBUG_VERBOSE)
1396                 if (compileverbose)
1397                         printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
1398 #endif
1399                 if (lt_s == UNUSED) {
1400 #if defined(SSA_DEBUG_VERBOSE)
1401                 if (compileverbose)
1402                         printf(" ... not processed \n");
1403 #endif
1404                         continue;
1405                 }
1406                         
1407                 d = VAR(ls->lifetime[lt_d].v_index);
1408                 s = VAR(ls->lifetime[lt_s].v_index);
1409                 
1410
1411                 if (d->type == -1) {
1412 #if defined(SSA_DEBUG_VERBOSE)
1413                         if (compileverbose)
1414                                 printf("...returning - phi lifetimes where joined\n");
1415 #endif
1416                         continue;
1417                 }
1418
1419                 if (s->type == -1) {
1420 #if defined(SSA_DEBUG_VERBOSE)
1421                         if (compileverbose)
1422                                 printf("...returning - phi lifetimes where joined\n");
1423 #endif
1424                         continue;
1425                 }
1426
1427                 tmp_i.opc = 0;
1428                 tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
1429                 tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
1430                 emit_copy(jd, &tmp_i);
1431
1432 #if defined(SSA_DEBUG_VERBOSE)
1433                 if (compileverbose) {
1434                         if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
1435                                 /* mem -> mem */
1436                                 printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1437                         }
1438                         else if (IS_INMEMORY(s->flags)) {
1439                                 /* mem -> reg */
1440                                 printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1441                         }
1442                         else if (IS_INMEMORY(d->flags)) {
1443                                 /* reg -> mem */
1444                                 printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1445                         }
1446                         else {
1447                                 /* reg -> reg */
1448                                 printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1449                         }
1450                         printf("\n");
1451                 }
1452 #endif /* defined(SSA_DEBUG_VERBOSE) */
1453         }
1454 }
1455 #endif /* defined(ENABLE_SSA) */
1456
1457
1458 /* REMOVEME When we have exception handling in C. */
1459
1460 void *md_asm_codegen_get_pv_from_pc(void *ra)
1461 {
1462         return md_codegen_get_pv_from_pc(ra);
1463 }
1464
1465
1466 /*
1467  * These are local overrides for various environment variables in Emacs.
1468  * Please do not remove this and leave it at the end of the file, where
1469  * Emacs will automagically detect them.
1470  * ---------------------------------------------------------------------
1471  * Local variables:
1472  * mode: c
1473  * indent-tabs-mode: t
1474  * c-basic-offset: 4
1475  * tab-width: 4
1476  * End:
1477  * vim:noexpandtab:sw=4:ts=4:
1478  */