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 7864 2007-05-03 21:17:26Z twisti $
54 #if defined(ENABLE_JIT)
55 /* this is required PATCHER_CALL_SIZE */
60 /* this is required for REG_SPLIT */
64 #include "mm/memory.h"
66 #include "toolbox/avl.h"
67 #include "toolbox/list.h"
68 #include "toolbox/logging.h"
70 #include "native/jni.h"
71 #include "native/native.h"
73 #include "threads/threads-common.h"
75 #include "vm/exceptions.h"
76 #include "vm/stringlocal.h"
78 #include "vm/jit/abi.h"
79 #include "vm/jit/asmpart.h"
80 #include "vm/jit/codegen-common.h"
82 #if defined(ENABLE_DISASSEMBLER)
83 # include "vm/jit/disass.h"
86 #include "vm/jit/dseg.h"
87 #include "vm/jit/emit-common.h"
88 #include "vm/jit/jit.h"
89 #include "vm/jit/md.h"
90 #include "vm/jit/replace.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>
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) */
144 /* codegen_setup ***************************************************************
146 Allocates and initialises code area, data area and references.
148 *******************************************************************************/
150 void codegen_setup(jitdata *jd)
155 /* get required compiler data */
160 /* initialize members */
164 cd->mcodebase = DMNEW(u1, MCODEINITSIZE);
165 cd->mcodeend = cd->mcodebase + MCODEINITSIZE;
166 cd->mcodesize = MCODEINITSIZE;
168 /* initialize mcode variables */
170 cd->mcodeptr = cd->mcodebase;
171 cd->lastmcodeptr = cd->mcodebase;
173 #if defined(ENABLE_INTRP)
174 /* native dynamic superinstructions variables */
177 cd->ncodebase = DMNEW(u1, NCODEINITSIZE);
178 cd->ncodesize = NCODEINITSIZE;
180 /* initialize ncode variables */
182 cd->ncodeptr = cd->ncodebase;
184 cd->lastinstwithoutdispatch = ~0; /* no inst without dispatch */
185 cd->superstarts = NULL;
192 cd->jumpreferences = NULL;
194 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
195 cd->datareferences = NULL;
198 /* cd->patchrefs = list_create_dump(OFFSET(patchref, linkage)); */
199 cd->patchrefs = NULL;
200 cd->brancheslabel = list_create_dump(OFFSET(branch_label_ref_t, linkage));
201 cd->listcritical = list_create_dump(OFFSET(critical_section_ref_t, linkage));
203 cd->linenumberreferences = NULL;
204 cd->linenumbertablesizepos = 0;
205 cd->linenumbertablestartpos = 0;
206 cd->linenumbertab = 0;
210 /* codegen_reset ***************************************************************
212 Resets the codegen data structure so we can recompile the method.
214 *******************************************************************************/
216 static void codegen_reset(jitdata *jd)
222 /* get required compiler data */
227 /* reset error flag */
229 cd->flags &= ~CODEGENDATA_FLAG_ERROR;
231 /* reset some members, we reuse the code memory already allocated
232 as this should have almost the correct size */
234 cd->mcodeptr = cd->mcodebase;
235 cd->lastmcodeptr = cd->mcodebase;
240 cd->jumpreferences = NULL;
242 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
243 cd->datareferences = NULL;
246 /* cd->patchrefs = list_create_dump(OFFSET(patchref, linkage)); */
247 cd->patchrefs = NULL;
248 cd->brancheslabel = list_create_dump(OFFSET(branch_label_ref_t, linkage));
249 cd->listcritical = list_create_dump(OFFSET(critical_section_ref_t, linkage));
251 cd->linenumberreferences = NULL;
252 cd->linenumbertablesizepos = 0;
253 cd->linenumbertablestartpos = 0;
254 cd->linenumbertab = 0;
256 /* We need to clear the mpc and the branch references from all
257 basic blocks as they will definitely change. */
259 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
261 bptr->branchrefs = NULL;
264 #if defined(ENABLE_REPLACEMENT)
265 code->rplpoints = NULL;
266 code->rplpointcount = 0;
267 code->regalloc = NULL;
268 code->regalloccount = 0;
269 code->globalcount = 0;
274 /* codegen_generate ************************************************************
276 Generates the code for the currently compiled method.
278 *******************************************************************************/
280 bool codegen_generate(jitdata *jd)
284 /* get required compiler data */
288 /* call the machine-dependent code generation function */
290 if (!codegen_emit(jd))
293 /* check for an error */
295 if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
296 /* check for long-branches flag, if it is set we recompile the
301 log_message_method("Re-generating code: ", jd->m);
304 /* XXX maybe we should tag long-branches-methods for recompilation */
306 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
307 /* we have to reset the codegendata structure first */
311 /* and restart the compiler run */
313 if (!codegen_emit(jd))
317 vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
322 log_message_method("Re-generating code done: ", jd->m);
326 /* reallocate the memory and finish the code generation */
330 /* everything's ok */
336 /* codegen_close ***************************************************************
340 *******************************************************************************/
342 void codegen_close(void)
344 /* TODO: release avl tree on i386 and x86_64 */
348 /* codegen_increase ************************************************************
352 *******************************************************************************/
354 void codegen_increase(codegendata *cd)
358 /* save old mcodebase pointer */
360 oldmcodebase = cd->mcodebase;
362 /* reallocate to new, doubled memory */
364 cd->mcodebase = DMREALLOC(cd->mcodebase,
369 cd->mcodeend = cd->mcodebase + cd->mcodesize;
371 /* set new mcodeptr */
373 cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
375 #if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(ENABLE_INTRP)
376 /* adjust the pointer to the last patcher position */
378 if (cd->lastmcodeptr != NULL)
379 cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
384 /* codegen_ncode_increase ******************************************************
388 *******************************************************************************/
390 #if defined(ENABLE_INTRP)
391 u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
395 /* save old ncodebase pointer */
397 oldncodebase = cd->ncodebase;
399 /* reallocate to new, doubled memory */
401 cd->ncodebase = DMREALLOC(cd->ncodebase,
407 /* return the new ncodeptr */
409 return (cd->ncodebase + (ncodeptr - oldncodebase));
414 /* codegen_add_branch_ref ******************************************************
416 Prepends an branch to the list.
418 *******************************************************************************/
420 void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
425 STATISTICS(count_branches_unresolved++);
427 /* calculate the mpc of the branch instruction */
429 branchmpc = cd->mcodeptr - cd->mcodebase;
431 br = DNEW(branchref);
433 br->branchmpc = branchmpc;
434 br->condition = condition;
436 br->options = options;
437 br->next = target->branchrefs;
439 target->branchrefs = br;
443 /* codegen_resolve_branchrefs **************************************************
445 Resolves and patches the branch references of a given basic block.
447 *******************************************************************************/
449 void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
454 /* Save the mcodeptr because in the branch emitting functions
455 we generate code somewhere inside already generated code,
456 but we're still in the actual code generation phase. */
458 mcodeptr = cd->mcodeptr;
460 /* just to make sure */
462 assert(bptr->mpc >= 0);
464 for (br = bptr->branchrefs; br != NULL; br = br->next) {
465 /* temporary set the mcodeptr */
467 cd->mcodeptr = cd->mcodebase + br->branchmpc;
469 /* emit_bccz and emit_branch emit the correct code, even if we
470 pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
472 emit_bccz(cd, bptr, br->condition, br->reg, br->options);
475 /* restore mcodeptr */
477 cd->mcodeptr = mcodeptr;
481 /* codegen_branch_label_add ****************************************************
483 Append an branch to the label-branch list.
485 *******************************************************************************/
487 void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
490 branch_label_ref_t *br;
493 /* get the label list */
495 list = cd->brancheslabel;
497 /* calculate the current mpc */
499 mpc = cd->mcodeptr - cd->mcodebase;
501 br = DNEW(branch_label_ref_t);
505 br->condition = condition;
507 br->options = options;
509 /* add the branch to the list */
511 list_add_last_unsynced(list, br);
515 /* codegen_add_patch_ref *******************************************************
517 Appends a new patcher reference to the list of patching positions.
519 *******************************************************************************/
521 void codegen_add_patch_ref(codegendata *cd, functionptr patcher, voidptr ref,
527 branchmpc = cd->mcodeptr - cd->mcodebase;
531 pr->branchpos = branchmpc;
533 pr->patcher = patcher;
536 /* list_add_first(cd->patchrefs, pr); */
537 pr->next = cd->patchrefs;
540 /* Generate NOPs for opt_shownops. */
545 #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__MIPS__) || defined(__X86_64__))
546 /* On some architectures the patcher stub call instruction might
547 be longer than the actual instruction generated. On this
548 architectures we store the last patcher call position and after
549 the basic block code generation is completed, we check the
550 range and maybe generate some nop's. */
552 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
557 /* codegen_critical_section_new ************************************************
559 Allocates a new critical-section reference and adds it to the
560 critical-section list.
562 *******************************************************************************/
564 #if defined(ENABLE_THREADS)
565 void codegen_critical_section_new(codegendata *cd)
568 critical_section_ref_t *csr;
571 /* get the critical section list */
573 list = cd->listcritical;
575 /* calculate the current mpc */
577 mpc = cd->mcodeptr - cd->mcodebase;
579 csr = DNEW(critical_section_ref_t);
581 /* We only can set restart right now, as start and end are set by
582 the following, corresponding functions. */
588 /* add the branch to the list */
590 list_add_last_unsynced(list, csr);
595 /* codegen_critical_section_start **********************************************
597 Set the start-point of the current critical section (which is the
598 last element of the list).
600 *******************************************************************************/
602 #if defined(ENABLE_THREADS)
603 void codegen_critical_section_start(codegendata *cd)
606 critical_section_ref_t *csr;
609 /* get the critical section list */
611 list = cd->listcritical;
613 /* calculate the current mpc */
615 mpc = cd->mcodeptr - cd->mcodebase;
617 /* get the current critical section */
619 csr = list_last_unsynced(list);
621 /* set the start point */
623 assert(csr->start == -1);
630 /* codegen_critical_section_end ************************************************
632 Set the end-point of the current critical section (which is the
633 last element of the list).
635 *******************************************************************************/
637 #if defined(ENABLE_THREADS)
638 void codegen_critical_section_end(codegendata *cd)
641 critical_section_ref_t *csr;
644 /* get the critical section list */
646 list = cd->listcritical;
648 /* calculate the current mpc */
650 mpc = cd->mcodeptr - cd->mcodebase;
652 /* get the current critical section */
654 csr = list_last_unsynced(list);
656 /* set the end point */
658 assert(csr->end == -1);
665 /* codegen_critical_section_finish *********************************************
667 Finish the critical sections, create the critical section nodes for
668 the AVL tree and insert them into the tree.
670 *******************************************************************************/
672 #if defined(ENABLE_THREADS)
673 static void codegen_critical_section_finish(jitdata *jd)
678 critical_section_ref_t *csr;
679 critical_section_node_t *csn;
681 /* get required compiler data */
686 /* get the critical section list */
688 list = cd->listcritical;
690 /* iterate over all critical sections */
692 for (csr = list_first_unsynced(list); csr != NULL;
693 csr = list_next_unsynced(list, csr)) {
694 /* check if all points are set */
696 assert(csr->start != -1);
697 assert(csr->end != -1);
698 assert(csr->restart != -1);
700 /* allocate tree node */
702 csn = NEW(critical_section_node_t);
704 csn->start = code->entrypoint + csr->start;
705 csn->end = code->entrypoint + csr->end;
706 csn->restart = code->entrypoint + csr->restart;
708 /* insert into the tree */
710 critical_section_register(csn);
716 /* methodtree_comparator *******************************************************
718 Comparator function used for the AVL tree of methods.
721 treenode....the node from the tree
722 node........the node to compare to the tree-node
724 *******************************************************************************/
726 static s4 methodtree_comparator(const void *treenode, const void *node)
728 methodtree_element *mte;
729 methodtree_element *mtepc;
731 mte = (methodtree_element *) treenode;
732 mtepc = (methodtree_element *) node;
734 /* compare both startpc and endpc of pc, even if they have the same value,
735 otherwise the avl_probe sometimes thinks the element is already in the
739 /* On S390 addresses are 31 bit. Compare only 31 bits of value.
741 # define ADDR_MASK(a) ((a) & 0x7FFFFFFF)
743 # define ADDR_MASK(a) (a)
746 if (ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->startpc) &&
747 ADDR_MASK((long) mtepc->startpc) <= ADDR_MASK((long) mte->endpc) &&
748 ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->endpc) &&
749 ADDR_MASK((long) mtepc->endpc) <= ADDR_MASK((long) mte->endpc)) {
752 } else if (ADDR_MASK((long) mtepc->startpc) < ADDR_MASK((long) mte->startpc)) {
763 /* codegen_insertmethod ********************************************************
765 Insert the machine code range of a method into the AVL tree of methods.
767 *******************************************************************************/
769 void codegen_insertmethod(u1 *startpc, u1 *endpc)
771 methodtree_element *mte;
773 /* allocate new method entry */
775 mte = NEW(methodtree_element);
777 mte->startpc = startpc;
780 /* this function does not return an error, but asserts for
783 avl_insert(methodtree, mte);
787 /* codegen_get_pv_from_pc ******************************************************
789 Find the PV for the given PC by searching in the AVL tree of
792 *******************************************************************************/
794 u1 *codegen_get_pv_from_pc(u1 *pc)
796 methodtree_element mtepc;
797 methodtree_element *mte;
799 /* allocation of the search structure on the stack is much faster */
804 mte = avl_find(methodtree, &mtepc);
807 /* No method was found. Let's dump a stacktrace. */
809 #if defined(ENABLE_VMLOG)
810 vmlog_cacao_signl("SIGSEGV");
813 log_println("We received a SIGSEGV and tried to handle it, but we were");
814 log_println("unable to find a Java method at:");
816 #if SIZEOF_VOID_P == 8
817 log_println("PC=0x%016lx", pc);
819 log_println("PC=0x%08x", pc);
822 log_println("Dumping the current stacktrace:");
824 #if defined(ENABLE_THREADS)
825 /* XXX michi: This should be available even without threads! */
826 threads_print_stacktrace();
829 vm_abort("Exiting...");
836 /* codegen_get_pv_from_pc_nocheck **********************************************
838 Find the PV for the given PC by searching in the AVL tree of
839 methods. This method does not check the return value and is used
842 *******************************************************************************/
844 u1 *codegen_get_pv_from_pc_nocheck(u1 *pc)
846 methodtree_element mtepc;
847 methodtree_element *mte;
849 /* allocation of the search structure on the stack is much faster */
854 mte = avl_find(methodtree, &mtepc);
863 /* codegen_set_replacement_point_notrap ****************************************
865 Record the position of a non-trappable replacement point.
867 *******************************************************************************/
869 #if defined(ENABLE_REPLACEMENT)
871 void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
873 void codegen_set_replacement_point_notrap(codegendata *cd)
876 assert(cd->replacementpoint);
877 assert(cd->replacementpoint->type == type);
878 assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
880 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
882 cd->replacementpoint++;
884 #endif /* defined(ENABLE_REPLACEMENT) */
887 /* codegen_set_replacement_point ***********************************************
889 Record the position of a trappable replacement point.
891 *******************************************************************************/
893 #if defined(ENABLE_REPLACEMENT)
895 void codegen_set_replacement_point(codegendata *cd, s4 type)
897 void codegen_set_replacement_point(codegendata *cd)
900 assert(cd->replacementpoint);
901 assert(cd->replacementpoint->type == type);
902 assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
904 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
906 cd->replacementpoint++;
908 /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
910 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
912 #endif /* defined(ENABLE_REPLACEMENT) */
915 /* codegen_finish **************************************************************
917 Finishes the code generation. A new memory, large enough for both
918 data and code, is allocated and data and code are copied together
919 to their final layout, unresolved jumps are resolved, ...
921 *******************************************************************************/
923 void codegen_finish(jitdata *jd)
928 #if defined(ENABLE_INTRP)
936 /* get required compiler data */
941 /* prevent compiler warning */
943 #if defined(ENABLE_INTRP)
947 /* calculate the code length */
949 mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
951 #if defined(ENABLE_STATISTICS)
953 count_code_len += mcodelen;
954 count_data_len += cd->dseglen;
958 alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
960 #if defined(ENABLE_INTRP)
962 ncodelen = cd->ncodeptr - cd->ncodebase;
964 ncodelen = 0; /* avoid compiler warning */
968 cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
969 alignedlen = alignedmcodelen + cd->dseglen;
971 #if defined(ENABLE_INTRP)
973 alignedlen += ncodelen;
977 /* allocate new memory */
979 code->mcodelength = mcodelen + cd->dseglen;
980 code->mcode = CNEW(u1, alignedlen);
982 /* set the entrypoint of the method */
984 assert(code->entrypoint == NULL);
985 code->entrypoint = epoint = (code->mcode + cd->dseglen);
987 /* fill the data segment (code->entrypoint must already be set!) */
991 /* copy code to the new location */
993 MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
995 #if defined(ENABLE_INTRP)
996 /* relocate native dynamic superinstruction code (if any) */
999 cd->mcodebase = code->entrypoint;
1002 u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
1004 MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
1006 /* flush the instruction and data caches */
1008 md_cacheflush(ncodebase, ncodelen);
1010 /* set some cd variables for dynamic_super_rerwite */
1012 cd->ncodebase = ncodebase;
1015 cd->ncodebase = NULL;
1018 dynamic_super_rewrite(cd);
1022 /* jump table resolving */
1024 for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
1025 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
1026 (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
1028 /* line number table resolving */
1034 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
1036 target = lr->targetmpc;
1037 /* if the entry contains an mcode pointer (normal case), resolve it */
1038 /* (see doc/inlining_stacktrace.txt for details) */
1039 if (lr->linenumber >= -2) {
1040 target += (ptrint) epoint;
1042 *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) =
1043 (functionptr) target;
1046 *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
1047 (functionptr) ((ptrint) epoint + cd->linenumbertab);
1049 *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
1052 #if defined(ENABLE_REPLACEMENT)
1053 /* replacement point resolving */
1058 code->replacementstubs += (ptrint) epoint;
1060 rp = code->rplpoints;
1061 for (i=0; i<code->rplpointcount; ++i, ++rp) {
1062 rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
1065 #endif /* defined(ENABLE_REPLACEMENT) */
1067 /* add method into methodtree to find the entrypoint */
1069 codegen_insertmethod(code->entrypoint, code->entrypoint + mcodelen);
1071 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
1072 /* resolve data segment references */
1074 dseg_resolve_datareferences(jd);
1077 #if defined(ENABLE_THREADS)
1078 /* create cirtical sections */
1080 codegen_critical_section_finish(jd);
1083 /* flush the instruction and data caches */
1085 md_cacheflush(code->mcode, code->mcodelength);
1089 /* codegen_generate_stub_compiler **********************************************
1091 Wrapper for codegen_emit_stub_compiler.
1094 pointer to the compiler stub code.
1096 *******************************************************************************/
1098 u1 *codegen_generate_stub_compiler(methodinfo *m)
1102 ptrint *d; /* pointer to data memory */
1103 u1 *c; /* pointer to code memory */
1106 /* mark dump memory */
1108 dumpsize = dump_size();
1110 /* allocate required data structures */
1115 jd->cd = DNEW(codegendata);
1118 /* get required compiler data */
1122 /* allocate code memory */
1124 c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1126 /* set pointers correctly */
1132 c = c + 3 * SIZEOF_VOID_P;
1135 /* NOTE: The codeinfo pointer is actually a pointer to the
1136 methodinfo (this fakes a codeinfo structure). */
1138 d[0] = (ptrint) asm_call_jit_compiler;
1140 d[2] = (ptrint) &d[1]; /* fake code->m */
1142 /* call the emit function */
1144 codegen_emit_stub_compiler(jd);
1146 #if defined(ENABLE_STATISTICS)
1148 count_cstub_len += 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
1153 md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1155 /* release dump memory */
1157 dump_release(dumpsize);
1159 /* return native stub code */
1165 /* codegen_generate_stub_native ************************************************
1167 Wrapper for codegen_emit_stub_native.
1170 the codeinfo representing the stub code.
1172 *******************************************************************************/
1174 codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
1183 /* mark dump memory */
1185 dumpsize = dump_size();
1190 jd->cd = DNEW(codegendata);
1191 jd->rd = DNEW(registerdata);
1194 /* Allocate codeinfo memory from the heap as we need to keep them. */
1196 jd->code = code_codeinfo_new(m); /* XXX check allocation */
1198 /* get required compiler data */
1202 /* set the flags for the current JIT run */
1204 #if defined(ENABLE_PROFILING)
1206 jd->flags |= JITDATA_FLAG_INSTRUMENT;
1209 if (opt_verbosecall)
1210 jd->flags |= JITDATA_FLAG_VERBOSECALL;
1212 /* setup code generation stuff */
1214 #if defined(ENABLE_JIT)
1215 # if defined(ENABLE_INTRP)
1223 /* create new method descriptor with additional native parameters */
1226 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
1228 nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
1229 md->paramcount * sizeof(typedesc) +
1230 nativeparams * sizeof(typedesc));
1232 nmd->paramcount = md->paramcount + nativeparams;
1234 nmd->params = DMNEW(paramdesc, nmd->paramcount);
1236 nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer */
1238 if (m->flags & ACC_STATIC)
1239 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer */
1241 MCOPY(nmd->paramtypes + nativeparams, md->paramtypes, typedesc,
1244 #if defined(ENABLE_JIT)
1245 # if defined(ENABLE_INTRP)
1248 /* pre-allocate the arguments for the native ABI */
1250 md_param_alloc_native(nmd);
1253 /* generate the code */
1255 #if defined(ENABLE_JIT)
1256 # if defined(ENABLE_INTRP)
1258 intrp_createnativestub(f, jd, nmd);
1261 codegen_emit_stub_native(jd, nmd, f);
1263 intrp_createnativestub(f, jd, nmd);
1266 #if defined(ENABLE_STATISTICS)
1268 count_nstub_len += code->mcodelength;
1271 /* reallocate the memory and finish the code generation */
1275 #if !defined(NDEBUG)
1276 /* disassemble native stub */
1278 if (opt_shownativestub) {
1279 #if defined(ENABLE_DISASSEMBLER)
1280 codegen_disassemble_nativestub(m,
1281 (u1 *) (ptrint) code->entrypoint,
1282 (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
1285 /* show data segment */
1287 if (opt_showddatasegment)
1290 #endif /* !defined(NDEBUG) */
1292 /* release memory */
1294 dump_release(dumpsize);
1296 /* return native stub code */
1302 /* codegen_disassemble_nativestub **********************************************
1304 Disassembles the generated native stub.
1306 *******************************************************************************/
1308 #if defined(ENABLE_DISASSEMBLER)
1309 void codegen_disassemble_nativestub(methodinfo *m, u1 *start, u1 *end)
1311 printf("Native stub: ");
1312 utf_fprint_printable_ascii_classname(stdout, m->class->name);
1314 utf_fprint_printable_ascii(stdout, m->name);
1315 utf_fprint_printable_ascii(stdout, m->descriptor);
1316 printf("\n\nLength: %d\n\n", (s4) (end - start));
1318 DISASSEMBLE(start, end);
1323 /* codegen_start_native_call ***************************************************
1325 Prepares the stuff required for a native (JNI) function call:
1327 - adds a stackframe info structure to the chain, for stacktraces
1328 - prepares the local references table on the stack
1330 The layout of the native stub stackframe should look like this:
1332 +---------------------------+ <- SP (of parent Java function)
1334 +---------------------------+
1336 | stackframe info structure |
1338 +---------------------------+
1340 | local references table |
1342 +---------------------------+
1344 | arguments (if any) |
1346 +---------------------------+ <- SP (native stub)
1348 *******************************************************************************/
1350 void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
1352 stackframeinfo *sfi;
1353 localref_table *lrt;
1355 /* get data structures from stack */
1357 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1358 lrt = (localref_table *) (datasp - sizeof(stackframeinfo) -
1359 sizeof(localref_table));
1361 /* add a stackframeinfo to the chain */
1363 stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
1365 #if defined(ENABLE_JNI)
1366 /* add current JNI local references table to this thread */
1368 lrt->capacity = LOCALREFTABLE_CAPACITY;
1370 lrt->localframes = 1;
1371 lrt->prev = LOCALREFTABLE;
1373 /* clear the references array (memset is faster the a for-loop) */
1375 MSET(lrt->refs, 0, java_objectheader*, LOCALREFTABLE_CAPACITY);
1377 LOCALREFTABLE = lrt;
1382 /* codegen_finish_native_call **************************************************
1384 Removes the stuff required for a native (JNI) function call.
1385 Additionally it checks for an exceptions and in case, get the
1386 exception object and clear the pointer.
1388 *******************************************************************************/
1390 java_objectheader *codegen_finish_native_call(u1 *datasp)
1392 stackframeinfo *sfi;
1393 stackframeinfo **psfi;
1394 #if defined(ENABLE_JNI)
1395 localref_table *lrt;
1396 localref_table *plrt;
1399 java_objectheader *e;
1401 /* get data structures from stack */
1403 sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1405 /* remove current stackframeinfo from chain */
1407 psfi = &STACKFRAMEINFO;
1411 #if defined(ENABLE_JNI)
1412 /* release JNI local references tables for this thread */
1414 lrt = LOCALREFTABLE;
1416 /* release all current local frames */
1418 for (localframes = lrt->localframes; localframes >= 1; localframes--) {
1419 /* get previous frame */
1423 /* Clear all reference entries (only for tables allocated on
1426 if (localframes > 1)
1427 MSET(&lrt->refs[0], 0, java_objectheader*, lrt->capacity);
1431 /* set new local references table */
1436 /* now store the previous local frames in the thread structure */
1438 LOCALREFTABLE = lrt;
1441 /* get the exception and return it */
1443 e = exceptions_get_and_clear_exception();
1449 /* removecompilerstub **********************************************************
1451 Deletes a compilerstub from memory (simply by freeing it).
1453 *******************************************************************************/
1455 void removecompilerstub(u1 *stub)
1457 /* pass size 1 to keep the intern function happy */
1459 CFREE((void *) stub, 1);
1463 /* removenativestub ************************************************************
1465 Removes a previously created native-stub from memory.
1467 *******************************************************************************/
1469 void removenativestub(u1 *stub)
1471 /* pass size 1 to keep the intern function happy */
1473 CFREE((void *) stub, 1);
1477 /* codegen_reg_of_var **********************************************************
1479 This function determines a register, to which the result of an
1480 operation should go, when it is ultimatively intended to store the
1481 result in pseudoregister v. If v is assigned to an actual
1482 register, this register will be returned. Otherwise (when v is
1483 spilled) this function returns tempregnum. If not already done,
1484 regoff and flags are set in the stack location.
1486 On ARM we have to check if a long/double variable is splitted
1487 across reg/stack (HIGH_REG == REG_SPLIT). We return the actual
1488 register of v for LOW_REG and the tempregnum for HIGH_REG in such
1489 cases. (michi 2005/07/24)
1491 *******************************************************************************/
1493 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
1497 /* Do we have to generate a conditional move? Yes, then always
1498 return the temporary register. The real register is identified
1499 during the store. */
1501 if (opcode & ICMD_CONDITION_MASK)
1505 if (!(v->flags & INMEMORY)) {
1506 #if defined(__ARM__) && defined(__ARMEL__)
1507 if (IS_2_WORD_TYPE(v->type) && (GET_HIGH_REG(v->vv.regoff) == REG_SPLIT))
1508 return PACK_REGS(GET_LOW_REG(v->vv.regoff),
1509 GET_HIGH_REG(tempregnum));
1511 #if defined(__ARM__) && defined(__ARMEB__)
1512 if (IS_2_WORD_TYPE(v->type) && (GET_LOW_REG(v->vv.regoff) == REG_SPLIT))
1513 return PACK_REGS(GET_LOW_REG(tempregnum),
1514 GET_HIGH_REG(v->vv.regoff));
1516 return v->vv.regoff;
1519 #if defined(ENABLE_STATISTICS)
1521 count_spills_read++;
1527 /* codegen_reg_of_dst **********************************************************
1529 This function determines a register, to which the result of an
1530 operation should go, when it is ultimatively intended to store the
1531 result in iptr->dst.var. If dst.var is assigned to an actual
1532 register, this register will be returned. Otherwise (when it is
1533 spilled) this function returns tempregnum. If not already done,
1534 regoff and flags are set in the stack location.
1536 On ARM we have to check if a long/double variable is splitted
1537 across reg/stack (HIGH_REG == REG_SPLIT). We return the actual
1538 register of dst.var for LOW_REG and the tempregnum for HIGH_REG in such
1539 cases. (michi 2005/07/24)
1541 *******************************************************************************/
1543 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
1545 return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
1550 * These are local overrides for various environment variables in Emacs.
1551 * Please do not remove this and leave it at the end of the file, where
1552 * Emacs will automagically detect them.
1553 * ---------------------------------------------------------------------
1556 * indent-tabs-mode: t
1560 * vim:noexpandtab:sw=4:ts=4: