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 8123 2007-06-20 23:50:55Z 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/builtin.h"
71 #include "vm/exceptions.h"
72 #include "vm/stringlocal.h"
74 #include "vm/jit/abi.h"
75 #include "vm/jit/asmpart.h"
76 #include "vm/jit/codegen-common.h"
78 #if defined(ENABLE_DISASSEMBLER)
79 # include "vm/jit/disass.h"
82 #include "vm/jit/dseg.h"
83 #include "vm/jit/emit-common.h"
84 #include "vm/jit/jit.h"
85 #include "vm/jit/md.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)
952 /* get required compiler data */
957 /* prevent compiler warning */
959 #if defined(ENABLE_INTRP)
963 /* calculate the code length */
965 mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
967 #if defined(ENABLE_STATISTICS)
969 count_code_len += mcodelen;
970 count_data_len += cd->dseglen;
974 alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
976 #if defined(ENABLE_INTRP)
978 ncodelen = cd->ncodeptr - cd->ncodebase;
980 ncodelen = 0; /* avoid compiler warning */
984 cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
985 alignedlen = alignedmcodelen + cd->dseglen;
987 #if defined(ENABLE_INTRP)
989 alignedlen += ncodelen;
993 /* allocate new memory */
995 code->mcodelength = mcodelen + cd->dseglen;
996 code->mcode = CNEW(u1, alignedlen);
998 /* set the entrypoint of the method */
1000 assert(code->entrypoint == NULL);
1001 code->entrypoint = epoint = (code->mcode + cd->dseglen);
1003 /* fill the data segment (code->entrypoint must already be set!) */
1007 /* copy code to the new location */
1009 MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
1011 #if defined(ENABLE_INTRP)
1012 /* relocate native dynamic superinstruction code (if any) */
1015 cd->mcodebase = code->entrypoint;
1018 u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
1020 MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
1022 /* flush the instruction and data caches */
1024 md_cacheflush(ncodebase, ncodelen);
1026 /* set some cd variables for dynamic_super_rerwite */
1028 cd->ncodebase = ncodebase;
1031 cd->ncodebase = NULL;
1034 dynamic_super_rewrite(cd);
1038 /* jump table resolving */
1040 for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
1041 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
1042 (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
1044 /* line number table resolving */
1050 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
1052 target = lr->targetmpc;
1053 /* if the entry contains an mcode pointer (normal case), resolve it */
1054 /* (see doc/inlining_stacktrace.txt for details) */
1055 if (lr->linenumber >= -2) {
1056 target += (ptrint) epoint;
1058 *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) =
1059 (functionptr) target;
1062 *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
1063 (functionptr) ((ptrint) epoint + cd->linenumbertab);
1065 *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
1068 #if defined(ENABLE_REPLACEMENT)
1069 /* replacement point resolving */
1074 code->replacementstubs += (ptrint) epoint;
1076 rp = code->rplpoints;
1077 for (i=0; i<code->rplpointcount; ++i, ++rp) {
1078 rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
1081 #endif /* defined(ENABLE_REPLACEMENT) */
1083 /* add method into methodtree to find the entrypoint */
1085 codegen_insertmethod(code->entrypoint, code->entrypoint + mcodelen);
1087 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
1088 /* resolve data segment references */
1090 dseg_resolve_datareferences(jd);
1093 #if defined(ENABLE_THREADS)
1094 /* create cirtical sections */
1096 codegen_critical_section_finish(jd);
1099 /* flush the instruction and data caches */
1101 md_cacheflush(code->mcode, code->mcodelength);
1105 /* codegen_generate_stub_compiler **********************************************
1107 Wrapper for codegen_emit_stub_compiler.
1110 pointer to the compiler stub code.
1112 *******************************************************************************/
1114 u1 *codegen_generate_stub_compiler(methodinfo *m)
1118 ptrint *d; /* pointer to data memory */
1119 u1 *c; /* pointer to code memory */
1122 /* mark dump memory */
1124 dumpsize = dump_size();
1126 /* allocate required data structures */
1131 jd->cd = DNEW(codegendata);
1134 /* get required compiler data */
1138 /* allocate code memory */
1140 c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1142 /* set pointers correctly */
1148 c = c + 3 * SIZEOF_VOID_P;
1151 /* NOTE: The codeinfo pointer is actually a pointer to the
1152 methodinfo (this fakes a codeinfo structure). */
1154 d[0] = (ptrint) asm_call_jit_compiler;
1156 d[2] = (ptrint) &d[1]; /* fake code->m */
1158 /* call the emit function */
1160 codegen_emit_stub_compiler(jd);
1162 #if defined(ENABLE_STATISTICS)
1164 count_cstub_len += 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
1169 md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1171 /* release dump memory */
1173 dump_release(dumpsize);
1175 /* return native stub code */
1181 /* codegen_generate_stub_builtin ***********************************************
1183 Wrapper for codegen_emit_stub_builtin.
1186 Pointer to the entrypoint of the stub.
1188 *******************************************************************************/
1190 void codegen_generate_stub_builtin(builtintable_entry *bte)
1196 /* mark dump memory */
1198 dumpsize = dump_size();
1203 jd->cd = DNEW(codegendata);
1207 /* Allocate codeinfo memory from the heap as we need to keep them. */
1209 jd->code = code_codeinfo_new(NULL);
1211 /* get required compiler data */
1215 /* setup code generation stuff */
1219 /* generate the code */
1221 #if defined(ENABLE_JIT)
1222 # if defined(ENABLE_INTRP)
1225 codegen_emit_stub_builtin(jd, bte);
1228 /* reallocate the memory and finish the code generation */
1232 /* set the stub entry point in the builtin table */
1234 bte->stub = code->entrypoint;
1236 #if defined(ENABLE_STATISTICS)
1238 size_stub_native += code->mcodelength;
1241 /* release memory */
1243 dump_release(dumpsize);
1247 /* codegen_generate_stub_native ************************************************
1249 Wrapper for codegen_emit_stub_native.
1252 the codeinfo representing the stub code.
1254 *******************************************************************************/
1256 codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
1265 /* mark dump memory */
1267 dumpsize = dump_size();
1272 jd->cd = DNEW(codegendata);
1273 jd->rd = DNEW(registerdata);
1276 /* Allocate codeinfo memory from the heap as we need to keep them. */
1278 jd->code = code_codeinfo_new(m); /* XXX check allocation */
1280 /* get required compiler data */
1284 /* set the flags for the current JIT run */
1286 #if defined(ENABLE_PROFILING)
1288 jd->flags |= JITDATA_FLAG_INSTRUMENT;
1291 if (opt_verbosecall)
1292 jd->flags |= JITDATA_FLAG_VERBOSECALL;
1294 /* setup code generation stuff */
1296 #if defined(ENABLE_JIT)
1297 # if defined(ENABLE_INTRP)
1305 /* create new method descriptor with additional native parameters */
1308 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
1310 nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
1311 md->paramcount * sizeof(typedesc) +
1312 nativeparams * sizeof(typedesc));
1314 nmd->paramcount = md->paramcount + nativeparams;
1316 nmd->params = DMNEW(paramdesc, nmd->paramcount);
1318 nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer */
1320 if (m->flags & ACC_STATIC)
1321 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer */
1323 MCOPY(nmd->paramtypes + nativeparams, md->paramtypes, typedesc,
1326 #if defined(ENABLE_JIT)
1327 # if defined(ENABLE_INTRP)
1330 /* pre-allocate the arguments for the native ABI */
1332 md_param_alloc_native(nmd);
1335 /* generate the code */
1337 #if defined(ENABLE_JIT)
1338 # if defined(ENABLE_INTRP)
1340 intrp_createnativestub(f, jd, nmd);
1343 codegen_emit_stub_native(jd, nmd, f);
1345 intrp_createnativestub(f, jd, nmd);
1348 /* reallocate the memory and finish the code generation */
1352 #if defined(ENABLE_STATISTICS)
1353 /* must be done after codegen_finish() */
1356 size_stub_native += code->mcodelength;
1359 #if !defined(NDEBUG)
1360 /* disassemble native stub */
1362 if (opt_shownativestub) {
1363 #if defined(ENABLE_DEBUG_FILTER)
1364 if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
1367 #if defined(ENABLE_DISASSEMBLER)
1368 codegen_disassemble_nativestub(m,
1369 (u1 *) (ptrint) code->entrypoint,
1370 (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
1373 /* show data segment */
1375 if (opt_showddatasegment)
1379 #endif /* !defined(NDEBUG) */
1381 /* release memory */
1383 dump_release(dumpsize);
1385 /* return native stub code */
1391 /* codegen_disassemble_nativestub **********************************************
1393 Disassembles the generated native stub.
1395 *******************************************************************************/
1397 #if defined(ENABLE_DISASSEMBLER)
1398 void codegen_disassemble_nativestub(methodinfo *m, u1 *start, u1 *end)
1400 printf("Native stub: ");
1401 utf_fprint_printable_ascii_classname(stdout, m->class->name);
1403 utf_fprint_printable_ascii(stdout, m->name);
1404 utf_fprint_printable_ascii(stdout, m->descriptor);
1405 printf("\n\nLength: %d\n\n", (s4) (end - start));
1407 DISASSEMBLE(start, end);
1412 /* codegen_stub_builtin_enter **************************************************
1414 Prepares the stuff required for a builtin function call:
1416 - adds a stackframe info structure to the chain, for stacktraces
1418 The layout of the builtin stub stackframe should look like this:
1420 +---------------------------+ <- SP (of parent Java function)
1422 +---------------------------+
1424 | stackframe info structure |
1426 +---------------------------+
1428 | arguments (if any) |
1430 +---------------------------+ <- SP (native stub)
1432 *******************************************************************************/
1434 void codegen_stub_builtin_enter(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
1436 stackframeinfo *sfi;
1438 /* get data structures from stack */
1440 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1442 /* add a stackframeinfo to the chain */
1444 stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
1446 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1447 /* set the native world flag */
1449 THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE;
1454 /* codegen_stub_builtin_exit ***************************************************
1456 Removes the stuff required for a builtin function call.
1458 *******************************************************************************/
1460 void codegen_stub_builtin_exit(u1 *datasp)
1462 stackframeinfo *sfi;
1463 stackframeinfo **psfi;
1465 /* get data structures from stack */
1467 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1469 /* remove current stackframeinfo from chain */
1471 psfi = &STACKFRAMEINFO;
1475 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1476 /* clear the native world flag */
1478 THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE;
1483 /* codegen_start_native_call ***************************************************
1485 Prepares the stuff required for a native (JNI) function call:
1487 - adds a stackframe info structure to the chain, for stacktraces
1488 - prepares the local references table on the stack
1490 The layout of the native stub stackframe should look like this:
1492 +---------------------------+ <- SP (of parent Java function)
1494 +---------------------------+
1496 | stackframe info structure |
1498 +---------------------------+
1500 | local references table |
1502 +---------------------------+
1504 | arguments (if any) |
1506 +---------------------------+ <- SP (native stub)
1508 *******************************************************************************/
1510 void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
1512 stackframeinfo *sfi;
1513 localref_table *lrt;
1515 STATISTICS(count_calls_java_to_native++);
1517 /* get data structures from stack */
1519 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1520 lrt = (localref_table *) (datasp - sizeof(stackframeinfo) -
1521 sizeof(localref_table));
1523 /* add a stackframeinfo to the chain */
1525 stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
1527 #if defined(ENABLE_JNI)
1528 /* add current JNI local references table to this thread */
1530 lrt->capacity = LOCALREFTABLE_CAPACITY;
1532 lrt->localframes = 1;
1533 lrt->prev = LOCALREFTABLE;
1535 /* clear the references array (memset is faster the a for-loop) */
1537 MSET(lrt->refs, 0, java_objectheader*, LOCALREFTABLE_CAPACITY);
1539 LOCALREFTABLE = lrt;
1542 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1543 /* set the native world flag */
1545 THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE;
1550 /* codegen_finish_native_call **************************************************
1552 Removes the stuff required for a native (JNI) function call.
1553 Additionally it checks for an exceptions and in case, get the
1554 exception object and clear the pointer.
1556 *******************************************************************************/
1558 java_objectheader *codegen_finish_native_call(u1 *datasp)
1560 stackframeinfo *sfi;
1561 stackframeinfo **psfi;
1562 #if defined(ENABLE_JNI)
1563 localref_table *lrt;
1564 localref_table *plrt;
1567 java_objectheader *e;
1569 /* get data structures from stack */
1571 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1573 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1574 /* clear the native world flag */
1576 THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE;
1579 /* remove current stackframeinfo from chain */
1581 psfi = &STACKFRAMEINFO;
1585 #if defined(ENABLE_JNI)
1586 /* release JNI local references tables for this thread */
1588 lrt = LOCALREFTABLE;
1590 /* release all current local frames */
1592 for (localframes = lrt->localframes; localframes >= 1; localframes--) {
1593 /* get previous frame */
1597 /* Clear all reference entries (only for tables allocated on
1600 if (localframes > 1)
1601 MSET(&lrt->refs[0], 0, java_objectheader*, lrt->capacity);
1605 /* set new local references table */
1610 /* now store the previous local frames in the thread structure */
1612 LOCALREFTABLE = lrt;
1615 /* get the exception and return it */
1617 e = exceptions_get_and_clear_exception();
1623 /* removecompilerstub **********************************************************
1625 Deletes a compilerstub from memory (simply by freeing it).
1627 *******************************************************************************/
1629 void removecompilerstub(u1 *stub)
1631 /* pass size 1 to keep the intern function happy */
1633 CFREE((void *) stub, 1);
1637 /* removenativestub ************************************************************
1639 Removes a previously created native-stub from memory.
1641 *******************************************************************************/
1643 void removenativestub(u1 *stub)
1645 /* pass size 1 to keep the intern function happy */
1647 CFREE((void *) stub, 1);
1651 /* codegen_reg_of_var **********************************************************
1653 This function determines a register, to which the result of an
1654 operation should go, when it is ultimatively intended to store the
1655 result in pseudoregister v. If v is assigned to an actual
1656 register, this register will be returned. Otherwise (when v is
1657 spilled) this function returns tempregnum. If not already done,
1658 regoff and flags are set in the stack location.
1660 *******************************************************************************/
1662 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
1666 /* Do we have to generate a conditional move? Yes, then always
1667 return the temporary register. The real register is identified
1668 during the store. */
1670 if (opcode & ICMD_CONDITION_MASK)
1674 if (!(v->flags & INMEMORY))
1675 return v->vv.regoff;
1681 /* codegen_reg_of_dst **********************************************************
1683 This function determines a register, to which the result of an
1684 operation should go, when it is ultimatively intended to store the
1685 result in iptr->dst.var. If dst.var is assigned to an actual
1686 register, this register will be returned. Otherwise (when it is
1687 spilled) this function returns tempregnum. If not already done,
1688 regoff and flags are set in the stack location.
1690 *******************************************************************************/
1692 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
1694 return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
1698 /* codegen_emit_phi_moves ****************************************************
1700 Emits phi moves at the end of the basicblock.
1702 *******************************************************************************/
1704 #if defined(ENABLE_SSA)
1705 void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
1718 /* Moves from phi functions with highest indices have to be */
1719 /* inserted first, since this is the order as is used for */
1720 /* conflict resolution */
1722 for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
1723 lt_d = ls->phi_moves[bptr->nr][i][0];
1724 lt_s = ls->phi_moves[bptr->nr][i][1];
1725 #if defined(SSA_DEBUG_VERBOSE)
1727 printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
1729 if (lt_s == UNUSED) {
1730 #if defined(SSA_DEBUG_VERBOSE)
1732 printf(" ... not processed \n");
1737 d = VAR(ls->lifetime[lt_d].v_index);
1738 s = VAR(ls->lifetime[lt_s].v_index);
1741 if (d->type == -1) {
1742 #if defined(SSA_DEBUG_VERBOSE)
1744 printf("...returning - phi lifetimes where joined\n");
1749 if (s->type == -1) {
1750 #if defined(SSA_DEBUG_VERBOSE)
1752 printf("...returning - phi lifetimes where joined\n");
1758 tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
1759 tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
1760 emit_copy(jd, &tmp_i);
1762 #if defined(SSA_DEBUG_VERBOSE)
1763 if (compileverbose) {
1764 if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
1766 printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1768 else if (IS_INMEMORY(s->flags)) {
1770 printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1772 else if (IS_INMEMORY(d->flags)) {
1774 printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1778 printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1782 #endif /* defined(SSA_DEBUG_VERBOSE) */
1785 #endif /* defined(ENABLE_SSA) */
1790 * These are local overrides for various environment variables in Emacs.
1791 * Please do not remove this and leave it at the end of the file, where
1792 * Emacs will automagically detect them.
1793 * ---------------------------------------------------------------------
1796 * indent-tabs-mode: t
1800 * vim:noexpandtab:sw=4:ts=4: