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