aefd39379aedc55b034dd6fd708292264c32d5d0
[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 7674 2007-04-05 13:27:11Z 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 #if defined(ENABLE_THREADS)
653                 /* XXX michi: This should be available even without threads! */
654                 threads_print_stacktrace(THREADOBJECT);
655 #endif
656
657                 vm_abort("Exiting...");
658         }
659
660         return mte->startpc;
661 }
662
663
664 /* codegen_get_pv_from_pc_nocheck **********************************************
665
666    Find the PV for the given PC by searching in the AVL tree of
667    methods.  This method does not check the return value and is used
668    by the profiler.
669
670 *******************************************************************************/
671
672 u1 *codegen_get_pv_from_pc_nocheck(u1 *pc)
673 {
674         methodtree_element  mtepc;
675         methodtree_element *mte;
676
677         /* allocation of the search structure on the stack is much faster */
678
679         mtepc.startpc = pc;
680         mtepc.endpc   = pc;
681
682         mte = avl_find(methodtree, &mtepc);
683
684         if (mte == NULL)
685                 return NULL;
686         else
687                 return mte->startpc;
688 }
689
690
691 /* codegen_set_replacement_point_notrap ****************************************
692
693    Record the position of a non-trappable replacement point.
694
695 *******************************************************************************/
696
697 #if defined(ENABLE_REPLACEMENT)
698 #if !defined(NDEBUG)
699 void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
700 #else
701 void codegen_set_replacement_point_notrap(codegendata *cd)
702 #endif
703 {
704         assert(cd->replacementpoint);
705         assert(cd->replacementpoint->type == type);
706         assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
707
708         cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
709
710         cd->replacementpoint++;
711 }
712 #endif /* defined(ENABLE_REPLACEMENT) */
713
714
715 /* codegen_set_replacement_point ***********************************************
716
717    Record the position of a trappable replacement point.
718
719 *******************************************************************************/
720
721 #if defined(ENABLE_REPLACEMENT)
722 #if !defined(NDEBUG)
723 void codegen_set_replacement_point(codegendata *cd, s4 type)
724 #else
725 void codegen_set_replacement_point(codegendata *cd)
726 #endif
727 {
728         assert(cd->replacementpoint);
729         assert(cd->replacementpoint->type == type);
730         assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
731
732         cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
733
734         cd->replacementpoint++;
735
736         /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
737
738         cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
739 }
740 #endif /* defined(ENABLE_REPLACEMENT) */
741
742
743 /* codegen_finish **************************************************************
744
745    Finishes the code generation. A new memory, large enough for both
746    data and code, is allocated and data and code are copied together
747    to their final layout, unresolved jumps are resolved, ...
748
749 *******************************************************************************/
750
751 void codegen_finish(jitdata *jd)
752 {
753         codeinfo    *code;
754         codegendata *cd;
755         s4           mcodelen;
756 #if defined(ENABLE_INTRP)
757         s4           ncodelen;
758 #endif
759         s4           alignedmcodelen;
760         jumpref     *jr;
761         u1          *epoint;
762         s4           extralen;
763         s4           alignedlen;
764
765         /* get required compiler data */
766
767         code = jd->code;
768         cd   = jd->cd;
769
770         /* prevent compiler warning */
771
772 #if defined(ENABLE_INTRP)
773         ncodelen = 0;
774 #endif
775
776         /* calculate the code length */
777
778         mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
779
780 #if defined(ENABLE_THREADS)
781         extralen = sizeof(critical_section_node_t) * cd->threadcritcount;
782 #else
783         extralen = 0;
784 #endif
785
786 #if defined(ENABLE_STATISTICS)
787         if (opt_stat) {
788                 count_code_len += mcodelen;
789                 count_data_len += cd->dseglen;
790         }
791 #endif
792
793         alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
794
795 #if defined(ENABLE_INTRP)
796         if (opt_intrp)
797                 ncodelen = cd->ncodeptr - cd->ncodebase;
798         else {
799                 ncodelen = 0; /* avoid compiler warning */
800         }
801 #endif
802
803         cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
804         alignedlen = alignedmcodelen + cd->dseglen;
805
806 #if defined(ENABLE_INTRP)
807         if (opt_intrp) {
808                 alignedlen += ncodelen;
809         }
810 #endif
811
812         /* allocate new memory */
813
814         code->mcodelength = mcodelen + cd->dseglen;
815         code->mcode       = CNEW(u1, alignedlen + extralen);
816
817         /* set the entrypoint of the method */
818         
819         assert(code->entrypoint == NULL);
820         code->entrypoint = epoint = (code->mcode + cd->dseglen);
821
822         /* fill the data segment (code->entrypoint must already be set!) */
823
824         dseg_finish(jd);
825
826         /* copy code to the new location */
827
828         MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
829
830 #if defined(ENABLE_INTRP)
831         /* relocate native dynamic superinstruction code (if any) */
832
833         if (opt_intrp) {
834                 cd->mcodebase = code->entrypoint;
835
836                 if (ncodelen > 0) {
837                         u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
838
839                         MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
840
841                         /* flush the instruction and data caches */
842
843                         md_cacheflush(ncodebase, ncodelen);
844
845                         /* set some cd variables for dynamic_super_rerwite */
846
847                         cd->ncodebase = ncodebase;
848
849                 } else {
850                         cd->ncodebase = NULL;
851                 }
852
853                 dynamic_super_rewrite(cd);
854         }
855 #endif
856
857         /* jump table resolving */
858
859         for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
860                 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
861                         (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
862
863         /* line number table resolving */
864         {
865                 linenumberref *lr;
866                 ptrint lrtlen = 0;
867                 ptrint target;
868
869                 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
870                         lrtlen++;
871                         target = lr->targetmpc;
872                         /* if the entry contains an mcode pointer (normal case), resolve it */
873                         /* (see doc/inlining_stacktrace.txt for details)                    */
874                         if (lr->linenumber >= -2) {
875                             target += (ptrint) epoint;
876                         }
877                         *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) = 
878                                 (functionptr) target;
879                 }
880                 
881                 *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
882                         (functionptr) ((ptrint) epoint + cd->linenumbertab);
883
884                 *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
885         }
886
887 #if defined(ENABLE_REPLACEMENT)
888         /* replacement point resolving */
889         {
890                 int i;
891                 rplpoint *rp;
892
893                 code->replacementstubs += (ptrint) epoint;
894
895                 rp = code->rplpoints;
896                 for (i=0; i<code->rplpointcount; ++i, ++rp) {
897                         rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
898                 }
899         }
900 #endif /* defined(ENABLE_REPLACEMENT) */
901
902         /* add method into methodtree to find the entrypoint */
903
904         codegen_insertmethod(code->entrypoint, code->entrypoint + mcodelen);
905
906 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
907         /* resolve data segment references */
908
909         dseg_resolve_datareferences(jd);
910 #endif
911
912 #if defined(ENABLE_THREADS)
913         {
914                 critical_section_node_t *n = (critical_section_node_t *) ((ptrint) code->mcode + alignedlen);
915                 s4 i;
916                 codegen_critical_section_t *nt = cd->threadcrit;
917
918                 for (i = 0; i < cd->threadcritcount; i++) {
919                         n->mcodebegin = (u1 *) (ptrint) code->mcode + nt->mcodebegin;
920                         n->mcodeend = (u1 *) (ptrint) code->mcode + nt->mcodeend;
921                         n->mcoderestart = (u1 *) (ptrint) code->mcode + nt->mcoderestart;
922                         critical_register_critical_section(n);
923                         n++;
924                         nt = nt->next;
925                 }
926         }
927 #endif
928
929         /* flush the instruction and data caches */
930
931         md_cacheflush(code->mcode, code->mcodelength);
932 }
933
934
935 /* codegen_createnativestub ****************************************************
936
937    Wrapper for createnativestub.
938
939    Returns:
940        the codeinfo representing the stub code.
941
942 *******************************************************************************/
943
944 codeinfo *codegen_createnativestub(functionptr f, methodinfo *m)
945 {
946         jitdata     *jd;
947         codeinfo    *code;
948         s4           dumpsize;
949         methoddesc  *md;
950         methoddesc  *nmd;       
951         s4           nativeparams;
952
953         /* mark dump memory */
954
955         dumpsize = dump_size();
956
957         jd = DNEW(jitdata);
958
959         jd->m     = m;
960         jd->cd    = DNEW(codegendata);
961         jd->rd    = DNEW(registerdata);
962         jd->flags = 0;
963
964         /* Allocate codeinfo memory from the heap as we need to keep them. */
965
966         jd->code  = code_codeinfo_new(m); /* XXX check allocation */
967
968         /* get required compiler data */
969
970         code = jd->code;
971
972         /* set the flags for the current JIT run */
973
974 #if defined(ENABLE_PROFILING)
975         if (opt_prof)
976                 jd->flags |= JITDATA_FLAG_INSTRUMENT;
977 #endif
978
979         if (opt_verbosecall)
980                 jd->flags |= JITDATA_FLAG_VERBOSECALL;
981
982         /* setup code generation stuff */
983
984 #if defined(ENABLE_JIT)
985 # if defined(ENABLE_INTRP)
986         if (!opt_intrp)
987 # endif
988                 reg_setup(jd);
989 #endif
990
991         codegen_setup(jd);
992
993         /* create new method descriptor with additional native parameters */
994
995         md = m->parseddesc;
996         nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
997         
998         nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
999                                                            md->paramcount * sizeof(typedesc) +
1000                                                            nativeparams * sizeof(typedesc));
1001
1002         nmd->paramcount = md->paramcount + nativeparams;
1003
1004         nmd->params = DMNEW(paramdesc, nmd->paramcount);
1005
1006         nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer            */
1007
1008         if (m->flags & ACC_STATIC)
1009                 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer              */
1010
1011         MCOPY(nmd->paramtypes + nativeparams, md->paramtypes, typedesc,
1012                   md->paramcount);
1013
1014 #if defined(ENABLE_JIT)
1015 # if defined(ENABLE_INTRP)
1016         if (!opt_intrp)
1017 # endif
1018                 /* pre-allocate the arguments for the native ABI */
1019
1020                 md_param_alloc_native(nmd);
1021 #endif
1022
1023         /* generate the code */
1024
1025 #if defined(ENABLE_JIT)
1026 # if defined(ENABLE_INTRP)
1027         if (opt_intrp)
1028                 code->entrypoint = intrp_createnativestub(f, jd, nmd);
1029         else
1030 # endif
1031                 code->entrypoint = createnativestub(f, jd, nmd);
1032 #else
1033         code->entrypoint = intrp_createnativestub(f, jd, nmd);
1034 #endif
1035
1036 #if defined(ENABLE_STATISTICS)
1037         if (opt_stat)
1038                 count_nstub_len += code->mcodelength;
1039 #endif
1040
1041 #if !defined(NDEBUG)
1042         /* disassemble native stub */
1043
1044         if (opt_shownativestub) {
1045 #if defined(ENABLE_DISASSEMBLER)
1046                 codegen_disassemble_nativestub(m,
1047                                                                            (u1 *) (ptrint) code->entrypoint,
1048                                                                            (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
1049 #endif
1050
1051                 /* show data segment */
1052
1053                 if (opt_showddatasegment)
1054                         dseg_display(jd);
1055         }
1056 #endif /* !defined(NDEBUG) */
1057
1058         /* release memory */
1059
1060         dump_release(dumpsize);
1061
1062         /* return native stub code */
1063
1064         return code;
1065 }
1066
1067
1068 /* codegen_disassemble_nativestub **********************************************
1069
1070    Disassembles the generated native stub.
1071
1072 *******************************************************************************/
1073
1074 #if defined(ENABLE_DISASSEMBLER)
1075 void codegen_disassemble_nativestub(methodinfo *m, u1 *start, u1 *end)
1076 {
1077         printf("Native stub: ");
1078         utf_fprint_printable_ascii_classname(stdout, m->class->name);
1079         printf(".");
1080         utf_fprint_printable_ascii(stdout, m->name);
1081         utf_fprint_printable_ascii(stdout, m->descriptor);
1082         printf("\n\nLength: %d\n\n", (s4) (end - start));
1083
1084         DISASSEMBLE(start, end);
1085 }
1086 #endif
1087
1088
1089 /* codegen_start_native_call ***************************************************
1090
1091    Prepares the stuff required for a native (JNI) function call:
1092
1093    - adds a stackframe info structure to the chain, for stacktraces
1094    - prepares the local references table on the stack
1095
1096    The layout of the native stub stackframe should look like this:
1097
1098    +---------------------------+ <- SP (of parent Java function)
1099    | return address            |
1100    +---------------------------+
1101    |                           |
1102    | stackframe info structure |
1103    |                           |
1104    +---------------------------+
1105    |                           |
1106    | local references table    |
1107    |                           |
1108    +---------------------------+
1109    |                           |
1110    | arguments (if any)        |
1111    |                           |
1112    +---------------------------+ <- SP (native stub)
1113
1114 *******************************************************************************/
1115
1116 void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
1117 {
1118         stackframeinfo *sfi;
1119         localref_table *lrt;
1120
1121         /* get data structures from stack */
1122
1123         sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1124         lrt = (localref_table *) (datasp - sizeof(stackframeinfo) - 
1125                                                           sizeof(localref_table));
1126
1127         /* add a stackframeinfo to the chain */
1128
1129         stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
1130
1131 #if defined(ENABLE_JAVASE)
1132         /* add current JNI local references table to this thread */
1133
1134         lrt->capacity    = LOCALREFTABLE_CAPACITY;
1135         lrt->used        = 0;
1136         lrt->localframes = 1;
1137         lrt->prev        = LOCALREFTABLE;
1138
1139         /* clear the references array (memset is faster the a for-loop) */
1140
1141         MSET(lrt->refs, 0, java_objectheader*, LOCALREFTABLE_CAPACITY);
1142
1143         LOCALREFTABLE = lrt;
1144 #endif
1145
1146 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1147         /* set the native world flag */
1148
1149         THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE;
1150 #endif
1151 }
1152
1153
1154 /* codegen_finish_native_call **************************************************
1155
1156    Removes the stuff required for a native (JNI) function call.
1157    Additionally it checks for an exceptions and in case, get the
1158    exception object and clear the pointer.
1159
1160 *******************************************************************************/
1161
1162 java_objectheader *codegen_finish_native_call(u1 *datasp)
1163 {
1164         stackframeinfo     *sfi;
1165         stackframeinfo    **psfi;
1166         localref_table     *lrt;
1167         localref_table     *plrt;
1168         s4                  localframes;
1169         java_objectheader  *e;
1170
1171         /* get data structures from stack */
1172
1173         sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1174         lrt = (localref_table *) (datasp - sizeof(stackframeinfo) - 
1175                                                           sizeof(localref_table));
1176
1177 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1178         /* clear the native world flag */
1179
1180         THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE;
1181 #endif
1182
1183         /* remove current stackframeinfo from chain */
1184
1185         psfi = &STACKFRAMEINFO;
1186
1187         *psfi = sfi->prev;
1188
1189 #if defined(ENABLE_JAVASE)
1190         /* release JNI local references tables for this thread */
1191
1192         lrt = LOCALREFTABLE;
1193
1194         /* release all current local frames */
1195
1196         for (localframes = lrt->localframes; localframes >= 1; localframes--) {
1197                 /* get previous frame */
1198
1199                 plrt = lrt->prev;
1200
1201                 /* Clear all reference entries (only for tables allocated on
1202                    the Java heap). */
1203
1204                 if (localframes > 1)
1205                         MSET(&lrt->refs[0], 0, java_objectheader*, lrt->capacity);
1206
1207                 lrt->prev = NULL;
1208
1209                 /* set new local references table */
1210
1211                 lrt = plrt;
1212         }
1213
1214         /* now store the previous local frames in the thread structure */
1215
1216         LOCALREFTABLE = lrt;
1217 #endif
1218
1219         /* get the exception and return it */
1220
1221         e = exceptions_get_and_clear_exception();
1222
1223         return e;
1224 }
1225
1226
1227 /* removecompilerstub **********************************************************
1228
1229    Deletes a compilerstub from memory (simply by freeing it).
1230
1231 *******************************************************************************/
1232
1233 void removecompilerstub(u1 *stub)
1234 {
1235         /* pass size 1 to keep the intern function happy */
1236
1237         CFREE((void *) stub, 1);
1238 }
1239
1240
1241 /* removenativestub ************************************************************
1242
1243    Removes a previously created native-stub from memory.
1244     
1245 *******************************************************************************/
1246
1247 void removenativestub(u1 *stub)
1248 {
1249         /* pass size 1 to keep the intern function happy */
1250
1251         CFREE((void *) stub, 1);
1252 }
1253
1254
1255 /* codegen_reg_of_var **********************************************************
1256
1257    This function determines a register, to which the result of an
1258    operation should go, when it is ultimatively intended to store the
1259    result in pseudoregister v.  If v is assigned to an actual
1260    register, this register will be returned.  Otherwise (when v is
1261    spilled) this function returns tempregnum.  If not already done,
1262    regoff and flags are set in the stack location.
1263        
1264    On ARM we have to check if a long/double variable is splitted
1265    across reg/stack (HIGH_REG == REG_SPLIT). We return the actual
1266    register of v for LOW_REG and the tempregnum for HIGH_REG in such
1267    cases.  (michi 2005/07/24)
1268
1269 *******************************************************************************/
1270
1271 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
1272 {
1273
1274 #if 0
1275         /* Do we have to generate a conditional move?  Yes, then always
1276            return the temporary register.  The real register is identified
1277            during the store. */
1278
1279         if (opcode & ICMD_CONDITION_MASK)
1280                 return tempregnum;
1281 #endif
1282
1283         if (!(v->flags & INMEMORY)) {
1284 #if defined(__ARM__) && defined(__ARMEL__)
1285                 if (IS_2_WORD_TYPE(v->type) && (GET_HIGH_REG(v->vv.regoff) == REG_SPLIT))
1286                         return PACK_REGS(GET_LOW_REG(v->vv.regoff),
1287                                                          GET_HIGH_REG(tempregnum));
1288 #endif
1289 #if defined(__ARM__) && defined(__ARMEB__)
1290                 if (IS_2_WORD_TYPE(v->type) && (GET_LOW_REG(v->vv.regoff) == REG_SPLIT))
1291                         return PACK_REGS(GET_LOW_REG(tempregnum),
1292                                                          GET_HIGH_REG(v->vv.regoff));
1293 #endif
1294                 return v->vv.regoff;
1295         }
1296
1297 #if defined(ENABLE_STATISTICS)
1298         if (opt_stat)
1299                 count_spills_read++;
1300 #endif
1301
1302         return tempregnum;
1303 }
1304
1305 /* codegen_reg_of_dst **********************************************************
1306
1307    This function determines a register, to which the result of an
1308    operation should go, when it is ultimatively intended to store the
1309    result in iptr->dst.var.  If dst.var is assigned to an actual
1310    register, this register will be returned.  Otherwise (when it is
1311    spilled) this function returns tempregnum.  If not already done,
1312    regoff and flags are set in the stack location.
1313        
1314    On ARM we have to check if a long/double variable is splitted
1315    across reg/stack (HIGH_REG == REG_SPLIT). We return the actual
1316    register of dst.var for LOW_REG and the tempregnum for HIGH_REG in such
1317    cases.  (michi 2005/07/24)
1318
1319 *******************************************************************************/
1320
1321 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
1322 {
1323         return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
1324 }
1325
1326
1327 #if defined(ENABLE_THREADS)
1328 void codegen_threadcritrestart(codegendata *cd, int offset)
1329 {
1330         cd->threadcritcurrent.mcoderestart = offset;
1331 }
1332
1333
1334 void codegen_threadcritstart(codegendata *cd, int offset)
1335 {
1336         cd->threadcritcurrent.mcodebegin = offset;
1337 }
1338
1339
1340 void codegen_threadcritstop(codegendata *cd, int offset)
1341 {
1342         cd->threadcritcurrent.next = cd->threadcrit;
1343         cd->threadcritcurrent.mcodeend = offset;
1344         cd->threadcrit = DNEW(codegen_critical_section_t);
1345         *(cd->threadcrit) = cd->threadcritcurrent;
1346         cd->threadcritcount++;
1347 }
1348 #endif
1349
1350
1351 /*
1352  * These are local overrides for various environment variables in Emacs.
1353  * Please do not remove this and leave it at the end of the file, where
1354  * Emacs will automagically detect them.
1355  * ---------------------------------------------------------------------
1356  * Local variables:
1357  * mode: c
1358  * indent-tabs-mode: t
1359  * c-basic-offset: 4
1360  * tab-width: 4
1361  * End:
1362  * vim:noexpandtab:sw=4:ts=4:
1363  */