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 7940 2007-05-23 09:42:08Z 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(__M68K__) || 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__) || defined(__M68K__))
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. */
556 /* The nops are generated in codegen_emit in each codegen */
558 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
563 /* codegen_critical_section_new ************************************************
565 Allocates a new critical-section reference and adds it to the
566 critical-section list.
568 *******************************************************************************/
570 #if defined(ENABLE_THREADS)
571 void codegen_critical_section_new(codegendata *cd)
574 critical_section_ref_t *csr;
577 /* get the critical section list */
579 list = cd->listcritical;
581 /* calculate the current mpc */
583 mpc = cd->mcodeptr - cd->mcodebase;
585 csr = DNEW(critical_section_ref_t);
587 /* We only can set restart right now, as start and end are set by
588 the following, corresponding functions. */
594 /* add the branch to the list */
596 list_add_last_unsynced(list, csr);
601 /* codegen_critical_section_start **********************************************
603 Set the start-point of the current critical section (which is the
604 last element of the list).
606 *******************************************************************************/
608 #if defined(ENABLE_THREADS)
609 void codegen_critical_section_start(codegendata *cd)
612 critical_section_ref_t *csr;
615 /* get the critical section list */
617 list = cd->listcritical;
619 /* calculate the current mpc */
621 mpc = cd->mcodeptr - cd->mcodebase;
623 /* get the current critical section */
625 csr = list_last_unsynced(list);
627 /* set the start point */
629 assert(csr->start == -1);
636 /* codegen_critical_section_end ************************************************
638 Set the end-point of the current critical section (which is the
639 last element of the list).
641 *******************************************************************************/
643 #if defined(ENABLE_THREADS)
644 void codegen_critical_section_end(codegendata *cd)
647 critical_section_ref_t *csr;
650 /* get the critical section list */
652 list = cd->listcritical;
654 /* calculate the current mpc */
656 mpc = cd->mcodeptr - cd->mcodebase;
658 /* get the current critical section */
660 csr = list_last_unsynced(list);
662 /* set the end point */
664 assert(csr->end == -1);
671 /* codegen_critical_section_finish *********************************************
673 Finish the critical sections, create the critical section nodes for
674 the AVL tree and insert them into the tree.
676 *******************************************************************************/
678 #if defined(ENABLE_THREADS)
679 static void codegen_critical_section_finish(jitdata *jd)
684 critical_section_ref_t *csr;
685 critical_section_node_t *csn;
687 /* get required compiler data */
692 /* get the critical section list */
694 list = cd->listcritical;
696 /* iterate over all critical sections */
698 for (csr = list_first_unsynced(list); csr != NULL;
699 csr = list_next_unsynced(list, csr)) {
700 /* check if all points are set */
702 assert(csr->start != -1);
703 assert(csr->end != -1);
704 assert(csr->restart != -1);
706 /* allocate tree node */
708 csn = NEW(critical_section_node_t);
710 csn->start = code->entrypoint + csr->start;
711 csn->end = code->entrypoint + csr->end;
712 csn->restart = code->entrypoint + csr->restart;
714 /* insert into the tree */
716 critical_section_register(csn);
722 /* methodtree_comparator *******************************************************
724 Comparator function used for the AVL tree of methods.
727 treenode....the node from the tree
728 node........the node to compare to the tree-node
730 *******************************************************************************/
732 static s4 methodtree_comparator(const void *treenode, const void *node)
734 methodtree_element *mte;
735 methodtree_element *mtepc;
737 mte = (methodtree_element *) treenode;
738 mtepc = (methodtree_element *) node;
740 /* compare both startpc and endpc of pc, even if they have the same value,
741 otherwise the avl_probe sometimes thinks the element is already in the
745 /* On S390 addresses are 31 bit. Compare only 31 bits of value.
747 # define ADDR_MASK(a) ((a) & 0x7FFFFFFF)
749 # define ADDR_MASK(a) (a)
752 if (ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->startpc) &&
753 ADDR_MASK((long) mtepc->startpc) <= ADDR_MASK((long) mte->endpc) &&
754 ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->endpc) &&
755 ADDR_MASK((long) mtepc->endpc) <= ADDR_MASK((long) mte->endpc)) {
758 } else if (ADDR_MASK((long) mtepc->startpc) < ADDR_MASK((long) mte->startpc)) {
769 /* codegen_insertmethod ********************************************************
771 Insert the machine code range of a method into the AVL tree of methods.
773 *******************************************************************************/
775 void codegen_insertmethod(u1 *startpc, u1 *endpc)
777 methodtree_element *mte;
779 /* allocate new method entry */
781 mte = NEW(methodtree_element);
783 mte->startpc = startpc;
786 /* this function does not return an error, but asserts for
789 avl_insert(methodtree, mte);
793 /* codegen_get_pv_from_pc ******************************************************
795 Find the PV for the given PC by searching in the AVL tree of
798 *******************************************************************************/
800 u1 *codegen_get_pv_from_pc(u1 *pc)
802 methodtree_element mtepc;
803 methodtree_element *mte;
805 /* allocation of the search structure on the stack is much faster */
810 mte = avl_find(methodtree, &mtepc);
813 /* No method was found. Let's dump a stacktrace. */
815 #if defined(ENABLE_VMLOG)
816 vmlog_cacao_signl("SIGSEGV");
819 log_println("We received a SIGSEGV and tried to handle it, but we were");
820 log_println("unable to find a Java method at:");
822 #if SIZEOF_VOID_P == 8
823 log_println("PC=0x%016lx", pc);
825 log_println("PC=0x%08x", pc);
828 log_println("Dumping the current stacktrace:");
830 #if defined(ENABLE_THREADS)
831 /* XXX michi: This should be available even without threads! */
832 threads_print_stacktrace();
835 vm_abort("Exiting...");
842 /* codegen_get_pv_from_pc_nocheck **********************************************
844 Find the PV for the given PC by searching in the AVL tree of
845 methods. This method does not check the return value and is used
848 *******************************************************************************/
850 u1 *codegen_get_pv_from_pc_nocheck(u1 *pc)
852 methodtree_element mtepc;
853 methodtree_element *mte;
855 /* allocation of the search structure on the stack is much faster */
860 mte = avl_find(methodtree, &mtepc);
869 /* codegen_set_replacement_point_notrap ****************************************
871 Record the position of a non-trappable replacement point.
873 *******************************************************************************/
875 #if defined(ENABLE_REPLACEMENT)
877 void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
879 void codegen_set_replacement_point_notrap(codegendata *cd)
882 assert(cd->replacementpoint);
883 assert(cd->replacementpoint->type == type);
884 assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
886 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
888 cd->replacementpoint++;
890 #endif /* defined(ENABLE_REPLACEMENT) */
893 /* codegen_set_replacement_point ***********************************************
895 Record the position of a trappable replacement point.
897 *******************************************************************************/
899 #if defined(ENABLE_REPLACEMENT)
901 void codegen_set_replacement_point(codegendata *cd, s4 type)
903 void codegen_set_replacement_point(codegendata *cd)
906 assert(cd->replacementpoint);
907 assert(cd->replacementpoint->type == type);
908 assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
910 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
912 cd->replacementpoint++;
914 /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
916 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
918 #endif /* defined(ENABLE_REPLACEMENT) */
921 /* codegen_finish **************************************************************
923 Finishes the code generation. A new memory, large enough for both
924 data and code, is allocated and data and code are copied together
925 to their final layout, unresolved jumps are resolved, ...
927 *******************************************************************************/
929 void codegen_finish(jitdata *jd)
934 #if defined(ENABLE_INTRP)
942 /* get required compiler data */
947 /* prevent compiler warning */
949 #if defined(ENABLE_INTRP)
953 /* calculate the code length */
955 mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
957 #if defined(ENABLE_STATISTICS)
959 count_code_len += mcodelen;
960 count_data_len += cd->dseglen;
964 alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
966 #if defined(ENABLE_INTRP)
968 ncodelen = cd->ncodeptr - cd->ncodebase;
970 ncodelen = 0; /* avoid compiler warning */
974 cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
975 alignedlen = alignedmcodelen + cd->dseglen;
977 #if defined(ENABLE_INTRP)
979 alignedlen += ncodelen;
983 /* allocate new memory */
985 code->mcodelength = mcodelen + cd->dseglen;
986 code->mcode = CNEW(u1, alignedlen);
988 /* set the entrypoint of the method */
990 assert(code->entrypoint == NULL);
991 code->entrypoint = epoint = (code->mcode + cd->dseglen);
993 /* fill the data segment (code->entrypoint must already be set!) */
997 /* copy code to the new location */
999 MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
1001 #if defined(ENABLE_INTRP)
1002 /* relocate native dynamic superinstruction code (if any) */
1005 cd->mcodebase = code->entrypoint;
1008 u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
1010 MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
1012 /* flush the instruction and data caches */
1014 md_cacheflush(ncodebase, ncodelen);
1016 /* set some cd variables for dynamic_super_rerwite */
1018 cd->ncodebase = ncodebase;
1021 cd->ncodebase = NULL;
1024 dynamic_super_rewrite(cd);
1028 /* jump table resolving */
1030 for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
1031 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
1032 (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
1034 /* line number table resolving */
1040 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
1042 target = lr->targetmpc;
1043 /* if the entry contains an mcode pointer (normal case), resolve it */
1044 /* (see doc/inlining_stacktrace.txt for details) */
1045 if (lr->linenumber >= -2) {
1046 target += (ptrint) epoint;
1048 *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) =
1049 (functionptr) target;
1052 *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
1053 (functionptr) ((ptrint) epoint + cd->linenumbertab);
1055 *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
1058 #if defined(ENABLE_REPLACEMENT)
1059 /* replacement point resolving */
1064 code->replacementstubs += (ptrint) epoint;
1066 rp = code->rplpoints;
1067 for (i=0; i<code->rplpointcount; ++i, ++rp) {
1068 rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
1071 #endif /* defined(ENABLE_REPLACEMENT) */
1073 /* add method into methodtree to find the entrypoint */
1075 codegen_insertmethod(code->entrypoint, code->entrypoint + mcodelen);
1077 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
1078 /* resolve data segment references */
1080 dseg_resolve_datareferences(jd);
1083 #if defined(ENABLE_THREADS)
1084 /* create cirtical sections */
1086 codegen_critical_section_finish(jd);
1089 /* flush the instruction and data caches */
1091 md_cacheflush(code->mcode, code->mcodelength);
1095 /* codegen_generate_stub_compiler **********************************************
1097 Wrapper for codegen_emit_stub_compiler.
1100 pointer to the compiler stub code.
1102 *******************************************************************************/
1104 u1 *codegen_generate_stub_compiler(methodinfo *m)
1108 ptrint *d; /* pointer to data memory */
1109 u1 *c; /* pointer to code memory */
1112 /* mark dump memory */
1114 dumpsize = dump_size();
1116 /* allocate required data structures */
1121 jd->cd = DNEW(codegendata);
1124 /* get required compiler data */
1128 /* allocate code memory */
1130 c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1132 /* set pointers correctly */
1138 c = c + 3 * SIZEOF_VOID_P;
1141 /* NOTE: The codeinfo pointer is actually a pointer to the
1142 methodinfo (this fakes a codeinfo structure). */
1144 d[0] = (ptrint) asm_call_jit_compiler;
1146 d[2] = (ptrint) &d[1]; /* fake code->m */
1148 /* call the emit function */
1150 codegen_emit_stub_compiler(jd);
1152 #if defined(ENABLE_STATISTICS)
1154 count_cstub_len += 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
1159 md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1161 /* release dump memory */
1163 dump_release(dumpsize);
1165 /* return native stub code */
1171 /* codegen_generate_stub_builtin ***********************************************
1173 Wrapper for codegen_emit_stub_builtin.
1176 Pointer to the entrypoint of the stub.
1178 *******************************************************************************/
1180 void codegen_generate_stub_builtin(builtintable_entry *bte)
1186 /* mark dump memory */
1188 dumpsize = dump_size();
1193 jd->cd = DNEW(codegendata);
1197 /* Allocate codeinfo memory from the heap as we need to keep them. */
1199 jd->code = code_codeinfo_new(NULL);
1201 /* get required compiler data */
1205 /* setup code generation stuff */
1209 /* generate the code */
1211 #if defined(ENABLE_JIT)
1212 # if defined(ENABLE_INTRP)
1215 codegen_emit_stub_builtin(jd, bte);
1218 /* reallocate the memory and finish the code generation */
1222 /* set the stub entry point in the builtin table */
1224 bte->stub = code->entrypoint;
1226 #if defined(ENABLE_STATISTICS)
1228 size_stub_native += code->mcodelength;
1231 /* release memory */
1233 dump_release(dumpsize);
1237 /* codegen_generate_stub_native ************************************************
1239 Wrapper for codegen_emit_stub_native.
1242 the codeinfo representing the stub code.
1244 *******************************************************************************/
1246 codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
1255 /* mark dump memory */
1257 dumpsize = dump_size();
1262 jd->cd = DNEW(codegendata);
1263 jd->rd = DNEW(registerdata);
1266 /* Allocate codeinfo memory from the heap as we need to keep them. */
1268 jd->code = code_codeinfo_new(m); /* XXX check allocation */
1270 /* get required compiler data */
1274 /* set the flags for the current JIT run */
1276 #if defined(ENABLE_PROFILING)
1278 jd->flags |= JITDATA_FLAG_INSTRUMENT;
1281 if (opt_verbosecall)
1282 jd->flags |= JITDATA_FLAG_VERBOSECALL;
1284 /* setup code generation stuff */
1286 #if defined(ENABLE_JIT)
1287 # if defined(ENABLE_INTRP)
1295 /* create new method descriptor with additional native parameters */
1298 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
1300 nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
1301 md->paramcount * sizeof(typedesc) +
1302 nativeparams * sizeof(typedesc));
1304 nmd->paramcount = md->paramcount + nativeparams;
1306 nmd->params = DMNEW(paramdesc, nmd->paramcount);
1308 nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer */
1310 if (m->flags & ACC_STATIC)
1311 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer */
1313 MCOPY(nmd->paramtypes + nativeparams, md->paramtypes, typedesc,
1316 #if defined(ENABLE_JIT)
1317 # if defined(ENABLE_INTRP)
1320 /* pre-allocate the arguments for the native ABI */
1322 md_param_alloc_native(nmd);
1325 /* generate the code */
1327 #if defined(ENABLE_JIT)
1328 # if defined(ENABLE_INTRP)
1330 intrp_createnativestub(f, jd, nmd);
1333 codegen_emit_stub_native(jd, nmd, f);
1335 intrp_createnativestub(f, jd, nmd);
1338 /* reallocate the memory and finish the code generation */
1342 #if defined(ENABLE_STATISTICS)
1343 /* must be done after codegen_finish() */
1346 size_stub_native += code->mcodelength;
1349 #if !defined(NDEBUG)
1350 /* disassemble native stub */
1352 if (opt_shownativestub) {
1353 #if defined(ENABLE_DISASSEMBLER)
1354 codegen_disassemble_nativestub(m,
1355 (u1 *) (ptrint) code->entrypoint,
1356 (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
1359 /* show data segment */
1361 if (opt_showddatasegment)
1364 #endif /* !defined(NDEBUG) */
1366 /* release memory */
1368 dump_release(dumpsize);
1370 /* return native stub code */
1376 /* codegen_disassemble_nativestub **********************************************
1378 Disassembles the generated native stub.
1380 *******************************************************************************/
1382 #if defined(ENABLE_DISASSEMBLER)
1383 void codegen_disassemble_nativestub(methodinfo *m, u1 *start, u1 *end)
1385 printf("Native stub: ");
1386 utf_fprint_printable_ascii_classname(stdout, m->class->name);
1388 utf_fprint_printable_ascii(stdout, m->name);
1389 utf_fprint_printable_ascii(stdout, m->descriptor);
1390 printf("\n\nLength: %d\n\n", (s4) (end - start));
1392 DISASSEMBLE(start, end);
1397 /* codegen_stub_builtin_enter **************************************************
1399 Prepares the stuff required for a builtin function call:
1401 - adds a stackframe info structure to the chain, for stacktraces
1403 The layout of the builtin stub stackframe should look like this:
1405 +---------------------------+ <- SP (of parent Java function)
1407 +---------------------------+
1409 | stackframe info structure |
1411 +---------------------------+
1413 | arguments (if any) |
1415 +---------------------------+ <- SP (native stub)
1417 *******************************************************************************/
1419 void codegen_stub_builtin_enter(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
1421 stackframeinfo *sfi;
1423 /* get data structures from stack */
1425 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1427 /* add a stackframeinfo to the chain */
1429 stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
1431 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1432 /* set the native world flag */
1434 THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE;
1439 /* codegen_stub_builtin_exit ***************************************************
1441 Removes the stuff required for a builtin function call.
1443 *******************************************************************************/
1445 void codegen_stub_builtin_exit(u1 *datasp)
1447 stackframeinfo *sfi;
1448 stackframeinfo **psfi;
1450 /* get data structures from stack */
1452 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1454 /* remove current stackframeinfo from chain */
1456 psfi = &STACKFRAMEINFO;
1460 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1461 /* clear the native world flag */
1463 THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE;
1468 /* codegen_start_native_call ***************************************************
1470 Prepares the stuff required for a native (JNI) function call:
1472 - adds a stackframe info structure to the chain, for stacktraces
1473 - prepares the local references table on the stack
1475 The layout of the native stub stackframe should look like this:
1477 +---------------------------+ <- SP (of parent Java function)
1479 +---------------------------+
1481 | stackframe info structure |
1483 +---------------------------+
1485 | local references table |
1487 +---------------------------+
1489 | arguments (if any) |
1491 +---------------------------+ <- SP (native stub)
1493 *******************************************************************************/
1495 void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
1497 stackframeinfo *sfi;
1498 localref_table *lrt;
1500 /* get data structures from stack */
1502 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1503 lrt = (localref_table *) (datasp - sizeof(stackframeinfo) -
1504 sizeof(localref_table));
1506 /* add a stackframeinfo to the chain */
1508 stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
1510 #if defined(ENABLE_JNI)
1511 /* add current JNI local references table to this thread */
1513 lrt->capacity = LOCALREFTABLE_CAPACITY;
1515 lrt->localframes = 1;
1516 lrt->prev = LOCALREFTABLE;
1518 /* clear the references array (memset is faster the a for-loop) */
1520 MSET(lrt->refs, 0, java_objectheader*, LOCALREFTABLE_CAPACITY);
1522 LOCALREFTABLE = lrt;
1525 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1526 /* set the native world flag */
1528 THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE;
1533 /* codegen_finish_native_call **************************************************
1535 Removes the stuff required for a native (JNI) function call.
1536 Additionally it checks for an exceptions and in case, get the
1537 exception object and clear the pointer.
1539 *******************************************************************************/
1541 java_objectheader *codegen_finish_native_call(u1 *datasp)
1543 stackframeinfo *sfi;
1544 stackframeinfo **psfi;
1545 #if defined(ENABLE_JNI)
1546 localref_table *lrt;
1547 localref_table *plrt;
1550 java_objectheader *e;
1552 /* get data structures from stack */
1554 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1556 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1557 /* clear the native world flag */
1559 THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE;
1562 /* remove current stackframeinfo from chain */
1564 psfi = &STACKFRAMEINFO;
1568 #if defined(ENABLE_JNI)
1569 /* release JNI local references tables for this thread */
1571 lrt = LOCALREFTABLE;
1573 /* release all current local frames */
1575 for (localframes = lrt->localframes; localframes >= 1; localframes--) {
1576 /* get previous frame */
1580 /* Clear all reference entries (only for tables allocated on
1583 if (localframes > 1)
1584 MSET(&lrt->refs[0], 0, java_objectheader*, lrt->capacity);
1588 /* set new local references table */
1593 /* now store the previous local frames in the thread structure */
1595 LOCALREFTABLE = lrt;
1598 /* get the exception and return it */
1600 e = exceptions_get_and_clear_exception();
1606 /* removecompilerstub **********************************************************
1608 Deletes a compilerstub from memory (simply by freeing it).
1610 *******************************************************************************/
1612 void removecompilerstub(u1 *stub)
1614 /* pass size 1 to keep the intern function happy */
1616 CFREE((void *) stub, 1);
1620 /* removenativestub ************************************************************
1622 Removes a previously created native-stub from memory.
1624 *******************************************************************************/
1626 void removenativestub(u1 *stub)
1628 /* pass size 1 to keep the intern function happy */
1630 CFREE((void *) stub, 1);
1634 /* codegen_reg_of_var **********************************************************
1636 This function determines a register, to which the result of an
1637 operation should go, when it is ultimatively intended to store the
1638 result in pseudoregister v. If v is assigned to an actual
1639 register, this register will be returned. Otherwise (when v is
1640 spilled) this function returns tempregnum. If not already done,
1641 regoff and flags are set in the stack location.
1643 On ARM we have to check if a long/double variable is splitted
1644 across reg/stack (HIGH_REG == REG_SPLIT). We return the actual
1645 register of v for LOW_REG and the tempregnum for HIGH_REG in such
1646 cases. (michi 2005/07/24)
1648 *******************************************************************************/
1650 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
1654 /* Do we have to generate a conditional move? Yes, then always
1655 return the temporary register. The real register is identified
1656 during the store. */
1658 if (opcode & ICMD_CONDITION_MASK)
1662 if (!(v->flags & INMEMORY)) {
1663 #if defined(__ARM__) && defined(__ARMEL__)
1664 if (IS_2_WORD_TYPE(v->type) && (GET_HIGH_REG(v->vv.regoff) == REG_SPLIT))
1665 return PACK_REGS(GET_LOW_REG(v->vv.regoff),
1666 GET_HIGH_REG(tempregnum));
1668 #if defined(__ARM__) && defined(__ARMEB__)
1669 if (IS_2_WORD_TYPE(v->type) && (GET_LOW_REG(v->vv.regoff) == REG_SPLIT))
1670 return PACK_REGS(GET_LOW_REG(tempregnum),
1671 GET_HIGH_REG(v->vv.regoff));
1673 return v->vv.regoff;
1676 #if defined(ENABLE_STATISTICS)
1678 count_spills_read++;
1684 /* codegen_reg_of_dst **********************************************************
1686 This function determines a register, to which the result of an
1687 operation should go, when it is ultimatively intended to store the
1688 result in iptr->dst.var. If dst.var is assigned to an actual
1689 register, this register will be returned. Otherwise (when it is
1690 spilled) this function returns tempregnum. If not already done,
1691 regoff and flags are set in the stack location.
1693 On ARM we have to check if a long/double variable is splitted
1694 across reg/stack (HIGH_REG == REG_SPLIT). We return the actual
1695 register of dst.var for LOW_REG and the tempregnum for HIGH_REG in such
1696 cases. (michi 2005/07/24)
1698 *******************************************************************************/
1700 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
1702 return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
1706 /* codegen_emit_phi_moves ****************************************************
1708 Emits phi moves at the end of the basicblock.
1710 *******************************************************************************/
1712 #if defined(ENABLE_SSA)
1713 void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
1726 /* Moves from phi functions with highest indices have to be */
1727 /* inserted first, since this is the order as is used for */
1728 /* conflict resolution */
1730 for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
1731 lt_d = ls->phi_moves[bptr->nr][i][0];
1732 lt_s = ls->phi_moves[bptr->nr][i][1];
1733 #if defined(SSA_DEBUG_VERBOSE)
1735 printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
1737 if (lt_s == UNUSED) {
1738 #if defined(SSA_DEBUG_VERBOSE)
1740 printf(" ... not processed \n");
1745 d = VAR(ls->lifetime[lt_d].v_index);
1746 s = VAR(ls->lifetime[lt_s].v_index);
1749 if (d->type == -1) {
1750 #if defined(SSA_DEBUG_VERBOSE)
1752 printf("...returning - phi lifetimes where joined\n");
1757 if (s->type == -1) {
1758 #if defined(SSA_DEBUG_VERBOSE)
1760 printf("...returning - phi lifetimes where joined\n");
1766 tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
1767 tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
1768 emit_copy(jd, &tmp_i);
1770 #if defined(SSA_DEBUG_VERBOSE)
1771 if (compileverbose) {
1772 if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
1774 printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1776 else if (IS_INMEMORY(s->flags)) {
1778 printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1780 else if (IS_INMEMORY(d->flags)) {
1782 printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1786 printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1790 #endif /* defined(SSA_DEBUG_VERBOSE) */
1793 #endif /* defined(ENABLE_SSA) */
1798 * These are local overrides for various environment variables in Emacs.
1799 * Please do not remove this and leave it at the end of the file, where
1800 * Emacs will automagically detect them.
1801 * ---------------------------------------------------------------------
1804 * indent-tabs-mode: t
1808 * vim:noexpandtab:sw=4:ts=4: