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 #include "threads/thread.hpp"
67 #include "vm/builtin.h"
68 #include "vm/exceptions.hpp"
69 #include "vm/method.h"
70 #include "vm/options.h"
71 #include "vm/string.hpp"
73 # include "vm/statistics.h"
76 #include "vm/jit/abi.h"
77 #include "vm/jit/asmpart.h"
78 #include "vm/jit/code.h"
79 #include "vm/jit/codegen-common.h"
81 #if defined(ENABLE_DISASSEMBLER)
82 # include "vm/jit/disass.h"
85 #include "vm/jit/dseg.h"
86 #include "vm/jit/emit-common.h"
87 #include "vm/jit/jit.h"
88 #include "vm/jit/linenumbertable.h"
89 #include "vm/jit/methodheader.h"
90 #include "vm/jit/methodtree.h"
91 #include "vm/jit/patcher-common.h"
92 #include "vm/jit/replace.h"
93 #if defined(ENABLE_SSA)
94 # include "vm/jit/optimizing/lsra.h"
95 # include "vm/jit/optimizing/ssa.h"
97 #include "vm/jit/stacktrace.hpp"
98 #include "vm/jit/trace.hpp"
100 #if defined(ENABLE_INTRP)
101 #include "vm/jit/intrp/intrp.h"
104 #if defined(ENABLE_VMLOG)
105 #include <vmlog_cacao.h>
111 /* codegen_init ****************************************************************
115 *******************************************************************************/
117 void codegen_init(void)
122 /* codegen_setup ***************************************************************
124 Allocates and initialises code area, data area and references.
126 *******************************************************************************/
128 void codegen_setup(jitdata *jd)
133 /* get required compiler data */
138 /* initialize members */
142 cd->mcodebase = DMNEW(u1, MCODEINITSIZE);
143 cd->mcodeend = cd->mcodebase + MCODEINITSIZE;
144 cd->mcodesize = MCODEINITSIZE;
146 /* initialize mcode variables */
148 cd->mcodeptr = cd->mcodebase;
149 cd->lastmcodeptr = cd->mcodebase;
151 #if defined(ENABLE_INTRP)
152 /* native dynamic superinstructions variables */
155 cd->ncodebase = DMNEW(u1, NCODEINITSIZE);
156 cd->ncodesize = NCODEINITSIZE;
158 /* initialize ncode variables */
160 cd->ncodeptr = cd->ncodebase;
162 cd->lastinstwithoutdispatch = ~0; /* no inst without dispatch */
163 cd->superstarts = NULL;
170 cd->jumpreferences = NULL;
172 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
173 cd->datareferences = NULL;
176 cd->brancheslabel = list_create_dump(OFFSET(branch_label_ref_t, linkage));
177 cd->linenumbers = list_create_dump(OFFSET(linenumbertable_list_entry_t, linkage));
181 /* codegen_reset ***************************************************************
183 Resets the codegen data structure so we can recompile the method.
185 *******************************************************************************/
187 static void codegen_reset(jitdata *jd)
193 /* get required compiler data */
198 /* reset error flag */
200 cd->flags &= ~CODEGENDATA_FLAG_ERROR;
202 /* reset some members, we reuse the code memory already allocated
203 as this should have almost the correct size */
205 cd->mcodeptr = cd->mcodebase;
206 cd->lastmcodeptr = cd->mcodebase;
211 cd->jumpreferences = NULL;
213 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
214 cd->datareferences = NULL;
217 cd->brancheslabel = list_create_dump(OFFSET(branch_label_ref_t, linkage));
218 cd->linenumbers = list_create_dump(OFFSET(linenumbertable_list_entry_t, linkage));
220 /* We need to clear the mpc and the branch references from all
221 basic blocks as they will definitely change. */
223 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
225 bptr->branchrefs = NULL;
228 /* We need to clear all the patcher references from the codeinfo
229 since they all will be regenerated */
231 patcher_list_reset(code);
233 #if defined(ENABLE_REPLACEMENT)
234 code->rplpoints = NULL;
235 code->rplpointcount = 0;
236 code->regalloc = NULL;
237 code->regalloccount = 0;
238 code->globalcount = 0;
243 /* codegen_generate ************************************************************
245 Generates the code for the currently compiled method.
247 *******************************************************************************/
249 bool codegen_generate(jitdata *jd)
253 /* get required compiler data */
257 /* call the machine-dependent code generation function */
259 if (!codegen_emit(jd))
262 /* check for an error */
264 if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
265 /* check for long-branches flag, if it is set we recompile the
270 log_message_method("Re-generating code: ", jd->m);
273 /* XXX maybe we should tag long-branches-methods for recompilation */
275 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
276 /* we have to reset the codegendata structure first */
280 /* and restart the compiler run */
282 if (!codegen_emit(jd))
286 vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
291 log_message_method("Re-generating code done: ", jd->m);
295 /* reallocate the memory and finish the code generation */
299 /* everything's ok */
305 /* codegen_close ***************************************************************
309 *******************************************************************************/
311 void codegen_close(void)
313 /* TODO: release avl tree on i386 and x86_64 */
317 /* codegen_increase ************************************************************
321 *******************************************************************************/
323 void codegen_increase(codegendata *cd)
327 /* save old mcodebase pointer */
329 oldmcodebase = cd->mcodebase;
331 /* reallocate to new, doubled memory */
333 cd->mcodebase = DMREALLOC(cd->mcodebase,
338 cd->mcodeend = cd->mcodebase + cd->mcodesize;
340 /* set new mcodeptr */
342 cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
344 #if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(__M68K__) || defined(ENABLE_INTRP) \
345 || defined(__SPARC_64__)
346 /* adjust the pointer to the last patcher position */
348 if (cd->lastmcodeptr != NULL)
349 cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
354 /* codegen_ncode_increase ******************************************************
358 *******************************************************************************/
360 #if defined(ENABLE_INTRP)
361 u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
365 /* save old ncodebase pointer */
367 oldncodebase = cd->ncodebase;
369 /* reallocate to new, doubled memory */
371 cd->ncodebase = DMREALLOC(cd->ncodebase,
377 /* return the new ncodeptr */
379 return (cd->ncodebase + (ncodeptr - oldncodebase));
384 /* codegen_add_branch_ref ******************************************************
386 Prepends an branch to the list.
388 *******************************************************************************/
390 void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
395 STATISTICS(count_branches_unresolved++);
397 /* calculate the mpc of the branch instruction */
399 branchmpc = cd->mcodeptr - cd->mcodebase;
401 br = DNEW(branchref);
403 br->branchmpc = branchmpc;
404 br->condition = condition;
406 br->options = options;
407 br->next = target->branchrefs;
409 target->branchrefs = br;
413 /* codegen_resolve_branchrefs **************************************************
415 Resolves and patches the branch references of a given basic block.
417 *******************************************************************************/
419 void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
424 /* Save the mcodeptr because in the branch emitting functions
425 we generate code somewhere inside already generated code,
426 but we're still in the actual code generation phase. */
428 mcodeptr = cd->mcodeptr;
430 /* just to make sure */
432 assert(bptr->mpc >= 0);
434 for (br = bptr->branchrefs; br != NULL; br = br->next) {
435 /* temporary set the mcodeptr */
437 cd->mcodeptr = cd->mcodebase + br->branchmpc;
439 /* emit_bccz and emit_branch emit the correct code, even if we
440 pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
442 emit_bccz(cd, bptr, br->condition, br->reg, br->options);
445 /* restore mcodeptr */
447 cd->mcodeptr = mcodeptr;
451 /* codegen_branch_label_add ****************************************************
453 Append an branch to the label-branch list.
455 *******************************************************************************/
457 void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
460 branch_label_ref_t *br;
463 /* Get the label list. */
465 l = cd->brancheslabel;
467 /* calculate the current mpc */
469 mpc = cd->mcodeptr - cd->mcodebase;
471 br = DNEW(branch_label_ref_t);
475 br->condition = condition;
477 br->options = options;
479 /* Add the branch to the list. */
481 list_add_last(l, br);
485 /* codegen_set_replacement_point_notrap ****************************************
487 Record the position of a non-trappable replacement point.
489 *******************************************************************************/
491 #if defined(ENABLE_REPLACEMENT)
493 void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
495 void codegen_set_replacement_point_notrap(codegendata *cd)
498 assert(cd->replacementpoint);
499 assert(cd->replacementpoint->type == type);
500 assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
502 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
504 cd->replacementpoint++;
506 #endif /* defined(ENABLE_REPLACEMENT) */
509 /* codegen_set_replacement_point ***********************************************
511 Record the position of a trappable replacement point.
513 *******************************************************************************/
515 #if defined(ENABLE_REPLACEMENT)
517 void codegen_set_replacement_point(codegendata *cd, s4 type)
519 void codegen_set_replacement_point(codegendata *cd)
522 assert(cd->replacementpoint);
523 assert(cd->replacementpoint->type == type);
524 assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
526 cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
528 cd->replacementpoint++;
531 /* XXX actually we should use an own REPLACEMENT_NOPS here! */
532 if (opt_TestReplacement)
536 /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
538 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
540 #endif /* defined(ENABLE_REPLACEMENT) */
543 /* codegen_finish **************************************************************
545 Finishes the code generation. A new memory, large enough for both
546 data and code, is allocated and data and code are copied together
547 to their final layout, unresolved jumps are resolved, ...
549 *******************************************************************************/
551 void codegen_finish(jitdata *jd)
556 #if defined(ENABLE_INTRP)
564 /* get required compiler data */
569 /* prevent compiler warning */
571 #if defined(ENABLE_INTRP)
575 /* calculate the code length */
577 mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
579 #if defined(ENABLE_STATISTICS)
581 count_code_len += mcodelen;
582 count_data_len += cd->dseglen;
586 alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
588 #if defined(ENABLE_INTRP)
590 ncodelen = cd->ncodeptr - cd->ncodebase;
592 ncodelen = 0; /* avoid compiler warning */
596 cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
597 alignedlen = alignedmcodelen + cd->dseglen;
599 #if defined(ENABLE_INTRP)
601 alignedlen += ncodelen;
605 /* allocate new memory */
607 code->mcodelength = mcodelen + cd->dseglen;
608 code->mcode = CNEW(u1, alignedlen);
610 /* set the entrypoint of the method */
612 assert(code->entrypoint == NULL);
613 code->entrypoint = epoint = (code->mcode + cd->dseglen);
615 /* fill the data segment (code->entrypoint must already be set!) */
619 /* copy code to the new location */
621 MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
623 #if defined(ENABLE_INTRP)
624 /* relocate native dynamic superinstruction code (if any) */
627 cd->mcodebase = code->entrypoint;
630 u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
632 MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
634 /* flush the instruction and data caches */
636 md_cacheflush(ncodebase, ncodelen);
638 /* set some cd variables for dynamic_super_rerwite */
640 cd->ncodebase = ncodebase;
643 cd->ncodebase = NULL;
646 dynamic_super_rewrite(cd);
650 /* Create the exception table. */
652 exceptiontable_create(jd);
654 /* Create the linenumber table. */
656 linenumbertable_create(jd);
658 /* jump table resolving */
660 for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
661 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
662 (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
664 /* patcher resolving */
668 #if defined(ENABLE_REPLACEMENT)
669 /* replacement point resolving */
674 rp = code->rplpoints;
675 for (i=0; i<code->rplpointcount; ++i, ++rp) {
676 rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
679 #endif /* defined(ENABLE_REPLACEMENT) */
681 /* Insert method into methodtree to find the entrypoint. */
683 methodtree_insert(code->entrypoint, code->entrypoint + mcodelen);
685 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
686 /* resolve data segment references */
688 dseg_resolve_datareferences(jd);
691 /* flush the instruction and data caches */
693 md_cacheflush(code->mcode, code->mcodelength);
697 /* codegen_generate_stub_compiler **********************************************
699 Wrapper for codegen_emit_stub_compiler.
702 pointer to the compiler stub code.
704 *******************************************************************************/
706 u1 *codegen_generate_stub_compiler(methodinfo *m)
710 ptrint *d; /* pointer to data memory */
711 u1 *c; /* pointer to code memory */
714 /* mark dump memory */
718 /* allocate required data structures */
723 jd->cd = DNEW(codegendata);
726 /* get required compiler data */
730 #if !defined(JIT_COMPILER_VIA_SIGNAL)
731 /* allocate code memory */
733 c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
735 /* set pointers correctly */
741 c = c + 3 * SIZEOF_VOID_P;
744 /* NOTE: The codeinfo pointer is actually a pointer to the
745 methodinfo (this fakes a codeinfo structure). */
747 d[0] = (ptrint) asm_call_jit_compiler;
749 d[2] = (ptrint) &d[1]; /* fake code->m */
751 /* call the emit function */
753 codegen_emit_stub_compiler(jd);
755 #if defined(ENABLE_STATISTICS)
757 count_cstub_len += 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
762 md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
764 /* Allocate code memory. */
766 c = CNEW(uint8_t, 2 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
768 /* Set pointers correctly. */
774 c = c + 2 * SIZEOF_VOID_P;
777 /* NOTE: The codeinfo pointer is actually a pointer to the
778 methodinfo (this fakes a codeinfo structure). */
781 d[1] = (ptrint) &d[0]; /* fake code->m */
783 /* Emit the trap instruction. */
785 emit_trap_compiler(cd);
787 #if defined(ENABLE_STATISTICS)
789 count_cstub_len += 2 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
794 md_cacheflush(cd->mcodebase, 2 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
797 /* release dump memory */
801 /* return native stub code */
807 /* codegen_generate_stub_builtin ***********************************************
809 Wrapper for codegen_emit_stub_native.
811 *******************************************************************************/
813 void codegen_generate_stub_builtin(methodinfo *m, builtintable_entry *bte)
820 /* mark dump memory */
824 /* Create JIT data structure. */
826 jd = jit_jitdata_new(m);
828 /* Get required compiler data. */
832 /* Stubs are non-leaf methods. */
834 code_unflag_leafmethod(code);
836 /* setup code generation stuff */
840 /* Set the number of native arguments we need to skip. */
844 /* generate the code */
846 #if defined(ENABLE_JIT)
847 # if defined(ENABLE_INTRP)
850 assert(bte->fp != NULL);
851 codegen_emit_stub_native(jd, bte->md, bte->fp, skipparams);
852 # if defined(ENABLE_INTRP)
857 /* reallocate the memory and finish the code generation */
861 /* set the stub entry point in the builtin table */
863 bte->stub = code->entrypoint;
865 #if defined(ENABLE_STATISTICS)
867 size_stub_native += code->mcodelength;
870 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
871 /* disassemble native stub */
873 if (opt_DisassembleStubs) {
874 codegen_disassemble_stub(m,
875 (u1 *) (ptrint) code->entrypoint,
876 (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
878 /* show data segment */
880 if (opt_showddatasegment)
883 #endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
891 /* codegen_generate_stub_native ************************************************
893 Wrapper for codegen_emit_stub_native.
896 the codeinfo representing the stub code.
898 *******************************************************************************/
900 codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
909 /* mark dump memory */
913 /* Create JIT data structure. */
915 jd = jit_jitdata_new(m);
917 /* Get required compiler data. */
921 /* Stubs are non-leaf methods. */
923 code_unflag_leafmethod(code);
925 /* set the flags for the current JIT run */
927 #if defined(ENABLE_PROFILING)
929 jd->flags |= JITDATA_FLAG_INSTRUMENT;
933 jd->flags |= JITDATA_FLAG_VERBOSECALL;
935 /* setup code generation stuff */
937 #if defined(ENABLE_JIT)
938 # if defined(ENABLE_INTRP)
946 /* create new method descriptor with additional native parameters */
950 /* Set the number of native arguments we need to skip. */
952 if (m->flags & ACC_STATIC)
957 nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
958 md->paramcount * sizeof(typedesc) +
959 skipparams * sizeof(typedesc));
961 nmd->paramcount = md->paramcount + skipparams;
963 nmd->params = DMNEW(paramdesc, nmd->paramcount);
965 nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer */
967 if (m->flags & ACC_STATIC)
968 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer */
970 MCOPY(nmd->paramtypes + skipparams, md->paramtypes, typedesc,
973 #if defined(ENABLE_JIT)
974 # if defined(ENABLE_INTRP)
977 /* pre-allocate the arguments for the native ABI */
979 md_param_alloc_native(nmd);
982 /* generate the code */
984 #if defined(ENABLE_JIT)
985 # if defined(ENABLE_INTRP)
987 intrp_createnativestub(f, jd, nmd);
990 codegen_emit_stub_native(jd, nmd, f, skipparams);
992 intrp_createnativestub(f, jd, nmd);
995 /* reallocate the memory and finish the code generation */
999 #if defined(ENABLE_STATISTICS)
1000 /* must be done after codegen_finish() */
1003 size_stub_native += code->mcodelength;
1006 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
1007 /* disassemble native stub */
1009 if (opt_DisassembleStubs) {
1010 # if defined(ENABLE_DEBUG_FILTER)
1011 if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
1014 codegen_disassemble_stub(m,
1015 (u1 *) (ptrint) code->entrypoint,
1016 (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
1018 /* show data segment */
1020 if (opt_showddatasegment)
1024 #endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
1026 /* release memory */
1030 /* return native stub code */
1036 /* codegen_disassemble_nativestub **********************************************
1038 Disassembles the generated builtin or native stub.
1040 *******************************************************************************/
1042 #if defined(ENABLE_DISASSEMBLER)
1043 void codegen_disassemble_stub(methodinfo *m, u1 *start, u1 *end)
1045 printf("Stub code: ");
1046 if (m->clazz != NULL)
1047 utf_fprint_printable_ascii_classname(stdout, m->clazz->name);
1051 utf_fprint_printable_ascii(stdout, m->name);
1052 utf_fprint_printable_ascii(stdout, m->descriptor);
1053 printf("\nLength: %d\n\n", (s4) (end - start));
1055 DISASSEMBLE(start, end);
1060 /* codegen_start_native_call ***************************************************
1062 Prepares the stuff required for a native (JNI) function call:
1064 - adds a stackframe info structure to the chain, for stacktraces
1065 - prepares the local references table on the stack
1067 The layout of the native stub stackframe should look like this:
1069 +---------------------------+ <- java SP (of parent Java function)
1071 +---------------------------+ <- data SP
1073 | stackframe info structure |
1075 +---------------------------+
1077 | local references table |
1079 +---------------------------+
1081 | saved registers (if any) |
1083 +---------------------------+
1085 | arguments (if any) |
1087 +---------------------------+ <- current SP (native stub)
1089 *******************************************************************************/
1091 java_handle_t *codegen_start_native_call(u1 *sp, u1 *pv)
1093 stackframeinfo_t *sfi;
1094 localref_table *lrt;
1101 uint64_t *arg_stack;
1103 STATISTICS(count_calls_java_to_native++);
1105 /* Get the methodinfo. */
1107 m = code_get_methodinfo_for_pv(pv);
1111 framesize = *((int32_t *) (pv + FrameSize));
1113 assert(framesize >= sizeof(stackframeinfo_t) + sizeof(localref_table));
1115 /* calculate needed values */
1117 #if defined(__ALPHA__) || defined(__ARM__)
1118 datasp = sp + framesize - SIZEOF_VOID_P;
1119 javasp = sp + framesize;
1120 arg_regs = (uint64_t *) sp;
1121 arg_stack = (uint64_t *) javasp;
1122 #elif defined(__MIPS__)
1123 /* MIPS always uses 8 bytes to store the RA */
1124 datasp = sp + framesize - 8;
1125 javasp = sp + framesize;
1126 #elif defined(__S390__)
1127 datasp = sp + framesize - 8;
1128 javasp = sp + framesize;
1129 arg_regs = (uint64_t *) (sp + 96);
1130 arg_stack = (uint64_t *) javasp;
1131 #elif defined(__I386__) || defined(__M68K__) || defined(__X86_64__)
1132 datasp = sp + framesize;
1133 javasp = sp + framesize + SIZEOF_VOID_P;
1134 arg_regs = (uint64_t *) sp;
1135 arg_stack = (uint64_t *) javasp;
1136 #elif defined(__POWERPC__)
1137 datasp = sp + framesize;
1138 javasp = sp + framesize;
1139 arg_regs = (uint64_t *) (sp + LA_SIZE + 4 * SIZEOF_VOID_P);
1140 arg_stack = (uint64_t *) javasp;
1141 #elif defined(__POWERPC64__)
1142 datasp = sp + framesize;
1143 javasp = sp + framesize;
1144 arg_regs = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 4 * SIZEOF_VOID_P);
1145 arg_stack = (uint64_t *) javasp;
1147 /* XXX is was unable to do this port for SPARC64, sorry. (-michi) */
1148 /* XXX maybe we need to pass the RA as argument there */
1149 vm_abort("codegen_start_native_call: unsupported architecture");
1152 /* get data structures from stack */
1154 sfi = (stackframeinfo_t *) (datasp - sizeof(stackframeinfo_t));
1155 lrt = (localref_table *) (datasp - sizeof(stackframeinfo_t) -
1156 sizeof(localref_table));
1158 #if defined(ENABLE_JNI)
1159 /* add current JNI local references table to this thread */
1161 localref_table_add(lrt);
1164 #if !defined(NDEBUG)
1165 # if defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__)
1166 /* print the call-trace if necesarry */
1167 /* BEFORE: filling the local reference table */
1169 if (opt_TraceJavaCalls)
1170 trace_java_call_enter(m, arg_regs, arg_stack);
1174 #if defined(ENABLE_HANDLES)
1175 /* place all references into the local reference table */
1176 /* BEFORE: creating stackframeinfo */
1178 localref_native_enter(m, arg_regs, arg_stack);
1181 /* Add a stackframeinfo for this native method. We don't have RA
1182 and XPC here. These are determined in
1183 stacktrace_stackframeinfo_add. */
1185 stacktrace_stackframeinfo_add(sfi, pv, sp, NULL, NULL);
1187 /* Return a wrapped classinfo for static methods. */
1189 if (m->flags & ACC_STATIC)
1190 return (java_handle_t *) LLNI_classinfo_wrap(m->clazz);
1196 /* codegen_finish_native_call **************************************************
1198 Removes the stuff required for a native (JNI) function call.
1199 Additionally it checks for an exceptions and in case, get the
1200 exception object and clear the pointer.
1202 *******************************************************************************/
1204 java_object_t *codegen_finish_native_call(u1 *sp, u1 *pv)
1206 stackframeinfo_t *sfi;
1216 /* get information from method header */
1218 code = code_get_codeinfo_for_pv(pv);
1220 framesize = *((int32_t *) (pv + FrameSize));
1224 /* get the methodinfo */
1229 /* calculate needed values */
1231 #if defined(__ALPHA__) || defined(__ARM__)
1232 datasp = sp + framesize - SIZEOF_VOID_P;
1233 ret_regs = (uint64_t *) sp;
1234 #elif defined(__MIPS__)
1235 /* MIPS always uses 8 bytes to store the RA */
1236 datasp = sp + framesize - 8;
1237 #elif defined(__S390__)
1238 datasp = sp + framesize - 8;
1239 ret_regs = (uint64_t *) (sp + 96);
1240 #elif defined(__I386__)
1241 datasp = sp + framesize;
1242 ret_regs = (uint64_t *) (sp + 2 * SIZEOF_VOID_P);
1243 #elif defined(__M68K__)
1244 datasp = sp + framesize;
1245 ret_regs = (uint64_t *) (sp + 2 * 8);
1246 #elif defined(__X86_64__)
1247 datasp = sp + framesize;
1248 ret_regs = (uint64_t *) sp;
1249 #elif defined(__POWERPC__)
1250 datasp = sp + framesize;
1251 ret_regs = (uint64_t *) (sp + LA_SIZE + 2 * SIZEOF_VOID_P);
1252 #elif defined(__POWERPC64__)
1253 datasp = sp + framesize;
1254 ret_regs = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 2 * SIZEOF_VOID_P);
1256 vm_abort("codegen_finish_native_call: unsupported architecture");
1259 /* get data structures from stack */
1261 sfi = (stackframeinfo_t *) (datasp - sizeof(stackframeinfo_t));
1263 /* Remove current stackframeinfo from chain. */
1265 stacktrace_stackframeinfo_remove(sfi);
1267 #if defined(ENABLE_HANDLES)
1268 /* unwrap the return value from the local reference table */
1269 /* AFTER: removing the stackframeinfo */
1270 /* BEFORE: releasing the local reference table */
1272 localref_native_exit(m, ret_regs);
1275 /* get and unwrap the exception */
1276 /* AFTER: removing the stackframe info */
1277 /* BEFORE: releasing the local reference table */
1279 e = exceptions_get_and_clear_exception();
1282 #if defined(ENABLE_JNI)
1283 /* release JNI local references table for this thread */
1285 localref_frame_pop_all();
1286 localref_table_remove();
1289 #if !defined(NDEBUG)
1290 # if defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__)
1291 /* print the call-trace if necesarry */
1292 /* AFTER: unwrapping the return value */
1294 if (opt_TraceJavaCalls)
1295 trace_java_call_exit(m, ret_regs);
1303 /* removecompilerstub **********************************************************
1305 Deletes a compilerstub from memory (simply by freeing it).
1307 *******************************************************************************/
1309 void removecompilerstub(u1 *stub)
1311 /* pass size 1 to keep the intern function happy */
1313 CFREE((void *) stub, 1);
1317 /* removenativestub ************************************************************
1319 Removes a previously created native-stub from memory.
1321 *******************************************************************************/
1323 void removenativestub(u1 *stub)
1325 /* pass size 1 to keep the intern function happy */
1327 CFREE((void *) stub, 1);
1331 /* codegen_reg_of_var **********************************************************
1333 This function determines a register, to which the result of an
1334 operation should go, when it is ultimatively intended to store the
1335 result in pseudoregister v. If v is assigned to an actual
1336 register, this register will be returned. Otherwise (when v is
1337 spilled) this function returns tempregnum. If not already done,
1338 regoff and flags are set in the stack location.
1340 *******************************************************************************/
1342 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
1344 if (!(v->flags & INMEMORY))
1345 return v->vv.regoff;
1351 /* codegen_reg_of_dst **********************************************************
1353 This function determines a register, to which the result of an
1354 operation should go, when it is ultimatively intended to store the
1355 result in iptr->dst.var. If dst.var is assigned to an actual
1356 register, this register will be returned. Otherwise (when it is
1357 spilled) this function returns tempregnum. If not already done,
1358 regoff and flags are set in the stack location.
1360 *******************************************************************************/
1362 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
1364 return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
1368 /* codegen_emit_phi_moves ****************************************************
1370 Emits phi moves at the end of the basicblock.
1372 *******************************************************************************/
1374 #if defined(ENABLE_SSA)
1375 void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
1388 /* Moves from phi functions with highest indices have to be */
1389 /* inserted first, since this is the order as is used for */
1390 /* conflict resolution */
1392 for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
1393 lt_d = ls->phi_moves[bptr->nr][i][0];
1394 lt_s = ls->phi_moves[bptr->nr][i][1];
1395 #if defined(SSA_DEBUG_VERBOSE)
1397 printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
1399 if (lt_s == UNUSED) {
1400 #if defined(SSA_DEBUG_VERBOSE)
1402 printf(" ... not processed \n");
1407 d = VAR(ls->lifetime[lt_d].v_index);
1408 s = VAR(ls->lifetime[lt_s].v_index);
1411 if (d->type == -1) {
1412 #if defined(SSA_DEBUG_VERBOSE)
1414 printf("...returning - phi lifetimes where joined\n");
1419 if (s->type == -1) {
1420 #if defined(SSA_DEBUG_VERBOSE)
1422 printf("...returning - phi lifetimes where joined\n");
1428 tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
1429 tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
1430 emit_copy(jd, &tmp_i);
1432 #if defined(SSA_DEBUG_VERBOSE)
1433 if (compileverbose) {
1434 if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
1436 printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1438 else if (IS_INMEMORY(s->flags)) {
1440 printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1442 else if (IS_INMEMORY(d->flags)) {
1444 printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1448 printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1452 #endif /* defined(SSA_DEBUG_VERBOSE) */
1455 #endif /* defined(ENABLE_SSA) */
1458 /* REMOVEME When we have exception handling in C. */
1460 void *md_asm_codegen_get_pv_from_pc(void *ra)
1462 return md_codegen_get_pv_from_pc(ra);
1467 * These are local overrides for various environment variables in Emacs.
1468 * Please do not remove this and leave it at the end of the file, where
1469 * Emacs will automagically detect them.
1470 * ---------------------------------------------------------------------
1473 * indent-tabs-mode: t
1477 * vim:noexpandtab:sw=4:ts=4: