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 8314 2007-08-15 22:18:44Z twisti $
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/localref.h"
67 #include "native/native.h"
69 #include "threads/threads-common.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 /* We need to clear all the patcher references from the codeinfo
269 since they all will be regenerated */
271 patcher_list_reset(code);
273 #if defined(ENABLE_REPLACEMENT)
274 code->rplpoints = NULL;
275 code->rplpointcount = 0;
276 code->regalloc = NULL;
277 code->regalloccount = 0;
278 code->globalcount = 0;
283 /* codegen_generate ************************************************************
285 Generates the code for the currently compiled method.
287 *******************************************************************************/
289 bool codegen_generate(jitdata *jd)
293 /* get required compiler data */
297 /* call the machine-dependent code generation function */
299 if (!codegen_emit(jd))
302 /* check for an error */
304 if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
305 /* check for long-branches flag, if it is set we recompile the
310 log_message_method("Re-generating code: ", jd->m);
313 /* XXX maybe we should tag long-branches-methods for recompilation */
315 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
316 /* we have to reset the codegendata structure first */
320 /* and restart the compiler run */
322 if (!codegen_emit(jd))
326 vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
331 log_message_method("Re-generating code done: ", jd->m);
335 /* reallocate the memory and finish the code generation */
339 /* everything's ok */
345 /* codegen_close ***************************************************************
349 *******************************************************************************/
351 void codegen_close(void)
353 /* TODO: release avl tree on i386 and x86_64 */
357 /* codegen_increase ************************************************************
361 *******************************************************************************/
363 void codegen_increase(codegendata *cd)
367 /* save old mcodebase pointer */
369 oldmcodebase = cd->mcodebase;
371 /* reallocate to new, doubled memory */
373 cd->mcodebase = DMREALLOC(cd->mcodebase,
378 cd->mcodeend = cd->mcodebase + cd->mcodesize;
380 /* set new mcodeptr */
382 cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
384 #if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(__M68K__) || defined(ENABLE_INTRP) \
385 || defined(__SPARC_64__)
386 /* adjust the pointer to the last patcher position */
388 if (cd->lastmcodeptr != NULL)
389 cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
394 /* codegen_ncode_increase ******************************************************
398 *******************************************************************************/
400 #if defined(ENABLE_INTRP)
401 u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
405 /* save old ncodebase pointer */
407 oldncodebase = cd->ncodebase;
409 /* reallocate to new, doubled memory */
411 cd->ncodebase = DMREALLOC(cd->ncodebase,
417 /* return the new ncodeptr */
419 return (cd->ncodebase + (ncodeptr - oldncodebase));
424 /* codegen_add_branch_ref ******************************************************
426 Prepends an branch to the list.
428 *******************************************************************************/
430 void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
435 STATISTICS(count_branches_unresolved++);
437 /* calculate the mpc of the branch instruction */
439 branchmpc = cd->mcodeptr - cd->mcodebase;
441 br = DNEW(branchref);
443 br->branchmpc = branchmpc;
444 br->condition = condition;
446 br->options = options;
447 br->next = target->branchrefs;
449 target->branchrefs = br;
453 /* codegen_resolve_branchrefs **************************************************
455 Resolves and patches the branch references of a given basic block.
457 *******************************************************************************/
459 void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
464 /* Save the mcodeptr because in the branch emitting functions
465 we generate code somewhere inside already generated code,
466 but we're still in the actual code generation phase. */
468 mcodeptr = cd->mcodeptr;
470 /* just to make sure */
472 assert(bptr->mpc >= 0);
474 for (br = bptr->branchrefs; br != NULL; br = br->next) {
475 /* temporary set the mcodeptr */
477 cd->mcodeptr = cd->mcodebase + br->branchmpc;
479 /* emit_bccz and emit_branch emit the correct code, even if we
480 pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
482 emit_bccz(cd, bptr, br->condition, br->reg, br->options);
485 /* restore mcodeptr */
487 cd->mcodeptr = mcodeptr;
491 /* codegen_branch_label_add ****************************************************
493 Append an branch to the label-branch list.
495 *******************************************************************************/
497 void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
500 branch_label_ref_t *br;
503 /* get the label list */
505 list = cd->brancheslabel;
507 /* calculate the current mpc */
509 mpc = cd->mcodeptr - cd->mcodebase;
511 br = DNEW(branch_label_ref_t);
515 br->condition = condition;
517 br->options = options;
519 /* add the branch to the list */
521 list_add_last_unsynced(list, br);
525 /* codegen_add_patch_ref *******************************************************
527 Appends a new patcher reference to the list of patching positions.
529 *******************************************************************************/
531 void codegen_add_patch_ref(codegendata *cd, functionptr patcher, voidptr ref,
537 branchmpc = cd->mcodeptr - cd->mcodebase;
541 pr->branchpos = branchmpc;
543 pr->patcher = patcher;
546 /* list_add_first(cd->patchrefs, pr); */
547 pr->next = cd->patchrefs;
550 /* Generate NOPs for opt_shownops. */
555 #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__M68K__) || defined(__MIPS__) \
556 || defined(__SPARC_64__) || defined(__X86_64__))
558 /* On some architectures the patcher stub call instruction might
559 be longer than the actual instruction generated. On this
560 architectures we store the last patcher call position and after
561 the basic block code generation is completed, we check the
562 range and maybe generate some nop's. */
563 /* The nops are generated in codegen_emit in each codegen */
565 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
570 /* codegen_critical_section_new ************************************************
572 Allocates a new critical-section reference and adds it to the
573 critical-section list.
575 *******************************************************************************/
577 #if defined(ENABLE_THREADS)
578 void codegen_critical_section_new(codegendata *cd)
581 critical_section_ref_t *csr;
584 /* get the critical section list */
586 list = cd->listcritical;
588 /* calculate the current mpc */
590 mpc = cd->mcodeptr - cd->mcodebase;
592 csr = DNEW(critical_section_ref_t);
594 /* We only can set restart right now, as start and end are set by
595 the following, corresponding functions. */
601 /* add the branch to the list */
603 list_add_last_unsynced(list, csr);
608 /* codegen_critical_section_start **********************************************
610 Set the start-point of the current critical section (which is the
611 last element of the list).
613 *******************************************************************************/
615 #if defined(ENABLE_THREADS)
616 void codegen_critical_section_start(codegendata *cd)
619 critical_section_ref_t *csr;
622 /* get the critical section list */
624 list = cd->listcritical;
626 /* calculate the current mpc */
628 mpc = cd->mcodeptr - cd->mcodebase;
630 /* get the current critical section */
632 csr = list_last_unsynced(list);
634 /* set the start point */
636 assert(csr->start == -1);
643 /* codegen_critical_section_end ************************************************
645 Set the end-point of the current critical section (which is the
646 last element of the list).
648 *******************************************************************************/
650 #if defined(ENABLE_THREADS)
651 void codegen_critical_section_end(codegendata *cd)
654 critical_section_ref_t *csr;
657 /* get the critical section list */
659 list = cd->listcritical;
661 /* calculate the current mpc */
663 mpc = cd->mcodeptr - cd->mcodebase;
665 /* get the current critical section */
667 csr = list_last_unsynced(list);
669 /* set the end point */
671 assert(csr->end == -1);
678 /* codegen_critical_section_finish *********************************************
680 Finish the critical sections, create the critical section nodes for
681 the AVL tree and insert them into the tree.
683 *******************************************************************************/
685 #if defined(ENABLE_THREADS)
686 static void codegen_critical_section_finish(jitdata *jd)
691 critical_section_ref_t *csr;
692 critical_section_node_t *csn;
694 /* get required compiler data */
699 /* get the critical section list */
701 list = cd->listcritical;
703 /* iterate over all critical sections */
705 for (csr = list_first_unsynced(list); csr != NULL;
706 csr = list_next_unsynced(list, csr)) {
707 /* check if all points are set */
709 assert(csr->start != -1);
710 assert(csr->end != -1);
711 assert(csr->restart != -1);
713 /* allocate tree node */
715 csn = NEW(critical_section_node_t);
717 csn->start = code->entrypoint + csr->start;
718 csn->end = code->entrypoint + csr->end;
719 csn->restart = code->entrypoint + csr->restart;
721 /* insert into the tree */
723 critical_section_register(csn);
729 /* methodtree_comparator *******************************************************
731 Comparator function used for the AVL tree of methods.
734 treenode....the node from the tree
735 node........the node to compare to the tree-node
737 *******************************************************************************/
739 static s4 methodtree_comparator(const void *treenode, const void *node)
741 methodtree_element *mte;
742 methodtree_element *mtepc;
744 mte = (methodtree_element *) treenode;
745 mtepc = (methodtree_element *) node;
747 /* compare both startpc and endpc of pc, even if they have the same value,
748 otherwise the avl_probe sometimes thinks the element is already in the
752 /* On S390 addresses are 31 bit. Compare only 31 bits of value.
754 # define ADDR_MASK(a) ((a) & 0x7FFFFFFF)
756 # define ADDR_MASK(a) (a)
759 if (ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->startpc) &&
760 ADDR_MASK((long) mtepc->startpc) <= ADDR_MASK((long) mte->endpc) &&
761 ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->endpc) &&
762 ADDR_MASK((long) mtepc->endpc) <= ADDR_MASK((long) mte->endpc)) {
765 } else if (ADDR_MASK((long) mtepc->startpc) < ADDR_MASK((long) mte->startpc)) {
776 /* codegen_insertmethod ********************************************************
778 Insert the machine code range of a method into the AVL tree of methods.
780 *******************************************************************************/
782 void codegen_insertmethod(u1 *startpc, u1 *endpc)
784 methodtree_element *mte;
786 /* allocate new method entry */
788 mte = NEW(methodtree_element);
790 mte->startpc = startpc;
793 /* this function does not return an error, but asserts for
796 avl_insert(methodtree, mte);
800 /* codegen_get_pv_from_pc ******************************************************
802 Find the PV for the given PC by searching in the AVL tree of
805 *******************************************************************************/
807 u1 *codegen_get_pv_from_pc(u1 *pc)
809 methodtree_element mtepc;
810 methodtree_element *mte;
812 /* allocation of the search structure on the stack is much faster */
817 mte = avl_find(methodtree, &mtepc);
820 /* No method was found. Let's dump a stacktrace. */
822 #if defined(ENABLE_VMLOG)
823 vmlog_cacao_signl("SIGSEGV");
826 log_println("We received a SIGSEGV and tried to handle it, but we were");
827 log_println("unable to find a Java method at:");
829 #if SIZEOF_VOID_P == 8
830 log_println("PC=0x%016lx", pc);
832 log_println("PC=0x%08x", pc);
836 log_println("Dumping the current stacktrace:");
838 #if defined(ENABLE_THREADS)
839 /* XXX michi: This should be available even without threads! */
840 threads_print_stacktrace();
843 vm_abort("Exiting...");
850 /* codegen_get_pv_from_pc_nocheck **********************************************
852 Find the PV for the given PC by searching in the AVL tree of
853 methods. This method does not check the return value and is used
856 *******************************************************************************/
858 u1 *codegen_get_pv_from_pc_nocheck(u1 *pc)
860 methodtree_element mtepc;
861 methodtree_element *mte;
863 /* allocation of the search structure on the stack is much faster */
868 mte = avl_find(methodtree, &mtepc);
877 /* codegen_set_replacement_point_notrap ****************************************
879 Record the position of a non-trappable replacement point.
881 *******************************************************************************/
883 #if defined(ENABLE_REPLACEMENT)
885 void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
887 void codegen_set_replacement_point_notrap(codegendata *cd)
890 assert(cd->replacementpoint);
891 assert(cd->replacementpoint->type == type);
892 assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
894 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
896 cd->replacementpoint++;
898 #endif /* defined(ENABLE_REPLACEMENT) */
901 /* codegen_set_replacement_point ***********************************************
903 Record the position of a trappable replacement point.
905 *******************************************************************************/
907 #if defined(ENABLE_REPLACEMENT)
909 void codegen_set_replacement_point(codegendata *cd, s4 type)
911 void codegen_set_replacement_point(codegendata *cd)
914 assert(cd->replacementpoint);
915 assert(cd->replacementpoint->type == type);
916 assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
918 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
920 cd->replacementpoint++;
922 /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
924 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
926 #endif /* defined(ENABLE_REPLACEMENT) */
929 /* codegen_finish **************************************************************
931 Finishes the code generation. A new memory, large enough for both
932 data and code, is allocated and data and code are copied together
933 to their final layout, unresolved jumps are resolved, ...
935 *******************************************************************************/
937 void codegen_finish(jitdata *jd)
942 #if defined(ENABLE_INTRP)
951 /* get required compiler data */
956 /* prevent compiler warning */
958 #if defined(ENABLE_INTRP)
962 /* calculate the code length */
964 mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
966 #if defined(ENABLE_STATISTICS)
968 count_code_len += mcodelen;
969 count_data_len += cd->dseglen;
973 alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
975 #if defined(ENABLE_INTRP)
977 ncodelen = cd->ncodeptr - cd->ncodebase;
979 ncodelen = 0; /* avoid compiler warning */
983 cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
984 alignedlen = alignedmcodelen + cd->dseglen;
986 #if defined(ENABLE_INTRP)
988 alignedlen += ncodelen;
992 /* allocate new memory */
994 code->mcodelength = mcodelen + cd->dseglen;
995 code->mcode = CNEW(u1, alignedlen);
997 /* set the entrypoint of the method */
999 assert(code->entrypoint == NULL);
1000 code->entrypoint = epoint = (code->mcode + cd->dseglen);
1002 /* fill the data segment (code->entrypoint must already be set!) */
1006 /* copy code to the new location */
1008 MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
1010 #if defined(ENABLE_INTRP)
1011 /* relocate native dynamic superinstruction code (if any) */
1014 cd->mcodebase = code->entrypoint;
1017 u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
1019 MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
1021 /* flush the instruction and data caches */
1023 md_cacheflush(ncodebase, ncodelen);
1025 /* set some cd variables for dynamic_super_rerwite */
1027 cd->ncodebase = ncodebase;
1030 cd->ncodebase = NULL;
1033 dynamic_super_rewrite(cd);
1037 /* jump table resolving */
1039 for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
1040 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
1041 (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
1043 /* line number table resolving */
1049 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
1051 target = lr->targetmpc;
1052 /* if the entry contains an mcode pointer (normal case), resolve it */
1053 /* (see doc/inlining_stacktrace.txt for details) */
1054 if (lr->linenumber >= -2) {
1055 target += (ptrint) epoint;
1057 *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) =
1058 (functionptr) target;
1061 *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
1062 (functionptr) ((ptrint) epoint + cd->linenumbertab);
1064 *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
1067 /* patcher resolving */
1069 pr = list_first_unsynced(code->patchers);
1071 pr->mpc += (ptrint) epoint;
1072 pr->datap = (ptrint) (pr->disp + epoint);
1073 pr = list_next_unsynced(code->patchers, pr);
1076 #if defined(ENABLE_REPLACEMENT)
1077 /* replacement point resolving */
1082 rp = code->rplpoints;
1083 for (i=0; i<code->rplpointcount; ++i, ++rp) {
1084 rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
1087 #endif /* defined(ENABLE_REPLACEMENT) */
1089 /* add method into methodtree to find the entrypoint */
1091 codegen_insertmethod(code->entrypoint, code->entrypoint + mcodelen);
1093 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
1094 /* resolve data segment references */
1096 dseg_resolve_datareferences(jd);
1099 #if defined(ENABLE_THREADS)
1100 /* create cirtical sections */
1102 codegen_critical_section_finish(jd);
1105 /* flush the instruction and data caches */
1107 md_cacheflush(code->mcode, code->mcodelength);
1111 /* codegen_generate_stub_compiler **********************************************
1113 Wrapper for codegen_emit_stub_compiler.
1116 pointer to the compiler stub code.
1118 *******************************************************************************/
1120 u1 *codegen_generate_stub_compiler(methodinfo *m)
1124 ptrint *d; /* pointer to data memory */
1125 u1 *c; /* pointer to code memory */
1128 /* mark dump memory */
1130 dumpsize = dump_size();
1132 /* allocate required data structures */
1137 jd->cd = DNEW(codegendata);
1140 /* get required compiler data */
1144 /* allocate code memory */
1146 c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1148 /* set pointers correctly */
1154 c = c + 3 * SIZEOF_VOID_P;
1157 /* NOTE: The codeinfo pointer is actually a pointer to the
1158 methodinfo (this fakes a codeinfo structure). */
1160 d[0] = (ptrint) asm_call_jit_compiler;
1162 d[2] = (ptrint) &d[1]; /* fake code->m */
1164 /* call the emit function */
1166 codegen_emit_stub_compiler(jd);
1168 #if defined(ENABLE_STATISTICS)
1170 count_cstub_len += 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
1175 md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1177 /* release dump memory */
1179 dump_release(dumpsize);
1181 /* return native stub code */
1187 /* codegen_generate_stub_native ************************************************
1189 Wrapper for codegen_emit_stub_native.
1192 the codeinfo representing the stub code.
1194 *******************************************************************************/
1196 codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
1205 /* mark dump memory */
1207 dumpsize = dump_size();
1212 jd->cd = DNEW(codegendata);
1213 jd->rd = DNEW(registerdata);
1216 /* Allocate codeinfo memory from the heap as we need to keep them. */
1218 jd->code = code_codeinfo_new(m); /* XXX check allocation */
1220 /* get required compiler data */
1224 /* set the flags for the current JIT run */
1226 #if defined(ENABLE_PROFILING)
1228 jd->flags |= JITDATA_FLAG_INSTRUMENT;
1231 if (opt_verbosecall)
1232 jd->flags |= JITDATA_FLAG_VERBOSECALL;
1234 /* setup code generation stuff */
1236 #if defined(ENABLE_JIT)
1237 # if defined(ENABLE_INTRP)
1245 /* create new method descriptor with additional native parameters */
1248 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
1250 nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
1251 md->paramcount * sizeof(typedesc) +
1252 nativeparams * sizeof(typedesc));
1254 nmd->paramcount = md->paramcount + nativeparams;
1256 nmd->params = DMNEW(paramdesc, nmd->paramcount);
1258 nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer */
1260 if (m->flags & ACC_STATIC)
1261 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer */
1263 MCOPY(nmd->paramtypes + nativeparams, md->paramtypes, typedesc,
1266 #if defined(ENABLE_JIT)
1267 # if defined(ENABLE_INTRP)
1270 /* pre-allocate the arguments for the native ABI */
1272 md_param_alloc_native(nmd);
1275 /* generate the code */
1277 #if defined(ENABLE_JIT)
1278 # if defined(ENABLE_INTRP)
1280 intrp_createnativestub(f, jd, nmd);
1283 codegen_emit_stub_native(jd, nmd, f);
1285 intrp_createnativestub(f, jd, nmd);
1288 /* reallocate the memory and finish the code generation */
1292 #if defined(ENABLE_STATISTICS)
1293 /* must be done after codegen_finish() */
1296 size_stub_native += code->mcodelength;
1299 #if !defined(NDEBUG)
1300 /* disassemble native stub */
1302 if (opt_shownativestub) {
1303 #if defined(ENABLE_DEBUG_FILTER)
1304 if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
1307 #if defined(ENABLE_DISASSEMBLER)
1308 codegen_disassemble_nativestub(m,
1309 (u1 *) (ptrint) code->entrypoint,
1310 (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
1313 /* show data segment */
1315 if (opt_showddatasegment)
1319 #endif /* !defined(NDEBUG) */
1321 /* release memory */
1323 dump_release(dumpsize);
1325 /* return native stub code */
1331 /* codegen_disassemble_nativestub **********************************************
1333 Disassembles the generated native stub.
1335 *******************************************************************************/
1337 #if defined(ENABLE_DISASSEMBLER)
1338 void codegen_disassemble_nativestub(methodinfo *m, u1 *start, u1 *end)
1340 printf("Native stub: ");
1341 utf_fprint_printable_ascii_classname(stdout, m->class->name);
1343 utf_fprint_printable_ascii(stdout, m->name);
1344 utf_fprint_printable_ascii(stdout, m->descriptor);
1345 printf("\n\nLength: %d\n\n", (s4) (end - start));
1347 DISASSEMBLE(start, end);
1352 /* codegen_start_native_call ***************************************************
1354 Prepares the stuff required for a native (JNI) function call:
1356 - adds a stackframe info structure to the chain, for stacktraces
1357 - prepares the local references table on the stack
1359 The layout of the native stub stackframe should look like this:
1361 +---------------------------+ <- SP (of parent Java function)
1363 +---------------------------+
1365 | stackframe info structure |
1367 +---------------------------+
1369 | local references table |
1371 +---------------------------+
1373 | arguments (if any) |
1375 +---------------------------+ <- SP (native stub)
1377 *******************************************************************************/
1379 void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
1381 stackframeinfo *sfi;
1382 localref_table *lrt;
1384 STATISTICS(count_calls_java_to_native++);
1386 /* get data structures from stack */
1388 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1389 lrt = (localref_table *) (datasp - sizeof(stackframeinfo) -
1390 sizeof(localref_table));
1392 /* add a stackframeinfo to the chain */
1394 stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
1396 #if defined(ENABLE_JNI)
1397 /* add current JNI local references table to this thread */
1399 localref_table_add(lrt);
1404 /* codegen_finish_native_call **************************************************
1406 Removes the stuff required for a native (JNI) function call.
1407 Additionally it checks for an exceptions and in case, get the
1408 exception object and clear the pointer.
1410 *******************************************************************************/
1412 java_object_t *codegen_finish_native_call(u1 *datasp)
1414 stackframeinfo *sfi;
1415 stackframeinfo **psfi;
1418 /* get data structures from stack */
1420 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1422 /* remove current stackframeinfo from chain */
1424 psfi = &STACKFRAMEINFO;
1428 #if defined(ENABLE_JNI)
1429 /* release JNI local references table for this thread */
1431 localref_frame_pop_all();
1432 localref_table_remove();
1435 /* get the exception and return it */
1437 e = exceptions_get_and_clear_exception();
1443 /* removecompilerstub **********************************************************
1445 Deletes a compilerstub from memory (simply by freeing it).
1447 *******************************************************************************/
1449 void removecompilerstub(u1 *stub)
1451 /* pass size 1 to keep the intern function happy */
1453 CFREE((void *) stub, 1);
1457 /* removenativestub ************************************************************
1459 Removes a previously created native-stub from memory.
1461 *******************************************************************************/
1463 void removenativestub(u1 *stub)
1465 /* pass size 1 to keep the intern function happy */
1467 CFREE((void *) stub, 1);
1471 /* codegen_reg_of_var **********************************************************
1473 This function determines a register, to which the result of an
1474 operation should go, when it is ultimatively intended to store the
1475 result in pseudoregister v. If v is assigned to an actual
1476 register, this register will be returned. Otherwise (when v is
1477 spilled) this function returns tempregnum. If not already done,
1478 regoff and flags are set in the stack location.
1480 *******************************************************************************/
1482 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
1486 /* Do we have to generate a conditional move? Yes, then always
1487 return the temporary register. The real register is identified
1488 during the store. */
1490 if (opcode & ICMD_CONDITION_MASK)
1494 if (!(v->flags & INMEMORY))
1495 return v->vv.regoff;
1501 /* codegen_reg_of_dst **********************************************************
1503 This function determines a register, to which the result of an
1504 operation should go, when it is ultimatively intended to store the
1505 result in iptr->dst.var. If dst.var is assigned to an actual
1506 register, this register will be returned. Otherwise (when it is
1507 spilled) this function returns tempregnum. If not already done,
1508 regoff and flags are set in the stack location.
1510 *******************************************************************************/
1512 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
1514 return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
1518 /* codegen_emit_phi_moves ****************************************************
1520 Emits phi moves at the end of the basicblock.
1522 *******************************************************************************/
1524 #if defined(ENABLE_SSA)
1525 void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
1538 /* Moves from phi functions with highest indices have to be */
1539 /* inserted first, since this is the order as is used for */
1540 /* conflict resolution */
1542 for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
1543 lt_d = ls->phi_moves[bptr->nr][i][0];
1544 lt_s = ls->phi_moves[bptr->nr][i][1];
1545 #if defined(SSA_DEBUG_VERBOSE)
1547 printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
1549 if (lt_s == UNUSED) {
1550 #if defined(SSA_DEBUG_VERBOSE)
1552 printf(" ... not processed \n");
1557 d = VAR(ls->lifetime[lt_d].v_index);
1558 s = VAR(ls->lifetime[lt_s].v_index);
1561 if (d->type == -1) {
1562 #if defined(SSA_DEBUG_VERBOSE)
1564 printf("...returning - phi lifetimes where joined\n");
1569 if (s->type == -1) {
1570 #if defined(SSA_DEBUG_VERBOSE)
1572 printf("...returning - phi lifetimes where joined\n");
1578 tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
1579 tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
1580 emit_copy(jd, &tmp_i);
1582 #if defined(SSA_DEBUG_VERBOSE)
1583 if (compileverbose) {
1584 if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
1586 printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1588 else if (IS_INMEMORY(s->flags)) {
1590 printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1592 else if (IS_INMEMORY(d->flags)) {
1594 printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1598 printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1602 #endif /* defined(SSA_DEBUG_VERBOSE) */
1605 #endif /* defined(ENABLE_SSA) */
1610 * These are local overrides for various environment variables in Emacs.
1611 * Please do not remove this and leave it at the end of the file, where
1612 * Emacs will automagically detect them.
1613 * ---------------------------------------------------------------------
1616 * indent-tabs-mode: t
1620 * vim:noexpandtab:sw=4:ts=4: