1 /* vm/jit/replace.c - on-stack replacement of methods
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Edwin Steiner
43 #include "mm/memory.h"
44 #include "toolbox/logging.h"
45 #include "vm/options.h"
46 #include "vm/stringlocal.h"
47 #include "vm/jit/abi.h"
48 #include "vm/jit/jit.h"
49 #include "vm/jit/replace.h"
50 #include "vm/jit/asmpart.h"
51 #include "vm/jit/disass.h"
52 #include "vm/jit/show.h"
53 #include "vm/jit/methodheader.h"
55 #include "native/include/java_lang_String.h"
58 /*** configuration of native stack slot size **********************************/
60 /* XXX this should be in md-abi.h files, probably */
62 #if defined(HAS_4BYTE_STACKSLOT)
63 #define SIZE_OF_STACKSLOT 4
64 #define STACK_SLOTS_PER_FLOAT 2
65 typedef u4 stackslot_t;
67 #define SIZE_OF_STACKSLOT 8
68 #define STACK_SLOTS_PER_FLOAT 1
69 typedef u8 stackslot_t;
73 /*** debugging ****************************************************************/
75 /*#define REPLACE_VERBOSE*/
77 #if !defined(NDEBUG) && defined(REPLACE_VERBOSE)
78 #define DOLOG(code) do{ if (1) { code; } } while(0)
84 /*** constants used internally ************************************************/
86 #define TOP_IS_NORMAL 0
87 #define TOP_IS_ON_STACK 1
88 #define TOP_IS_IN_ITMP1 2
91 /* replace_create_replacement_point ********************************************
93 Create a replacement point.
96 jd...............current jitdata
97 iinfo............inlining info for the current position
98 rp...............pre-allocated (uninitialized) rplpoint
99 type.............RPLPOINT_TYPE constant
100 *pra.............current rplalloc pointer
101 javalocals.......the javalocals at the current point
102 stackvars........the stack variables at the current point
103 stackdepth.......the stack depth at the current point
104 paramcount.......number of parameters at the start of stackvars
107 *rpa.............points to the next free rplalloc
109 *******************************************************************************/
111 static void replace_create_replacement_point(jitdata *jd,
112 insinfo_inline *iinfo,
129 /* there will be a replacement point at the start of this block */
131 rp->method = (iinfo) ? iinfo->method : jd->m;
132 rp->pc = NULL; /* set by codegen */
133 rp->outcode = NULL; /* set by codegen */
134 rp->callsize = 0; /* set by codegen */
139 rp->id = iptr->flags.bits >> INS_FLAG_ID_SHIFT;
141 /* XXX unify these two fields */
143 rp->parent = (iinfo) ? iinfo->rp : NULL;
145 /* store local allocation info of javalocals */
148 for (i = 0; i < rp->method->maxlocals; ++i) {
149 index = javalocals[i];
154 if (index < UNUSED) {
155 ra->regoff = (UNUSED - index) - 1;
161 ra->flags = v->flags & (INMEMORY);
162 ra->regoff = v->vv.regoff;
169 /* store allocation info of java stack vars */
171 for (i = 0; i < stackdepth; ++i) {
172 v = VAR(stackvars[i]);
173 ra->flags = v->flags & (INMEMORY);
174 ra->index = (i < paramcount) ? RPLALLOC_PARAM : RPLALLOC_STACK;
175 ra->regoff = v->vv.regoff;
180 /* total number of allocations */
182 rp->regalloccount = ra - rp->regalloc;
188 /* replace_create_replacement_points *******************************************
190 Create the replacement points for the given code.
193 jd...............current jitdata, must not have any replacement points
196 code->rplpoints.......set to the list of replacement points
197 code->rplpointcount...number of replacement points
198 code->regalloc........list of allocation info
199 code->regalloccount...total length of allocation info list
200 code->globalcount.....number of global allocations at the
201 start of code->regalloc
204 true.............everything ok
205 false............an exception has been thrown
207 *******************************************************************************/
209 bool replace_create_replacement_points(jitdata *jd)
227 insinfo_inline *iinfo;
228 insinfo_inline *calleeinfo;
230 /* get required compiler data */
235 /* assert that we wont overwrite already allocated data */
239 assert(code->rplpoints == NULL);
240 assert(code->rplpointcount == 0);
241 assert(code->regalloc == NULL);
242 assert(code->regalloccount == 0);
243 assert(code->globalcount == 0);
245 /* iterate over the basic block list to find replacement points */
252 javalocals = DMNEW(s4, jd->maxlocals);
254 for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
258 if (bptr->flags < BBFINISHED)
261 /* get info about this block */
264 iinfo = bptr->inlineinfo;
266 /* initialize javalocals at the start of this block */
268 if (bptr->javalocals)
269 MCOPY(javalocals, bptr->javalocals, s4, m->maxlocals);
271 for (i=0; i<m->maxlocals; ++i)
272 javalocals[i] = UNUSED;
274 /* create replacement points at targets of backward branches */
276 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
278 alloccount += bptr->indepth;
280 for (i=0; i<m->maxlocals; ++i)
281 if (bptr->javalocals[i] != UNUSED)
285 /* iterate over the instructions */
288 iend = iptr + bptr->icount;
290 for (; iptr != iend; ++iptr) {
292 case ICMD_INVOKESTATIC:
293 case ICMD_INVOKESPECIAL:
294 case ICMD_INVOKEVIRTUAL:
295 case ICMD_INVOKEINTERFACE:
296 INSTRUCTION_GET_METHODDESC(iptr, md);
298 for (i=0; i<m->maxlocals; ++i)
299 if (javalocals[i] != UNUSED)
301 alloccount += iptr->s1.argcount;
303 alloccount -= iinfo->throughcount;
311 /* XXX share code with stack.c */
312 j = iptr->dst.varindex;
313 i = iptr->sx.s23.s3.javaindex;
315 if (iptr->flags.bits & INS_FLAG_RETADDR)
316 javalocals[i] = iptr->sx.s23.s2.retaddrnr;
319 if (iptr->flags.bits & INS_FLAG_KILL_PREV)
320 javalocals[i-1] = UNUSED;
321 if (iptr->flags.bits & INS_FLAG_KILL_NEXT)
322 javalocals[i+1] = UNUSED;
337 case ICMD_INLINE_START:
338 iinfo = iptr->sx.s23.s3.inlineinfo;
341 for (i=0; i<m->maxlocals; ++i)
342 if (javalocals[i] != UNUSED)
344 alloccount += iinfo->stackvarscount;
345 if (iinfo->synclocal != UNUSED)
349 if (iinfo->javalocals_start)
350 MCOPY(javalocals, iinfo->javalocals_start, s4, m->maxlocals);
353 case ICMD_INLINE_END:
354 iinfo = iptr->sx.s23.s3.inlineinfo;
356 if (iinfo->javalocals_end)
357 MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
358 iinfo = iinfo->parent;
364 /* if no points were found, there's nothing to do */
369 /* allocate replacement point array and allocation array */
371 rplpoints = MNEW(rplpoint, count);
372 regalloc = MNEW(rplalloc, alloccount);
375 /* initialize replacement point structs */
379 /* XXX try to share code with the counting loop! */
381 for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
384 if (bptr->flags < BBFINISHED)
387 /* get info about this block */
390 iinfo = bptr->inlineinfo;
392 /* initialize javalocals at the start of this block */
394 if (bptr->javalocals)
395 MCOPY(javalocals, bptr->javalocals, s4, m->maxlocals);
397 for (i=0; i<m->maxlocals; ++i)
398 javalocals[i] = UNUSED;
400 /* create replacement points at targets of backward branches */
402 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
404 replace_create_replacement_point(jd, iinfo, rp++,
405 bptr->type, bptr->iinstr, &ra,
406 bptr->javalocals, bptr->invars, bptr->indepth, 0);
409 /* iterate over the instructions */
412 iend = iptr + bptr->icount;
414 for (; iptr != iend; ++iptr) {
416 case ICMD_INVOKESTATIC:
417 case ICMD_INVOKESPECIAL:
418 case ICMD_INVOKEVIRTUAL:
419 case ICMD_INVOKEINTERFACE:
420 INSTRUCTION_GET_METHODDESC(iptr, md);
422 i = (iinfo) ? iinfo->throughcount : 0;
423 replace_create_replacement_point(jd, iinfo, rp++,
424 RPLPOINT_TYPE_CALL, iptr, &ra,
425 javalocals, iptr->sx.s23.s2.args,
426 iptr->s1.argcount - i,
435 /* XXX share code with stack.c */
436 j = iptr->dst.varindex;
437 i = iptr->sx.s23.s3.javaindex;
439 if (iptr->flags.bits & INS_FLAG_RETADDR)
440 javalocals[i] = iptr->sx.s23.s2.retaddrnr;
443 if (iptr->flags.bits & INS_FLAG_KILL_PREV)
444 javalocals[i-1] = UNUSED;
445 if (iptr->flags.bits & INS_FLAG_KILL_NEXT)
446 javalocals[i+1] = UNUSED;
455 replace_create_replacement_point(jd, iinfo, rp++,
456 RPLPOINT_TYPE_RETURN, iptr, &ra,
457 NULL, &(iptr->s1.varindex), 1, 0);
461 replace_create_replacement_point(jd, iinfo, rp++,
462 RPLPOINT_TYPE_RETURN, iptr, &ra,
466 case ICMD_INLINE_START:
467 calleeinfo = iptr->sx.s23.s3.inlineinfo;
470 replace_create_replacement_point(jd, iinfo, rp++,
471 RPLPOINT_TYPE_INLINE, iptr, &ra,
473 calleeinfo->stackvars, calleeinfo->stackvarscount,
474 calleeinfo->paramcount);
476 if (calleeinfo->synclocal != UNUSED) {
477 ra->index = RPLALLOC_SYNC;
478 ra->regoff = jd->var[calleeinfo->synclocal].vv.regoff;
479 ra->flags = jd->var[calleeinfo->synclocal].flags & INMEMORY;
482 rp[-1].regalloccount++;
487 if (iinfo->javalocals_start)
488 MCOPY(javalocals, iinfo->javalocals_start, s4, m->maxlocals);
491 case ICMD_INLINE_END:
492 iinfo = iptr->sx.s23.s3.inlineinfo;
494 if (iinfo->javalocals_end)
495 MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
496 iinfo = iinfo->parent;
502 /* store the data in the codeinfo */
504 code->rplpoints = rplpoints;
505 code->rplpointcount = count;
506 code->regalloc = regalloc;
507 code->regalloccount = alloccount;
508 code->globalcount = 0;
509 code->savedintcount = INT_SAV_CNT - rd->savintreguse;
510 code->savedfltcount = FLT_SAV_CNT - rd->savfltreguse;
511 code->memuse = rd->memuse;
512 code->stackframesize = jd->cd->stackframesize;
514 /* everything alright */
520 /* replace_free_replacement_points *********************************************
522 Free memory used by replacement points.
525 code.............codeinfo whose replacement points should be freed.
527 *******************************************************************************/
529 void replace_free_replacement_points(codeinfo *code)
534 MFREE(code->rplpoints,rplpoint,code->rplpointcount);
537 MFREE(code->regalloc,rplalloc,code->regalloccount);
539 code->rplpoints = NULL;
540 code->rplpointcount = 0;
541 code->regalloc = NULL;
542 code->regalloccount = 0;
543 code->globalcount = 0;
547 /* replace_activate_replacement_point ******************************************
549 Activate a replacement point. When this function returns, the
550 replacement point is "armed", that is each thread reaching this point
551 will be replace to `target`.
554 rp...............replacement point to activate
555 target...........target of replacement
557 *******************************************************************************/
559 void replace_activate_replacement_point(rplpoint *rp,rplpoint *target)
561 assert(rp->target == NULL);
563 DOLOG( printf("activate replacement point:\n");
564 replace_replacement_point_println(rp, 1); fflush(stdout); );
568 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
569 md_patch_replacement_point(rp);
574 /* replace_deactivate_replacement_point ****************************************
576 Deactivate a replacement point. When this function returns, the
577 replacement point is "un-armed", that is a each thread reaching this point
578 will just continue normally.
581 rp...............replacement point to deactivate
583 *******************************************************************************/
585 void replace_deactivate_replacement_point(rplpoint *rp)
589 DOLOG( printf("deactivate replacement point:\n");
590 replace_replacement_point_println(rp, 1); fflush(stdout); );
594 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
595 md_patch_replacement_point(rp);
600 /* replace_read_value **********************************************************
602 Read a value with the given allocation from the execution state.
605 es...............execution state
606 sp...............stack pointer of the execution state (XXX eliminate?)
607 ra...............allocation
608 javaval..........where to put the value
611 *javaval.........the value
613 *******************************************************************************/
615 static void replace_read_value(executionstate_t *es,
620 if (ra->flags & INMEMORY) {
621 /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
622 #ifdef HAS_4BYTE_STACKSLOT
623 if (IS_2_WORD_TYPE(ra->type)) {
624 *javaval = *(u8*)(sp + ra->regoff);
628 *javaval = sp[ra->regoff];
629 #ifdef HAS_4BYTE_STACKSLOT
634 /* allocated register */
635 if (IS_FLT_DBL_TYPE(ra->type)) {
636 *javaval = es->fltregs[ra->regoff];
639 *javaval = es->intregs[ra->regoff];
645 /* replace_write_value *********************************************************
647 Write a value to the given allocation in the execution state.
650 es...............execution state
651 sp...............stack pointer of the execution state (XXX eliminate?)
652 ra...............allocation
653 *javaval.........the value
655 *******************************************************************************/
657 static void replace_write_value(executionstate_t *es,
662 if (ra->flags & INMEMORY) {
663 /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
664 #ifdef HAS_4BYTE_STACKSLOT
665 if (IS_2_WORD_TYPE(ra->type)) {
666 *(u8*)(sp + ra->regoff) = *javaval;
670 sp[ra->regoff] = *javaval;
671 #ifdef HAS_4BYTE_STACKSLOT
676 /* allocated register */
677 if (IS_FLT_DBL_TYPE(ra->type)) {
678 es->fltregs[ra->regoff] = *javaval;
681 es->intregs[ra->regoff] = *javaval;
687 /* replace_read_executionstate *************************************************
689 Read the given executions state and translate it to a source frame.
692 rp...............replacement point at which `es` was taken
693 es...............execution state
694 ss...............where to put the source state
697 *ss..............the source state derived from the execution state
699 *******************************************************************************/
701 static void replace_read_executionstate(rplpoint *rp,
702 executionstate_t *es,
711 sourceframe_t *frame;
718 topslot = TOP_IS_NORMAL;
722 sp = (stackslot_t *) es->sp;
724 /* on some architectures the returnAddress is passed on the stack by JSR */
726 #if defined(__I386__) || defined(__X86_64__)
727 if (rp->type == BBTYPE_SBR) {
729 topslot = TOP_IS_ON_STACK; /* XXX */
733 /* in some cases the top stack slot is passed in REG_ITMP1 */
735 if ( (rp->type == BBTYPE_EXH)
736 #if defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)
737 || (rp->type == BBTYPE_SBR) /* XXX */
741 topslot = TOP_IS_IN_ITMP1;
744 /* calculate base stack pointer */
746 basesp = sp + code_get_stack_frame_size(code);
748 /* create the source frame */
750 frame = DNEW(sourceframe_t);
751 frame->up = ss->frames;
752 frame->method = rp->method;
754 frame->syncslotcount = 0;
755 frame->syncslots = NULL;
759 /* read local variables */
761 count = m->maxlocals;
762 frame->javalocalcount = count;
763 frame->javalocals = DMNEW(u8, count);
764 frame->javalocaltype = DMNEW(u1, count);
767 /* mark values as undefined */
768 for (i=0; i<count; ++i) {
769 frame->javalocals[i] = (u8) 0x00dead0000dead00ULL;
770 frame->javalocaltype[i] = TYPE_VOID;
773 /* some entries in the intregs array are not meaningful */
774 /*es->intregs[REG_ITMP3] = (u8) 0x11dead1111dead11ULL;*/
775 es->intregs[REG_SP ] = (u8) 0x11dead1111dead11ULL;
777 es->intregs[REG_PV ] = (u8) 0x11dead1111dead11ULL;
779 #endif /* !defined(NDEBUG) */
781 /* read javalocals */
783 count = rp->regalloccount;
786 while (count && (i = ra->index) >= 0) {
787 assert(i < m->maxlocals);
788 frame->javalocaltype[i] = ra->type;
789 if (ra->type == TYPE_RET)
790 frame->javalocals[i] = ra->regoff;
792 replace_read_value(es, sp, ra, frame->javalocals + i);
797 /* read stack slots */
799 frame->javastackdepth = count;
800 frame->javastack = DMNEW(u8, count);
801 frame->javastacktype = DMNEW(u1, count);
804 /* mark values as undefined */
805 for (i=0; i<count; ++i) {
806 frame->javastack[i] = (u8) 0x00dead0000dead00ULL;
807 frame->javastacktype[i] = TYPE_VOID;
809 #endif /* !defined(NDEBUG) */
813 /* the first stack slot is special in SBR and EXH blocks */
815 if (topslot == TOP_IS_ON_STACK) {
818 assert(ra->index == RPLALLOC_STACK);
819 frame->javastack[i] = sp[-1];
820 frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
825 else if (topslot == TOP_IS_IN_ITMP1) {
828 assert(ra->index == RPLALLOC_STACK);
829 frame->javastack[i] = es->intregs[REG_ITMP1];
830 frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
836 /* read remaining stack slots */
838 for (; count--; ra++) {
839 if (ra->index == RPLALLOC_SYNC) {
840 assert(rp->type == RPLPOINT_TYPE_INLINE);
842 /* only read synchronization slots when traversing an inline point */
845 sourceframe_t *calleeframe = frame->up;
847 assert(calleeframe->syncslotcount == 0);
848 assert(calleeframe->syncslots == NULL);
850 calleeframe->syncslotcount = 1;
851 calleeframe->syncslots = DMNEW(u8, 1);
852 replace_read_value(es,sp,ra,calleeframe->syncslots);
855 frame->javastackdepth--;
859 assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
861 /* do not read parameters of calls down the call chain */
863 if (!topframe && ra->index == RPLALLOC_PARAM) {
864 frame->javastackdepth--;
867 replace_read_value(es,sp,ra,frame->javastack + i);
868 frame->javastacktype[i] = ra->type;
875 /* replace_write_executionstate ************************************************
877 Translate the given source state into an execution state.
880 rp...............replacement point for which execution state should be
882 es...............where to put the execution state
883 ss...............the given source state
886 *es..............the execution state derived from the source state
888 *******************************************************************************/
890 static void replace_write_executionstate(rplpoint *rp,
891 executionstate_t *es,
900 sourceframe_t *frame;
907 topslot = TOP_IS_NORMAL;
909 /* pop a source frame */
913 ss->frames = frame->up;
915 /* calculate stack pointer */
917 sp = (stackslot_t *) es->sp;
919 basesp = sp + code_get_stack_frame_size(code);
921 /* on some architectures the returnAddress is passed on the stack by JSR */
923 #if defined(__I386__) || defined(__X86_64__)
924 if (rp->type == BBTYPE_SBR) {
925 topslot = TOP_IS_ON_STACK; /* XXX */
929 /* in some cases the top stack slot is passed in REG_ITMP1 */
931 if ( (rp->type == BBTYPE_EXH)
932 #if defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)
933 || (rp->type == BBTYPE_SBR) /* XXX */
937 topslot = TOP_IS_IN_ITMP1;
940 /* write javalocals */
943 count = rp->regalloccount;
945 while (count && (i = ra->index) >= 0) {
946 assert(i < m->maxlocals);
947 assert(i < frame->javalocalcount);
948 assert(ra->type == frame->javalocaltype[i]);
949 if (ra->type == TYPE_RET) {
950 /* XXX assert that it matches this rplpoint */
953 replace_write_value(es, sp, ra, frame->javalocals + i);
958 /* write stack slots */
962 /* the first stack slot is special in SBR and EXH blocks */
964 if (topslot == TOP_IS_ON_STACK) {
967 assert(ra->index == RPLALLOC_STACK);
968 assert(i < frame->javastackdepth);
969 assert(frame->javastacktype[i] == TYPE_ADR);
970 sp[-1] = frame->javastack[i];
975 else if (topslot == TOP_IS_IN_ITMP1) {
978 assert(ra->index == RPLALLOC_STACK);
979 assert(i < frame->javastackdepth);
980 assert(frame->javastacktype[i] == TYPE_ADR);
981 es->intregs[REG_ITMP1] = frame->javastack[i];
987 /* write remaining stack slots */
989 for (; count--; ra++) {
990 if (ra->index == RPLALLOC_SYNC) {
991 assert(rp->type == RPLPOINT_TYPE_INLINE);
993 /* only write synchronization slots when traversing an inline point */
996 assert(frame->syncslotcount == 1); /* XXX need to understand more cases */
997 assert(frame->syncslots != NULL);
999 replace_write_value(es,sp,ra,frame->syncslots);
1004 assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
1006 /* do not write parameters of calls down the call chain */
1008 if (!topframe && ra->index == RPLALLOC_PARAM) {
1012 assert(i < frame->javastackdepth);
1013 assert(ra->type == frame->javastacktype[i]);
1014 replace_write_value(es,sp,ra,frame->javastack + i);
1025 /* replace_pop_activation_record ***********************************************
1027 Peel a stack frame from the execution state.
1029 *** This function imitates the effects of the method epilog ***
1030 *** and returning from the method call. ***
1033 es...............execution state
1034 frame............source frame, receives synchronization slots
1037 *es..............the execution state after popping the stack frame
1039 *******************************************************************************/
1041 bool replace_pop_activation_record(executionstate_t *es,
1042 sourceframe_t *frame)
1050 stackslot_t *basesp;
1056 /* read the return address */
1058 ra = md_stacktrace_get_returnaddress(es->sp,
1059 SIZE_OF_STACKSLOT * es->code->stackframesize);
1061 DOLOG( printf("return address: %p\n", (void*)ra); );
1063 /* find the new codeinfo */
1065 pv = md_codegen_get_pv_from_pc(ra);
1067 DOLOG( printf("PV = %p\n", (void*) pv); );
1072 code = *(codeinfo **)(pv + CodeinfoPointer);
1074 DOLOG( printf("CODE = %p\n", (void*) code); );
1079 /* calculate the base of the stack frame */
1081 sp = (stackslot_t *) es->sp;
1082 basesp = sp + es->code->stackframesize;
1084 /* read slots used for synchronization */
1086 assert(frame->syncslotcount == 0);
1087 assert(frame->syncslots == NULL);
1088 count = code_get_sync_slot_count(es->code);
1089 frame->syncslotcount = count;
1090 frame->syncslots = DMNEW(u8, count);
1091 for (i=0; i<count; ++i) {
1092 frame->syncslots[i] = sp[es->code->memuse + i];
1095 /* restore saved int registers */
1098 for (i=0; i<es->code->savedintcount; ++i) {
1099 while (nregdescint[--reg] != REG_SAV)
1101 es->intregs[reg] = *--basesp;
1104 /* restore saved flt registers */
1108 for (i=0; i<es->code->savedfltcount; ++i) {
1109 while (nregdescfloat[--reg] != REG_SAV)
1111 basesp -= STACK_SLOTS_PER_FLOAT;
1112 es->fltregs[reg] = *(u8*)basesp;
1115 /* Set the new pc. Subtract one so we do not hit the replacement point */
1116 /* of the instruction following the call, if there is one. */
1120 /* adjust the stackpointer */
1122 es->sp += SIZE_OF_STACKSLOT * es->code->stackframesize;
1123 es->sp += SIZE_OF_STACKSLOT; /* skip return address */
1128 #if !defined(NDEBUG)
1130 for (i=0; i<INT_REG_CNT; ++i)
1131 if (nregdescint[i] != REG_SAV)
1132 es->intregs[i] = 0x33dead3333dead33ULL;
1133 for (i=0; i<FLT_REG_CNT; ++i)
1134 if (nregdescfloat[i] != REG_SAV)
1135 es->fltregs[i] = 0x33dead3333dead33ULL;
1136 #endif /* !defined(NDEBUG) */
1142 /* replace_push_activation_record **********************************************
1144 Push a stack frame onto the execution state.
1146 *** This function imitates the effects of a call and the ***
1147 *** method prolog of the callee. ***
1150 es...............execution state
1151 rpcall...........the replacement point at the call site
1152 calleecode.......the codeinfo of the callee
1153 frame............source frame, only the synch. slots are used
1156 *es..............the execution state after pushing the stack frame
1158 *******************************************************************************/
1160 void replace_push_activation_record(executionstate_t *es,
1162 codeinfo *calleecode,
1163 sourceframe_t *frame)
1168 stackslot_t *basesp;
1172 assert(rpcall && rpcall->type == RPLPOINT_TYPE_CALL);
1176 /* write the return address */
1178 es->sp -= SIZE_OF_STACKSLOT;
1180 DOLOG( printf("writing return address %p to %p\n",
1181 (void*) (rpcall->pc + rpcall->callsize),
1184 *((stackslot_t *)es->sp) = (stackslot_t) (rpcall->pc + rpcall->callsize);
1186 /* we move into a new code unit */
1188 es->code = calleecode;
1190 /* set the new pc XXX not needed */
1192 es->pc = es->code->entrypoint;
1194 /* build the stackframe */
1196 DOLOG( printf("building stackframe of %d words at %p\n",
1197 es->code->stackframesize, (void*)es->sp); );
1199 sp = (stackslot_t *) es->sp;
1202 sp -= es->code->stackframesize;
1205 /* in debug mode, invalidate stack frame first */
1207 #if !defined(NDEBUG)
1208 for (i=0; i<(basesp - sp); ++i) {
1209 sp[i] = 0xdeaddeadU;
1213 /* save int registers */
1216 for (i=0; i<es->code->savedintcount; ++i) {
1217 while (nregdescint[--reg] != REG_SAV)
1219 *--basesp = es->intregs[reg];
1221 #if !defined(NDEBUG)
1222 es->intregs[reg] = 0x44dead4444dead44ULL;
1226 /* save flt registers */
1230 for (i=0; i<es->code->savedfltcount; ++i) {
1231 while (nregdescfloat[--reg] != REG_SAV)
1233 basesp -= STACK_SLOTS_PER_FLOAT;
1234 *(u8*)basesp = es->fltregs[reg];
1236 #if !defined(NDEBUG)
1237 es->fltregs[reg] = 0x44dead4444dead44ULL;
1241 /* write slots used for synchronization */
1243 count = code_get_sync_slot_count(es->code);
1244 assert(count == frame->syncslotcount);
1245 for (i=0; i<count; ++i) {
1246 sp[es->code->memuse + i] = frame->syncslots[i];
1251 es->pv = es->code->entrypoint;
1255 /* replace_find_replacement_point **********************************************
1257 Find the replacement point in the given code corresponding to the
1258 position given in the source frame.
1261 code.............the codeinfo in which to search the rplpoint
1262 ss...............the source state defining the position to look for
1265 the replacement point
1267 *******************************************************************************/
1269 rplpoint * replace_find_replacement_point(codeinfo *code, sourcestate_t *ss)
1271 sourceframe_t *frame;
1283 DOLOG( printf("searching replacement point for:\n");
1284 replace_source_frame_println(frame); );
1288 DOLOG( printf("code = %p\n", (void*)code); );
1290 rp = code->rplpoints;
1291 i = code->rplpointcount;
1293 if (rp->id == frame->id && rp->method == frame->method) {
1294 /* check if returnAddresses match */
1296 for (j = rp->regalloccount; j--; ++ra) {
1297 if (ra->type == TYPE_RET) {
1298 assert(ra->index >= 0 && ra->index < frame->javalocalcount);
1299 if (frame->javalocals[ra->index] != ra->regoff)
1312 return NULL; /* NOT REACHED */
1316 /* replace_me ******************************************************************
1318 This function is called by asm_replacement_out when a thread reaches
1319 a replacement point. `replace_me` must map the execution state to the
1320 target replacement point and let execution continue there.
1322 This function never returns!
1325 rp...............replacement point that has been reached
1326 es...............execution state read by asm_replacement_out
1328 *******************************************************************************/
1330 void replace_me(rplpoint *rp, executionstate_t *es)
1335 rplpoint *candidate;
1339 es->code = rp->code;
1341 /* mark start of dump memory area */
1343 dumpsize = dump_size();
1345 /* fetch the target of the replacement */
1347 target = rp->target;
1349 /* XXX DEBUG turn off self-replacement */
1351 replace_deactivate_replacement_point(rp);
1353 DOLOG( printf("replace_me(%p,%p)\n",(void*)rp,(void*)es); fflush(stdout);
1354 replace_replacement_point_println(rp, 1);
1355 replace_executionstate_println(es); );
1357 /* read execution state of old code */
1365 DOLOG( printf("recovering source state for:\n");
1366 replace_replacement_point_println(candidate, 1); );
1368 replace_read_executionstate(candidate, es, &ss, ss.frames == NULL);
1370 if (candidate->parent) {
1371 DOLOG( printf("INLINED!\n"); );
1372 candidate = candidate->parent;
1373 assert(candidate->type == RPLPOINT_TYPE_INLINE);
1376 DOLOG( printf("UNWIND\n"); );
1377 if (!replace_pop_activation_record(es, ss.frames)) {
1378 DOLOG( printf("BREAKING\n"); );
1381 DOLOG( replace_executionstate_println(es); );
1383 rp = es->code->rplpoints;
1384 for (i=0; i<es->code->rplpointcount; ++i, ++rp)
1385 if (rp->pc <= es->pc)
1388 DOLOG( printf("NO CANDIDATE!\n"); );
1390 DOLOG( printf("found replacement point.\n");
1391 replace_replacement_point_println(candidate, 1); );
1392 assert(candidate->type == RPLPOINT_TYPE_CALL);
1395 } while (candidate);
1397 DOLOG( replace_sourcestate_println(&ss); );
1399 /* write execution state of new code */
1401 DOLOG( replace_executionstate_println(es); );
1405 /* XXX get new code */
1409 candidate = replace_find_replacement_point(code, &ss);
1411 DOLOG( printf("creating execution state for:\n");
1412 replace_replacement_point_println(candidate, 1); );
1414 replace_write_executionstate(candidate, es, &ss, ss.frames->up == NULL);
1415 if (ss.frames == NULL)
1417 DOLOG( replace_executionstate_println(es); );
1419 if (candidate->type == RPLPOINT_TYPE_CALL) {
1420 jit_recompile(ss.frames->method);
1421 code = ss.frames->method->code;
1423 DOLOG( printf("pushing activation record for:\n");
1424 replace_replacement_point_println(candidate, 1); );
1425 replace_push_activation_record(es, candidate, code, ss.frames);
1427 DOLOG( replace_executionstate_println(es); );
1430 DOLOG( replace_executionstate_println(es); );
1432 /* release dump area */
1434 dump_release(dumpsize);
1436 /* enter new code */
1438 DOLOG( printf("JUMPING IN!\n"); fflush(stdout); );
1440 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
1441 asm_replacement_in(es);
1443 abort(); /* NOT REACHED */
1447 /* replace_replacement_point_println *******************************************
1449 Print replacement point info.
1452 rp...............the replacement point to print
1454 *******************************************************************************/
1456 #if !defined(NDEBUG)
1458 #define TYPECHAR(t) (((t) >= 0 && (t) <= TYPE_RET) ? show_jit_type_letters[t] : '?')
1460 static char *replace_type_str[] = {
1469 void replace_replacement_point_println(rplpoint *rp, int depth)
1475 printf("(rplpoint *)NULL\n");
1479 for (j=0; j<depth; ++j)
1482 printf("rplpoint (id %d) %p pc:%p+%d out:%p target:%p mcode:%016llx type:%s flags:%01x parent:%p\n",
1483 rp->id, (void*)rp,rp->pc,rp->callsize,rp->outcode,(void*)rp->target,
1484 (unsigned long long)rp->mcode,replace_type_str[rp->type],rp->flags,
1486 for (j=0; j<depth; ++j)
1488 printf("ra:%d = [", rp->regalloccount);
1490 for (j=0; j<rp->regalloccount; ++j) {
1493 index = rp->regalloc[j].index;
1495 case RPLALLOC_STACK: printf("S"); break;
1496 case RPLALLOC_PARAM: printf("P"); break;
1497 case RPLALLOC_SYNC : printf("Y"); break;
1498 default: printf("%d", index);
1500 printf(":%1c:", TYPECHAR(rp->regalloc[j].type));
1501 if (rp->regalloc[j].type == TYPE_RET) {
1502 printf("ret(L%03d)", rp->regalloc[j].regoff);
1505 show_allocation(rp->regalloc[j].type, rp->regalloc[j].flags, rp->regalloc[j].regoff);
1510 for (j=0; j<depth; ++j)
1513 method_print(rp->method);
1520 /* replace_show_replacement_points *********************************************
1522 Print replacement point info.
1525 code.............codeinfo whose replacement points should be printed.
1527 *******************************************************************************/
1529 #if !defined(NDEBUG)
1530 void replace_show_replacement_points(codeinfo *code)
1538 printf("(codeinfo *)NULL\n");
1542 printf("\treplacement points: %d\n",code->rplpointcount);
1544 printf("\ttotal allocations : %d\n",code->regalloccount);
1545 printf("\tsaved int regs : %d\n",code->savedintcount);
1546 printf("\tsaved flt regs : %d\n",code->savedfltcount);
1547 printf("\tmemuse : %d\n",code->memuse);
1551 for (i=0; i<code->rplpointcount; ++i) {
1552 rp = code->rplpoints + i;
1554 assert(rp->code == code);
1557 parent = rp->parent;
1560 parent = parent->parent;
1562 replace_replacement_point_println(rp, depth);
1568 /* replace_executionstate_println **********************************************
1570 Print execution state
1573 es...............the execution state to print
1575 *******************************************************************************/
1577 #if !defined(NDEBUG)
1578 void replace_executionstate_println(executionstate_t *es)
1586 printf("(executionstate_t *)NULL\n");
1590 printf("executionstate_t:\n");
1591 printf("\tpc = %p",(void*)es->pc);
1592 printf(" sp = %p",(void*)es->sp);
1593 printf(" pv = %p\n",(void*)es->pv);
1594 #if defined(ENABLE_DISASSEMBLER)
1595 for (i=0; i<INT_REG_CNT; ++i) {
1600 printf("%-3s = %016llx",regs[i],(unsigned long long)es->intregs[i]);
1604 for (i=0; i<FLT_REG_CNT; ++i) {
1609 printf("F%02d = %016llx",i,(unsigned long long)es->fltregs[i]);
1615 sp = (stackslot_t *) es->sp;
1620 methoddesc *md = es->code->m->parseddesc;
1621 slots = code_get_stack_frame_size(es->code);
1622 extraslots = 1 + md->memuse;
1629 printf("\tstack slots(+%d) at sp:", extraslots);
1630 for (i=0; i<slots+extraslots; ++i) {
1633 printf("M%02d%c", i, (i >= slots) ? '(' : ' ');
1634 #ifdef HAS_4BYTE_STACKSLOT
1635 printf("%08lx",(unsigned long)*sp++);
1637 printf("%016llx",(unsigned long long)*sp++);
1639 printf("%c", (i >= slots) ? ')' : ' ');
1644 printf("\tcode: %p", (void*)es->code);
1645 if (es->code != NULL) {
1646 printf(" stackframesize=%d ", es->code->stackframesize);
1647 method_print(es->code->m);
1655 #if !defined(NDEBUG)
1656 void java_value_print(s4 type, u8 value)
1658 java_objectheader *obj;
1661 printf("%016llx",(unsigned long long) value);
1663 if (type < 0 || type > TYPE_RET)
1664 printf(" <INVALID TYPE:%d>", type);
1666 printf(" %s", show_jit_type_names[type]);
1668 if (type == TYPE_ADR && value != 0) {
1669 obj = (java_objectheader *) (ptrint) value;
1671 utf_display_printable_ascii_classname(obj->vftbl->class->name);
1673 if (obj->vftbl->class == class_java_lang_String) {
1675 u = javastring_toutf((java_lang_String *)obj, false);
1676 utf_display_printable_ascii(u);
1680 else if (type == TYPE_INT || type == TYPE_LNG) {
1681 printf(" %lld", (long long) value);
1684 #endif /* !defined(NDEBUG) */
1687 #if !defined(NDEBUG)
1688 void replace_source_frame_println(sourceframe_t *frame)
1694 method_println(frame->method);
1695 printf("\tid: %d\n", frame->id);
1698 if (frame->javalocalcount) {
1699 printf("\tlocals (%d):\n",frame->javalocalcount);
1700 for (i=0; i<frame->javalocalcount; ++i) {
1701 t = frame->javalocaltype[i];
1702 if (t == TYPE_VOID) {
1703 printf("\tlocal[ %2d] = void\n",i);
1706 printf("\tlocal[%c%2d] = ",TYPECHAR(t),i);
1707 java_value_print(t, frame->javalocals[i]);
1714 if (frame->javastackdepth) {
1715 printf("\tstack (depth %d):\n",frame->javastackdepth);
1716 for (i=0; i<frame->javastackdepth; ++i) {
1717 printf("\tstack[%2d] = ",i);
1718 java_value_print(frame->javastacktype[i], frame->javastack[i]);
1724 if (frame->syncslotcount) {
1725 printf("\tsynchronization slots (%d):\n",frame->syncslotcount);
1726 for (i=0; i<frame->syncslotcount; ++i) {
1727 printf("\tslot[%2d] = ",i);
1728 #ifdef HAS_4BYTE_STACKSLOT
1729 printf("%08lx\n",(unsigned long) frame->syncslots[i]);
1731 printf("%016llx\n",(unsigned long long) frame->syncslots[i]);
1737 #endif /* !defined(NDEBUG) */
1740 /* replace_sourcestate_println *************************************************
1745 ss...............the source state to print
1747 *******************************************************************************/
1749 #if !defined(NDEBUG)
1750 void replace_sourcestate_println(sourcestate_t *ss)
1753 sourceframe_t *frame;
1756 printf("(sourcestate_t *)NULL\n");
1760 printf("sourcestate_t:\n");
1762 for (i=0, frame = ss->frames; frame != NULL; frame = frame->up, ++i) {
1763 printf(" frame %d:\n", i);
1764 replace_source_frame_println(frame);
1770 * These are local overrides for various environment variables in Emacs.
1771 * Please do not remove this and leave it at the end of the file, where
1772 * Emacs will automagically detect them.
1773 * ---------------------------------------------------------------------
1776 * indent-tabs-mode: t
1780 * vim:noexpandtab:sw=4:ts=4: