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).
52 #if defined(ENABLE_JIT)
53 /* 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/llni.h"
67 #include "native/localref.h"
68 #include "native/native.h"
70 #include "native/include/java_lang_Class.h"
72 #include "threads/threads-common.h"
74 #include "vm/builtin.h"
75 #include "vm/exceptions.h"
76 #include "vm/stringlocal.h"
78 #include "vm/jit/abi.h"
79 #include "vm/jit/asmpart.h"
80 #include "vm/jit/codegen-common.h"
82 #if defined(ENABLE_DISASSEMBLER)
83 # include "vm/jit/disass.h"
86 #include "vm/jit/dseg.h"
87 #include "vm/jit/emit-common.h"
88 #include "vm/jit/jit.h"
89 #include "vm/jit/md.h"
90 #include "vm/jit/methodheader.h"
91 #include "vm/jit/patcher-common.h"
92 #include "vm/jit/replace.h"
93 #if defined(ENABLE_SSA)
94 # include "vm/jit/optimizing/lsra.h"
95 # include "vm/jit/optimizing/ssa.h"
97 #include "vm/jit/stacktrace.h"
98 #include "vm/jit/trace.h"
100 #if defined(ENABLE_INTRP)
101 #include "vm/jit/intrp/intrp.h"
104 #include "vmcore/method.h"
105 #include "vmcore/options.h"
107 # include "vmcore/statistics.h"
109 #if defined(ENABLE_VMLOG)
110 #include <vmlog_cacao.h>
115 /* in this tree we store all method addresses *********************************/
117 static avl_tree_t *methodtree = NULL;
118 static s4 methodtree_comparator(const void *treenode, const void *node);
121 /* codegen_init ****************************************************************
125 *******************************************************************************/
127 void codegen_init(void)
129 /* this tree is global, not method specific */
132 #if defined(ENABLE_JIT)
133 methodtree_element *mte;
136 methodtree = avl_create(&methodtree_comparator);
138 #if defined(ENABLE_JIT)
139 /* insert asm_vm_call_method */
141 mte = NEW(methodtree_element);
143 mte->startpc = (u1 *) (ptrint) asm_vm_call_method;
144 mte->endpc = (u1 *) (ptrint) asm_vm_call_method_end;
146 avl_insert(methodtree, mte);
147 #endif /* defined(ENABLE_JIT) */
154 /* codegen_setup ***************************************************************
156 Allocates and initialises code area, data area and references.
158 *******************************************************************************/
160 void codegen_setup(jitdata *jd)
165 /* get required compiler data */
170 /* initialize members */
174 cd->mcodebase = DMNEW(u1, MCODEINITSIZE);
175 cd->mcodeend = cd->mcodebase + MCODEINITSIZE;
176 cd->mcodesize = MCODEINITSIZE;
178 /* initialize mcode variables */
180 cd->mcodeptr = cd->mcodebase;
181 cd->lastmcodeptr = cd->mcodebase;
183 #if defined(ENABLE_INTRP)
184 /* native dynamic superinstructions variables */
187 cd->ncodebase = DMNEW(u1, NCODEINITSIZE);
188 cd->ncodesize = NCODEINITSIZE;
190 /* initialize ncode variables */
192 cd->ncodeptr = cd->ncodebase;
194 cd->lastinstwithoutdispatch = ~0; /* no inst without dispatch */
195 cd->superstarts = NULL;
202 cd->jumpreferences = NULL;
204 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
205 cd->datareferences = NULL;
208 /* cd->patchrefs = list_create_dump(OFFSET(patchref, linkage)); */
209 cd->patchrefs = NULL;
210 cd->brancheslabel = list_create_dump(OFFSET(branch_label_ref_t, linkage));
211 cd->listcritical = list_create_dump(OFFSET(critical_section_ref_t, linkage));
213 cd->linenumberreferences = NULL;
214 cd->linenumbertablesizepos = 0;
215 cd->linenumbertablestartpos = 0;
216 cd->linenumbertab = 0;
220 /* codegen_reset ***************************************************************
222 Resets the codegen data structure so we can recompile the method.
224 *******************************************************************************/
226 static void codegen_reset(jitdata *jd)
232 /* get required compiler data */
237 /* reset error flag */
239 cd->flags &= ~CODEGENDATA_FLAG_ERROR;
241 /* reset some members, we reuse the code memory already allocated
242 as this should have almost the correct size */
244 cd->mcodeptr = cd->mcodebase;
245 cd->lastmcodeptr = cd->mcodebase;
250 cd->jumpreferences = NULL;
252 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
253 cd->datareferences = NULL;
256 /* cd->patchrefs = list_create_dump(OFFSET(patchref, linkage)); */
257 cd->patchrefs = NULL;
258 cd->brancheslabel = list_create_dump(OFFSET(branch_label_ref_t, linkage));
259 cd->listcritical = list_create_dump(OFFSET(critical_section_ref_t, linkage));
261 cd->linenumberreferences = NULL;
262 cd->linenumbertablesizepos = 0;
263 cd->linenumbertablestartpos = 0;
264 cd->linenumbertab = 0;
266 /* We need to clear the mpc and the branch references from all
267 basic blocks as they will definitely change. */
269 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
271 bptr->branchrefs = NULL;
274 /* We need to clear all the patcher references from the codeinfo
275 since they all will be regenerated */
277 patcher_list_reset(code);
279 #if defined(ENABLE_REPLACEMENT)
280 code->rplpoints = NULL;
281 code->rplpointcount = 0;
282 code->regalloc = NULL;
283 code->regalloccount = 0;
284 code->globalcount = 0;
289 /* codegen_generate ************************************************************
291 Generates the code for the currently compiled method.
293 *******************************************************************************/
295 bool codegen_generate(jitdata *jd)
299 /* get required compiler data */
303 /* call the machine-dependent code generation function */
305 if (!codegen_emit(jd))
308 /* check for an error */
310 if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
311 /* check for long-branches flag, if it is set we recompile the
316 log_message_method("Re-generating code: ", jd->m);
319 /* XXX maybe we should tag long-branches-methods for recompilation */
321 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
322 /* we have to reset the codegendata structure first */
326 /* and restart the compiler run */
328 if (!codegen_emit(jd))
332 vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
337 log_message_method("Re-generating code done: ", jd->m);
341 /* reallocate the memory and finish the code generation */
345 /* everything's ok */
351 /* codegen_close ***************************************************************
355 *******************************************************************************/
357 void codegen_close(void)
359 /* TODO: release avl tree on i386 and x86_64 */
363 /* codegen_increase ************************************************************
367 *******************************************************************************/
369 void codegen_increase(codegendata *cd)
373 /* save old mcodebase pointer */
375 oldmcodebase = cd->mcodebase;
377 /* reallocate to new, doubled memory */
379 cd->mcodebase = DMREALLOC(cd->mcodebase,
384 cd->mcodeend = cd->mcodebase + cd->mcodesize;
386 /* set new mcodeptr */
388 cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
390 #if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(__M68K__) || defined(ENABLE_INTRP) \
391 || defined(__SPARC_64__)
392 /* adjust the pointer to the last patcher position */
394 if (cd->lastmcodeptr != NULL)
395 cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
400 /* codegen_ncode_increase ******************************************************
404 *******************************************************************************/
406 #if defined(ENABLE_INTRP)
407 u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
411 /* save old ncodebase pointer */
413 oldncodebase = cd->ncodebase;
415 /* reallocate to new, doubled memory */
417 cd->ncodebase = DMREALLOC(cd->ncodebase,
423 /* return the new ncodeptr */
425 return (cd->ncodebase + (ncodeptr - oldncodebase));
430 /* codegen_add_branch_ref ******************************************************
432 Prepends an branch to the list.
434 *******************************************************************************/
436 void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
441 STATISTICS(count_branches_unresolved++);
443 /* calculate the mpc of the branch instruction */
445 branchmpc = cd->mcodeptr - cd->mcodebase;
447 br = DNEW(branchref);
449 br->branchmpc = branchmpc;
450 br->condition = condition;
452 br->options = options;
453 br->next = target->branchrefs;
455 target->branchrefs = br;
459 /* codegen_resolve_branchrefs **************************************************
461 Resolves and patches the branch references of a given basic block.
463 *******************************************************************************/
465 void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
470 /* Save the mcodeptr because in the branch emitting functions
471 we generate code somewhere inside already generated code,
472 but we're still in the actual code generation phase. */
474 mcodeptr = cd->mcodeptr;
476 /* just to make sure */
478 assert(bptr->mpc >= 0);
480 for (br = bptr->branchrefs; br != NULL; br = br->next) {
481 /* temporary set the mcodeptr */
483 cd->mcodeptr = cd->mcodebase + br->branchmpc;
485 /* emit_bccz and emit_branch emit the correct code, even if we
486 pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
488 emit_bccz(cd, bptr, br->condition, br->reg, br->options);
491 /* restore mcodeptr */
493 cd->mcodeptr = mcodeptr;
497 /* codegen_branch_label_add ****************************************************
499 Append an branch to the label-branch list.
501 *******************************************************************************/
503 void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
506 branch_label_ref_t *br;
509 /* get the label list */
511 list = cd->brancheslabel;
513 /* calculate the current mpc */
515 mpc = cd->mcodeptr - cd->mcodebase;
517 br = DNEW(branch_label_ref_t);
521 br->condition = condition;
523 br->options = options;
525 /* add the branch to the list */
527 list_add_last_unsynced(list, br);
531 /* codegen_add_patch_ref *******************************************************
533 Appends a new patcher reference to the list of patching positions.
535 *******************************************************************************/
537 void codegen_add_patch_ref(codegendata *cd, functionptr patcher, voidptr ref,
543 branchmpc = cd->mcodeptr - cd->mcodebase;
547 pr->branchpos = branchmpc;
549 pr->patcher = patcher;
552 /* list_add_first(cd->patchrefs, pr); */
553 pr->next = cd->patchrefs;
556 /* Generate NOPs for opt_shownops. */
561 #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__M68K__) || defined(__MIPS__) \
562 || defined(__SPARC_64__) || defined(__X86_64__))
564 /* On some architectures the patcher stub call instruction might
565 be longer than the actual instruction generated. On this
566 architectures we store the last patcher call position and after
567 the basic block code generation is completed, we check the
568 range and maybe generate some nop's. */
569 /* The nops are generated in codegen_emit in each codegen */
571 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
576 /* codegen_critical_section_new ************************************************
578 Allocates a new critical-section reference and adds it to the
579 critical-section list.
581 *******************************************************************************/
583 #if defined(ENABLE_THREADS)
584 void codegen_critical_section_new(codegendata *cd)
587 critical_section_ref_t *csr;
590 /* get the critical section list */
592 list = cd->listcritical;
594 /* calculate the current mpc */
596 mpc = cd->mcodeptr - cd->mcodebase;
598 csr = DNEW(critical_section_ref_t);
600 /* We only can set restart right now, as start and end are set by
601 the following, corresponding functions. */
607 /* add the branch to the list */
609 list_add_last_unsynced(list, csr);
614 /* codegen_critical_section_start **********************************************
616 Set the start-point of the current critical section (which is the
617 last element of the list).
619 *******************************************************************************/
621 #if defined(ENABLE_THREADS)
622 void codegen_critical_section_start(codegendata *cd)
625 critical_section_ref_t *csr;
628 /* get the critical section list */
630 list = cd->listcritical;
632 /* calculate the current mpc */
634 mpc = cd->mcodeptr - cd->mcodebase;
636 /* get the current critical section */
638 csr = list_last_unsynced(list);
640 /* set the start point */
642 assert(csr->start == -1);
649 /* codegen_critical_section_end ************************************************
651 Set the end-point of the current critical section (which is the
652 last element of the list).
654 *******************************************************************************/
656 #if defined(ENABLE_THREADS)
657 void codegen_critical_section_end(codegendata *cd)
660 critical_section_ref_t *csr;
663 /* get the critical section list */
665 list = cd->listcritical;
667 /* calculate the current mpc */
669 mpc = cd->mcodeptr - cd->mcodebase;
671 /* get the current critical section */
673 csr = list_last_unsynced(list);
675 /* set the end point */
677 assert(csr->end == -1);
684 /* codegen_critical_section_finish *********************************************
686 Finish the critical sections, create the critical section nodes for
687 the AVL tree and insert them into the tree.
689 *******************************************************************************/
691 #if defined(ENABLE_THREADS)
692 static void codegen_critical_section_finish(jitdata *jd)
697 critical_section_ref_t *csr;
698 critical_section_node_t *csn;
700 /* get required compiler data */
705 /* get the critical section list */
707 list = cd->listcritical;
709 /* iterate over all critical sections */
711 for (csr = list_first_unsynced(list); csr != NULL;
712 csr = list_next_unsynced(list, csr)) {
713 /* check if all points are set */
715 assert(csr->start != -1);
716 assert(csr->end != -1);
717 assert(csr->restart != -1);
719 /* allocate tree node */
721 csn = NEW(critical_section_node_t);
723 csn->start = code->entrypoint + csr->start;
724 csn->end = code->entrypoint + csr->end;
725 csn->restart = code->entrypoint + csr->restart;
727 /* insert into the tree */
729 critical_section_register(csn);
735 /* methodtree_comparator *******************************************************
737 Comparator function used for the AVL tree of methods.
740 treenode....the node from the tree
741 node........the node to compare to the tree-node
743 *******************************************************************************/
745 static s4 methodtree_comparator(const void *treenode, const void *node)
747 methodtree_element *mte;
748 methodtree_element *mtepc;
750 mte = (methodtree_element *) treenode;
751 mtepc = (methodtree_element *) node;
753 /* compare both startpc and endpc of pc, even if they have the same value,
754 otherwise the avl_probe sometimes thinks the element is already in the
758 /* On S390 addresses are 31 bit. Compare only 31 bits of value.
760 # define ADDR_MASK(a) ((a) & 0x7FFFFFFF)
762 # define ADDR_MASK(a) (a)
765 if (ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->startpc) &&
766 ADDR_MASK((long) mtepc->startpc) <= ADDR_MASK((long) mte->endpc) &&
767 ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->endpc) &&
768 ADDR_MASK((long) mtepc->endpc) <= ADDR_MASK((long) mte->endpc)) {
771 } else if (ADDR_MASK((long) mtepc->startpc) < ADDR_MASK((long) mte->startpc)) {
782 /* codegen_insertmethod ********************************************************
784 Insert the machine code range of a method into the AVL tree of methods.
786 *******************************************************************************/
788 void codegen_insertmethod(u1 *startpc, u1 *endpc)
790 methodtree_element *mte;
792 /* allocate new method entry */
794 mte = NEW(methodtree_element);
796 mte->startpc = startpc;
799 /* this function does not return an error, but asserts for
802 avl_insert(methodtree, mte);
806 /* codegen_get_pv_from_pc ******************************************************
808 Find the PV for the given PC by searching in the AVL tree of
811 *******************************************************************************/
813 u1 *codegen_get_pv_from_pc(u1 *pc)
815 methodtree_element mtepc;
816 methodtree_element *mte;
818 /* allocation of the search structure on the stack is much faster */
823 mte = avl_find(methodtree, &mtepc);
826 /* No method was found. Let's dump a stacktrace. */
828 #if defined(ENABLE_VMLOG)
829 vmlog_cacao_signl("SIGSEGV");
832 log_println("We received a SIGSEGV and tried to handle it, but we were");
833 log_println("unable to find a Java method at:");
835 #if SIZEOF_VOID_P == 8
836 log_println("PC=0x%016lx", pc);
838 log_println("PC=0x%08x", pc);
842 log_println("Dumping the current stacktrace:");
844 #if defined(ENABLE_THREADS)
845 /* XXX michi: This should be available even without threads! */
846 threads_print_stacktrace();
849 vm_abort("Exiting...");
856 /* codegen_get_pv_from_pc_nocheck **********************************************
858 Find the PV for the given PC by searching in the AVL tree of
859 methods. This method does not check the return value and is used
862 *******************************************************************************/
864 u1 *codegen_get_pv_from_pc_nocheck(u1 *pc)
866 methodtree_element mtepc;
867 methodtree_element *mte;
869 /* allocation of the search structure on the stack is much faster */
874 mte = avl_find(methodtree, &mtepc);
883 /* codegen_set_replacement_point_notrap ****************************************
885 Record the position of a non-trappable replacement point.
887 *******************************************************************************/
889 #if defined(ENABLE_REPLACEMENT)
891 void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
893 void codegen_set_replacement_point_notrap(codegendata *cd)
896 assert(cd->replacementpoint);
897 assert(cd->replacementpoint->type == type);
898 assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
900 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
902 cd->replacementpoint++;
904 #endif /* defined(ENABLE_REPLACEMENT) */
907 /* codegen_set_replacement_point ***********************************************
909 Record the position of a trappable replacement point.
911 *******************************************************************************/
913 #if defined(ENABLE_REPLACEMENT)
915 void codegen_set_replacement_point(codegendata *cd, s4 type)
917 void codegen_set_replacement_point(codegendata *cd)
920 assert(cd->replacementpoint);
921 assert(cd->replacementpoint->type == type);
922 assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
924 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
926 cd->replacementpoint++;
928 /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
930 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
932 #endif /* defined(ENABLE_REPLACEMENT) */
935 /* codegen_finish **************************************************************
937 Finishes the code generation. A new memory, large enough for both
938 data and code, is allocated and data and code are copied together
939 to their final layout, unresolved jumps are resolved, ...
941 *******************************************************************************/
943 void codegen_finish(jitdata *jd)
948 #if defined(ENABLE_INTRP)
957 /* get required compiler data */
962 /* prevent compiler warning */
964 #if defined(ENABLE_INTRP)
968 /* calculate the code length */
970 mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
972 #if defined(ENABLE_STATISTICS)
974 count_code_len += mcodelen;
975 count_data_len += cd->dseglen;
979 alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
981 #if defined(ENABLE_INTRP)
983 ncodelen = cd->ncodeptr - cd->ncodebase;
985 ncodelen = 0; /* avoid compiler warning */
989 cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
990 alignedlen = alignedmcodelen + cd->dseglen;
992 #if defined(ENABLE_INTRP)
994 alignedlen += ncodelen;
998 /* allocate new memory */
1000 code->mcodelength = mcodelen + cd->dseglen;
1001 code->mcode = CNEW(u1, alignedlen);
1003 /* set the entrypoint of the method */
1005 assert(code->entrypoint == NULL);
1006 code->entrypoint = epoint = (code->mcode + cd->dseglen);
1008 /* fill the data segment (code->entrypoint must already be set!) */
1012 /* copy code to the new location */
1014 MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
1016 #if defined(ENABLE_INTRP)
1017 /* relocate native dynamic superinstruction code (if any) */
1020 cd->mcodebase = code->entrypoint;
1023 u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
1025 MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
1027 /* flush the instruction and data caches */
1029 md_cacheflush(ncodebase, ncodelen);
1031 /* set some cd variables for dynamic_super_rerwite */
1033 cd->ncodebase = ncodebase;
1036 cd->ncodebase = NULL;
1039 dynamic_super_rewrite(cd);
1043 /* jump table resolving */
1045 for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
1046 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
1047 (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
1049 /* line number table resolving */
1055 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
1057 target = lr->targetmpc;
1058 /* if the entry contains an mcode pointer (normal case), resolve it */
1059 /* (see doc/inlining_stacktrace.txt for details) */
1060 if (lr->linenumber >= -2) {
1061 target += (ptrint) epoint;
1063 *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) =
1064 (functionptr) target;
1067 *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
1068 (functionptr) ((ptrint) epoint + cd->linenumbertab);
1070 *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
1073 /* patcher resolving */
1075 pr = list_first_unsynced(code->patchers);
1077 pr->mpc += (ptrint) epoint;
1078 pr->datap = (ptrint) (pr->disp + epoint);
1079 pr = list_next_unsynced(code->patchers, pr);
1082 #if defined(ENABLE_REPLACEMENT)
1083 /* replacement point resolving */
1088 rp = code->rplpoints;
1089 for (i=0; i<code->rplpointcount; ++i, ++rp) {
1090 rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
1093 #endif /* defined(ENABLE_REPLACEMENT) */
1095 /* add method into methodtree to find the entrypoint */
1097 codegen_insertmethod(code->entrypoint, code->entrypoint + mcodelen);
1099 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
1100 /* resolve data segment references */
1102 dseg_resolve_datareferences(jd);
1105 #if defined(ENABLE_THREADS)
1106 /* create cirtical sections */
1108 codegen_critical_section_finish(jd);
1111 /* flush the instruction and data caches */
1113 md_cacheflush(code->mcode, code->mcodelength);
1117 /* codegen_generate_stub_compiler **********************************************
1119 Wrapper for codegen_emit_stub_compiler.
1122 pointer to the compiler stub code.
1124 *******************************************************************************/
1126 u1 *codegen_generate_stub_compiler(methodinfo *m)
1130 ptrint *d; /* pointer to data memory */
1131 u1 *c; /* pointer to code memory */
1134 /* mark dump memory */
1136 dumpsize = dump_size();
1138 /* allocate required data structures */
1143 jd->cd = DNEW(codegendata);
1146 /* get required compiler data */
1150 /* allocate code memory */
1152 c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1154 /* set pointers correctly */
1160 c = c + 3 * SIZEOF_VOID_P;
1163 /* NOTE: The codeinfo pointer is actually a pointer to the
1164 methodinfo (this fakes a codeinfo structure). */
1166 d[0] = (ptrint) asm_call_jit_compiler;
1168 d[2] = (ptrint) &d[1]; /* fake code->m */
1170 /* call the emit function */
1172 codegen_emit_stub_compiler(jd);
1174 #if defined(ENABLE_STATISTICS)
1176 count_cstub_len += 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
1181 md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1183 /* release dump memory */
1185 dump_release(dumpsize);
1187 /* return native stub code */
1193 /* codegen_generate_stub_builtin ***********************************************
1195 Wrapper for codegen_emit_stub_builtin.
1198 Pointer to the entrypoint of the stub.
1200 *******************************************************************************/
1202 void codegen_generate_stub_builtin(builtintable_entry *bte)
1204 #if defined(__ARM__) || defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__SPARC64__) || defined(__X86_64__)
1209 /* mark dump memory */
1211 dumpsize = dump_size();
1216 jd->cd = DNEW(codegendata);
1220 /* Allocate codeinfo memory from the heap as we need to keep them. */
1222 jd->code = code_codeinfo_new(NULL);
1224 /* get required compiler data */
1228 /* setup code generation stuff */
1232 /* generate the code */
1234 #if defined(ENABLE_JIT)
1235 # if defined(ENABLE_INTRP)
1238 /* XXX This is only a hack for builtin_arraycopy and should be done better! */
1239 if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION) {
1240 assert(bte->md->returntype.type == TYPE_VOID);
1241 bte->md->returntype.type = TYPE_INT;
1244 codegen_emit_stub_builtin(jd, bte);
1247 if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION) {
1248 bte->md->returntype.type = TYPE_VOID;
1250 # if defined(ENABLE_INTRP)
1255 /* reallocate the memory and finish the code generation */
1259 /* set the stub entry point in the builtin table */
1261 bte->stub = code->entrypoint;
1263 #if defined(ENABLE_STATISTICS)
1265 size_stub_native += code->mcodelength;
1268 /* release memory */
1270 dump_release(dumpsize);
1271 #endif /* architecture list */
1275 /* codegen_generate_stub_native ************************************************
1277 Wrapper for codegen_emit_stub_native.
1280 the codeinfo representing the stub code.
1282 *******************************************************************************/
1284 codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
1293 /* mark dump memory */
1295 dumpsize = dump_size();
1300 jd->cd = DNEW(codegendata);
1301 jd->rd = DNEW(registerdata);
1304 /* Allocate codeinfo memory from the heap as we need to keep them. */
1306 jd->code = code_codeinfo_new(m); /* XXX check allocation */
1308 /* get required compiler data */
1312 /* set the flags for the current JIT run */
1314 #if defined(ENABLE_PROFILING)
1316 jd->flags |= JITDATA_FLAG_INSTRUMENT;
1319 if (opt_verbosecall)
1320 jd->flags |= JITDATA_FLAG_VERBOSECALL;
1322 /* setup code generation stuff */
1324 #if defined(ENABLE_JIT)
1325 # if defined(ENABLE_INTRP)
1333 /* create new method descriptor with additional native parameters */
1336 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
1338 nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
1339 md->paramcount * sizeof(typedesc) +
1340 nativeparams * sizeof(typedesc));
1342 nmd->paramcount = md->paramcount + nativeparams;
1344 nmd->params = DMNEW(paramdesc, nmd->paramcount);
1346 nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer */
1348 if (m->flags & ACC_STATIC)
1349 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer */
1351 MCOPY(nmd->paramtypes + nativeparams, md->paramtypes, typedesc,
1354 #if defined(ENABLE_JIT)
1355 # if defined(ENABLE_INTRP)
1358 /* pre-allocate the arguments for the native ABI */
1360 md_param_alloc_native(nmd);
1363 /* generate the code */
1365 #if defined(ENABLE_JIT)
1366 # if defined(ENABLE_INTRP)
1368 intrp_createnativestub(f, jd, nmd);
1371 codegen_emit_stub_native(jd, nmd, f);
1373 intrp_createnativestub(f, jd, nmd);
1376 /* reallocate the memory and finish the code generation */
1380 #if defined(ENABLE_STATISTICS)
1381 /* must be done after codegen_finish() */
1384 size_stub_native += code->mcodelength;
1387 #if !defined(NDEBUG)
1388 /* disassemble native stub */
1390 if (opt_shownativestub) {
1391 #if defined(ENABLE_DEBUG_FILTER)
1392 if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
1395 #if defined(ENABLE_DISASSEMBLER)
1396 codegen_disassemble_nativestub(m,
1397 (u1 *) (ptrint) code->entrypoint,
1398 (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
1401 /* show data segment */
1403 if (opt_showddatasegment)
1407 #endif /* !defined(NDEBUG) */
1409 /* release memory */
1411 dump_release(dumpsize);
1413 /* return native stub code */
1419 /* codegen_disassemble_nativestub **********************************************
1421 Disassembles the generated native stub.
1423 *******************************************************************************/
1425 #if defined(ENABLE_DISASSEMBLER)
1426 void codegen_disassemble_nativestub(methodinfo *m, u1 *start, u1 *end)
1428 printf("Native stub: ");
1429 utf_fprint_printable_ascii_classname(stdout, m->class->name);
1431 utf_fprint_printable_ascii(stdout, m->name);
1432 utf_fprint_printable_ascii(stdout, m->descriptor);
1433 printf("\n\nLength: %d\n\n", (s4) (end - start));
1435 DISASSEMBLE(start, end);
1440 /* codegen_stub_builtin_enter **************************************************
1442 Prepares the stuff required for a builtin function call:
1444 - adds a stackframe info structure to the chain, for stacktraces
1446 The layout of the builtin stub stackframe should look like this:
1448 +---------------------------+ <- SP (of parent Java function)
1450 +---------------------------+
1452 | stackframe info structure |
1454 +---------------------------+
1456 | arguments (if any) |
1458 +---------------------------+ <- SP (native stub)
1460 *******************************************************************************/
1462 void codegen_stub_builtin_enter(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
1464 stackframeinfo *sfi;
1466 /* get data structures from stack */
1468 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1470 /* add a stackframeinfo to the chain */
1472 stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
1476 /* codegen_stub_builtin_exit ***************************************************
1478 Removes the stuff required for a builtin function call.
1480 *******************************************************************************/
1482 void codegen_stub_builtin_exit(u1 *datasp)
1484 stackframeinfo *sfi;
1486 /* get data structures from stack */
1488 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1490 /* remove current stackframeinfo from chain */
1492 stacktrace_remove_stackframeinfo(sfi);
1496 /* codegen_start_native_call ***************************************************
1498 Prepares the stuff required for a native (JNI) function call:
1500 - adds a stackframe info structure to the chain, for stacktraces
1501 - prepares the local references table on the stack
1503 The layout of the native stub stackframe should look like this:
1505 +---------------------------+ <- java SP (of parent Java function)
1507 +---------------------------+ <- data SP
1509 | stackframe info structure |
1511 +---------------------------+
1513 | local references table |
1515 +---------------------------+
1517 | saved registers (if any) |
1519 +---------------------------+
1521 | arguments (if any) |
1523 +---------------------------+ <- current SP (native stub)
1525 *******************************************************************************/
1527 java_handle_t *codegen_start_native_call(u1 *currentsp, u1 *pv)
1529 stackframeinfo *sfi;
1530 localref_table *lrt;
1538 uint64_t *args_regs;
1539 uint64_t *args_stack;
1541 STATISTICS(count_calls_java_to_native++);
1543 /* get information from method header */
1545 code = *((codeinfo **) (pv + CodeinfoPointer));
1546 framesize = *((int32_t *) (pv + FrameSize));
1549 assert(framesize > sizeof(stackframeinfo) + sizeof(localref_table));
1551 /* get the methodinfo */
1557 /* calculate needed values */
1559 #if defined(__ALPHA__) || defined(__ARM__)
1560 datasp = currentsp + framesize - SIZEOF_VOID_P;
1561 javasp = currentsp + framesize;
1562 javara = *((uint8_t **) datasp);
1563 args_regs = (uint64_t *) currentsp;
1564 args_stack = (uint64_t *) javasp;
1565 #elif defined(__MIPS__) || defined(__S390__)
1566 /* MIPS and S390 always uses 8 bytes to store the RA */
1567 datasp = currentsp + framesize - 8;
1568 javasp = currentsp + framesize;
1569 javara = *((uint8_t **) datasp);
1570 #elif defined(__I386__) || defined (__M68K__) || defined (__X86_64__)
1571 datasp = currentsp + framesize;
1572 javasp = currentsp + framesize + SIZEOF_VOID_P;
1573 javara = *((uint8_t **) datasp);
1574 args_regs = (uint64_t *) currentsp;
1575 args_stack = (uint64_t *) javasp;
1576 #elif defined(__POWERPC__) || defined(__POWERPC64__)
1577 datasp = currentsp + framesize;
1578 javasp = currentsp + framesize;
1579 javara = *((uint8_t **) (datasp + LA_LR_OFFSET));
1581 /* XXX is was unable to do this port for SPARC64, sorry. (-michi) */
1582 /* XXX maybe we need to pass the RA as argument there */
1583 vm_abort("codegen_start_native_call: unsupported architecture");
1586 #if 0 && !defined(NDEBUG)
1587 /* print the call-trace if necesarry */
1589 if (opt_TraceJavaCalls)
1590 trace_java_call_enter(m, args_regs, args_stack);
1593 /* get data structures from stack */
1595 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1596 lrt = (localref_table *) (datasp - sizeof(stackframeinfo) -
1597 sizeof(localref_table));
1599 #if defined(ENABLE_JNI)
1600 /* add current JNI local references table to this thread */
1602 localref_table_add(lrt);
1605 #if defined(ENABLE_HANDLES)
1606 /* place all references into the local reference table */
1608 localref_fill(m, args_regs, args_stack);
1611 /* add a stackframeinfo to the chain */
1613 stacktrace_create_native_stackframeinfo(sfi, pv, javasp, javara);
1615 /* return a wrapped classinfo for static methods */
1617 if (m->flags & ACC_STATIC)
1618 return LLNI_classinfo_wrap(m->class);
1624 /* codegen_finish_native_call **************************************************
1626 Removes the stuff required for a native (JNI) function call.
1627 Additionally it checks for an exceptions and in case, get the
1628 exception object and clear the pointer.
1630 *******************************************************************************/
1632 java_object_t *codegen_finish_native_call(u1 *datasp)
1634 stackframeinfo *sfi;
1638 /* get data structures from stack */
1640 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1642 /* remove current stackframeinfo from chain */
1644 stacktrace_remove_stackframeinfo(sfi);
1646 /* get and unwrap the exception */
1647 /* ATTENTION: do the this _after_ the stackframeinfo was
1648 removed but _before_ the localref_table gets removed! */
1650 e = exceptions_get_and_clear_exception();
1653 #if defined(ENABLE_JNI)
1654 /* release JNI local references table for this thread */
1656 localref_frame_pop_all();
1657 localref_table_remove();
1664 /* removecompilerstub **********************************************************
1666 Deletes a compilerstub from memory (simply by freeing it).
1668 *******************************************************************************/
1670 void removecompilerstub(u1 *stub)
1672 /* pass size 1 to keep the intern function happy */
1674 CFREE((void *) stub, 1);
1678 /* removenativestub ************************************************************
1680 Removes a previously created native-stub from memory.
1682 *******************************************************************************/
1684 void removenativestub(u1 *stub)
1686 /* pass size 1 to keep the intern function happy */
1688 CFREE((void *) stub, 1);
1692 /* codegen_reg_of_var **********************************************************
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 pseudoregister v. If v is assigned to an actual
1697 register, this register will be returned. Otherwise (when v 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_var(u2 opcode, varinfo *v, s4 tempregnum)
1707 /* Do we have to generate a conditional move? Yes, then always
1708 return the temporary register. The real register is identified
1709 during the store. */
1711 if (opcode & ICMD_CONDITION_MASK)
1715 if (!(v->flags & INMEMORY))
1716 return v->vv.regoff;
1722 /* codegen_reg_of_dst **********************************************************
1724 This function determines a register, to which the result of an
1725 operation should go, when it is ultimatively intended to store the
1726 result in iptr->dst.var. If dst.var is assigned to an actual
1727 register, this register will be returned. Otherwise (when it is
1728 spilled) this function returns tempregnum. If not already done,
1729 regoff and flags are set in the stack location.
1731 *******************************************************************************/
1733 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
1735 return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
1739 /* codegen_emit_phi_moves ****************************************************
1741 Emits phi moves at the end of the basicblock.
1743 *******************************************************************************/
1745 #if defined(ENABLE_SSA)
1746 void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
1759 /* Moves from phi functions with highest indices have to be */
1760 /* inserted first, since this is the order as is used for */
1761 /* conflict resolution */
1763 for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
1764 lt_d = ls->phi_moves[bptr->nr][i][0];
1765 lt_s = ls->phi_moves[bptr->nr][i][1];
1766 #if defined(SSA_DEBUG_VERBOSE)
1768 printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
1770 if (lt_s == UNUSED) {
1771 #if defined(SSA_DEBUG_VERBOSE)
1773 printf(" ... not processed \n");
1778 d = VAR(ls->lifetime[lt_d].v_index);
1779 s = VAR(ls->lifetime[lt_s].v_index);
1782 if (d->type == -1) {
1783 #if defined(SSA_DEBUG_VERBOSE)
1785 printf("...returning - phi lifetimes where joined\n");
1790 if (s->type == -1) {
1791 #if defined(SSA_DEBUG_VERBOSE)
1793 printf("...returning - phi lifetimes where joined\n");
1799 tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
1800 tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
1801 emit_copy(jd, &tmp_i);
1803 #if defined(SSA_DEBUG_VERBOSE)
1804 if (compileverbose) {
1805 if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
1807 printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1809 else if (IS_INMEMORY(s->flags)) {
1811 printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1813 else if (IS_INMEMORY(d->flags)) {
1815 printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1819 printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1823 #endif /* defined(SSA_DEBUG_VERBOSE) */
1826 #endif /* defined(ENABLE_SSA) */
1831 * These are local overrides for various environment variables in Emacs.
1832 * Please do not remove this and leave it at the end of the file, where
1833 * Emacs will automagically detect them.
1834 * ---------------------------------------------------------------------
1837 * indent-tabs-mode: t
1841 * vim:noexpandtab:sw=4:ts=4: