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