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/stack.h"
51 #include "vm/jit/asmpart.h"
52 #include "vm/jit/disass.h"
53 #include "vm/jit/show.h"
54 #include "vm/jit/methodheader.h"
56 #include "native/include/java_lang_String.h"
58 #define REPLACE_PATCH_DYNAMIC_CALL
59 /*#define REPLACE_PATCH_ALL*/
62 /*** configuration of native stack slot size **********************************/
64 /* XXX this should be in md-abi.h files, probably */
66 #if defined(HAS_4BYTE_STACKSLOT)
67 #define SIZE_OF_STACKSLOT 4
68 #define STACK_SLOTS_PER_FLOAT 2
69 typedef u4 stackslot_t;
71 #define SIZE_OF_STACKSLOT 8
72 #define STACK_SLOTS_PER_FLOAT 1
73 typedef u8 stackslot_t;
77 /*** debugging ****************************************************************/
79 /*#define REPLACE_VERBOSE*/
82 void java_value_print(s4 type, u8 value);
84 static char *replace_type_str[] = {
93 #endif /* !defined(NDEBUG) */
95 #if !defined(NDEBUG) && defined(REPLACE_VERBOSE)
96 #define DOLOG(code) do{ if (1) { code; } } while(0)
97 #define DOLOG_SHORT(code) do{ if (1) { code; } } while(0)
100 #define DOLOG_SHORT(code)
104 /*** statistics ***************************************************************/
106 #define REPLACE_STATISTICS
108 #if defined(REPLACE_STATISTICS)
110 static int stat_replacements = 0;
111 static int stat_frames = 0;
112 static int stat_recompile = 0;
113 static int stat_staticpatch = 0;
114 static int stat_unroll_inline = 0;
115 static int stat_unroll_call = 0;
116 static int stat_dist_frames[20] = { 0 };
117 static int stat_dist_locals[20] = { 0 };
118 static int stat_dist_locals_adr[10] = { 0 };
119 static int stat_dist_locals_prim[10] = { 0 };
120 static int stat_dist_locals_ret[10] = { 0 };
121 static int stat_dist_locals_void[10] = { 0 };
122 static int stat_dist_stack[10] = { 0 };
123 static int stat_dist_stack_adr[10] = { 0 };
124 static int stat_dist_stack_prim[10] = { 0 };
125 static int stat_dist_stack_ret[10] = { 0 };
126 static int stat_methods = 0;
127 static int stat_rploints = 0;
128 static int stat_regallocs = 0;
129 static int stat_dist_method_rplpoints[20] = { 0 };
131 #define REPLACE_COUNT(cnt) (cnt)++
132 #define REPLACE_COUNT_IF(cnt, cond) do{ if(cond) (cnt)++; } while(0)
133 #define REPLACE_COUNT_INC(cnt, inc) ((cnt) += (inc))
135 #define REPLACE_COUNT_DIST(array, val) \
137 int limit = (sizeof(array) / sizeof(int)) - 1; \
138 if ((val) < (limit)) (array)[val]++; \
139 else (array)[limit]++; \
142 #define REPLACE_PRINT_DIST(name, array) \
143 printf(" " name " distribution:\n"); \
144 print_freq(stdout, (array), sizeof(array)/sizeof(int) - 1);
146 static void print_freq(FILE *file,int *array,int limit)
151 for (i=0; i<limit; ++i)
154 for (i=0; i<limit; ++i) {
156 fprintf(file," %3d: %8d (cum %3d%%)\n",
157 i, array[i], (sum) ? ((100*cum)/sum) : 0);
159 fprintf(file," >=%3d: %8d\n",limit,array[limit]);
162 void replace_print_statistics(void)
164 printf("replacement statistics:\n");
165 printf(" # of replacements: %d\n", stat_replacements);
166 printf(" # of frames: %d\n", stat_frames);
167 printf(" # of recompilations: %d\n", stat_recompile);
168 printf(" patched static calls:%d\n", stat_staticpatch);
169 printf(" unrolled inlines: %d\n", stat_unroll_inline);
170 printf(" unrolled calls: %d\n", stat_unroll_call);
171 REPLACE_PRINT_DIST("frame depth", stat_dist_frames);
172 REPLACE_PRINT_DIST("locals per frame", stat_dist_locals);
173 REPLACE_PRINT_DIST("ADR locals per frame", stat_dist_locals_adr);
174 REPLACE_PRINT_DIST("primitive locals per frame", stat_dist_locals_prim);
175 REPLACE_PRINT_DIST("RET locals per frame", stat_dist_locals_ret);
176 REPLACE_PRINT_DIST("void locals per frame", stat_dist_locals_void);
177 REPLACE_PRINT_DIST("stack slots per frame", stat_dist_stack);
178 REPLACE_PRINT_DIST("ADR stack slots per frame", stat_dist_stack_adr);
179 REPLACE_PRINT_DIST("primitive stack slots per frame", stat_dist_stack_prim);
180 REPLACE_PRINT_DIST("RET stack slots per frame", stat_dist_stack_ret);
182 printf(" # of methods: %d\n", stat_methods);
183 printf(" # of replacement points: %d\n", stat_rploints);
184 printf(" # of regallocs: %d\n", stat_regallocs);
185 printf(" per rplpoint: %f\n", (double)stat_regallocs / stat_rploints);
186 printf(" per method: %f\n", (double)stat_regallocs / stat_methods);
187 REPLACE_PRINT_DIST("replacement points per method", stat_dist_method_rplpoints);
194 #define REPLACE_COUNT(cnt)
195 #define REPLACE_COUNT_IF(cnt, cond)
196 #define REPLACE_COUNT_INC(cnt, inc)
197 #define REPLACE_COUNT_DIST(array, val)
199 #endif /* defined(REPLACE_STATISTICS) */
201 /*** constants used internally ************************************************/
203 #define TOP_IS_NORMAL 0
204 #define TOP_IS_ON_STACK 1
205 #define TOP_IS_IN_ITMP1 2
206 #define TOP_IS_VOID 3
209 /* replace_create_replacement_point ********************************************
211 Create a replacement point.
214 jd...............current jitdata
215 iinfo............inlining info for the current position
216 rp...............pre-allocated (uninitialized) rplpoint
217 type.............RPLPOINT_TYPE constant
218 iptr.............current instruction
219 *pra.............current rplalloc pointer
220 javalocals.......the javalocals at the current point
221 stackvars........the stack variables at the current point
222 stackdepth.......the stack depth at the current point
223 paramcount.......number of parameters at the start of stackvars
226 *rpa.............points to the next free rplalloc
228 *******************************************************************************/
230 static void replace_create_replacement_point(jitdata *jd,
231 insinfo_inline *iinfo,
248 REPLACE_COUNT(stat_rploints);
250 rp->method = (iinfo) ? iinfo->method : jd->m;
251 rp->pc = NULL; /* set by codegen */
252 rp->outcode = NULL; /* set by codegen */
253 rp->callsize = 0; /* set by codegen */
258 rp->id = iptr->flags.bits >> INS_FLAG_ID_SHIFT;
260 /* XXX unify these two fields */
262 rp->parent = (iinfo) ? iinfo->rp : NULL;
264 /* store local allocation info of javalocals */
267 for (i = 0; i < rp->method->maxlocals; ++i) {
268 index = javalocals[i];
273 if (index < UNUSED) {
274 ra->regoff = (UNUSED - index) - 1;
280 ra->flags = v->flags & (INMEMORY);
281 ra->regoff = v->vv.regoff;
288 /* store allocation info of java stack vars */
290 for (i = 0; i < stackdepth; ++i) {
291 v = VAR(stackvars[i]);
292 ra->flags = v->flags & (INMEMORY);
293 ra->index = (i < paramcount) ? RPLALLOC_PARAM : RPLALLOC_STACK;
295 /* XXX how to handle locals on the stack containing returnAddresses? */
296 if (v->type == TYPE_RET) {
297 assert(stackvars[i] >= jd->localcount);
298 ra->regoff = v->vv.retaddr->nr;
301 ra->regoff = v->vv.regoff;
305 /* total number of allocations */
307 rp->regalloccount = ra - rp->regalloc;
313 /* replace_create_inline_start_replacement_point *******************************
315 Create an INLINE_START replacement point.
318 jd...............current jitdata
319 rp...............pre-allocated (uninitialized) rplpoint
320 iptr.............current instruction
321 *pra.............current rplalloc pointer
322 javalocals.......the javalocals at the current point
325 *rpa.............points to the next free rplalloc
328 the insinfo_inline * for the following inlined body
330 *******************************************************************************/
332 static insinfo_inline * replace_create_inline_start_replacement_point(
339 insinfo_inline *calleeinfo;
342 calleeinfo = iptr->sx.s23.s3.inlineinfo;
346 replace_create_replacement_point(jd, calleeinfo->parent, rp,
347 RPLPOINT_TYPE_INLINE, iptr, pra,
349 calleeinfo->stackvars, calleeinfo->stackvarscount,
350 calleeinfo->paramcount);
352 if (calleeinfo->synclocal != UNUSED) {
354 ra->index = RPLALLOC_SYNC;
355 ra->regoff = jd->var[calleeinfo->synclocal].vv.regoff;
356 ra->flags = jd->var[calleeinfo->synclocal].flags & INMEMORY;
366 /* replace_create_replacement_points *******************************************
368 Create the replacement points for the given code.
371 jd...............current jitdata, must not have any replacement points
374 code->rplpoints.......set to the list of replacement points
375 code->rplpointcount...number of replacement points
376 code->regalloc........list of allocation info
377 code->regalloccount...total length of allocation info list
378 code->globalcount.....number of global allocations at the
379 start of code->regalloc
382 true.............everything ok
383 false............an exception has been thrown
385 *******************************************************************************/
387 #define CLEAR_javalocals(array, method) \
389 for (i=0; i<(method)->maxlocals; ++i) \
390 (array)[i] = UNUSED; \
393 #define COPY_OR_CLEAR_javalocals(dest, array, method) \
395 if ((array) != NULL) \
396 MCOPY((dest), (array), s4, (method)->maxlocals); \
398 CLEAR_javalocals((dest), (method)); \
401 #define COUNT_javalocals(array, method, counter) \
403 for (i=0; i<(method)->maxlocals; ++i) \
404 if ((array)[i] != UNUSED) \
408 bool replace_create_replacement_points(jitdata *jd)
426 insinfo_inline *iinfo;
429 #if defined(REPLACE_PATCH_DYNAMIC_CALL)
433 REPLACE_COUNT(stat_methods);
435 /* get required compiler data */
440 /* assert that we wont overwrite already allocated data */
444 assert(code->rplpoints == NULL);
445 assert(code->rplpointcount == 0);
446 assert(code->regalloc == NULL);
447 assert(code->regalloccount == 0);
448 assert(code->globalcount == 0);
452 /* in instance methods, we may need a rplpoint at the method entry */
454 #if defined(REPLACE_PATCH_DYNAMIC_CALL)
455 if (!(m->flags & ACC_STATIC)) {
456 jd->basicblocks[0].bitflags |= BBFLAG_REPLACEMENT;
462 #endif /* defined(REPLACE_PATCH_DYNAMIC_CALL) */
464 /* iterate over the basic block list to find replacement points */
469 javalocals = DMNEW(s4, jd->maxlocals);
471 for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
475 if (bptr->flags < BBFINISHED)
478 /* get info about this block */
481 iinfo = bptr->inlineinfo;
483 /* initialize javalocals at the start of this block */
485 COPY_OR_CLEAR_javalocals(javalocals, bptr->javalocals, m);
487 /* iterate over the instructions */
490 iend = iptr + bptr->icount;
494 for (; iptr != iend; ++iptr) {
496 case ICMD_INVOKESTATIC:
497 case ICMD_INVOKESPECIAL:
498 case ICMD_INVOKEVIRTUAL:
499 case ICMD_INVOKEINTERFACE:
500 INSTRUCTION_GET_METHODDESC(iptr, md);
502 COUNT_javalocals(javalocals, m, alloccount);
503 alloccount += iptr->s1.argcount;
505 alloccount -= iinfo->throughcount;
513 stack_javalocals_store(iptr, javalocals);
527 case ICMD_INLINE_START:
528 iinfo = iptr->sx.s23.s3.inlineinfo;
531 COUNT_javalocals(javalocals, m, alloccount);
532 alloccount += iinfo->stackvarscount;
533 if (iinfo->synclocal != UNUSED)
537 /* javalocals may be set at next block start, or now */
538 COPY_OR_CLEAR_javalocals(javalocals, iinfo->javalocals_start, m);
541 case ICMD_INLINE_BODY:
542 assert(iinfo == iptr->sx.s23.s3.inlineinfo);
544 jl = iinfo->javalocals_start;
546 /* get the javalocals from the following block start */
548 jl = bptr->next->javalocals;
551 COUNT_javalocals(jl, m, alloccount);
554 case ICMD_INLINE_END:
555 assert(iinfo == iptr->sx.s23.s3.inlineinfo ||
556 iinfo == iptr->sx.s23.s3.inlineinfo->parent);
557 iinfo = iptr->sx.s23.s3.inlineinfo;
559 if (iinfo->javalocals_end)
560 MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
561 iinfo = iinfo->parent;
565 if (iptr == bptr->iinstr)
567 } /* end instruction loop */
569 /* create replacement points at targets of backward branches */
570 /* We only need the replacement point there, if there is no */
571 /* replacement point inside the block. */
573 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
574 #if defined(REPLACE_PATCH_DYNAMIC_CALL)
575 int test = (needentry && bptr == jd->basicblocks) ? firstcount : count;
579 if (test > startcount) {
580 /* we don't need an extra rplpoint */
581 bptr->bitflags &= ~BBFLAG_REPLACEMENT;
585 alloccount += bptr->indepth;
586 if (bptr->inlineinfo)
587 alloccount -= bptr->inlineinfo->throughcount;
589 COUNT_javalocals(bptr->javalocals, bptr->method, alloccount);
593 } /* end basicblock loop */
595 /* if no points were found, there's nothing to do */
600 /* allocate replacement point array and allocation array */
602 rplpoints = MNEW(rplpoint, count);
603 regalloc = MNEW(rplalloc, alloccount);
606 /* initialize replacement point structs */
610 /* XXX try to share code with the counting loop! */
612 for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
615 if (bptr->flags < BBFINISHED)
618 /* get info about this block */
621 iinfo = bptr->inlineinfo;
623 /* initialize javalocals at the start of this block */
625 COPY_OR_CLEAR_javalocals(javalocals, bptr->javalocals, m);
627 /* create replacement points at targets of backward branches */
629 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
631 i = (iinfo) ? iinfo->throughcount : 0;
632 replace_create_replacement_point(jd, iinfo, rp++,
633 bptr->type, bptr->iinstr, &ra,
634 bptr->javalocals, bptr->invars + i, bptr->indepth - i, 0);
637 /* iterate over the instructions */
640 iend = iptr + bptr->icount;
642 for (; iptr != iend; ++iptr) {
644 case ICMD_INVOKESTATIC:
645 case ICMD_INVOKESPECIAL:
646 case ICMD_INVOKEVIRTUAL:
647 case ICMD_INVOKEINTERFACE:
648 INSTRUCTION_GET_METHODDESC(iptr, md);
650 i = (iinfo) ? iinfo->throughcount : 0;
651 replace_create_replacement_point(jd, iinfo, rp++,
652 RPLPOINT_TYPE_CALL, iptr, &ra,
653 javalocals, iptr->sx.s23.s2.args,
654 iptr->s1.argcount - i,
663 stack_javalocals_store(iptr, javalocals);
671 replace_create_replacement_point(jd, iinfo, rp++,
672 RPLPOINT_TYPE_RETURN, iptr, &ra,
673 NULL, &(iptr->s1.varindex), 1, 0);
677 replace_create_replacement_point(jd, iinfo, rp++,
678 RPLPOINT_TYPE_RETURN, iptr, &ra,
682 case ICMD_INLINE_START:
683 iinfo = replace_create_inline_start_replacement_point(
684 jd, rp++, iptr, &ra, javalocals);
686 /* javalocals may be set at next block start, or now */
687 COPY_OR_CLEAR_javalocals(javalocals, iinfo->javalocals_start, m);
690 case ICMD_INLINE_BODY:
691 assert(iinfo == iptr->sx.s23.s3.inlineinfo);
693 jl = iinfo->javalocals_start;
695 /* get the javalocals from the following block start */
697 jl = bptr->next->javalocals;
699 /* create a non-trappable rplpoint */
700 replace_create_replacement_point(jd, iinfo, rp++,
701 RPLPOINT_TYPE_BODY, iptr, &ra,
703 rp[-1].flags |= RPLPOINT_FLAG_NOTRAP;
706 case ICMD_INLINE_END:
707 assert(iinfo == iptr->sx.s23.s3.inlineinfo ||
708 iinfo == iptr->sx.s23.s3.inlineinfo->parent);
709 iinfo = iptr->sx.s23.s3.inlineinfo;
711 if (iinfo->javalocals_end)
712 MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
713 iinfo = iinfo->parent;
716 } /* end instruction loop */
717 } /* end basicblock loop */
719 assert((rp - rplpoints) == count);
720 assert((ra - regalloc) == alloccount);
722 /* store the data in the codeinfo */
724 code->rplpoints = rplpoints;
725 code->rplpointcount = count;
726 code->regalloc = regalloc;
727 code->regalloccount = alloccount;
728 code->globalcount = 0;
729 code->savedintcount = INT_SAV_CNT - rd->savintreguse;
730 code->savedfltcount = FLT_SAV_CNT - rd->savfltreguse;
731 code->memuse = rd->memuse;
732 code->stackframesize = jd->cd->stackframesize;
734 REPLACE_COUNT_DIST(stat_dist_method_rplpoints, count);
735 REPLACE_COUNT_INC(stat_regallocs, alloccount);
737 /* everything alright */
743 /* replace_free_replacement_points *********************************************
745 Free memory used by replacement points.
748 code.............codeinfo whose replacement points should be freed.
750 *******************************************************************************/
752 void replace_free_replacement_points(codeinfo *code)
757 MFREE(code->rplpoints,rplpoint,code->rplpointcount);
760 MFREE(code->regalloc,rplalloc,code->regalloccount);
762 code->rplpoints = NULL;
763 code->rplpointcount = 0;
764 code->regalloc = NULL;
765 code->regalloccount = 0;
766 code->globalcount = 0;
770 /* replace_activate_replacement_point ******************************************
772 Activate a replacement point. When this function returns, the
773 replacement point is "armed", that is each thread reaching this point
774 will be replace to `target`.
777 rp...............replacement point to activate
778 target...........target of replacement
780 *******************************************************************************/
782 void replace_activate_replacement_point(rplpoint *rp,rplpoint *target)
784 assert(rp->target == NULL);
786 DOLOG( printf("activate replacement point:\n");
787 replace_replacement_point_println(rp, 1); fflush(stdout); );
791 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
792 md_patch_replacement_point(rp);
797 /* replace_deactivate_replacement_point ****************************************
799 Deactivate a replacement point. When this function returns, the
800 replacement point is "un-armed", that is a each thread reaching this point
801 will just continue normally.
804 rp...............replacement point to deactivate
806 *******************************************************************************/
808 void replace_deactivate_replacement_point(rplpoint *rp)
812 DOLOG( printf("deactivate replacement point:\n");
813 replace_replacement_point_println(rp, 1); fflush(stdout); );
817 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
818 md_patch_replacement_point(rp);
823 /* replace_read_value **********************************************************
825 Read a value with the given allocation from the execution state.
828 es...............execution state
829 sp...............stack pointer of the execution state (XXX eliminate?)
830 ra...............allocation
831 javaval..........where to put the value
834 *javaval.........the value
836 *******************************************************************************/
838 static void replace_read_value(executionstate_t *es,
843 if (ra->flags & INMEMORY) {
844 /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
845 #ifdef HAS_4BYTE_STACKSLOT
846 if (IS_2_WORD_TYPE(ra->type)) {
847 *javaval = *(u8*)(sp + ra->regoff);
851 *javaval = sp[ra->regoff];
852 #ifdef HAS_4BYTE_STACKSLOT
857 /* allocated register */
858 if (IS_FLT_DBL_TYPE(ra->type)) {
859 *javaval = es->fltregs[ra->regoff];
862 *javaval = es->intregs[ra->regoff];
868 /* replace_write_value *********************************************************
870 Write a value to the given allocation in the execution state.
873 es...............execution state
874 sp...............stack pointer of the execution state (XXX eliminate?)
875 ra...............allocation
876 *javaval.........the value
878 *******************************************************************************/
880 static void replace_write_value(executionstate_t *es,
885 if (ra->flags & INMEMORY) {
886 /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
887 #ifdef HAS_4BYTE_STACKSLOT
888 if (IS_2_WORD_TYPE(ra->type)) {
889 *(u8*)(sp + ra->regoff) = *javaval;
893 sp[ra->regoff] = *javaval;
894 #ifdef HAS_4BYTE_STACKSLOT
899 /* allocated register */
900 if (IS_FLT_DBL_TYPE(ra->type)) {
901 es->fltregs[ra->regoff] = *javaval;
904 es->intregs[ra->regoff] = *javaval;
910 /* replace_read_executionstate *************************************************
912 Read the given executions state and translate it to a source frame.
915 rp...............replacement point at which `es` was taken
916 es...............execution state
917 ss...............where to put the source state
920 *ss..............the source state derived from the execution state
922 *******************************************************************************/
924 static s4 replace_normalize_type_map[] = {
925 /* RPLPOINT_TYPE_STD |--> */ RPLPOINT_TYPE_STD,
926 /* RPLPOINT_TYPE_EXH |--> */ RPLPOINT_TYPE_STD,
927 /* RPLPOINT_TYPE_SBR |--> */ RPLPOINT_TYPE_STD,
928 /* RPLPOINT_TYPE_CALL |--> */ RPLPOINT_TYPE_CALL,
929 /* RPLPOINT_TYPE_INLINE |--> */ RPLPOINT_TYPE_CALL,
930 /* RPLPOINT_TYPE_RETURN |--> */ RPLPOINT_TYPE_RETURN,
931 /* RPLPOINT_TYPE_BODY |--> */ RPLPOINT_TYPE_STD
934 static void replace_read_executionstate(rplpoint *rp,
935 executionstate_t *es,
944 sourceframe_t *frame;
951 topslot = TOP_IS_NORMAL;
955 sp = (stackslot_t *) es->sp;
957 /* in some cases the top stack slot is passed in REG_ITMP1 */
959 if (rp->type == BBTYPE_EXH) {
960 topslot = TOP_IS_IN_ITMP1;
963 /* calculate base stack pointer */
965 basesp = sp + code_get_stack_frame_size(code);
967 /* create the source frame */
969 frame = DNEW(sourceframe_t);
970 frame->down = ss->frames;
971 frame->method = rp->method;
973 assert(rp->type >= 0 && rp->type < sizeof(replace_normalize_type_map)/sizeof(s4));
974 frame->type = replace_normalize_type_map[rp->type];
976 frame->syncslotcount = 0;
977 frame->syncslots = NULL;
982 /* read local variables */
984 count = m->maxlocals;
985 frame->javalocalcount = count;
986 frame->javalocals = DMNEW(u8, count);
987 frame->javalocaltype = DMNEW(u1, count);
990 /* mark values as undefined */
991 for (i=0; i<count; ++i) {
992 frame->javalocals[i] = (u8) 0x00dead0000dead00ULL;
993 frame->javalocaltype[i] = TYPE_VOID;
996 /* some entries in the intregs array are not meaningful */
997 /*es->intregs[REG_ITMP3] = (u8) 0x11dead1111dead11ULL;*/
998 es->intregs[REG_SP ] = (u8) 0x11dead1111dead11ULL;
1000 es->intregs[REG_PV ] = (u8) 0x11dead1111dead11ULL;
1002 #endif /* !defined(NDEBUG) */
1004 /* read javalocals */
1006 count = rp->regalloccount;
1009 while (count && (i = ra->index) >= 0) {
1010 assert(i < m->maxlocals);
1011 frame->javalocaltype[i] = ra->type;
1012 if (ra->type == TYPE_RET)
1013 frame->javalocals[i] = ra->regoff;
1015 replace_read_value(es, sp, ra, frame->javalocals + i);
1020 /* read instance, if this is the first rplpoint */
1022 #if defined(REPLACE_PATCH_DYNAMIC_CALL)
1023 if (topframe && !(rp->method->flags & ACC_STATIC) && rp == code->rplpoints) {
1027 md = rp->method->parseddesc;
1029 assert(md->paramcount >= 1);
1030 instra.type = TYPE_ADR;
1031 instra.regoff = md->params[0].regoff;
1032 if (md->params[0].inmemory) {
1033 instra.flags = INMEMORY;
1034 instra.regoff += (1 + code->stackframesize);
1039 replace_read_value(es, sp, &instra, &(frame->instance));
1041 #endif /* defined(REPLACE_PATCH_DYNAMIC_CALL) */
1043 /* read stack slots */
1045 frame->javastackdepth = count;
1046 frame->javastack = DMNEW(u8, count);
1047 frame->javastacktype = DMNEW(u1, count);
1049 #if !defined(NDEBUG)
1050 /* mark values as undefined */
1051 for (i=0; i<count; ++i) {
1052 frame->javastack[i] = (u8) 0x00dead0000dead00ULL;
1053 frame->javastacktype[i] = TYPE_VOID;
1055 #endif /* !defined(NDEBUG) */
1059 /* the first stack slot is special in SBR and EXH blocks */
1061 if (topslot == TOP_IS_ON_STACK) {
1064 assert(ra->index == RPLALLOC_STACK);
1065 frame->javastack[i] = sp[-1];
1066 frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
1071 else if (topslot == TOP_IS_IN_ITMP1) {
1074 assert(ra->index == RPLALLOC_STACK);
1075 frame->javastack[i] = es->intregs[REG_ITMP1];
1076 frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
1081 else if (topslot == TOP_IS_VOID) {
1084 assert(ra->index == RPLALLOC_STACK);
1085 frame->javastack[i] = 0;
1086 frame->javastacktype[i] = TYPE_VOID;
1092 /* read remaining stack slots */
1094 for (; count--; ra++) {
1095 if (ra->index == RPLALLOC_SYNC) {
1096 assert(rp->type == RPLPOINT_TYPE_INLINE);
1098 /* only read synchronization slots when traversing an inline point */
1101 sourceframe_t *calleeframe = frame->down;
1102 assert(calleeframe);
1103 assert(calleeframe->syncslotcount == 0);
1104 assert(calleeframe->syncslots == NULL);
1106 calleeframe->syncslotcount = 1;
1107 calleeframe->syncslots = DMNEW(u8, 1);
1108 replace_read_value(es,sp,ra,calleeframe->syncslots);
1111 frame->javastackdepth--;
1115 assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
1117 /* do not read parameters of calls down the call chain */
1119 if (!topframe && ra->index == RPLALLOC_PARAM) {
1120 frame->javastackdepth--;
1123 if (ra->type == TYPE_RET)
1124 frame->javastack[i] = ra->regoff;
1126 replace_read_value(es,sp,ra,frame->javastack + i);
1127 frame->javastacktype[i] = ra->type;
1134 /* replace_write_executionstate ************************************************
1136 Translate the given source state into an execution state.
1139 rp...............replacement point for which execution state should be
1141 es...............where to put the execution state
1142 ss...............the given source state
1145 *es..............the execution state derived from the source state
1147 *******************************************************************************/
1149 static void replace_write_executionstate(rplpoint *rp,
1150 executionstate_t *es,
1159 sourceframe_t *frame;
1162 stackslot_t *basesp;
1166 topslot = TOP_IS_NORMAL;
1168 /* pop a source frame */
1172 ss->frames = frame->down;
1174 /* calculate stack pointer */
1176 sp = (stackslot_t *) es->sp;
1178 basesp = sp + code_get_stack_frame_size(code);
1180 /* in some cases the top stack slot is passed in REG_ITMP1 */
1182 if (rp->type == BBTYPE_EXH) {
1183 topslot = TOP_IS_IN_ITMP1;
1186 /* write javalocals */
1189 count = rp->regalloccount;
1191 while (count && (i = ra->index) >= 0) {
1192 assert(i < m->maxlocals);
1193 assert(i < frame->javalocalcount);
1194 assert(ra->type == frame->javalocaltype[i]);
1195 if (ra->type == TYPE_RET) {
1196 /* XXX assert that it matches this rplpoint */
1199 replace_write_value(es, sp, ra, frame->javalocals + i);
1204 /* write stack slots */
1208 /* the first stack slot is special in SBR and EXH blocks */
1210 if (topslot == TOP_IS_ON_STACK) {
1213 assert(ra->index == RPLALLOC_STACK);
1214 assert(i < frame->javastackdepth);
1215 assert(frame->javastacktype[i] == TYPE_ADR);
1216 sp[-1] = frame->javastack[i];
1221 else if (topslot == TOP_IS_IN_ITMP1) {
1224 assert(ra->index == RPLALLOC_STACK);
1225 assert(i < frame->javastackdepth);
1226 assert(frame->javastacktype[i] == TYPE_ADR);
1227 es->intregs[REG_ITMP1] = frame->javastack[i];
1232 else if (topslot == TOP_IS_VOID) {
1235 assert(ra->index == RPLALLOC_STACK);
1236 assert(i < frame->javastackdepth);
1237 assert(frame->javastacktype[i] == TYPE_VOID);
1243 /* write remaining stack slots */
1245 for (; count--; ra++) {
1246 if (ra->index == RPLALLOC_SYNC) {
1247 assert(rp->type == RPLPOINT_TYPE_INLINE);
1249 /* only write synchronization slots when traversing an inline point */
1252 assert(frame->down);
1253 assert(frame->down->syncslotcount == 1); /* XXX need to understand more cases */
1254 assert(frame->down->syncslots != NULL);
1256 replace_write_value(es,sp,ra,frame->down->syncslots);
1261 assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
1263 /* do not write parameters of calls down the call chain */
1265 if (!topframe && ra->index == RPLALLOC_PARAM) {
1269 assert(i < frame->javastackdepth);
1270 assert(ra->type == frame->javastacktype[i]);
1271 if (ra->type == TYPE_RET) {
1272 /* XXX assert that it matches this rplpoint */
1275 replace_write_value(es,sp,ra,frame->javastack + i);
1287 /* replace_pop_activation_record ***********************************************
1289 Peel a stack frame from the execution state.
1291 *** This function imitates the effects of the method epilog ***
1292 *** and returning from the method call. ***
1295 es...............execution state
1296 frame............source frame, receives synchronization slots
1299 *es..............the execution state after popping the stack frame
1301 *******************************************************************************/
1303 u1* replace_pop_activation_record(executionstate_t *es,
1304 sourceframe_t *frame)
1312 stackslot_t *basesp;
1318 /* read the return address */
1320 ra = md_stacktrace_get_returnaddress(es->sp,
1321 SIZE_OF_STACKSLOT * es->code->stackframesize);
1323 DOLOG( printf("return address: %p\n", (void*)ra); );
1325 /* find the new codeinfo */
1327 pv = md_codegen_get_pv_from_pc(ra);
1329 DOLOG( printf("PV = %p\n", (void*) pv); );
1334 code = *(codeinfo **)(pv + CodeinfoPointer);
1336 DOLOG( printf("CODE = %p\n", (void*) code); );
1341 /* calculate the base of the stack frame */
1343 sp = (stackslot_t *) es->sp;
1344 basesp = sp + es->code->stackframesize;
1346 /* read slots used for synchronization */
1348 assert(frame->syncslotcount == 0);
1349 assert(frame->syncslots == NULL);
1350 count = code_get_sync_slot_count(es->code);
1351 frame->syncslotcount = count;
1352 frame->syncslots = DMNEW(u8, count);
1353 for (i=0; i<count; ++i) {
1354 frame->syncslots[i] = sp[es->code->memuse + i];
1357 /* restore saved int registers */
1360 for (i=0; i<es->code->savedintcount; ++i) {
1361 while (nregdescint[--reg] != REG_SAV)
1363 es->intregs[reg] = *--basesp;
1366 /* restore saved flt registers */
1370 for (i=0; i<es->code->savedfltcount; ++i) {
1371 while (nregdescfloat[--reg] != REG_SAV)
1373 basesp -= STACK_SLOTS_PER_FLOAT;
1374 es->fltregs[reg] = *(u8*)basesp;
1377 /* Set the new pc. Subtract one so we do not hit the replacement point */
1378 /* of the instruction following the call, if there is one. */
1382 /* adjust the stackpointer */
1384 es->sp += SIZE_OF_STACKSLOT * es->code->stackframesize;
1385 es->sp += SIZE_OF_STACKSLOT; /* skip return address */
1390 #if !defined(NDEBUG)
1392 for (i=0; i<INT_REG_CNT; ++i)
1393 if (nregdescint[i] != REG_SAV)
1394 es->intregs[i] = 0x33dead3333dead33ULL;
1395 for (i=0; i<FLT_REG_CNT; ++i)
1396 if (nregdescfloat[i] != REG_SAV)
1397 es->fltregs[i] = 0x33dead3333dead33ULL;
1398 #endif /* !defined(NDEBUG) */
1404 /* replace_patch_future_calls **************************************************
1406 Analyse a call site and depending on the kind of call patch the call, the
1407 virtual function table, or the interface table.
1410 ra...............return address pointing after the call site
1411 calleeframe......source frame of the callee
1412 calleecode.......the codeinfo of the callee
1414 *******************************************************************************/
1416 void replace_patch_future_calls(u1 *ra, sourceframe_t *calleeframe, codeinfo *calleecode)
1420 #if !defined(NDEBUG)
1424 #if defined(REPLACE_VERBOSE)
1435 atentry = (calleeframe->down == NULL)
1436 && !(calleecode->m->flags & ACC_STATIC)
1437 && (calleeframe->readrp->id == 0); /* XXX */
1439 DOLOG( printf("bytes at patch position:");
1440 for (i=0; i<16; ++i)
1441 printf(" %02x", ra[-16+i]);
1444 if (ra[-2] == 0xff && ra[-1] == 0xd1
1447 DOLOG_SHORT( logkind = "static "; );
1448 DOLOG( printf("PATCHING static call to "); method_println(calleecode->m); disas = 7; );
1449 REPLACE_COUNT(stat_staticpatch);
1450 mpp = (methodptr*)(ra - 6);
1452 #if defined(REPLACE_PATCH_DYNAMIC_CALL)
1453 else if (ra[-2] == 0xff && ra[-1] == 0xd2
1454 && ra[-8] == 0x8b && ra[-7] == 0x91
1457 java_objectheader *obj;
1461 DOLOG_SHORT( printf("\tinstance: "); java_value_print(TYPE_ADR, calleeframe->instance);
1464 assert(calleeframe->instance != 0);
1466 obj = (java_objectheader *) (ptrint) calleeframe->instance;
1467 table = (u1*) obj->vftbl;
1468 offset = *(u4*)(ra - 6);
1470 if (ra[-10] == 0x8b && ra[-9] == 0x08) {
1471 mpp = (methodptr *) (table + offset);
1472 DOLOG_SHORT( logkind = "virtual "; );
1473 DOLOG( printf("updating virtual call at %p\n", (void*) ra); disas = 8);
1476 u4 ioffset = *(u4*)(ra - 12);
1477 u1 *itable = *(u1**)(table + ioffset);
1479 assert(ra[-14] == 0x8b && ra[-13] == 0x89);
1480 mpp = (methodptr *) (itable + offset);
1481 DOLOG_SHORT( logkind = "interface"; );
1482 DOLOG( printf("updating interface call at %p\n", (void*) ra); disas = 14);
1485 #endif /* defined(REPLACE_PATCH_DYNAMIC_CALL) */
1491 u1* u1ptr = ra - disas;
1499 DOLOG( printf("patch method pointer from: %p to %p\n",
1500 (void*) *mpp, (void*)calleecode->entrypoint); );
1502 #if !defined(NDEBUG)
1503 oldcode = *(codeinfo **)((u1*)(*mpp) + CodeinfoPointer);
1504 newcode = *(codeinfo **)((u1*)(calleecode->entrypoint) + CodeinfoPointer);
1506 DOLOG_SHORT( printf("\tpatch %s %p ", logkind, (void*) oldcode->entrypoint);
1507 method_println(oldcode->m);
1508 printf("\t with %p ", (void*) newcode->entrypoint);
1509 method_println(newcode->m); );
1511 assert(oldcode->m == newcode->m);
1514 /* write the new entrypoint */
1516 *mpp = (methodptr) calleecode->entrypoint;
1520 /* replace_push_activation_record **********************************************
1522 Push a stack frame onto the execution state.
1524 *** This function imitates the effects of a call and the ***
1525 *** method prolog of the callee. ***
1528 es...............execution state
1529 rpcall...........the replacement point at the call site
1530 callerframe......source frame of the caller
1531 calleecode.......the codeinfo of the callee
1532 calleeframe......source frame of the callee
1535 *es..............the execution state after pushing the stack frame
1537 *******************************************************************************/
1539 void replace_push_activation_record(executionstate_t *es,
1541 sourceframe_t *callerframe,
1542 codeinfo *calleecode,
1543 sourceframe_t *calleeframe)
1548 stackslot_t *basesp;
1553 assert(rpcall && rpcall->type == RPLPOINT_TYPE_CALL);
1555 assert(callerframe);
1556 assert(calleeframe);
1557 assert(calleeframe == callerframe->down);
1559 /* write the return address */
1561 es->sp -= SIZE_OF_STACKSLOT;
1563 ra = rpcall->pc + rpcall->callsize;
1565 DOLOG( printf("writing return address %p to %p\n",
1566 (void*) ra, (void*) es->sp); );
1568 *((stackslot_t *)es->sp) = (stackslot_t) ra;
1570 /* we move into a new code unit */
1572 es->code = calleecode;
1574 /* set the new pc XXX not needed */
1576 es->pc = es->code->entrypoint;
1578 /* build the stackframe */
1580 DOLOG( printf("building stackframe of %d words at %p\n",
1581 es->code->stackframesize, (void*)es->sp); );
1583 sp = (stackslot_t *) es->sp;
1586 sp -= es->code->stackframesize;
1589 /* in debug mode, invalidate stack frame first */
1591 #if !defined(NDEBUG)
1592 for (i=0; i<(basesp - sp); ++i) {
1593 sp[i] = 0xdeaddeadU;
1597 /* save int registers */
1600 for (i=0; i<es->code->savedintcount; ++i) {
1601 while (nregdescint[--reg] != REG_SAV)
1603 *--basesp = es->intregs[reg];
1605 #if !defined(NDEBUG)
1606 es->intregs[reg] = 0x44dead4444dead44ULL;
1610 /* save flt registers */
1614 for (i=0; i<es->code->savedfltcount; ++i) {
1615 while (nregdescfloat[--reg] != REG_SAV)
1617 basesp -= STACK_SLOTS_PER_FLOAT;
1618 *(u8*)basesp = es->fltregs[reg];
1620 #if !defined(NDEBUG)
1621 es->fltregs[reg] = 0x44dead4444dead44ULL;
1625 /* write slots used for synchronization */
1627 count = code_get_sync_slot_count(es->code);
1628 assert(count == calleeframe->syncslotcount);
1629 for (i=0; i<count; ++i) {
1630 sp[es->code->memuse + i] = calleeframe->syncslots[i];
1635 es->pv = es->code->entrypoint;
1637 /* redirect future invocations */
1639 #if defined(REPLACE_PATCH_ALL)
1640 if (rpcall->type == callerframe->readrp->type)
1642 if (rpcall == callerframe->readrp)
1644 replace_patch_future_calls(ra, calleeframe, calleecode);
1648 /* replace_find_replacement_point **********************************************
1650 Find the replacement point in the given code corresponding to the
1651 position given in the source frame.
1654 code.............the codeinfo in which to search the rplpoint
1655 ss...............the source state defining the position to look for
1656 parent...........parent replacement point to match
1659 the replacement point
1661 *******************************************************************************/
1663 rplpoint * replace_find_replacement_point(codeinfo *code,
1667 sourceframe_t *frame;
1680 DOLOG( printf("searching replacement point for:\n");
1681 replace_source_frame_println(frame); );
1685 DOLOG( printf("code = %p\n", (void*)code); );
1687 rp = code->rplpoints;
1688 i = code->rplpointcount;
1690 if (rp->id == frame->id && rp->method == frame->method
1691 && rp->parent == parent
1692 && replace_normalize_type_map[rp->type] == frame->type)
1694 /* check if returnAddresses match */
1695 /* XXX optimize: only do this if JSRs in method */
1696 DOLOG( printf("checking match for:");
1697 replace_replacement_point_println(rp, 1); fflush(stdout); );
1700 for (j = rp->regalloccount; j--; ++ra) {
1701 if (ra->type == TYPE_RET) {
1702 if (ra->index == RPLALLOC_STACK) {
1703 assert(stacki < frame->javastackdepth);
1704 if (frame->javastack[stacki] != ra->regoff)
1709 assert(ra->index >= 0 && ra->index < frame->javalocalcount);
1710 if (frame->javalocals[ra->index] != ra->regoff)
1723 #if !defined(NDEBUG)
1724 printf("candidate replacement points were:\n");
1725 rp = code->rplpoints;
1726 i = code->rplpointcount;
1728 replace_replacement_point_println(rp, 1);
1732 vm_abort("no matching replacement point found");
1733 return NULL; /* NOT REACHED */
1737 /* replace_me ******************************************************************
1739 This function is called by asm_replacement_out when a thread reaches
1740 a replacement point. `replace_me` must map the execution state to the
1741 target replacement point and let execution continue there.
1743 This function never returns!
1746 rp...............replacement point that has been reached
1747 es...............execution state read by asm_replacement_out
1749 *******************************************************************************/
1751 void replace_me(rplpoint *rp, executionstate_t *es)
1755 rplpoint *candidate;
1762 sourceframe_t *prevframe;
1763 #if defined(REPLACE_STATISTICS)
1768 es->code = rp->code;
1770 DOLOG_SHORT( printf("REPLACING(%d %p): (id %d %p) ",
1771 stat_replacements, (void*)THREADOBJECT,
1773 method_println(es->code->m); );
1775 DOLOG( printf("replace_me(%p,%p)\n",(void*)rp,(void*)es); fflush(stdout);
1776 replace_replacement_point_println(rp, 1);
1777 replace_executionstate_println(es); );
1779 REPLACE_COUNT(stat_replacements);
1781 /* mark start of dump memory area */
1783 dumpsize = dump_size();
1785 /* read execution state of old code */
1794 DOLOG( printf("recovering source state for%s:\n",
1795 (ss.frames == NULL) ? " TOPFRAME" : "");
1796 replace_replacement_point_println(candidate, 1); );
1798 replace_read_executionstate(candidate, es, &ss, ss.frames == NULL);
1799 REPLACE_COUNT(stat_frames);
1802 #if defined(REPLACE_STATISTICS)
1804 int adr = 0; int ret = 0; int prim = 0; int vd = 0; int n = 0;
1805 for (i=0; i<ss.frames->javalocalcount; ++i) {
1806 switch (ss.frames->javalocaltype[i]) {
1807 case TYPE_ADR: adr++; break;
1808 case TYPE_RET: ret++; break;
1809 case TYPE_INT: case TYPE_LNG: case TYPE_FLT: case TYPE_DBL: prim++; break;
1810 case TYPE_VOID: vd++; break;
1815 REPLACE_COUNT_DIST(stat_dist_locals, n);
1816 REPLACE_COUNT_DIST(stat_dist_locals_adr, adr);
1817 REPLACE_COUNT_DIST(stat_dist_locals_void, vd);
1818 REPLACE_COUNT_DIST(stat_dist_locals_ret, ret);
1819 REPLACE_COUNT_DIST(stat_dist_locals_prim, prim);
1820 adr = ret = prim = n = 0;
1821 for (i=0; i<ss.frames->javastackdepth; ++i) {
1822 switch (ss.frames->javastacktype[i]) {
1823 case TYPE_ADR: adr++; break;
1824 case TYPE_RET: ret++; break;
1825 case TYPE_INT: case TYPE_LNG: case TYPE_FLT: case TYPE_DBL: prim++; break;
1829 REPLACE_COUNT_DIST(stat_dist_stack, n);
1830 REPLACE_COUNT_DIST(stat_dist_stack_adr, adr);
1831 REPLACE_COUNT_DIST(stat_dist_stack_ret, ret);
1832 REPLACE_COUNT_DIST(stat_dist_stack_prim, prim);
1834 #endif /* defined(REPLACE_STATISTICS) */
1836 if (candidate->parent) {
1837 DOLOG( printf("INLINED!\n"); );
1838 candidate = candidate->parent;
1839 assert(candidate->type == RPLPOINT_TYPE_INLINE);
1840 REPLACE_COUNT(stat_unroll_inline);
1843 DOLOG( printf("UNWIND\n"); );
1844 REPLACE_COUNT(stat_unroll_call);
1846 ra = replace_pop_activation_record(es, ss.frames);
1848 DOLOG( printf("BREAKING\n"); );
1851 DOLOG( replace_executionstate_println(es); );
1853 rp = es->code->rplpoints;
1854 for (i=0; i<es->code->rplpointcount; ++i, ++rp)
1855 if (rp->pc <= es->pc)
1858 DOLOG( printf("NO CANDIDATE!\n"); );
1860 DOLOG( printf("found replacement point.\n");
1861 replace_replacement_point_println(candidate, 1); );
1862 assert(candidate->type == RPLPOINT_TYPE_CALL);
1865 } while (candidate);
1867 REPLACE_COUNT_DIST(stat_dist_frames, depth);
1868 DOLOG( replace_sourcestate_println(&ss); );
1870 /* write execution state of new code */
1872 DOLOG( replace_executionstate_println(es); );
1876 /* XXX get new code */
1882 candidate = replace_find_replacement_point(code, &ss, parent);
1884 DOLOG( printf("creating execution state for%s:\n",
1885 (ss.frames->down == NULL) ? " TOPFRAME" : "");
1886 replace_replacement_point_println(ss.frames->readrp, 1);
1887 replace_replacement_point_println(candidate, 1); );
1889 DOLOG_SHORT( printf("\t%c%s ",
1890 (candidate == ss.frames->readrp) ? '=' : '+',
1891 replace_type_str[candidate->type]);
1892 method_println(ss.frames->method); );
1894 prevframe = ss.frames;
1895 replace_write_executionstate(candidate, es, &ss, ss.frames->down == NULL);
1896 if (ss.frames == NULL)
1898 DOLOG( replace_executionstate_println(es); );
1900 if (candidate->type == RPLPOINT_TYPE_CALL) {
1901 #if defined(REPLACE_STATISTICS)
1902 oldcode = ss.frames->method->code;
1904 code = jit_get_current_code(ss.frames->method);
1906 REPLACE_COUNT_IF(stat_recompile, code != oldcode);
1908 DOLOG( printf("pushing activation record for:\n");
1909 replace_replacement_point_println(candidate, 1); );
1911 replace_push_activation_record(es, candidate, prevframe, code, ss.frames);
1917 DOLOG( replace_executionstate_println(es); );
1920 DOLOG( replace_executionstate_println(es); );
1923 if (candidate == origrp) {
1925 printf("WARNING: identity replacement, turning off rp to avoid infinite loop\n");
1927 replace_deactivate_replacement_point(origrp);
1930 /* release dump area */
1932 dump_release(dumpsize);
1934 /* enter new code */
1936 DOLOG( printf("JUMPING IN!\n"); fflush(stdout); );
1938 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
1939 asm_replacement_in(es);
1941 abort(); /* NOT REACHED */
1945 /* replace_replacement_point_println *******************************************
1947 Print replacement point info.
1950 rp...............the replacement point to print
1952 *******************************************************************************/
1954 #if !defined(NDEBUG)
1956 #define TYPECHAR(t) (((t) >= 0 && (t) <= TYPE_RET) ? show_jit_type_letters[t] : '?')
1958 void replace_replacement_point_println(rplpoint *rp, int depth)
1964 printf("(rplpoint *)NULL\n");
1968 for (j=0; j<depth; ++j)
1971 printf("rplpoint (id %d) %p pc:%p+%d out:%p target:%p mcode:%016llx type:%s",
1972 rp->id, (void*)rp,rp->pc,rp->callsize,rp->outcode,(void*)rp->target,
1973 (unsigned long long)rp->mcode,replace_type_str[rp->type]);
1974 if (rp->flags & RPLPOINT_FLAG_NOTRAP)
1976 printf(" parent:%p\n", (void*)rp->parent);
1977 for (j=0; j<depth; ++j)
1979 printf("ra:%d = [", rp->regalloccount);
1981 for (j=0; j<rp->regalloccount; ++j) {
1984 index = rp->regalloc[j].index;
1986 case RPLALLOC_STACK: printf("S"); break;
1987 case RPLALLOC_PARAM: printf("P"); break;
1988 case RPLALLOC_SYNC : printf("Y"); break;
1989 default: printf("%d", index);
1991 printf(":%1c:", TYPECHAR(rp->regalloc[j].type));
1992 if (rp->regalloc[j].type == TYPE_RET) {
1993 printf("ret(L%03d)", rp->regalloc[j].regoff);
1996 show_allocation(rp->regalloc[j].type, rp->regalloc[j].flags, rp->regalloc[j].regoff);
2001 for (j=0; j<depth; ++j)
2004 method_print(rp->method);
2011 /* replace_show_replacement_points *********************************************
2013 Print replacement point info.
2016 code.............codeinfo whose replacement points should be printed.
2018 *******************************************************************************/
2020 #if !defined(NDEBUG)
2021 void replace_show_replacement_points(codeinfo *code)
2029 printf("(codeinfo *)NULL\n");
2033 printf("\treplacement points: %d\n",code->rplpointcount);
2035 printf("\ttotal allocations : %d\n",code->regalloccount);
2036 printf("\tsaved int regs : %d\n",code->savedintcount);
2037 printf("\tsaved flt regs : %d\n",code->savedfltcount);
2038 printf("\tmemuse : %d\n",code->memuse);
2042 for (i=0; i<code->rplpointcount; ++i) {
2043 rp = code->rplpoints + i;
2045 assert(rp->code == code);
2048 parent = rp->parent;
2051 parent = parent->parent;
2053 replace_replacement_point_println(rp, depth);
2059 /* replace_executionstate_println **********************************************
2061 Print execution state
2064 es...............the execution state to print
2066 *******************************************************************************/
2068 #if !defined(NDEBUG)
2069 void replace_executionstate_println(executionstate_t *es)
2077 printf("(executionstate_t *)NULL\n");
2081 printf("executionstate_t:\n");
2082 printf("\tpc = %p",(void*)es->pc);
2083 printf(" sp = %p",(void*)es->sp);
2084 printf(" pv = %p\n",(void*)es->pv);
2085 #if defined(ENABLE_DISASSEMBLER)
2086 for (i=0; i<INT_REG_CNT; ++i) {
2091 printf("%-3s = %016llx",regs[i],(unsigned long long)es->intregs[i]);
2095 for (i=0; i<FLT_REG_CNT; ++i) {
2100 printf("F%02d = %016llx",i,(unsigned long long)es->fltregs[i]);
2106 sp = (stackslot_t *) es->sp;
2111 methoddesc *md = es->code->m->parseddesc;
2112 slots = code_get_stack_frame_size(es->code);
2113 extraslots = 1 + md->memuse;
2120 printf("\tstack slots(+%d) at sp:", extraslots);
2121 for (i=0; i<slots+extraslots; ++i) {
2124 printf("M%02d%c", i, (i >= slots) ? '(' : ' ');
2125 #ifdef HAS_4BYTE_STACKSLOT
2126 printf("%08lx",(unsigned long)*sp++);
2128 printf("%016llx",(unsigned long long)*sp++);
2130 printf("%c", (i >= slots) ? ')' : ' ');
2135 printf("\tcode: %p", (void*)es->code);
2136 if (es->code != NULL) {
2137 printf(" stackframesize=%d ", es->code->stackframesize);
2138 method_print(es->code->m);
2146 #if !defined(NDEBUG)
2147 void java_value_print(s4 type, u8 value)
2149 java_objectheader *obj;
2152 printf("%016llx",(unsigned long long) value);
2154 if (type < 0 || type > TYPE_RET)
2155 printf(" <INVALID TYPE:%d>", type);
2157 printf(" %s", show_jit_type_names[type]);
2159 if (type == TYPE_ADR && value != 0) {
2160 obj = (java_objectheader *) (ptrint) value;
2162 utf_display_printable_ascii_classname(obj->vftbl->class->name);
2164 if (obj->vftbl->class == class_java_lang_String) {
2166 u = javastring_toutf((java_lang_String *)obj, false);
2167 utf_display_printable_ascii(u);
2171 else if (type == TYPE_INT || type == TYPE_LNG) {
2172 printf(" %lld", (long long) value);
2175 #endif /* !defined(NDEBUG) */
2178 #if !defined(NDEBUG)
2179 void replace_source_frame_println(sourceframe_t *frame)
2185 method_println(frame->method);
2186 printf("\tid: %d\n", frame->id);
2187 printf("\ttype: %s\n", replace_type_str[frame->type]);
2190 if (frame->instance) {
2191 printf("\tinstance: ");
2192 java_value_print(TYPE_ADR, frame->instance);
2196 if (frame->javalocalcount) {
2197 printf("\tlocals (%d):\n",frame->javalocalcount);
2198 for (i=0; i<frame->javalocalcount; ++i) {
2199 t = frame->javalocaltype[i];
2200 if (t == TYPE_VOID) {
2201 printf("\tlocal[ %2d] = void\n",i);
2204 printf("\tlocal[%c%2d] = ",TYPECHAR(t),i);
2205 java_value_print(t, frame->javalocals[i]);
2212 if (frame->javastackdepth) {
2213 printf("\tstack (depth %d):\n",frame->javastackdepth);
2214 for (i=0; i<frame->javastackdepth; ++i) {
2215 t = frame->javastacktype[i];
2216 if (t == TYPE_VOID) {
2217 printf("\tstack[%2d] = void", i);
2220 printf("\tstack[%2d] = ",i);
2221 java_value_print(frame->javastacktype[i], frame->javastack[i]);
2228 if (frame->syncslotcount) {
2229 printf("\tsynchronization slots (%d):\n",frame->syncslotcount);
2230 for (i=0; i<frame->syncslotcount; ++i) {
2231 printf("\tslot[%2d] = ",i);
2232 #ifdef HAS_4BYTE_STACKSLOT
2233 printf("%08lx\n",(unsigned long) frame->syncslots[i]);
2235 printf("%016llx\n",(unsigned long long) frame->syncslots[i]);
2241 if (frame->readrp) {
2242 printf("\tread replacement point:\n");
2243 replace_replacement_point_println(frame->readrp, 2);
2247 #endif /* !defined(NDEBUG) */
2250 /* replace_sourcestate_println *************************************************
2255 ss...............the source state to print
2257 *******************************************************************************/
2259 #if !defined(NDEBUG)
2260 void replace_sourcestate_println(sourcestate_t *ss)
2263 sourceframe_t *frame;
2266 printf("(sourcestate_t *)NULL\n");
2270 printf("sourcestate_t:\n");
2272 for (i=0, frame = ss->frames; frame != NULL; frame = frame->down, ++i) {
2273 printf(" frame %d:\n", i);
2274 replace_source_frame_println(frame);
2280 * These are local overrides for various environment variables in Emacs.
2281 * Please do not remove this and leave it at the end of the file, where
2282 * Emacs will automagically detect them.
2283 * ---------------------------------------------------------------------
2286 * indent-tabs-mode: t
2290 * vim:noexpandtab:sw=4:ts=4: