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
92 /* replace_create_replacement_point ********************************************
94 Create a replacement point.
97 jd...............current jitdata
98 iinfo............inlining info for the current position
99 rp...............pre-allocated (uninitialized) rplpoint
100 type.............RPLPOINT_TYPE constant
101 *pra.............current rplalloc pointer
102 javalocals.......the javalocals at the current point
103 stackvars........the stack variables at the current point
104 stackdepth.......the stack depth at the current point
105 paramcount.......number of parameters at the start of stackvars
108 *rpa.............points to the next free rplalloc
110 *******************************************************************************/
112 static void replace_create_replacement_point(jitdata *jd,
113 insinfo_inline *iinfo,
130 /* there will be a replacement point at the start of this block */
132 rp->method = (iinfo) ? iinfo->method : jd->m;
133 rp->pc = NULL; /* set by codegen */
134 rp->outcode = NULL; /* set by codegen */
135 rp->callsize = 0; /* set by codegen */
140 rp->id = iptr->flags.bits >> INS_FLAG_ID_SHIFT;
142 /* XXX unify these two fields */
144 rp->parent = (iinfo) ? iinfo->rp : NULL;
146 /* store local allocation info of javalocals */
149 for (i = 0; i < rp->method->maxlocals; ++i) {
150 index = javalocals[i];
155 if (index < UNUSED) {
156 ra->regoff = (UNUSED - index) - 1;
162 ra->flags = v->flags & (INMEMORY);
163 ra->regoff = v->vv.regoff;
170 /* store allocation info of java stack vars */
172 for (i = 0; i < stackdepth; ++i) {
173 v = VAR(stackvars[i]);
174 ra->flags = v->flags & (INMEMORY);
175 ra->index = (i < paramcount) ? RPLALLOC_PARAM : RPLALLOC_STACK;
177 /* XXX how to handle locals on the stack containing returnAddresses? */
178 if (v->type == TYPE_RET) {
179 assert(stackvars[i] >= jd->localcount);
180 ra->regoff = v->vv.retaddr->nr;
183 ra->regoff = v->vv.regoff;
187 /* total number of allocations */
189 rp->regalloccount = ra - rp->regalloc;
195 /* replace_create_replacement_points *******************************************
197 Create the replacement points for the given code.
200 jd...............current jitdata, must not have any replacement points
203 code->rplpoints.......set to the list of replacement points
204 code->rplpointcount...number of replacement points
205 code->regalloc........list of allocation info
206 code->regalloccount...total length of allocation info list
207 code->globalcount.....number of global allocations at the
208 start of code->regalloc
211 true.............everything ok
212 false............an exception has been thrown
214 *******************************************************************************/
216 bool replace_create_replacement_points(jitdata *jd)
234 insinfo_inline *iinfo;
235 insinfo_inline *calleeinfo;
238 /* get required compiler data */
243 /* assert that we wont overwrite already allocated data */
247 assert(code->rplpoints == NULL);
248 assert(code->rplpointcount == 0);
249 assert(code->regalloc == NULL);
250 assert(code->regalloccount == 0);
251 assert(code->globalcount == 0);
253 /* iterate over the basic block list to find replacement points */
260 javalocals = DMNEW(s4, jd->maxlocals);
262 for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
266 if (bptr->flags < BBFINISHED)
269 /* get info about this block */
272 iinfo = bptr->inlineinfo;
274 /* initialize javalocals at the start of this block */
276 if (bptr->javalocals)
277 MCOPY(javalocals, bptr->javalocals, s4, m->maxlocals);
279 for (i=0; i<m->maxlocals; ++i)
280 javalocals[i] = UNUSED;
282 /* iterate over the instructions */
285 iend = iptr + bptr->icount;
288 for (; iptr != iend; ++iptr) {
290 case ICMD_INVOKESTATIC:
291 case ICMD_INVOKESPECIAL:
292 case ICMD_INVOKEVIRTUAL:
293 case ICMD_INVOKEINTERFACE:
294 INSTRUCTION_GET_METHODDESC(iptr, md);
296 for (i=0; i<m->maxlocals; ++i)
297 if (javalocals[i] != UNUSED)
299 alloccount += iptr->s1.argcount;
301 alloccount -= iinfo->throughcount;
309 /* XXX share code with stack.c */
310 j = iptr->dst.varindex;
311 i = iptr->sx.s23.s3.javaindex;
313 if (iptr->flags.bits & INS_FLAG_RETADDR)
314 javalocals[i] = iptr->sx.s23.s2.retaddrnr;
317 if (iptr->flags.bits & INS_FLAG_KILL_PREV)
318 javalocals[i-1] = UNUSED;
319 if (iptr->flags.bits & INS_FLAG_KILL_NEXT)
320 javalocals[i+1] = UNUSED;
335 case ICMD_INLINE_START:
336 iinfo = iptr->sx.s23.s3.inlineinfo;
339 for (i=0; i<m->maxlocals; ++i)
340 if (javalocals[i] != UNUSED)
342 alloccount += iinfo->stackvarscount;
343 if (iinfo->synclocal != UNUSED)
347 if (iinfo->javalocals_start)
348 MCOPY(javalocals, iinfo->javalocals_start, s4, m->maxlocals);
351 case ICMD_INLINE_END:
352 iinfo = iptr->sx.s23.s3.inlineinfo;
354 if (iinfo->javalocals_end)
355 MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
356 iinfo = iinfo->parent;
359 } /* end instruction loop */
361 /* create replacement points at targets of backward branches */
362 /* We only need the replacement point there, if there is no */
363 /* replacement point inside the block. */
365 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
366 if (count > startcount) {
367 /* we don't need it */
368 bptr->bitflags &= ~BBFLAG_REPLACEMENT;
372 alloccount += bptr->indepth;
374 for (i=0; i<m->maxlocals; ++i)
375 if (bptr->javalocals[i] != UNUSED)
380 } /* end basicblock loop */
382 /* if no points were found, there's nothing to do */
387 /* allocate replacement point array and allocation array */
389 rplpoints = MNEW(rplpoint, count);
390 regalloc = MNEW(rplalloc, alloccount);
393 /* initialize replacement point structs */
397 /* XXX try to share code with the counting loop! */
399 for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
402 if (bptr->flags < BBFINISHED)
405 /* get info about this block */
408 iinfo = bptr->inlineinfo;
410 /* initialize javalocals at the start of this block */
412 if (bptr->javalocals)
413 MCOPY(javalocals, bptr->javalocals, s4, m->maxlocals);
415 for (i=0; i<m->maxlocals; ++i)
416 javalocals[i] = UNUSED;
418 /* create replacement points at targets of backward branches */
420 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
422 replace_create_replacement_point(jd, iinfo, rp++,
423 bptr->type, bptr->iinstr, &ra,
424 bptr->javalocals, bptr->invars, bptr->indepth, 0);
427 /* iterate over the instructions */
430 iend = iptr + bptr->icount;
432 for (; iptr != iend; ++iptr) {
434 case ICMD_INVOKESTATIC:
435 case ICMD_INVOKESPECIAL:
436 case ICMD_INVOKEVIRTUAL:
437 case ICMD_INVOKEINTERFACE:
438 INSTRUCTION_GET_METHODDESC(iptr, md);
440 i = (iinfo) ? iinfo->throughcount : 0;
441 replace_create_replacement_point(jd, iinfo, rp++,
442 RPLPOINT_TYPE_CALL, iptr, &ra,
443 javalocals, iptr->sx.s23.s2.args,
444 iptr->s1.argcount - i,
453 /* XXX share code with stack.c */
454 j = iptr->dst.varindex;
455 i = iptr->sx.s23.s3.javaindex;
457 if (iptr->flags.bits & INS_FLAG_RETADDR)
458 javalocals[i] = iptr->sx.s23.s2.retaddrnr;
461 if (iptr->flags.bits & INS_FLAG_KILL_PREV)
462 javalocals[i-1] = UNUSED;
463 if (iptr->flags.bits & INS_FLAG_KILL_NEXT)
464 javalocals[i+1] = UNUSED;
473 replace_create_replacement_point(jd, iinfo, rp++,
474 RPLPOINT_TYPE_RETURN, iptr, &ra,
475 NULL, &(iptr->s1.varindex), 1, 0);
479 replace_create_replacement_point(jd, iinfo, rp++,
480 RPLPOINT_TYPE_RETURN, iptr, &ra,
484 case ICMD_INLINE_START:
485 calleeinfo = iptr->sx.s23.s3.inlineinfo;
488 replace_create_replacement_point(jd, iinfo, rp++,
489 RPLPOINT_TYPE_INLINE, iptr, &ra,
491 calleeinfo->stackvars, calleeinfo->stackvarscount,
492 calleeinfo->paramcount);
494 if (calleeinfo->synclocal != UNUSED) {
495 ra->index = RPLALLOC_SYNC;
496 ra->regoff = jd->var[calleeinfo->synclocal].vv.regoff;
497 ra->flags = jd->var[calleeinfo->synclocal].flags & INMEMORY;
500 rp[-1].regalloccount++;
505 if (iinfo->javalocals_start)
506 MCOPY(javalocals, iinfo->javalocals_start, s4, m->maxlocals);
509 case ICMD_INLINE_END:
510 iinfo = iptr->sx.s23.s3.inlineinfo;
512 if (iinfo->javalocals_end)
513 MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
514 iinfo = iinfo->parent;
517 } /* end instruction loop */
518 } /* end basicblock loop */
520 assert((rp - rplpoints) == count);
521 assert((ra - regalloc) == alloccount);
523 /* store the data in the codeinfo */
525 code->rplpoints = rplpoints;
526 code->rplpointcount = count;
527 code->regalloc = regalloc;
528 code->regalloccount = alloccount;
529 code->globalcount = 0;
530 code->savedintcount = INT_SAV_CNT - rd->savintreguse;
531 code->savedfltcount = FLT_SAV_CNT - rd->savfltreguse;
532 code->memuse = rd->memuse;
533 code->stackframesize = jd->cd->stackframesize;
535 /* everything alright */
541 /* replace_free_replacement_points *********************************************
543 Free memory used by replacement points.
546 code.............codeinfo whose replacement points should be freed.
548 *******************************************************************************/
550 void replace_free_replacement_points(codeinfo *code)
555 MFREE(code->rplpoints,rplpoint,code->rplpointcount);
558 MFREE(code->regalloc,rplalloc,code->regalloccount);
560 code->rplpoints = NULL;
561 code->rplpointcount = 0;
562 code->regalloc = NULL;
563 code->regalloccount = 0;
564 code->globalcount = 0;
568 /* replace_activate_replacement_point ******************************************
570 Activate a replacement point. When this function returns, the
571 replacement point is "armed", that is each thread reaching this point
572 will be replace to `target`.
575 rp...............replacement point to activate
576 target...........target of replacement
578 *******************************************************************************/
580 void replace_activate_replacement_point(rplpoint *rp,rplpoint *target)
582 assert(rp->target == NULL);
584 DOLOG( printf("activate replacement point:\n");
585 replace_replacement_point_println(rp, 1); fflush(stdout); );
589 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
590 md_patch_replacement_point(rp);
595 /* replace_deactivate_replacement_point ****************************************
597 Deactivate a replacement point. When this function returns, the
598 replacement point is "un-armed", that is a each thread reaching this point
599 will just continue normally.
602 rp...............replacement point to deactivate
604 *******************************************************************************/
606 void replace_deactivate_replacement_point(rplpoint *rp)
610 DOLOG( printf("deactivate replacement point:\n");
611 replace_replacement_point_println(rp, 1); fflush(stdout); );
615 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
616 md_patch_replacement_point(rp);
621 /* replace_read_value **********************************************************
623 Read a value with the given allocation from the execution state.
626 es...............execution state
627 sp...............stack pointer of the execution state (XXX eliminate?)
628 ra...............allocation
629 javaval..........where to put the value
632 *javaval.........the value
634 *******************************************************************************/
636 static void replace_read_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 *javaval = *(u8*)(sp + ra->regoff);
649 *javaval = sp[ra->regoff];
650 #ifdef HAS_4BYTE_STACKSLOT
655 /* allocated register */
656 if (IS_FLT_DBL_TYPE(ra->type)) {
657 *javaval = es->fltregs[ra->regoff];
660 *javaval = es->intregs[ra->regoff];
666 /* replace_write_value *********************************************************
668 Write a value to the given allocation in the execution state.
671 es...............execution state
672 sp...............stack pointer of the execution state (XXX eliminate?)
673 ra...............allocation
674 *javaval.........the value
676 *******************************************************************************/
678 static void replace_write_value(executionstate_t *es,
683 if (ra->flags & INMEMORY) {
684 /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
685 #ifdef HAS_4BYTE_STACKSLOT
686 if (IS_2_WORD_TYPE(ra->type)) {
687 *(u8*)(sp + ra->regoff) = *javaval;
691 sp[ra->regoff] = *javaval;
692 #ifdef HAS_4BYTE_STACKSLOT
697 /* allocated register */
698 if (IS_FLT_DBL_TYPE(ra->type)) {
699 es->fltregs[ra->regoff] = *javaval;
702 es->intregs[ra->regoff] = *javaval;
708 /* replace_read_executionstate *************************************************
710 Read the given executions state and translate it to a source frame.
713 rp...............replacement point at which `es` was taken
714 es...............execution state
715 ss...............where to put the source state
718 *ss..............the source state derived from the execution state
720 *******************************************************************************/
722 static void replace_read_executionstate(rplpoint *rp,
723 executionstate_t *es,
732 sourceframe_t *frame;
739 topslot = TOP_IS_NORMAL;
743 sp = (stackslot_t *) es->sp;
745 /* in some cases the top stack slot is passed in REG_ITMP1 */
747 if (rp->type == BBTYPE_EXH) {
748 topslot = TOP_IS_IN_ITMP1;
751 /* calculate base stack pointer */
753 basesp = sp + code_get_stack_frame_size(code);
755 /* create the source frame */
757 frame = DNEW(sourceframe_t);
758 frame->up = ss->frames;
759 frame->method = rp->method;
761 frame->syncslotcount = 0;
762 frame->syncslots = NULL;
764 frame->debug_rp = rp;
769 /* read local variables */
771 count = m->maxlocals;
772 frame->javalocalcount = count;
773 frame->javalocals = DMNEW(u8, count);
774 frame->javalocaltype = DMNEW(u1, count);
777 /* mark values as undefined */
778 for (i=0; i<count; ++i) {
779 frame->javalocals[i] = (u8) 0x00dead0000dead00ULL;
780 frame->javalocaltype[i] = TYPE_VOID;
783 /* some entries in the intregs array are not meaningful */
784 /*es->intregs[REG_ITMP3] = (u8) 0x11dead1111dead11ULL;*/
785 es->intregs[REG_SP ] = (u8) 0x11dead1111dead11ULL;
787 es->intregs[REG_PV ] = (u8) 0x11dead1111dead11ULL;
789 #endif /* !defined(NDEBUG) */
791 /* read javalocals */
793 count = rp->regalloccount;
796 while (count && (i = ra->index) >= 0) {
797 assert(i < m->maxlocals);
798 frame->javalocaltype[i] = ra->type;
799 if (ra->type == TYPE_RET)
800 frame->javalocals[i] = ra->regoff;
802 replace_read_value(es, sp, ra, frame->javalocals + i);
807 /* read stack slots */
809 frame->javastackdepth = count;
810 frame->javastack = DMNEW(u8, count);
811 frame->javastacktype = DMNEW(u1, count);
814 /* mark values as undefined */
815 for (i=0; i<count; ++i) {
816 frame->javastack[i] = (u8) 0x00dead0000dead00ULL;
817 frame->javastacktype[i] = TYPE_VOID;
819 #endif /* !defined(NDEBUG) */
823 /* the first stack slot is special in SBR and EXH blocks */
825 if (topslot == TOP_IS_ON_STACK) {
828 assert(ra->index == RPLALLOC_STACK);
829 frame->javastack[i] = sp[-1];
830 frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
835 else if (topslot == TOP_IS_IN_ITMP1) {
838 assert(ra->index == RPLALLOC_STACK);
839 frame->javastack[i] = es->intregs[REG_ITMP1];
840 frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
845 else if (topslot == TOP_IS_VOID) {
848 assert(ra->index == RPLALLOC_STACK);
849 frame->javastack[i] = 0;
850 frame->javastacktype[i] = TYPE_VOID;
856 /* read remaining stack slots */
858 for (; count--; ra++) {
859 if (ra->index == RPLALLOC_SYNC) {
860 assert(rp->type == RPLPOINT_TYPE_INLINE);
862 /* only read synchronization slots when traversing an inline point */
865 sourceframe_t *calleeframe = frame->up;
867 assert(calleeframe->syncslotcount == 0);
868 assert(calleeframe->syncslots == NULL);
870 calleeframe->syncslotcount = 1;
871 calleeframe->syncslots = DMNEW(u8, 1);
872 replace_read_value(es,sp,ra,calleeframe->syncslots);
875 frame->javastackdepth--;
879 assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
881 /* do not read parameters of calls down the call chain */
883 if (!topframe && ra->index == RPLALLOC_PARAM) {
884 frame->javastackdepth--;
887 if (ra->type == TYPE_RET)
888 frame->javastack[i] = ra->regoff;
890 replace_read_value(es,sp,ra,frame->javastack + i);
891 frame->javastacktype[i] = ra->type;
898 /* replace_write_executionstate ************************************************
900 Translate the given source state into an execution state.
903 rp...............replacement point for which execution state should be
905 es...............where to put the execution state
906 ss...............the given source state
909 *es..............the execution state derived from the source state
911 *******************************************************************************/
913 static void replace_write_executionstate(rplpoint *rp,
914 executionstate_t *es,
923 sourceframe_t *frame;
930 topslot = TOP_IS_NORMAL;
932 /* pop a source frame */
936 ss->frames = frame->up;
938 /* calculate stack pointer */
940 sp = (stackslot_t *) es->sp;
942 basesp = sp + code_get_stack_frame_size(code);
944 /* in some cases the top stack slot is passed in REG_ITMP1 */
946 if (rp->type == BBTYPE_EXH) {
947 topslot = TOP_IS_IN_ITMP1;
950 /* write javalocals */
953 count = rp->regalloccount;
955 while (count && (i = ra->index) >= 0) {
956 assert(i < m->maxlocals);
957 assert(i < frame->javalocalcount);
958 assert(ra->type == frame->javalocaltype[i]);
959 if (ra->type == TYPE_RET) {
960 /* XXX assert that it matches this rplpoint */
963 replace_write_value(es, sp, ra, frame->javalocals + i);
968 /* write stack slots */
972 /* the first stack slot is special in SBR and EXH blocks */
974 if (topslot == TOP_IS_ON_STACK) {
977 assert(ra->index == RPLALLOC_STACK);
978 assert(i < frame->javastackdepth);
979 assert(frame->javastacktype[i] == TYPE_ADR);
980 sp[-1] = frame->javastack[i];
985 else if (topslot == TOP_IS_IN_ITMP1) {
988 assert(ra->index == RPLALLOC_STACK);
989 assert(i < frame->javastackdepth);
990 assert(frame->javastacktype[i] == TYPE_ADR);
991 es->intregs[REG_ITMP1] = frame->javastack[i];
996 else if (topslot == TOP_IS_VOID) {
999 assert(ra->index == RPLALLOC_STACK);
1000 assert(i < frame->javastackdepth);
1001 assert(frame->javastacktype[i] == TYPE_VOID);
1007 /* write remaining stack slots */
1009 for (; count--; ra++) {
1010 if (ra->index == RPLALLOC_SYNC) {
1011 assert(rp->type == RPLPOINT_TYPE_INLINE);
1013 /* only write synchronization slots when traversing an inline point */
1016 assert(frame->syncslotcount == 1); /* XXX need to understand more cases */
1017 assert(frame->syncslots != NULL);
1019 replace_write_value(es,sp,ra,frame->syncslots);
1024 assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
1026 /* do not write parameters of calls down the call chain */
1028 if (!topframe && ra->index == RPLALLOC_PARAM) {
1032 assert(i < frame->javastackdepth);
1033 assert(ra->type == frame->javastacktype[i]);
1034 if (ra->type == TYPE_RET) {
1035 /* XXX assert that it matches this rplpoint */
1038 replace_write_value(es,sp,ra,frame->javastack + i);
1050 /* replace_pop_activation_record ***********************************************
1052 Peel a stack frame from the execution state.
1054 *** This function imitates the effects of the method epilog ***
1055 *** and returning from the method call. ***
1058 es...............execution state
1059 frame............source frame, receives synchronization slots
1062 *es..............the execution state after popping the stack frame
1064 *******************************************************************************/
1066 bool replace_pop_activation_record(executionstate_t *es,
1067 sourceframe_t *frame)
1075 stackslot_t *basesp;
1081 /* read the return address */
1083 ra = md_stacktrace_get_returnaddress(es->sp,
1084 SIZE_OF_STACKSLOT * es->code->stackframesize);
1086 DOLOG( printf("return address: %p\n", (void*)ra); );
1088 /* find the new codeinfo */
1090 pv = md_codegen_get_pv_from_pc(ra);
1092 DOLOG( printf("PV = %p\n", (void*) pv); );
1097 code = *(codeinfo **)(pv + CodeinfoPointer);
1099 DOLOG( printf("CODE = %p\n", (void*) code); );
1104 /* calculate the base of the stack frame */
1106 sp = (stackslot_t *) es->sp;
1107 basesp = sp + es->code->stackframesize;
1109 /* read slots used for synchronization */
1111 assert(frame->syncslotcount == 0);
1112 assert(frame->syncslots == NULL);
1113 count = code_get_sync_slot_count(es->code);
1114 frame->syncslotcount = count;
1115 frame->syncslots = DMNEW(u8, count);
1116 for (i=0; i<count; ++i) {
1117 frame->syncslots[i] = sp[es->code->memuse + i];
1120 /* restore saved int registers */
1123 for (i=0; i<es->code->savedintcount; ++i) {
1124 while (nregdescint[--reg] != REG_SAV)
1126 es->intregs[reg] = *--basesp;
1129 /* restore saved flt registers */
1133 for (i=0; i<es->code->savedfltcount; ++i) {
1134 while (nregdescfloat[--reg] != REG_SAV)
1136 basesp -= STACK_SLOTS_PER_FLOAT;
1137 es->fltregs[reg] = *(u8*)basesp;
1140 /* Set the new pc. Subtract one so we do not hit the replacement point */
1141 /* of the instruction following the call, if there is one. */
1145 /* adjust the stackpointer */
1147 es->sp += SIZE_OF_STACKSLOT * es->code->stackframesize;
1148 es->sp += SIZE_OF_STACKSLOT; /* skip return address */
1153 #if !defined(NDEBUG)
1155 for (i=0; i<INT_REG_CNT; ++i)
1156 if (nregdescint[i] != REG_SAV)
1157 es->intregs[i] = 0x33dead3333dead33ULL;
1158 for (i=0; i<FLT_REG_CNT; ++i)
1159 if (nregdescfloat[i] != REG_SAV)
1160 es->fltregs[i] = 0x33dead3333dead33ULL;
1161 #endif /* !defined(NDEBUG) */
1167 /* replace_push_activation_record **********************************************
1169 Push a stack frame onto the execution state.
1171 *** This function imitates the effects of a call and the ***
1172 *** method prolog of the callee. ***
1175 es...............execution state
1176 rpcall...........the replacement point at the call site
1177 calleecode.......the codeinfo of the callee
1178 frame............source frame, only the synch. slots are used
1181 *es..............the execution state after pushing the stack frame
1183 *******************************************************************************/
1185 void replace_push_activation_record(executionstate_t *es,
1187 codeinfo *calleecode,
1188 sourceframe_t *frame)
1193 stackslot_t *basesp;
1197 assert(rpcall && rpcall->type == RPLPOINT_TYPE_CALL);
1201 /* write the return address */
1203 es->sp -= SIZE_OF_STACKSLOT;
1205 DOLOG( printf("writing return address %p to %p\n",
1206 (void*) (rpcall->pc + rpcall->callsize),
1209 *((stackslot_t *)es->sp) = (stackslot_t) (rpcall->pc + rpcall->callsize);
1211 /* we move into a new code unit */
1213 es->code = calleecode;
1215 /* set the new pc XXX not needed */
1217 es->pc = es->code->entrypoint;
1219 /* build the stackframe */
1221 DOLOG( printf("building stackframe of %d words at %p\n",
1222 es->code->stackframesize, (void*)es->sp); );
1224 sp = (stackslot_t *) es->sp;
1227 sp -= es->code->stackframesize;
1230 /* in debug mode, invalidate stack frame first */
1232 #if !defined(NDEBUG)
1233 for (i=0; i<(basesp - sp); ++i) {
1234 sp[i] = 0xdeaddeadU;
1238 /* save int registers */
1241 for (i=0; i<es->code->savedintcount; ++i) {
1242 while (nregdescint[--reg] != REG_SAV)
1244 *--basesp = es->intregs[reg];
1246 #if !defined(NDEBUG)
1247 es->intregs[reg] = 0x44dead4444dead44ULL;
1251 /* save flt registers */
1255 for (i=0; i<es->code->savedfltcount; ++i) {
1256 while (nregdescfloat[--reg] != REG_SAV)
1258 basesp -= STACK_SLOTS_PER_FLOAT;
1259 *(u8*)basesp = es->fltregs[reg];
1261 #if !defined(NDEBUG)
1262 es->fltregs[reg] = 0x44dead4444dead44ULL;
1266 /* write slots used for synchronization */
1268 count = code_get_sync_slot_count(es->code);
1269 assert(count == frame->syncslotcount);
1270 for (i=0; i<count; ++i) {
1271 sp[es->code->memuse + i] = frame->syncslots[i];
1276 es->pv = es->code->entrypoint;
1280 /* replace_find_replacement_point **********************************************
1282 Find the replacement point in the given code corresponding to the
1283 position given in the source frame.
1286 code.............the codeinfo in which to search the rplpoint
1287 ss...............the source state defining the position to look for
1290 the replacement point
1292 *******************************************************************************/
1294 rplpoint * replace_find_replacement_point(codeinfo *code, sourcestate_t *ss)
1296 sourceframe_t *frame;
1309 DOLOG( printf("searching replacement point for:\n");
1310 replace_source_frame_println(frame); );
1314 DOLOG( printf("code = %p\n", (void*)code); );
1316 rp = code->rplpoints;
1317 i = code->rplpointcount;
1319 if (rp->id == frame->id && rp->method == frame->method) {
1320 /* check if returnAddresses match */
1321 /* XXX optimize: only do this if JSRs in method */
1322 DOLOG( printf("checking match for:");
1323 replace_replacement_point_println(rp, 1); fflush(stdout); );
1326 for (j = rp->regalloccount; j--; ++ra) {
1327 if (ra->type == TYPE_RET) {
1328 if (ra->index == RPLALLOC_STACK) {
1329 assert(stacki < frame->javastackdepth);
1330 if (frame->javastack[stacki] != ra->regoff)
1335 assert(ra->index >= 0 && ra->index < frame->javalocalcount);
1336 if (frame->javalocals[ra->index] != ra->regoff)
1350 return NULL; /* NOT REACHED */
1354 /* replace_me ******************************************************************
1356 This function is called by asm_replacement_out when a thread reaches
1357 a replacement point. `replace_me` must map the execution state to the
1358 target replacement point and let execution continue there.
1360 This function never returns!
1363 rp...............replacement point that has been reached
1364 es...............execution state read by asm_replacement_out
1366 *******************************************************************************/
1368 void replace_me(rplpoint *rp, executionstate_t *es)
1373 rplpoint *candidate;
1377 es->code = rp->code;
1379 DOLOG( printf("REPLACING: "); method_println(es->code->m); );
1381 /* mark start of dump memory area */
1383 dumpsize = dump_size();
1385 /* fetch the target of the replacement */
1387 target = rp->target;
1389 /* XXX DEBUG turn off self-replacement */
1391 replace_deactivate_replacement_point(rp);
1393 DOLOG( printf("replace_me(%p,%p)\n",(void*)rp,(void*)es); fflush(stdout);
1394 replace_replacement_point_println(rp, 1);
1395 replace_executionstate_println(es); );
1397 /* read execution state of old code */
1405 DOLOG( printf("recovering source state for%s:\n",
1406 (ss.frames == NULL) ? " TOPFRAME" : "");
1407 replace_replacement_point_println(candidate, 1); );
1409 replace_read_executionstate(candidate, es, &ss, ss.frames == NULL);
1411 if (candidate->parent) {
1412 DOLOG( printf("INLINED!\n"); );
1413 candidate = candidate->parent;
1414 assert(candidate->type == RPLPOINT_TYPE_INLINE);
1417 DOLOG( printf("UNWIND\n"); );
1418 if (!replace_pop_activation_record(es, ss.frames)) {
1419 DOLOG( printf("BREAKING\n"); );
1422 DOLOG( replace_executionstate_println(es); );
1424 rp = es->code->rplpoints;
1425 for (i=0; i<es->code->rplpointcount; ++i, ++rp)
1426 if (rp->pc <= es->pc)
1429 DOLOG( printf("NO CANDIDATE!\n"); );
1431 DOLOG( printf("found replacement point.\n");
1432 replace_replacement_point_println(candidate, 1); );
1433 assert(candidate->type == RPLPOINT_TYPE_CALL);
1436 } while (candidate);
1438 DOLOG( replace_sourcestate_println(&ss); );
1440 /* write execution state of new code */
1442 DOLOG( replace_executionstate_println(es); );
1446 /* XXX get new code */
1450 candidate = replace_find_replacement_point(code, &ss);
1452 DOLOG( printf("creating execution state for%s:\n",
1453 (ss.frames->up == NULL) ? " TOPFRAME" : "");
1454 replace_replacement_point_println(ss.frames->debug_rp, 1);
1455 replace_replacement_point_println(candidate, 1); );
1457 replace_write_executionstate(candidate, es, &ss, ss.frames->up == NULL);
1458 if (ss.frames == NULL)
1460 DOLOG( replace_executionstate_println(es); );
1462 if (candidate->type == RPLPOINT_TYPE_CALL) {
1463 jit_recompile(ss.frames->method);
1464 code = ss.frames->method->code;
1466 DOLOG( printf("pushing activation record for:\n");
1467 replace_replacement_point_println(candidate, 1); );
1468 replace_push_activation_record(es, candidate, code, ss.frames);
1470 DOLOG( replace_executionstate_println(es); );
1473 DOLOG( replace_executionstate_println(es); );
1475 /* release dump area */
1477 dump_release(dumpsize);
1479 /* enter new code */
1481 DOLOG( printf("JUMPING IN!\n"); fflush(stdout); );
1483 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
1484 asm_replacement_in(es);
1486 abort(); /* NOT REACHED */
1490 /* replace_replacement_point_println *******************************************
1492 Print replacement point info.
1495 rp...............the replacement point to print
1497 *******************************************************************************/
1499 #if !defined(NDEBUG)
1501 #define TYPECHAR(t) (((t) >= 0 && (t) <= TYPE_RET) ? show_jit_type_letters[t] : '?')
1503 static char *replace_type_str[] = {
1512 void replace_replacement_point_println(rplpoint *rp, int depth)
1518 printf("(rplpoint *)NULL\n");
1522 for (j=0; j<depth; ++j)
1525 printf("rplpoint (id %d) %p pc:%p+%d out:%p target:%p mcode:%016llx type:%s flags:%01x parent:%p\n",
1526 rp->id, (void*)rp,rp->pc,rp->callsize,rp->outcode,(void*)rp->target,
1527 (unsigned long long)rp->mcode,replace_type_str[rp->type],rp->flags,
1529 for (j=0; j<depth; ++j)
1531 printf("ra:%d = [", rp->regalloccount);
1533 for (j=0; j<rp->regalloccount; ++j) {
1536 index = rp->regalloc[j].index;
1538 case RPLALLOC_STACK: printf("S"); break;
1539 case RPLALLOC_PARAM: printf("P"); break;
1540 case RPLALLOC_SYNC : printf("Y"); break;
1541 default: printf("%d", index);
1543 printf(":%1c:", TYPECHAR(rp->regalloc[j].type));
1544 if (rp->regalloc[j].type == TYPE_RET) {
1545 printf("ret(L%03d)", rp->regalloc[j].regoff);
1548 show_allocation(rp->regalloc[j].type, rp->regalloc[j].flags, rp->regalloc[j].regoff);
1553 for (j=0; j<depth; ++j)
1556 method_print(rp->method);
1563 /* replace_show_replacement_points *********************************************
1565 Print replacement point info.
1568 code.............codeinfo whose replacement points should be printed.
1570 *******************************************************************************/
1572 #if !defined(NDEBUG)
1573 void replace_show_replacement_points(codeinfo *code)
1581 printf("(codeinfo *)NULL\n");
1585 printf("\treplacement points: %d\n",code->rplpointcount);
1587 printf("\ttotal allocations : %d\n",code->regalloccount);
1588 printf("\tsaved int regs : %d\n",code->savedintcount);
1589 printf("\tsaved flt regs : %d\n",code->savedfltcount);
1590 printf("\tmemuse : %d\n",code->memuse);
1594 for (i=0; i<code->rplpointcount; ++i) {
1595 rp = code->rplpoints + i;
1597 assert(rp->code == code);
1600 parent = rp->parent;
1603 parent = parent->parent;
1605 replace_replacement_point_println(rp, depth);
1611 /* replace_executionstate_println **********************************************
1613 Print execution state
1616 es...............the execution state to print
1618 *******************************************************************************/
1620 #if !defined(NDEBUG)
1621 void replace_executionstate_println(executionstate_t *es)
1629 printf("(executionstate_t *)NULL\n");
1633 printf("executionstate_t:\n");
1634 printf("\tpc = %p",(void*)es->pc);
1635 printf(" sp = %p",(void*)es->sp);
1636 printf(" pv = %p\n",(void*)es->pv);
1637 #if defined(ENABLE_DISASSEMBLER)
1638 for (i=0; i<INT_REG_CNT; ++i) {
1643 printf("%-3s = %016llx",regs[i],(unsigned long long)es->intregs[i]);
1647 for (i=0; i<FLT_REG_CNT; ++i) {
1652 printf("F%02d = %016llx",i,(unsigned long long)es->fltregs[i]);
1658 sp = (stackslot_t *) es->sp;
1663 methoddesc *md = es->code->m->parseddesc;
1664 slots = code_get_stack_frame_size(es->code);
1665 extraslots = 1 + md->memuse;
1672 printf("\tstack slots(+%d) at sp:", extraslots);
1673 for (i=0; i<slots+extraslots; ++i) {
1676 printf("M%02d%c", i, (i >= slots) ? '(' : ' ');
1677 #ifdef HAS_4BYTE_STACKSLOT
1678 printf("%08lx",(unsigned long)*sp++);
1680 printf("%016llx",(unsigned long long)*sp++);
1682 printf("%c", (i >= slots) ? ')' : ' ');
1687 printf("\tcode: %p", (void*)es->code);
1688 if (es->code != NULL) {
1689 printf(" stackframesize=%d ", es->code->stackframesize);
1690 method_print(es->code->m);
1698 #if !defined(NDEBUG)
1699 void java_value_print(s4 type, u8 value)
1701 java_objectheader *obj;
1704 printf("%016llx",(unsigned long long) value);
1706 if (type < 0 || type > TYPE_RET)
1707 printf(" <INVALID TYPE:%d>", type);
1709 printf(" %s", show_jit_type_names[type]);
1711 if (type == TYPE_ADR && value != 0) {
1712 obj = (java_objectheader *) (ptrint) value;
1714 utf_display_printable_ascii_classname(obj->vftbl->class->name);
1716 if (obj->vftbl->class == class_java_lang_String) {
1718 u = javastring_toutf((java_lang_String *)obj, false);
1719 utf_display_printable_ascii(u);
1723 else if (type == TYPE_INT || type == TYPE_LNG) {
1724 printf(" %lld", (long long) value);
1727 #endif /* !defined(NDEBUG) */
1730 #if !defined(NDEBUG)
1731 void replace_source_frame_println(sourceframe_t *frame)
1737 method_println(frame->method);
1738 printf("\tid: %d\n", frame->id);
1741 if (frame->javalocalcount) {
1742 printf("\tlocals (%d):\n",frame->javalocalcount);
1743 for (i=0; i<frame->javalocalcount; ++i) {
1744 t = frame->javalocaltype[i];
1745 if (t == TYPE_VOID) {
1746 printf("\tlocal[ %2d] = void\n",i);
1749 printf("\tlocal[%c%2d] = ",TYPECHAR(t),i);
1750 java_value_print(t, frame->javalocals[i]);
1757 if (frame->javastackdepth) {
1758 printf("\tstack (depth %d):\n",frame->javastackdepth);
1759 for (i=0; i<frame->javastackdepth; ++i) {
1760 t = frame->javastacktype[i];
1761 if (t == TYPE_VOID) {
1762 printf("\tstack[%2d] = void", i);
1765 printf("\tstack[%2d] = ",i);
1766 java_value_print(frame->javastacktype[i], frame->javastack[i]);
1773 if (frame->syncslotcount) {
1774 printf("\tsynchronization slots (%d):\n",frame->syncslotcount);
1775 for (i=0; i<frame->syncslotcount; ++i) {
1776 printf("\tslot[%2d] = ",i);
1777 #ifdef HAS_4BYTE_STACKSLOT
1778 printf("%08lx\n",(unsigned long) frame->syncslots[i]);
1780 printf("%016llx\n",(unsigned long long) frame->syncslots[i]);
1786 #endif /* !defined(NDEBUG) */
1789 /* replace_sourcestate_println *************************************************
1794 ss...............the source state to print
1796 *******************************************************************************/
1798 #if !defined(NDEBUG)
1799 void replace_sourcestate_println(sourcestate_t *ss)
1802 sourceframe_t *frame;
1805 printf("(sourcestate_t *)NULL\n");
1809 printf("sourcestate_t:\n");
1811 for (i=0, frame = ss->frames; frame != NULL; frame = frame->up, ++i) {
1812 printf(" frame %d:\n", i);
1813 replace_source_frame_println(frame);
1819 * These are local overrides for various environment variables in Emacs.
1820 * Please do not remove this and leave it at the end of the file, where
1821 * Emacs will automagically detect them.
1822 * ---------------------------------------------------------------------
1825 * indent-tabs-mode: t
1829 * vim:noexpandtab:sw=4:ts=4: