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.
1197 *******************************************************************************/
1199 void codegen_generate_stub_builtin(methodinfo *m, builtintable_entry *bte)
1201 #if defined(__ARM__) || defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__SPARC64__) || defined(__X86_64__)
1206 /* mark dump memory */
1208 dumpsize = dump_size();
1213 jd->cd = DNEW(codegendata);
1217 /* Allocate codeinfo memory from the heap as we need to keep them. */
1219 jd->code = code_codeinfo_new(m); /* XXX check allocation */
1221 /* get required compiler data */
1225 /* setup code generation stuff */
1229 /* generate the code */
1231 #if defined(ENABLE_JIT)
1232 # if defined(ENABLE_INTRP)
1235 assert(bte->fp != NULL);
1236 codegen_emit_stub_native(jd, bte->md, bte->fp);
1237 # if defined(ENABLE_INTRP)
1242 /* reallocate the memory and finish the code generation */
1246 /* set the stub entry point in the builtin table */
1248 bte->stub = code->entrypoint;
1250 #if defined(ENABLE_STATISTICS)
1252 size_stub_native += code->mcodelength;
1255 /* release memory */
1257 dump_release(dumpsize);
1258 #endif /* architecture list */
1262 /* codegen_generate_stub_native ************************************************
1264 Wrapper for codegen_emit_stub_native.
1267 the codeinfo representing the stub code.
1269 *******************************************************************************/
1271 codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
1280 /* mark dump memory */
1282 dumpsize = dump_size();
1287 jd->cd = DNEW(codegendata);
1288 jd->rd = DNEW(registerdata);
1291 /* Allocate codeinfo memory from the heap as we need to keep them. */
1293 jd->code = code_codeinfo_new(m); /* XXX check allocation */
1295 /* get required compiler data */
1299 /* set the flags for the current JIT run */
1301 #if defined(ENABLE_PROFILING)
1303 jd->flags |= JITDATA_FLAG_INSTRUMENT;
1306 if (opt_verbosecall)
1307 jd->flags |= JITDATA_FLAG_VERBOSECALL;
1309 /* setup code generation stuff */
1311 #if defined(ENABLE_JIT)
1312 # if defined(ENABLE_INTRP)
1320 /* create new method descriptor with additional native parameters */
1323 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
1325 nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
1326 md->paramcount * sizeof(typedesc) +
1327 nativeparams * sizeof(typedesc));
1329 nmd->paramcount = md->paramcount + nativeparams;
1331 nmd->params = DMNEW(paramdesc, nmd->paramcount);
1333 nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer */
1335 if (m->flags & ACC_STATIC)
1336 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer */
1338 MCOPY(nmd->paramtypes + nativeparams, md->paramtypes, typedesc,
1341 #if defined(ENABLE_JIT)
1342 # if defined(ENABLE_INTRP)
1345 /* pre-allocate the arguments for the native ABI */
1347 md_param_alloc_native(nmd);
1350 /* generate the code */
1352 #if defined(ENABLE_JIT)
1353 # if defined(ENABLE_INTRP)
1355 intrp_createnativestub(f, jd, nmd);
1358 codegen_emit_stub_native(jd, nmd, f);
1360 intrp_createnativestub(f, jd, nmd);
1363 /* reallocate the memory and finish the code generation */
1367 #if defined(ENABLE_STATISTICS)
1368 /* must be done after codegen_finish() */
1371 size_stub_native += code->mcodelength;
1374 #if !defined(NDEBUG)
1375 /* disassemble native stub */
1377 if (opt_shownativestub) {
1378 #if defined(ENABLE_DEBUG_FILTER)
1379 if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
1382 #if defined(ENABLE_DISASSEMBLER)
1383 codegen_disassemble_nativestub(m,
1384 (u1 *) (ptrint) code->entrypoint,
1385 (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
1388 /* show data segment */
1390 if (opt_showddatasegment)
1394 #endif /* !defined(NDEBUG) */
1396 /* release memory */
1398 dump_release(dumpsize);
1400 /* return native stub code */
1406 /* codegen_disassemble_nativestub **********************************************
1408 Disassembles the generated native stub.
1410 *******************************************************************************/
1412 #if defined(ENABLE_DISASSEMBLER)
1413 void codegen_disassemble_nativestub(methodinfo *m, u1 *start, u1 *end)
1415 printf("Native stub: ");
1416 utf_fprint_printable_ascii_classname(stdout, m->class->name);
1418 utf_fprint_printable_ascii(stdout, m->name);
1419 utf_fprint_printable_ascii(stdout, m->descriptor);
1420 printf("\n\nLength: %d\n\n", (s4) (end - start));
1422 DISASSEMBLE(start, end);
1427 /* codegen_start_native_call ***************************************************
1429 Prepares the stuff required for a native (JNI) function call:
1431 - adds a stackframe info structure to the chain, for stacktraces
1432 - prepares the local references table on the stack
1434 The layout of the native stub stackframe should look like this:
1436 +---------------------------+ <- java SP (of parent Java function)
1438 +---------------------------+ <- data SP
1440 | stackframe info structure |
1442 +---------------------------+
1444 | local references table |
1446 +---------------------------+
1448 | saved registers (if any) |
1450 +---------------------------+
1452 | arguments (if any) |
1454 +---------------------------+ <- current SP (native stub)
1456 *******************************************************************************/
1458 java_handle_t *codegen_start_native_call(u1 *currentsp, u1 *pv)
1460 stackframeinfo *sfi;
1461 localref_table *lrt;
1470 uint64_t *arg_stack;
1472 STATISTICS(count_calls_java_to_native++);
1474 /* get information from method header */
1476 code = *((codeinfo **) (pv + CodeinfoPointer));
1477 framesize = *((int32_t *) (pv + FrameSize));
1479 assert(framesize > sizeof(stackframeinfo) + sizeof(localref_table));
1481 /* get the methodinfo */
1486 /* calculate needed values */
1488 #if defined(__ALPHA__) || defined(__ARM__)
1489 datasp = currentsp + framesize - SIZEOF_VOID_P;
1490 javasp = currentsp + framesize;
1491 javara = *((uint8_t **) datasp);
1492 arg_regs = (uint64_t *) currentsp;
1493 arg_stack = (uint64_t *) javasp;
1494 #elif defined(__MIPS__) || defined(__S390__)
1495 /* MIPS and S390 always uses 8 bytes to store the RA */
1496 datasp = currentsp + framesize - 8;
1497 javasp = currentsp + framesize;
1498 javara = *((uint8_t **) datasp);
1499 #elif defined(__I386__) || defined (__M68K__) || defined (__X86_64__)
1500 datasp = currentsp + framesize;
1501 javasp = currentsp + framesize + SIZEOF_VOID_P;
1502 javara = *((uint8_t **) datasp);
1503 arg_regs = (uint64_t *) currentsp;
1504 arg_stack = (uint64_t *) javasp;
1505 #elif defined(__POWERPC__) || defined(__POWERPC64__)
1506 datasp = currentsp + framesize;
1507 javasp = currentsp + framesize;
1508 javara = *((uint8_t **) (datasp + LA_LR_OFFSET));
1509 arg_regs = (uint64_t *) (currentsp + LA_SIZE + 4 * SIZEOF_VOID_P);
1510 arg_stack = (uint64_t *) javasp;
1512 /* XXX is was unable to do this port for SPARC64, sorry. (-michi) */
1513 /* XXX maybe we need to pass the RA as argument there */
1514 vm_abort("codegen_start_native_call: unsupported architecture");
1517 #if !defined(NDEBUG)
1518 # if defined(__POWERPC__) || defined (__X86_64__)
1519 /* print the call-trace if necesarry */
1521 if (opt_TraceJavaCalls)
1522 trace_java_call_enter(m, arg_regs, arg_stack);
1526 /* get data structures from stack */
1528 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1529 lrt = (localref_table *) (datasp - sizeof(stackframeinfo) -
1530 sizeof(localref_table));
1532 #if defined(ENABLE_JNI)
1533 /* add current JNI local references table to this thread */
1535 localref_table_add(lrt);
1538 #if defined(ENABLE_HANDLES)
1539 /* place all references into the local reference table */
1541 localref_fill(m, arg_regs, arg_stack);
1544 /* add a stackframeinfo to the chain */
1546 stacktrace_create_native_stackframeinfo(sfi, pv, javasp, javara);
1548 /* return a wrapped classinfo for static native methods */
1550 if (m->flags & ACC_STATIC)
1551 return LLNI_classinfo_wrap(m->class);
1557 /* codegen_finish_native_call **************************************************
1559 Removes the stuff required for a native (JNI) function call.
1560 Additionally it checks for an exceptions and in case, get the
1561 exception object and clear the pointer.
1563 *******************************************************************************/
1565 java_object_t *codegen_finish_native_call(u1 *currentsp, u1 *pv)
1567 stackframeinfo *sfi;
1577 /* get information from method header */
1579 code = *((codeinfo **) (pv + CodeinfoPointer));
1580 framesize = *((int32_t *) (pv + FrameSize));
1583 /* get the methodinfo */
1588 /* calculate needed values */
1590 #if defined(__ALPHA__) || defined(__ARM__)
1591 datasp = currentsp + framesize - SIZEOF_VOID_P;
1592 ret_regs = (uint64_t *) currentsp;
1593 #elif defined(__MIPS__) || defined(__S390__)
1594 /* MIPS and S390 always uses 8 bytes to store the RA */
1595 datasp = currentsp + framesize - 8;
1596 #elif defined(__I386__)
1597 datasp = currentsp + framesize;
1598 ret_regs = (uint64_t *) (currentsp + 2 * SIZEOF_VOID_P);
1599 #elif defined (__M68K__) || defined (__X86_64__)
1600 datasp = currentsp + framesize;
1601 ret_regs = (uint64_t *) currentsp;
1602 #elif defined(__POWERPC__) || defined(__POWERPC64__)
1603 datasp = currentsp + framesize;
1604 ret_regs = (uint64_t *) (currentsp + LA_SIZE + 2 * SIZEOF_VOID_P);
1606 vm_abort("codegen_finish_native_call: unsupported architecture");
1610 #if !defined(NDEBUG)
1611 # if defined(__POWERPC__) || defined (__X86_64__)
1612 /* print the call-trace if necesarry */
1614 if (opt_TraceJavaCalls)
1615 trace_java_call_exit(m, ret_regs);
1619 /* get data structures from stack */
1621 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1623 /* remove current stackframeinfo from chain */
1625 stacktrace_remove_stackframeinfo(sfi);
1627 /* XXX unfill lrt here!!! */
1629 /* get and unwrap the exception */
1630 /* ATTENTION: do the this _after_ the stackframeinfo was
1631 removed but _before_ the localref_table gets removed! */
1633 e = exceptions_get_and_clear_exception();
1636 #if defined(ENABLE_JNI)
1637 /* release JNI local references table for this thread */
1639 localref_frame_pop_all();
1640 localref_table_remove();
1647 /* removecompilerstub **********************************************************
1649 Deletes a compilerstub from memory (simply by freeing it).
1651 *******************************************************************************/
1653 void removecompilerstub(u1 *stub)
1655 /* pass size 1 to keep the intern function happy */
1657 CFREE((void *) stub, 1);
1661 /* removenativestub ************************************************************
1663 Removes a previously created native-stub from memory.
1665 *******************************************************************************/
1667 void removenativestub(u1 *stub)
1669 /* pass size 1 to keep the intern function happy */
1671 CFREE((void *) stub, 1);
1675 /* codegen_reg_of_var **********************************************************
1677 This function determines a register, to which the result of an
1678 operation should go, when it is ultimatively intended to store the
1679 result in pseudoregister v. If v is assigned to an actual
1680 register, this register will be returned. Otherwise (when v is
1681 spilled) this function returns tempregnum. If not already done,
1682 regoff and flags are set in the stack location.
1684 *******************************************************************************/
1686 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
1690 /* Do we have to generate a conditional move? Yes, then always
1691 return the temporary register. The real register is identified
1692 during the store. */
1694 if (opcode & ICMD_CONDITION_MASK)
1698 if (!(v->flags & INMEMORY))
1699 return v->vv.regoff;
1705 /* codegen_reg_of_dst **********************************************************
1707 This function determines a register, to which the result of an
1708 operation should go, when it is ultimatively intended to store the
1709 result in iptr->dst.var. If dst.var is assigned to an actual
1710 register, this register will be returned. Otherwise (when it is
1711 spilled) this function returns tempregnum. If not already done,
1712 regoff and flags are set in the stack location.
1714 *******************************************************************************/
1716 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
1718 return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
1722 /* codegen_emit_phi_moves ****************************************************
1724 Emits phi moves at the end of the basicblock.
1726 *******************************************************************************/
1728 #if defined(ENABLE_SSA)
1729 void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
1742 /* Moves from phi functions with highest indices have to be */
1743 /* inserted first, since this is the order as is used for */
1744 /* conflict resolution */
1746 for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
1747 lt_d = ls->phi_moves[bptr->nr][i][0];
1748 lt_s = ls->phi_moves[bptr->nr][i][1];
1749 #if defined(SSA_DEBUG_VERBOSE)
1751 printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
1753 if (lt_s == UNUSED) {
1754 #if defined(SSA_DEBUG_VERBOSE)
1756 printf(" ... not processed \n");
1761 d = VAR(ls->lifetime[lt_d].v_index);
1762 s = VAR(ls->lifetime[lt_s].v_index);
1765 if (d->type == -1) {
1766 #if defined(SSA_DEBUG_VERBOSE)
1768 printf("...returning - phi lifetimes where joined\n");
1773 if (s->type == -1) {
1774 #if defined(SSA_DEBUG_VERBOSE)
1776 printf("...returning - phi lifetimes where joined\n");
1782 tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
1783 tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
1784 emit_copy(jd, &tmp_i);
1786 #if defined(SSA_DEBUG_VERBOSE)
1787 if (compileverbose) {
1788 if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
1790 printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1792 else if (IS_INMEMORY(s->flags)) {
1794 printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1796 else if (IS_INMEMORY(d->flags)) {
1798 printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1802 printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1806 #endif /* defined(SSA_DEBUG_VERBOSE) */
1809 #endif /* defined(ENABLE_SSA) */
1814 * These are local overrides for various environment variables in Emacs.
1815 * Please do not remove this and leave it at the end of the file, where
1816 * Emacs will automagically detect them.
1817 * ---------------------------------------------------------------------
1820 * indent-tabs-mode: t
1824 * vim:noexpandtab:sw=4:ts=4: