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
106 *rpa.............points to the next free rplalloc
108 *******************************************************************************/
110 static void replace_create_replacement_point(jitdata *jd,
111 insinfo_inline *iinfo,
124 static s4 fake_id = 0;
128 /* there will be a replacement point at the start of this block */
130 rp->method = (iinfo) ? iinfo->method : jd->m;
131 rp->pc = NULL; /* set by codegen */
132 rp->outcode = NULL; /* set by codegen */
133 rp->callsize = 0; /* set by codegen */
138 rp->id = ++fake_id; /* XXX need a real invariant id */
140 /* XXX unify these two fields */
142 rp->parent = (iinfo) ? iinfo->rp : NULL;
144 /* store local allocation info of javalocals */
147 for (i = 0; i < rp->method->maxlocals; ++i) {
148 index = javalocals[i];
153 ra->flags = v->flags & (INMEMORY);
155 ra->regoff = v->vv.regoff;
161 /* store allocation info of java stack vars */
163 for (i = 0; i < stackdepth; ++i) {
164 v = VAR(stackvars[i]);
165 ra->flags = v->flags & (INMEMORY);
167 ra->regoff = v->vv.regoff;
172 /* total number of allocations */
174 rp->regalloccount = ra - rp->regalloc;
180 /* replace_create_replacement_points *******************************************
182 Create the replacement points for the given code.
185 jd...............current jitdata, must not have any replacement points
188 code->rplpoints.......set to the list of replacement points
189 code->rplpointcount...number of replacement points
190 code->regalloc........list of allocation info
191 code->regalloccount...total length of allocation info list
192 code->globalcount.....number of global allocations at the
193 start of code->regalloc
196 true.............everything ok
197 false............an exception has been thrown
199 *******************************************************************************/
201 bool replace_create_replacement_points(jitdata *jd)
219 insinfo_inline *iinfo;
220 insinfo_inline *calleeinfo;
222 /* get required compiler data */
227 /* assert that we wont overwrite already allocated data */
231 assert(code->rplpoints == NULL);
232 assert(code->rplpointcount == 0);
233 assert(code->regalloc == NULL);
234 assert(code->regalloccount == 0);
235 assert(code->globalcount == 0);
237 /* iterate over the basic block list to find replacement points */
244 javalocals = DMNEW(s4, jd->maxlocals);
246 for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
250 if (bptr->flags < BBFINISHED)
253 /* get info about this block */
256 iinfo = bptr->inlineinfo;
258 /* initialize javalocals at the start of this block */
260 if (bptr->javalocals)
261 MCOPY(javalocals, bptr->javalocals, s4, m->maxlocals);
263 for (i=0; i<m->maxlocals; ++i)
264 javalocals[i] = UNUSED;
266 /* create replacement points at targets of backward branches */
268 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
270 alloccount += bptr->indepth;
272 for (i=0; i<m->maxlocals; ++i)
273 if (bptr->javalocals[i] != UNUSED)
277 /* iterate over the instructions */
280 iend = iptr + bptr->icount;
282 for (; iptr != iend; ++iptr) {
284 case ICMD_INVOKESTATIC:
285 case ICMD_INVOKESPECIAL:
286 case ICMD_INVOKEVIRTUAL:
287 case ICMD_INVOKEINTERFACE:
288 INSTRUCTION_GET_METHODDESC(iptr, md);
290 for (i=0; i<m->maxlocals; ++i)
291 if (javalocals[i] != UNUSED)
293 alloccount += iptr->s1.argcount - md->paramcount;
295 alloccount -= iinfo->throughcount;
303 /* XXX share code with stack.c */
304 j = iptr->dst.varindex;
305 i = iptr->sx.s23.s3.javaindex;
307 if (iptr->flags.bits & INS_FLAG_RETADDR)
308 javalocals[i] = UNUSED;
311 if (iptr->flags.bits & INS_FLAG_KILL_PREV)
312 javalocals[i-1] = UNUSED;
313 if (iptr->flags.bits & INS_FLAG_KILL_NEXT)
314 javalocals[i+1] = UNUSED;
329 case ICMD_INLINE_START:
330 iinfo = iptr->sx.s23.s3.inlineinfo;
333 for (i=0; i<m->maxlocals; ++i)
334 if (javalocals[i] != UNUSED)
336 alloccount += iinfo->stackvarscount;
339 if (iinfo->javalocals_start)
340 MCOPY(javalocals, iinfo->javalocals_start, s4, m->maxlocals);
343 case ICMD_INLINE_END:
344 iinfo = iptr->sx.s23.s3.inlineinfo;
346 if (iinfo->javalocals_end)
347 MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
348 iinfo = iinfo->parent;
354 /* if no points were found, there's nothing to do */
359 /* allocate replacement point array and allocation array */
361 rplpoints = MNEW(rplpoint, count);
362 regalloc = MNEW(rplalloc, alloccount);
365 /* initialize replacement point structs */
369 /* XXX try to share code with the counting loop! */
371 for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
374 if (bptr->flags < BBFINISHED)
377 /* get info about this block */
380 iinfo = bptr->inlineinfo;
382 /* initialize javalocals at the start of this block */
384 if (bptr->javalocals)
385 MCOPY(javalocals, bptr->javalocals, s4, m->maxlocals);
387 for (i=0; i<m->maxlocals; ++i)
388 javalocals[i] = UNUSED;
390 /* create replacement points at targets of backward branches */
392 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
394 replace_create_replacement_point(jd, iinfo, rp++,
396 bptr->javalocals, bptr->invars, bptr->indepth);
399 /* iterate over the instructions */
402 iend = iptr + bptr->icount;
404 for (; iptr != iend; ++iptr) {
406 case ICMD_INVOKESTATIC:
407 case ICMD_INVOKESPECIAL:
408 case ICMD_INVOKEVIRTUAL:
409 case ICMD_INVOKEINTERFACE:
410 INSTRUCTION_GET_METHODDESC(iptr, md);
412 i = (iinfo) ? iinfo->throughcount : 0;
413 replace_create_replacement_point(jd, iinfo, rp++,
414 RPLPOINT_TYPE_CALL, &ra,
415 javalocals, iptr->sx.s23.s2.args + md->paramcount,
416 iptr->s1.argcount - md->paramcount - i);
424 /* XXX share code with stack.c */
425 j = iptr->dst.varindex;
426 i = iptr->sx.s23.s3.javaindex;
428 if (iptr->flags.bits & INS_FLAG_RETADDR)
429 javalocals[i] = UNUSED;
432 if (iptr->flags.bits & INS_FLAG_KILL_PREV)
433 javalocals[i-1] = UNUSED;
434 if (iptr->flags.bits & INS_FLAG_KILL_NEXT)
435 javalocals[i+1] = UNUSED;
444 replace_create_replacement_point(jd, iinfo, rp++,
445 RPLPOINT_TYPE_RETURN, &ra,
446 NULL, &(iptr->s1.varindex), 1);
450 replace_create_replacement_point(jd, iinfo, rp++,
451 RPLPOINT_TYPE_RETURN, &ra,
455 case ICMD_INLINE_START:
456 calleeinfo = iptr->sx.s23.s3.inlineinfo;
459 replace_create_replacement_point(jd, iinfo, rp++,
460 RPLPOINT_TYPE_INLINE, &ra,
462 calleeinfo->stackvars, calleeinfo->stackvarscount);
466 if (iinfo->javalocals_start)
467 MCOPY(javalocals, iinfo->javalocals_start, s4, m->maxlocals);
470 case ICMD_INLINE_END:
471 iinfo = iptr->sx.s23.s3.inlineinfo;
473 if (iinfo->javalocals_end)
474 MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
475 iinfo = iinfo->parent;
481 /* store the data in the codeinfo */
483 code->rplpoints = rplpoints;
484 code->rplpointcount = count;
485 code->regalloc = regalloc;
486 code->regalloccount = alloccount;
487 code->globalcount = 0;
488 code->savedintcount = INT_SAV_CNT - rd->savintreguse;
489 code->savedfltcount = FLT_SAV_CNT - rd->savfltreguse;
490 code->memuse = rd->memuse;
491 code->stackframesize = jd->cd->stackframesize;
493 /* everything alright */
499 /* replace_free_replacement_points *********************************************
501 Free memory used by replacement points.
504 code.............codeinfo whose replacement points should be freed.
506 *******************************************************************************/
508 void replace_free_replacement_points(codeinfo *code)
513 MFREE(code->rplpoints,rplpoint,code->rplpointcount);
516 MFREE(code->regalloc,rplalloc,code->regalloccount);
518 code->rplpoints = NULL;
519 code->rplpointcount = 0;
520 code->regalloc = NULL;
521 code->regalloccount = 0;
522 code->globalcount = 0;
526 /* replace_activate_replacement_point ******************************************
528 Activate a replacement point. When this function returns, the
529 replacement point is "armed", that is each thread reaching this point
530 will be replace to `target`.
533 rp...............replacement point to activate
534 target...........target of replacement
536 *******************************************************************************/
538 void replace_activate_replacement_point(rplpoint *rp,rplpoint *target)
540 assert(rp->target == NULL);
542 DOLOG( printf("activate replacement point:\n");
543 replace_replacement_point_println(rp, 1); fflush(stdout); );
547 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
548 md_patch_replacement_point(rp);
553 /* replace_deactivate_replacement_point ****************************************
555 Deactivate a replacement point. When this function returns, the
556 replacement point is "un-armed", that is a each thread reaching this point
557 will just continue normally.
560 rp...............replacement point to deactivate
562 *******************************************************************************/
564 void replace_deactivate_replacement_point(rplpoint *rp)
568 DOLOG( printf("deactivate replacement point:\n");
569 replace_replacement_point_println(rp, 1); fflush(stdout); );
573 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
574 md_patch_replacement_point(rp);
579 /* replace_read_value **********************************************************
581 Read a value with the given allocation from the execution state.
584 es...............execution state
585 sp...............stack pointer of the execution state (XXX eliminate?)
586 ra...............allocation
587 javaval..........where to put the value
590 *javaval.........the value
592 *******************************************************************************/
594 static void replace_read_value(executionstate_t *es,
599 if (ra->flags & INMEMORY) {
600 /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
601 #ifdef HAS_4BYTE_STACKSLOT
602 if (IS_2_WORD_TYPE(ra->type)) {
603 *javaval = *(u8*)(sp + ra->regoff);
607 *javaval = sp[ra->regoff];
608 #ifdef HAS_4BYTE_STACKSLOT
613 /* allocated register */
614 if (IS_FLT_DBL_TYPE(ra->type)) {
615 *javaval = es->fltregs[ra->regoff];
618 *javaval = es->intregs[ra->regoff];
624 /* replace_write_value *********************************************************
626 Write a value to the given allocation in the execution state.
629 es...............execution state
630 sp...............stack pointer of the execution state (XXX eliminate?)
631 ra...............allocation
632 *javaval.........the value
634 *******************************************************************************/
636 static void replace_write_value(executionstate_t *es,
641 if (ra->flags & INMEMORY) {
642 /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
643 #ifdef HAS_4BYTE_STACKSLOT
644 if (IS_2_WORD_TYPE(ra->type)) {
645 *(u8*)(sp + ra->regoff) = *javaval;
649 sp[ra->regoff] = *javaval;
650 #ifdef HAS_4BYTE_STACKSLOT
655 /* allocated register */
656 if (IS_FLT_DBL_TYPE(ra->type)) {
657 es->fltregs[ra->regoff] = *javaval;
660 es->intregs[ra->regoff] = *javaval;
666 /* replace_read_executionstate *************************************************
668 Read the given executions state and translate it to a source state.
671 rp...............replacement point at which `es` was taken
672 es...............execution state
673 ss...............where to put the source state
676 *ss..............the source state derived from the execution state
678 *******************************************************************************/
680 static void replace_read_executionstate(rplpoint *rp,executionstate_t *es,
688 sourceframe_t *frame;
695 topslot = TOP_IS_NORMAL;
699 sp = (stackslot_t *) es->sp;
701 /* on some architectures the returnAddress is passed on the stack by JSR */
703 #if defined(__I386__) || defined(__X86_64__)
704 if (rp->type == BBTYPE_SBR) {
706 topslot = TOP_IS_ON_STACK; /* XXX */
710 /* in some cases the top stack slot is passed in REG_ITMP1 */
712 if ( (rp->type == BBTYPE_EXH)
713 #if defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)
714 || (rp->type == BBTYPE_SBR) /* XXX */
718 topslot = TOP_IS_IN_ITMP1;
721 /* calculate base stack pointer */
723 basesp = sp + code_get_stack_frame_size(code);
725 /* create the source frame */
727 frame = DNEW(sourceframe_t);
728 frame->up = ss->frames;
729 frame->method = rp->method;
734 /* read local variables */
736 count = m->maxlocals;
737 frame->javalocalcount = count;
738 frame->javalocals = DMNEW(u8, count);
739 frame->javalocaltype = DMNEW(u1, count);
742 /* mark values as undefined */
743 for (i=0; i<count; ++i) {
744 frame->javalocals[i] = (u8) 0x00dead0000dead00ULL;
745 frame->javalocaltype[i] = TYPE_VOID;
748 /* some entries in the intregs array are not meaningful */
749 /*es->intregs[REG_ITMP3] = (u8) 0x11dead1111dead11ULL;*/
750 es->intregs[REG_SP ] = (u8) 0x11dead1111dead11ULL;
752 es->intregs[REG_PV ] = (u8) 0x11dead1111dead11ULL;
754 #endif /* !defined(NDEBUG) */
756 /* read javalocals */
758 count = rp->regalloccount;
761 while (count && (i = ra->index) >= 0) {
762 assert(i < m->maxlocals);
763 frame->javalocaltype[i] = ra->type;
764 replace_read_value(es, sp, ra, frame->javalocals + i);
769 /* read stack slots */
771 frame->javastackdepth = count;
772 frame->javastack = DMNEW(u8, count);
773 frame->javastacktype = DMNEW(u1, count);
776 /* mark values as undefined */
777 for (i=0; i<count; ++i) {
778 frame->javastack[i] = (u8) 0x00dead0000dead00ULL;
779 frame->javastacktype[i] = TYPE_VOID;
781 #endif /* !defined(NDEBUG) */
785 /* the first stack slot is special in SBR and EXH blocks */
787 if (topslot == TOP_IS_ON_STACK) {
790 frame->javastack[i] = sp[-1];
791 frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
796 else if (topslot == TOP_IS_IN_ITMP1) {
799 frame->javastack[i] = es->intregs[REG_ITMP1];
800 frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
806 /* read remaining stack slots */
808 for (; count--; ra++, i++) {
809 assert(ra->index == -1);
811 replace_read_value(es,sp,ra,frame->javastack + i);
812 frame->javastacktype[i] = ra->type;
815 /* read slots used for synchronization */
817 count = code_get_sync_slot_count(code);
818 frame->syncslotcount = count;
819 frame->syncslots = DMNEW(u8,count);
820 for (i=0; i<count; ++i) {
821 frame->syncslots[i] = sp[code->memuse + i];
826 /* replace_write_executionstate ************************************************
828 Translate the given source state into an execution state.
831 rp...............replacement point for which execution state should be
833 es...............where to put the execution state
834 ss...............the given source state
837 *es..............the execution state derived from the source state
839 *******************************************************************************/
841 static void replace_write_executionstate(rplpoint *rp,
842 executionstate_t *es,
850 sourceframe_t *frame;
857 topslot = TOP_IS_NORMAL;
859 /* pop a source frame */
863 ss->frames = frame->up;
865 /* calculate stack pointer */
867 sp = (stackslot_t *) es->sp;
869 basesp = sp + code_get_stack_frame_size(code);
871 /* on some architectures the returnAddress is passed on the stack by JSR */
873 #if defined(__I386__) || defined(__X86_64__)
874 if (rp->type == BBTYPE_SBR) {
875 topslot = TOP_IS_ON_STACK; /* XXX */
879 /* in some cases the top stack slot is passed in REG_ITMP1 */
881 if ( (rp->type == BBTYPE_EXH)
882 #if defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)
883 || (rp->type == BBTYPE_SBR) /* XXX */
887 topslot = TOP_IS_IN_ITMP1;
890 /* write javalocals */
893 count = rp->regalloccount;
895 while (count && (i = ra->index) >= 0) {
896 assert(i < m->maxlocals);
897 assert(i < frame->javalocalcount);
898 assert(ra->type == frame->javalocaltype[i]);
899 replace_write_value(es, sp, ra, frame->javalocals + i);
904 /* write stack slots */
908 /* the first stack slot is special in SBR and EXH blocks */
910 if (topslot == TOP_IS_ON_STACK) {
913 assert(i < frame->javastackdepth);
914 assert(frame->javastacktype[i] == TYPE_ADR);
915 sp[-1] = frame->javastack[i];
920 else if (topslot == TOP_IS_IN_ITMP1) {
923 assert(i < frame->javastackdepth);
924 assert(frame->javastacktype[i] == TYPE_ADR);
925 es->intregs[REG_ITMP1] = frame->javastack[i];
931 /* write remaining stack slots */
933 for (; count--; ra++, i++) {
934 assert(ra->index == -1);
935 assert(i < frame->javastackdepth);
936 assert(ra->type == frame->javastacktype[i]);
937 replace_write_value(es,sp,ra,frame->javastack + i);
940 /* write slots used for synchronization */
942 count = code_get_sync_slot_count(code);
943 assert(count == frame->syncslotcount);
944 for (i=0; i<count; ++i) {
945 sp[code->memuse + i] = frame->syncslots[i];
954 /* replace_pop_activation_record ***********************************************
956 Peel a stack frame from the execution state.
958 *** This function imitates the effects of the method epilog ***
959 *** and returning from the method call. ***
962 es...............execution state
965 *es..............the execution state after popping the stack frame
967 *******************************************************************************/
969 bool replace_pop_activation_record(executionstate_t *es)
980 /* read the return address */
982 ra = md_stacktrace_get_returnaddress(es->sp,
983 SIZE_OF_STACKSLOT * es->code->stackframesize);
985 DOLOG( printf("return address: %p\n", (void*)ra); );
987 /* find the new codeinfo */
989 pv = md_codegen_get_pv_from_pc(ra);
991 DOLOG( printf("PV = %p\n", (void*) pv); );
996 code = *(codeinfo **)(pv + CodeinfoPointer);
998 DOLOG( printf("CODE = %p\n", (void*) code); );
1003 /* calculate the base of the stack frame */
1005 basesp = (stackslot_t *)es->sp + es->code->stackframesize;
1007 /* restore saved int registers */
1010 for (i=0; i<es->code->savedintcount; ++i) {
1011 while (nregdescint[--reg] != REG_SAV)
1013 es->intregs[reg] = *--basesp;
1016 /* restore saved flt registers */
1020 for (i=0; i<es->code->savedfltcount; ++i) {
1021 while (nregdescfloat[--reg] != REG_SAV)
1023 basesp -= STACK_SLOTS_PER_FLOAT;
1024 es->fltregs[reg] = *(u8*)basesp;
1027 /* Set the new pc. Subtract one so we do not hit the replacement point */
1028 /* of the instruction following the call, if there is one. */
1032 /* adjust the stackpointer */
1034 es->sp += SIZE_OF_STACKSLOT * es->code->stackframesize;
1035 es->sp += SIZE_OF_STACKSLOT; /* skip return address */
1040 #if !defined(NDEBUG)
1042 for (i=0; i<INT_REG_CNT; ++i)
1043 if (nregdescint[i] != REG_SAV)
1044 es->intregs[i] = 0x33dead3333dead33ULL;
1045 for (i=0; i<FLT_REG_CNT; ++i)
1046 if (nregdescfloat[i] != REG_SAV)
1047 es->fltregs[i] = 0x33dead3333dead33ULL;
1048 #endif /* !defined(NDEBUG) */
1054 /* replace_push_activation_record **********************************************
1056 Push a stack frame onto the execution state.
1058 *** This function imitates the effects of a call and the ***
1059 *** method prolog of the callee. ***
1062 es...............execution state
1063 rpcall...........the replacement point at the call site
1064 calleecode.......the codeinfo of the callee
1067 *es..............the execution state after pushing the stack frame
1069 *******************************************************************************/
1071 void replace_push_activation_record(executionstate_t *es,
1073 codeinfo *calleecode)
1077 stackslot_t *basesp;
1079 /* write the return address */
1081 *((stackslot_t *)es->sp) = (stackslot_t) (rpcall->pc + rpcall->callsize);
1083 es->sp -= SIZE_OF_STACKSLOT;
1085 /* we move into a new code unit */
1087 es->code = calleecode;
1089 /* set the new pc XXX not needed */
1091 es->pc = es->code->entrypoint;
1093 /* build the stackframe */
1095 basesp = (stackslot_t *) es->sp;
1096 es->sp -= SIZE_OF_STACKSLOT * es->code->stackframesize;
1098 /* in debug mode, invalidate stack frame first */
1100 #if !defined(NDEBUG)
1102 stackslot_t *sp = (stackslot_t *) es->sp;
1103 for (i=0; i<(basesp - sp); ++i) {
1104 sp[i] = 0xdeaddeadU;
1109 /* save int registers */
1112 for (i=0; i<es->code->savedintcount; ++i) {
1113 while (nregdescint[--reg] != REG_SAV)
1115 *--basesp = es->intregs[reg];
1117 #if !defined(NDEBUG)
1118 es->intregs[reg] = 0x44dead4444dead44ULL;
1122 /* save flt registers */
1126 for (i=0; i<es->code->savedfltcount; ++i) {
1127 while (nregdescfloat[--reg] != REG_SAV)
1129 basesp -= STACK_SLOTS_PER_FLOAT;
1130 *(u8*)basesp = es->fltregs[reg];
1132 #if !defined(NDEBUG)
1133 es->fltregs[reg] = 0x44dead4444dead44ULL;
1139 es->pv = es->code->entrypoint;
1143 /* replace_find_replacement_point **********************************************
1145 Find the replacement point in the given code corresponding to the
1146 position given in the source frame.
1149 code.............the codeinfo in which to search the rplpoint
1150 ss...............the source state defining the position to look for
1153 the replacement point
1155 *******************************************************************************/
1157 rplpoint * replace_find_replacement_point(codeinfo *code, sourcestate_t *ss)
1159 sourceframe_t *frame;
1169 DOLOG( printf("searching replacement point for:\n");
1170 replace_source_frame_println(frame); );
1174 DOLOG( printf("code = %p\n", (void*)code); );
1176 rp = code->rplpoints;
1177 i = code->rplpointcount;
1179 if (rp->id == frame->id)
1185 return NULL; /* NOT REACHED */
1189 /* replace_me ******************************************************************
1191 This function is called by asm_replacement_out when a thread reaches
1192 a replacement point. `replace_me` must map the execution state to the
1193 target replacement point and let execution continue there.
1195 This function never returns!
1198 rp...............replacement point that has been reached
1199 es...............execution state read by asm_replacement_out
1201 *******************************************************************************/
1203 void replace_me(rplpoint *rp, executionstate_t *es)
1208 rplpoint *candidate;
1212 es->code = rp->code;
1214 /* mark start of dump memory area */
1216 dumpsize = dump_size();
1218 /* fetch the target of the replacement */
1220 target = rp->target;
1222 /* XXX DEBUG turn off self-replacement */
1224 replace_deactivate_replacement_point(rp);
1226 DOLOG( printf("replace_me(%p,%p)\n",(void*)rp,(void*)es); fflush(stdout);
1227 replace_replacement_point_println(rp, 1);
1228 replace_executionstate_println(es); );
1230 /* read execution state of old code */
1238 DOLOG( printf("recovering source state for:\n");
1239 replace_replacement_point_println(candidate, 1); );
1241 replace_read_executionstate(candidate,es,&ss);
1243 if (candidate->parent) {
1244 DOLOG( printf("INLINED!\n"); );
1245 candidate = candidate->parent;
1246 assert(candidate->type == RPLPOINT_TYPE_INLINE);
1249 DOLOG( printf("UNWIND\n"); );
1250 if (!replace_pop_activation_record(es)) {
1251 DOLOG( printf("BREAKING\n"); );
1254 DOLOG( replace_executionstate_println(es); );
1256 rp = es->code->rplpoints;
1257 for (i=0; i<es->code->rplpointcount; ++i, ++rp)
1258 if (rp->pc <= es->pc)
1261 DOLOG( printf("NO CANDIDATE!\n"); );
1263 DOLOG( printf("found replacement point.\n");
1264 replace_replacement_point_println(candidate, 1); );
1265 assert(candidate->type == RPLPOINT_TYPE_CALL);
1268 } while (candidate);
1270 DOLOG( replace_sourcestate_println(&ss); );
1272 /* write execution state of new code */
1274 DOLOG( replace_executionstate_println(es); );
1278 /* XXX get new code */
1282 candidate = replace_find_replacement_point(code, &ss);
1284 DOLOG( printf("creating execution state for:\n");
1285 replace_replacement_point_println(candidate, 1); );
1287 replace_write_executionstate(candidate, es, &ss);
1288 if (ss.frames == NULL)
1291 if (candidate->type == RPLPOINT_TYPE_CALL) {
1292 code = ss.frames->method->code;
1294 replace_push_activation_record(es, candidate, code);
1296 DOLOG( replace_executionstate_println(es); );
1299 DOLOG( replace_executionstate_println(es); );
1301 /* release dump area */
1303 dump_release(dumpsize);
1305 /* enter new code */
1307 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
1308 asm_replacement_in(es);
1310 abort(); /* NOT REACHED */
1314 /* replace_replacement_point_println *******************************************
1316 Print replacement point info.
1319 rp...............the replacement point to print
1321 *******************************************************************************/
1323 #if !defined(NDEBUG)
1324 static const char *type_char = "IJFDA";
1326 #define TYPECHAR(t) (((t) >= 0 && (t) <= 4) ? type_char[t] : '?')
1328 static char *replace_type_str[] = {
1337 void replace_replacement_point_println(rplpoint *rp, int depth)
1342 printf("(rplpoint *)NULL\n");
1346 for (j=0; j<depth; ++j)
1349 printf("rplpoint %p pc:%p+%d out:%p target:%p mcode:%016llx type:%s flags:%01x parent:%p\n",
1350 (void*)rp,rp->pc,rp->callsize,rp->outcode,(void*)rp->target,
1351 (unsigned long long)rp->mcode,replace_type_str[rp->type],rp->flags,
1353 for (j=0; j<depth; ++j)
1355 printf("ra:%d = [", rp->regalloccount);
1357 for (j=0; j<rp->regalloccount; ++j) {
1361 rp->regalloc[j].index,
1362 /* (rp->regalloc[j].next) ? '^' : ' ', */
1363 TYPECHAR(rp->regalloc[j].type));
1364 show_allocation(rp->regalloc[j].type, rp->regalloc[j].flags, rp->regalloc[j].regoff);
1368 for (j=0; j<depth; ++j)
1371 method_print(rp->method);
1378 /* replace_show_replacement_points *********************************************
1380 Print replacement point info.
1383 code.............codeinfo whose replacement points should be printed.
1385 *******************************************************************************/
1387 #if !defined(NDEBUG)
1388 void replace_show_replacement_points(codeinfo *code)
1396 printf("(codeinfo *)NULL\n");
1400 printf("\treplacement points: %d\n",code->rplpointcount);
1402 printf("\ttotal allocations : %d\n",code->regalloccount);
1403 printf("\tsaved int regs : %d\n",code->savedintcount);
1404 printf("\tsaved flt regs : %d\n",code->savedfltcount);
1405 printf("\tmemuse : %d\n",code->memuse);
1409 for (i=0; i<code->rplpointcount; ++i) {
1410 rp = code->rplpoints + i;
1412 assert(rp->code == code);
1415 parent = rp->parent;
1418 parent = parent->parent;
1420 replace_replacement_point_println(rp, depth);
1426 /* replace_executionstate_println **********************************************
1428 Print execution state
1431 es...............the execution state to print
1433 *******************************************************************************/
1435 #if !defined(NDEBUG)
1436 void replace_executionstate_println(executionstate_t *es)
1443 printf("(executionstate_t *)NULL\n");
1447 printf("executionstate_t:\n");
1448 printf("\tpc = %p",(void*)es->pc);
1449 printf(" sp = %p",(void*)es->sp);
1450 printf(" pv = %p\n",(void*)es->pv);
1451 #if defined(ENABLE_DISASSEMBLER)
1452 for (i=0; i<INT_REG_CNT; ++i) {
1457 printf("%-3s = %016llx",regs[i],(unsigned long long)es->intregs[i]);
1461 for (i=0; i<FLT_REG_CNT; ++i) {
1466 printf("F%02d = %016llx",i,(unsigned long long)es->fltregs[i]);
1472 sp = (stackslot_t *) es->sp;
1475 slots = code_get_stack_frame_size(es->code);
1480 printf("\tstack slots(+1) at sp:");
1481 for (i=0; i<slots+1; ++i) {
1488 #ifdef HAS_4BYTE_STACKSLOT
1489 printf("%08lx",(unsigned long)*sp++);
1491 printf("%016llx",(unsigned long long)*sp++);
1499 printf("\tcode: %p", (void*)es->code);
1500 if (es->code != NULL) {
1501 printf(" stackframesize=%d ", es->code->stackframesize);
1502 method_print(es->code->m);
1510 #if !defined(NDEBUG)
1511 void java_value_print(s4 type, u8 value)
1513 java_objectheader *obj;
1516 printf("%016llx",(unsigned long long) value);
1518 if (type < 0 || type > TYPE_RET)
1519 printf(" <INVALID TYPE:%d>", type);
1521 printf(" %s", show_jit_type_names[type]);
1523 if (type == TYPE_ADR && value != 0) {
1524 obj = (java_objectheader *) (ptrint) value;
1526 utf_display_printable_ascii_classname(obj->vftbl->class->name);
1528 if (obj->vftbl->class == class_java_lang_String) {
1530 u = javastring_toutf((java_lang_String *)obj, false);
1531 utf_display_printable_ascii(u);
1535 else if (type == TYPE_INT || type == TYPE_LNG) {
1536 printf(" %lld", (long long) value);
1539 #endif /* !defined(NDEBUG) */
1542 #if !defined(NDEBUG)
1543 void replace_source_frame_println(sourceframe_t *frame)
1549 method_println(frame->method);
1550 printf("\tid: %d\n", frame->id);
1553 if (frame->javalocalcount) {
1554 printf("\tlocals (%d):\n",frame->javalocalcount);
1555 for (i=0; i<frame->javalocalcount; ++i) {
1556 t = frame->javalocaltype[i];
1557 if (t == TYPE_VOID) {
1558 printf("\tlocal[ %2d] = void\n",i);
1561 printf("\tlocal[%c%2d] = ",TYPECHAR(t),i);
1562 java_value_print(t, frame->javalocals[i]);
1569 if (frame->javastackdepth) {
1570 printf("\tstack (depth %d):\n",frame->javastackdepth);
1571 for (i=0; i<frame->javastackdepth; ++i) {
1572 printf("\tstack[%2d] = ",i);
1573 java_value_print(frame->javastacktype[i], frame->javastack[i]);
1579 if (frame->syncslotcount) {
1580 printf("\tsynchronization slots (%d):\n",frame->syncslotcount);
1581 for (i=0; i<frame->syncslotcount; ++i) {
1582 printf("\tslot[%2d] = ",i);
1583 #ifdef HAS_4BYTE_STACKSLOT
1584 printf("%08lx\n",(unsigned long) frame->syncslots[i]);
1586 printf("%016llx\n",(unsigned long long) frame->syncslots[i]);
1592 #endif /* !defined(NDEBUG) */
1595 /* replace_sourcestate_println *************************************************
1600 ss...............the source state to print
1602 *******************************************************************************/
1604 #if !defined(NDEBUG)
1605 void replace_sourcestate_println(sourcestate_t *ss)
1608 sourceframe_t *frame;
1611 printf("(sourcestate_t *)NULL\n");
1615 printf("sourcestate_t:\n");
1617 for (i=0, frame = ss->frames; frame != NULL; frame = frame->up, ++i) {
1618 printf(" frame %d:\n", i);
1619 replace_source_frame_println(frame);
1625 * These are local overrides for various environment variables in Emacs.
1626 * Please do not remove this and leave it at the end of the file, where
1627 * Emacs will automagically detect them.
1628 * ---------------------------------------------------------------------
1631 * indent-tabs-mode: t
1635 * vim:noexpandtab:sw=4:ts=4: