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