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 */
57 #include "mm/memory.h"
59 #include "toolbox/avl.h"
60 #include "toolbox/list.h"
61 #include "toolbox/logging.h"
63 #include "native/jni.h"
64 #include "native/localref.h"
65 #include "native/native.h"
67 #include "threads/threads-common.h"
69 #include "vm/builtin.h"
70 #include "vm/exceptions.h"
71 #include "vm/stringlocal.h"
73 #include "vm/jit/abi.h"
74 #include "vm/jit/asmpart.h"
75 #include "vm/jit/codegen-common.h"
77 #if defined(ENABLE_DISASSEMBLER)
78 # include "vm/jit/disass.h"
81 #include "vm/jit/dseg.h"
82 #include "vm/jit/emit-common.h"
83 #include "vm/jit/jit.h"
84 #include "vm/jit/md.h"
85 #include "vm/jit/patcher-common.h"
86 #include "vm/jit/replace.h"
87 #if defined(ENABLE_SSA)
88 # include "vm/jit/optimizing/lsra.h"
89 # include "vm/jit/optimizing/ssa.h"
91 #include "vm/jit/stacktrace.h"
93 #if defined(ENABLE_INTRP)
94 #include "vm/jit/intrp/intrp.h"
97 #include "vmcore/method.h"
98 #include "vmcore/options.h"
100 # include "vmcore/statistics.h"
102 #if defined(ENABLE_VMLOG)
103 #include <vmlog_cacao.h>
108 /* in this tree we store all method addresses *********************************/
110 static avl_tree_t *methodtree = NULL;
111 static s4 methodtree_comparator(const void *treenode, const void *node);
114 /* codegen_init ****************************************************************
118 *******************************************************************************/
120 void codegen_init(void)
122 /* this tree is global, not method specific */
125 #if defined(ENABLE_JIT)
126 methodtree_element *mte;
129 methodtree = avl_create(&methodtree_comparator);
131 #if defined(ENABLE_JIT)
132 /* insert asm_vm_call_method */
134 mte = NEW(methodtree_element);
136 mte->startpc = (u1 *) (ptrint) asm_vm_call_method;
137 mte->endpc = (u1 *) (ptrint) asm_vm_call_method_end;
139 avl_insert(methodtree, mte);
140 #endif /* defined(ENABLE_JIT) */
147 /* codegen_setup ***************************************************************
149 Allocates and initialises code area, data area and references.
151 *******************************************************************************/
153 void codegen_setup(jitdata *jd)
158 /* get required compiler data */
163 /* initialize members */
167 cd->mcodebase = DMNEW(u1, MCODEINITSIZE);
168 cd->mcodeend = cd->mcodebase + MCODEINITSIZE;
169 cd->mcodesize = MCODEINITSIZE;
171 /* initialize mcode variables */
173 cd->mcodeptr = cd->mcodebase;
174 cd->lastmcodeptr = cd->mcodebase;
176 #if defined(ENABLE_INTRP)
177 /* native dynamic superinstructions variables */
180 cd->ncodebase = DMNEW(u1, NCODEINITSIZE);
181 cd->ncodesize = NCODEINITSIZE;
183 /* initialize ncode variables */
185 cd->ncodeptr = cd->ncodebase;
187 cd->lastinstwithoutdispatch = ~0; /* no inst without dispatch */
188 cd->superstarts = NULL;
195 cd->jumpreferences = NULL;
197 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
198 cd->datareferences = NULL;
201 /* cd->patchrefs = list_create_dump(OFFSET(patchref, linkage)); */
202 cd->patchrefs = NULL;
203 cd->brancheslabel = list_create_dump(OFFSET(branch_label_ref_t, linkage));
204 cd->listcritical = list_create_dump(OFFSET(critical_section_ref_t, linkage));
206 cd->linenumberreferences = NULL;
207 cd->linenumbertablesizepos = 0;
208 cd->linenumbertablestartpos = 0;
209 cd->linenumbertab = 0;
213 /* codegen_reset ***************************************************************
215 Resets the codegen data structure so we can recompile the method.
217 *******************************************************************************/
219 static void codegen_reset(jitdata *jd)
225 /* get required compiler data */
230 /* reset error flag */
232 cd->flags &= ~CODEGENDATA_FLAG_ERROR;
234 /* reset some members, we reuse the code memory already allocated
235 as this should have almost the correct size */
237 cd->mcodeptr = cd->mcodebase;
238 cd->lastmcodeptr = cd->mcodebase;
243 cd->jumpreferences = NULL;
245 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
246 cd->datareferences = NULL;
249 /* cd->patchrefs = list_create_dump(OFFSET(patchref, linkage)); */
250 cd->patchrefs = NULL;
251 cd->brancheslabel = list_create_dump(OFFSET(branch_label_ref_t, linkage));
252 cd->listcritical = list_create_dump(OFFSET(critical_section_ref_t, linkage));
254 cd->linenumberreferences = NULL;
255 cd->linenumbertablesizepos = 0;
256 cd->linenumbertablestartpos = 0;
257 cd->linenumbertab = 0;
259 /* We need to clear the mpc and the branch references from all
260 basic blocks as they will definitely change. */
262 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
264 bptr->branchrefs = NULL;
267 /* We need to clear all the patcher references from the codeinfo
268 since they all will be regenerated */
270 patcher_list_reset(code);
272 #if defined(ENABLE_REPLACEMENT)
273 code->rplpoints = NULL;
274 code->rplpointcount = 0;
275 code->regalloc = NULL;
276 code->regalloccount = 0;
277 code->globalcount = 0;
282 /* codegen_generate ************************************************************
284 Generates the code for the currently compiled method.
286 *******************************************************************************/
288 bool codegen_generate(jitdata *jd)
292 /* get required compiler data */
296 /* call the machine-dependent code generation function */
298 if (!codegen_emit(jd))
301 /* check for an error */
303 if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
304 /* check for long-branches flag, if it is set we recompile the
309 log_message_method("Re-generating code: ", jd->m);
312 /* XXX maybe we should tag long-branches-methods for recompilation */
314 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
315 /* we have to reset the codegendata structure first */
319 /* and restart the compiler run */
321 if (!codegen_emit(jd))
325 vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
330 log_message_method("Re-generating code done: ", jd->m);
334 /* reallocate the memory and finish the code generation */
338 /* everything's ok */
344 /* codegen_close ***************************************************************
348 *******************************************************************************/
350 void codegen_close(void)
352 /* TODO: release avl tree on i386 and x86_64 */
356 /* codegen_increase ************************************************************
360 *******************************************************************************/
362 void codegen_increase(codegendata *cd)
366 /* save old mcodebase pointer */
368 oldmcodebase = cd->mcodebase;
370 /* reallocate to new, doubled memory */
372 cd->mcodebase = DMREALLOC(cd->mcodebase,
377 cd->mcodeend = cd->mcodebase + cd->mcodesize;
379 /* set new mcodeptr */
381 cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
383 #if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(__M68K__) || defined(ENABLE_INTRP) \
384 || defined(__SPARC_64__)
385 /* adjust the pointer to the last patcher position */
387 if (cd->lastmcodeptr != NULL)
388 cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
393 /* codegen_ncode_increase ******************************************************
397 *******************************************************************************/
399 #if defined(ENABLE_INTRP)
400 u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
404 /* save old ncodebase pointer */
406 oldncodebase = cd->ncodebase;
408 /* reallocate to new, doubled memory */
410 cd->ncodebase = DMREALLOC(cd->ncodebase,
416 /* return the new ncodeptr */
418 return (cd->ncodebase + (ncodeptr - oldncodebase));
423 /* codegen_add_branch_ref ******************************************************
425 Prepends an branch to the list.
427 *******************************************************************************/
429 void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
434 STATISTICS(count_branches_unresolved++);
436 /* calculate the mpc of the branch instruction */
438 branchmpc = cd->mcodeptr - cd->mcodebase;
440 br = DNEW(branchref);
442 br->branchmpc = branchmpc;
443 br->condition = condition;
445 br->options = options;
446 br->next = target->branchrefs;
448 target->branchrefs = br;
452 /* codegen_resolve_branchrefs **************************************************
454 Resolves and patches the branch references of a given basic block.
456 *******************************************************************************/
458 void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
463 /* Save the mcodeptr because in the branch emitting functions
464 we generate code somewhere inside already generated code,
465 but we're still in the actual code generation phase. */
467 mcodeptr = cd->mcodeptr;
469 /* just to make sure */
471 assert(bptr->mpc >= 0);
473 for (br = bptr->branchrefs; br != NULL; br = br->next) {
474 /* temporary set the mcodeptr */
476 cd->mcodeptr = cd->mcodebase + br->branchmpc;
478 /* emit_bccz and emit_branch emit the correct code, even if we
479 pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
481 emit_bccz(cd, bptr, br->condition, br->reg, br->options);
484 /* restore mcodeptr */
486 cd->mcodeptr = mcodeptr;
490 /* codegen_branch_label_add ****************************************************
492 Append an branch to the label-branch list.
494 *******************************************************************************/
496 void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
499 branch_label_ref_t *br;
502 /* get the label list */
504 list = cd->brancheslabel;
506 /* calculate the current mpc */
508 mpc = cd->mcodeptr - cd->mcodebase;
510 br = DNEW(branch_label_ref_t);
514 br->condition = condition;
516 br->options = options;
518 /* add the branch to the list */
520 list_add_last_unsynced(list, br);
524 /* codegen_add_patch_ref *******************************************************
526 Appends a new patcher reference to the list of patching positions.
528 *******************************************************************************/
530 void codegen_add_patch_ref(codegendata *cd, functionptr patcher, voidptr ref,
536 branchmpc = cd->mcodeptr - cd->mcodebase;
540 pr->branchpos = branchmpc;
542 pr->patcher = patcher;
545 /* list_add_first(cd->patchrefs, pr); */
546 pr->next = cd->patchrefs;
549 /* Generate NOPs for opt_shownops. */
554 #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__M68K__) || defined(__MIPS__) \
555 || defined(__SPARC_64__) || defined(__X86_64__))
557 /* On some architectures the patcher stub call instruction might
558 be longer than the actual instruction generated. On this
559 architectures we store the last patcher call position and after
560 the basic block code generation is completed, we check the
561 range and maybe generate some nop's. */
562 /* The nops are generated in codegen_emit in each codegen */
564 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
569 /* codegen_critical_section_new ************************************************
571 Allocates a new critical-section reference and adds it to the
572 critical-section list.
574 *******************************************************************************/
576 #if defined(ENABLE_THREADS)
577 void codegen_critical_section_new(codegendata *cd)
580 critical_section_ref_t *csr;
583 /* get the critical section list */
585 list = cd->listcritical;
587 /* calculate the current mpc */
589 mpc = cd->mcodeptr - cd->mcodebase;
591 csr = DNEW(critical_section_ref_t);
593 /* We only can set restart right now, as start and end are set by
594 the following, corresponding functions. */
600 /* add the branch to the list */
602 list_add_last_unsynced(list, csr);
607 /* codegen_critical_section_start **********************************************
609 Set the start-point of the current critical section (which is the
610 last element of the list).
612 *******************************************************************************/
614 #if defined(ENABLE_THREADS)
615 void codegen_critical_section_start(codegendata *cd)
618 critical_section_ref_t *csr;
621 /* get the critical section list */
623 list = cd->listcritical;
625 /* calculate the current mpc */
627 mpc = cd->mcodeptr - cd->mcodebase;
629 /* get the current critical section */
631 csr = list_last_unsynced(list);
633 /* set the start point */
635 assert(csr->start == -1);
642 /* codegen_critical_section_end ************************************************
644 Set the end-point of the current critical section (which is the
645 last element of the list).
647 *******************************************************************************/
649 #if defined(ENABLE_THREADS)
650 void codegen_critical_section_end(codegendata *cd)
653 critical_section_ref_t *csr;
656 /* get the critical section list */
658 list = cd->listcritical;
660 /* calculate the current mpc */
662 mpc = cd->mcodeptr - cd->mcodebase;
664 /* get the current critical section */
666 csr = list_last_unsynced(list);
668 /* set the end point */
670 assert(csr->end == -1);
677 /* codegen_critical_section_finish *********************************************
679 Finish the critical sections, create the critical section nodes for
680 the AVL tree and insert them into the tree.
682 *******************************************************************************/
684 #if defined(ENABLE_THREADS)
685 static void codegen_critical_section_finish(jitdata *jd)
690 critical_section_ref_t *csr;
691 critical_section_node_t *csn;
693 /* get required compiler data */
698 /* get the critical section list */
700 list = cd->listcritical;
702 /* iterate over all critical sections */
704 for (csr = list_first_unsynced(list); csr != NULL;
705 csr = list_next_unsynced(list, csr)) {
706 /* check if all points are set */
708 assert(csr->start != -1);
709 assert(csr->end != -1);
710 assert(csr->restart != -1);
712 /* allocate tree node */
714 csn = NEW(critical_section_node_t);
716 csn->start = code->entrypoint + csr->start;
717 csn->end = code->entrypoint + csr->end;
718 csn->restart = code->entrypoint + csr->restart;
720 /* insert into the tree */
722 critical_section_register(csn);
728 /* methodtree_comparator *******************************************************
730 Comparator function used for the AVL tree of methods.
733 treenode....the node from the tree
734 node........the node to compare to the tree-node
736 *******************************************************************************/
738 static s4 methodtree_comparator(const void *treenode, const void *node)
740 methodtree_element *mte;
741 methodtree_element *mtepc;
743 mte = (methodtree_element *) treenode;
744 mtepc = (methodtree_element *) node;
746 /* compare both startpc and endpc of pc, even if they have the same value,
747 otherwise the avl_probe sometimes thinks the element is already in the
751 /* On S390 addresses are 31 bit. Compare only 31 bits of value.
753 # define ADDR_MASK(a) ((a) & 0x7FFFFFFF)
755 # define ADDR_MASK(a) (a)
758 if (ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->startpc) &&
759 ADDR_MASK((long) mtepc->startpc) <= ADDR_MASK((long) mte->endpc) &&
760 ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->endpc) &&
761 ADDR_MASK((long) mtepc->endpc) <= ADDR_MASK((long) mte->endpc)) {
764 } else if (ADDR_MASK((long) mtepc->startpc) < ADDR_MASK((long) mte->startpc)) {
775 /* codegen_insertmethod ********************************************************
777 Insert the machine code range of a method into the AVL tree of methods.
779 *******************************************************************************/
781 void codegen_insertmethod(u1 *startpc, u1 *endpc)
783 methodtree_element *mte;
785 /* allocate new method entry */
787 mte = NEW(methodtree_element);
789 mte->startpc = startpc;
792 /* this function does not return an error, but asserts for
795 avl_insert(methodtree, mte);
799 /* codegen_get_pv_from_pc ******************************************************
801 Find the PV for the given PC by searching in the AVL tree of
804 *******************************************************************************/
806 u1 *codegen_get_pv_from_pc(u1 *pc)
808 methodtree_element mtepc;
809 methodtree_element *mte;
811 /* allocation of the search structure on the stack is much faster */
816 mte = avl_find(methodtree, &mtepc);
819 /* No method was found. Let's dump a stacktrace. */
821 #if defined(ENABLE_VMLOG)
822 vmlog_cacao_signl("SIGSEGV");
825 log_println("We received a SIGSEGV and tried to handle it, but we were");
826 log_println("unable to find a Java method at:");
828 #if SIZEOF_VOID_P == 8
829 log_println("PC=0x%016lx", pc);
831 log_println("PC=0x%08x", pc);
835 log_println("Dumping the current stacktrace:");
837 #if defined(ENABLE_THREADS)
838 /* XXX michi: This should be available even without threads! */
839 threads_print_stacktrace();
842 vm_abort("Exiting...");
849 /* codegen_get_pv_from_pc_nocheck **********************************************
851 Find the PV for the given PC by searching in the AVL tree of
852 methods. This method does not check the return value and is used
855 *******************************************************************************/
857 u1 *codegen_get_pv_from_pc_nocheck(u1 *pc)
859 methodtree_element mtepc;
860 methodtree_element *mte;
862 /* allocation of the search structure on the stack is much faster */
867 mte = avl_find(methodtree, &mtepc);
876 /* codegen_set_replacement_point_notrap ****************************************
878 Record the position of a non-trappable replacement point.
880 *******************************************************************************/
882 #if defined(ENABLE_REPLACEMENT)
884 void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
886 void codegen_set_replacement_point_notrap(codegendata *cd)
889 assert(cd->replacementpoint);
890 assert(cd->replacementpoint->type == type);
891 assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
893 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
895 cd->replacementpoint++;
897 #endif /* defined(ENABLE_REPLACEMENT) */
900 /* codegen_set_replacement_point ***********************************************
902 Record the position of a trappable replacement point.
904 *******************************************************************************/
906 #if defined(ENABLE_REPLACEMENT)
908 void codegen_set_replacement_point(codegendata *cd, s4 type)
910 void codegen_set_replacement_point(codegendata *cd)
913 assert(cd->replacementpoint);
914 assert(cd->replacementpoint->type == type);
915 assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
917 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
919 cd->replacementpoint++;
921 /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
923 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
925 #endif /* defined(ENABLE_REPLACEMENT) */
928 /* codegen_finish **************************************************************
930 Finishes the code generation. A new memory, large enough for both
931 data and code, is allocated and data and code are copied together
932 to their final layout, unresolved jumps are resolved, ...
934 *******************************************************************************/
936 void codegen_finish(jitdata *jd)
941 #if defined(ENABLE_INTRP)
950 /* get required compiler data */
955 /* prevent compiler warning */
957 #if defined(ENABLE_INTRP)
961 /* calculate the code length */
963 mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
965 #if defined(ENABLE_STATISTICS)
967 count_code_len += mcodelen;
968 count_data_len += cd->dseglen;
972 alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
974 #if defined(ENABLE_INTRP)
976 ncodelen = cd->ncodeptr - cd->ncodebase;
978 ncodelen = 0; /* avoid compiler warning */
982 cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
983 alignedlen = alignedmcodelen + cd->dseglen;
985 #if defined(ENABLE_INTRP)
987 alignedlen += ncodelen;
991 /* allocate new memory */
993 code->mcodelength = mcodelen + cd->dseglen;
994 code->mcode = CNEW(u1, alignedlen);
996 /* set the entrypoint of the method */
998 assert(code->entrypoint == NULL);
999 code->entrypoint = epoint = (code->mcode + cd->dseglen);
1001 /* fill the data segment (code->entrypoint must already be set!) */
1005 /* copy code to the new location */
1007 MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
1009 #if defined(ENABLE_INTRP)
1010 /* relocate native dynamic superinstruction code (if any) */
1013 cd->mcodebase = code->entrypoint;
1016 u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
1018 MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
1020 /* flush the instruction and data caches */
1022 md_cacheflush(ncodebase, ncodelen);
1024 /* set some cd variables for dynamic_super_rerwite */
1026 cd->ncodebase = ncodebase;
1029 cd->ncodebase = NULL;
1032 dynamic_super_rewrite(cd);
1036 /* jump table resolving */
1038 for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
1039 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
1040 (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
1042 /* line number table resolving */
1048 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
1050 target = lr->targetmpc;
1051 /* if the entry contains an mcode pointer (normal case), resolve it */
1052 /* (see doc/inlining_stacktrace.txt for details) */
1053 if (lr->linenumber >= -2) {
1054 target += (ptrint) epoint;
1056 *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) =
1057 (functionptr) target;
1060 *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
1061 (functionptr) ((ptrint) epoint + cd->linenumbertab);
1063 *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
1066 /* patcher resolving */
1068 pr = list_first_unsynced(code->patchers);
1070 pr->mpc += (ptrint) epoint;
1071 pr->datap = (ptrint) (pr->disp + epoint);
1072 pr = list_next_unsynced(code->patchers, pr);
1075 #if defined(ENABLE_REPLACEMENT)
1076 /* replacement point resolving */
1081 rp = code->rplpoints;
1082 for (i=0; i<code->rplpointcount; ++i, ++rp) {
1083 rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
1086 #endif /* defined(ENABLE_REPLACEMENT) */
1088 /* add method into methodtree to find the entrypoint */
1090 codegen_insertmethod(code->entrypoint, code->entrypoint + mcodelen);
1092 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
1093 /* resolve data segment references */
1095 dseg_resolve_datareferences(jd);
1098 #if defined(ENABLE_THREADS)
1099 /* create cirtical sections */
1101 codegen_critical_section_finish(jd);
1104 /* flush the instruction and data caches */
1106 md_cacheflush(code->mcode, code->mcodelength);
1110 /* codegen_generate_stub_compiler **********************************************
1112 Wrapper for codegen_emit_stub_compiler.
1115 pointer to the compiler stub code.
1117 *******************************************************************************/
1119 u1 *codegen_generate_stub_compiler(methodinfo *m)
1123 ptrint *d; /* pointer to data memory */
1124 u1 *c; /* pointer to code memory */
1127 /* mark dump memory */
1129 dumpsize = dump_size();
1131 /* allocate required data structures */
1136 jd->cd = DNEW(codegendata);
1139 /* get required compiler data */
1143 /* allocate code memory */
1145 c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1147 /* set pointers correctly */
1153 c = c + 3 * SIZEOF_VOID_P;
1156 /* NOTE: The codeinfo pointer is actually a pointer to the
1157 methodinfo (this fakes a codeinfo structure). */
1159 d[0] = (ptrint) asm_call_jit_compiler;
1161 d[2] = (ptrint) &d[1]; /* fake code->m */
1163 /* call the emit function */
1165 codegen_emit_stub_compiler(jd);
1167 #if defined(ENABLE_STATISTICS)
1169 count_cstub_len += 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
1174 md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1176 /* release dump memory */
1178 dump_release(dumpsize);
1180 /* return native stub code */
1186 /* codegen_generate_stub_builtin ***********************************************
1188 Wrapper for codegen_emit_stub_builtin.
1191 Pointer to the entrypoint of the stub.
1193 *******************************************************************************/
1195 void codegen_generate_stub_builtin(builtintable_entry *bte)
1201 /* mark dump memory */
1203 dumpsize = dump_size();
1208 jd->cd = DNEW(codegendata);
1212 /* Allocate codeinfo memory from the heap as we need to keep them. */
1214 jd->code = code_codeinfo_new(NULL);
1216 /* get required compiler data */
1220 /* setup code generation stuff */
1224 /* generate the code */
1226 #if defined(ENABLE_JIT)
1227 # if defined(ENABLE_INTRP)
1230 codegen_emit_stub_builtin(jd, bte);
1233 /* reallocate the memory and finish the code generation */
1237 /* set the stub entry point in the builtin table */
1239 bte->stub = code->entrypoint;
1241 #if defined(ENABLE_STATISTICS)
1243 size_stub_native += code->mcodelength;
1246 /* release memory */
1248 dump_release(dumpsize);
1252 /* codegen_generate_stub_native ************************************************
1254 Wrapper for codegen_emit_stub_native.
1257 the codeinfo representing the stub code.
1259 *******************************************************************************/
1261 codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
1270 /* mark dump memory */
1272 dumpsize = dump_size();
1277 jd->cd = DNEW(codegendata);
1278 jd->rd = DNEW(registerdata);
1281 /* Allocate codeinfo memory from the heap as we need to keep them. */
1283 jd->code = code_codeinfo_new(m); /* XXX check allocation */
1285 /* get required compiler data */
1289 /* set the flags for the current JIT run */
1291 #if defined(ENABLE_PROFILING)
1293 jd->flags |= JITDATA_FLAG_INSTRUMENT;
1296 if (opt_verbosecall)
1297 jd->flags |= JITDATA_FLAG_VERBOSECALL;
1299 /* setup code generation stuff */
1301 #if defined(ENABLE_JIT)
1302 # if defined(ENABLE_INTRP)
1310 /* create new method descriptor with additional native parameters */
1313 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
1315 nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
1316 md->paramcount * sizeof(typedesc) +
1317 nativeparams * sizeof(typedesc));
1319 nmd->paramcount = md->paramcount + nativeparams;
1321 nmd->params = DMNEW(paramdesc, nmd->paramcount);
1323 nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer */
1325 if (m->flags & ACC_STATIC)
1326 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer */
1328 MCOPY(nmd->paramtypes + nativeparams, md->paramtypes, typedesc,
1331 #if defined(ENABLE_JIT)
1332 # if defined(ENABLE_INTRP)
1335 /* pre-allocate the arguments for the native ABI */
1337 md_param_alloc_native(nmd);
1340 /* generate the code */
1342 #if defined(ENABLE_JIT)
1343 # if defined(ENABLE_INTRP)
1345 intrp_createnativestub(f, jd, nmd);
1348 codegen_emit_stub_native(jd, nmd, f);
1350 intrp_createnativestub(f, jd, nmd);
1353 /* reallocate the memory and finish the code generation */
1357 #if defined(ENABLE_STATISTICS)
1358 /* must be done after codegen_finish() */
1361 size_stub_native += code->mcodelength;
1364 #if !defined(NDEBUG)
1365 /* disassemble native stub */
1367 if (opt_shownativestub) {
1368 #if defined(ENABLE_DEBUG_FILTER)
1369 if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
1372 #if defined(ENABLE_DISASSEMBLER)
1373 codegen_disassemble_nativestub(m,
1374 (u1 *) (ptrint) code->entrypoint,
1375 (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
1378 /* show data segment */
1380 if (opt_showddatasegment)
1384 #endif /* !defined(NDEBUG) */
1386 /* release memory */
1388 dump_release(dumpsize);
1390 /* return native stub code */
1396 /* codegen_disassemble_nativestub **********************************************
1398 Disassembles the generated native stub.
1400 *******************************************************************************/
1402 #if defined(ENABLE_DISASSEMBLER)
1403 void codegen_disassemble_nativestub(methodinfo *m, u1 *start, u1 *end)
1405 printf("Native stub: ");
1406 utf_fprint_printable_ascii_classname(stdout, m->class->name);
1408 utf_fprint_printable_ascii(stdout, m->name);
1409 utf_fprint_printable_ascii(stdout, m->descriptor);
1410 printf("\n\nLength: %d\n\n", (s4) (end - start));
1412 DISASSEMBLE(start, end);
1417 /* codegen_stub_builtin_enter **************************************************
1419 Prepares the stuff required for a builtin function call:
1421 - adds a stackframe info structure to the chain, for stacktraces
1423 The layout of the builtin stub stackframe should look like this:
1425 +---------------------------+ <- SP (of parent Java function)
1427 +---------------------------+
1429 | stackframe info structure |
1431 +---------------------------+
1433 | arguments (if any) |
1435 +---------------------------+ <- SP (native stub)
1437 *******************************************************************************/
1439 void codegen_stub_builtin_enter(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
1441 stackframeinfo *sfi;
1443 /* get data structures from stack */
1445 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1447 /* add a stackframeinfo to the chain */
1449 stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
1451 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1452 /* set the native world flag */
1454 THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE;
1459 /* codegen_stub_builtin_exit ***************************************************
1461 Removes the stuff required for a builtin function call.
1463 *******************************************************************************/
1465 void codegen_stub_builtin_exit(u1 *datasp)
1467 stackframeinfo *sfi;
1468 stackframeinfo **psfi;
1470 /* get data structures from stack */
1472 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1474 /* remove current stackframeinfo from chain */
1476 psfi = &STACKFRAMEINFO;
1480 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1481 /* clear the native world flag */
1483 THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE;
1488 /* codegen_start_native_call ***************************************************
1490 Prepares the stuff required for a native (JNI) function call:
1492 - adds a stackframe info structure to the chain, for stacktraces
1493 - prepares the local references table on the stack
1495 The layout of the native stub stackframe should look like this:
1497 +---------------------------+ <- SP (of parent Java function)
1499 +---------------------------+
1501 | stackframe info structure |
1503 +---------------------------+
1505 | local references table |
1507 +---------------------------+
1509 | arguments (if any) |
1511 +---------------------------+ <- SP (native stub)
1513 *******************************************************************************/
1515 void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
1517 stackframeinfo *sfi;
1518 localref_table *lrt;
1520 STATISTICS(count_calls_java_to_native++);
1522 /* get data structures from stack */
1524 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1525 lrt = (localref_table *) (datasp - sizeof(stackframeinfo) -
1526 sizeof(localref_table));
1528 /* add a stackframeinfo to the chain */
1530 stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
1532 #if defined(ENABLE_JNI)
1533 /* add current JNI local references table to this thread */
1535 localref_table_add(lrt);
1538 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1539 /* set the native world flag */
1541 THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE;
1546 /* codegen_finish_native_call **************************************************
1548 Removes the stuff required for a native (JNI) function call.
1549 Additionally it checks for an exceptions and in case, get the
1550 exception object and clear the pointer.
1552 *******************************************************************************/
1554 java_object_t *codegen_finish_native_call(u1 *datasp)
1556 stackframeinfo *sfi;
1557 stackframeinfo **psfi;
1560 /* get data structures from stack */
1562 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1564 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1565 /* clear the native world flag */
1567 THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE;
1570 /* remove current stackframeinfo from chain */
1572 psfi = &STACKFRAMEINFO;
1576 #if defined(ENABLE_JNI)
1577 /* release JNI local references table for this thread */
1579 localref_frame_pop_all();
1580 localref_table_remove();
1583 /* get the exception and return it */
1585 e = exceptions_get_and_clear_exception();
1591 /* removecompilerstub **********************************************************
1593 Deletes a compilerstub from memory (simply by freeing it).
1595 *******************************************************************************/
1597 void removecompilerstub(u1 *stub)
1599 /* pass size 1 to keep the intern function happy */
1601 CFREE((void *) stub, 1);
1605 /* removenativestub ************************************************************
1607 Removes a previously created native-stub from memory.
1609 *******************************************************************************/
1611 void removenativestub(u1 *stub)
1613 /* pass size 1 to keep the intern function happy */
1615 CFREE((void *) stub, 1);
1619 /* codegen_reg_of_var **********************************************************
1621 This function determines a register, to which the result of an
1622 operation should go, when it is ultimatively intended to store the
1623 result in pseudoregister v. If v is assigned to an actual
1624 register, this register will be returned. Otherwise (when v is
1625 spilled) this function returns tempregnum. If not already done,
1626 regoff and flags are set in the stack location.
1628 *******************************************************************************/
1630 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
1634 /* Do we have to generate a conditional move? Yes, then always
1635 return the temporary register. The real register is identified
1636 during the store. */
1638 if (opcode & ICMD_CONDITION_MASK)
1642 if (!(v->flags & INMEMORY))
1643 return v->vv.regoff;
1649 /* codegen_reg_of_dst **********************************************************
1651 This function determines a register, to which the result of an
1652 operation should go, when it is ultimatively intended to store the
1653 result in iptr->dst.var. If dst.var is assigned to an actual
1654 register, this register will be returned. Otherwise (when it is
1655 spilled) this function returns tempregnum. If not already done,
1656 regoff and flags are set in the stack location.
1658 *******************************************************************************/
1660 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
1662 return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
1666 /* codegen_emit_phi_moves ****************************************************
1668 Emits phi moves at the end of the basicblock.
1670 *******************************************************************************/
1672 #if defined(ENABLE_SSA)
1673 void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
1686 /* Moves from phi functions with highest indices have to be */
1687 /* inserted first, since this is the order as is used for */
1688 /* conflict resolution */
1690 for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
1691 lt_d = ls->phi_moves[bptr->nr][i][0];
1692 lt_s = ls->phi_moves[bptr->nr][i][1];
1693 #if defined(SSA_DEBUG_VERBOSE)
1695 printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
1697 if (lt_s == UNUSED) {
1698 #if defined(SSA_DEBUG_VERBOSE)
1700 printf(" ... not processed \n");
1705 d = VAR(ls->lifetime[lt_d].v_index);
1706 s = VAR(ls->lifetime[lt_s].v_index);
1709 if (d->type == -1) {
1710 #if defined(SSA_DEBUG_VERBOSE)
1712 printf("...returning - phi lifetimes where joined\n");
1717 if (s->type == -1) {
1718 #if defined(SSA_DEBUG_VERBOSE)
1720 printf("...returning - phi lifetimes where joined\n");
1726 tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
1727 tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
1728 emit_copy(jd, &tmp_i);
1730 #if defined(SSA_DEBUG_VERBOSE)
1731 if (compileverbose) {
1732 if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
1734 printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1736 else if (IS_INMEMORY(s->flags)) {
1738 printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1740 else if (IS_INMEMORY(d->flags)) {
1742 printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1746 printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1750 #endif /* defined(SSA_DEBUG_VERBOSE) */
1753 #endif /* defined(ENABLE_SSA) */
1758 * These are local overrides for various environment variables in Emacs.
1759 * Please do not remove this and leave it at the end of the file, where
1760 * Emacs will automagically detect them.
1761 * ---------------------------------------------------------------------
1764 * indent-tabs-mode: t
1768 * vim:noexpandtab:sw=4:ts=4: