f7b44053e6f0b1006fb812325780a9ca82be9736
[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    $Id: codegen-common.c 7864 2007-05-03 21:17:26Z twisti $
43
44 */
45
46
47 #include "config.h"
48
49 #include <assert.h>
50 #include <string.h>
51
52 #include "vm/types.h"
53
54 #if defined(ENABLE_JIT)
55 /* this is required PATCHER_CALL_SIZE */
56 # include "codegen.h"
57 #endif
58
59 #if defined(__ARM__)
60 /* this is required for REG_SPLIT */
61 # include "md-abi.h"
62 #endif
63
64 #include "mm/memory.h"
65
66 #include "toolbox/avl.h"
67 #include "toolbox/list.h"
68 #include "toolbox/logging.h"
69
70 #include "native/jni.h"
71 #include "native/native.h"
72
73 #include "threads/threads-common.h"
74
75 #include "vm/exceptions.h"
76 #include "vm/stringlocal.h"
77
78 #include "vm/jit/abi.h"
79 #include "vm/jit/asmpart.h"
80 #include "vm/jit/codegen-common.h"
81
82 #if defined(ENABLE_DISASSEMBLER)
83 # include "vm/jit/disass.h"
84 #endif
85
86 #include "vm/jit/dseg.h"
87 #include "vm/jit/emit-common.h"
88 #include "vm/jit/jit.h"
89 #include "vm/jit/md.h"
90 #include "vm/jit/replace.h"
91 #include "vm/jit/stacktrace.h"
92
93 #if defined(ENABLE_INTRP)
94 #include "vm/jit/intrp/intrp.h"
95 #endif
96
97 #include "vmcore/method.h"
98 #include "vmcore/options.h"
99
100 # include "vmcore/statistics.h"
101
102 #if defined(ENABLE_VMLOG)
103 #include <vmlog_cacao.h>
104 #endif
105
106
107 /* in this tree we store all method addresses *********************************/
108
109 static avl_tree_t *methodtree = NULL;
110 static s4 methodtree_comparator(const void *treenode, const void *node);
111
112
113 /* codegen_init ****************************************************************
114
115    TODO
116
117 *******************************************************************************/
118
119 void codegen_init(void)
120 {
121         /* this tree is global, not method specific */
122
123         if (!methodtree) {
124 #if defined(ENABLE_JIT)
125                 methodtree_element *mte;
126 #endif
127
128                 methodtree = avl_create(&methodtree_comparator);
129
130 #if defined(ENABLE_JIT)
131                 /* insert asm_vm_call_method */
132
133                 mte = NEW(methodtree_element);
134
135                 mte->startpc = (u1 *) (ptrint) asm_vm_call_method;
136                 mte->endpc   = (u1 *) (ptrint) asm_vm_call_method_end;
137
138                 avl_insert(methodtree, mte);
139 #endif /* defined(ENABLE_JIT) */
140         }
141 }
142
143
144 /* codegen_setup ***************************************************************
145
146    Allocates and initialises code area, data area and references.
147
148 *******************************************************************************/
149
150 void codegen_setup(jitdata *jd)
151 {
152         methodinfo  *m;
153         codegendata *cd;
154
155         /* get required compiler data */
156
157         m  = jd->m;
158         cd = jd->cd;
159
160         /* initialize members */
161
162         cd->flags        = 0;
163
164         cd->mcodebase    = DMNEW(u1, MCODEINITSIZE);
165         cd->mcodeend     = cd->mcodebase + MCODEINITSIZE;
166         cd->mcodesize    = MCODEINITSIZE;
167
168         /* initialize mcode variables */
169
170         cd->mcodeptr     = cd->mcodebase;
171         cd->lastmcodeptr = cd->mcodebase;
172
173 #if defined(ENABLE_INTRP)
174         /* native dynamic superinstructions variables */
175
176         if (opt_intrp) {
177                 cd->ncodebase = DMNEW(u1, NCODEINITSIZE);
178                 cd->ncodesize = NCODEINITSIZE;
179
180                 /* initialize ncode variables */
181         
182                 cd->ncodeptr = cd->ncodebase;
183
184                 cd->lastinstwithoutdispatch = ~0; /* no inst without dispatch */
185                 cd->superstarts = NULL;
186         }
187 #endif
188
189         cd->dseg           = NULL;
190         cd->dseglen        = 0;
191
192         cd->jumpreferences = NULL;
193
194 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
195         cd->datareferences = NULL;
196 #endif
197
198 /*      cd->patchrefs      = list_create_dump(OFFSET(patchref, linkage)); */
199         cd->patchrefs      = NULL;
200         cd->brancheslabel  = list_create_dump(OFFSET(branch_label_ref_t, linkage));
201         cd->listcritical   = list_create_dump(OFFSET(critical_section_ref_t, linkage));
202
203         cd->linenumberreferences = NULL;
204         cd->linenumbertablesizepos = 0;
205         cd->linenumbertablestartpos = 0;
206         cd->linenumbertab = 0;
207 }
208
209
210 /* codegen_reset ***************************************************************
211
212    Resets the codegen data structure so we can recompile the method.
213
214 *******************************************************************************/
215
216 static void codegen_reset(jitdata *jd)
217 {
218         codeinfo    *code;
219         codegendata *cd;
220         basicblock  *bptr;
221
222         /* get required compiler data */
223
224         code = jd->code;
225         cd   = jd->cd;
226
227         /* reset error flag */
228
229         cd->flags          &= ~CODEGENDATA_FLAG_ERROR;
230
231         /* reset some members, we reuse the code memory already allocated
232            as this should have almost the correct size */
233
234         cd->mcodeptr        = cd->mcodebase;
235         cd->lastmcodeptr    = cd->mcodebase;
236
237         cd->dseg            = NULL;
238         cd->dseglen         = 0;
239
240         cd->jumpreferences  = NULL;
241
242 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
243         cd->datareferences  = NULL;
244 #endif
245
246 /*      cd->patchrefs       = list_create_dump(OFFSET(patchref, linkage)); */
247         cd->patchrefs       = NULL;
248         cd->brancheslabel   = list_create_dump(OFFSET(branch_label_ref_t, linkage));
249         cd->listcritical    = list_create_dump(OFFSET(critical_section_ref_t, linkage));
250
251         cd->linenumberreferences    = NULL;
252         cd->linenumbertablesizepos  = 0;
253         cd->linenumbertablestartpos = 0;
254         cd->linenumbertab           = 0;
255         
256         /* We need to clear the mpc and the branch references from all
257            basic blocks as they will definitely change. */
258
259         for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
260                 bptr->mpc        = -1;
261                 bptr->branchrefs = NULL;
262         }
263
264 #if defined(ENABLE_REPLACEMENT)
265         code->rplpoints     = NULL;
266         code->rplpointcount = 0;
267         code->regalloc      = NULL;
268         code->regalloccount = 0;
269         code->globalcount   = 0;
270 #endif
271 }
272
273
274 /* codegen_generate ************************************************************
275
276    Generates the code for the currently compiled method.
277
278 *******************************************************************************/
279
280 bool codegen_generate(jitdata *jd)
281 {
282         codegendata *cd;
283
284         /* get required compiler data */
285
286         cd = jd->cd;
287
288         /* call the machine-dependent code generation function */
289
290         if (!codegen_emit(jd))
291                 return false;
292
293         /* check for an error */
294
295         if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
296                 /* check for long-branches flag, if it is set we recompile the
297                    method */
298
299 #if !defined(NDEBUG)
300         if (compileverbose)
301             log_message_method("Re-generating code: ", jd->m);
302 #endif
303
304                 /* XXX maybe we should tag long-branches-methods for recompilation */
305
306                 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
307                         /* we have to reset the codegendata structure first */
308
309                         codegen_reset(jd);
310
311                         /* and restart the compiler run */
312
313                         if (!codegen_emit(jd))
314                                 return false;
315                 }
316                 else {
317                         vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
318                 }
319
320 #if !defined(NDEBUG)
321         if (compileverbose)
322             log_message_method("Re-generating code done: ", jd->m);
323 #endif
324         }
325
326         /* reallocate the memory and finish the code generation */
327
328         codegen_finish(jd);
329
330         /* everything's ok */
331
332         return true;
333 }
334
335
336 /* codegen_close ***************************************************************
337
338    TODO
339
340 *******************************************************************************/
341
342 void codegen_close(void)
343 {
344         /* TODO: release avl tree on i386 and x86_64 */
345 }
346
347
348 /* codegen_increase ************************************************************
349
350    Doubles code area.
351
352 *******************************************************************************/
353
354 void codegen_increase(codegendata *cd)
355 {
356         u1 *oldmcodebase;
357
358         /* save old mcodebase pointer */
359
360         oldmcodebase = cd->mcodebase;
361
362         /* reallocate to new, doubled memory */
363
364         cd->mcodebase = DMREALLOC(cd->mcodebase,
365                                                           u1,
366                                                           cd->mcodesize,
367                                                           cd->mcodesize * 2);
368         cd->mcodesize *= 2;
369         cd->mcodeend   = cd->mcodebase + cd->mcodesize;
370
371         /* set new mcodeptr */
372
373         cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
374
375 #if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(ENABLE_INTRP)
376         /* adjust the pointer to the last patcher position */
377
378         if (cd->lastmcodeptr != NULL)
379                 cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
380 #endif
381 }
382
383
384 /* codegen_ncode_increase ******************************************************
385
386    Doubles code area.
387
388 *******************************************************************************/
389
390 #if defined(ENABLE_INTRP)
391 u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
392 {
393         u1 *oldncodebase;
394
395         /* save old ncodebase pointer */
396
397         oldncodebase = cd->ncodebase;
398
399         /* reallocate to new, doubled memory */
400
401         cd->ncodebase = DMREALLOC(cd->ncodebase,
402                                                           u1,
403                                                           cd->ncodesize,
404                                                           cd->ncodesize * 2);
405         cd->ncodesize *= 2;
406
407         /* return the new ncodeptr */
408
409         return (cd->ncodebase + (ncodeptr - oldncodebase));
410 }
411 #endif
412
413
414 /* codegen_add_branch_ref ******************************************************
415
416    Prepends an branch to the list.
417
418 *******************************************************************************/
419
420 void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
421 {
422         branchref *br;
423         s4         branchmpc;
424
425         STATISTICS(count_branches_unresolved++);
426
427         /* calculate the mpc of the branch instruction */
428
429         branchmpc = cd->mcodeptr - cd->mcodebase;
430
431         br = DNEW(branchref);
432
433         br->branchmpc = branchmpc;
434         br->condition = condition;
435         br->reg       = reg;
436         br->options   = options;
437         br->next      = target->branchrefs;
438
439         target->branchrefs = br;
440 }
441
442
443 /* codegen_resolve_branchrefs **************************************************
444
445    Resolves and patches the branch references of a given basic block.
446
447 *******************************************************************************/
448
449 void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
450 {
451         branchref *br;
452         u1        *mcodeptr;
453
454         /* Save the mcodeptr because in the branch emitting functions
455            we generate code somewhere inside already generated code,
456            but we're still in the actual code generation phase. */
457
458         mcodeptr = cd->mcodeptr;
459
460         /* just to make sure */
461
462         assert(bptr->mpc >= 0);
463
464         for (br = bptr->branchrefs; br != NULL; br = br->next) {
465                 /* temporary set the mcodeptr */
466
467                 cd->mcodeptr = cd->mcodebase + br->branchmpc;
468
469                 /* emit_bccz and emit_branch emit the correct code, even if we
470                    pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
471
472                 emit_bccz(cd, bptr, br->condition, br->reg, br->options);
473         }
474
475         /* restore mcodeptr */
476
477         cd->mcodeptr = mcodeptr;
478 }
479
480
481 /* codegen_branch_label_add ****************************************************
482
483    Append an branch to the label-branch list.
484
485 *******************************************************************************/
486
487 void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
488 {
489         list_t             *list;
490         branch_label_ref_t *br;
491         s4                  mpc;
492
493         /* get the label list */
494
495         list = cd->brancheslabel;
496         
497         /* calculate the current mpc */
498
499         mpc = cd->mcodeptr - cd->mcodebase;
500
501         br = DNEW(branch_label_ref_t);
502
503         br->mpc       = mpc;
504         br->label     = label;
505         br->condition = condition;
506         br->reg       = reg;
507         br->options   = options;
508
509         /* add the branch to the list */
510
511         list_add_last_unsynced(list, br);
512 }
513
514
515 /* codegen_add_patch_ref *******************************************************
516
517    Appends a new patcher reference to the list of patching positions.
518
519 *******************************************************************************/
520
521 void codegen_add_patch_ref(codegendata *cd, functionptr patcher, voidptr ref,
522                                                    s4 disp)
523 {
524         patchref *pr;
525         s4        branchmpc;
526
527         branchmpc = cd->mcodeptr - cd->mcodebase;
528
529         pr = DNEW(patchref);
530
531         pr->branchpos = branchmpc;
532         pr->disp      = disp;
533         pr->patcher   = patcher;
534         pr->ref       = ref;
535
536 /*      list_add_first(cd->patchrefs, pr); */
537         pr->next      = cd->patchrefs;
538         cd->patchrefs = pr;
539
540         /* Generate NOPs for opt_shownops. */
541
542         if (opt_shownops)
543                 PATCHER_NOPS;
544
545 #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__MIPS__) || defined(__X86_64__))
546         /* On some architectures the patcher stub call instruction might
547            be longer than the actual instruction generated.  On this
548            architectures we store the last patcher call position and after
549            the basic block code generation is completed, we check the
550            range and maybe generate some nop's. */
551
552         cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
553 #endif
554 }
555
556
557 /* codegen_critical_section_new ************************************************
558
559    Allocates a new critical-section reference and adds it to the
560    critical-section list.
561
562 *******************************************************************************/
563
564 #if defined(ENABLE_THREADS)
565 void codegen_critical_section_new(codegendata *cd)
566 {
567         list_t                 *list;
568         critical_section_ref_t *csr;
569         s4                      mpc;
570
571         /* get the critical section list */
572
573         list = cd->listcritical;
574         
575         /* calculate the current mpc */
576
577         mpc = cd->mcodeptr - cd->mcodebase;
578
579         csr = DNEW(critical_section_ref_t);
580
581         /* We only can set restart right now, as start and end are set by
582            the following, corresponding functions. */
583
584         csr->start   = -1;
585         csr->end     = -1;
586         csr->restart = mpc;
587
588         /* add the branch to the list */
589
590         list_add_last_unsynced(list, csr);
591 }
592 #endif
593
594
595 /* codegen_critical_section_start **********************************************
596
597    Set the start-point of the current critical section (which is the
598    last element of the list).
599
600 *******************************************************************************/
601
602 #if defined(ENABLE_THREADS)
603 void codegen_critical_section_start(codegendata *cd)
604 {
605         list_t                 *list;
606         critical_section_ref_t *csr;
607         s4                      mpc;
608
609         /* get the critical section list */
610
611         list = cd->listcritical;
612         
613         /* calculate the current mpc */
614
615         mpc = cd->mcodeptr - cd->mcodebase;
616
617         /* get the current critical section */
618
619         csr = list_last_unsynced(list);
620
621         /* set the start point */
622
623         assert(csr->start == -1);
624
625         csr->start = mpc;
626 }
627 #endif
628
629
630 /* codegen_critical_section_end ************************************************
631
632    Set the end-point of the current critical section (which is the
633    last element of the list).
634
635 *******************************************************************************/
636
637 #if defined(ENABLE_THREADS)
638 void codegen_critical_section_end(codegendata *cd)
639 {
640         list_t                 *list;
641         critical_section_ref_t *csr;
642         s4                      mpc;
643
644         /* get the critical section list */
645
646         list = cd->listcritical;
647         
648         /* calculate the current mpc */
649
650         mpc = cd->mcodeptr - cd->mcodebase;
651
652         /* get the current critical section */
653
654         csr = list_last_unsynced(list);
655
656         /* set the end point */
657
658         assert(csr->end == -1);
659
660         csr->end = mpc;
661 }
662 #endif
663
664
665 /* codegen_critical_section_finish *********************************************
666
667    Finish the critical sections, create the critical section nodes for
668    the AVL tree and insert them into the tree.
669
670 *******************************************************************************/
671
672 #if defined(ENABLE_THREADS)
673 static void codegen_critical_section_finish(jitdata *jd)
674 {
675         codeinfo    *code;
676         codegendata *cd;
677         list_t                  *list;
678         critical_section_ref_t  *csr;
679         critical_section_node_t *csn;
680
681         /* get required compiler data */
682
683         code = jd->code;
684         cd   = jd->cd;
685
686         /* get the critical section list */
687
688         list = cd->listcritical;
689
690         /* iterate over all critical sections */
691
692         for (csr = list_first_unsynced(list); csr != NULL;
693                  csr = list_next_unsynced(list, csr)) {
694                 /* check if all points are set */
695
696                 assert(csr->start   != -1);
697                 assert(csr->end     != -1);
698                 assert(csr->restart != -1);
699
700                 /* allocate tree node */
701
702                 csn = NEW(critical_section_node_t);
703
704                 csn->start   = code->entrypoint + csr->start;
705                 csn->end     = code->entrypoint + csr->end;
706                 csn->restart = code->entrypoint + csr->restart;
707
708                 /* insert into the tree */
709
710                 critical_section_register(csn);
711         }
712 }
713 #endif
714
715
716 /* methodtree_comparator *******************************************************
717
718    Comparator function used for the AVL tree of methods.
719
720    ARGUMENTS:
721       treenode....the node from the tree
722       node........the node to compare to the tree-node
723
724 *******************************************************************************/
725
726 static s4 methodtree_comparator(const void *treenode, const void *node)
727 {
728         methodtree_element *mte;
729         methodtree_element *mtepc;
730
731         mte   = (methodtree_element *) treenode;
732         mtepc = (methodtree_element *) node;
733
734         /* compare both startpc and endpc of pc, even if they have the same value,
735            otherwise the avl_probe sometimes thinks the element is already in the
736            tree */
737
738 #ifdef __S390__
739         /* On S390 addresses are 31 bit. Compare only 31 bits of value.
740          */
741 #       define ADDR_MASK(a) ((a) & 0x7FFFFFFF)
742 #else
743 #       define ADDR_MASK(a) (a)
744 #endif
745
746         if (ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->startpc) &&
747                 ADDR_MASK((long) mtepc->startpc) <= ADDR_MASK((long) mte->endpc) &&
748                 ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->endpc) &&
749                 ADDR_MASK((long) mtepc->endpc) <= ADDR_MASK((long) mte->endpc)) {
750                 return 0;
751
752         } else if (ADDR_MASK((long) mtepc->startpc) < ADDR_MASK((long) mte->startpc)) {
753                 return -1;
754
755         } else {
756                 return 1;
757         }
758
759 #       undef ADDR_MASK
760 }
761
762
763 /* codegen_insertmethod ********************************************************
764
765    Insert the machine code range of a method into the AVL tree of methods.
766
767 *******************************************************************************/
768
769 void codegen_insertmethod(u1 *startpc, u1 *endpc)
770 {
771         methodtree_element *mte;
772
773         /* allocate new method entry */
774
775         mte = NEW(methodtree_element);
776
777         mte->startpc = startpc;
778         mte->endpc   = endpc;
779
780         /* this function does not return an error, but asserts for
781            duplicate entries */
782
783         avl_insert(methodtree, mte);
784 }
785
786
787 /* codegen_get_pv_from_pc ******************************************************
788
789    Find the PV for the given PC by searching in the AVL tree of
790    methods.
791
792 *******************************************************************************/
793
794 u1 *codegen_get_pv_from_pc(u1 *pc)
795 {
796         methodtree_element  mtepc;
797         methodtree_element *mte;
798
799         /* allocation of the search structure on the stack is much faster */
800
801         mtepc.startpc = pc;
802         mtepc.endpc   = pc;
803
804         mte = avl_find(methodtree, &mtepc);
805
806         if (mte == NULL) {
807                 /* No method was found.  Let's dump a stacktrace. */
808
809 #if defined(ENABLE_VMLOG)
810                 vmlog_cacao_signl("SIGSEGV");
811 #endif
812
813                 log_println("We received a SIGSEGV and tried to handle it, but we were");
814                 log_println("unable to find a Java method at:");
815                 log_println("");
816 #if SIZEOF_VOID_P == 8
817                 log_println("PC=0x%016lx", pc);
818 #else
819                 log_println("PC=0x%08x", pc);
820 #endif
821                 log_println("");
822                 log_println("Dumping the current stacktrace:");
823
824 #if defined(ENABLE_THREADS)
825                 /* XXX michi: This should be available even without threads! */
826                 threads_print_stacktrace();
827 #endif
828
829                 vm_abort("Exiting...");
830         }
831
832         return mte->startpc;
833 }
834
835
836 /* codegen_get_pv_from_pc_nocheck **********************************************
837
838    Find the PV for the given PC by searching in the AVL tree of
839    methods.  This method does not check the return value and is used
840    by the profiler.
841
842 *******************************************************************************/
843
844 u1 *codegen_get_pv_from_pc_nocheck(u1 *pc)
845 {
846         methodtree_element  mtepc;
847         methodtree_element *mte;
848
849         /* allocation of the search structure on the stack is much faster */
850
851         mtepc.startpc = pc;
852         mtepc.endpc   = pc;
853
854         mte = avl_find(methodtree, &mtepc);
855
856         if (mte == NULL)
857                 return NULL;
858         else
859                 return mte->startpc;
860 }
861
862
863 /* codegen_set_replacement_point_notrap ****************************************
864
865    Record the position of a non-trappable replacement point.
866
867 *******************************************************************************/
868
869 #if defined(ENABLE_REPLACEMENT)
870 #if !defined(NDEBUG)
871 void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
872 #else
873 void codegen_set_replacement_point_notrap(codegendata *cd)
874 #endif
875 {
876         assert(cd->replacementpoint);
877         assert(cd->replacementpoint->type == type);
878         assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
879
880         cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
881
882         cd->replacementpoint++;
883 }
884 #endif /* defined(ENABLE_REPLACEMENT) */
885
886
887 /* codegen_set_replacement_point ***********************************************
888
889    Record the position of a trappable replacement point.
890
891 *******************************************************************************/
892
893 #if defined(ENABLE_REPLACEMENT)
894 #if !defined(NDEBUG)
895 void codegen_set_replacement_point(codegendata *cd, s4 type)
896 #else
897 void codegen_set_replacement_point(codegendata *cd)
898 #endif
899 {
900         assert(cd->replacementpoint);
901         assert(cd->replacementpoint->type == type);
902         assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
903
904         cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
905
906         cd->replacementpoint++;
907
908         /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
909
910         cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
911 }
912 #endif /* defined(ENABLE_REPLACEMENT) */
913
914
915 /* codegen_finish **************************************************************
916
917    Finishes the code generation. A new memory, large enough for both
918    data and code, is allocated and data and code are copied together
919    to their final layout, unresolved jumps are resolved, ...
920
921 *******************************************************************************/
922
923 void codegen_finish(jitdata *jd)
924 {
925         codeinfo    *code;
926         codegendata *cd;
927         s4           mcodelen;
928 #if defined(ENABLE_INTRP)
929         s4           ncodelen;
930 #endif
931         s4           alignedmcodelen;
932         jumpref     *jr;
933         u1          *epoint;
934         s4           alignedlen;
935
936         /* get required compiler data */
937
938         code = jd->code;
939         cd   = jd->cd;
940
941         /* prevent compiler warning */
942
943 #if defined(ENABLE_INTRP)
944         ncodelen = 0;
945 #endif
946
947         /* calculate the code length */
948
949         mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
950
951 #if defined(ENABLE_STATISTICS)
952         if (opt_stat) {
953                 count_code_len += mcodelen;
954                 count_data_len += cd->dseglen;
955         }
956 #endif
957
958         alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
959
960 #if defined(ENABLE_INTRP)
961         if (opt_intrp)
962                 ncodelen = cd->ncodeptr - cd->ncodebase;
963         else {
964                 ncodelen = 0; /* avoid compiler warning */
965         }
966 #endif
967
968         cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
969         alignedlen = alignedmcodelen + cd->dseglen;
970
971 #if defined(ENABLE_INTRP)
972         if (opt_intrp) {
973                 alignedlen += ncodelen;
974         }
975 #endif
976
977         /* allocate new memory */
978
979         code->mcodelength = mcodelen + cd->dseglen;
980         code->mcode       = CNEW(u1, alignedlen);
981
982         /* set the entrypoint of the method */
983         
984         assert(code->entrypoint == NULL);
985         code->entrypoint = epoint = (code->mcode + cd->dseglen);
986
987         /* fill the data segment (code->entrypoint must already be set!) */
988
989         dseg_finish(jd);
990
991         /* copy code to the new location */
992
993         MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
994
995 #if defined(ENABLE_INTRP)
996         /* relocate native dynamic superinstruction code (if any) */
997
998         if (opt_intrp) {
999                 cd->mcodebase = code->entrypoint;
1000
1001                 if (ncodelen > 0) {
1002                         u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
1003
1004                         MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
1005
1006                         /* flush the instruction and data caches */
1007
1008                         md_cacheflush(ncodebase, ncodelen);
1009
1010                         /* set some cd variables for dynamic_super_rerwite */
1011
1012                         cd->ncodebase = ncodebase;
1013
1014                 } else {
1015                         cd->ncodebase = NULL;
1016                 }
1017
1018                 dynamic_super_rewrite(cd);
1019         }
1020 #endif
1021
1022         /* jump table resolving */
1023
1024         for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
1025                 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
1026                         (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
1027
1028         /* line number table resolving */
1029         {
1030                 linenumberref *lr;
1031                 ptrint lrtlen = 0;
1032                 ptrint target;
1033
1034                 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
1035                         lrtlen++;
1036                         target = lr->targetmpc;
1037                         /* if the entry contains an mcode pointer (normal case), resolve it */
1038                         /* (see doc/inlining_stacktrace.txt for details)                    */
1039                         if (lr->linenumber >= -2) {
1040                             target += (ptrint) epoint;
1041                         }
1042                         *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) = 
1043                                 (functionptr) target;
1044                 }
1045                 
1046                 *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
1047                         (functionptr) ((ptrint) epoint + cd->linenumbertab);
1048
1049                 *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
1050         }
1051
1052 #if defined(ENABLE_REPLACEMENT)
1053         /* replacement point resolving */
1054         {
1055                 int i;
1056                 rplpoint *rp;
1057
1058                 code->replacementstubs += (ptrint) epoint;
1059
1060                 rp = code->rplpoints;
1061                 for (i=0; i<code->rplpointcount; ++i, ++rp) {
1062                         rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
1063                 }
1064         }
1065 #endif /* defined(ENABLE_REPLACEMENT) */
1066
1067         /* add method into methodtree to find the entrypoint */
1068
1069         codegen_insertmethod(code->entrypoint, code->entrypoint + mcodelen);
1070
1071 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
1072         /* resolve data segment references */
1073
1074         dseg_resolve_datareferences(jd);
1075 #endif
1076
1077 #if defined(ENABLE_THREADS)
1078         /* create cirtical sections */
1079
1080         codegen_critical_section_finish(jd);
1081 #endif
1082
1083         /* flush the instruction and data caches */
1084
1085         md_cacheflush(code->mcode, code->mcodelength);
1086 }
1087
1088
1089 /* codegen_generate_stub_compiler **********************************************
1090
1091    Wrapper for codegen_emit_stub_compiler.
1092
1093    Returns:
1094        pointer to the compiler stub code.
1095
1096 *******************************************************************************/
1097
1098 u1 *codegen_generate_stub_compiler(methodinfo *m)
1099 {
1100         jitdata     *jd;
1101         codegendata *cd;
1102         ptrint      *d;                     /* pointer to data memory             */
1103         u1          *c;                     /* pointer to code memory             */
1104         s4           dumpsize;
1105
1106         /* mark dump memory */
1107
1108         dumpsize = dump_size();
1109
1110         /* allocate required data structures */
1111
1112         jd = DNEW(jitdata);
1113
1114         jd->m     = m;
1115         jd->cd    = DNEW(codegendata);
1116         jd->flags = 0;
1117
1118         /* get required compiler data */
1119
1120         cd = jd->cd;
1121
1122         /* allocate code memory */
1123
1124         c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1125
1126         /* set pointers correctly */
1127
1128         d = (ptrint *) c;
1129
1130         cd->mcodebase = c;
1131
1132         c = c + 3 * SIZEOF_VOID_P;
1133         cd->mcodeptr = c;
1134
1135         /* NOTE: The codeinfo pointer is actually a pointer to the
1136            methodinfo (this fakes a codeinfo structure). */
1137
1138         d[0] = (ptrint) asm_call_jit_compiler;
1139         d[1] = (ptrint) m;
1140         d[2] = (ptrint) &d[1];                                    /* fake code->m */
1141
1142         /* call the emit function */
1143
1144         codegen_emit_stub_compiler(jd);
1145
1146 #if defined(ENABLE_STATISTICS)
1147         if (opt_stat)
1148                 count_cstub_len += 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
1149 #endif
1150
1151         /* flush caches */
1152
1153         md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1154
1155         /* release dump memory */
1156
1157         dump_release(dumpsize);
1158
1159         /* return native stub code */
1160
1161         return c;
1162 }
1163
1164
1165 /* codegen_generate_stub_native ************************************************
1166
1167    Wrapper for codegen_emit_stub_native.
1168
1169    Returns:
1170        the codeinfo representing the stub code.
1171
1172 *******************************************************************************/
1173
1174 codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
1175 {
1176         jitdata     *jd;
1177         codeinfo    *code;
1178         s4           dumpsize;
1179         methoddesc  *md;
1180         methoddesc  *nmd;       
1181         s4           nativeparams;
1182
1183         /* mark dump memory */
1184
1185         dumpsize = dump_size();
1186
1187         jd = DNEW(jitdata);
1188
1189         jd->m     = m;
1190         jd->cd    = DNEW(codegendata);
1191         jd->rd    = DNEW(registerdata);
1192         jd->flags = 0;
1193
1194         /* Allocate codeinfo memory from the heap as we need to keep them. */
1195
1196         jd->code  = code_codeinfo_new(m); /* XXX check allocation */
1197
1198         /* get required compiler data */
1199
1200         code = jd->code;
1201
1202         /* set the flags for the current JIT run */
1203
1204 #if defined(ENABLE_PROFILING)
1205         if (opt_prof)
1206                 jd->flags |= JITDATA_FLAG_INSTRUMENT;
1207 #endif
1208
1209         if (opt_verbosecall)
1210                 jd->flags |= JITDATA_FLAG_VERBOSECALL;
1211
1212         /* setup code generation stuff */
1213
1214 #if defined(ENABLE_JIT)
1215 # if defined(ENABLE_INTRP)
1216         if (!opt_intrp)
1217 # endif
1218                 reg_setup(jd);
1219 #endif
1220
1221         codegen_setup(jd);
1222
1223         /* create new method descriptor with additional native parameters */
1224
1225         md = m->parseddesc;
1226         nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
1227         
1228         nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
1229                                                            md->paramcount * sizeof(typedesc) +
1230                                                            nativeparams * sizeof(typedesc));
1231
1232         nmd->paramcount = md->paramcount + nativeparams;
1233
1234         nmd->params = DMNEW(paramdesc, nmd->paramcount);
1235
1236         nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer            */
1237
1238         if (m->flags & ACC_STATIC)
1239                 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer              */
1240
1241         MCOPY(nmd->paramtypes + nativeparams, md->paramtypes, typedesc,
1242                   md->paramcount);
1243
1244 #if defined(ENABLE_JIT)
1245 # if defined(ENABLE_INTRP)
1246         if (!opt_intrp)
1247 # endif
1248                 /* pre-allocate the arguments for the native ABI */
1249
1250                 md_param_alloc_native(nmd);
1251 #endif
1252
1253         /* generate the code */
1254
1255 #if defined(ENABLE_JIT)
1256 # if defined(ENABLE_INTRP)
1257         if (opt_intrp)
1258                 intrp_createnativestub(f, jd, nmd);
1259         else
1260 # endif
1261                 codegen_emit_stub_native(jd, nmd, f);
1262 #else
1263         intrp_createnativestub(f, jd, nmd);
1264 #endif
1265
1266 #if defined(ENABLE_STATISTICS)
1267         if (opt_stat)
1268                 count_nstub_len += code->mcodelength;
1269 #endif
1270
1271         /* reallocate the memory and finish the code generation */
1272
1273         codegen_finish(jd);
1274
1275 #if !defined(NDEBUG)
1276         /* disassemble native stub */
1277
1278         if (opt_shownativestub) {
1279 #if defined(ENABLE_DISASSEMBLER)
1280                 codegen_disassemble_nativestub(m,
1281                                                                            (u1 *) (ptrint) code->entrypoint,
1282                                                                            (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
1283 #endif
1284
1285                 /* show data segment */
1286
1287                 if (opt_showddatasegment)
1288                         dseg_display(jd);
1289         }
1290 #endif /* !defined(NDEBUG) */
1291
1292         /* release memory */
1293
1294         dump_release(dumpsize);
1295
1296         /* return native stub code */
1297
1298         return code;
1299 }
1300
1301
1302 /* codegen_disassemble_nativestub **********************************************
1303
1304    Disassembles the generated native stub.
1305
1306 *******************************************************************************/
1307
1308 #if defined(ENABLE_DISASSEMBLER)
1309 void codegen_disassemble_nativestub(methodinfo *m, u1 *start, u1 *end)
1310 {
1311         printf("Native stub: ");
1312         utf_fprint_printable_ascii_classname(stdout, m->class->name);
1313         printf(".");
1314         utf_fprint_printable_ascii(stdout, m->name);
1315         utf_fprint_printable_ascii(stdout, m->descriptor);
1316         printf("\n\nLength: %d\n\n", (s4) (end - start));
1317
1318         DISASSEMBLE(start, end);
1319 }
1320 #endif
1321
1322
1323 /* codegen_start_native_call ***************************************************
1324
1325    Prepares the stuff required for a native (JNI) function call:
1326
1327    - adds a stackframe info structure to the chain, for stacktraces
1328    - prepares the local references table on the stack
1329
1330    The layout of the native stub stackframe should look like this:
1331
1332    +---------------------------+ <- SP (of parent Java function)
1333    | return address            |
1334    +---------------------------+
1335    |                           |
1336    | stackframe info structure |
1337    |                           |
1338    +---------------------------+
1339    |                           |
1340    | local references table    |
1341    |                           |
1342    +---------------------------+
1343    |                           |
1344    | arguments (if any)        |
1345    |                           |
1346    +---------------------------+ <- SP (native stub)
1347
1348 *******************************************************************************/
1349
1350 void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
1351 {
1352         stackframeinfo *sfi;
1353         localref_table *lrt;
1354
1355         /* get data structures from stack */
1356
1357         sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1358         lrt = (localref_table *) (datasp - sizeof(stackframeinfo) - 
1359                                                           sizeof(localref_table));
1360
1361         /* add a stackframeinfo to the chain */
1362
1363         stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
1364
1365 #if defined(ENABLE_JNI)
1366         /* add current JNI local references table to this thread */
1367
1368         lrt->capacity    = LOCALREFTABLE_CAPACITY;
1369         lrt->used        = 0;
1370         lrt->localframes = 1;
1371         lrt->prev        = LOCALREFTABLE;
1372
1373         /* clear the references array (memset is faster the a for-loop) */
1374
1375         MSET(lrt->refs, 0, java_objectheader*, LOCALREFTABLE_CAPACITY);
1376
1377         LOCALREFTABLE = lrt;
1378 #endif
1379 }
1380
1381
1382 /* codegen_finish_native_call **************************************************
1383
1384    Removes the stuff required for a native (JNI) function call.
1385    Additionally it checks for an exceptions and in case, get the
1386    exception object and clear the pointer.
1387
1388 *******************************************************************************/
1389
1390 java_objectheader *codegen_finish_native_call(u1 *datasp)
1391 {
1392         stackframeinfo     *sfi;
1393         stackframeinfo    **psfi;
1394 #if defined(ENABLE_JNI)
1395         localref_table     *lrt;
1396         localref_table     *plrt;
1397         s4                  localframes;
1398 #endif
1399         java_objectheader  *e;
1400
1401         /* get data structures from stack */
1402
1403         sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1404
1405         /* remove current stackframeinfo from chain */
1406
1407         psfi = &STACKFRAMEINFO;
1408
1409         *psfi = sfi->prev;
1410
1411 #if defined(ENABLE_JNI)
1412         /* release JNI local references tables for this thread */
1413
1414         lrt = LOCALREFTABLE;
1415
1416         /* release all current local frames */
1417
1418         for (localframes = lrt->localframes; localframes >= 1; localframes--) {
1419                 /* get previous frame */
1420
1421                 plrt = lrt->prev;
1422
1423                 /* Clear all reference entries (only for tables allocated on
1424                    the Java heap). */
1425
1426                 if (localframes > 1)
1427                         MSET(&lrt->refs[0], 0, java_objectheader*, lrt->capacity);
1428
1429                 lrt->prev = NULL;
1430
1431                 /* set new local references table */
1432
1433                 lrt = plrt;
1434         }
1435
1436         /* now store the previous local frames in the thread structure */
1437
1438         LOCALREFTABLE = lrt;
1439 #endif
1440
1441         /* get the exception and return it */
1442
1443         e = exceptions_get_and_clear_exception();
1444
1445         return e;
1446 }
1447
1448
1449 /* removecompilerstub **********************************************************
1450
1451    Deletes a compilerstub from memory (simply by freeing it).
1452
1453 *******************************************************************************/
1454
1455 void removecompilerstub(u1 *stub)
1456 {
1457         /* pass size 1 to keep the intern function happy */
1458
1459         CFREE((void *) stub, 1);
1460 }
1461
1462
1463 /* removenativestub ************************************************************
1464
1465    Removes a previously created native-stub from memory.
1466     
1467 *******************************************************************************/
1468
1469 void removenativestub(u1 *stub)
1470 {
1471         /* pass size 1 to keep the intern function happy */
1472
1473         CFREE((void *) stub, 1);
1474 }
1475
1476
1477 /* codegen_reg_of_var **********************************************************
1478
1479    This function determines a register, to which the result of an
1480    operation should go, when it is ultimatively intended to store the
1481    result in pseudoregister v.  If v is assigned to an actual
1482    register, this register will be returned.  Otherwise (when v is
1483    spilled) this function returns tempregnum.  If not already done,
1484    regoff and flags are set in the stack location.
1485        
1486    On ARM we have to check if a long/double variable is splitted
1487    across reg/stack (HIGH_REG == REG_SPLIT). We return the actual
1488    register of v for LOW_REG and the tempregnum for HIGH_REG in such
1489    cases.  (michi 2005/07/24)
1490
1491 *******************************************************************************/
1492
1493 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
1494 {
1495
1496 #if 0
1497         /* Do we have to generate a conditional move?  Yes, then always
1498            return the temporary register.  The real register is identified
1499            during the store. */
1500
1501         if (opcode & ICMD_CONDITION_MASK)
1502                 return tempregnum;
1503 #endif
1504
1505         if (!(v->flags & INMEMORY)) {
1506 #if defined(__ARM__) && defined(__ARMEL__)
1507                 if (IS_2_WORD_TYPE(v->type) && (GET_HIGH_REG(v->vv.regoff) == REG_SPLIT))
1508                         return PACK_REGS(GET_LOW_REG(v->vv.regoff),
1509                                                          GET_HIGH_REG(tempregnum));
1510 #endif
1511 #if defined(__ARM__) && defined(__ARMEB__)
1512                 if (IS_2_WORD_TYPE(v->type) && (GET_LOW_REG(v->vv.regoff) == REG_SPLIT))
1513                         return PACK_REGS(GET_LOW_REG(tempregnum),
1514                                                          GET_HIGH_REG(v->vv.regoff));
1515 #endif
1516                 return v->vv.regoff;
1517         }
1518
1519 #if defined(ENABLE_STATISTICS)
1520         if (opt_stat)
1521                 count_spills_read++;
1522 #endif
1523
1524         return tempregnum;
1525 }
1526
1527 /* codegen_reg_of_dst **********************************************************
1528
1529    This function determines a register, to which the result of an
1530    operation should go, when it is ultimatively intended to store the
1531    result in iptr->dst.var.  If dst.var is assigned to an actual
1532    register, this register will be returned.  Otherwise (when it is
1533    spilled) this function returns tempregnum.  If not already done,
1534    regoff and flags are set in the stack location.
1535        
1536    On ARM we have to check if a long/double variable is splitted
1537    across reg/stack (HIGH_REG == REG_SPLIT). We return the actual
1538    register of dst.var for LOW_REG and the tempregnum for HIGH_REG in such
1539    cases.  (michi 2005/07/24)
1540
1541 *******************************************************************************/
1542
1543 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
1544 {
1545         return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
1546 }
1547
1548
1549 /*
1550  * These are local overrides for various environment variables in Emacs.
1551  * Please do not remove this and leave it at the end of the file, where
1552  * Emacs will automagically detect them.
1553  * ---------------------------------------------------------------------
1554  * Local variables:
1555  * mode: c
1556  * indent-tabs-mode: t
1557  * c-basic-offset: 4
1558  * tab-width: 4
1559  * End:
1560  * vim:noexpandtab:sw=4:ts=4:
1561  */