1 /* src/vm/jit/codegen-common.c - architecture independent code generator stuff
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 All functions assume the following code area / data area layout:
29 | code area | code area grows to higher addresses
31 +-----------+ <-- start of procedure
33 | data area | data area grows to lower addresses
37 The functions first write into a temporary code/data area allocated by
38 "codegen_init". "codegen_finish" copies the code and data area into permanent
39 memory. All functions writing values into the data area return the offset
40 relative the begin of the code area (start of procedure).
52 #if defined(ENABLE_JIT)
53 /* this is required PATCHER_CALL_SIZE */
57 #include "mm/memory.h"
59 #include "toolbox/avl.h"
60 #include "toolbox/list.h"
61 #include "toolbox/logging.h"
63 #include "native/jni.h"
64 #include "native/localref.h"
65 #include "native/native.h"
67 #include "threads/threads-common.h"
69 #include "vm/exceptions.h"
70 #include "vm/stringlocal.h"
72 #include "vm/jit/abi.h"
73 #include "vm/jit/asmpart.h"
74 #include "vm/jit/codegen-common.h"
76 #if defined(ENABLE_DISASSEMBLER)
77 # include "vm/jit/disass.h"
80 #include "vm/jit/dseg.h"
81 #include "vm/jit/emit-common.h"
82 #include "vm/jit/jit.h"
83 #include "vm/jit/md.h"
84 #include "vm/jit/patcher-common.h"
85 #include "vm/jit/replace.h"
86 #if defined(ENABLE_SSA)
87 # include "vm/jit/optimizing/lsra.h"
88 # include "vm/jit/optimizing/ssa.h"
90 #include "vm/jit/stacktrace.h"
92 #if defined(ENABLE_INTRP)
93 #include "vm/jit/intrp/intrp.h"
96 #include "vmcore/method.h"
97 #include "vmcore/options.h"
99 # include "vmcore/statistics.h"
101 #if defined(ENABLE_VMLOG)
102 #include <vmlog_cacao.h>
107 /* in this tree we store all method addresses *********************************/
109 static avl_tree_t *methodtree = NULL;
110 static s4 methodtree_comparator(const void *treenode, const void *node);
113 /* codegen_init ****************************************************************
117 *******************************************************************************/
119 void codegen_init(void)
121 /* this tree is global, not method specific */
124 #if defined(ENABLE_JIT)
125 methodtree_element *mte;
128 methodtree = avl_create(&methodtree_comparator);
130 #if defined(ENABLE_JIT)
131 /* insert asm_vm_call_method */
133 mte = NEW(methodtree_element);
135 mte->startpc = (u1 *) (ptrint) asm_vm_call_method;
136 mte->endpc = (u1 *) (ptrint) asm_vm_call_method_end;
138 avl_insert(methodtree, mte);
139 #endif /* defined(ENABLE_JIT) */
146 /* codegen_setup ***************************************************************
148 Allocates and initialises code area, data area and references.
150 *******************************************************************************/
152 void codegen_setup(jitdata *jd)
157 /* get required compiler data */
162 /* initialize members */
166 cd->mcodebase = DMNEW(u1, MCODEINITSIZE);
167 cd->mcodeend = cd->mcodebase + MCODEINITSIZE;
168 cd->mcodesize = MCODEINITSIZE;
170 /* initialize mcode variables */
172 cd->mcodeptr = cd->mcodebase;
173 cd->lastmcodeptr = cd->mcodebase;
175 #if defined(ENABLE_INTRP)
176 /* native dynamic superinstructions variables */
179 cd->ncodebase = DMNEW(u1, NCODEINITSIZE);
180 cd->ncodesize = NCODEINITSIZE;
182 /* initialize ncode variables */
184 cd->ncodeptr = cd->ncodebase;
186 cd->lastinstwithoutdispatch = ~0; /* no inst without dispatch */
187 cd->superstarts = NULL;
194 cd->jumpreferences = NULL;
196 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
197 cd->datareferences = NULL;
200 /* cd->patchrefs = list_create_dump(OFFSET(patchref, linkage)); */
201 cd->patchrefs = NULL;
202 cd->brancheslabel = list_create_dump(OFFSET(branch_label_ref_t, linkage));
203 cd->listcritical = list_create_dump(OFFSET(critical_section_ref_t, linkage));
205 cd->linenumberreferences = NULL;
206 cd->linenumbertablesizepos = 0;
207 cd->linenumbertablestartpos = 0;
208 cd->linenumbertab = 0;
212 /* codegen_reset ***************************************************************
214 Resets the codegen data structure so we can recompile the method.
216 *******************************************************************************/
218 static void codegen_reset(jitdata *jd)
224 /* get required compiler data */
229 /* reset error flag */
231 cd->flags &= ~CODEGENDATA_FLAG_ERROR;
233 /* reset some members, we reuse the code memory already allocated
234 as this should have almost the correct size */
236 cd->mcodeptr = cd->mcodebase;
237 cd->lastmcodeptr = cd->mcodebase;
242 cd->jumpreferences = NULL;
244 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
245 cd->datareferences = NULL;
248 /* cd->patchrefs = list_create_dump(OFFSET(patchref, linkage)); */
249 cd->patchrefs = NULL;
250 cd->brancheslabel = list_create_dump(OFFSET(branch_label_ref_t, linkage));
251 cd->listcritical = list_create_dump(OFFSET(critical_section_ref_t, linkage));
253 cd->linenumberreferences = NULL;
254 cd->linenumbertablesizepos = 0;
255 cd->linenumbertablestartpos = 0;
256 cd->linenumbertab = 0;
258 /* We need to clear the mpc and the branch references from all
259 basic blocks as they will definitely change. */
261 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
263 bptr->branchrefs = NULL;
266 /* We need to clear all the patcher references from the codeinfo
267 since they all will be regenerated */
269 patcher_list_reset(code);
271 #if defined(ENABLE_REPLACEMENT)
272 code->rplpoints = NULL;
273 code->rplpointcount = 0;
274 code->regalloc = NULL;
275 code->regalloccount = 0;
276 code->globalcount = 0;
281 /* codegen_generate ************************************************************
283 Generates the code for the currently compiled method.
285 *******************************************************************************/
287 bool codegen_generate(jitdata *jd)
291 /* get required compiler data */
295 /* call the machine-dependent code generation function */
297 if (!codegen_emit(jd))
300 /* check for an error */
302 if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
303 /* check for long-branches flag, if it is set we recompile the
308 log_message_method("Re-generating code: ", jd->m);
311 /* XXX maybe we should tag long-branches-methods for recompilation */
313 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
314 /* we have to reset the codegendata structure first */
318 /* and restart the compiler run */
320 if (!codegen_emit(jd))
324 vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
329 log_message_method("Re-generating code done: ", jd->m);
333 /* reallocate the memory and finish the code generation */
337 /* everything's ok */
343 /* codegen_close ***************************************************************
347 *******************************************************************************/
349 void codegen_close(void)
351 /* TODO: release avl tree on i386 and x86_64 */
355 /* codegen_increase ************************************************************
359 *******************************************************************************/
361 void codegen_increase(codegendata *cd)
365 /* save old mcodebase pointer */
367 oldmcodebase = cd->mcodebase;
369 /* reallocate to new, doubled memory */
371 cd->mcodebase = DMREALLOC(cd->mcodebase,
376 cd->mcodeend = cd->mcodebase + cd->mcodesize;
378 /* set new mcodeptr */
380 cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
382 #if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(__M68K__) || defined(ENABLE_INTRP) \
383 || defined(__SPARC_64__)
384 /* adjust the pointer to the last patcher position */
386 if (cd->lastmcodeptr != NULL)
387 cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
392 /* codegen_ncode_increase ******************************************************
396 *******************************************************************************/
398 #if defined(ENABLE_INTRP)
399 u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
403 /* save old ncodebase pointer */
405 oldncodebase = cd->ncodebase;
407 /* reallocate to new, doubled memory */
409 cd->ncodebase = DMREALLOC(cd->ncodebase,
415 /* return the new ncodeptr */
417 return (cd->ncodebase + (ncodeptr - oldncodebase));
422 /* codegen_add_branch_ref ******************************************************
424 Prepends an branch to the list.
426 *******************************************************************************/
428 void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
433 STATISTICS(count_branches_unresolved++);
435 /* calculate the mpc of the branch instruction */
437 branchmpc = cd->mcodeptr - cd->mcodebase;
439 br = DNEW(branchref);
441 br->branchmpc = branchmpc;
442 br->condition = condition;
444 br->options = options;
445 br->next = target->branchrefs;
447 target->branchrefs = br;
451 /* codegen_resolve_branchrefs **************************************************
453 Resolves and patches the branch references of a given basic block.
455 *******************************************************************************/
457 void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
462 /* Save the mcodeptr because in the branch emitting functions
463 we generate code somewhere inside already generated code,
464 but we're still in the actual code generation phase. */
466 mcodeptr = cd->mcodeptr;
468 /* just to make sure */
470 assert(bptr->mpc >= 0);
472 for (br = bptr->branchrefs; br != NULL; br = br->next) {
473 /* temporary set the mcodeptr */
475 cd->mcodeptr = cd->mcodebase + br->branchmpc;
477 /* emit_bccz and emit_branch emit the correct code, even if we
478 pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
480 emit_bccz(cd, bptr, br->condition, br->reg, br->options);
483 /* restore mcodeptr */
485 cd->mcodeptr = mcodeptr;
489 /* codegen_branch_label_add ****************************************************
491 Append an branch to the label-branch list.
493 *******************************************************************************/
495 void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
498 branch_label_ref_t *br;
501 /* get the label list */
503 list = cd->brancheslabel;
505 /* calculate the current mpc */
507 mpc = cd->mcodeptr - cd->mcodebase;
509 br = DNEW(branch_label_ref_t);
513 br->condition = condition;
515 br->options = options;
517 /* add the branch to the list */
519 list_add_last_unsynced(list, br);
523 /* codegen_add_patch_ref *******************************************************
525 Appends a new patcher reference to the list of patching positions.
527 *******************************************************************************/
529 void codegen_add_patch_ref(codegendata *cd, functionptr patcher, voidptr ref,
535 branchmpc = cd->mcodeptr - cd->mcodebase;
539 pr->branchpos = branchmpc;
541 pr->patcher = patcher;
544 /* list_add_first(cd->patchrefs, pr); */
545 pr->next = cd->patchrefs;
548 /* Generate NOPs for opt_shownops. */
553 #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__M68K__) || defined(__MIPS__) \
554 || defined(__SPARC_64__) || defined(__X86_64__))
556 /* On some architectures the patcher stub call instruction might
557 be longer than the actual instruction generated. On this
558 architectures we store the last patcher call position and after
559 the basic block code generation is completed, we check the
560 range and maybe generate some nop's. */
561 /* The nops are generated in codegen_emit in each codegen */
563 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
568 /* codegen_critical_section_new ************************************************
570 Allocates a new critical-section reference and adds it to the
571 critical-section list.
573 *******************************************************************************/
575 #if defined(ENABLE_THREADS)
576 void codegen_critical_section_new(codegendata *cd)
579 critical_section_ref_t *csr;
582 /* get the critical section list */
584 list = cd->listcritical;
586 /* calculate the current mpc */
588 mpc = cd->mcodeptr - cd->mcodebase;
590 csr = DNEW(critical_section_ref_t);
592 /* We only can set restart right now, as start and end are set by
593 the following, corresponding functions. */
599 /* add the branch to the list */
601 list_add_last_unsynced(list, csr);
606 /* codegen_critical_section_start **********************************************
608 Set the start-point of the current critical section (which is the
609 last element of the list).
611 *******************************************************************************/
613 #if defined(ENABLE_THREADS)
614 void codegen_critical_section_start(codegendata *cd)
617 critical_section_ref_t *csr;
620 /* get the critical section list */
622 list = cd->listcritical;
624 /* calculate the current mpc */
626 mpc = cd->mcodeptr - cd->mcodebase;
628 /* get the current critical section */
630 csr = list_last_unsynced(list);
632 /* set the start point */
634 assert(csr->start == -1);
641 /* codegen_critical_section_end ************************************************
643 Set the end-point of the current critical section (which is the
644 last element of the list).
646 *******************************************************************************/
648 #if defined(ENABLE_THREADS)
649 void codegen_critical_section_end(codegendata *cd)
652 critical_section_ref_t *csr;
655 /* get the critical section list */
657 list = cd->listcritical;
659 /* calculate the current mpc */
661 mpc = cd->mcodeptr - cd->mcodebase;
663 /* get the current critical section */
665 csr = list_last_unsynced(list);
667 /* set the end point */
669 assert(csr->end == -1);
676 /* codegen_critical_section_finish *********************************************
678 Finish the critical sections, create the critical section nodes for
679 the AVL tree and insert them into the tree.
681 *******************************************************************************/
683 #if defined(ENABLE_THREADS)
684 static void codegen_critical_section_finish(jitdata *jd)
689 critical_section_ref_t *csr;
690 critical_section_node_t *csn;
692 /* get required compiler data */
697 /* get the critical section list */
699 list = cd->listcritical;
701 /* iterate over all critical sections */
703 for (csr = list_first_unsynced(list); csr != NULL;
704 csr = list_next_unsynced(list, csr)) {
705 /* check if all points are set */
707 assert(csr->start != -1);
708 assert(csr->end != -1);
709 assert(csr->restart != -1);
711 /* allocate tree node */
713 csn = NEW(critical_section_node_t);
715 csn->start = code->entrypoint + csr->start;
716 csn->end = code->entrypoint + csr->end;
717 csn->restart = code->entrypoint + csr->restart;
719 /* insert into the tree */
721 critical_section_register(csn);
727 /* methodtree_comparator *******************************************************
729 Comparator function used for the AVL tree of methods.
732 treenode....the node from the tree
733 node........the node to compare to the tree-node
735 *******************************************************************************/
737 static s4 methodtree_comparator(const void *treenode, const void *node)
739 methodtree_element *mte;
740 methodtree_element *mtepc;
742 mte = (methodtree_element *) treenode;
743 mtepc = (methodtree_element *) node;
745 /* compare both startpc and endpc of pc, even if they have the same value,
746 otherwise the avl_probe sometimes thinks the element is already in the
750 /* On S390 addresses are 31 bit. Compare only 31 bits of value.
752 # define ADDR_MASK(a) ((a) & 0x7FFFFFFF)
754 # define ADDR_MASK(a) (a)
757 if (ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->startpc) &&
758 ADDR_MASK((long) mtepc->startpc) <= ADDR_MASK((long) mte->endpc) &&
759 ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->endpc) &&
760 ADDR_MASK((long) mtepc->endpc) <= ADDR_MASK((long) mte->endpc)) {
763 } else if (ADDR_MASK((long) mtepc->startpc) < ADDR_MASK((long) mte->startpc)) {
774 /* codegen_insertmethod ********************************************************
776 Insert the machine code range of a method into the AVL tree of methods.
778 *******************************************************************************/
780 void codegen_insertmethod(u1 *startpc, u1 *endpc)
782 methodtree_element *mte;
784 /* allocate new method entry */
786 mte = NEW(methodtree_element);
788 mte->startpc = startpc;
791 /* this function does not return an error, but asserts for
794 avl_insert(methodtree, mte);
798 /* codegen_get_pv_from_pc ******************************************************
800 Find the PV for the given PC by searching in the AVL tree of
803 *******************************************************************************/
805 u1 *codegen_get_pv_from_pc(u1 *pc)
807 methodtree_element mtepc;
808 methodtree_element *mte;
810 /* allocation of the search structure on the stack is much faster */
815 mte = avl_find(methodtree, &mtepc);
818 /* No method was found. Let's dump a stacktrace. */
820 #if defined(ENABLE_VMLOG)
821 vmlog_cacao_signl("SIGSEGV");
824 log_println("We received a SIGSEGV and tried to handle it, but we were");
825 log_println("unable to find a Java method at:");
827 #if SIZEOF_VOID_P == 8
828 log_println("PC=0x%016lx", pc);
830 log_println("PC=0x%08x", pc);
834 log_println("Dumping the current stacktrace:");
836 #if defined(ENABLE_THREADS)
837 /* XXX michi: This should be available even without threads! */
838 threads_print_stacktrace();
841 vm_abort("Exiting...");
848 /* codegen_get_pv_from_pc_nocheck **********************************************
850 Find the PV for the given PC by searching in the AVL tree of
851 methods. This method does not check the return value and is used
854 *******************************************************************************/
856 u1 *codegen_get_pv_from_pc_nocheck(u1 *pc)
858 methodtree_element mtepc;
859 methodtree_element *mte;
861 /* allocation of the search structure on the stack is much faster */
866 mte = avl_find(methodtree, &mtepc);
875 /* codegen_set_replacement_point_notrap ****************************************
877 Record the position of a non-trappable replacement point.
879 *******************************************************************************/
881 #if defined(ENABLE_REPLACEMENT)
883 void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
885 void codegen_set_replacement_point_notrap(codegendata *cd)
888 assert(cd->replacementpoint);
889 assert(cd->replacementpoint->type == type);
890 assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
892 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
894 cd->replacementpoint++;
896 #endif /* defined(ENABLE_REPLACEMENT) */
899 /* codegen_set_replacement_point ***********************************************
901 Record the position of a trappable replacement point.
903 *******************************************************************************/
905 #if defined(ENABLE_REPLACEMENT)
907 void codegen_set_replacement_point(codegendata *cd, s4 type)
909 void codegen_set_replacement_point(codegendata *cd)
912 assert(cd->replacementpoint);
913 assert(cd->replacementpoint->type == type);
914 assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
916 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
918 cd->replacementpoint++;
920 /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
922 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
924 #endif /* defined(ENABLE_REPLACEMENT) */
927 /* codegen_finish **************************************************************
929 Finishes the code generation. A new memory, large enough for both
930 data and code, is allocated and data and code are copied together
931 to their final layout, unresolved jumps are resolved, ...
933 *******************************************************************************/
935 void codegen_finish(jitdata *jd)
940 #if defined(ENABLE_INTRP)
949 /* get required compiler data */
954 /* prevent compiler warning */
956 #if defined(ENABLE_INTRP)
960 /* calculate the code length */
962 mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
964 #if defined(ENABLE_STATISTICS)
966 count_code_len += mcodelen;
967 count_data_len += cd->dseglen;
971 alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
973 #if defined(ENABLE_INTRP)
975 ncodelen = cd->ncodeptr - cd->ncodebase;
977 ncodelen = 0; /* avoid compiler warning */
981 cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
982 alignedlen = alignedmcodelen + cd->dseglen;
984 #if defined(ENABLE_INTRP)
986 alignedlen += ncodelen;
990 /* allocate new memory */
992 code->mcodelength = mcodelen + cd->dseglen;
993 code->mcode = CNEW(u1, alignedlen);
995 /* set the entrypoint of the method */
997 assert(code->entrypoint == NULL);
998 code->entrypoint = epoint = (code->mcode + cd->dseglen);
1000 /* fill the data segment (code->entrypoint must already be set!) */
1004 /* copy code to the new location */
1006 MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
1008 #if defined(ENABLE_INTRP)
1009 /* relocate native dynamic superinstruction code (if any) */
1012 cd->mcodebase = code->entrypoint;
1015 u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
1017 MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
1019 /* flush the instruction and data caches */
1021 md_cacheflush(ncodebase, ncodelen);
1023 /* set some cd variables for dynamic_super_rerwite */
1025 cd->ncodebase = ncodebase;
1028 cd->ncodebase = NULL;
1031 dynamic_super_rewrite(cd);
1035 /* jump table resolving */
1037 for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
1038 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
1039 (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
1041 /* line number table resolving */
1047 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
1049 target = lr->targetmpc;
1050 /* if the entry contains an mcode pointer (normal case), resolve it */
1051 /* (see doc/inlining_stacktrace.txt for details) */
1052 if (lr->linenumber >= -2) {
1053 target += (ptrint) epoint;
1055 *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) =
1056 (functionptr) target;
1059 *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
1060 (functionptr) ((ptrint) epoint + cd->linenumbertab);
1062 *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
1065 /* patcher resolving */
1067 pr = list_first_unsynced(code->patchers);
1069 pr->mpc += (ptrint) epoint;
1070 pr->datap = (ptrint) (pr->disp + epoint);
1071 pr = list_next_unsynced(code->patchers, pr);
1074 #if defined(ENABLE_REPLACEMENT)
1075 /* replacement point resolving */
1080 rp = code->rplpoints;
1081 for (i=0; i<code->rplpointcount; ++i, ++rp) {
1082 rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
1085 #endif /* defined(ENABLE_REPLACEMENT) */
1087 /* add method into methodtree to find the entrypoint */
1089 codegen_insertmethod(code->entrypoint, code->entrypoint + mcodelen);
1091 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
1092 /* resolve data segment references */
1094 dseg_resolve_datareferences(jd);
1097 #if defined(ENABLE_THREADS)
1098 /* create cirtical sections */
1100 codegen_critical_section_finish(jd);
1103 /* flush the instruction and data caches */
1105 md_cacheflush(code->mcode, code->mcodelength);
1109 /* codegen_generate_stub_compiler **********************************************
1111 Wrapper for codegen_emit_stub_compiler.
1114 pointer to the compiler stub code.
1116 *******************************************************************************/
1118 u1 *codegen_generate_stub_compiler(methodinfo *m)
1122 ptrint *d; /* pointer to data memory */
1123 u1 *c; /* pointer to code memory */
1126 /* mark dump memory */
1128 dumpsize = dump_size();
1130 /* allocate required data structures */
1135 jd->cd = DNEW(codegendata);
1138 /* get required compiler data */
1142 /* allocate code memory */
1144 c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1146 /* set pointers correctly */
1152 c = c + 3 * SIZEOF_VOID_P;
1155 /* NOTE: The codeinfo pointer is actually a pointer to the
1156 methodinfo (this fakes a codeinfo structure). */
1158 d[0] = (ptrint) asm_call_jit_compiler;
1160 d[2] = (ptrint) &d[1]; /* fake code->m */
1162 /* call the emit function */
1164 codegen_emit_stub_compiler(jd);
1166 #if defined(ENABLE_STATISTICS)
1168 count_cstub_len += 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
1173 md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1175 /* release dump memory */
1177 dump_release(dumpsize);
1179 /* return native stub code */
1185 /* codegen_generate_stub_native ************************************************
1187 Wrapper for codegen_emit_stub_native.
1190 the codeinfo representing the stub code.
1192 *******************************************************************************/
1194 codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
1203 /* mark dump memory */
1205 dumpsize = dump_size();
1210 jd->cd = DNEW(codegendata);
1211 jd->rd = DNEW(registerdata);
1214 /* Allocate codeinfo memory from the heap as we need to keep them. */
1216 jd->code = code_codeinfo_new(m); /* XXX check allocation */
1218 /* get required compiler data */
1222 /* set the flags for the current JIT run */
1224 #if defined(ENABLE_PROFILING)
1226 jd->flags |= JITDATA_FLAG_INSTRUMENT;
1229 if (opt_verbosecall)
1230 jd->flags |= JITDATA_FLAG_VERBOSECALL;
1232 /* setup code generation stuff */
1234 #if defined(ENABLE_JIT)
1235 # if defined(ENABLE_INTRP)
1243 /* create new method descriptor with additional native parameters */
1246 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
1248 nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
1249 md->paramcount * sizeof(typedesc) +
1250 nativeparams * sizeof(typedesc));
1252 nmd->paramcount = md->paramcount + nativeparams;
1254 nmd->params = DMNEW(paramdesc, nmd->paramcount);
1256 nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer */
1258 if (m->flags & ACC_STATIC)
1259 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer */
1261 MCOPY(nmd->paramtypes + nativeparams, md->paramtypes, typedesc,
1264 #if defined(ENABLE_JIT)
1265 # if defined(ENABLE_INTRP)
1268 /* pre-allocate the arguments for the native ABI */
1270 md_param_alloc_native(nmd);
1273 /* generate the code */
1275 #if defined(ENABLE_JIT)
1276 # if defined(ENABLE_INTRP)
1278 intrp_createnativestub(f, jd, nmd);
1281 codegen_emit_stub_native(jd, nmd, f);
1283 intrp_createnativestub(f, jd, nmd);
1286 /* reallocate the memory and finish the code generation */
1290 #if defined(ENABLE_STATISTICS)
1291 /* must be done after codegen_finish() */
1294 size_stub_native += code->mcodelength;
1297 #if !defined(NDEBUG)
1298 /* disassemble native stub */
1300 if (opt_shownativestub) {
1301 #if defined(ENABLE_DEBUG_FILTER)
1302 if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
1305 #if defined(ENABLE_DISASSEMBLER)
1306 codegen_disassemble_nativestub(m,
1307 (u1 *) (ptrint) code->entrypoint,
1308 (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
1311 /* show data segment */
1313 if (opt_showddatasegment)
1317 #endif /* !defined(NDEBUG) */
1319 /* release memory */
1321 dump_release(dumpsize);
1323 /* return native stub code */
1329 /* codegen_disassemble_nativestub **********************************************
1331 Disassembles the generated native stub.
1333 *******************************************************************************/
1335 #if defined(ENABLE_DISASSEMBLER)
1336 void codegen_disassemble_nativestub(methodinfo *m, u1 *start, u1 *end)
1338 printf("Native stub: ");
1339 utf_fprint_printable_ascii_classname(stdout, m->class->name);
1341 utf_fprint_printable_ascii(stdout, m->name);
1342 utf_fprint_printable_ascii(stdout, m->descriptor);
1343 printf("\n\nLength: %d\n\n", (s4) (end - start));
1345 DISASSEMBLE(start, end);
1350 /* codegen_start_native_call ***************************************************
1352 Prepares the stuff required for a native (JNI) function call:
1354 - adds a stackframe info structure to the chain, for stacktraces
1355 - prepares the local references table on the stack
1357 The layout of the native stub stackframe should look like this:
1359 +---------------------------+ <- SP (of parent Java function)
1361 +---------------------------+
1363 | stackframe info structure |
1365 +---------------------------+
1367 | local references table |
1369 +---------------------------+
1371 | arguments (if any) |
1373 +---------------------------+ <- SP (native stub)
1375 *******************************************************************************/
1377 void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
1379 stackframeinfo *sfi;
1380 localref_table *lrt;
1382 STATISTICS(count_calls_java_to_native++);
1384 /* get data structures from stack */
1386 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1387 lrt = (localref_table *) (datasp - sizeof(stackframeinfo) -
1388 sizeof(localref_table));
1390 /* add a stackframeinfo to the chain */
1392 stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
1394 #if defined(ENABLE_JNI)
1395 /* add current JNI local references table to this thread */
1397 localref_table_add(lrt);
1402 /* codegen_finish_native_call **************************************************
1404 Removes the stuff required for a native (JNI) function call.
1405 Additionally it checks for an exceptions and in case, get the
1406 exception object and clear the pointer.
1408 *******************************************************************************/
1410 java_object_t *codegen_finish_native_call(u1 *datasp)
1412 stackframeinfo *sfi;
1413 stackframeinfo **psfi;
1416 /* get data structures from stack */
1418 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1420 /* remove current stackframeinfo from chain */
1422 psfi = &STACKFRAMEINFO;
1426 #if defined(ENABLE_JNI)
1427 /* release JNI local references table for this thread */
1429 localref_frame_pop_all();
1430 localref_table_remove();
1433 /* get the exception and return it */
1435 e = exceptions_get_and_clear_exception();
1441 /* removecompilerstub **********************************************************
1443 Deletes a compilerstub from memory (simply by freeing it).
1445 *******************************************************************************/
1447 void removecompilerstub(u1 *stub)
1449 /* pass size 1 to keep the intern function happy */
1451 CFREE((void *) stub, 1);
1455 /* removenativestub ************************************************************
1457 Removes a previously created native-stub from memory.
1459 *******************************************************************************/
1461 void removenativestub(u1 *stub)
1463 /* pass size 1 to keep the intern function happy */
1465 CFREE((void *) stub, 1);
1469 /* codegen_reg_of_var **********************************************************
1471 This function determines a register, to which the result of an
1472 operation should go, when it is ultimatively intended to store the
1473 result in pseudoregister v. If v is assigned to an actual
1474 register, this register will be returned. Otherwise (when v is
1475 spilled) this function returns tempregnum. If not already done,
1476 regoff and flags are set in the stack location.
1478 *******************************************************************************/
1480 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
1484 /* Do we have to generate a conditional move? Yes, then always
1485 return the temporary register. The real register is identified
1486 during the store. */
1488 if (opcode & ICMD_CONDITION_MASK)
1492 if (!(v->flags & INMEMORY))
1493 return v->vv.regoff;
1499 /* codegen_reg_of_dst **********************************************************
1501 This function determines a register, to which the result of an
1502 operation should go, when it is ultimatively intended to store the
1503 result in iptr->dst.var. If dst.var is assigned to an actual
1504 register, this register will be returned. Otherwise (when it is
1505 spilled) this function returns tempregnum. If not already done,
1506 regoff and flags are set in the stack location.
1508 *******************************************************************************/
1510 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
1512 return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
1516 /* codegen_emit_phi_moves ****************************************************
1518 Emits phi moves at the end of the basicblock.
1520 *******************************************************************************/
1522 #if defined(ENABLE_SSA)
1523 void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
1536 /* Moves from phi functions with highest indices have to be */
1537 /* inserted first, since this is the order as is used for */
1538 /* conflict resolution */
1540 for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
1541 lt_d = ls->phi_moves[bptr->nr][i][0];
1542 lt_s = ls->phi_moves[bptr->nr][i][1];
1543 #if defined(SSA_DEBUG_VERBOSE)
1545 printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
1547 if (lt_s == UNUSED) {
1548 #if defined(SSA_DEBUG_VERBOSE)
1550 printf(" ... not processed \n");
1555 d = VAR(ls->lifetime[lt_d].v_index);
1556 s = VAR(ls->lifetime[lt_s].v_index);
1559 if (d->type == -1) {
1560 #if defined(SSA_DEBUG_VERBOSE)
1562 printf("...returning - phi lifetimes where joined\n");
1567 if (s->type == -1) {
1568 #if defined(SSA_DEBUG_VERBOSE)
1570 printf("...returning - phi lifetimes where joined\n");
1576 tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
1577 tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
1578 emit_copy(jd, &tmp_i);
1580 #if defined(SSA_DEBUG_VERBOSE)
1581 if (compileverbose) {
1582 if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
1584 printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1586 else if (IS_INMEMORY(s->flags)) {
1588 printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1590 else if (IS_INMEMORY(d->flags)) {
1592 printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1596 printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1600 #endif /* defined(SSA_DEBUG_VERBOSE) */
1603 #endif /* defined(ENABLE_SSA) */
1608 * These are local overrides for various environment variables in Emacs.
1609 * Please do not remove this and leave it at the end of the file, where
1610 * Emacs will automagically detect them.
1611 * ---------------------------------------------------------------------
1614 * indent-tabs-mode: t
1618 * vim:noexpandtab:sw=4:ts=4: