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