1 /* src/vm/jit/codegen-common.c - architecture independent code generator stuff
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 All functions assume the following code area / data area layout:
27 | code area | code area grows to higher addresses
29 +-----------+ <-- start of procedure
31 | data area | data area grows to lower addresses
35 The functions first write into a temporary code/data area allocated by
36 "codegen_init". "codegen_finish" copies the code and data area into permanent
37 memory. All functions writing values into the data area return the offset
38 relative the begin of the code area (start of procedure).
54 #include "mm/memory.h"
56 #include "toolbox/avl.h"
57 #include "toolbox/list.h"
58 #include "toolbox/logging.h"
60 #include "native/jni.h"
61 #include "native/llni.h"
62 #include "native/localref.h"
63 #include "native/native.h"
65 #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
66 # include "native/include/java_lang_Object.h"
67 # include "native/include/java_lang_String.h" /* required by j.l.CL */
68 # include "native/include/java_nio_ByteBuffer.h" /* required by j.l.CL */
69 # include "native/include/java_lang_ClassLoader.h"
72 #if defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
73 # include "native/include/java_lang_String.h"
76 #include "native/include/java_lang_Class.h"
78 #include "threads/thread.hpp"
80 #include "vm/builtin.h"
81 #include "vm/exceptions.h"
82 #include "vm/stringlocal.h"
84 #include "vm/jit/abi.h"
85 #include "vm/jit/asmpart.h"
86 #include "vm/jit/code.h"
87 #include "vm/jit/codegen-common.h"
89 #if defined(ENABLE_DISASSEMBLER)
90 # include "vm/jit/disass.h"
93 #include "vm/jit/dseg.h"
94 #include "vm/jit/emit-common.h"
95 #include "vm/jit/jit.h"
96 #include "vm/jit/linenumbertable.h"
97 #include "vm/jit/methodheader.h"
98 #include "vm/jit/methodtree.h"
99 #include "vm/jit/patcher-common.h"
100 #include "vm/jit/replace.h"
101 #if defined(ENABLE_SSA)
102 # include "vm/jit/optimizing/lsra.h"
103 # include "vm/jit/optimizing/ssa.h"
105 #include "vm/jit/stacktrace.hpp"
106 #include "vm/jit/trace.hpp"
108 #if defined(ENABLE_INTRP)
109 #include "vm/jit/intrp/intrp.h"
112 #include "vmcore/method.h"
113 #include "vmcore/options.h"
115 # include "vmcore/statistics.h"
117 #if defined(ENABLE_VMLOG)
118 #include <vmlog_cacao.h>
124 /* codegen_init ****************************************************************
128 *******************************************************************************/
130 void codegen_init(void)
135 /* codegen_setup ***************************************************************
137 Allocates and initialises code area, data area and references.
139 *******************************************************************************/
141 void codegen_setup(jitdata *jd)
146 /* get required compiler data */
151 /* initialize members */
155 cd->mcodebase = DMNEW(u1, MCODEINITSIZE);
156 cd->mcodeend = cd->mcodebase + MCODEINITSIZE;
157 cd->mcodesize = MCODEINITSIZE;
159 /* initialize mcode variables */
161 cd->mcodeptr = cd->mcodebase;
162 cd->lastmcodeptr = cd->mcodebase;
164 #if defined(ENABLE_INTRP)
165 /* native dynamic superinstructions variables */
168 cd->ncodebase = DMNEW(u1, NCODEINITSIZE);
169 cd->ncodesize = NCODEINITSIZE;
171 /* initialize ncode variables */
173 cd->ncodeptr = cd->ncodebase;
175 cd->lastinstwithoutdispatch = ~0; /* no inst without dispatch */
176 cd->superstarts = NULL;
183 cd->jumpreferences = NULL;
185 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
186 cd->datareferences = NULL;
189 cd->brancheslabel = list_create_dump(OFFSET(branch_label_ref_t, linkage));
190 cd->linenumbers = list_create_dump(OFFSET(linenumbertable_list_entry_t, linkage));
194 /* codegen_reset ***************************************************************
196 Resets the codegen data structure so we can recompile the method.
198 *******************************************************************************/
200 static void codegen_reset(jitdata *jd)
206 /* get required compiler data */
211 /* reset error flag */
213 cd->flags &= ~CODEGENDATA_FLAG_ERROR;
215 /* reset some members, we reuse the code memory already allocated
216 as this should have almost the correct size */
218 cd->mcodeptr = cd->mcodebase;
219 cd->lastmcodeptr = cd->mcodebase;
224 cd->jumpreferences = NULL;
226 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
227 cd->datareferences = NULL;
230 cd->brancheslabel = list_create_dump(OFFSET(branch_label_ref_t, linkage));
231 cd->linenumbers = list_create_dump(OFFSET(linenumbertable_list_entry_t, linkage));
233 /* We need to clear the mpc and the branch references from all
234 basic blocks as they will definitely change. */
236 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
238 bptr->branchrefs = NULL;
241 /* We need to clear all the patcher references from the codeinfo
242 since they all will be regenerated */
244 patcher_list_reset(code);
246 #if defined(ENABLE_REPLACEMENT)
247 code->rplpoints = NULL;
248 code->rplpointcount = 0;
249 code->regalloc = NULL;
250 code->regalloccount = 0;
251 code->globalcount = 0;
256 /* codegen_generate ************************************************************
258 Generates the code for the currently compiled method.
260 *******************************************************************************/
262 bool codegen_generate(jitdata *jd)
266 /* get required compiler data */
270 /* call the machine-dependent code generation function */
272 if (!codegen_emit(jd))
275 /* check for an error */
277 if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
278 /* check for long-branches flag, if it is set we recompile the
283 log_message_method("Re-generating code: ", jd->m);
286 /* XXX maybe we should tag long-branches-methods for recompilation */
288 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
289 /* we have to reset the codegendata structure first */
293 /* and restart the compiler run */
295 if (!codegen_emit(jd))
299 vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
304 log_message_method("Re-generating code done: ", jd->m);
308 /* reallocate the memory and finish the code generation */
312 /* everything's ok */
318 /* codegen_close ***************************************************************
322 *******************************************************************************/
324 void codegen_close(void)
326 /* TODO: release avl tree on i386 and x86_64 */
330 /* codegen_increase ************************************************************
334 *******************************************************************************/
336 void codegen_increase(codegendata *cd)
340 /* save old mcodebase pointer */
342 oldmcodebase = cd->mcodebase;
344 /* reallocate to new, doubled memory */
346 cd->mcodebase = DMREALLOC(cd->mcodebase,
351 cd->mcodeend = cd->mcodebase + cd->mcodesize;
353 /* set new mcodeptr */
355 cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
357 #if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(__M68K__) || defined(ENABLE_INTRP) \
358 || defined(__SPARC_64__)
359 /* adjust the pointer to the last patcher position */
361 if (cd->lastmcodeptr != NULL)
362 cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
367 /* codegen_ncode_increase ******************************************************
371 *******************************************************************************/
373 #if defined(ENABLE_INTRP)
374 u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
378 /* save old ncodebase pointer */
380 oldncodebase = cd->ncodebase;
382 /* reallocate to new, doubled memory */
384 cd->ncodebase = DMREALLOC(cd->ncodebase,
390 /* return the new ncodeptr */
392 return (cd->ncodebase + (ncodeptr - oldncodebase));
397 /* codegen_add_branch_ref ******************************************************
399 Prepends an branch to the list.
401 *******************************************************************************/
403 void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
408 STATISTICS(count_branches_unresolved++);
410 /* calculate the mpc of the branch instruction */
412 branchmpc = cd->mcodeptr - cd->mcodebase;
414 br = DNEW(branchref);
416 br->branchmpc = branchmpc;
417 br->condition = condition;
419 br->options = options;
420 br->next = target->branchrefs;
422 target->branchrefs = br;
426 /* codegen_resolve_branchrefs **************************************************
428 Resolves and patches the branch references of a given basic block.
430 *******************************************************************************/
432 void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
437 /* Save the mcodeptr because in the branch emitting functions
438 we generate code somewhere inside already generated code,
439 but we're still in the actual code generation phase. */
441 mcodeptr = cd->mcodeptr;
443 /* just to make sure */
445 assert(bptr->mpc >= 0);
447 for (br = bptr->branchrefs; br != NULL; br = br->next) {
448 /* temporary set the mcodeptr */
450 cd->mcodeptr = cd->mcodebase + br->branchmpc;
452 /* emit_bccz and emit_branch emit the correct code, even if we
453 pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
455 emit_bccz(cd, bptr, br->condition, br->reg, br->options);
458 /* restore mcodeptr */
460 cd->mcodeptr = mcodeptr;
464 /* codegen_branch_label_add ****************************************************
466 Append an branch to the label-branch list.
468 *******************************************************************************/
470 void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
473 branch_label_ref_t *br;
476 /* Get the label list. */
478 l = cd->brancheslabel;
480 /* calculate the current mpc */
482 mpc = cd->mcodeptr - cd->mcodebase;
484 br = DNEW(branch_label_ref_t);
488 br->condition = condition;
490 br->options = options;
492 /* Add the branch to the list. */
494 list_add_last(l, br);
498 /* codegen_set_replacement_point_notrap ****************************************
500 Record the position of a non-trappable replacement point.
502 *******************************************************************************/
504 #if defined(ENABLE_REPLACEMENT)
506 void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
508 void codegen_set_replacement_point_notrap(codegendata *cd)
511 assert(cd->replacementpoint);
512 assert(cd->replacementpoint->type == type);
513 assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
515 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
517 cd->replacementpoint++;
519 #endif /* defined(ENABLE_REPLACEMENT) */
522 /* codegen_set_replacement_point ***********************************************
524 Record the position of a trappable replacement point.
526 *******************************************************************************/
528 #if defined(ENABLE_REPLACEMENT)
530 void codegen_set_replacement_point(codegendata *cd, s4 type)
532 void codegen_set_replacement_point(codegendata *cd)
535 assert(cd->replacementpoint);
536 assert(cd->replacementpoint->type == type);
537 assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
539 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
541 cd->replacementpoint++;
544 /* XXX actually we should use an own REPLACEMENT_NOPS here! */
545 if (opt_TestReplacement)
549 /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
551 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
553 #endif /* defined(ENABLE_REPLACEMENT) */
556 /* codegen_finish **************************************************************
558 Finishes the code generation. A new memory, large enough for both
559 data and code, is allocated and data and code are copied together
560 to their final layout, unresolved jumps are resolved, ...
562 *******************************************************************************/
564 void codegen_finish(jitdata *jd)
569 #if defined(ENABLE_INTRP)
577 /* get required compiler data */
582 /* prevent compiler warning */
584 #if defined(ENABLE_INTRP)
588 /* calculate the code length */
590 mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
592 #if defined(ENABLE_STATISTICS)
594 count_code_len += mcodelen;
595 count_data_len += cd->dseglen;
599 alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
601 #if defined(ENABLE_INTRP)
603 ncodelen = cd->ncodeptr - cd->ncodebase;
605 ncodelen = 0; /* avoid compiler warning */
609 cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
610 alignedlen = alignedmcodelen + cd->dseglen;
612 #if defined(ENABLE_INTRP)
614 alignedlen += ncodelen;
618 /* allocate new memory */
620 code->mcodelength = mcodelen + cd->dseglen;
621 code->mcode = CNEW(u1, alignedlen);
623 /* set the entrypoint of the method */
625 assert(code->entrypoint == NULL);
626 code->entrypoint = epoint = (code->mcode + cd->dseglen);
628 /* fill the data segment (code->entrypoint must already be set!) */
632 /* copy code to the new location */
634 MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
636 #if defined(ENABLE_INTRP)
637 /* relocate native dynamic superinstruction code (if any) */
640 cd->mcodebase = code->entrypoint;
643 u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
645 MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
647 /* flush the instruction and data caches */
649 md_cacheflush(ncodebase, ncodelen);
651 /* set some cd variables for dynamic_super_rerwite */
653 cd->ncodebase = ncodebase;
656 cd->ncodebase = NULL;
659 dynamic_super_rewrite(cd);
663 /* Create the exception table. */
665 exceptiontable_create(jd);
667 /* Create the linenumber table. */
669 linenumbertable_create(jd);
671 /* jump table resolving */
673 for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
674 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
675 (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
677 /* patcher resolving */
681 #if defined(ENABLE_REPLACEMENT)
682 /* replacement point resolving */
687 rp = code->rplpoints;
688 for (i=0; i<code->rplpointcount; ++i, ++rp) {
689 rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
692 #endif /* defined(ENABLE_REPLACEMENT) */
694 /* Insert method into methodtree to find the entrypoint. */
696 methodtree_insert(code->entrypoint, code->entrypoint + mcodelen);
698 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
699 /* resolve data segment references */
701 dseg_resolve_datareferences(jd);
704 /* flush the instruction and data caches */
706 md_cacheflush(code->mcode, code->mcodelength);
710 /* codegen_generate_stub_compiler **********************************************
712 Wrapper for codegen_emit_stub_compiler.
715 pointer to the compiler stub code.
717 *******************************************************************************/
719 u1 *codegen_generate_stub_compiler(methodinfo *m)
723 ptrint *d; /* pointer to data memory */
724 u1 *c; /* pointer to code memory */
727 /* mark dump memory */
731 /* allocate required data structures */
736 jd->cd = DNEW(codegendata);
739 /* get required compiler data */
743 #if !defined(JIT_COMPILER_VIA_SIGNAL)
744 /* allocate code memory */
746 c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
748 /* set pointers correctly */
754 c = c + 3 * SIZEOF_VOID_P;
757 /* NOTE: The codeinfo pointer is actually a pointer to the
758 methodinfo (this fakes a codeinfo structure). */
760 d[0] = (ptrint) asm_call_jit_compiler;
762 d[2] = (ptrint) &d[1]; /* fake code->m */
764 /* call the emit function */
766 codegen_emit_stub_compiler(jd);
768 #if defined(ENABLE_STATISTICS)
770 count_cstub_len += 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
775 md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
777 /* Allocate code memory. */
779 c = CNEW(uint8_t, 2 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
781 /* Set pointers correctly. */
787 c = c + 2 * SIZEOF_VOID_P;
790 /* NOTE: The codeinfo pointer is actually a pointer to the
791 methodinfo (this fakes a codeinfo structure). */
794 d[1] = (ptrint) &d[0]; /* fake code->m */
796 /* Emit the trap instruction. */
798 emit_trap_compiler(cd);
800 #if defined(ENABLE_STATISTICS)
802 count_cstub_len += 2 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
807 md_cacheflush(cd->mcodebase, 2 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
810 /* release dump memory */
814 /* return native stub code */
820 /* codegen_generate_stub_builtin ***********************************************
822 Wrapper for codegen_emit_stub_native.
824 *******************************************************************************/
826 void codegen_generate_stub_builtin(methodinfo *m, builtintable_entry *bte)
833 /* mark dump memory */
837 /* Create JIT data structure. */
839 jd = jit_jitdata_new(m);
841 /* Get required compiler data. */
845 /* Stubs are non-leaf methods. */
847 code_unflag_leafmethod(code);
849 /* setup code generation stuff */
853 /* Set the number of native arguments we need to skip. */
857 /* generate the code */
859 #if defined(ENABLE_JIT)
860 # if defined(ENABLE_INTRP)
863 assert(bte->fp != NULL);
864 codegen_emit_stub_native(jd, bte->md, bte->fp, skipparams);
865 # if defined(ENABLE_INTRP)
870 /* reallocate the memory and finish the code generation */
874 /* set the stub entry point in the builtin table */
876 bte->stub = code->entrypoint;
878 #if defined(ENABLE_STATISTICS)
880 size_stub_native += code->mcodelength;
883 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
884 /* disassemble native stub */
886 if (opt_DisassembleStubs) {
887 codegen_disassemble_stub(m,
888 (u1 *) (ptrint) code->entrypoint,
889 (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
891 /* show data segment */
893 if (opt_showddatasegment)
896 #endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
904 /* codegen_generate_stub_native ************************************************
906 Wrapper for codegen_emit_stub_native.
909 the codeinfo representing the stub code.
911 *******************************************************************************/
913 codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
922 /* mark dump memory */
926 /* Create JIT data structure. */
928 jd = jit_jitdata_new(m);
930 /* Get required compiler data. */
934 /* Stubs are non-leaf methods. */
936 code_unflag_leafmethod(code);
938 /* set the flags for the current JIT run */
940 #if defined(ENABLE_PROFILING)
942 jd->flags |= JITDATA_FLAG_INSTRUMENT;
946 jd->flags |= JITDATA_FLAG_VERBOSECALL;
948 /* setup code generation stuff */
950 #if defined(ENABLE_JIT)
951 # if defined(ENABLE_INTRP)
959 /* create new method descriptor with additional native parameters */
963 /* Set the number of native arguments we need to skip. */
965 if (m->flags & ACC_STATIC)
970 nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
971 md->paramcount * sizeof(typedesc) +
972 skipparams * sizeof(typedesc));
974 nmd->paramcount = md->paramcount + skipparams;
976 nmd->params = DMNEW(paramdesc, nmd->paramcount);
978 nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer */
980 if (m->flags & ACC_STATIC)
981 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer */
983 MCOPY(nmd->paramtypes + skipparams, md->paramtypes, typedesc,
986 #if defined(ENABLE_JIT)
987 # if defined(ENABLE_INTRP)
990 /* pre-allocate the arguments for the native ABI */
992 md_param_alloc_native(nmd);
995 /* generate the code */
997 #if defined(ENABLE_JIT)
998 # if defined(ENABLE_INTRP)
1000 intrp_createnativestub(f, jd, nmd);
1003 codegen_emit_stub_native(jd, nmd, f, skipparams);
1005 intrp_createnativestub(f, jd, nmd);
1008 /* reallocate the memory and finish the code generation */
1012 #if defined(ENABLE_STATISTICS)
1013 /* must be done after codegen_finish() */
1016 size_stub_native += code->mcodelength;
1019 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
1020 /* disassemble native stub */
1022 if (opt_DisassembleStubs) {
1023 # if defined(ENABLE_DEBUG_FILTER)
1024 if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
1027 codegen_disassemble_stub(m,
1028 (u1 *) (ptrint) code->entrypoint,
1029 (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
1031 /* show data segment */
1033 if (opt_showddatasegment)
1037 #endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
1039 /* release memory */
1043 /* return native stub code */
1049 /* codegen_disassemble_nativestub **********************************************
1051 Disassembles the generated builtin or native stub.
1053 *******************************************************************************/
1055 #if defined(ENABLE_DISASSEMBLER)
1056 void codegen_disassemble_stub(methodinfo *m, u1 *start, u1 *end)
1058 printf("Stub code: ");
1059 if (m->clazz != NULL)
1060 utf_fprint_printable_ascii_classname(stdout, m->clazz->name);
1064 utf_fprint_printable_ascii(stdout, m->name);
1065 utf_fprint_printable_ascii(stdout, m->descriptor);
1066 printf("\nLength: %d\n\n", (s4) (end - start));
1068 DISASSEMBLE(start, end);
1073 /* codegen_start_native_call ***************************************************
1075 Prepares the stuff required for a native (JNI) function call:
1077 - adds a stackframe info structure to the chain, for stacktraces
1078 - prepares the local references table on the stack
1080 The layout of the native stub stackframe should look like this:
1082 +---------------------------+ <- java SP (of parent Java function)
1084 +---------------------------+ <- data SP
1086 | stackframe info structure |
1088 +---------------------------+
1090 | local references table |
1092 +---------------------------+
1094 | saved registers (if any) |
1096 +---------------------------+
1098 | arguments (if any) |
1100 +---------------------------+ <- current SP (native stub)
1102 *******************************************************************************/
1104 java_handle_t *codegen_start_native_call(u1 *sp, u1 *pv)
1106 stackframeinfo_t *sfi;
1107 localref_table *lrt;
1114 uint64_t *arg_stack;
1116 STATISTICS(count_calls_java_to_native++);
1118 /* Get the methodinfo. */
1120 m = code_get_methodinfo_for_pv(pv);
1124 framesize = *((int32_t *) (pv + FrameSize));
1126 assert(framesize >= sizeof(stackframeinfo_t) + sizeof(localref_table));
1128 /* calculate needed values */
1130 #if defined(__ALPHA__) || defined(__ARM__)
1131 datasp = sp + framesize - SIZEOF_VOID_P;
1132 javasp = sp + framesize;
1133 arg_regs = (uint64_t *) sp;
1134 arg_stack = (uint64_t *) javasp;
1135 #elif defined(__MIPS__)
1136 /* MIPS always uses 8 bytes to store the RA */
1137 datasp = sp + framesize - 8;
1138 javasp = sp + framesize;
1139 #elif defined(__S390__)
1140 datasp = sp + framesize - 8;
1141 javasp = sp + framesize;
1142 arg_regs = (uint64_t *) (sp + 96);
1143 arg_stack = (uint64_t *) javasp;
1144 #elif defined(__I386__) || defined(__M68K__) || defined(__X86_64__)
1145 datasp = sp + framesize;
1146 javasp = sp + framesize + SIZEOF_VOID_P;
1147 arg_regs = (uint64_t *) sp;
1148 arg_stack = (uint64_t *) javasp;
1149 #elif defined(__POWERPC__)
1150 datasp = sp + framesize;
1151 javasp = sp + framesize;
1152 arg_regs = (uint64_t *) (sp + LA_SIZE + 4 * SIZEOF_VOID_P);
1153 arg_stack = (uint64_t *) javasp;
1154 #elif defined(__POWERPC64__)
1155 datasp = sp + framesize;
1156 javasp = sp + framesize;
1157 arg_regs = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 4 * SIZEOF_VOID_P);
1158 arg_stack = (uint64_t *) javasp;
1160 /* XXX is was unable to do this port for SPARC64, sorry. (-michi) */
1161 /* XXX maybe we need to pass the RA as argument there */
1162 vm_abort("codegen_start_native_call: unsupported architecture");
1165 /* get data structures from stack */
1167 sfi = (stackframeinfo_t *) (datasp - sizeof(stackframeinfo_t));
1168 lrt = (localref_table *) (datasp - sizeof(stackframeinfo_t) -
1169 sizeof(localref_table));
1171 #if defined(ENABLE_JNI)
1172 /* add current JNI local references table to this thread */
1174 localref_table_add(lrt);
1177 #if !defined(NDEBUG)
1178 # if defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__)
1179 /* print the call-trace if necesarry */
1180 /* BEFORE: filling the local reference table */
1182 if (opt_TraceJavaCalls)
1183 trace_java_call_enter(m, arg_regs, arg_stack);
1187 #if defined(ENABLE_HANDLES)
1188 /* place all references into the local reference table */
1189 /* BEFORE: creating stackframeinfo */
1191 localref_native_enter(m, arg_regs, arg_stack);
1194 /* Add a stackframeinfo for this native method. We don't have RA
1195 and XPC here. These are determined in
1196 stacktrace_stackframeinfo_add. */
1198 stacktrace_stackframeinfo_add(sfi, pv, sp, NULL, NULL);
1200 /* Return a wrapped classinfo for static methods. */
1202 if (m->flags & ACC_STATIC)
1203 return (java_handle_t *) LLNI_classinfo_wrap(m->clazz);
1209 /* codegen_finish_native_call **************************************************
1211 Removes the stuff required for a native (JNI) function call.
1212 Additionally it checks for an exceptions and in case, get the
1213 exception object and clear the pointer.
1215 *******************************************************************************/
1217 java_object_t *codegen_finish_native_call(u1 *sp, u1 *pv)
1219 stackframeinfo_t *sfi;
1229 /* get information from method header */
1231 code = code_get_codeinfo_for_pv(pv);
1233 framesize = *((int32_t *) (pv + FrameSize));
1237 /* get the methodinfo */
1242 /* calculate needed values */
1244 #if defined(__ALPHA__) || defined(__ARM__)
1245 datasp = sp + framesize - SIZEOF_VOID_P;
1246 ret_regs = (uint64_t *) sp;
1247 #elif defined(__MIPS__)
1248 /* MIPS always uses 8 bytes to store the RA */
1249 datasp = sp + framesize - 8;
1250 #elif defined(__S390__)
1251 datasp = sp + framesize - 8;
1252 ret_regs = (uint64_t *) (sp + 96);
1253 #elif defined(__I386__)
1254 datasp = sp + framesize;
1255 ret_regs = (uint64_t *) (sp + 2 * SIZEOF_VOID_P);
1256 #elif defined(__M68K__)
1257 datasp = sp + framesize;
1258 ret_regs = (uint64_t *) (sp + 2 * 8);
1259 #elif defined(__X86_64__)
1260 datasp = sp + framesize;
1261 ret_regs = (uint64_t *) sp;
1262 #elif defined(__POWERPC__)
1263 datasp = sp + framesize;
1264 ret_regs = (uint64_t *) (sp + LA_SIZE + 2 * SIZEOF_VOID_P);
1265 #elif defined(__POWERPC64__)
1266 datasp = sp + framesize;
1267 ret_regs = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 2 * SIZEOF_VOID_P);
1269 vm_abort("codegen_finish_native_call: unsupported architecture");
1272 /* get data structures from stack */
1274 sfi = (stackframeinfo_t *) (datasp - sizeof(stackframeinfo_t));
1276 /* Remove current stackframeinfo from chain. */
1278 stacktrace_stackframeinfo_remove(sfi);
1280 #if defined(ENABLE_HANDLES)
1281 /* unwrap the return value from the local reference table */
1282 /* AFTER: removing the stackframeinfo */
1283 /* BEFORE: releasing the local reference table */
1285 localref_native_exit(m, ret_regs);
1288 /* get and unwrap the exception */
1289 /* AFTER: removing the stackframe info */
1290 /* BEFORE: releasing the local reference table */
1292 e = exceptions_get_and_clear_exception();
1295 #if defined(ENABLE_JNI)
1296 /* release JNI local references table for this thread */
1298 localref_frame_pop_all();
1299 localref_table_remove();
1302 #if !defined(NDEBUG)
1303 # if defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__)
1304 /* print the call-trace if necesarry */
1305 /* AFTER: unwrapping the return value */
1307 if (opt_TraceJavaCalls)
1308 trace_java_call_exit(m, ret_regs);
1316 /* removecompilerstub **********************************************************
1318 Deletes a compilerstub from memory (simply by freeing it).
1320 *******************************************************************************/
1322 void removecompilerstub(u1 *stub)
1324 /* pass size 1 to keep the intern function happy */
1326 CFREE((void *) stub, 1);
1330 /* removenativestub ************************************************************
1332 Removes a previously created native-stub from memory.
1334 *******************************************************************************/
1336 void removenativestub(u1 *stub)
1338 /* pass size 1 to keep the intern function happy */
1340 CFREE((void *) stub, 1);
1344 /* codegen_reg_of_var **********************************************************
1346 This function determines a register, to which the result of an
1347 operation should go, when it is ultimatively intended to store the
1348 result in pseudoregister v. If v is assigned to an actual
1349 register, this register will be returned. Otherwise (when v is
1350 spilled) this function returns tempregnum. If not already done,
1351 regoff and flags are set in the stack location.
1353 *******************************************************************************/
1355 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
1357 if (!(v->flags & INMEMORY))
1358 return v->vv.regoff;
1364 /* codegen_reg_of_dst **********************************************************
1366 This function determines a register, to which the result of an
1367 operation should go, when it is ultimatively intended to store the
1368 result in iptr->dst.var. If dst.var is assigned to an actual
1369 register, this register will be returned. Otherwise (when it is
1370 spilled) this function returns tempregnum. If not already done,
1371 regoff and flags are set in the stack location.
1373 *******************************************************************************/
1375 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
1377 return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
1381 /* codegen_emit_phi_moves ****************************************************
1383 Emits phi moves at the end of the basicblock.
1385 *******************************************************************************/
1387 #if defined(ENABLE_SSA)
1388 void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
1401 /* Moves from phi functions with highest indices have to be */
1402 /* inserted first, since this is the order as is used for */
1403 /* conflict resolution */
1405 for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
1406 lt_d = ls->phi_moves[bptr->nr][i][0];
1407 lt_s = ls->phi_moves[bptr->nr][i][1];
1408 #if defined(SSA_DEBUG_VERBOSE)
1410 printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
1412 if (lt_s == UNUSED) {
1413 #if defined(SSA_DEBUG_VERBOSE)
1415 printf(" ... not processed \n");
1420 d = VAR(ls->lifetime[lt_d].v_index);
1421 s = VAR(ls->lifetime[lt_s].v_index);
1424 if (d->type == -1) {
1425 #if defined(SSA_DEBUG_VERBOSE)
1427 printf("...returning - phi lifetimes where joined\n");
1432 if (s->type == -1) {
1433 #if defined(SSA_DEBUG_VERBOSE)
1435 printf("...returning - phi lifetimes where joined\n");
1441 tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
1442 tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
1443 emit_copy(jd, &tmp_i);
1445 #if defined(SSA_DEBUG_VERBOSE)
1446 if (compileverbose) {
1447 if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
1449 printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1451 else if (IS_INMEMORY(s->flags)) {
1453 printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1455 else if (IS_INMEMORY(d->flags)) {
1457 printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1461 printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1465 #endif /* defined(SSA_DEBUG_VERBOSE) */
1468 #endif /* defined(ENABLE_SSA) */
1471 /* REMOVEME When we have exception handling in C. */
1473 void *md_asm_codegen_get_pv_from_pc(void *ra)
1475 return md_codegen_get_pv_from_pc(ra);
1480 * These are local overrides for various environment variables in Emacs.
1481 * Please do not remove this and leave it at the end of the file, where
1482 * Emacs will automagically detect them.
1483 * ---------------------------------------------------------------------
1486 * indent-tabs-mode: t
1490 * vim:noexpandtab:sw=4:ts=4: