1 /* src/vm/jit/codegen-common.c - architecture independent code generator stuff
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
8 This file is part of CACAO.
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.
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.
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
25 All functions assume the following code area / data area layout:
29 | code area | code area grows to higher addresses
31 +-----------+ <-- start of procedure
33 | data area | data area grows to lower addresses
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).
42 $Id: codegen-common.c 8179 2007-07-05 11:21:08Z michi $
54 #if defined(ENABLE_JIT)
55 /* this is required PATCHER_CALL_SIZE */
59 #include "mm/memory.h"
61 #include "toolbox/avl.h"
62 #include "toolbox/list.h"
63 #include "toolbox/logging.h"
65 #include "native/jni.h"
66 #include "native/native.h"
68 #include "threads/threads-common.h"
70 #include "vm/builtin.h"
71 #include "vm/exceptions.h"
72 #include "vm/stringlocal.h"
74 #include "vm/jit/abi.h"
75 #include "vm/jit/asmpart.h"
76 #include "vm/jit/codegen-common.h"
78 #if defined(ENABLE_DISASSEMBLER)
79 # include "vm/jit/disass.h"
82 #include "vm/jit/dseg.h"
83 #include "vm/jit/emit-common.h"
84 #include "vm/jit/jit.h"
85 #include "vm/jit/md.h"
86 #include "vm/jit/patcher-common.h"
87 #include "vm/jit/replace.h"
88 #if defined(ENABLE_SSA)
89 # include "vm/jit/optimizing/lsra.h"
90 # include "vm/jit/optimizing/ssa.h"
92 #include "vm/jit/stacktrace.h"
94 #if defined(ENABLE_INTRP)
95 #include "vm/jit/intrp/intrp.h"
98 #include "vmcore/method.h"
99 #include "vmcore/options.h"
101 # include "vmcore/statistics.h"
103 #if defined(ENABLE_VMLOG)
104 #include <vmlog_cacao.h>
109 /* in this tree we store all method addresses *********************************/
111 static avl_tree_t *methodtree = NULL;
112 static s4 methodtree_comparator(const void *treenode, const void *node);
115 /* codegen_init ****************************************************************
119 *******************************************************************************/
121 void codegen_init(void)
123 /* this tree is global, not method specific */
126 #if defined(ENABLE_JIT)
127 methodtree_element *mte;
130 methodtree = avl_create(&methodtree_comparator);
132 #if defined(ENABLE_JIT)
133 /* insert asm_vm_call_method */
135 mte = NEW(methodtree_element);
137 mte->startpc = (u1 *) (ptrint) asm_vm_call_method;
138 mte->endpc = (u1 *) (ptrint) asm_vm_call_method_end;
140 avl_insert(methodtree, mte);
141 #endif /* defined(ENABLE_JIT) */
148 /* codegen_setup ***************************************************************
150 Allocates and initialises code area, data area and references.
152 *******************************************************************************/
154 void codegen_setup(jitdata *jd)
159 /* get required compiler data */
164 /* initialize members */
168 cd->mcodebase = DMNEW(u1, MCODEINITSIZE);
169 cd->mcodeend = cd->mcodebase + MCODEINITSIZE;
170 cd->mcodesize = MCODEINITSIZE;
172 /* initialize mcode variables */
174 cd->mcodeptr = cd->mcodebase;
175 cd->lastmcodeptr = cd->mcodebase;
177 #if defined(ENABLE_INTRP)
178 /* native dynamic superinstructions variables */
181 cd->ncodebase = DMNEW(u1, NCODEINITSIZE);
182 cd->ncodesize = NCODEINITSIZE;
184 /* initialize ncode variables */
186 cd->ncodeptr = cd->ncodebase;
188 cd->lastinstwithoutdispatch = ~0; /* no inst without dispatch */
189 cd->superstarts = NULL;
196 cd->jumpreferences = NULL;
198 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
199 cd->datareferences = NULL;
202 /* cd->patchrefs = list_create_dump(OFFSET(patchref, linkage)); */
203 cd->patchrefs = NULL;
204 cd->brancheslabel = list_create_dump(OFFSET(branch_label_ref_t, linkage));
205 cd->listcritical = list_create_dump(OFFSET(critical_section_ref_t, linkage));
207 cd->linenumberreferences = NULL;
208 cd->linenumbertablesizepos = 0;
209 cd->linenumbertablestartpos = 0;
210 cd->linenumbertab = 0;
214 /* codegen_reset ***************************************************************
216 Resets the codegen data structure so we can recompile the method.
218 *******************************************************************************/
220 static void codegen_reset(jitdata *jd)
226 /* get required compiler data */
231 /* reset error flag */
233 cd->flags &= ~CODEGENDATA_FLAG_ERROR;
235 /* reset some members, we reuse the code memory already allocated
236 as this should have almost the correct size */
238 cd->mcodeptr = cd->mcodebase;
239 cd->lastmcodeptr = cd->mcodebase;
244 cd->jumpreferences = NULL;
246 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
247 cd->datareferences = NULL;
250 /* cd->patchrefs = list_create_dump(OFFSET(patchref, linkage)); */
251 cd->patchrefs = NULL;
252 cd->brancheslabel = list_create_dump(OFFSET(branch_label_ref_t, linkage));
253 cd->listcritical = list_create_dump(OFFSET(critical_section_ref_t, linkage));
255 cd->linenumberreferences = NULL;
256 cd->linenumbertablesizepos = 0;
257 cd->linenumbertablestartpos = 0;
258 cd->linenumbertab = 0;
260 /* We need to clear the mpc and the branch references from all
261 basic blocks as they will definitely change. */
263 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
265 bptr->branchrefs = NULL;
268 #if defined(ENABLE_REPLACEMENT)
269 code->rplpoints = NULL;
270 code->rplpointcount = 0;
271 code->regalloc = NULL;
272 code->regalloccount = 0;
273 code->globalcount = 0;
278 /* codegen_generate ************************************************************
280 Generates the code for the currently compiled method.
282 *******************************************************************************/
284 bool codegen_generate(jitdata *jd)
288 /* get required compiler data */
292 /* call the machine-dependent code generation function */
294 if (!codegen_emit(jd))
297 /* check for an error */
299 if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
300 /* check for long-branches flag, if it is set we recompile the
305 log_message_method("Re-generating code: ", jd->m);
308 /* XXX maybe we should tag long-branches-methods for recompilation */
310 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
311 /* we have to reset the codegendata structure first */
315 /* and restart the compiler run */
317 if (!codegen_emit(jd))
321 vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
326 log_message_method("Re-generating code done: ", jd->m);
330 /* reallocate the memory and finish the code generation */
334 /* everything's ok */
340 /* codegen_close ***************************************************************
344 *******************************************************************************/
346 void codegen_close(void)
348 /* TODO: release avl tree on i386 and x86_64 */
352 /* codegen_increase ************************************************************
356 *******************************************************************************/
358 void codegen_increase(codegendata *cd)
362 /* save old mcodebase pointer */
364 oldmcodebase = cd->mcodebase;
366 /* reallocate to new, doubled memory */
368 cd->mcodebase = DMREALLOC(cd->mcodebase,
373 cd->mcodeend = cd->mcodebase + cd->mcodesize;
375 /* set new mcodeptr */
377 cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
379 #if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(__M68K__) || defined(ENABLE_INTRP) \
380 || defined(__SPARC_64__)
381 /* adjust the pointer to the last patcher position */
383 if (cd->lastmcodeptr != NULL)
384 cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
389 /* codegen_ncode_increase ******************************************************
393 *******************************************************************************/
395 #if defined(ENABLE_INTRP)
396 u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
400 /* save old ncodebase pointer */
402 oldncodebase = cd->ncodebase;
404 /* reallocate to new, doubled memory */
406 cd->ncodebase = DMREALLOC(cd->ncodebase,
412 /* return the new ncodeptr */
414 return (cd->ncodebase + (ncodeptr - oldncodebase));
419 /* codegen_add_branch_ref ******************************************************
421 Prepends an branch to the list.
423 *******************************************************************************/
425 void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
430 STATISTICS(count_branches_unresolved++);
432 /* calculate the mpc of the branch instruction */
434 branchmpc = cd->mcodeptr - cd->mcodebase;
436 br = DNEW(branchref);
438 br->branchmpc = branchmpc;
439 br->condition = condition;
441 br->options = options;
442 br->next = target->branchrefs;
444 target->branchrefs = br;
448 /* codegen_resolve_branchrefs **************************************************
450 Resolves and patches the branch references of a given basic block.
452 *******************************************************************************/
454 void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
459 /* Save the mcodeptr because in the branch emitting functions
460 we generate code somewhere inside already generated code,
461 but we're still in the actual code generation phase. */
463 mcodeptr = cd->mcodeptr;
465 /* just to make sure */
467 assert(bptr->mpc >= 0);
469 for (br = bptr->branchrefs; br != NULL; br = br->next) {
470 /* temporary set the mcodeptr */
472 cd->mcodeptr = cd->mcodebase + br->branchmpc;
474 /* emit_bccz and emit_branch emit the correct code, even if we
475 pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
477 emit_bccz(cd, bptr, br->condition, br->reg, br->options);
480 /* restore mcodeptr */
482 cd->mcodeptr = mcodeptr;
486 /* codegen_branch_label_add ****************************************************
488 Append an branch to the label-branch list.
490 *******************************************************************************/
492 void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
495 branch_label_ref_t *br;
498 /* get the label list */
500 list = cd->brancheslabel;
502 /* calculate the current mpc */
504 mpc = cd->mcodeptr - cd->mcodebase;
506 br = DNEW(branch_label_ref_t);
510 br->condition = condition;
512 br->options = options;
514 /* add the branch to the list */
516 list_add_last_unsynced(list, br);
520 /* codegen_add_patch_ref *******************************************************
522 Appends a new patcher reference to the list of patching positions.
524 *******************************************************************************/
526 void codegen_add_patch_ref(codegendata *cd, functionptr patcher, voidptr ref,
532 branchmpc = cd->mcodeptr - cd->mcodebase;
536 pr->branchpos = branchmpc;
538 pr->patcher = patcher;
541 /* list_add_first(cd->patchrefs, pr); */
542 pr->next = cd->patchrefs;
545 /* Generate NOPs for opt_shownops. */
550 /* If the codegen provides a PACHER_LONGBRANCHES_NOPS macro, honour it. */
552 #if defined(PATCHER_LONGBRANCHES_NOPS)
553 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
554 PATCHER_LONGBRANCHES_NOPS;
558 #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__M68K__) || defined(__MIPS__) \
559 || defined(__SPARC_64__) || defined(__X86_64__))
561 /* On some architectures the patcher stub call instruction might
562 be longer than the actual instruction generated. On this
563 architectures we store the last patcher call position and after
564 the basic block code generation is completed, we check the
565 range and maybe generate some nop's. */
566 /* The nops are generated in codegen_emit in each codegen */
568 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
573 /* codegen_critical_section_new ************************************************
575 Allocates a new critical-section reference and adds it to the
576 critical-section list.
578 *******************************************************************************/
580 #if defined(ENABLE_THREADS)
581 void codegen_critical_section_new(codegendata *cd)
584 critical_section_ref_t *csr;
587 /* get the critical section list */
589 list = cd->listcritical;
591 /* calculate the current mpc */
593 mpc = cd->mcodeptr - cd->mcodebase;
595 csr = DNEW(critical_section_ref_t);
597 /* We only can set restart right now, as start and end are set by
598 the following, corresponding functions. */
604 /* add the branch to the list */
606 list_add_last_unsynced(list, csr);
611 /* codegen_critical_section_start **********************************************
613 Set the start-point of the current critical section (which is the
614 last element of the list).
616 *******************************************************************************/
618 #if defined(ENABLE_THREADS)
619 void codegen_critical_section_start(codegendata *cd)
622 critical_section_ref_t *csr;
625 /* get the critical section list */
627 list = cd->listcritical;
629 /* calculate the current mpc */
631 mpc = cd->mcodeptr - cd->mcodebase;
633 /* get the current critical section */
635 csr = list_last_unsynced(list);
637 /* set the start point */
639 assert(csr->start == -1);
646 /* codegen_critical_section_end ************************************************
648 Set the end-point of the current critical section (which is the
649 last element of the list).
651 *******************************************************************************/
653 #if defined(ENABLE_THREADS)
654 void codegen_critical_section_end(codegendata *cd)
657 critical_section_ref_t *csr;
660 /* get the critical section list */
662 list = cd->listcritical;
664 /* calculate the current mpc */
666 mpc = cd->mcodeptr - cd->mcodebase;
668 /* get the current critical section */
670 csr = list_last_unsynced(list);
672 /* set the end point */
674 assert(csr->end == -1);
681 /* codegen_critical_section_finish *********************************************
683 Finish the critical sections, create the critical section nodes for
684 the AVL tree and insert them into the tree.
686 *******************************************************************************/
688 #if defined(ENABLE_THREADS)
689 static void codegen_critical_section_finish(jitdata *jd)
694 critical_section_ref_t *csr;
695 critical_section_node_t *csn;
697 /* get required compiler data */
702 /* get the critical section list */
704 list = cd->listcritical;
706 /* iterate over all critical sections */
708 for (csr = list_first_unsynced(list); csr != NULL;
709 csr = list_next_unsynced(list, csr)) {
710 /* check if all points are set */
712 assert(csr->start != -1);
713 assert(csr->end != -1);
714 assert(csr->restart != -1);
716 /* allocate tree node */
718 csn = NEW(critical_section_node_t);
720 csn->start = code->entrypoint + csr->start;
721 csn->end = code->entrypoint + csr->end;
722 csn->restart = code->entrypoint + csr->restart;
724 /* insert into the tree */
726 critical_section_register(csn);
732 /* methodtree_comparator *******************************************************
734 Comparator function used for the AVL tree of methods.
737 treenode....the node from the tree
738 node........the node to compare to the tree-node
740 *******************************************************************************/
742 static s4 methodtree_comparator(const void *treenode, const void *node)
744 methodtree_element *mte;
745 methodtree_element *mtepc;
747 mte = (methodtree_element *) treenode;
748 mtepc = (methodtree_element *) node;
750 /* compare both startpc and endpc of pc, even if they have the same value,
751 otherwise the avl_probe sometimes thinks the element is already in the
755 /* On S390 addresses are 31 bit. Compare only 31 bits of value.
757 # define ADDR_MASK(a) ((a) & 0x7FFFFFFF)
759 # define ADDR_MASK(a) (a)
762 if (ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->startpc) &&
763 ADDR_MASK((long) mtepc->startpc) <= ADDR_MASK((long) mte->endpc) &&
764 ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->endpc) &&
765 ADDR_MASK((long) mtepc->endpc) <= ADDR_MASK((long) mte->endpc)) {
768 } else if (ADDR_MASK((long) mtepc->startpc) < ADDR_MASK((long) mte->startpc)) {
779 /* codegen_insertmethod ********************************************************
781 Insert the machine code range of a method into the AVL tree of methods.
783 *******************************************************************************/
785 void codegen_insertmethod(u1 *startpc, u1 *endpc)
787 methodtree_element *mte;
789 /* allocate new method entry */
791 mte = NEW(methodtree_element);
793 mte->startpc = startpc;
796 /* this function does not return an error, but asserts for
799 avl_insert(methodtree, mte);
803 /* codegen_get_pv_from_pc ******************************************************
805 Find the PV for the given PC by searching in the AVL tree of
808 *******************************************************************************/
810 u1 *codegen_get_pv_from_pc(u1 *pc)
812 methodtree_element mtepc;
813 methodtree_element *mte;
815 /* allocation of the search structure on the stack is much faster */
820 mte = avl_find(methodtree, &mtepc);
823 /* No method was found. Let's dump a stacktrace. */
825 #if defined(ENABLE_VMLOG)
826 vmlog_cacao_signl("SIGSEGV");
829 log_println("We received a SIGSEGV and tried to handle it, but we were");
830 log_println("unable to find a Java method at:");
832 #if SIZEOF_VOID_P == 8
833 log_println("PC=0x%016lx", pc);
835 log_println("PC=0x%08x", pc);
839 log_println("Dumping the current stacktrace:");
841 #if defined(ENABLE_THREADS)
842 /* XXX michi: This should be available even without threads! */
843 threads_print_stacktrace();
846 vm_abort("Exiting...");
853 /* codegen_get_pv_from_pc_nocheck **********************************************
855 Find the PV for the given PC by searching in the AVL tree of
856 methods. This method does not check the return value and is used
859 *******************************************************************************/
861 u1 *codegen_get_pv_from_pc_nocheck(u1 *pc)
863 methodtree_element mtepc;
864 methodtree_element *mte;
866 /* allocation of the search structure on the stack is much faster */
871 mte = avl_find(methodtree, &mtepc);
880 /* codegen_set_replacement_point_notrap ****************************************
882 Record the position of a non-trappable replacement point.
884 *******************************************************************************/
886 #if defined(ENABLE_REPLACEMENT)
888 void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
890 void codegen_set_replacement_point_notrap(codegendata *cd)
893 assert(cd->replacementpoint);
894 assert(cd->replacementpoint->type == type);
895 assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
897 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
899 cd->replacementpoint++;
901 #endif /* defined(ENABLE_REPLACEMENT) */
904 /* codegen_set_replacement_point ***********************************************
906 Record the position of a trappable replacement point.
908 *******************************************************************************/
910 #if defined(ENABLE_REPLACEMENT)
912 void codegen_set_replacement_point(codegendata *cd, s4 type)
914 void codegen_set_replacement_point(codegendata *cd)
917 assert(cd->replacementpoint);
918 assert(cd->replacementpoint->type == type);
919 assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
921 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
923 cd->replacementpoint++;
925 /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
927 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
929 #endif /* defined(ENABLE_REPLACEMENT) */
932 /* codegen_finish **************************************************************
934 Finishes the code generation. A new memory, large enough for both
935 data and code, is allocated and data and code are copied together
936 to their final layout, unresolved jumps are resolved, ...
938 *******************************************************************************/
940 void codegen_finish(jitdata *jd)
945 #if defined(ENABLE_INTRP)
954 /* get required compiler data */
959 /* prevent compiler warning */
961 #if defined(ENABLE_INTRP)
965 /* calculate the code length */
967 mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
969 #if defined(ENABLE_STATISTICS)
971 count_code_len += mcodelen;
972 count_data_len += cd->dseglen;
976 alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
978 #if defined(ENABLE_INTRP)
980 ncodelen = cd->ncodeptr - cd->ncodebase;
982 ncodelen = 0; /* avoid compiler warning */
986 cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
987 alignedlen = alignedmcodelen + cd->dseglen;
989 #if defined(ENABLE_INTRP)
991 alignedlen += ncodelen;
995 /* allocate new memory */
997 code->mcodelength = mcodelen + cd->dseglen;
998 code->mcode = CNEW(u1, alignedlen);
1000 /* set the entrypoint of the method */
1002 assert(code->entrypoint == NULL);
1003 code->entrypoint = epoint = (code->mcode + cd->dseglen);
1005 /* fill the data segment (code->entrypoint must already be set!) */
1009 /* copy code to the new location */
1011 MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
1013 #if defined(ENABLE_INTRP)
1014 /* relocate native dynamic superinstruction code (if any) */
1017 cd->mcodebase = code->entrypoint;
1020 u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
1022 MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
1024 /* flush the instruction and data caches */
1026 md_cacheflush(ncodebase, ncodelen);
1028 /* set some cd variables for dynamic_super_rerwite */
1030 cd->ncodebase = ncodebase;
1033 cd->ncodebase = NULL;
1036 dynamic_super_rewrite(cd);
1040 /* jump table resolving */
1042 for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
1043 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
1044 (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
1046 /* line number table resolving */
1052 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
1054 target = lr->targetmpc;
1055 /* if the entry contains an mcode pointer (normal case), resolve it */
1056 /* (see doc/inlining_stacktrace.txt for details) */
1057 if (lr->linenumber >= -2) {
1058 target += (ptrint) epoint;
1060 *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) =
1061 (functionptr) target;
1064 *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
1065 (functionptr) ((ptrint) epoint + cd->linenumbertab);
1067 *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
1070 /* patcher resolving */
1072 pr = list_first_unsynced(code->patchers);
1074 pr->mpc += (ptrint) epoint;
1075 pr->datap = (ptrint) (pr->disp + epoint);
1076 pr = list_next_unsynced(code->patchers, pr);
1079 #if defined(ENABLE_REPLACEMENT)
1080 /* replacement point resolving */
1085 code->replacementstubs += (ptrint) epoint;
1087 rp = code->rplpoints;
1088 for (i=0; i<code->rplpointcount; ++i, ++rp) {
1089 rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
1092 #endif /* defined(ENABLE_REPLACEMENT) */
1094 /* add method into methodtree to find the entrypoint */
1096 codegen_insertmethod(code->entrypoint, code->entrypoint + mcodelen);
1098 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
1099 /* resolve data segment references */
1101 dseg_resolve_datareferences(jd);
1104 #if defined(ENABLE_THREADS)
1105 /* create cirtical sections */
1107 codegen_critical_section_finish(jd);
1110 /* flush the instruction and data caches */
1112 md_cacheflush(code->mcode, code->mcodelength);
1116 /* codegen_generate_stub_compiler **********************************************
1118 Wrapper for codegen_emit_stub_compiler.
1121 pointer to the compiler stub code.
1123 *******************************************************************************/
1125 u1 *codegen_generate_stub_compiler(methodinfo *m)
1129 ptrint *d; /* pointer to data memory */
1130 u1 *c; /* pointer to code memory */
1133 /* mark dump memory */
1135 dumpsize = dump_size();
1137 /* allocate required data structures */
1142 jd->cd = DNEW(codegendata);
1145 /* get required compiler data */
1149 /* allocate code memory */
1151 c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1153 /* set pointers correctly */
1159 c = c + 3 * SIZEOF_VOID_P;
1162 /* NOTE: The codeinfo pointer is actually a pointer to the
1163 methodinfo (this fakes a codeinfo structure). */
1165 d[0] = (ptrint) asm_call_jit_compiler;
1167 d[2] = (ptrint) &d[1]; /* fake code->m */
1169 /* call the emit function */
1171 codegen_emit_stub_compiler(jd);
1173 #if defined(ENABLE_STATISTICS)
1175 count_cstub_len += 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
1180 md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1182 /* release dump memory */
1184 dump_release(dumpsize);
1186 /* return native stub code */
1192 /* codegen_generate_stub_builtin ***********************************************
1194 Wrapper for codegen_emit_stub_builtin.
1197 Pointer to the entrypoint of the stub.
1199 *******************************************************************************/
1201 void codegen_generate_stub_builtin(builtintable_entry *bte)
1207 /* mark dump memory */
1209 dumpsize = dump_size();
1214 jd->cd = DNEW(codegendata);
1218 /* Allocate codeinfo memory from the heap as we need to keep them. */
1220 jd->code = code_codeinfo_new(NULL);
1222 /* get required compiler data */
1226 /* setup code generation stuff */
1230 /* generate the code */
1232 #if defined(ENABLE_JIT)
1233 # if defined(ENABLE_INTRP)
1236 codegen_emit_stub_builtin(jd, bte);
1239 /* reallocate the memory and finish the code generation */
1243 /* set the stub entry point in the builtin table */
1245 bte->stub = code->entrypoint;
1247 #if defined(ENABLE_STATISTICS)
1249 size_stub_native += code->mcodelength;
1252 /* release memory */
1254 dump_release(dumpsize);
1258 /* codegen_generate_stub_native ************************************************
1260 Wrapper for codegen_emit_stub_native.
1263 the codeinfo representing the stub code.
1265 *******************************************************************************/
1267 codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
1276 /* mark dump memory */
1278 dumpsize = dump_size();
1283 jd->cd = DNEW(codegendata);
1284 jd->rd = DNEW(registerdata);
1287 /* Allocate codeinfo memory from the heap as we need to keep them. */
1289 jd->code = code_codeinfo_new(m); /* XXX check allocation */
1291 /* get required compiler data */
1295 /* set the flags for the current JIT run */
1297 #if defined(ENABLE_PROFILING)
1299 jd->flags |= JITDATA_FLAG_INSTRUMENT;
1302 if (opt_verbosecall)
1303 jd->flags |= JITDATA_FLAG_VERBOSECALL;
1305 /* setup code generation stuff */
1307 #if defined(ENABLE_JIT)
1308 # if defined(ENABLE_INTRP)
1316 /* create new method descriptor with additional native parameters */
1319 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
1321 nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
1322 md->paramcount * sizeof(typedesc) +
1323 nativeparams * sizeof(typedesc));
1325 nmd->paramcount = md->paramcount + nativeparams;
1327 nmd->params = DMNEW(paramdesc, nmd->paramcount);
1329 nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer */
1331 if (m->flags & ACC_STATIC)
1332 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer */
1334 MCOPY(nmd->paramtypes + nativeparams, md->paramtypes, typedesc,
1337 #if defined(ENABLE_JIT)
1338 # if defined(ENABLE_INTRP)
1341 /* pre-allocate the arguments for the native ABI */
1343 md_param_alloc_native(nmd);
1346 /* generate the code */
1348 #if defined(ENABLE_JIT)
1349 # if defined(ENABLE_INTRP)
1351 intrp_createnativestub(f, jd, nmd);
1354 codegen_emit_stub_native(jd, nmd, f);
1356 intrp_createnativestub(f, jd, nmd);
1359 /* reallocate the memory and finish the code generation */
1363 #if defined(ENABLE_STATISTICS)
1364 /* must be done after codegen_finish() */
1367 size_stub_native += code->mcodelength;
1370 #if !defined(NDEBUG)
1371 /* disassemble native stub */
1373 if (opt_shownativestub) {
1374 #if defined(ENABLE_DEBUG_FILTER)
1375 if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
1378 #if defined(ENABLE_DISASSEMBLER)
1379 codegen_disassemble_nativestub(m,
1380 (u1 *) (ptrint) code->entrypoint,
1381 (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
1384 /* show data segment */
1386 if (opt_showddatasegment)
1390 #endif /* !defined(NDEBUG) */
1392 /* release memory */
1394 dump_release(dumpsize);
1396 /* return native stub code */
1402 /* codegen_disassemble_nativestub **********************************************
1404 Disassembles the generated native stub.
1406 *******************************************************************************/
1408 #if defined(ENABLE_DISASSEMBLER)
1409 void codegen_disassemble_nativestub(methodinfo *m, u1 *start, u1 *end)
1411 printf("Native stub: ");
1412 utf_fprint_printable_ascii_classname(stdout, m->class->name);
1414 utf_fprint_printable_ascii(stdout, m->name);
1415 utf_fprint_printable_ascii(stdout, m->descriptor);
1416 printf("\n\nLength: %d\n\n", (s4) (end - start));
1418 DISASSEMBLE(start, end);
1423 /* codegen_stub_builtin_enter **************************************************
1425 Prepares the stuff required for a builtin function call:
1427 - adds a stackframe info structure to the chain, for stacktraces
1429 The layout of the builtin stub stackframe should look like this:
1431 +---------------------------+ <- SP (of parent Java function)
1433 +---------------------------+
1435 | stackframe info structure |
1437 +---------------------------+
1439 | arguments (if any) |
1441 +---------------------------+ <- SP (native stub)
1443 *******************************************************************************/
1445 void codegen_stub_builtin_enter(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
1447 stackframeinfo *sfi;
1449 /* get data structures from stack */
1451 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1453 /* add a stackframeinfo to the chain */
1455 stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
1457 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1458 /* set the native world flag */
1460 THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE;
1465 /* codegen_stub_builtin_exit ***************************************************
1467 Removes the stuff required for a builtin function call.
1469 *******************************************************************************/
1471 void codegen_stub_builtin_exit(u1 *datasp)
1473 stackframeinfo *sfi;
1474 stackframeinfo **psfi;
1476 /* get data structures from stack */
1478 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1480 /* remove current stackframeinfo from chain */
1482 psfi = &STACKFRAMEINFO;
1486 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1487 /* clear the native world flag */
1489 THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE;
1494 /* codegen_start_native_call ***************************************************
1496 Prepares the stuff required for a native (JNI) function call:
1498 - adds a stackframe info structure to the chain, for stacktraces
1499 - prepares the local references table on the stack
1501 The layout of the native stub stackframe should look like this:
1503 +---------------------------+ <- SP (of parent Java function)
1505 +---------------------------+
1507 | stackframe info structure |
1509 +---------------------------+
1511 | local references table |
1513 +---------------------------+
1515 | arguments (if any) |
1517 +---------------------------+ <- SP (native stub)
1519 *******************************************************************************/
1521 void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
1523 stackframeinfo *sfi;
1524 localref_table *lrt;
1526 STATISTICS(count_calls_java_to_native++);
1528 /* get data structures from stack */
1530 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1531 lrt = (localref_table *) (datasp - sizeof(stackframeinfo) -
1532 sizeof(localref_table));
1534 /* add a stackframeinfo to the chain */
1536 stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
1538 #if defined(ENABLE_JNI)
1539 /* add current JNI local references table to this thread */
1541 lrt->capacity = LOCALREFTABLE_CAPACITY;
1543 lrt->localframes = 1;
1544 lrt->prev = LOCALREFTABLE;
1546 /* clear the references array (memset is faster the a for-loop) */
1548 MSET(lrt->refs, 0, java_objectheader*, LOCALREFTABLE_CAPACITY);
1550 LOCALREFTABLE = lrt;
1553 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1554 /* set the native world flag */
1556 THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE;
1561 /* codegen_finish_native_call **************************************************
1563 Removes the stuff required for a native (JNI) function call.
1564 Additionally it checks for an exceptions and in case, get the
1565 exception object and clear the pointer.
1567 *******************************************************************************/
1569 java_objectheader *codegen_finish_native_call(u1 *datasp)
1571 stackframeinfo *sfi;
1572 stackframeinfo **psfi;
1573 #if defined(ENABLE_JNI)
1574 localref_table *lrt;
1575 localref_table *plrt;
1578 java_objectheader *e;
1580 /* get data structures from stack */
1582 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1584 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1585 /* clear the native world flag */
1587 THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE;
1590 /* remove current stackframeinfo from chain */
1592 psfi = &STACKFRAMEINFO;
1596 #if defined(ENABLE_JNI)
1597 /* release JNI local references tables for this thread */
1599 lrt = LOCALREFTABLE;
1601 /* release all current local frames */
1603 for (localframes = lrt->localframes; localframes >= 1; localframes--) {
1604 /* get previous frame */
1608 /* Clear all reference entries (only for tables allocated on
1611 if (localframes > 1)
1612 MSET(&lrt->refs[0], 0, java_objectheader*, lrt->capacity);
1616 /* set new local references table */
1621 /* now store the previous local frames in the thread structure */
1623 LOCALREFTABLE = lrt;
1626 /* get the exception and return it */
1628 e = exceptions_get_and_clear_exception();
1634 /* removecompilerstub **********************************************************
1636 Deletes a compilerstub from memory (simply by freeing it).
1638 *******************************************************************************/
1640 void removecompilerstub(u1 *stub)
1642 /* pass size 1 to keep the intern function happy */
1644 CFREE((void *) stub, 1);
1648 /* removenativestub ************************************************************
1650 Removes a previously created native-stub from memory.
1652 *******************************************************************************/
1654 void removenativestub(u1 *stub)
1656 /* pass size 1 to keep the intern function happy */
1658 CFREE((void *) stub, 1);
1662 /* codegen_reg_of_var **********************************************************
1664 This function determines a register, to which the result of an
1665 operation should go, when it is ultimatively intended to store the
1666 result in pseudoregister v. If v is assigned to an actual
1667 register, this register will be returned. Otherwise (when v is
1668 spilled) this function returns tempregnum. If not already done,
1669 regoff and flags are set in the stack location.
1671 *******************************************************************************/
1673 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
1677 /* Do we have to generate a conditional move? Yes, then always
1678 return the temporary register. The real register is identified
1679 during the store. */
1681 if (opcode & ICMD_CONDITION_MASK)
1685 if (!(v->flags & INMEMORY))
1686 return v->vv.regoff;
1692 /* codegen_reg_of_dst **********************************************************
1694 This function determines a register, to which the result of an
1695 operation should go, when it is ultimatively intended to store the
1696 result in iptr->dst.var. If dst.var is assigned to an actual
1697 register, this register will be returned. Otherwise (when it is
1698 spilled) this function returns tempregnum. If not already done,
1699 regoff and flags are set in the stack location.
1701 *******************************************************************************/
1703 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
1705 return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
1709 /* codegen_emit_phi_moves ****************************************************
1711 Emits phi moves at the end of the basicblock.
1713 *******************************************************************************/
1715 #if defined(ENABLE_SSA)
1716 void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
1729 /* Moves from phi functions with highest indices have to be */
1730 /* inserted first, since this is the order as is used for */
1731 /* conflict resolution */
1733 for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
1734 lt_d = ls->phi_moves[bptr->nr][i][0];
1735 lt_s = ls->phi_moves[bptr->nr][i][1];
1736 #if defined(SSA_DEBUG_VERBOSE)
1738 printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
1740 if (lt_s == UNUSED) {
1741 #if defined(SSA_DEBUG_VERBOSE)
1743 printf(" ... not processed \n");
1748 d = VAR(ls->lifetime[lt_d].v_index);
1749 s = VAR(ls->lifetime[lt_s].v_index);
1752 if (d->type == -1) {
1753 #if defined(SSA_DEBUG_VERBOSE)
1755 printf("...returning - phi lifetimes where joined\n");
1760 if (s->type == -1) {
1761 #if defined(SSA_DEBUG_VERBOSE)
1763 printf("...returning - phi lifetimes where joined\n");
1769 tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
1770 tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
1771 emit_copy(jd, &tmp_i);
1773 #if defined(SSA_DEBUG_VERBOSE)
1774 if (compileverbose) {
1775 if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
1777 printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1779 else if (IS_INMEMORY(s->flags)) {
1781 printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1783 else if (IS_INMEMORY(d->flags)) {
1785 printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1789 printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1793 #endif /* defined(SSA_DEBUG_VERBOSE) */
1796 #endif /* defined(ENABLE_SSA) */
1801 * These are local overrides for various environment variables in Emacs.
1802 * Please do not remove this and leave it at the end of the file, where
1803 * Emacs will automagically detect them.
1804 * ---------------------------------------------------------------------
1807 * indent-tabs-mode: t
1811 * vim:noexpandtab:sw=4:ts=4: