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 /*** constants used internally ************************************************/
75 #define TOP_IS_NORMAL 0
76 #define TOP_IS_ON_STACK 1
77 #define TOP_IS_IN_ITMP1 2
80 /* replace_create_replacement_point ********************************************
82 Create a replacement point.
85 jd...............current jitdata
86 iinfo............inlining info for the current position
87 rp...............pre-allocated (uninitialized) rplpoint
88 type.............RPLPOINT_TYPE constant
89 *pra.............current rplalloc pointer
90 javalocals.......the javalocals at the current point
91 stackvars........the stack variables at the current point
92 stackdepth.......the stack depth at the current point
95 *rpa.............points to the next free rplalloc
97 *******************************************************************************/
99 static void replace_create_replacement_point(jitdata *jd,
100 insinfo_inline *iinfo,
113 static s4 fake_id = 0;
117 /* there will be a replacement point at the start of this block */
119 rp->method = (iinfo) ? iinfo->method : jd->m;
120 rp->pc = NULL; /* set by codegen */
121 rp->outcode = NULL; /* set by codegen */
122 rp->callsize = 0; /* set by codegen */
127 rp->id = ++fake_id; /* XXX need a real invariant id */
129 /* XXX unify these two fields */
131 rp->parent = (iinfo) ? iinfo->rp : NULL;
133 /* store local allocation info of javalocals */
136 for (i = 0; i < rp->method->maxlocals; ++i) {
137 index = javalocals[i];
142 ra->flags = v->flags & (INMEMORY);
144 ra->regoff = v->vv.regoff;
150 /* store allocation info of java stack vars */
152 for (i = 0; i < stackdepth; ++i) {
153 v = VAR(stackvars[i]);
154 ra->flags = v->flags & (INMEMORY);
156 ra->regoff = v->vv.regoff;
161 /* total number of allocations */
163 rp->regalloccount = ra - rp->regalloc;
169 /* replace_create_replacement_points *******************************************
171 Create the replacement points for the given code.
174 jd...............current jitdata, must not have any replacement points
177 code->rplpoints.......set to the list of replacement points
178 code->rplpointcount...number of replacement points
179 code->regalloc........list of allocation info
180 code->regalloccount...total length of allocation info list
181 code->globalcount.....number of global allocations at the
182 start of code->regalloc
185 true.............everything ok
186 false............an exception has been thrown
188 *******************************************************************************/
190 bool replace_create_replacement_points(jitdata *jd)
208 insinfo_inline *iinfo;
209 insinfo_inline *calleeinfo;
211 /* get required compiler data */
216 /* assert that we wont overwrite already allocated data */
220 assert(code->rplpoints == NULL);
221 assert(code->rplpointcount == 0);
222 assert(code->regalloc == NULL);
223 assert(code->regalloccount == 0);
224 assert(code->globalcount == 0);
226 /* iterate over the basic block list to find replacement points */
233 javalocals = DMNEW(s4, jd->maxlocals);
235 for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
239 if (bptr->flags < BBFINISHED)
242 /* get info about this block */
245 iinfo = bptr->inlineinfo;
247 /* initialize javalocals at the start of this block */
249 if (bptr->javalocals)
250 MCOPY(javalocals, bptr->javalocals, s4, m->maxlocals);
252 for (i=0; i<m->maxlocals; ++i)
253 javalocals[i] = UNUSED;
255 /* create replacement points at targets of backward branches */
257 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
259 alloccount += bptr->indepth;
261 for (i=0; i<m->maxlocals; ++i)
262 if (bptr->javalocals[i] != UNUSED)
266 /* iterate over the instructions */
269 iend = iptr + bptr->icount;
271 for (; iptr != iend; ++iptr) {
273 case ICMD_INVOKESTATIC:
274 case ICMD_INVOKESPECIAL:
275 case ICMD_INVOKEVIRTUAL:
276 case ICMD_INVOKEINTERFACE:
277 INSTRUCTION_GET_METHODDESC(iptr, md);
279 for (i=0; i<m->maxlocals; ++i)
280 if (javalocals[i] != UNUSED)
282 alloccount += iptr->s1.argcount - md->paramcount;
284 alloccount -= iinfo->throughcount;
292 /* XXX share code with stack.c */
293 j = iptr->dst.varindex;
294 i = iptr->sx.s23.s3.javaindex;
296 if (iptr->flags.bits & INS_FLAG_RETADDR)
297 javalocals[i] = UNUSED;
300 if (iptr->flags.bits & INS_FLAG_KILL_PREV)
301 javalocals[i-1] = UNUSED;
302 if (iptr->flags.bits & INS_FLAG_KILL_NEXT)
303 javalocals[i+1] = UNUSED;
318 case ICMD_INLINE_START:
319 iinfo = iptr->sx.s23.s3.inlineinfo;
322 for (i=0; i<m->maxlocals; ++i)
323 if (javalocals[i] != UNUSED)
325 alloccount += iinfo->stackvarscount;
328 if (iinfo->javalocals_start)
329 MCOPY(javalocals, iinfo->javalocals_start, s4, m->maxlocals);
332 case ICMD_INLINE_END:
333 iinfo = iptr->sx.s23.s3.inlineinfo;
335 if (iinfo->javalocals_end)
336 MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
337 iinfo = iinfo->parent;
343 /* if no points were found, there's nothing to do */
348 /* allocate replacement point array and allocation array */
350 rplpoints = MNEW(rplpoint, count);
351 regalloc = MNEW(rplalloc, alloccount);
354 /* initialize replacement point structs */
358 /* XXX try to share code with the counting loop! */
360 for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
363 if (bptr->flags < BBFINISHED)
366 /* get info about this block */
369 iinfo = bptr->inlineinfo;
371 /* initialize javalocals at the start of this block */
373 if (bptr->javalocals)
374 MCOPY(javalocals, bptr->javalocals, s4, m->maxlocals);
376 for (i=0; i<m->maxlocals; ++i)
377 javalocals[i] = UNUSED;
379 /* create replacement points at targets of backward branches */
381 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
383 replace_create_replacement_point(jd, iinfo, rp++,
385 bptr->javalocals, bptr->invars, bptr->indepth);
388 /* iterate over the instructions */
391 iend = iptr + bptr->icount;
393 for (; iptr != iend; ++iptr) {
395 case ICMD_INVOKESTATIC:
396 case ICMD_INVOKESPECIAL:
397 case ICMD_INVOKEVIRTUAL:
398 case ICMD_INVOKEINTERFACE:
399 INSTRUCTION_GET_METHODDESC(iptr, md);
401 i = (iinfo) ? iinfo->throughcount : 0;
402 replace_create_replacement_point(jd, iinfo, rp++,
403 RPLPOINT_TYPE_CALL, &ra,
404 javalocals, iptr->sx.s23.s2.args + md->paramcount,
405 iptr->s1.argcount - md->paramcount - i);
413 /* XXX share code with stack.c */
414 j = iptr->dst.varindex;
415 i = iptr->sx.s23.s3.javaindex;
417 if (iptr->flags.bits & INS_FLAG_RETADDR)
418 javalocals[i] = UNUSED;
421 if (iptr->flags.bits & INS_FLAG_KILL_PREV)
422 javalocals[i-1] = UNUSED;
423 if (iptr->flags.bits & INS_FLAG_KILL_NEXT)
424 javalocals[i+1] = UNUSED;
433 replace_create_replacement_point(jd, iinfo, rp++,
434 RPLPOINT_TYPE_RETURN, &ra,
435 NULL, &(iptr->s1.varindex), 1);
439 replace_create_replacement_point(jd, iinfo, rp++,
440 RPLPOINT_TYPE_RETURN, &ra,
444 case ICMD_INLINE_START:
445 calleeinfo = iptr->sx.s23.s3.inlineinfo;
448 replace_create_replacement_point(jd, iinfo, rp++,
449 RPLPOINT_TYPE_INLINE, &ra,
451 calleeinfo->stackvars, calleeinfo->stackvarscount);
455 if (iinfo->javalocals_start)
456 MCOPY(javalocals, iinfo->javalocals_start, s4, m->maxlocals);
459 case ICMD_INLINE_END:
460 iinfo = iptr->sx.s23.s3.inlineinfo;
462 if (iinfo->javalocals_end)
463 MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
464 iinfo = iinfo->parent;
470 /* store the data in the codeinfo */
472 code->rplpoints = rplpoints;
473 code->rplpointcount = count;
474 code->regalloc = regalloc;
475 code->regalloccount = alloccount;
476 code->globalcount = 0;
477 code->savedintcount = INT_SAV_CNT - rd->savintreguse;
478 code->savedfltcount = FLT_SAV_CNT - rd->savfltreguse;
479 code->memuse = rd->memuse;
480 code->stackframesize = jd->cd->stackframesize;
482 /* everything alright */
488 /* replace_free_replacement_points *********************************************
490 Free memory used by replacement points.
493 code.............codeinfo whose replacement points should be freed.
495 *******************************************************************************/
497 void replace_free_replacement_points(codeinfo *code)
502 MFREE(code->rplpoints,rplpoint,code->rplpointcount);
505 MFREE(code->regalloc,rplalloc,code->regalloccount);
507 code->rplpoints = NULL;
508 code->rplpointcount = 0;
509 code->regalloc = NULL;
510 code->regalloccount = 0;
511 code->globalcount = 0;
515 /* replace_activate_replacement_point ******************************************
517 Activate a replacement point. When this function returns, the
518 replacement point is "armed", that is each thread reaching this point
519 will be replace to `target`.
522 rp...............replacement point to activate
523 target...........target of replacement
525 *******************************************************************************/
527 void replace_activate_replacement_point(rplpoint *rp,rplpoint *target)
529 assert(rp->target == NULL);
532 printf("activate replacement point: ");
533 replace_replacement_point_println(rp, 0);
539 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
540 md_patch_replacement_point(rp);
545 /* replace_deactivate_replacement_point ****************************************
547 Deactivate a replacement point. When this function returns, the
548 replacement point is "un-armed", that is a each thread reaching this point
549 will just continue normally.
552 rp...............replacement point to deactivate
554 *******************************************************************************/
556 void replace_deactivate_replacement_point(rplpoint *rp)
561 printf("deactivate replacement point: ");
562 replace_replacement_point_println(rp, 0);
568 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
569 md_patch_replacement_point(rp);
574 /* replace_read_value **********************************************************
576 Read a value with the given allocation from the execution state.
579 es...............execution state
580 sp...............stack pointer of the execution state (XXX eliminate?)
581 ra...............allocation
582 javaval..........where to put the value
585 *javaval.........the value
587 *******************************************************************************/
589 static void replace_read_value(executionstate_t *es,
594 if (ra->flags & INMEMORY) {
595 /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
596 #ifdef HAS_4BYTE_STACKSLOT
597 if (IS_2_WORD_TYPE(ra->type)) {
598 *javaval = *(u8*)(sp + ra->regoff);
602 *javaval = sp[ra->regoff];
603 #ifdef HAS_4BYTE_STACKSLOT
608 /* allocated register */
609 if (IS_FLT_DBL_TYPE(ra->type)) {
610 *javaval = es->fltregs[ra->regoff];
613 *javaval = es->intregs[ra->regoff];
619 /* replace_write_value *********************************************************
621 Write a value to the given allocation in the execution state.
624 es...............execution state
625 sp...............stack pointer of the execution state (XXX eliminate?)
626 ra...............allocation
627 *javaval.........the value
629 *******************************************************************************/
631 static void replace_write_value(executionstate_t *es,
636 if (ra->flags & INMEMORY) {
637 /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
638 #ifdef HAS_4BYTE_STACKSLOT
639 if (IS_2_WORD_TYPE(ra->type)) {
640 *(u8*)(sp + ra->regoff) = *javaval;
644 sp[ra->regoff] = *javaval;
645 #ifdef HAS_4BYTE_STACKSLOT
650 /* allocated register */
651 if (IS_FLT_DBL_TYPE(ra->type)) {
652 es->fltregs[ra->regoff] = *javaval;
655 es->intregs[ra->regoff] = *javaval;
661 /* replace_read_executionstate *************************************************
663 Read the given executions state and translate it to a source state.
666 rp...............replacement point at which `es` was taken
667 es...............execution state
668 ss...............where to put the source state
671 *ss..............the source state derived from the execution state
673 *******************************************************************************/
675 static void replace_read_executionstate(rplpoint *rp,executionstate_t *es,
683 sourceframe_t *frame;
690 topslot = TOP_IS_NORMAL;
694 sp = (stackslot_t *) es->sp;
696 /* on some architectures the returnAddress is passed on the stack by JSR */
698 #if defined(__I386__) || defined(__X86_64__)
699 if (rp->type == BBTYPE_SBR) {
701 topslot = TOP_IS_ON_STACK; /* XXX */
705 /* in some cases the top stack slot is passed in REG_ITMP1 */
707 if ( (rp->type == BBTYPE_EXH)
708 #if defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)
709 || (rp->type == BBTYPE_SBR) /* XXX */
713 topslot = TOP_IS_IN_ITMP1;
716 /* calculate base stack pointer */
718 basesp = sp + code_get_stack_frame_size(code);
720 /* create the source frame */
722 frame = DNEW(sourceframe_t);
723 frame->up = ss->frames;
724 frame->method = rp->method;
729 /* read local variables */
731 count = m->maxlocals;
732 frame->javalocalcount = count;
733 frame->javalocals = DMNEW(u8, count);
734 frame->javalocaltype = DMNEW(u1, count);
737 /* mark values as undefined */
738 for (i=0; i<count; ++i) {
739 frame->javalocals[i] = (u8) 0x00dead0000dead00ULL;
740 frame->javalocaltype[i] = TYPE_VOID;
743 /* some entries in the intregs array are not meaningful */
744 /*es->intregs[REG_ITMP3] = (u8) 0x11dead1111dead11ULL;*/
745 es->intregs[REG_SP ] = (u8) 0x11dead1111dead11ULL;
747 es->intregs[REG_PV ] = (u8) 0x11dead1111dead11ULL;
749 #endif /* !defined(NDEBUG) */
751 /* read javalocals */
753 count = rp->regalloccount;
756 while (count && (i = ra->index) >= 0) {
757 assert(i < m->maxlocals);
758 frame->javalocaltype[i] = ra->type;
759 replace_read_value(es, sp, ra, frame->javalocals + i);
764 /* read stack slots */
766 frame->javastackdepth = count;
767 frame->javastack = DMNEW(u8, count);
768 frame->javastacktype = DMNEW(u1, count);
771 /* mark values as undefined */
772 for (i=0; i<count; ++i) {
773 frame->javastack[i] = (u8) 0x00dead0000dead00ULL;
774 frame->javastacktype[i] = TYPE_VOID;
776 #endif /* !defined(NDEBUG) */
780 /* the first stack slot is special in SBR and EXH blocks */
782 if (topslot == TOP_IS_ON_STACK) {
785 frame->javastack[i] = sp[-1];
786 frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
791 else if (topslot == TOP_IS_IN_ITMP1) {
794 frame->javastack[i] = es->intregs[REG_ITMP1];
795 frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
801 /* read remaining stack slots */
803 for (; count--; ra++, i++) {
804 assert(ra->index == -1);
806 replace_read_value(es,sp,ra,frame->javastack + i);
807 frame->javastacktype[i] = ra->type;
810 /* read slots used for synchronization */
812 count = code_get_sync_slot_count(code);
813 frame->syncslotcount = count;
814 frame->syncslots = DMNEW(u8,count);
815 for (i=0; i<count; ++i) {
816 frame->syncslots[i] = sp[code->memuse + i];
821 /* replace_write_executionstate ************************************************
823 Translate the given source state into an execution state.
826 rp...............replacement point for which execution state should be
828 es...............where to put the execution state
829 ss...............the given source state
832 *es..............the execution state derived from the source state
834 *******************************************************************************/
836 static void replace_write_executionstate(rplpoint *rp,
837 executionstate_t *es,
845 sourceframe_t *frame;
852 topslot = TOP_IS_NORMAL;
854 /* pop a source frame */
858 ss->frames = frame->up;
860 /* calculate stack pointer */
862 sp = (stackslot_t *) es->sp;
864 basesp = sp + code_get_stack_frame_size(code);
866 /* on some architectures the returnAddress is passed on the stack by JSR */
868 #if defined(__I386__) || defined(__X86_64__)
869 if (rp->type == BBTYPE_SBR) {
870 topslot = TOP_IS_ON_STACK; /* XXX */
874 /* in some cases the top stack slot is passed in REG_ITMP1 */
876 if ( (rp->type == BBTYPE_EXH)
877 #if defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)
878 || (rp->type == BBTYPE_SBR) /* XXX */
882 topslot = TOP_IS_IN_ITMP1;
885 /* write javalocals */
888 count = rp->regalloccount;
890 while (count && (i = ra->index) >= 0) {
891 assert(i < m->maxlocals);
892 assert(ra->type == frame->javalocaltype[i]);
893 replace_write_value(es, sp, ra, frame->javalocals + i);
898 /* write stack slots */
902 /* the first stack slot is special in SBR and EXH blocks */
904 if (topslot == TOP_IS_ON_STACK) {
907 assert(frame->javastacktype[i] == TYPE_ADR);
908 sp[-1] = frame->javastack[i];
913 else if (topslot == TOP_IS_IN_ITMP1) {
916 assert(frame->javastacktype[i] == TYPE_ADR);
917 assert(frame->javastacktype[i] == TYPE_ADR);
918 es->intregs[REG_ITMP1] = frame->javastack[i];
924 /* write remaining stack slots */
926 for (; count--; ra++, i++) {
927 assert(ra->index == -1);
929 assert(ra->type == frame->javastacktype[i]);
930 replace_write_value(es,sp,ra,frame->javastack + i);
933 /* write slots used for synchronization */
935 count = code_get_sync_slot_count(code);
936 assert(count == frame->syncslotcount);
937 for (i=0; i<count; ++i) {
938 sp[code->memuse + i] = frame->syncslots[i];
947 /* replace_pop_activation_record ***********************************************
949 Peel a stack frame from the execution state.
951 *** This function imitates the effects of the method epilog ***
952 *** and returning from the method call. ***
955 es...............execution state
958 *es..............the execution state after popping the stack frame
960 *******************************************************************************/
962 bool replace_pop_activation_record(executionstate_t *es)
973 /* read the return address */
975 ra = md_stacktrace_get_returnaddress(es->sp,
976 SIZE_OF_STACKSLOT * es->code->stackframesize);
978 printf("return address: %p\n", (void*)ra);
980 /* find the new codeinfo */
982 pv = md_codegen_get_pv_from_pc(ra);
984 printf("PV = %p\n", (void*) pv);
989 code = *(codeinfo **)(pv + CodeinfoPointer);
991 printf("CODE = %p\n", (void*) code);
996 /* calculate the base of the stack frame */
998 basesp = (stackslot_t *)es->sp + es->code->stackframesize;
1000 /* restore saved int registers */
1003 for (i=0; i<es->code->savedintcount; ++i) {
1004 while (nregdescint[--reg] != REG_SAV)
1006 es->intregs[reg] = *--basesp;
1009 /* restore saved flt registers */
1013 for (i=0; i<es->code->savedfltcount; ++i) {
1014 while (nregdescfloat[--reg] != REG_SAV)
1016 basesp -= STACK_SLOTS_PER_FLOAT;
1017 es->fltregs[reg] = *(u8*)basesp;
1020 /* set the new pc */
1024 /* adjust the stackpointer */
1026 es->sp += SIZE_OF_STACKSLOT * es->code->stackframesize;
1027 es->sp += SIZE_OF_STACKSLOT; /* skip return address */
1032 #if !defined(NDEBUG)
1034 for (i=0; i<INT_REG_CNT; ++i)
1035 if (nregdescint[i] != REG_SAV)
1036 es->intregs[i] = 0x33dead3333dead33ULL;
1037 for (i=0; i<FLT_REG_CNT; ++i)
1038 if (nregdescfloat[i] != REG_SAV)
1039 es->fltregs[i] = 0x33dead3333dead33ULL;
1040 #endif /* !defined(NDEBUG) */
1046 /* replace_push_activation_record **********************************************
1048 Push a stack frame onto the execution state.
1050 *** This function imitates the effects of a call and the ***
1051 *** method prolog of the callee. ***
1054 es...............execution state
1055 rpcall...........the replacement point at the call site
1056 calleecode.......the codeinfo of the callee
1059 *es..............the execution state after pushing the stack frame
1061 *******************************************************************************/
1063 void replace_push_activation_record(executionstate_t *es,
1065 codeinfo *calleecode)
1069 stackslot_t *basesp;
1071 /* write the return address */
1073 *((stackslot_t *)es->sp) = (stackslot_t) (rpcall->pc + rpcall->callsize);
1075 es->sp -= SIZE_OF_STACKSLOT;
1077 /* we move into a new code unit */
1079 es->code = calleecode;
1081 /* set the new pc XXX not needed */
1083 es->pc = es->code->entrypoint;
1085 /* build the stackframe */
1087 basesp = (stackslot_t *) es->sp;
1088 es->sp -= SIZE_OF_STACKSLOT * es->code->stackframesize;
1090 /* in debug mode, invalidate stack frame first */
1092 #if !defined(NDEBUG)
1094 stackslot_t *sp = (stackslot_t *) es->sp;
1095 for (i=0; i<(basesp - sp); ++i) {
1096 sp[i] = 0xdeaddeadU;
1101 /* save int registers */
1104 for (i=0; i<es->code->savedintcount; ++i) {
1105 while (nregdescint[--reg] != REG_SAV)
1107 *--basesp = es->intregs[reg];
1109 #if !defined(NDEBUG)
1110 es->intregs[reg] = 0x44dead4444dead44ULL;
1114 /* save flt registers */
1118 for (i=0; i<es->code->savedfltcount; ++i) {
1119 while (nregdescfloat[--reg] != REG_SAV)
1121 basesp -= STACK_SLOTS_PER_FLOAT;
1122 *(u8*)basesp = es->fltregs[reg];
1124 #if !defined(NDEBUG)
1125 es->fltregs[reg] = 0x44dead4444dead44ULL;
1131 es->pv = es->code->entrypoint;
1135 /* replace_find_replacement_point **********************************************
1137 Find the replacement point in the given code corresponding to the
1138 position given in the source frame.
1141 code.............the codeinfo in which to search the rplpoint
1142 ss...............the source state defining the position to look for
1145 the replacement point
1147 *******************************************************************************/
1149 rplpoint * replace_find_replacement_point(codeinfo *code, sourcestate_t *ss)
1151 sourceframe_t *frame;
1161 #if !defined(NDEBUG)
1162 printf("searching replacement point for:\n");
1163 replace_source_frame_println(frame);
1168 #if !defined(NDEBUG)
1169 printf("code = %p\n", (void*)code);
1172 rp = code->rplpoints;
1173 i = code->rplpointcount;
1175 if (rp->id == frame->id)
1181 return NULL; /* NOT REACHED */
1185 /* replace_me ******************************************************************
1187 This function is called by asm_replacement_out when a thread reaches
1188 a replacement point. `replace_me` must map the execution state to the
1189 target replacement point and let execution continue there.
1191 This function never returns!
1194 rp...............replacement point that has been reached
1195 es...............execution state read by asm_replacement_out
1197 *******************************************************************************/
1199 void replace_me(rplpoint *rp, executionstate_t *es)
1204 rplpoint *candidate;
1208 es->code = rp->code;
1210 /* mark start of dump memory area */
1212 dumpsize = dump_size();
1214 /* fetch the target of the replacement */
1216 target = rp->target;
1218 /* XXX DEBUG turn off self-replacement */
1220 replace_deactivate_replacement_point(rp);
1222 #if !defined(NDEBUG)
1223 printf("replace_me(%p,%p)\n",(void*)rp,(void*)es);
1225 replace_replacement_point_println(rp, 0);
1226 replace_executionstate_println(es);
1229 /* read execution state of old code */
1237 #if !defined(NDEBUG)
1238 printf("recovering source state for:\n");
1239 replace_replacement_point_println(candidate, 1);
1242 replace_read_executionstate(candidate,es,&ss);
1244 if (candidate->parent) {
1245 printf("INLINED!\n");
1246 candidate = candidate->parent;
1247 assert(candidate->type == RPLPOINT_TYPE_INLINE);
1251 if (!replace_pop_activation_record(es)) {
1252 printf("BREAKING\n");
1255 #if !defined(NDEBUG)
1256 replace_executionstate_println(es);
1259 rp = es->code->rplpoints;
1260 for (i=0; i<es->code->rplpointcount; ++i, ++rp)
1261 if (rp->pc <= es->pc)
1264 printf("NO CANDIDATE!\n");
1266 printf("found replacement point.\n");
1267 assert(candidate->type == RPLPOINT_TYPE_CALL);
1270 } while (candidate);
1272 #if !defined(NDEBUG)
1273 replace_sourcestate_println(&ss);
1276 /* write execution state of new code */
1278 #if !defined(NDEBUG)
1279 replace_executionstate_println(es);
1287 candidate = replace_find_replacement_point(code, &ss);
1289 #if !defined(NDEBUG)
1290 printf("creating execution state for:\n");
1291 replace_replacement_point_println(candidate, 1);
1294 replace_write_executionstate(candidate, es, &ss);
1295 if (ss.frames == NULL)
1298 if (candidate->type == RPLPOINT_TYPE_CALL) {
1299 code = ss.frames->method->code;
1301 replace_push_activation_record(es, candidate, code);
1303 #if !defined(NDEBUG)
1304 replace_executionstate_println(es);
1308 #if !defined(NDEBUG)
1309 replace_executionstate_println(es);
1312 /* release dump area */
1314 dump_release(dumpsize);
1316 /* enter new code */
1318 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
1319 asm_replacement_in(es);
1321 abort(); /* NOT REACHED */
1325 /* replace_replacement_point_println *******************************************
1327 Print replacement point info.
1330 rp...............the replacement point to print
1332 *******************************************************************************/
1334 #if !defined(NDEBUG)
1335 static const char *type_char = "IJFDA";
1337 #define TYPECHAR(t) (((t) >= 0 && (t) <= 4) ? type_char[t] : '?')
1339 static char *replace_type_str[] = {
1348 void replace_replacement_point_println(rplpoint *rp, int depth)
1353 printf("(rplpoint *)NULL\n");
1357 for (j=0; j<depth; ++j)
1360 printf("rplpoint %p pc:%p+%d out:%p target:%p mcode:%016llx type:%s flags:%01x parent:%p\n",
1361 (void*)rp,rp->pc,rp->callsize,rp->outcode,(void*)rp->target,
1362 (unsigned long long)rp->mcode,replace_type_str[rp->type],rp->flags,
1364 for (j=0; j<depth; ++j)
1366 printf("ra:%d = [", rp->regalloccount);
1368 for (j=0; j<rp->regalloccount; ++j) {
1372 rp->regalloc[j].index,
1373 /* (rp->regalloc[j].next) ? '^' : ' ', */
1374 TYPECHAR(rp->regalloc[j].type));
1375 show_allocation(rp->regalloc[j].type, rp->regalloc[j].flags, rp->regalloc[j].regoff);
1379 for (j=0; j<depth; ++j)
1382 method_print(rp->method);
1389 /* replace_show_replacement_points *********************************************
1391 Print replacement point info.
1394 code.............codeinfo whose replacement points should be printed.
1396 *******************************************************************************/
1398 #if !defined(NDEBUG)
1399 void replace_show_replacement_points(codeinfo *code)
1407 printf("(codeinfo *)NULL\n");
1411 printf("\treplacement points: %d\n",code->rplpointcount);
1413 printf("\ttotal allocations : %d\n",code->regalloccount);
1414 printf("\tsaved int regs : %d\n",code->savedintcount);
1415 printf("\tsaved flt regs : %d\n",code->savedfltcount);
1416 printf("\tmemuse : %d\n",code->memuse);
1420 for (i=0; i<code->rplpointcount; ++i) {
1421 rp = code->rplpoints + i;
1423 assert(rp->code == code);
1426 parent = rp->parent;
1429 parent = parent->parent;
1431 replace_replacement_point_println(rp, depth);
1437 /* replace_executionstate_println **********************************************
1439 Print execution state
1442 es...............the execution state to print
1444 *******************************************************************************/
1446 #if !defined(NDEBUG)
1447 void replace_executionstate_println(executionstate_t *es)
1454 printf("(executionstate_t *)NULL\n");
1458 printf("executionstate_t:\n");
1459 printf("\tpc = %p",(void*)es->pc);
1460 printf(" sp = %p",(void*)es->sp);
1461 printf(" pv = %p\n",(void*)es->pv);
1462 #if defined(ENABLE_DISASSEMBLER)
1463 for (i=0; i<INT_REG_CNT; ++i) {
1468 printf("%-3s = %016llx",regs[i],(unsigned long long)es->intregs[i]);
1472 for (i=0; i<FLT_REG_CNT; ++i) {
1477 printf("F%02d = %016llx",i,(unsigned long long)es->fltregs[i]);
1483 sp = (stackslot_t *) es->sp;
1486 slots = code_get_stack_frame_size(es->code);
1491 printf("\tstack slots(+1) at sp:");
1492 for (i=0; i<slots+1; ++i) {
1499 #ifdef HAS_4BYTE_STACKSLOT
1500 printf("%08lx",(unsigned long)*sp++);
1502 printf("%016llx",(unsigned long long)*sp++);
1510 printf("\tcode: %p", (void*)es->code);
1511 if (es->code != NULL) {
1512 printf(" stackframesize=%d ", es->code->stackframesize);
1513 method_print(es->code->m);
1521 #if !defined(NDEBUG)
1522 void java_value_print(s4 type, u8 value)
1524 java_objectheader *obj;
1527 printf("%016llx",(unsigned long long) value);
1529 if (type < 0 || type > TYPE_RET)
1530 printf(" <INVALID TYPE:%d>", type);
1532 printf(" %s", show_jit_type_names[type]);
1534 if (type == TYPE_ADR && value != 0) {
1535 obj = (java_objectheader *) (ptrint) value;
1537 utf_display_printable_ascii_classname(obj->vftbl->class->name);
1539 if (obj->vftbl->class == class_java_lang_String) {
1541 u = javastring_toutf((java_lang_String *)obj, false);
1542 utf_display_printable_ascii(u);
1546 else if (type == TYPE_INT || type == TYPE_LNG) {
1547 printf(" %lld", (long long) value);
1550 #endif /* !defined(NDEBUG) */
1553 #if !defined(NDEBUG)
1554 void replace_source_frame_println(sourceframe_t *frame)
1560 method_println(frame->method);
1563 if (frame->javalocalcount) {
1564 printf("\tlocals (%d):\n",frame->javalocalcount);
1565 for (i=0; i<frame->javalocalcount; ++i) {
1566 t = frame->javalocaltype[i];
1567 if (t == TYPE_VOID) {
1568 printf("\tlocal[ %2d] = void\n",i);
1571 printf("\tlocal[%c%2d] = ",TYPECHAR(t),i);
1572 java_value_print(t, frame->javalocals[i]);
1579 if (frame->javastackdepth) {
1580 printf("\tstack (depth %d):\n",frame->javastackdepth);
1581 for (i=0; i<frame->javastackdepth; ++i) {
1582 printf("\tstack[%2d] = ",i);
1583 java_value_print(frame->javastacktype[i], frame->javastack[i]);
1589 if (frame->syncslotcount) {
1590 printf("\tsynchronization slots (%d):\n",frame->syncslotcount);
1591 for (i=0; i<frame->syncslotcount; ++i) {
1592 printf("\tslot[%2d] = ",i);
1593 #ifdef HAS_4BYTE_STACKSLOT
1594 printf("%08lx\n",(unsigned long) frame->syncslots[i]);
1596 printf("%016llx\n",(unsigned long long) frame->syncslots[i]);
1602 #endif /* !defined(NDEBUG) */
1605 /* replace_sourcestate_println *************************************************
1610 ss...............the source state to print
1612 *******************************************************************************/
1614 #if !defined(NDEBUG)
1615 void replace_sourcestate_println(sourcestate_t *ss)
1618 sourceframe_t *frame;
1621 printf("(sourcestate_t *)NULL\n");
1625 printf("sourcestate_t:\n");
1627 for (i=0, frame = ss->frames; frame != NULL; frame = frame->up, ++i) {
1628 printf(" frame %d:\n", i);
1629 replace_source_frame_println(frame);
1635 * These are local overrides for various environment variables in Emacs.
1636 * Please do not remove this and leave it at the end of the file, where
1637 * Emacs will automagically detect them.
1638 * ---------------------------------------------------------------------
1641 * indent-tabs-mode: t
1645 * vim:noexpandtab:sw=4:ts=4: