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