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