1 /* src/vm/jit/codegen-common.c - architecture independent code generator stuff
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 All functions assume the following code area / data area layout:
29 | code area | code area grows to higher addresses
31 +-----------+ <-- start of procedure
33 | data area | data area grows to lower addresses
37 The functions first write into a temporary code/data area allocated by
38 "codegen_init". "codegen_finish" copies the code and data area into permanent
39 memory. All functions writing values into the data area return the offset
40 relative the begin of the code area (start of procedure).
42 $Id: codegen-common.c 7918 2007-05-20 20:42:18Z michi $
54 #if defined(ENABLE_JIT)
55 /* this is required PATCHER_CALL_SIZE */
60 /* this is required for REG_SPLIT */
64 #include "mm/memory.h"
66 #include "toolbox/avl.h"
67 #include "toolbox/list.h"
68 #include "toolbox/logging.h"
70 #include "native/jni.h"
71 #include "native/native.h"
73 #include "threads/threads-common.h"
75 #include "vm/builtin.h"
76 #include "vm/exceptions.h"
77 #include "vm/stringlocal.h"
79 #include "vm/jit/abi.h"
80 #include "vm/jit/asmpart.h"
81 #include "vm/jit/codegen-common.h"
83 #if defined(ENABLE_DISASSEMBLER)
84 # include "vm/jit/disass.h"
87 #include "vm/jit/dseg.h"
88 #include "vm/jit/emit-common.h"
89 #include "vm/jit/jit.h"
90 #include "vm/jit/md.h"
91 #include "vm/jit/replace.h"
92 #if defined(ENABLE_SSA)
93 # include "vm/jit/optimizing/lsra.h"
94 # include "vm/jit/optimizing/ssa.h"
96 #include "vm/jit/stacktrace.h"
98 #if defined(ENABLE_INTRP)
99 #include "vm/jit/intrp/intrp.h"
102 #include "vmcore/method.h"
103 #include "vmcore/options.h"
105 # include "vmcore/statistics.h"
107 #if defined(ENABLE_VMLOG)
108 #include <vmlog_cacao.h>
112 /* in this tree we store all method addresses *********************************/
114 static avl_tree_t *methodtree = NULL;
115 static s4 methodtree_comparator(const void *treenode, const void *node);
118 /* codegen_init ****************************************************************
122 *******************************************************************************/
124 void codegen_init(void)
126 /* this tree is global, not method specific */
129 #if defined(ENABLE_JIT)
130 methodtree_element *mte;
133 methodtree = avl_create(&methodtree_comparator);
135 #if defined(ENABLE_JIT)
136 /* insert asm_vm_call_method */
138 mte = NEW(methodtree_element);
140 mte->startpc = (u1 *) (ptrint) asm_vm_call_method;
141 mte->endpc = (u1 *) (ptrint) asm_vm_call_method_end;
143 avl_insert(methodtree, mte);
144 #endif /* defined(ENABLE_JIT) */
149 /* codegen_setup ***************************************************************
151 Allocates and initialises code area, data area and references.
153 *******************************************************************************/
155 void codegen_setup(jitdata *jd)
160 /* get required compiler data */
165 /* initialize members */
169 cd->mcodebase = DMNEW(u1, MCODEINITSIZE);
170 cd->mcodeend = cd->mcodebase + MCODEINITSIZE;
171 cd->mcodesize = MCODEINITSIZE;
173 /* initialize mcode variables */
175 cd->mcodeptr = cd->mcodebase;
176 cd->lastmcodeptr = cd->mcodebase;
178 #if defined(ENABLE_INTRP)
179 /* native dynamic superinstructions variables */
182 cd->ncodebase = DMNEW(u1, NCODEINITSIZE);
183 cd->ncodesize = NCODEINITSIZE;
185 /* initialize ncode variables */
187 cd->ncodeptr = cd->ncodebase;
189 cd->lastinstwithoutdispatch = ~0; /* no inst without dispatch */
190 cd->superstarts = NULL;
197 cd->jumpreferences = NULL;
199 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
200 cd->datareferences = NULL;
203 /* cd->patchrefs = list_create_dump(OFFSET(patchref, linkage)); */
204 cd->patchrefs = NULL;
205 cd->brancheslabel = list_create_dump(OFFSET(branch_label_ref_t, linkage));
206 cd->listcritical = list_create_dump(OFFSET(critical_section_ref_t, linkage));
208 cd->linenumberreferences = NULL;
209 cd->linenumbertablesizepos = 0;
210 cd->linenumbertablestartpos = 0;
211 cd->linenumbertab = 0;
215 /* codegen_reset ***************************************************************
217 Resets the codegen data structure so we can recompile the method.
219 *******************************************************************************/
221 static void codegen_reset(jitdata *jd)
227 /* get required compiler data */
232 /* reset error flag */
234 cd->flags &= ~CODEGENDATA_FLAG_ERROR;
236 /* reset some members, we reuse the code memory already allocated
237 as this should have almost the correct size */
239 cd->mcodeptr = cd->mcodebase;
240 cd->lastmcodeptr = cd->mcodebase;
245 cd->jumpreferences = NULL;
247 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
248 cd->datareferences = NULL;
251 /* cd->patchrefs = list_create_dump(OFFSET(patchref, linkage)); */
252 cd->patchrefs = NULL;
253 cd->brancheslabel = list_create_dump(OFFSET(branch_label_ref_t, linkage));
254 cd->listcritical = list_create_dump(OFFSET(critical_section_ref_t, linkage));
256 cd->linenumberreferences = NULL;
257 cd->linenumbertablesizepos = 0;
258 cd->linenumbertablestartpos = 0;
259 cd->linenumbertab = 0;
261 /* We need to clear the mpc and the branch references from all
262 basic blocks as they will definitely change. */
264 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
266 bptr->branchrefs = NULL;
269 #if defined(ENABLE_REPLACEMENT)
270 code->rplpoints = NULL;
271 code->rplpointcount = 0;
272 code->regalloc = NULL;
273 code->regalloccount = 0;
274 code->globalcount = 0;
279 /* codegen_generate ************************************************************
281 Generates the code for the currently compiled method.
283 *******************************************************************************/
285 bool codegen_generate(jitdata *jd)
289 /* get required compiler data */
293 /* call the machine-dependent code generation function */
295 if (!codegen_emit(jd))
298 /* check for an error */
300 if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
301 /* check for long-branches flag, if it is set we recompile the
306 log_message_method("Re-generating code: ", jd->m);
309 /* XXX maybe we should tag long-branches-methods for recompilation */
311 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
312 /* we have to reset the codegendata structure first */
316 /* and restart the compiler run */
318 if (!codegen_emit(jd))
322 vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
327 log_message_method("Re-generating code done: ", jd->m);
331 /* reallocate the memory and finish the code generation */
335 /* everything's ok */
341 /* codegen_close ***************************************************************
345 *******************************************************************************/
347 void codegen_close(void)
349 /* TODO: release avl tree on i386 and x86_64 */
353 /* codegen_increase ************************************************************
357 *******************************************************************************/
359 void codegen_increase(codegendata *cd)
363 /* save old mcodebase pointer */
365 oldmcodebase = cd->mcodebase;
367 /* reallocate to new, doubled memory */
369 cd->mcodebase = DMREALLOC(cd->mcodebase,
374 cd->mcodeend = cd->mcodebase + cd->mcodesize;
376 /* set new mcodeptr */
378 cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
380 #if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(ENABLE_INTRP)
381 /* adjust the pointer to the last patcher position */
383 if (cd->lastmcodeptr != NULL)
384 cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
389 /* codegen_ncode_increase ******************************************************
393 *******************************************************************************/
395 #if defined(ENABLE_INTRP)
396 u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
400 /* save old ncodebase pointer */
402 oldncodebase = cd->ncodebase;
404 /* reallocate to new, doubled memory */
406 cd->ncodebase = DMREALLOC(cd->ncodebase,
412 /* return the new ncodeptr */
414 return (cd->ncodebase + (ncodeptr - oldncodebase));
419 /* codegen_add_branch_ref ******************************************************
421 Prepends an branch to the list.
423 *******************************************************************************/
425 void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
430 STATISTICS(count_branches_unresolved++);
432 /* calculate the mpc of the branch instruction */
434 branchmpc = cd->mcodeptr - cd->mcodebase;
436 br = DNEW(branchref);
438 br->branchmpc = branchmpc;
439 br->condition = condition;
441 br->options = options;
442 br->next = target->branchrefs;
444 target->branchrefs = br;
448 /* codegen_resolve_branchrefs **************************************************
450 Resolves and patches the branch references of a given basic block.
452 *******************************************************************************/
454 void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
459 /* Save the mcodeptr because in the branch emitting functions
460 we generate code somewhere inside already generated code,
461 but we're still in the actual code generation phase. */
463 mcodeptr = cd->mcodeptr;
465 /* just to make sure */
467 assert(bptr->mpc >= 0);
469 for (br = bptr->branchrefs; br != NULL; br = br->next) {
470 /* temporary set the mcodeptr */
472 cd->mcodeptr = cd->mcodebase + br->branchmpc;
474 /* emit_bccz and emit_branch emit the correct code, even if we
475 pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
477 emit_bccz(cd, bptr, br->condition, br->reg, br->options);
480 /* restore mcodeptr */
482 cd->mcodeptr = mcodeptr;
486 /* codegen_branch_label_add ****************************************************
488 Append an branch to the label-branch list.
490 *******************************************************************************/
492 void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
495 branch_label_ref_t *br;
498 /* get the label list */
500 list = cd->brancheslabel;
502 /* calculate the current mpc */
504 mpc = cd->mcodeptr - cd->mcodebase;
506 br = DNEW(branch_label_ref_t);
510 br->condition = condition;
512 br->options = options;
514 /* add the branch to the list */
516 list_add_last_unsynced(list, br);
520 /* codegen_add_patch_ref *******************************************************
522 Appends a new patcher reference to the list of patching positions.
524 *******************************************************************************/
526 void codegen_add_patch_ref(codegendata *cd, functionptr patcher, voidptr ref,
532 branchmpc = cd->mcodeptr - cd->mcodebase;
536 pr->branchpos = branchmpc;
538 pr->patcher = patcher;
541 /* list_add_first(cd->patchrefs, pr); */
542 pr->next = cd->patchrefs;
545 /* Generate NOPs for opt_shownops. */
550 #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__MIPS__) || defined(__X86_64__))
551 /* On some architectures the patcher stub call instruction might
552 be longer than the actual instruction generated. On this
553 architectures we store the last patcher call position and after
554 the basic block code generation is completed, we check the
555 range and maybe generate some nop's. */
557 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
562 /* codegen_critical_section_new ************************************************
564 Allocates a new critical-section reference and adds it to the
565 critical-section list.
567 *******************************************************************************/
569 #if defined(ENABLE_THREADS)
570 void codegen_critical_section_new(codegendata *cd)
573 critical_section_ref_t *csr;
576 /* get the critical section list */
578 list = cd->listcritical;
580 /* calculate the current mpc */
582 mpc = cd->mcodeptr - cd->mcodebase;
584 csr = DNEW(critical_section_ref_t);
586 /* We only can set restart right now, as start and end are set by
587 the following, corresponding functions. */
593 /* add the branch to the list */
595 list_add_last_unsynced(list, csr);
600 /* codegen_critical_section_start **********************************************
602 Set the start-point of the current critical section (which is the
603 last element of the list).
605 *******************************************************************************/
607 #if defined(ENABLE_THREADS)
608 void codegen_critical_section_start(codegendata *cd)
611 critical_section_ref_t *csr;
614 /* get the critical section list */
616 list = cd->listcritical;
618 /* calculate the current mpc */
620 mpc = cd->mcodeptr - cd->mcodebase;
622 /* get the current critical section */
624 csr = list_last_unsynced(list);
626 /* set the start point */
628 assert(csr->start == -1);
635 /* codegen_critical_section_end ************************************************
637 Set the end-point of the current critical section (which is the
638 last element of the list).
640 *******************************************************************************/
642 #if defined(ENABLE_THREADS)
643 void codegen_critical_section_end(codegendata *cd)
646 critical_section_ref_t *csr;
649 /* get the critical section list */
651 list = cd->listcritical;
653 /* calculate the current mpc */
655 mpc = cd->mcodeptr - cd->mcodebase;
657 /* get the current critical section */
659 csr = list_last_unsynced(list);
661 /* set the end point */
663 assert(csr->end == -1);
670 /* codegen_critical_section_finish *********************************************
672 Finish the critical sections, create the critical section nodes for
673 the AVL tree and insert them into the tree.
675 *******************************************************************************/
677 #if defined(ENABLE_THREADS)
678 static void codegen_critical_section_finish(jitdata *jd)
683 critical_section_ref_t *csr;
684 critical_section_node_t *csn;
686 /* get required compiler data */
691 /* get the critical section list */
693 list = cd->listcritical;
695 /* iterate over all critical sections */
697 for (csr = list_first_unsynced(list); csr != NULL;
698 csr = list_next_unsynced(list, csr)) {
699 /* check if all points are set */
701 assert(csr->start != -1);
702 assert(csr->end != -1);
703 assert(csr->restart != -1);
705 /* allocate tree node */
707 csn = NEW(critical_section_node_t);
709 csn->start = code->entrypoint + csr->start;
710 csn->end = code->entrypoint + csr->end;
711 csn->restart = code->entrypoint + csr->restart;
713 /* insert into the tree */
715 critical_section_register(csn);
721 /* methodtree_comparator *******************************************************
723 Comparator function used for the AVL tree of methods.
726 treenode....the node from the tree
727 node........the node to compare to the tree-node
729 *******************************************************************************/
731 static s4 methodtree_comparator(const void *treenode, const void *node)
733 methodtree_element *mte;
734 methodtree_element *mtepc;
736 mte = (methodtree_element *) treenode;
737 mtepc = (methodtree_element *) node;
739 /* compare both startpc and endpc of pc, even if they have the same value,
740 otherwise the avl_probe sometimes thinks the element is already in the
744 /* On S390 addresses are 31 bit. Compare only 31 bits of value.
746 # define ADDR_MASK(a) ((a) & 0x7FFFFFFF)
748 # define ADDR_MASK(a) (a)
751 if (ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->startpc) &&
752 ADDR_MASK((long) mtepc->startpc) <= ADDR_MASK((long) mte->endpc) &&
753 ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->endpc) &&
754 ADDR_MASK((long) mtepc->endpc) <= ADDR_MASK((long) mte->endpc)) {
757 } else if (ADDR_MASK((long) mtepc->startpc) < ADDR_MASK((long) mte->startpc)) {
768 /* codegen_insertmethod ********************************************************
770 Insert the machine code range of a method into the AVL tree of methods.
772 *******************************************************************************/
774 void codegen_insertmethod(u1 *startpc, u1 *endpc)
776 methodtree_element *mte;
778 /* allocate new method entry */
780 mte = NEW(methodtree_element);
782 mte->startpc = startpc;
785 /* this function does not return an error, but asserts for
788 avl_insert(methodtree, mte);
792 /* codegen_get_pv_from_pc ******************************************************
794 Find the PV for the given PC by searching in the AVL tree of
797 *******************************************************************************/
799 u1 *codegen_get_pv_from_pc(u1 *pc)
801 methodtree_element mtepc;
802 methodtree_element *mte;
804 /* allocation of the search structure on the stack is much faster */
809 mte = avl_find(methodtree, &mtepc);
812 /* No method was found. Let's dump a stacktrace. */
814 #if defined(ENABLE_VMLOG)
815 vmlog_cacao_signl("SIGSEGV");
818 log_println("We received a SIGSEGV and tried to handle it, but we were");
819 log_println("unable to find a Java method at:");
821 #if SIZEOF_VOID_P == 8
822 log_println("PC=0x%016lx", pc);
824 log_println("PC=0x%08x", pc);
827 log_println("Dumping the current stacktrace:");
829 #if defined(ENABLE_THREADS)
830 /* XXX michi: This should be available even without threads! */
831 threads_print_stacktrace();
834 vm_abort("Exiting...");
841 /* codegen_get_pv_from_pc_nocheck **********************************************
843 Find the PV for the given PC by searching in the AVL tree of
844 methods. This method does not check the return value and is used
847 *******************************************************************************/
849 u1 *codegen_get_pv_from_pc_nocheck(u1 *pc)
851 methodtree_element mtepc;
852 methodtree_element *mte;
854 /* allocation of the search structure on the stack is much faster */
859 mte = avl_find(methodtree, &mtepc);
868 /* codegen_set_replacement_point_notrap ****************************************
870 Record the position of a non-trappable replacement point.
872 *******************************************************************************/
874 #if defined(ENABLE_REPLACEMENT)
876 void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
878 void codegen_set_replacement_point_notrap(codegendata *cd)
881 assert(cd->replacementpoint);
882 assert(cd->replacementpoint->type == type);
883 assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
885 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
887 cd->replacementpoint++;
889 #endif /* defined(ENABLE_REPLACEMENT) */
892 /* codegen_set_replacement_point ***********************************************
894 Record the position of a trappable replacement point.
896 *******************************************************************************/
898 #if defined(ENABLE_REPLACEMENT)
900 void codegen_set_replacement_point(codegendata *cd, s4 type)
902 void codegen_set_replacement_point(codegendata *cd)
905 assert(cd->replacementpoint);
906 assert(cd->replacementpoint->type == type);
907 assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
909 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
911 cd->replacementpoint++;
913 /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
915 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
917 #endif /* defined(ENABLE_REPLACEMENT) */
920 /* codegen_finish **************************************************************
922 Finishes the code generation. A new memory, large enough for both
923 data and code, is allocated and data and code are copied together
924 to their final layout, unresolved jumps are resolved, ...
926 *******************************************************************************/
928 void codegen_finish(jitdata *jd)
933 #if defined(ENABLE_INTRP)
941 /* get required compiler data */
946 /* prevent compiler warning */
948 #if defined(ENABLE_INTRP)
952 /* calculate the code length */
954 mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
956 #if defined(ENABLE_STATISTICS)
958 count_code_len += mcodelen;
959 count_data_len += cd->dseglen;
963 alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
965 #if defined(ENABLE_INTRP)
967 ncodelen = cd->ncodeptr - cd->ncodebase;
969 ncodelen = 0; /* avoid compiler warning */
973 cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
974 alignedlen = alignedmcodelen + cd->dseglen;
976 #if defined(ENABLE_INTRP)
978 alignedlen += ncodelen;
982 /* allocate new memory */
984 code->mcodelength = mcodelen + cd->dseglen;
985 code->mcode = CNEW(u1, alignedlen);
987 /* set the entrypoint of the method */
989 assert(code->entrypoint == NULL);
990 code->entrypoint = epoint = (code->mcode + cd->dseglen);
992 /* fill the data segment (code->entrypoint must already be set!) */
996 /* copy code to the new location */
998 MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
1000 #if defined(ENABLE_INTRP)
1001 /* relocate native dynamic superinstruction code (if any) */
1004 cd->mcodebase = code->entrypoint;
1007 u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
1009 MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
1011 /* flush the instruction and data caches */
1013 md_cacheflush(ncodebase, ncodelen);
1015 /* set some cd variables for dynamic_super_rerwite */
1017 cd->ncodebase = ncodebase;
1020 cd->ncodebase = NULL;
1023 dynamic_super_rewrite(cd);
1027 /* jump table resolving */
1029 for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
1030 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
1031 (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
1033 /* line number table resolving */
1039 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
1041 target = lr->targetmpc;
1042 /* if the entry contains an mcode pointer (normal case), resolve it */
1043 /* (see doc/inlining_stacktrace.txt for details) */
1044 if (lr->linenumber >= -2) {
1045 target += (ptrint) epoint;
1047 *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) =
1048 (functionptr) target;
1051 *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
1052 (functionptr) ((ptrint) epoint + cd->linenumbertab);
1054 *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
1057 #if defined(ENABLE_REPLACEMENT)
1058 /* replacement point resolving */
1063 code->replacementstubs += (ptrint) epoint;
1065 rp = code->rplpoints;
1066 for (i=0; i<code->rplpointcount; ++i, ++rp) {
1067 rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
1070 #endif /* defined(ENABLE_REPLACEMENT) */
1072 /* add method into methodtree to find the entrypoint */
1074 codegen_insertmethod(code->entrypoint, code->entrypoint + mcodelen);
1076 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
1077 /* resolve data segment references */
1079 dseg_resolve_datareferences(jd);
1082 #if defined(ENABLE_THREADS)
1083 /* create cirtical sections */
1085 codegen_critical_section_finish(jd);
1088 /* flush the instruction and data caches */
1090 md_cacheflush(code->mcode, code->mcodelength);
1094 /* codegen_generate_stub_compiler **********************************************
1096 Wrapper for codegen_emit_stub_compiler.
1099 pointer to the compiler stub code.
1101 *******************************************************************************/
1103 u1 *codegen_generate_stub_compiler(methodinfo *m)
1107 ptrint *d; /* pointer to data memory */
1108 u1 *c; /* pointer to code memory */
1111 /* mark dump memory */
1113 dumpsize = dump_size();
1115 /* allocate required data structures */
1120 jd->cd = DNEW(codegendata);
1123 /* get required compiler data */
1127 /* allocate code memory */
1129 c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1131 /* set pointers correctly */
1137 c = c + 3 * SIZEOF_VOID_P;
1140 /* NOTE: The codeinfo pointer is actually a pointer to the
1141 methodinfo (this fakes a codeinfo structure). */
1143 d[0] = (ptrint) asm_call_jit_compiler;
1145 d[2] = (ptrint) &d[1]; /* fake code->m */
1147 /* call the emit function */
1149 codegen_emit_stub_compiler(jd);
1151 #if defined(ENABLE_STATISTICS)
1153 count_cstub_len += 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
1158 md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1160 /* release dump memory */
1162 dump_release(dumpsize);
1164 /* return native stub code */
1170 /* codegen_generate_stub_builtin ***********************************************
1172 Wrapper for codegen_emit_stub_builtin.
1175 Pointer to the entrypoint of the stub.
1177 *******************************************************************************/
1179 void codegen_generate_stub_builtin(builtintable_entry *bte)
1185 /* mark dump memory */
1187 dumpsize = dump_size();
1192 jd->cd = DNEW(codegendata);
1196 /* Allocate codeinfo memory from the heap as we need to keep them. */
1198 jd->code = code_codeinfo_new(NULL);
1200 /* get required compiler data */
1204 /* setup code generation stuff */
1208 /* generate the code */
1210 #if defined(ENABLE_JIT)
1211 # if defined(ENABLE_INTRP)
1214 codegen_emit_stub_builtin(jd, bte);
1217 /* reallocate the memory and finish the code generation */
1221 /* set the stub entry point in the builtin table */
1223 bte->stub = code->entrypoint;
1225 #if defined(ENABLE_STATISTICS)
1227 size_stub_native += code->mcodelength;
1230 /* release memory */
1232 dump_release(dumpsize);
1236 /* codegen_generate_stub_native ************************************************
1238 Wrapper for codegen_emit_stub_native.
1241 the codeinfo representing the stub code.
1243 *******************************************************************************/
1245 codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
1254 /* mark dump memory */
1256 dumpsize = dump_size();
1261 jd->cd = DNEW(codegendata);
1262 jd->rd = DNEW(registerdata);
1265 /* Allocate codeinfo memory from the heap as we need to keep them. */
1267 jd->code = code_codeinfo_new(m); /* XXX check allocation */
1269 /* get required compiler data */
1273 /* set the flags for the current JIT run */
1275 #if defined(ENABLE_PROFILING)
1277 jd->flags |= JITDATA_FLAG_INSTRUMENT;
1280 if (opt_verbosecall)
1281 jd->flags |= JITDATA_FLAG_VERBOSECALL;
1283 /* setup code generation stuff */
1285 #if defined(ENABLE_JIT)
1286 # if defined(ENABLE_INTRP)
1294 /* create new method descriptor with additional native parameters */
1297 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
1299 nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
1300 md->paramcount * sizeof(typedesc) +
1301 nativeparams * sizeof(typedesc));
1303 nmd->paramcount = md->paramcount + nativeparams;
1305 nmd->params = DMNEW(paramdesc, nmd->paramcount);
1307 nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer */
1309 if (m->flags & ACC_STATIC)
1310 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer */
1312 MCOPY(nmd->paramtypes + nativeparams, md->paramtypes, typedesc,
1315 #if defined(ENABLE_JIT)
1316 # if defined(ENABLE_INTRP)
1319 /* pre-allocate the arguments for the native ABI */
1321 md_param_alloc_native(nmd);
1324 /* generate the code */
1326 #if defined(ENABLE_JIT)
1327 # if defined(ENABLE_INTRP)
1329 intrp_createnativestub(f, jd, nmd);
1332 codegen_emit_stub_native(jd, nmd, f);
1334 intrp_createnativestub(f, jd, nmd);
1337 /* reallocate the memory and finish the code generation */
1341 #if defined(ENABLE_STATISTICS)
1342 /* must be done after codegen_finish() */
1345 size_stub_native += code->mcodelength;
1348 #if !defined(NDEBUG)
1349 /* disassemble native stub */
1351 if (opt_shownativestub) {
1352 #if defined(ENABLE_DISASSEMBLER)
1353 codegen_disassemble_nativestub(m,
1354 (u1 *) (ptrint) code->entrypoint,
1355 (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
1358 /* show data segment */
1360 if (opt_showddatasegment)
1363 #endif /* !defined(NDEBUG) */
1365 /* release memory */
1367 dump_release(dumpsize);
1369 /* return native stub code */
1375 /* codegen_disassemble_nativestub **********************************************
1377 Disassembles the generated native stub.
1379 *******************************************************************************/
1381 #if defined(ENABLE_DISASSEMBLER)
1382 void codegen_disassemble_nativestub(methodinfo *m, u1 *start, u1 *end)
1384 printf("Native stub: ");
1385 utf_fprint_printable_ascii_classname(stdout, m->class->name);
1387 utf_fprint_printable_ascii(stdout, m->name);
1388 utf_fprint_printable_ascii(stdout, m->descriptor);
1389 printf("\n\nLength: %d\n\n", (s4) (end - start));
1391 DISASSEMBLE(start, end);
1396 /* codegen_stub_builtin_enter **************************************************
1398 Prepares the stuff required for a builtin function call:
1400 - adds a stackframe info structure to the chain, for stacktraces
1402 The layout of the builtin stub stackframe should look like this:
1404 +---------------------------+ <- SP (of parent Java function)
1406 +---------------------------+
1408 | stackframe info structure |
1410 +---------------------------+
1412 | arguments (if any) |
1414 +---------------------------+ <- SP (native stub)
1416 *******************************************************************************/
1418 void codegen_stub_builtin_enter(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
1420 stackframeinfo *sfi;
1422 /* get data structures from stack */
1424 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1426 /* add a stackframeinfo to the chain */
1428 stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
1430 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1431 /* set the native world flag */
1433 THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE;
1438 /* codegen_stub_builtin_exit ***************************************************
1440 Removes the stuff required for a builtin function call.
1442 *******************************************************************************/
1444 void codegen_stub_builtin_exit(u1 *datasp)
1446 stackframeinfo *sfi;
1447 stackframeinfo **psfi;
1449 /* get data structures from stack */
1451 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1453 /* remove current stackframeinfo from chain */
1455 psfi = &STACKFRAMEINFO;
1459 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1460 /* clear the native world flag */
1462 THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE;
1467 /* codegen_start_native_call ***************************************************
1469 Prepares the stuff required for a native (JNI) function call:
1471 - adds a stackframe info structure to the chain, for stacktraces
1472 - prepares the local references table on the stack
1474 The layout of the native stub stackframe should look like this:
1476 +---------------------------+ <- SP (of parent Java function)
1478 +---------------------------+
1480 | stackframe info structure |
1482 +---------------------------+
1484 | local references table |
1486 +---------------------------+
1488 | arguments (if any) |
1490 +---------------------------+ <- SP (native stub)
1492 *******************************************************************************/
1494 void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
1496 stackframeinfo *sfi;
1497 localref_table *lrt;
1499 /* get data structures from stack */
1501 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1502 lrt = (localref_table *) (datasp - sizeof(stackframeinfo) -
1503 sizeof(localref_table));
1505 /* add a stackframeinfo to the chain */
1507 stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
1509 #if defined(ENABLE_JNI)
1510 /* add current JNI local references table to this thread */
1512 lrt->capacity = LOCALREFTABLE_CAPACITY;
1514 lrt->localframes = 1;
1515 lrt->prev = LOCALREFTABLE;
1517 /* clear the references array (memset is faster the a for-loop) */
1519 MSET(lrt->refs, 0, java_objectheader*, LOCALREFTABLE_CAPACITY);
1521 LOCALREFTABLE = lrt;
1524 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1525 /* set the native world flag */
1527 THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE;
1532 /* codegen_finish_native_call **************************************************
1534 Removes the stuff required for a native (JNI) function call.
1535 Additionally it checks for an exceptions and in case, get the
1536 exception object and clear the pointer.
1538 *******************************************************************************/
1540 java_objectheader *codegen_finish_native_call(u1 *datasp)
1542 stackframeinfo *sfi;
1543 stackframeinfo **psfi;
1544 #if defined(ENABLE_JNI)
1545 localref_table *lrt;
1546 localref_table *plrt;
1549 java_objectheader *e;
1551 /* get data structures from stack */
1553 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1555 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1556 /* clear the native world flag */
1558 THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE;
1561 /* remove current stackframeinfo from chain */
1563 psfi = &STACKFRAMEINFO;
1567 #if defined(ENABLE_JNI)
1568 /* release JNI local references tables for this thread */
1570 lrt = LOCALREFTABLE;
1572 /* release all current local frames */
1574 for (localframes = lrt->localframes; localframes >= 1; localframes--) {
1575 /* get previous frame */
1579 /* Clear all reference entries (only for tables allocated on
1582 if (localframes > 1)
1583 MSET(&lrt->refs[0], 0, java_objectheader*, lrt->capacity);
1587 /* set new local references table */
1592 /* now store the previous local frames in the thread structure */
1594 LOCALREFTABLE = lrt;
1597 /* get the exception and return it */
1599 e = exceptions_get_and_clear_exception();
1605 /* removecompilerstub **********************************************************
1607 Deletes a compilerstub from memory (simply by freeing it).
1609 *******************************************************************************/
1611 void removecompilerstub(u1 *stub)
1613 /* pass size 1 to keep the intern function happy */
1615 CFREE((void *) stub, 1);
1619 /* removenativestub ************************************************************
1621 Removes a previously created native-stub from memory.
1623 *******************************************************************************/
1625 void removenativestub(u1 *stub)
1627 /* pass size 1 to keep the intern function happy */
1629 CFREE((void *) stub, 1);
1633 /* codegen_reg_of_var **********************************************************
1635 This function determines a register, to which the result of an
1636 operation should go, when it is ultimatively intended to store the
1637 result in pseudoregister v. If v is assigned to an actual
1638 register, this register will be returned. Otherwise (when v is
1639 spilled) this function returns tempregnum. If not already done,
1640 regoff and flags are set in the stack location.
1642 On ARM we have to check if a long/double variable is splitted
1643 across reg/stack (HIGH_REG == REG_SPLIT). We return the actual
1644 register of v for LOW_REG and the tempregnum for HIGH_REG in such
1645 cases. (michi 2005/07/24)
1647 *******************************************************************************/
1649 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
1653 /* Do we have to generate a conditional move? Yes, then always
1654 return the temporary register. The real register is identified
1655 during the store. */
1657 if (opcode & ICMD_CONDITION_MASK)
1661 if (!(v->flags & INMEMORY)) {
1662 #if defined(__ARM__) && defined(__ARMEL__)
1663 if (IS_2_WORD_TYPE(v->type) && (GET_HIGH_REG(v->vv.regoff) == REG_SPLIT))
1664 return PACK_REGS(GET_LOW_REG(v->vv.regoff),
1665 GET_HIGH_REG(tempregnum));
1667 #if defined(__ARM__) && defined(__ARMEB__)
1668 if (IS_2_WORD_TYPE(v->type) && (GET_LOW_REG(v->vv.regoff) == REG_SPLIT))
1669 return PACK_REGS(GET_LOW_REG(tempregnum),
1670 GET_HIGH_REG(v->vv.regoff));
1672 return v->vv.regoff;
1675 #if defined(ENABLE_STATISTICS)
1677 count_spills_read++;
1683 /* codegen_reg_of_dst **********************************************************
1685 This function determines a register, to which the result of an
1686 operation should go, when it is ultimatively intended to store the
1687 result in iptr->dst.var. If dst.var is assigned to an actual
1688 register, this register will be returned. Otherwise (when it is
1689 spilled) this function returns tempregnum. If not already done,
1690 regoff and flags are set in the stack location.
1692 On ARM we have to check if a long/double variable is splitted
1693 across reg/stack (HIGH_REG == REG_SPLIT). We return the actual
1694 register of dst.var for LOW_REG and the tempregnum for HIGH_REG in such
1695 cases. (michi 2005/07/24)
1697 *******************************************************************************/
1699 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
1701 return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
1705 /* codegen_emit_phi_moves ****************************************************
1707 Emits phi moves at the end of the basicblock.
1709 *******************************************************************************/
1711 #if defined(ENABLE_SSA)
1712 void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
1725 /* Moves from phi functions with highest indices have to be */
1726 /* inserted first, since this is the order as is used for */
1727 /* conflict resolution */
1729 for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
1730 lt_d = ls->phi_moves[bptr->nr][i][0];
1731 lt_s = ls->phi_moves[bptr->nr][i][1];
1732 #if defined(SSA_DEBUG_VERBOSE)
1734 printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
1736 if (lt_s == UNUSED) {
1737 #if defined(SSA_DEBUG_VERBOSE)
1739 printf(" ... not processed \n");
1744 d = VAR(ls->lifetime[lt_d].v_index);
1745 s = VAR(ls->lifetime[lt_s].v_index);
1748 if (d->type == -1) {
1749 #if defined(SSA_DEBUG_VERBOSE)
1751 printf("...returning - phi lifetimes where joined\n");
1756 if (s->type == -1) {
1757 #if defined(SSA_DEBUG_VERBOSE)
1759 printf("...returning - phi lifetimes where joined\n");
1765 tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
1766 tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
1767 emit_copy(jd, &tmp_i);
1769 #if defined(SSA_DEBUG_VERBOSE)
1770 if (compileverbose) {
1771 if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
1773 printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1775 else if (IS_INMEMORY(s->flags)) {
1777 printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1779 else if (IS_INMEMORY(d->flags)) {
1781 printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1785 printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1789 #endif /* defined(SSA_DEBUG_VERBOSE) */
1792 #endif /* defined(ENABLE_SSA) */
1797 * These are local overrides for various environment variables in Emacs.
1798 * Please do not remove this and leave it at the end of the file, where
1799 * Emacs will automagically detect them.
1800 * ---------------------------------------------------------------------
1803 * indent-tabs-mode: t
1807 * vim:noexpandtab:sw=4:ts=4: