1 /* vm/jit/replace.c - on-stack replacement of methods
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Edwin Steiner
43 #include "mm/memory.h"
44 #include "toolbox/logging.h"
45 #include "vm/options.h"
46 #include "vm/stringlocal.h"
47 #include "vm/jit/abi.h"
48 #include "vm/jit/jit.h"
49 #include "vm/jit/replace.h"
50 #include "vm/jit/asmpart.h"
51 #include "vm/jit/disass.h"
52 #include "vm/jit/show.h"
53 #include "vm/jit/methodheader.h"
55 #include "native/include/java_lang_String.h"
58 /*** configuration of native stack slot size **********************************/
60 /* XXX this should be in md-abi.h files, probably */
62 #if defined(HAS_4BYTE_STACKSLOT)
63 #define SIZE_OF_STACKSLOT 4
64 #define STACK_SLOTS_PER_FLOAT 2
65 typedef u4 stackslot_t;
67 #define SIZE_OF_STACKSLOT 8
68 #define STACK_SLOTS_PER_FLOAT 1
69 typedef u8 stackslot_t;
73 /*** debugging ****************************************************************/
75 /*#define REPLACE_VERBOSE*/
77 #if !defined(NDEBUG) && defined(REPLACE_VERBOSE)
78 #define DOLOG(code) do{ if (1) { code; } } while(0)
84 /*** constants used internally ************************************************/
86 #define TOP_IS_NORMAL 0
87 #define TOP_IS_ON_STACK 1
88 #define TOP_IS_IN_ITMP1 2
91 /* replace_create_replacement_point ********************************************
93 Create a replacement point.
96 jd...............current jitdata
97 iinfo............inlining info for the current position
98 rp...............pre-allocated (uninitialized) rplpoint
99 type.............RPLPOINT_TYPE constant
100 *pra.............current rplalloc pointer
101 javalocals.......the javalocals at the current point
102 stackvars........the stack variables at the current point
103 stackdepth.......the stack depth at the current point
104 paramcount.......number of parameters at the start of stackvars
107 *rpa.............points to the next free rplalloc
109 *******************************************************************************/
111 static void replace_create_replacement_point(jitdata *jd,
112 insinfo_inline *iinfo,
129 /* there will be a replacement point at the start of this block */
131 rp->method = (iinfo) ? iinfo->method : jd->m;
132 rp->pc = NULL; /* set by codegen */
133 rp->outcode = NULL; /* set by codegen */
134 rp->callsize = 0; /* set by codegen */
139 rp->id = iptr->flags.bits >> INS_FLAG_ID_SHIFT;
141 /* XXX unify these two fields */
143 rp->parent = (iinfo) ? iinfo->rp : NULL;
145 /* store local allocation info of javalocals */
148 for (i = 0; i < rp->method->maxlocals; ++i) {
149 index = javalocals[i];
154 ra->flags = v->flags & (INMEMORY);
156 ra->regoff = v->vv.regoff;
162 /* store allocation info of java stack vars */
164 for (i = 0; i < stackdepth; ++i) {
165 v = VAR(stackvars[i]);
166 ra->flags = v->flags & (INMEMORY);
167 ra->index = (i < paramcount) ? RPLALLOC_PARAM : RPLALLOC_STACK;
168 ra->regoff = v->vv.regoff;
173 /* total number of allocations */
175 rp->regalloccount = ra - rp->regalloc;
181 /* replace_create_replacement_points *******************************************
183 Create the replacement points for the given code.
186 jd...............current jitdata, must not have any replacement points
189 code->rplpoints.......set to the list of replacement points
190 code->rplpointcount...number of replacement points
191 code->regalloc........list of allocation info
192 code->regalloccount...total length of allocation info list
193 code->globalcount.....number of global allocations at the
194 start of code->regalloc
197 true.............everything ok
198 false............an exception has been thrown
200 *******************************************************************************/
202 bool replace_create_replacement_points(jitdata *jd)
220 insinfo_inline *iinfo;
221 insinfo_inline *calleeinfo;
223 /* get required compiler data */
228 /* assert that we wont overwrite already allocated data */
232 assert(code->rplpoints == NULL);
233 assert(code->rplpointcount == 0);
234 assert(code->regalloc == NULL);
235 assert(code->regalloccount == 0);
236 assert(code->globalcount == 0);
238 /* iterate over the basic block list to find replacement points */
245 javalocals = DMNEW(s4, jd->maxlocals);
247 for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
251 if (bptr->flags < BBFINISHED)
254 /* get info about this block */
257 iinfo = bptr->inlineinfo;
259 /* initialize javalocals at the start of this block */
261 if (bptr->javalocals)
262 MCOPY(javalocals, bptr->javalocals, s4, m->maxlocals);
264 for (i=0; i<m->maxlocals; ++i)
265 javalocals[i] = UNUSED;
267 /* create replacement points at targets of backward branches */
269 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
271 alloccount += bptr->indepth;
273 for (i=0; i<m->maxlocals; ++i)
274 if (bptr->javalocals[i] != UNUSED)
278 /* iterate over the instructions */
281 iend = iptr + bptr->icount;
283 for (; iptr != iend; ++iptr) {
285 case ICMD_INVOKESTATIC:
286 case ICMD_INVOKESPECIAL:
287 case ICMD_INVOKEVIRTUAL:
288 case ICMD_INVOKEINTERFACE:
289 INSTRUCTION_GET_METHODDESC(iptr, md);
291 for (i=0; i<m->maxlocals; ++i)
292 if (javalocals[i] != UNUSED)
294 alloccount += iptr->s1.argcount;
296 alloccount -= iinfo->throughcount;
304 /* XXX share code with stack.c */
305 j = iptr->dst.varindex;
306 i = iptr->sx.s23.s3.javaindex;
308 if (iptr->flags.bits & INS_FLAG_RETADDR)
309 javalocals[i] = UNUSED;
312 if (iptr->flags.bits & INS_FLAG_KILL_PREV)
313 javalocals[i-1] = UNUSED;
314 if (iptr->flags.bits & INS_FLAG_KILL_NEXT)
315 javalocals[i+1] = UNUSED;
330 case ICMD_INLINE_START:
331 iinfo = iptr->sx.s23.s3.inlineinfo;
334 for (i=0; i<m->maxlocals; ++i)
335 if (javalocals[i] != UNUSED)
337 alloccount += iinfo->stackvarscount;
340 if (iinfo->javalocals_start)
341 MCOPY(javalocals, iinfo->javalocals_start, s4, m->maxlocals);
344 case ICMD_INLINE_END:
345 iinfo = iptr->sx.s23.s3.inlineinfo;
347 if (iinfo->javalocals_end)
348 MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
349 iinfo = iinfo->parent;
355 /* if no points were found, there's nothing to do */
360 /* allocate replacement point array and allocation array */
362 rplpoints = MNEW(rplpoint, count);
363 regalloc = MNEW(rplalloc, alloccount);
366 /* initialize replacement point structs */
370 /* XXX try to share code with the counting loop! */
372 for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
375 if (bptr->flags < BBFINISHED)
378 /* get info about this block */
381 iinfo = bptr->inlineinfo;
383 /* initialize javalocals at the start of this block */
385 if (bptr->javalocals)
386 MCOPY(javalocals, bptr->javalocals, s4, m->maxlocals);
388 for (i=0; i<m->maxlocals; ++i)
389 javalocals[i] = UNUSED;
391 /* create replacement points at targets of backward branches */
393 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
395 replace_create_replacement_point(jd, iinfo, rp++,
396 bptr->type, bptr->iinstr, &ra,
397 bptr->javalocals, bptr->invars, bptr->indepth, 0);
400 /* iterate over the instructions */
403 iend = iptr + bptr->icount;
405 for (; iptr != iend; ++iptr) {
407 case ICMD_INVOKESTATIC:
408 case ICMD_INVOKESPECIAL:
409 case ICMD_INVOKEVIRTUAL:
410 case ICMD_INVOKEINTERFACE:
411 INSTRUCTION_GET_METHODDESC(iptr, md);
413 i = (iinfo) ? iinfo->throughcount : 0;
414 replace_create_replacement_point(jd, iinfo, rp++,
415 RPLPOINT_TYPE_CALL, iptr, &ra,
416 javalocals, iptr->sx.s23.s2.args,
417 iptr->s1.argcount - i,
426 /* XXX share code with stack.c */
427 j = iptr->dst.varindex;
428 i = iptr->sx.s23.s3.javaindex;
430 if (iptr->flags.bits & INS_FLAG_RETADDR)
431 javalocals[i] = UNUSED;
434 if (iptr->flags.bits & INS_FLAG_KILL_PREV)
435 javalocals[i-1] = UNUSED;
436 if (iptr->flags.bits & INS_FLAG_KILL_NEXT)
437 javalocals[i+1] = UNUSED;
446 replace_create_replacement_point(jd, iinfo, rp++,
447 RPLPOINT_TYPE_RETURN, iptr, &ra,
448 NULL, &(iptr->s1.varindex), 1, 0);
452 replace_create_replacement_point(jd, iinfo, rp++,
453 RPLPOINT_TYPE_RETURN, iptr, &ra,
457 case ICMD_INLINE_START:
458 calleeinfo = iptr->sx.s23.s3.inlineinfo;
461 replace_create_replacement_point(jd, iinfo, rp++,
462 RPLPOINT_TYPE_INLINE, iptr, &ra,
464 calleeinfo->stackvars, calleeinfo->stackvarscount,
465 calleeinfo->paramcount);
469 if (iinfo->javalocals_start)
470 MCOPY(javalocals, iinfo->javalocals_start, s4, m->maxlocals);
473 case ICMD_INLINE_END:
474 iinfo = iptr->sx.s23.s3.inlineinfo;
476 if (iinfo->javalocals_end)
477 MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
478 iinfo = iinfo->parent;
484 /* store the data in the codeinfo */
486 code->rplpoints = rplpoints;
487 code->rplpointcount = count;
488 code->regalloc = regalloc;
489 code->regalloccount = alloccount;
490 code->globalcount = 0;
491 code->savedintcount = INT_SAV_CNT - rd->savintreguse;
492 code->savedfltcount = FLT_SAV_CNT - rd->savfltreguse;
493 code->memuse = rd->memuse;
494 code->stackframesize = jd->cd->stackframesize;
496 /* everything alright */
502 /* replace_free_replacement_points *********************************************
504 Free memory used by replacement points.
507 code.............codeinfo whose replacement points should be freed.
509 *******************************************************************************/
511 void replace_free_replacement_points(codeinfo *code)
516 MFREE(code->rplpoints,rplpoint,code->rplpointcount);
519 MFREE(code->regalloc,rplalloc,code->regalloccount);
521 code->rplpoints = NULL;
522 code->rplpointcount = 0;
523 code->regalloc = NULL;
524 code->regalloccount = 0;
525 code->globalcount = 0;
529 /* replace_activate_replacement_point ******************************************
531 Activate a replacement point. When this function returns, the
532 replacement point is "armed", that is each thread reaching this point
533 will be replace to `target`.
536 rp...............replacement point to activate
537 target...........target of replacement
539 *******************************************************************************/
541 void replace_activate_replacement_point(rplpoint *rp,rplpoint *target)
543 assert(rp->target == NULL);
545 DOLOG( printf("activate replacement point:\n");
546 replace_replacement_point_println(rp, 1); fflush(stdout); );
550 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
551 md_patch_replacement_point(rp);
556 /* replace_deactivate_replacement_point ****************************************
558 Deactivate a replacement point. When this function returns, the
559 replacement point is "un-armed", that is a each thread reaching this point
560 will just continue normally.
563 rp...............replacement point to deactivate
565 *******************************************************************************/
567 void replace_deactivate_replacement_point(rplpoint *rp)
571 DOLOG( printf("deactivate replacement point:\n");
572 replace_replacement_point_println(rp, 1); fflush(stdout); );
576 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
577 md_patch_replacement_point(rp);
582 /* replace_read_value **********************************************************
584 Read a value with the given allocation from the execution state.
587 es...............execution state
588 sp...............stack pointer of the execution state (XXX eliminate?)
589 ra...............allocation
590 javaval..........where to put the value
593 *javaval.........the value
595 *******************************************************************************/
597 static void replace_read_value(executionstate_t *es,
602 if (ra->flags & INMEMORY) {
603 /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
604 #ifdef HAS_4BYTE_STACKSLOT
605 if (IS_2_WORD_TYPE(ra->type)) {
606 *javaval = *(u8*)(sp + ra->regoff);
610 *javaval = sp[ra->regoff];
611 #ifdef HAS_4BYTE_STACKSLOT
616 /* allocated register */
617 if (IS_FLT_DBL_TYPE(ra->type)) {
618 *javaval = es->fltregs[ra->regoff];
621 *javaval = es->intregs[ra->regoff];
627 /* replace_write_value *********************************************************
629 Write a value to the given allocation in the execution state.
632 es...............execution state
633 sp...............stack pointer of the execution state (XXX eliminate?)
634 ra...............allocation
635 *javaval.........the value
637 *******************************************************************************/
639 static void replace_write_value(executionstate_t *es,
644 if (ra->flags & INMEMORY) {
645 /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
646 #ifdef HAS_4BYTE_STACKSLOT
647 if (IS_2_WORD_TYPE(ra->type)) {
648 *(u8*)(sp + ra->regoff) = *javaval;
652 sp[ra->regoff] = *javaval;
653 #ifdef HAS_4BYTE_STACKSLOT
658 /* allocated register */
659 if (IS_FLT_DBL_TYPE(ra->type)) {
660 es->fltregs[ra->regoff] = *javaval;
663 es->intregs[ra->regoff] = *javaval;
669 /* replace_read_executionstate *************************************************
671 Read the given executions state and translate it to a source state.
674 rp...............replacement point at which `es` was taken
675 es...............execution state
676 ss...............where to put the source state
679 *ss..............the source state derived from the execution state
681 *******************************************************************************/
683 static void replace_read_executionstate(rplpoint *rp,executionstate_t *es,
692 sourceframe_t *frame;
699 topslot = TOP_IS_NORMAL;
703 sp = (stackslot_t *) es->sp;
705 /* on some architectures the returnAddress is passed on the stack by JSR */
707 #if defined(__I386__) || defined(__X86_64__)
708 if (rp->type == BBTYPE_SBR) {
710 topslot = TOP_IS_ON_STACK; /* XXX */
714 /* in some cases the top stack slot is passed in REG_ITMP1 */
716 if ( (rp->type == BBTYPE_EXH)
717 #if defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)
718 || (rp->type == BBTYPE_SBR) /* XXX */
722 topslot = TOP_IS_IN_ITMP1;
725 /* calculate base stack pointer */
727 basesp = sp + code_get_stack_frame_size(code);
729 /* create the source frame */
731 frame = DNEW(sourceframe_t);
732 frame->up = ss->frames;
733 frame->method = rp->method;
738 /* read local variables */
740 count = m->maxlocals;
741 frame->javalocalcount = count;
742 frame->javalocals = DMNEW(u8, count);
743 frame->javalocaltype = DMNEW(u1, count);
746 /* mark values as undefined */
747 for (i=0; i<count; ++i) {
748 frame->javalocals[i] = (u8) 0x00dead0000dead00ULL;
749 frame->javalocaltype[i] = TYPE_VOID;
752 /* some entries in the intregs array are not meaningful */
753 /*es->intregs[REG_ITMP3] = (u8) 0x11dead1111dead11ULL;*/
754 es->intregs[REG_SP ] = (u8) 0x11dead1111dead11ULL;
756 es->intregs[REG_PV ] = (u8) 0x11dead1111dead11ULL;
758 #endif /* !defined(NDEBUG) */
760 /* read javalocals */
762 count = rp->regalloccount;
765 while (count && (i = ra->index) >= 0) {
766 assert(i < m->maxlocals);
767 frame->javalocaltype[i] = ra->type;
768 replace_read_value(es, sp, ra, frame->javalocals + i);
773 /* read stack slots */
775 frame->javastackdepth = count;
776 frame->javastack = DMNEW(u8, count);
777 frame->javastacktype = DMNEW(u1, count);
780 /* mark values as undefined */
781 for (i=0; i<count; ++i) {
782 frame->javastack[i] = (u8) 0x00dead0000dead00ULL;
783 frame->javastacktype[i] = TYPE_VOID;
785 #endif /* !defined(NDEBUG) */
789 /* the first stack slot is special in SBR and EXH blocks */
791 if (topslot == TOP_IS_ON_STACK) {
794 assert(ra->index == RPLALLOC_STACK);
795 frame->javastack[i] = sp[-1];
796 frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
801 else if (topslot == TOP_IS_IN_ITMP1) {
804 assert(ra->index == RPLALLOC_STACK);
805 frame->javastack[i] = es->intregs[REG_ITMP1];
806 frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
812 /* read remaining stack slots */
814 for (; count--; ra++) {
815 assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
817 /* do not read parameters of calls down the call chain */
819 if (!topframe && ra->index == RPLALLOC_PARAM) {
820 frame->javastackdepth--;
823 replace_read_value(es,sp,ra,frame->javastack + i);
824 frame->javastacktype[i] = ra->type;
829 /* read slots used for synchronization */
831 count = code_get_sync_slot_count(code);
832 frame->syncslotcount = count;
833 frame->syncslots = DMNEW(u8,count);
834 for (i=0; i<count; ++i) {
835 frame->syncslots[i] = sp[code->memuse + i];
840 /* replace_write_executionstate ************************************************
842 Translate the given source state into an execution state.
845 rp...............replacement point for which execution state should be
847 es...............where to put the execution state
848 ss...............the given source state
851 *es..............the execution state derived from the source state
853 *******************************************************************************/
855 static void replace_write_executionstate(rplpoint *rp,
856 executionstate_t *es,
865 sourceframe_t *frame;
872 topslot = TOP_IS_NORMAL;
874 /* pop a source frame */
878 ss->frames = frame->up;
880 /* calculate stack pointer */
882 sp = (stackslot_t *) es->sp;
884 basesp = sp + code_get_stack_frame_size(code);
886 /* on some architectures the returnAddress is passed on the stack by JSR */
888 #if defined(__I386__) || defined(__X86_64__)
889 if (rp->type == BBTYPE_SBR) {
890 topslot = TOP_IS_ON_STACK; /* XXX */
894 /* in some cases the top stack slot is passed in REG_ITMP1 */
896 if ( (rp->type == BBTYPE_EXH)
897 #if defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)
898 || (rp->type == BBTYPE_SBR) /* XXX */
902 topslot = TOP_IS_IN_ITMP1;
905 /* write javalocals */
908 count = rp->regalloccount;
910 while (count && (i = ra->index) >= 0) {
911 assert(i < m->maxlocals);
912 assert(i < frame->javalocalcount);
913 assert(ra->type == frame->javalocaltype[i]);
914 replace_write_value(es, sp, ra, frame->javalocals + i);
919 /* write stack slots */
923 /* the first stack slot is special in SBR and EXH blocks */
925 if (topslot == TOP_IS_ON_STACK) {
928 assert(ra->index == RPLALLOC_STACK);
929 assert(i < frame->javastackdepth);
930 assert(frame->javastacktype[i] == TYPE_ADR);
931 sp[-1] = frame->javastack[i];
936 else if (topslot == TOP_IS_IN_ITMP1) {
939 assert(ra->index == RPLALLOC_STACK);
940 assert(i < frame->javastackdepth);
941 assert(frame->javastacktype[i] == TYPE_ADR);
942 es->intregs[REG_ITMP1] = frame->javastack[i];
948 /* write remaining stack slots */
950 for (; count--; ra++) {
951 assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
953 /* do not write parameters of calls down the call chain */
955 if (!topframe && ra->index == RPLALLOC_PARAM) {
959 assert(i < frame->javastackdepth);
960 assert(ra->type == frame->javastacktype[i]);
961 replace_write_value(es,sp,ra,frame->javastack + i);
966 /* write slots used for synchronization */
968 count = code_get_sync_slot_count(code);
969 assert(count == frame->syncslotcount);
970 for (i=0; i<count; ++i) {
971 sp[code->memuse + i] = frame->syncslots[i];
980 /* replace_pop_activation_record ***********************************************
982 Peel a stack frame from the execution state.
984 *** This function imitates the effects of the method epilog ***
985 *** and returning from the method call. ***
988 es...............execution state
991 *es..............the execution state after popping the stack frame
993 *******************************************************************************/
995 bool replace_pop_activation_record(executionstate_t *es)
1002 stackslot_t *basesp;
1006 /* read the return address */
1008 ra = md_stacktrace_get_returnaddress(es->sp,
1009 SIZE_OF_STACKSLOT * es->code->stackframesize);
1011 DOLOG( printf("return address: %p\n", (void*)ra); );
1013 /* find the new codeinfo */
1015 pv = md_codegen_get_pv_from_pc(ra);
1017 DOLOG( printf("PV = %p\n", (void*) pv); );
1022 code = *(codeinfo **)(pv + CodeinfoPointer);
1024 DOLOG( printf("CODE = %p\n", (void*) code); );
1029 /* calculate the base of the stack frame */
1031 basesp = (stackslot_t *)es->sp + es->code->stackframesize;
1033 /* restore saved int registers */
1036 for (i=0; i<es->code->savedintcount; ++i) {
1037 while (nregdescint[--reg] != REG_SAV)
1039 es->intregs[reg] = *--basesp;
1042 /* restore saved flt registers */
1046 for (i=0; i<es->code->savedfltcount; ++i) {
1047 while (nregdescfloat[--reg] != REG_SAV)
1049 basesp -= STACK_SLOTS_PER_FLOAT;
1050 es->fltregs[reg] = *(u8*)basesp;
1053 /* Set the new pc. Subtract one so we do not hit the replacement point */
1054 /* of the instruction following the call, if there is one. */
1058 /* adjust the stackpointer */
1060 es->sp += SIZE_OF_STACKSLOT * es->code->stackframesize;
1061 es->sp += SIZE_OF_STACKSLOT; /* skip return address */
1066 #if !defined(NDEBUG)
1068 for (i=0; i<INT_REG_CNT; ++i)
1069 if (nregdescint[i] != REG_SAV)
1070 es->intregs[i] = 0x33dead3333dead33ULL;
1071 for (i=0; i<FLT_REG_CNT; ++i)
1072 if (nregdescfloat[i] != REG_SAV)
1073 es->fltregs[i] = 0x33dead3333dead33ULL;
1074 #endif /* !defined(NDEBUG) */
1080 /* replace_push_activation_record **********************************************
1082 Push a stack frame onto the execution state.
1084 *** This function imitates the effects of a call and the ***
1085 *** method prolog of the callee. ***
1088 es...............execution state
1089 rpcall...........the replacement point at the call site
1090 calleecode.......the codeinfo of the callee
1093 *es..............the execution state after pushing the stack frame
1095 *******************************************************************************/
1097 void replace_push_activation_record(executionstate_t *es,
1099 codeinfo *calleecode)
1103 stackslot_t *basesp;
1105 /* write the return address */
1107 es->sp -= SIZE_OF_STACKSLOT;
1109 DOLOG( printf("writing return address %p to %p\n",
1110 (void*) (rpcall->pc + rpcall->callsize),
1113 *((stackslot_t *)es->sp) = (stackslot_t) (rpcall->pc + rpcall->callsize);
1115 /* we move into a new code unit */
1117 es->code = calleecode;
1119 /* set the new pc XXX not needed */
1121 es->pc = es->code->entrypoint;
1123 /* build the stackframe */
1125 DOLOG( printf("building stackframe of %d words at %p\n",
1126 es->code->stackframesize, (void*)es->sp); );
1128 basesp = (stackslot_t *) es->sp;
1129 es->sp -= SIZE_OF_STACKSLOT * es->code->stackframesize;
1131 /* in debug mode, invalidate stack frame first */
1133 #if !defined(NDEBUG)
1135 stackslot_t *sp = (stackslot_t *) es->sp;
1136 for (i=0; i<(basesp - sp); ++i) {
1137 sp[i] = 0xdeaddeadU;
1142 /* save int registers */
1145 for (i=0; i<es->code->savedintcount; ++i) {
1146 while (nregdescint[--reg] != REG_SAV)
1148 *--basesp = es->intregs[reg];
1150 #if !defined(NDEBUG)
1151 es->intregs[reg] = 0x44dead4444dead44ULL;
1155 /* save flt registers */
1159 for (i=0; i<es->code->savedfltcount; ++i) {
1160 while (nregdescfloat[--reg] != REG_SAV)
1162 basesp -= STACK_SLOTS_PER_FLOAT;
1163 *(u8*)basesp = es->fltregs[reg];
1165 #if !defined(NDEBUG)
1166 es->fltregs[reg] = 0x44dead4444dead44ULL;
1172 es->pv = es->code->entrypoint;
1176 /* replace_find_replacement_point **********************************************
1178 Find the replacement point in the given code corresponding to the
1179 position given in the source frame.
1182 code.............the codeinfo in which to search the rplpoint
1183 ss...............the source state defining the position to look for
1186 the replacement point
1188 *******************************************************************************/
1190 rplpoint * replace_find_replacement_point(codeinfo *code, sourcestate_t *ss)
1192 sourceframe_t *frame;
1202 DOLOG( printf("searching replacement point for:\n");
1203 replace_source_frame_println(frame); );
1207 DOLOG( printf("code = %p\n", (void*)code); );
1209 rp = code->rplpoints;
1210 i = code->rplpointcount;
1212 if (rp->id == frame->id)
1218 return NULL; /* NOT REACHED */
1222 /* replace_me ******************************************************************
1224 This function is called by asm_replacement_out when a thread reaches
1225 a replacement point. `replace_me` must map the execution state to the
1226 target replacement point and let execution continue there.
1228 This function never returns!
1231 rp...............replacement point that has been reached
1232 es...............execution state read by asm_replacement_out
1234 *******************************************************************************/
1236 void replace_me(rplpoint *rp, executionstate_t *es)
1241 rplpoint *candidate;
1245 es->code = rp->code;
1247 /* mark start of dump memory area */
1249 dumpsize = dump_size();
1251 /* fetch the target of the replacement */
1253 target = rp->target;
1255 /* XXX DEBUG turn off self-replacement */
1257 replace_deactivate_replacement_point(rp);
1259 DOLOG( printf("replace_me(%p,%p)\n",(void*)rp,(void*)es); fflush(stdout);
1260 replace_replacement_point_println(rp, 1);
1261 replace_executionstate_println(es); );
1263 /* read execution state of old code */
1271 DOLOG( printf("recovering source state for:\n");
1272 replace_replacement_point_println(candidate, 1); );
1274 replace_read_executionstate(candidate, es, &ss, ss.frames == NULL);
1276 if (candidate->parent) {
1277 DOLOG( printf("INLINED!\n"); );
1278 candidate = candidate->parent;
1279 assert(candidate->type == RPLPOINT_TYPE_INLINE);
1282 DOLOG( printf("UNWIND\n"); );
1283 if (!replace_pop_activation_record(es)) {
1284 DOLOG( printf("BREAKING\n"); );
1287 DOLOG( replace_executionstate_println(es); );
1289 rp = es->code->rplpoints;
1290 for (i=0; i<es->code->rplpointcount; ++i, ++rp)
1291 if (rp->pc <= es->pc)
1294 DOLOG( printf("NO CANDIDATE!\n"); );
1296 DOLOG( printf("found replacement point.\n");
1297 replace_replacement_point_println(candidate, 1); );
1298 assert(candidate->type == RPLPOINT_TYPE_CALL);
1301 } while (candidate);
1303 DOLOG( replace_sourcestate_println(&ss); );
1305 /* write execution state of new code */
1307 DOLOG( replace_executionstate_println(es); );
1311 /* XXX get new code */
1315 candidate = replace_find_replacement_point(code, &ss);
1317 DOLOG( printf("creating execution state for:\n");
1318 replace_replacement_point_println(candidate, 1); );
1320 replace_write_executionstate(candidate, es, &ss, ss.frames->up == NULL);
1321 if (ss.frames == NULL)
1323 DOLOG( replace_executionstate_println(es); );
1325 if (candidate->type == RPLPOINT_TYPE_CALL) {
1326 jit_recompile(ss.frames->method);
1327 code = ss.frames->method->code;
1329 DOLOG( printf("pushing activation record for:\n");
1330 replace_replacement_point_println(candidate, 1); );
1331 replace_push_activation_record(es, candidate, code);
1333 DOLOG( replace_executionstate_println(es); );
1336 DOLOG( replace_executionstate_println(es); );
1338 /* release dump area */
1340 dump_release(dumpsize);
1342 /* enter new code */
1344 DOLOG( printf("JUMPING IN!\n"); fflush(stdout); );
1346 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
1347 asm_replacement_in(es);
1349 abort(); /* NOT REACHED */
1353 /* replace_replacement_point_println *******************************************
1355 Print replacement point info.
1358 rp...............the replacement point to print
1360 *******************************************************************************/
1362 #if !defined(NDEBUG)
1363 static const char *type_char = "IJFDA";
1365 #define TYPECHAR(t) (((t) >= 0 && (t) <= 4) ? type_char[t] : '?')
1367 static char *replace_type_str[] = {
1376 void replace_replacement_point_println(rplpoint *rp, int depth)
1382 printf("(rplpoint *)NULL\n");
1386 for (j=0; j<depth; ++j)
1389 printf("rplpoint (id %d) %p pc:%p+%d out:%p target:%p mcode:%016llx type:%s flags:%01x parent:%p\n",
1390 rp->id, (void*)rp,rp->pc,rp->callsize,rp->outcode,(void*)rp->target,
1391 (unsigned long long)rp->mcode,replace_type_str[rp->type],rp->flags,
1393 for (j=0; j<depth; ++j)
1395 printf("ra:%d = [", rp->regalloccount);
1397 for (j=0; j<rp->regalloccount; ++j) {
1400 index = rp->regalloc[j].index;
1402 case RPLALLOC_STACK: printf("S"); break;
1403 case RPLALLOC_PARAM: printf("P"); break;
1404 case RPLALLOC_SYNC : printf("Y"); break;
1405 default: printf("%d", index);
1407 printf(":%1c:", TYPECHAR(rp->regalloc[j].type));
1408 show_allocation(rp->regalloc[j].type, rp->regalloc[j].flags, rp->regalloc[j].regoff);
1412 for (j=0; j<depth; ++j)
1415 method_print(rp->method);
1422 /* replace_show_replacement_points *********************************************
1424 Print replacement point info.
1427 code.............codeinfo whose replacement points should be printed.
1429 *******************************************************************************/
1431 #if !defined(NDEBUG)
1432 void replace_show_replacement_points(codeinfo *code)
1440 printf("(codeinfo *)NULL\n");
1444 printf("\treplacement points: %d\n",code->rplpointcount);
1446 printf("\ttotal allocations : %d\n",code->regalloccount);
1447 printf("\tsaved int regs : %d\n",code->savedintcount);
1448 printf("\tsaved flt regs : %d\n",code->savedfltcount);
1449 printf("\tmemuse : %d\n",code->memuse);
1453 for (i=0; i<code->rplpointcount; ++i) {
1454 rp = code->rplpoints + i;
1456 assert(rp->code == code);
1459 parent = rp->parent;
1462 parent = parent->parent;
1464 replace_replacement_point_println(rp, depth);
1470 /* replace_executionstate_println **********************************************
1472 Print execution state
1475 es...............the execution state to print
1477 *******************************************************************************/
1479 #if !defined(NDEBUG)
1480 void replace_executionstate_println(executionstate_t *es)
1488 printf("(executionstate_t *)NULL\n");
1492 printf("executionstate_t:\n");
1493 printf("\tpc = %p",(void*)es->pc);
1494 printf(" sp = %p",(void*)es->sp);
1495 printf(" pv = %p\n",(void*)es->pv);
1496 #if defined(ENABLE_DISASSEMBLER)
1497 for (i=0; i<INT_REG_CNT; ++i) {
1502 printf("%-3s = %016llx",regs[i],(unsigned long long)es->intregs[i]);
1506 for (i=0; i<FLT_REG_CNT; ++i) {
1511 printf("F%02d = %016llx",i,(unsigned long long)es->fltregs[i]);
1517 sp = (stackslot_t *) es->sp;
1522 methoddesc *md = es->code->m->parseddesc;
1523 slots = code_get_stack_frame_size(es->code);
1524 extraslots = 1 + md->memuse;
1531 printf("\tstack slots(+%d) at sp:", extraslots);
1532 for (i=0; i<slots+extraslots; ++i) {
1537 printf("M%02d ", i);
1540 #ifdef HAS_4BYTE_STACKSLOT
1541 printf("%08lx",(unsigned long)*sp++);
1543 printf("%016llx",(unsigned long long)*sp++);
1551 printf("\tcode: %p", (void*)es->code);
1552 if (es->code != NULL) {
1553 printf(" stackframesize=%d ", es->code->stackframesize);
1554 method_print(es->code->m);
1562 #if !defined(NDEBUG)
1563 void java_value_print(s4 type, u8 value)
1565 java_objectheader *obj;
1568 printf("%016llx",(unsigned long long) value);
1570 if (type < 0 || type > TYPE_RET)
1571 printf(" <INVALID TYPE:%d>", type);
1573 printf(" %s", show_jit_type_names[type]);
1575 if (type == TYPE_ADR && value != 0) {
1576 obj = (java_objectheader *) (ptrint) value;
1578 utf_display_printable_ascii_classname(obj->vftbl->class->name);
1580 if (obj->vftbl->class == class_java_lang_String) {
1582 u = javastring_toutf((java_lang_String *)obj, false);
1583 utf_display_printable_ascii(u);
1587 else if (type == TYPE_INT || type == TYPE_LNG) {
1588 printf(" %lld", (long long) value);
1591 #endif /* !defined(NDEBUG) */
1594 #if !defined(NDEBUG)
1595 void replace_source_frame_println(sourceframe_t *frame)
1601 method_println(frame->method);
1602 printf("\tid: %d\n", frame->id);
1605 if (frame->javalocalcount) {
1606 printf("\tlocals (%d):\n",frame->javalocalcount);
1607 for (i=0; i<frame->javalocalcount; ++i) {
1608 t = frame->javalocaltype[i];
1609 if (t == TYPE_VOID) {
1610 printf("\tlocal[ %2d] = void\n",i);
1613 printf("\tlocal[%c%2d] = ",TYPECHAR(t),i);
1614 java_value_print(t, frame->javalocals[i]);
1621 if (frame->javastackdepth) {
1622 printf("\tstack (depth %d):\n",frame->javastackdepth);
1623 for (i=0; i<frame->javastackdepth; ++i) {
1624 printf("\tstack[%2d] = ",i);
1625 java_value_print(frame->javastacktype[i], frame->javastack[i]);
1631 if (frame->syncslotcount) {
1632 printf("\tsynchronization slots (%d):\n",frame->syncslotcount);
1633 for (i=0; i<frame->syncslotcount; ++i) {
1634 printf("\tslot[%2d] = ",i);
1635 #ifdef HAS_4BYTE_STACKSLOT
1636 printf("%08lx\n",(unsigned long) frame->syncslots[i]);
1638 printf("%016llx\n",(unsigned long long) frame->syncslots[i]);
1644 #endif /* !defined(NDEBUG) */
1647 /* replace_sourcestate_println *************************************************
1652 ss...............the source state to print
1654 *******************************************************************************/
1656 #if !defined(NDEBUG)
1657 void replace_sourcestate_println(sourcestate_t *ss)
1660 sourceframe_t *frame;
1663 printf("(sourcestate_t *)NULL\n");
1667 printf("sourcestate_t:\n");
1669 for (i=0, frame = ss->frames; frame != NULL; frame = frame->up, ++i) {
1670 printf(" frame %d:\n", i);
1671 replace_source_frame_println(frame);
1677 * These are local overrides for various environment variables in Emacs.
1678 * Please do not remove this and leave it at the end of the file, where
1679 * Emacs will automagically detect them.
1680 * ---------------------------------------------------------------------
1683 * indent-tabs-mode: t
1687 * vim:noexpandtab:sw=4:ts=4: