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