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