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).
48 #include "vm/jit/jitcache.h"
56 #include "mm/memory.h"
58 #include "toolbox/avl.h"
59 #include "toolbox/list.h"
60 #include "toolbox/logging.h"
62 #include "native/jni.h"
63 #include "native/llni.h"
64 #include "native/localref.h"
65 #include "native/native.h"
67 #include "threads/thread.hpp"
69 #include "vm/builtin.h"
70 #include "vm/exceptions.hpp"
71 #include "vm/method.h"
72 #include "vm/options.h"
73 #include "vm/string.hpp"
75 # include "vm/statistics.h"
78 #include "vm/jit/abi.h"
79 #include "vm/jit/asmpart.h"
80 #include "vm/jit/code.h"
81 #include "vm/jit/codegen-common.h"
83 #if defined(ENABLE_DISASSEMBLER)
84 # include "vm/jit/disass.h"
87 #include "vm/jit/dseg.h"
88 #include "vm/jit/emit-common.h"
89 #include "vm/jit/jit.h"
90 #include "vm/jit/linenumbertable.h"
91 #include "vm/jit/methodheader.h"
92 #include "vm/jit/methodtree.h"
93 #include "vm/jit/patcher-common.h"
94 #include "vm/jit/replace.h"
95 #if defined(ENABLE_SSA)
96 # include "vm/jit/optimizing/lsra.h"
97 # include "vm/jit/optimizing/ssa.h"
99 #include "vm/jit/stacktrace.hpp"
100 #include "vm/jit/trace.hpp"
102 #if defined(ENABLE_INTRP)
103 #include "vm/jit/intrp/intrp.h"
106 #if defined(ENABLE_VMLOG)
107 #include <vmlog_cacao.h>
113 /* codegen_init ****************************************************************
117 *******************************************************************************/
119 void codegen_init(void)
124 /* codegen_setup ***************************************************************
126 Allocates and initialises code area, data area and references.
128 *******************************************************************************/
130 void codegen_setup(jitdata *jd)
135 /* get required compiler data */
140 /* initialize members */
144 cd->mcodebase = DMNEW(u1, MCODEINITSIZE);
145 cd->mcodeend = cd->mcodebase + MCODEINITSIZE;
146 cd->mcodesize = MCODEINITSIZE;
148 /* initialize mcode variables */
150 cd->mcodeptr = cd->mcodebase;
151 cd->lastmcodeptr = cd->mcodebase;
153 #if defined(ENABLE_INTRP)
154 /* native dynamic superinstructions variables */
157 cd->ncodebase = DMNEW(u1, NCODEINITSIZE);
158 cd->ncodesize = NCODEINITSIZE;
160 /* initialize ncode variables */
162 cd->ncodeptr = cd->ncodebase;
164 cd->lastinstwithoutdispatch = ~0; /* no inst without dispatch */
165 cd->superstarts = NULL;
172 cd->jumpreferences = NULL;
174 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
175 cd->datareferences = NULL;
178 cd->brancheslabel = list_create_dump(OFFSET(branch_label_ref_t, linkage));
179 cd->linenumbers = list_create_dump(OFFSET(linenumbertable_list_entry_t, linkage));
183 /* codegen_reset ***************************************************************
185 Resets the codegen data structure so we can recompile the method.
187 *******************************************************************************/
189 static void codegen_reset(jitdata *jd)
195 /* get required compiler data */
200 /* reset error flag */
202 cd->flags &= ~CODEGENDATA_FLAG_ERROR;
204 /* reset some members, we reuse the code memory already allocated
205 as this should have almost the correct size */
207 cd->mcodeptr = cd->mcodebase;
208 cd->lastmcodeptr = cd->mcodebase;
213 cd->jumpreferences = NULL;
215 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
216 cd->datareferences = NULL;
219 cd->brancheslabel = list_create_dump(OFFSET(branch_label_ref_t, linkage));
220 cd->linenumbers = list_create_dump(OFFSET(linenumbertable_list_entry_t, linkage));
222 /* We need to clear the mpc and the branch references from all
223 basic blocks as they will definitely change. */
225 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
227 bptr->branchrefs = NULL;
230 /* We need to clear all the patcher references from the codeinfo
231 since they all will be regenerated */
233 patcher_list_reset(code);
235 #if defined(ENABLE_REPLACEMENT)
236 code->rplpoints = NULL;
237 code->rplpointcount = 0;
238 code->regalloc = NULL;
239 code->regalloccount = 0;
240 code->globalcount = 0;
245 /* codegen_generate ************************************************************
247 Generates the code for the currently compiled method.
249 *******************************************************************************/
251 bool codegen_generate(jitdata *jd)
255 /* get required compiler data */
259 /* call the machine-dependent code generation function */
261 if (!codegen_emit(jd))
264 /* check for an error */
266 if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
267 /* check for long-branches flag, if it is set we recompile the
272 log_message_method("Re-generating code: ", jd->m);
275 /* XXX maybe we should tag long-branches-methods for recompilation */
277 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
278 /* we have to reset the codegendata structure first */
282 /* and restart the compiler run */
284 if (!codegen_emit(jd))
288 vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
293 log_message_method("Re-generating code done: ", jd->m);
297 /* reallocate the memory and finish the code generation */
301 /* everything's ok */
307 /* codegen_close ***************************************************************
311 *******************************************************************************/
313 void codegen_close(void)
315 /* TODO: release avl tree on i386 and x86_64 */
319 /* codegen_increase ************************************************************
323 *******************************************************************************/
325 void codegen_increase(codegendata *cd)
329 /* save old mcodebase pointer */
331 oldmcodebase = cd->mcodebase;
333 /* reallocate to new, doubled memory */
335 cd->mcodebase = DMREALLOC(cd->mcodebase,
340 cd->mcodeend = cd->mcodebase + cd->mcodesize;
342 /* set new mcodeptr */
344 cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
346 #if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(__M68K__) || defined(ENABLE_INTRP) \
347 || defined(__SPARC_64__)
348 /* adjust the pointer to the last patcher position */
350 if (cd->lastmcodeptr != NULL)
351 cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
356 /* codegen_ncode_increase ******************************************************
360 *******************************************************************************/
362 #if defined(ENABLE_INTRP)
363 u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
367 /* save old ncodebase pointer */
369 oldncodebase = cd->ncodebase;
371 /* reallocate to new, doubled memory */
373 cd->ncodebase = DMREALLOC(cd->ncodebase,
379 /* return the new ncodeptr */
381 return (cd->ncodebase + (ncodeptr - oldncodebase));
386 /* codegen_add_branch_ref ******************************************************
388 Prepends an branch to the list.
390 *******************************************************************************/
392 void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
397 STATISTICS(count_branches_unresolved++);
399 /* calculate the mpc of the branch instruction */
401 branchmpc = cd->mcodeptr - cd->mcodebase;
403 br = DNEW(branchref);
405 br->branchmpc = branchmpc;
406 br->condition = condition;
408 br->options = options;
409 br->next = target->branchrefs;
411 target->branchrefs = br;
415 /* codegen_resolve_branchrefs **************************************************
417 Resolves and patches the branch references of a given basic block.
419 *******************************************************************************/
421 void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
426 /* Save the mcodeptr because in the branch emitting functions
427 we generate code somewhere inside already generated code,
428 but we're still in the actual code generation phase. */
430 mcodeptr = cd->mcodeptr;
432 /* just to make sure */
434 assert(bptr->mpc >= 0);
436 for (br = bptr->branchrefs; br != NULL; br = br->next) {
437 /* temporary set the mcodeptr */
439 cd->mcodeptr = cd->mcodebase + br->branchmpc;
441 /* emit_bccz and emit_branch emit the correct code, even if we
442 pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
444 emit_bccz(cd, bptr, br->condition, br->reg, br->options);
447 /* restore mcodeptr */
449 cd->mcodeptr = mcodeptr;
453 /* codegen_branch_label_add ****************************************************
455 Append an branch to the label-branch list.
457 *******************************************************************************/
459 void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
462 branch_label_ref_t *br;
465 /* Get the label list. */
467 l = cd->brancheslabel;
469 /* calculate the current mpc */
471 mpc = cd->mcodeptr - cd->mcodebase;
473 br = DNEW(branch_label_ref_t);
477 br->condition = condition;
479 br->options = options;
481 /* Add the branch to the list. */
483 list_add_last(l, br);
487 /* codegen_set_replacement_point_notrap ****************************************
489 Record the position of a non-trappable replacement point.
491 *******************************************************************************/
493 #if defined(ENABLE_REPLACEMENT)
495 void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
497 void codegen_set_replacement_point_notrap(codegendata *cd)
500 assert(cd->replacementpoint);
501 assert(cd->replacementpoint->type == type);
502 assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
504 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
506 cd->replacementpoint++;
508 #endif /* defined(ENABLE_REPLACEMENT) */
511 /* codegen_set_replacement_point ***********************************************
513 Record the position of a trappable replacement point.
515 *******************************************************************************/
517 #if defined(ENABLE_REPLACEMENT)
519 void codegen_set_replacement_point(codegendata *cd, s4 type)
521 void codegen_set_replacement_point(codegendata *cd)
524 assert(cd->replacementpoint);
525 assert(cd->replacementpoint->type == type);
526 assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
528 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
530 cd->replacementpoint++;
533 /* XXX actually we should use an own REPLACEMENT_NOPS here! */
534 if (opt_TestReplacement)
538 /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
540 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
542 #endif /* defined(ENABLE_REPLACEMENT) */
545 /* codegen_finish **************************************************************
547 Finishes the code generation. A new memory, large enough for both
548 data and code, is allocated and data and code are copied together
549 to their final layout, unresolved jumps are resolved, ...
551 *******************************************************************************/
553 void codegen_finish(jitdata *jd)
558 #if defined(ENABLE_INTRP)
566 /* get required compiler data */
571 /* prevent compiler warning */
573 #if defined(ENABLE_INTRP)
577 /* calculate the code length */
579 mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
581 #if defined(ENABLE_STATISTICS)
583 count_code_len += mcodelen;
584 count_data_len += cd->dseglen;
588 alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
590 #if defined(ENABLE_INTRP)
592 ncodelen = cd->ncodeptr - cd->ncodebase;
594 ncodelen = 0; /* avoid compiler warning */
598 cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
599 alignedlen = alignedmcodelen + cd->dseglen;
601 #if defined(ENABLE_INTRP)
603 alignedlen += ncodelen;
607 /* allocate new memory */
609 code->mcodelength = mcodelen + cd->dseglen;
610 code->mcode = CNEW(u1, alignedlen);
612 /* set the entrypoint of the method */
614 assert(code->entrypoint == NULL);
615 code->entrypoint = epoint = (code->mcode + cd->dseglen);
617 /* fill the data segment (code->entrypoint must already be set!) */
621 /* copy code to the new location */
623 MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
625 #if defined(ENABLE_INTRP)
626 /* relocate native dynamic superinstruction code (if any) */
629 cd->mcodebase = code->entrypoint;
632 u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
634 MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
636 /* flush the instruction and data caches */
638 md_cacheflush(ncodebase, ncodelen);
640 /* set some cd variables for dynamic_super_rerwite */
642 cd->ncodebase = ncodebase;
645 cd->ncodebase = NULL;
648 dynamic_super_rewrite(cd);
652 /* Create the exception table. */
654 exceptiontable_create(jd);
656 /* Create the linenumber table. */
658 linenumbertable_create(jd);
660 /* jump table resolving */
662 for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
664 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
665 (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
667 JITCACHE_ADD_CACHED_REF(code, CRT_JUMPREFERENCE, jr->target->mpc, jr->tablepos);
670 /* patcher resolving */
674 #if defined(ENABLE_REPLACEMENT)
675 /* replacement point resolving */
680 rp = code->rplpoints;
681 for (i=0; i<code->rplpointcount; ++i, ++rp) {
682 rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
685 #endif /* defined(ENABLE_REPLACEMENT) */
687 /* Insert method into methodtree to find the entrypoint. */
689 methodtree_insert(code->entrypoint, code->entrypoint + mcodelen);
691 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
692 /* resolve data segment references */
694 dseg_resolve_datareferences(jd);
697 /* flush the instruction and data caches */
699 md_cacheflush(code->mcode, code->mcodelength);
703 /* codegen_generate_stub_compiler **********************************************
705 Wrapper for codegen_emit_stub_compiler.
708 pointer to the compiler stub code.
710 *******************************************************************************/
712 u1 *codegen_generate_stub_compiler(methodinfo *m)
716 ptrint *d; /* pointer to data memory */
717 u1 *c; /* pointer to code memory */
720 /* mark dump memory */
724 /* allocate required data structures */
729 jd->cd = DNEW(codegendata);
732 /* get required compiler data */
736 #if !defined(JIT_COMPILER_VIA_SIGNAL)
737 /* allocate code memory */
739 c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
741 /* set pointers correctly */
747 c = c + 3 * SIZEOF_VOID_P;
750 /* NOTE: The codeinfo pointer is actually a pointer to the
751 methodinfo (this fakes a codeinfo structure). */
753 d[0] = (ptrint) asm_call_jit_compiler;
755 d[2] = (ptrint) &d[1]; /* fake code->m */
757 /* call the emit function */
759 codegen_emit_stub_compiler(jd);
761 #if defined(ENABLE_STATISTICS)
763 count_cstub_len += 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
768 md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
770 /* Allocate code memory. */
772 c = CNEW(uint8_t, 2 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
774 /* Set pointers correctly. */
780 c = c + 2 * SIZEOF_VOID_P;
783 /* NOTE: The codeinfo pointer is actually a pointer to the
784 methodinfo (this fakes a codeinfo structure). */
787 d[1] = (ptrint) &d[0]; /* fake code->m */
789 /* Emit the trap instruction. */
791 emit_trap_compiler(cd);
793 #if defined(ENABLE_STATISTICS)
795 count_cstub_len += 2 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
800 md_cacheflush(cd->mcodebase, 2 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
803 /* release dump memory */
807 /* return native stub code */
813 /* codegen_generate_stub_builtin ***********************************************
815 Wrapper for codegen_emit_stub_native.
817 *******************************************************************************/
819 void codegen_generate_stub_builtin(methodinfo *m, builtintable_entry *bte)
826 /* mark dump memory */
830 /* Create JIT data structure. */
832 jd = jit_jitdata_new(m);
834 /* Get required compiler data. */
838 /* Stubs are non-leaf methods. */
840 code_unflag_leafmethod(code);
842 /* setup code generation stuff */
846 /* Set the number of native arguments we need to skip. */
850 /* generate the code */
852 #if defined(ENABLE_JIT)
853 # if defined(ENABLE_INTRP)
856 assert(bte->fp != NULL);
857 codegen_emit_stub_native(jd, bte->md, bte->fp, skipparams);
858 # if defined(ENABLE_INTRP)
863 /* reallocate the memory and finish the code generation */
867 /* set the stub entry point in the builtin table */
869 bte->stub = code->entrypoint;
871 #if defined(ENABLE_STATISTICS)
873 size_stub_native += code->mcodelength;
876 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
877 /* disassemble native stub */
879 if (opt_DisassembleStubs) {
880 codegen_disassemble_stub(m,
881 (u1 *) (ptrint) code->entrypoint,
882 (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
884 /* show data segment */
886 if (opt_showddatasegment)
889 #endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
897 /* codegen_generate_stub_native ************************************************
899 Wrapper for codegen_emit_stub_native.
902 the codeinfo representing the stub code.
904 *******************************************************************************/
906 codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
915 /* mark dump memory */
919 /* Create JIT data structure. */
921 jd = jit_jitdata_new(m);
923 /* Get required compiler data. */
927 /* Stubs are non-leaf methods. */
929 code_unflag_leafmethod(code);
931 /* set the flags for the current JIT run */
933 #if defined(ENABLE_PROFILING)
935 jd->flags |= JITDATA_FLAG_INSTRUMENT;
939 jd->flags |= JITDATA_FLAG_VERBOSECALL;
941 /* setup code generation stuff */
943 #if defined(ENABLE_JIT)
944 # if defined(ENABLE_INTRP)
952 /* create new method descriptor with additional native parameters */
956 /* Set the number of native arguments we need to skip. */
958 if (m->flags & ACC_STATIC)
963 nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
964 md->paramcount * sizeof(typedesc) +
965 skipparams * sizeof(typedesc));
967 nmd->paramcount = md->paramcount + skipparams;
969 nmd->params = DMNEW(paramdesc, nmd->paramcount);
971 nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer */
973 if (m->flags & ACC_STATIC)
974 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer */
976 MCOPY(nmd->paramtypes + skipparams, md->paramtypes, typedesc,
979 #if defined(ENABLE_JIT)
980 # if defined(ENABLE_INTRP)
983 /* pre-allocate the arguments for the native ABI */
985 md_param_alloc_native(nmd);
988 /* generate the code */
990 #if defined(ENABLE_JIT)
991 # if defined(ENABLE_INTRP)
993 intrp_createnativestub(f, jd, nmd);
996 codegen_emit_stub_native(jd, nmd, f, skipparams);
998 intrp_createnativestub(f, jd, nmd);
1001 /* reallocate the memory and finish the code generation */
1005 #if defined(ENABLE_STATISTICS)
1006 /* must be done after codegen_finish() */
1009 size_stub_native += code->mcodelength;
1012 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
1013 /* disassemble native stub */
1015 if (opt_DisassembleStubs) {
1016 # if defined(ENABLE_DEBUG_FILTER)
1017 if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
1020 codegen_disassemble_stub(m,
1021 (u1 *) (ptrint) code->entrypoint,
1022 (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
1024 /* show data segment */
1026 if (opt_showddatasegment)
1030 #endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
1032 /* release memory */
1036 /* return native stub code */
1042 /* codegen_disassemble_nativestub **********************************************
1044 Disassembles the generated builtin or native stub.
1046 *******************************************************************************/
1048 #if defined(ENABLE_DISASSEMBLER)
1049 void codegen_disassemble_stub(methodinfo *m, u1 *start, u1 *end)
1051 printf("Stub code: ");
1052 if (m->clazz != NULL)
1053 utf_fprint_printable_ascii_classname(stdout, m->clazz->name);
1057 utf_fprint_printable_ascii(stdout, m->name);
1058 utf_fprint_printable_ascii(stdout, m->descriptor);
1059 printf("\nLength: %d\n\n", (s4) (end - start));
1061 DISASSEMBLE(start, end);
1066 /* codegen_start_native_call ***************************************************
1068 Prepares the stuff required for a native (JNI) function call:
1070 - adds a stackframe info structure to the chain, for stacktraces
1071 - prepares the local references table on the stack
1073 The layout of the native stub stackframe should look like this:
1075 +---------------------------+ <- java SP (of parent Java function)
1077 +---------------------------+ <- data SP
1079 | stackframe info structure |
1081 +---------------------------+
1083 | local references table |
1085 +---------------------------+
1087 | saved registers (if any) |
1089 +---------------------------+
1091 | arguments (if any) |
1093 +---------------------------+ <- current SP (native stub)
1095 *******************************************************************************/
1097 java_handle_t *codegen_start_native_call(u1 *sp, u1 *pv)
1099 stackframeinfo_t *sfi;
1100 localref_table *lrt;
1107 uint64_t *arg_stack;
1109 STATISTICS(count_calls_java_to_native++);
1111 /* Get the methodinfo. */
1113 m = code_get_methodinfo_for_pv(pv);
1117 framesize = *((int32_t *) (pv + FrameSize));
1119 assert(framesize >= sizeof(stackframeinfo_t) + sizeof(localref_table));
1121 /* calculate needed values */
1123 #if defined(__ALPHA__) || defined(__ARM__)
1124 datasp = sp + framesize - SIZEOF_VOID_P;
1125 javasp = sp + framesize;
1126 arg_regs = (uint64_t *) sp;
1127 arg_stack = (uint64_t *) javasp;
1128 #elif defined(__MIPS__)
1129 /* MIPS always uses 8 bytes to store the RA */
1130 datasp = sp + framesize - 8;
1131 javasp = sp + framesize;
1132 #elif defined(__S390__)
1133 datasp = sp + framesize - 8;
1134 javasp = sp + framesize;
1135 arg_regs = (uint64_t *) (sp + 96);
1136 arg_stack = (uint64_t *) javasp;
1137 #elif defined(__I386__) || defined(__M68K__) || defined(__X86_64__)
1138 datasp = sp + framesize;
1139 javasp = sp + framesize + SIZEOF_VOID_P;
1140 arg_regs = (uint64_t *) sp;
1141 arg_stack = (uint64_t *) javasp;
1142 #elif defined(__POWERPC__)
1143 datasp = sp + framesize;
1144 javasp = sp + framesize;
1145 arg_regs = (uint64_t *) (sp + LA_SIZE + 4 * SIZEOF_VOID_P);
1146 arg_stack = (uint64_t *) javasp;
1147 #elif defined(__POWERPC64__)
1148 datasp = sp + framesize;
1149 javasp = sp + framesize;
1150 arg_regs = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 4 * SIZEOF_VOID_P);
1151 arg_stack = (uint64_t *) javasp;
1153 /* XXX is was unable to do this port for SPARC64, sorry. (-michi) */
1154 /* XXX maybe we need to pass the RA as argument there */
1155 vm_abort("codegen_start_native_call: unsupported architecture");
1158 /* get data structures from stack */
1160 sfi = (stackframeinfo_t *) (datasp - sizeof(stackframeinfo_t));
1161 lrt = (localref_table *) (datasp - sizeof(stackframeinfo_t) -
1162 sizeof(localref_table));
1164 #if defined(ENABLE_JNI)
1165 /* add current JNI local references table to this thread */
1167 localref_table_add(lrt);
1170 #if !defined(NDEBUG)
1171 # if defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__)
1172 /* print the call-trace if necesarry */
1173 /* BEFORE: filling the local reference table */
1175 if (opt_TraceJavaCalls)
1176 trace_java_call_enter(m, arg_regs, arg_stack);
1180 #if defined(ENABLE_HANDLES)
1181 /* place all references into the local reference table */
1182 /* BEFORE: creating stackframeinfo */
1184 localref_native_enter(m, arg_regs, arg_stack);
1187 /* Add a stackframeinfo for this native method. We don't have RA
1188 and XPC here. These are determined in
1189 stacktrace_stackframeinfo_add. */
1191 stacktrace_stackframeinfo_add(sfi, pv, sp, NULL, NULL);
1193 /* Return a wrapped classinfo for static methods. */
1195 if (m->flags & ACC_STATIC)
1196 return (java_handle_t *) LLNI_classinfo_wrap(m->clazz);
1202 /* codegen_finish_native_call **************************************************
1204 Removes the stuff required for a native (JNI) function call.
1205 Additionally it checks for an exceptions and in case, get the
1206 exception object and clear the pointer.
1208 *******************************************************************************/
1210 java_object_t *codegen_finish_native_call(u1 *sp, u1 *pv)
1212 stackframeinfo_t *sfi;
1222 /* get information from method header */
1224 code = code_get_codeinfo_for_pv(pv);
1226 framesize = *((int32_t *) (pv + FrameSize));
1230 /* get the methodinfo */
1235 /* calculate needed values */
1237 #if defined(__ALPHA__) || defined(__ARM__)
1238 datasp = sp + framesize - SIZEOF_VOID_P;
1239 ret_regs = (uint64_t *) sp;
1240 #elif defined(__MIPS__)
1241 /* MIPS always uses 8 bytes to store the RA */
1242 datasp = sp + framesize - 8;
1243 #elif defined(__S390__)
1244 datasp = sp + framesize - 8;
1245 ret_regs = (uint64_t *) (sp + 96);
1246 #elif defined(__I386__)
1247 datasp = sp + framesize;
1248 ret_regs = (uint64_t *) (sp + 2 * SIZEOF_VOID_P);
1249 #elif defined(__M68K__)
1250 datasp = sp + framesize;
1251 ret_regs = (uint64_t *) (sp + 2 * 8);
1252 #elif defined(__X86_64__)
1253 datasp = sp + framesize;
1254 ret_regs = (uint64_t *) sp;
1255 #elif defined(__POWERPC__)
1256 datasp = sp + framesize;
1257 ret_regs = (uint64_t *) (sp + LA_SIZE + 2 * SIZEOF_VOID_P);
1258 #elif defined(__POWERPC64__)
1259 datasp = sp + framesize;
1260 ret_regs = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 2 * SIZEOF_VOID_P);
1262 vm_abort("codegen_finish_native_call: unsupported architecture");
1265 /* get data structures from stack */
1267 sfi = (stackframeinfo_t *) (datasp - sizeof(stackframeinfo_t));
1269 /* Remove current stackframeinfo from chain. */
1271 stacktrace_stackframeinfo_remove(sfi);
1273 #if defined(ENABLE_HANDLES)
1274 /* unwrap the return value from the local reference table */
1275 /* AFTER: removing the stackframeinfo */
1276 /* BEFORE: releasing the local reference table */
1278 localref_native_exit(m, ret_regs);
1281 /* get and unwrap the exception */
1282 /* AFTER: removing the stackframe info */
1283 /* BEFORE: releasing the local reference table */
1285 e = exceptions_get_and_clear_exception();
1288 #if defined(ENABLE_JNI)
1289 /* release JNI local references table for this thread */
1291 localref_frame_pop_all();
1292 localref_table_remove();
1295 #if !defined(NDEBUG)
1296 # if defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__)
1297 /* print the call-trace if necesarry */
1298 /* AFTER: unwrapping the return value */
1300 if (opt_TraceJavaCalls)
1301 trace_java_call_exit(m, ret_regs);
1309 /* removecompilerstub **********************************************************
1311 Deletes a compilerstub from memory (simply by freeing it).
1313 *******************************************************************************/
1315 void removecompilerstub(u1 *stub)
1317 /* pass size 1 to keep the intern function happy */
1319 CFREE((void *) stub, 1);
1323 /* removenativestub ************************************************************
1325 Removes a previously created native-stub from memory.
1327 *******************************************************************************/
1329 void removenativestub(u1 *stub)
1331 /* pass size 1 to keep the intern function happy */
1333 CFREE((void *) stub, 1);
1337 /* codegen_reg_of_var **********************************************************
1339 This function determines a register, to which the result of an
1340 operation should go, when it is ultimatively intended to store the
1341 result in pseudoregister v. If v is assigned to an actual
1342 register, this register will be returned. Otherwise (when v is
1343 spilled) this function returns tempregnum. If not already done,
1344 regoff and flags are set in the stack location.
1346 *******************************************************************************/
1348 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
1350 if (!(v->flags & INMEMORY))
1351 return v->vv.regoff;
1357 /* codegen_reg_of_dst **********************************************************
1359 This function determines a register, to which the result of an
1360 operation should go, when it is ultimatively intended to store the
1361 result in iptr->dst.var. If dst.var is assigned to an actual
1362 register, this register will be returned. Otherwise (when it is
1363 spilled) this function returns tempregnum. If not already done,
1364 regoff and flags are set in the stack location.
1366 *******************************************************************************/
1368 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
1370 return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
1374 /* codegen_emit_phi_moves ****************************************************
1376 Emits phi moves at the end of the basicblock.
1378 *******************************************************************************/
1380 #if defined(ENABLE_SSA)
1381 void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
1394 /* Moves from phi functions with highest indices have to be */
1395 /* inserted first, since this is the order as is used for */
1396 /* conflict resolution */
1398 for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
1399 lt_d = ls->phi_moves[bptr->nr][i][0];
1400 lt_s = ls->phi_moves[bptr->nr][i][1];
1401 #if defined(SSA_DEBUG_VERBOSE)
1403 printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
1405 if (lt_s == UNUSED) {
1406 #if defined(SSA_DEBUG_VERBOSE)
1408 printf(" ... not processed \n");
1413 d = VAR(ls->lifetime[lt_d].v_index);
1414 s = VAR(ls->lifetime[lt_s].v_index);
1417 if (d->type == -1) {
1418 #if defined(SSA_DEBUG_VERBOSE)
1420 printf("...returning - phi lifetimes where joined\n");
1425 if (s->type == -1) {
1426 #if defined(SSA_DEBUG_VERBOSE)
1428 printf("...returning - phi lifetimes where joined\n");
1434 tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
1435 tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
1436 emit_copy(jd, &tmp_i);
1438 #if defined(SSA_DEBUG_VERBOSE)
1439 if (compileverbose) {
1440 if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
1442 printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1444 else if (IS_INMEMORY(s->flags)) {
1446 printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1448 else if (IS_INMEMORY(d->flags)) {
1450 printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1454 printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1458 #endif /* defined(SSA_DEBUG_VERBOSE) */
1461 #endif /* defined(ENABLE_SSA) */
1464 /* REMOVEME When we have exception handling in C. */
1466 void *md_asm_codegen_get_pv_from_pc(void *ra)
1468 return md_codegen_get_pv_from_pc(ra);
1473 * These are local overrides for various environment variables in Emacs.
1474 * Please do not remove this and leave it at the end of the file, where
1475 * Emacs will automagically detect them.
1476 * ---------------------------------------------------------------------
1479 * indent-tabs-mode: t
1483 * vim:noexpandtab:sw=4:ts=4: