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 8160 2007-06-28 01:52:19Z michi $
54 #if defined(ENABLE_JIT)
55 /* this is required PATCHER_CALL_SIZE */
59 #include "mm/memory.h"
61 #include "toolbox/avl.h"
62 #include "toolbox/list.h"
63 #include "toolbox/logging.h"
65 #include "native/jni.h"
66 #include "native/native.h"
68 #include "threads/threads-common.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 #if defined(ENABLE_REPLACEMENT)
268 code->rplpoints = NULL;
269 code->rplpointcount = 0;
270 code->regalloc = NULL;
271 code->regalloccount = 0;
272 code->globalcount = 0;
277 /* codegen_generate ************************************************************
279 Generates the code for the currently compiled method.
281 *******************************************************************************/
283 bool codegen_generate(jitdata *jd)
287 /* get required compiler data */
291 /* call the machine-dependent code generation function */
293 if (!codegen_emit(jd))
296 /* check for an error */
298 if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
299 /* check for long-branches flag, if it is set we recompile the
304 log_message_method("Re-generating code: ", jd->m);
307 /* XXX maybe we should tag long-branches-methods for recompilation */
309 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
310 /* we have to reset the codegendata structure first */
314 /* and restart the compiler run */
316 if (!codegen_emit(jd))
320 vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
325 log_message_method("Re-generating code done: ", jd->m);
329 /* reallocate the memory and finish the code generation */
333 /* everything's ok */
339 /* codegen_close ***************************************************************
343 *******************************************************************************/
345 void codegen_close(void)
347 /* TODO: release avl tree on i386 and x86_64 */
351 /* codegen_increase ************************************************************
355 *******************************************************************************/
357 void codegen_increase(codegendata *cd)
361 /* save old mcodebase pointer */
363 oldmcodebase = cd->mcodebase;
365 /* reallocate to new, doubled memory */
367 cd->mcodebase = DMREALLOC(cd->mcodebase,
372 cd->mcodeend = cd->mcodebase + cd->mcodesize;
374 /* set new mcodeptr */
376 cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
378 #if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(__M68K__) || defined(ENABLE_INTRP) \
379 || defined(__SPARC_64__)
380 /* adjust the pointer to the last patcher position */
382 if (cd->lastmcodeptr != NULL)
383 cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
388 /* codegen_ncode_increase ******************************************************
392 *******************************************************************************/
394 #if defined(ENABLE_INTRP)
395 u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
399 /* save old ncodebase pointer */
401 oldncodebase = cd->ncodebase;
403 /* reallocate to new, doubled memory */
405 cd->ncodebase = DMREALLOC(cd->ncodebase,
411 /* return the new ncodeptr */
413 return (cd->ncodebase + (ncodeptr - oldncodebase));
418 /* codegen_add_branch_ref ******************************************************
420 Prepends an branch to the list.
422 *******************************************************************************/
424 void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
429 STATISTICS(count_branches_unresolved++);
431 /* calculate the mpc of the branch instruction */
433 branchmpc = cd->mcodeptr - cd->mcodebase;
435 br = DNEW(branchref);
437 br->branchmpc = branchmpc;
438 br->condition = condition;
440 br->options = options;
441 br->next = target->branchrefs;
443 target->branchrefs = br;
447 /* codegen_resolve_branchrefs **************************************************
449 Resolves and patches the branch references of a given basic block.
451 *******************************************************************************/
453 void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
458 /* Save the mcodeptr because in the branch emitting functions
459 we generate code somewhere inside already generated code,
460 but we're still in the actual code generation phase. */
462 mcodeptr = cd->mcodeptr;
464 /* just to make sure */
466 assert(bptr->mpc >= 0);
468 for (br = bptr->branchrefs; br != NULL; br = br->next) {
469 /* temporary set the mcodeptr */
471 cd->mcodeptr = cd->mcodebase + br->branchmpc;
473 /* emit_bccz and emit_branch emit the correct code, even if we
474 pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
476 emit_bccz(cd, bptr, br->condition, br->reg, br->options);
479 /* restore mcodeptr */
481 cd->mcodeptr = mcodeptr;
485 /* codegen_branch_label_add ****************************************************
487 Append an branch to the label-branch list.
489 *******************************************************************************/
491 void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
494 branch_label_ref_t *br;
497 /* get the label list */
499 list = cd->brancheslabel;
501 /* calculate the current mpc */
503 mpc = cd->mcodeptr - cd->mcodebase;
505 br = DNEW(branch_label_ref_t);
509 br->condition = condition;
511 br->options = options;
513 /* add the branch to the list */
515 list_add_last_unsynced(list, br);
519 /* codegen_add_patch_ref *******************************************************
521 Appends a new patcher reference to the list of patching positions.
523 *******************************************************************************/
525 void codegen_add_patch_ref(codegendata *cd, functionptr patcher, voidptr ref,
531 branchmpc = cd->mcodeptr - cd->mcodebase;
535 pr->branchpos = branchmpc;
537 pr->patcher = patcher;
540 /* list_add_first(cd->patchrefs, pr); */
541 pr->next = cd->patchrefs;
544 /* Generate NOPs for opt_shownops. */
549 /* If the codegen provides a PACHER_LONGBRANCHES_NOPS macro, honour it. */
551 #if defined(PATCHER_LONGBRANCHES_NOPS)
552 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
553 PATCHER_LONGBRANCHES_NOPS;
557 #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__M68K__) || defined(__MIPS__) \
558 || defined(__SPARC_64__) || defined(__X86_64__))
560 /* On some architectures the patcher stub call instruction might
561 be longer than the actual instruction generated. On this
562 architectures we store the last patcher call position and after
563 the basic block code generation is completed, we check the
564 range and maybe generate some nop's. */
565 /* The nops are generated in codegen_emit in each codegen */
567 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
572 /* codegen_critical_section_new ************************************************
574 Allocates a new critical-section reference and adds it to the
575 critical-section list.
577 *******************************************************************************/
579 #if defined(ENABLE_THREADS)
580 void codegen_critical_section_new(codegendata *cd)
583 critical_section_ref_t *csr;
586 /* get the critical section list */
588 list = cd->listcritical;
590 /* calculate the current mpc */
592 mpc = cd->mcodeptr - cd->mcodebase;
594 csr = DNEW(critical_section_ref_t);
596 /* We only can set restart right now, as start and end are set by
597 the following, corresponding functions. */
603 /* add the branch to the list */
605 list_add_last_unsynced(list, csr);
610 /* codegen_critical_section_start **********************************************
612 Set the start-point of the current critical section (which is the
613 last element of the list).
615 *******************************************************************************/
617 #if defined(ENABLE_THREADS)
618 void codegen_critical_section_start(codegendata *cd)
621 critical_section_ref_t *csr;
624 /* get the critical section list */
626 list = cd->listcritical;
628 /* calculate the current mpc */
630 mpc = cd->mcodeptr - cd->mcodebase;
632 /* get the current critical section */
634 csr = list_last_unsynced(list);
636 /* set the start point */
638 assert(csr->start == -1);
645 /* codegen_critical_section_end ************************************************
647 Set the end-point of the current critical section (which is the
648 last element of the list).
650 *******************************************************************************/
652 #if defined(ENABLE_THREADS)
653 void codegen_critical_section_end(codegendata *cd)
656 critical_section_ref_t *csr;
659 /* get the critical section list */
661 list = cd->listcritical;
663 /* calculate the current mpc */
665 mpc = cd->mcodeptr - cd->mcodebase;
667 /* get the current critical section */
669 csr = list_last_unsynced(list);
671 /* set the end point */
673 assert(csr->end == -1);
680 /* codegen_critical_section_finish *********************************************
682 Finish the critical sections, create the critical section nodes for
683 the AVL tree and insert them into the tree.
685 *******************************************************************************/
687 #if defined(ENABLE_THREADS)
688 static void codegen_critical_section_finish(jitdata *jd)
693 critical_section_ref_t *csr;
694 critical_section_node_t *csn;
696 /* get required compiler data */
701 /* get the critical section list */
703 list = cd->listcritical;
705 /* iterate over all critical sections */
707 for (csr = list_first_unsynced(list); csr != NULL;
708 csr = list_next_unsynced(list, csr)) {
709 /* check if all points are set */
711 assert(csr->start != -1);
712 assert(csr->end != -1);
713 assert(csr->restart != -1);
715 /* allocate tree node */
717 csn = NEW(critical_section_node_t);
719 csn->start = code->entrypoint + csr->start;
720 csn->end = code->entrypoint + csr->end;
721 csn->restart = code->entrypoint + csr->restart;
723 /* insert into the tree */
725 critical_section_register(csn);
731 /* methodtree_comparator *******************************************************
733 Comparator function used for the AVL tree of methods.
736 treenode....the node from the tree
737 node........the node to compare to the tree-node
739 *******************************************************************************/
741 static s4 methodtree_comparator(const void *treenode, const void *node)
743 methodtree_element *mte;
744 methodtree_element *mtepc;
746 mte = (methodtree_element *) treenode;
747 mtepc = (methodtree_element *) node;
749 /* compare both startpc and endpc of pc, even if they have the same value,
750 otherwise the avl_probe sometimes thinks the element is already in the
754 /* On S390 addresses are 31 bit. Compare only 31 bits of value.
756 # define ADDR_MASK(a) ((a) & 0x7FFFFFFF)
758 # define ADDR_MASK(a) (a)
761 if (ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->startpc) &&
762 ADDR_MASK((long) mtepc->startpc) <= ADDR_MASK((long) mte->endpc) &&
763 ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->endpc) &&
764 ADDR_MASK((long) mtepc->endpc) <= ADDR_MASK((long) mte->endpc)) {
767 } else if (ADDR_MASK((long) mtepc->startpc) < ADDR_MASK((long) mte->startpc)) {
778 /* codegen_insertmethod ********************************************************
780 Insert the machine code range of a method into the AVL tree of methods.
782 *******************************************************************************/
784 void codegen_insertmethod(u1 *startpc, u1 *endpc)
786 methodtree_element *mte;
788 /* allocate new method entry */
790 mte = NEW(methodtree_element);
792 mte->startpc = startpc;
795 /* this function does not return an error, but asserts for
798 avl_insert(methodtree, mte);
802 /* codegen_get_pv_from_pc ******************************************************
804 Find the PV for the given PC by searching in the AVL tree of
807 *******************************************************************************/
809 u1 *codegen_get_pv_from_pc(u1 *pc)
811 methodtree_element mtepc;
812 methodtree_element *mte;
814 /* allocation of the search structure on the stack is much faster */
819 mte = avl_find(methodtree, &mtepc);
822 /* No method was found. Let's dump a stacktrace. */
824 #if defined(ENABLE_VMLOG)
825 vmlog_cacao_signl("SIGSEGV");
828 log_println("We received a SIGSEGV and tried to handle it, but we were");
829 log_println("unable to find a Java method at:");
831 #if SIZEOF_VOID_P == 8
832 log_println("PC=0x%016lx", pc);
834 log_println("PC=0x%08x", pc);
838 log_println("Dumping the current stacktrace:");
840 #if defined(ENABLE_THREADS)
841 /* XXX michi: This should be available even without threads! */
842 threads_print_stacktrace();
845 vm_abort("Exiting...");
852 /* codegen_get_pv_from_pc_nocheck **********************************************
854 Find the PV for the given PC by searching in the AVL tree of
855 methods. This method does not check the return value and is used
858 *******************************************************************************/
860 u1 *codegen_get_pv_from_pc_nocheck(u1 *pc)
862 methodtree_element mtepc;
863 methodtree_element *mte;
865 /* allocation of the search structure on the stack is much faster */
870 mte = avl_find(methodtree, &mtepc);
879 /* codegen_set_replacement_point_notrap ****************************************
881 Record the position of a non-trappable replacement point.
883 *******************************************************************************/
885 #if defined(ENABLE_REPLACEMENT)
887 void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
889 void codegen_set_replacement_point_notrap(codegendata *cd)
892 assert(cd->replacementpoint);
893 assert(cd->replacementpoint->type == type);
894 assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
896 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
898 cd->replacementpoint++;
900 #endif /* defined(ENABLE_REPLACEMENT) */
903 /* codegen_set_replacement_point ***********************************************
905 Record the position of a trappable replacement point.
907 *******************************************************************************/
909 #if defined(ENABLE_REPLACEMENT)
911 void codegen_set_replacement_point(codegendata *cd, s4 type)
913 void codegen_set_replacement_point(codegendata *cd)
916 assert(cd->replacementpoint);
917 assert(cd->replacementpoint->type == type);
918 assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
920 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
922 cd->replacementpoint++;
924 /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
926 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
928 #endif /* defined(ENABLE_REPLACEMENT) */
931 /* codegen_finish **************************************************************
933 Finishes the code generation. A new memory, large enough for both
934 data and code, is allocated and data and code are copied together
935 to their final layout, unresolved jumps are resolved, ...
937 *******************************************************************************/
939 void codegen_finish(jitdata *jd)
944 #if defined(ENABLE_INTRP)
953 /* get required compiler data */
958 /* prevent compiler warning */
960 #if defined(ENABLE_INTRP)
964 /* calculate the code length */
966 mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
968 #if defined(ENABLE_STATISTICS)
970 count_code_len += mcodelen;
971 count_data_len += cd->dseglen;
975 alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
977 #if defined(ENABLE_INTRP)
979 ncodelen = cd->ncodeptr - cd->ncodebase;
981 ncodelen = 0; /* avoid compiler warning */
985 cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
986 alignedlen = alignedmcodelen + cd->dseglen;
988 #if defined(ENABLE_INTRP)
990 alignedlen += ncodelen;
994 /* allocate new memory */
996 code->mcodelength = mcodelen + cd->dseglen;
997 code->mcode = CNEW(u1, alignedlen);
999 /* set the entrypoint of the method */
1001 assert(code->entrypoint == NULL);
1002 code->entrypoint = epoint = (code->mcode + cd->dseglen);
1004 /* fill the data segment (code->entrypoint must already be set!) */
1008 /* copy code to the new location */
1010 MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
1012 #if defined(ENABLE_INTRP)
1013 /* relocate native dynamic superinstruction code (if any) */
1016 cd->mcodebase = code->entrypoint;
1019 u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
1021 MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
1023 /* flush the instruction and data caches */
1025 md_cacheflush(ncodebase, ncodelen);
1027 /* set some cd variables for dynamic_super_rerwite */
1029 cd->ncodebase = ncodebase;
1032 cd->ncodebase = NULL;
1035 dynamic_super_rewrite(cd);
1039 /* jump table resolving */
1041 for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
1042 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
1043 (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
1045 /* line number table resolving */
1051 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
1053 target = lr->targetmpc;
1054 /* if the entry contains an mcode pointer (normal case), resolve it */
1055 /* (see doc/inlining_stacktrace.txt for details) */
1056 if (lr->linenumber >= -2) {
1057 target += (ptrint) epoint;
1059 *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) =
1060 (functionptr) target;
1063 *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
1064 (functionptr) ((ptrint) epoint + cd->linenumbertab);
1066 *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
1069 /* patcher resolving */
1071 pr = list_first_unsynced(code->patchers);
1073 pr->mpc += (ptrint) epoint;
1074 pr->datap = (ptrint) (pr->disp + epoint);
1075 pr = list_next_unsynced(code->patchers, pr);
1078 #if defined(ENABLE_REPLACEMENT)
1079 /* replacement point resolving */
1084 code->replacementstubs += (ptrint) epoint;
1086 rp = code->rplpoints;
1087 for (i=0; i<code->rplpointcount; ++i, ++rp) {
1088 rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
1091 #endif /* defined(ENABLE_REPLACEMENT) */
1093 /* add method into methodtree to find the entrypoint */
1095 codegen_insertmethod(code->entrypoint, code->entrypoint + mcodelen);
1097 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
1098 /* resolve data segment references */
1100 dseg_resolve_datareferences(jd);
1103 #if defined(ENABLE_THREADS)
1104 /* create cirtical sections */
1106 codegen_critical_section_finish(jd);
1109 /* flush the instruction and data caches */
1111 md_cacheflush(code->mcode, code->mcodelength);
1115 /* codegen_generate_stub_compiler **********************************************
1117 Wrapper for codegen_emit_stub_compiler.
1120 pointer to the compiler stub code.
1122 *******************************************************************************/
1124 u1 *codegen_generate_stub_compiler(methodinfo *m)
1128 ptrint *d; /* pointer to data memory */
1129 u1 *c; /* pointer to code memory */
1132 /* mark dump memory */
1134 dumpsize = dump_size();
1136 /* allocate required data structures */
1141 jd->cd = DNEW(codegendata);
1144 /* get required compiler data */
1148 /* allocate code memory */
1150 c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1152 /* set pointers correctly */
1158 c = c + 3 * SIZEOF_VOID_P;
1161 /* NOTE: The codeinfo pointer is actually a pointer to the
1162 methodinfo (this fakes a codeinfo structure). */
1164 d[0] = (ptrint) asm_call_jit_compiler;
1166 d[2] = (ptrint) &d[1]; /* fake code->m */
1168 /* call the emit function */
1170 codegen_emit_stub_compiler(jd);
1172 #if defined(ENABLE_STATISTICS)
1174 count_cstub_len += 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
1179 md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1181 /* release dump memory */
1183 dump_release(dumpsize);
1185 /* return native stub code */
1191 /* codegen_generate_stub_native ************************************************
1193 Wrapper for codegen_emit_stub_native.
1196 the codeinfo representing the stub code.
1198 *******************************************************************************/
1200 codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
1209 /* mark dump memory */
1211 dumpsize = dump_size();
1216 jd->cd = DNEW(codegendata);
1217 jd->rd = DNEW(registerdata);
1220 /* Allocate codeinfo memory from the heap as we need to keep them. */
1222 jd->code = code_codeinfo_new(m); /* XXX check allocation */
1224 /* get required compiler data */
1228 /* set the flags for the current JIT run */
1230 #if defined(ENABLE_PROFILING)
1232 jd->flags |= JITDATA_FLAG_INSTRUMENT;
1235 if (opt_verbosecall)
1236 jd->flags |= JITDATA_FLAG_VERBOSECALL;
1238 /* setup code generation stuff */
1240 #if defined(ENABLE_JIT)
1241 # if defined(ENABLE_INTRP)
1249 /* create new method descriptor with additional native parameters */
1252 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
1254 nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
1255 md->paramcount * sizeof(typedesc) +
1256 nativeparams * sizeof(typedesc));
1258 nmd->paramcount = md->paramcount + nativeparams;
1260 nmd->params = DMNEW(paramdesc, nmd->paramcount);
1262 nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer */
1264 if (m->flags & ACC_STATIC)
1265 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer */
1267 MCOPY(nmd->paramtypes + nativeparams, md->paramtypes, typedesc,
1270 #if defined(ENABLE_JIT)
1271 # if defined(ENABLE_INTRP)
1274 /* pre-allocate the arguments for the native ABI */
1276 md_param_alloc_native(nmd);
1279 /* generate the code */
1281 #if defined(ENABLE_JIT)
1282 # if defined(ENABLE_INTRP)
1284 intrp_createnativestub(f, jd, nmd);
1287 codegen_emit_stub_native(jd, nmd, f);
1289 intrp_createnativestub(f, jd, nmd);
1292 /* reallocate the memory and finish the code generation */
1296 #if defined(ENABLE_STATISTICS)
1297 /* must be done after codegen_finish() */
1300 size_stub_native += code->mcodelength;
1303 #if !defined(NDEBUG)
1304 /* disassemble native stub */
1306 if (opt_shownativestub) {
1307 #if defined(ENABLE_DEBUG_FILTER)
1308 if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
1311 #if defined(ENABLE_DISASSEMBLER)
1312 codegen_disassemble_nativestub(m,
1313 (u1 *) (ptrint) code->entrypoint,
1314 (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
1317 /* show data segment */
1319 if (opt_showddatasegment)
1323 #endif /* !defined(NDEBUG) */
1325 /* release memory */
1327 dump_release(dumpsize);
1329 /* return native stub code */
1335 /* codegen_disassemble_nativestub **********************************************
1337 Disassembles the generated native stub.
1339 *******************************************************************************/
1341 #if defined(ENABLE_DISASSEMBLER)
1342 void codegen_disassemble_nativestub(methodinfo *m, u1 *start, u1 *end)
1344 printf("Native stub: ");
1345 utf_fprint_printable_ascii_classname(stdout, m->class->name);
1347 utf_fprint_printable_ascii(stdout, m->name);
1348 utf_fprint_printable_ascii(stdout, m->descriptor);
1349 printf("\n\nLength: %d\n\n", (s4) (end - start));
1351 DISASSEMBLE(start, end);
1356 /* codegen_start_native_call ***************************************************
1358 Prepares the stuff required for a native (JNI) function call:
1360 - adds a stackframe info structure to the chain, for stacktraces
1361 - prepares the local references table on the stack
1363 The layout of the native stub stackframe should look like this:
1365 +---------------------------+ <- SP (of parent Java function)
1367 +---------------------------+
1369 | stackframe info structure |
1371 +---------------------------+
1373 | local references table |
1375 +---------------------------+
1377 | arguments (if any) |
1379 +---------------------------+ <- SP (native stub)
1381 *******************************************************************************/
1383 void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
1385 stackframeinfo *sfi;
1386 localref_table *lrt;
1388 STATISTICS(count_calls_java_to_native++);
1390 /* get data structures from stack */
1392 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1393 lrt = (localref_table *) (datasp - sizeof(stackframeinfo) -
1394 sizeof(localref_table));
1396 /* add a stackframeinfo to the chain */
1398 stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
1400 #if defined(ENABLE_JNI)
1401 /* add current JNI local references table to this thread */
1403 lrt->capacity = LOCALREFTABLE_CAPACITY;
1405 lrt->localframes = 1;
1406 lrt->prev = LOCALREFTABLE;
1408 /* clear the references array (memset is faster the a for-loop) */
1410 MSET(lrt->refs, 0, java_objectheader*, LOCALREFTABLE_CAPACITY);
1412 LOCALREFTABLE = lrt;
1417 /* codegen_finish_native_call **************************************************
1419 Removes the stuff required for a native (JNI) function call.
1420 Additionally it checks for an exceptions and in case, get the
1421 exception object and clear the pointer.
1423 *******************************************************************************/
1425 java_objectheader *codegen_finish_native_call(u1 *datasp)
1427 stackframeinfo *sfi;
1428 stackframeinfo **psfi;
1429 #if defined(ENABLE_JNI)
1430 localref_table *lrt;
1431 localref_table *plrt;
1434 java_objectheader *e;
1436 /* get data structures from stack */
1438 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1440 /* remove current stackframeinfo from chain */
1442 psfi = &STACKFRAMEINFO;
1446 #if defined(ENABLE_JNI)
1447 /* release JNI local references tables for this thread */
1449 lrt = LOCALREFTABLE;
1451 /* release all current local frames */
1453 for (localframes = lrt->localframes; localframes >= 1; localframes--) {
1454 /* get previous frame */
1458 /* Clear all reference entries (only for tables allocated on
1461 if (localframes > 1)
1462 MSET(&lrt->refs[0], 0, java_objectheader*, lrt->capacity);
1466 /* set new local references table */
1471 /* now store the previous local frames in the thread structure */
1473 LOCALREFTABLE = lrt;
1476 /* get the exception and return it */
1478 e = exceptions_get_and_clear_exception();
1484 /* removecompilerstub **********************************************************
1486 Deletes a compilerstub from memory (simply by freeing it).
1488 *******************************************************************************/
1490 void removecompilerstub(u1 *stub)
1492 /* pass size 1 to keep the intern function happy */
1494 CFREE((void *) stub, 1);
1498 /* removenativestub ************************************************************
1500 Removes a previously created native-stub from memory.
1502 *******************************************************************************/
1504 void removenativestub(u1 *stub)
1506 /* pass size 1 to keep the intern function happy */
1508 CFREE((void *) stub, 1);
1512 /* codegen_reg_of_var **********************************************************
1514 This function determines a register, to which the result of an
1515 operation should go, when it is ultimatively intended to store the
1516 result in pseudoregister v. If v is assigned to an actual
1517 register, this register will be returned. Otherwise (when v is
1518 spilled) this function returns tempregnum. If not already done,
1519 regoff and flags are set in the stack location.
1521 *******************************************************************************/
1523 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
1527 /* Do we have to generate a conditional move? Yes, then always
1528 return the temporary register. The real register is identified
1529 during the store. */
1531 if (opcode & ICMD_CONDITION_MASK)
1535 if (!(v->flags & INMEMORY))
1536 return v->vv.regoff;
1542 /* codegen_reg_of_dst **********************************************************
1544 This function determines a register, to which the result of an
1545 operation should go, when it is ultimatively intended to store the
1546 result in iptr->dst.var. If dst.var is assigned to an actual
1547 register, this register will be returned. Otherwise (when it is
1548 spilled) this function returns tempregnum. If not already done,
1549 regoff and flags are set in the stack location.
1551 *******************************************************************************/
1553 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
1555 return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
1559 /* codegen_emit_phi_moves ****************************************************
1561 Emits phi moves at the end of the basicblock.
1563 *******************************************************************************/
1565 #if defined(ENABLE_SSA)
1566 void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
1579 /* Moves from phi functions with highest indices have to be */
1580 /* inserted first, since this is the order as is used for */
1581 /* conflict resolution */
1583 for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
1584 lt_d = ls->phi_moves[bptr->nr][i][0];
1585 lt_s = ls->phi_moves[bptr->nr][i][1];
1586 #if defined(SSA_DEBUG_VERBOSE)
1588 printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
1590 if (lt_s == UNUSED) {
1591 #if defined(SSA_DEBUG_VERBOSE)
1593 printf(" ... not processed \n");
1598 d = VAR(ls->lifetime[lt_d].v_index);
1599 s = VAR(ls->lifetime[lt_s].v_index);
1602 if (d->type == -1) {
1603 #if defined(SSA_DEBUG_VERBOSE)
1605 printf("...returning - phi lifetimes where joined\n");
1610 if (s->type == -1) {
1611 #if defined(SSA_DEBUG_VERBOSE)
1613 printf("...returning - phi lifetimes where joined\n");
1619 tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
1620 tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
1621 emit_copy(jd, &tmp_i);
1623 #if defined(SSA_DEBUG_VERBOSE)
1624 if (compileverbose) {
1625 if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
1627 printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1629 else if (IS_INMEMORY(s->flags)) {
1631 printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1633 else if (IS_INMEMORY(d->flags)) {
1635 printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1639 printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1643 #endif /* defined(SSA_DEBUG_VERBOSE) */
1646 #endif /* defined(ENABLE_SSA) */
1651 * These are local overrides for various environment variables in Emacs.
1652 * Please do not remove this and leave it at the end of the file, where
1653 * Emacs will automagically detect them.
1654 * ---------------------------------------------------------------------
1657 * indent-tabs-mode: t
1661 * vim:noexpandtab:sw=4:ts=4: