2f5f48586391bae699eb8a4631add5484606efa3
[cacao.git] / src / vm / jit / replace.c
1 /* vm/jit/replace.c - on-stack replacement of methods
2
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
7
8    This file is part of CACAO.
9
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.
14
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.
19
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
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Edwin Steiner
28
29    Changes:
30
31    $Id$
32
33 */
34
35 #include "config.h"
36 #include "vm/types.h"
37
38 #include <assert.h>
39 #include <stdlib.h>
40
41 #include "arch.h"
42
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"
54
55 #include "native/include/java_lang_String.h"
56
57
58 /*** configuration of native stack slot size **********************************/
59
60 /* XXX this should be in md-abi.h files, probably */
61
62 #if defined(HAS_4BYTE_STACKSLOT)
63 #define SIZE_OF_STACKSLOT      4
64 #define STACK_SLOTS_PER_FLOAT  2
65 typedef u4 stackslot_t;
66 #else
67 #define SIZE_OF_STACKSLOT      8
68 #define STACK_SLOTS_PER_FLOAT  1
69 typedef u8 stackslot_t;
70 #endif
71
72
73 /*** debugging ****************************************************************/
74
75 /*#define REPLACE_VERBOSE*/
76
77 #if !defined(NDEBUG) && defined(REPLACE_VERBOSE)
78 #define DOLOG(code) do{ if (1) { code; } } while(0)
79 #else
80 #define DOLOG(code)
81 #endif
82
83
84 /*** constants used internally ************************************************/
85
86 #define TOP_IS_NORMAL    0
87 #define TOP_IS_ON_STACK  1
88 #define TOP_IS_IN_ITMP1  2
89 #define TOP_IS_VOID      3
90
91
92 /* replace_create_replacement_point ********************************************
93  
94    Create a replacement point.
95   
96    IN:
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
106   
107    OUT:
108        *rpa.............points to the next free rplalloc
109   
110 *******************************************************************************/
111
112 static void replace_create_replacement_point(jitdata *jd,
113                                                                                          insinfo_inline *iinfo,
114                                                                                          rplpoint *rp,
115                                                                                          s4 type,
116                                                                                          instruction *iptr,
117                                                                                          rplalloc **pra,
118                                                                                          s4 *javalocals,
119                                                                                          s4 *stackvars,
120                                                                                          s4 stackdepth,
121                                                                                          s4 paramcount)
122 {
123         rplalloc *ra;
124         s4        i;
125         varinfo  *v;
126         s4        index;
127
128         ra = *pra;
129
130         /* there will be a replacement point at the start of this block */
131
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 */
136         rp->target = NULL;
137         rp->regalloc = ra;
138         rp->flags = 0;
139         rp->type = type;
140         rp->id = iptr->flags.bits >> INS_FLAG_ID_SHIFT;
141
142         /* XXX unify these two fields */
143         rp->code = jd->code;
144         rp->parent = (iinfo) ? iinfo->rp : NULL;
145
146         /* store local allocation info of javalocals */
147
148         if (javalocals) {
149                 for (i = 0; i < rp->method->maxlocals; ++i) {
150                         index = javalocals[i];
151                         if (index == UNUSED)
152                                 continue;
153
154                         ra->index = i;
155                         if (index < UNUSED) {
156                                 ra->regoff = (UNUSED - index) - 1;
157                                 ra->type = TYPE_RET;
158                                 ra->flags = 0;
159                         }
160                         else {
161                                 v = VAR(index);
162                                 ra->flags = v->flags & (INMEMORY);
163                                 ra->regoff = v->vv.regoff;
164                                 ra->type = v->type;
165                         }
166                         ra++;
167                 }
168         }
169
170         /* store allocation info of java stack vars */
171
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;
176                 ra->type  = v->type;
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;
181                 }
182                 else
183                         ra->regoff = v->vv.regoff;
184                 ra++;
185         }
186
187         /* total number of allocations */
188
189         rp->regalloccount = ra - rp->regalloc;
190
191         *pra = ra;
192 }
193
194
195 /* replace_create_replacement_points *******************************************
196  
197    Create the replacement points for the given code.
198   
199    IN:
200        jd...............current jitdata, must not have any replacement points
201   
202    OUT:
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
209   
210    RETURN VALUE:
211        true.............everything ok 
212        false............an exception has been thrown
213    
214 *******************************************************************************/
215
216 bool replace_create_replacement_points(jitdata *jd)
217 {
218         codeinfo        *code;
219         registerdata    *rd;
220         basicblock      *bptr;
221         int              count;
222         methodinfo      *m;
223         rplpoint        *rplpoints;
224         rplpoint        *rp;
225         int              alloccount;
226         rplalloc        *regalloc;
227         rplalloc        *ra;
228         int              i;
229         instruction     *iptr;
230         instruction     *iend;
231         s4              *javalocals;
232         methoddesc      *md;
233         s4               j;
234         insinfo_inline  *iinfo;
235         insinfo_inline  *calleeinfo;
236         s4               startcount;
237
238         /* get required compiler data */
239
240         code = jd->code;
241         rd   = jd->rd;
242
243         /* assert that we wont overwrite already allocated data */
244
245         assert(code);
246         assert(code->m);
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);
252
253         /* iterate over the basic block list to find replacement points */
254
255         m = code->m;
256
257         count = 0;
258         alloccount = 0;
259
260         javalocals = DMNEW(s4, jd->maxlocals);
261
262         for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
263
264                 /* skip dead code */
265
266                 if (bptr->flags < BBFINISHED)
267                         continue;
268
269                 /* get info about this block */
270
271                 m = bptr->method;
272                 iinfo = bptr->inlineinfo;
273
274                 /* initialize javalocals at the start of this block */
275
276                 if (bptr->javalocals)
277                         MCOPY(javalocals, bptr->javalocals, s4, m->maxlocals);
278                 else
279                         for (i=0; i<m->maxlocals; ++i)
280                                 javalocals[i] = UNUSED;
281
282                 /* iterate over the instructions */
283
284                 iptr = bptr->iinstr;
285                 iend = iptr + bptr->icount;
286                 startcount = count;
287
288                 for (; iptr != iend; ++iptr) {
289                         switch (iptr->opc) {
290                                 case ICMD_INVOKESTATIC:
291                                 case ICMD_INVOKESPECIAL:
292                                 case ICMD_INVOKEVIRTUAL:
293                                 case ICMD_INVOKEINTERFACE:
294                                         INSTRUCTION_GET_METHODDESC(iptr, md);
295                                         count++;
296                                         for (i=0; i<m->maxlocals; ++i)
297                                                 if (javalocals[i] != UNUSED)
298                                                         alloccount++;
299                                         alloccount += iptr->s1.argcount;
300                                         if (iinfo)
301                                                 alloccount -= iinfo->throughcount;
302                                         break;
303
304                                 case ICMD_ISTORE:
305                                 case ICMD_LSTORE:
306                                 case ICMD_FSTORE:
307                                 case ICMD_DSTORE:
308                                 case ICMD_ASTORE:
309                                         /* XXX share code with stack.c */
310                                         j = iptr->dst.varindex;
311                                         i = iptr->sx.s23.s3.javaindex;
312                                         if (i != UNUSED) {
313                                                 if (iptr->flags.bits & INS_FLAG_RETADDR)
314                                                         javalocals[i] = iptr->sx.s23.s2.retaddrnr;
315                                                 else
316                                                         javalocals[i] = j;
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;
321                                         }
322                                         break;
323
324                                 case ICMD_IRETURN:
325                                 case ICMD_LRETURN:
326                                 case ICMD_FRETURN:
327                                 case ICMD_DRETURN:
328                                 case ICMD_ARETURN:
329                                         alloccount += 1;
330                                         /* FALLTHROUGH! */
331                                 case ICMD_RETURN:
332                                         count++;
333                                         break;
334
335                                 case ICMD_INLINE_START:
336                                         iinfo = iptr->sx.s23.s3.inlineinfo;
337
338                                         count++;
339                                         for (i=0; i<m->maxlocals; ++i)
340                                                 if (javalocals[i] != UNUSED)
341                                                         alloccount++;
342                                         alloccount += iinfo->stackvarscount;
343                                         if (iinfo->synclocal != UNUSED)
344                                                 alloccount++;
345
346                                         m = iinfo->method;
347                                         if (iinfo->javalocals_start)
348                                                 MCOPY(javalocals, iinfo->javalocals_start, s4, m->maxlocals);
349                                         break;
350
351                                 case ICMD_INLINE_END:
352                                         iinfo = iptr->sx.s23.s3.inlineinfo;
353                                         m = iinfo->outer;
354                                         if (iinfo->javalocals_end)
355                                                 MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
356                                         iinfo = iinfo->parent;
357                                         break;
358                         }
359                 } /* end instruction loop */
360
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.                       */
364
365                 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
366                         if (count > startcount) {
367                                 /* we don't need it */
368                                 bptr->bitflags &= ~BBFLAG_REPLACEMENT;
369                         }
370                         else {
371                                 count++;
372                                 alloccount += bptr->indepth;
373
374                                 for (i=0; i<m->maxlocals; ++i)
375                                         if (bptr->javalocals[i] != UNUSED)
376                                                 alloccount++;
377                         }
378                 }
379
380         } /* end basicblock loop */
381
382         /* if no points were found, there's nothing to do */
383
384         if (!count)
385                 return true;
386
387         /* allocate replacement point array and allocation array */
388
389         rplpoints = MNEW(rplpoint, count);
390         regalloc = MNEW(rplalloc, alloccount);
391         ra = regalloc;
392
393         /* initialize replacement point structs */
394
395         rp = rplpoints;
396
397         /* XXX try to share code with the counting loop! */
398
399         for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
400                 /* skip dead code */
401
402                 if (bptr->flags < BBFINISHED)
403                         continue;
404
405                 /* get info about this block */
406
407                 m = bptr->method;
408                 iinfo = bptr->inlineinfo;
409
410                 /* initialize javalocals at the start of this block */
411
412                 if (bptr->javalocals)
413                         MCOPY(javalocals, bptr->javalocals, s4, m->maxlocals);
414                 else
415                         for (i=0; i<m->maxlocals; ++i)
416                                 javalocals[i] = UNUSED;
417
418                 /* create replacement points at targets of backward branches */
419
420                 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
421
422                         replace_create_replacement_point(jd, iinfo, rp++,
423                                         bptr->type, bptr->iinstr, &ra,
424                                         bptr->javalocals, bptr->invars, bptr->indepth, 0);
425                 }
426
427                 /* iterate over the instructions */
428
429                 iptr = bptr->iinstr;
430                 iend = iptr + bptr->icount;
431
432                 for (; iptr != iend; ++iptr) {
433                         switch (iptr->opc) {
434                                 case ICMD_INVOKESTATIC:
435                                 case ICMD_INVOKESPECIAL:
436                                 case ICMD_INVOKEVIRTUAL:
437                                 case ICMD_INVOKEINTERFACE:
438                                         INSTRUCTION_GET_METHODDESC(iptr, md);
439
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,
445                                                         md->paramcount);
446                                         break;
447
448                                 case ICMD_ISTORE:
449                                 case ICMD_LSTORE:
450                                 case ICMD_FSTORE:
451                                 case ICMD_DSTORE:
452                                 case ICMD_ASTORE:
453                                         /* XXX share code with stack.c */
454                                         j = iptr->dst.varindex;
455                                         i = iptr->sx.s23.s3.javaindex;
456                                         if (i != UNUSED) {
457                                                 if (iptr->flags.bits & INS_FLAG_RETADDR)
458                                                         javalocals[i] = iptr->sx.s23.s2.retaddrnr;
459                                                 else
460                                                         javalocals[i] = j;
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;
465                                         }
466                                         break;
467
468                                 case ICMD_IRETURN:
469                                 case ICMD_LRETURN:
470                                 case ICMD_FRETURN:
471                                 case ICMD_DRETURN:
472                                 case ICMD_ARETURN:
473                                         replace_create_replacement_point(jd, iinfo, rp++,
474                                                         RPLPOINT_TYPE_RETURN, iptr, &ra,
475                                                         NULL, &(iptr->s1.varindex), 1, 0);
476                                         break;
477
478                                 case ICMD_RETURN:
479                                         replace_create_replacement_point(jd, iinfo, rp++,
480                                                         RPLPOINT_TYPE_RETURN, iptr, &ra,
481                                                         NULL, NULL, 0, 0);
482                                         break;
483
484                                 case ICMD_INLINE_START:
485                                         calleeinfo = iptr->sx.s23.s3.inlineinfo;
486
487                                         calleeinfo->rp = rp;
488                                         replace_create_replacement_point(jd, iinfo, rp++,
489                                                         RPLPOINT_TYPE_INLINE, iptr, &ra,
490                                                         javalocals,
491                                                         calleeinfo->stackvars, calleeinfo->stackvarscount,
492                                                         calleeinfo->paramcount);
493
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;
498                                                 ra->type = TYPE_ADR;
499                                                 ra++;
500                                                 rp[-1].regalloccount++;
501                                         }
502
503                                         iinfo = calleeinfo;
504                                         m = iinfo->method;
505                                         if (iinfo->javalocals_start)
506                                                 MCOPY(javalocals, iinfo->javalocals_start, s4, m->maxlocals);
507                                         break;
508
509                                 case ICMD_INLINE_END:
510                                         iinfo = iptr->sx.s23.s3.inlineinfo;
511                                         m = iinfo->outer;
512                                         if (iinfo->javalocals_end)
513                                                 MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
514                                         iinfo = iinfo->parent;
515                                         break;
516                         }
517                 } /* end instruction loop */
518         } /* end basicblock loop */
519
520         assert((rp - rplpoints) == count);
521         assert((ra - regalloc) == alloccount);
522
523         /* store the data in the codeinfo */
524
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;
534
535         /* everything alright */
536
537         return true;
538 }
539
540
541 /* replace_free_replacement_points *********************************************
542  
543    Free memory used by replacement points.
544   
545    IN:
546        code.............codeinfo whose replacement points should be freed.
547   
548 *******************************************************************************/
549
550 void replace_free_replacement_points(codeinfo *code)
551 {
552         assert(code);
553
554         if (code->rplpoints)
555                 MFREE(code->rplpoints,rplpoint,code->rplpointcount);
556
557         if (code->regalloc)
558                 MFREE(code->regalloc,rplalloc,code->regalloccount);
559
560         code->rplpoints = NULL;
561         code->rplpointcount = 0;
562         code->regalloc = NULL;
563         code->regalloccount = 0;
564         code->globalcount = 0;
565 }
566
567
568 /* replace_activate_replacement_point ******************************************
569  
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`.
573    
574    IN:
575        rp...............replacement point to activate
576            target...........target of replacement
577   
578 *******************************************************************************/
579
580 void replace_activate_replacement_point(rplpoint *rp,rplpoint *target)
581 {
582         assert(rp->target == NULL);
583
584         DOLOG( printf("activate replacement point:\n");
585                    replace_replacement_point_println(rp, 1); fflush(stdout); );
586
587         rp->target = target;
588
589 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
590         md_patch_replacement_point(rp);
591 #endif
592 }
593
594
595 /* replace_deactivate_replacement_point ****************************************
596  
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.
600    
601    IN:
602        rp...............replacement point to deactivate
603   
604 *******************************************************************************/
605
606 void replace_deactivate_replacement_point(rplpoint *rp)
607 {
608         assert(rp->target);
609
610         DOLOG( printf("deactivate replacement point:\n");
611                    replace_replacement_point_println(rp, 1); fflush(stdout); );
612
613         rp->target = NULL;
614
615 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
616         md_patch_replacement_point(rp);
617 #endif
618 }
619
620
621 /* replace_read_value **********************************************************
622
623    Read a value with the given allocation from the execution state.
624    
625    IN:
626            es...............execution state
627            sp...............stack pointer of the execution state (XXX eliminate?)
628            ra...............allocation
629            javaval..........where to put the value
630
631    OUT:
632        *javaval.........the value
633   
634 *******************************************************************************/
635
636 static void replace_read_value(executionstate_t *es,
637                                                            stackslot_t *sp,
638                                                            rplalloc *ra,
639                                                            u8 *javaval)
640 {
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);
646                 }
647                 else {
648 #endif
649                         *javaval = sp[ra->regoff];
650 #ifdef HAS_4BYTE_STACKSLOT
651                 }
652 #endif
653         }
654         else {
655                 /* allocated register */
656                 if (IS_FLT_DBL_TYPE(ra->type)) {
657                         *javaval = es->fltregs[ra->regoff];
658                 }
659                 else {
660                         *javaval = es->intregs[ra->regoff];
661                 }
662         }
663 }
664
665
666 /* replace_write_value *********************************************************
667
668    Write a value to the given allocation in the execution state.
669    
670    IN:
671            es...............execution state
672            sp...............stack pointer of the execution state (XXX eliminate?)
673            ra...............allocation
674            *javaval.........the value
675
676 *******************************************************************************/
677
678 static void replace_write_value(executionstate_t *es,
679                                                             stackslot_t *sp,
680                                                             rplalloc *ra,
681                                                             u8 *javaval)
682 {
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;
688                 }
689                 else {
690 #endif
691                         sp[ra->regoff] = *javaval;
692 #ifdef HAS_4BYTE_STACKSLOT
693                 }
694 #endif
695         }
696         else {
697                 /* allocated register */
698                 if (IS_FLT_DBL_TYPE(ra->type)) {
699                         es->fltregs[ra->regoff] = *javaval;
700                 }
701                 else {
702                         es->intregs[ra->regoff] = *javaval;
703                 }
704         }
705 }
706
707
708 /* replace_read_executionstate *************************************************
709
710    Read the given executions state and translate it to a source frame.
711    
712    IN:
713        rp...............replacement point at which `es` was taken
714            es...............execution state
715            ss...............where to put the source state
716
717    OUT:
718        *ss..............the source state derived from the execution state
719   
720 *******************************************************************************/
721
722 static void replace_read_executionstate(rplpoint *rp,
723                                                                                 executionstate_t *es,
724                                                                                 sourcestate_t *ss,
725                                                                                 bool topframe)
726 {
727         methodinfo    *m;
728         codeinfo      *code;
729         int            count;
730         int            i;
731         rplalloc      *ra;
732         sourceframe_t *frame;
733         int            topslot;
734         stackslot_t   *sp;
735         stackslot_t   *basesp;
736
737         code = rp->code;
738         m = rp->method;
739         topslot = TOP_IS_NORMAL;
740
741         /* stack pointer */
742
743         sp = (stackslot_t *) es->sp;
744
745         /* in some cases the top stack slot is passed in REG_ITMP1 */
746
747         if (rp->type == BBTYPE_EXH) {
748                 topslot = TOP_IS_IN_ITMP1;
749         }
750
751         /* calculate base stack pointer */
752
753         basesp = sp + code_get_stack_frame_size(code);
754
755         /* create the source frame */
756
757         frame = DNEW(sourceframe_t);
758         frame->up = ss->frames;
759         frame->method = rp->method;
760         frame->id = rp->id;
761         frame->syncslotcount = 0;
762         frame->syncslots = NULL;
763 #if !defined(NDEBUG)
764         frame->debug_rp = rp;
765 #endif
766
767         ss->frames = frame;
768
769         /* read local variables */
770
771         count = m->maxlocals;
772         frame->javalocalcount = count;
773         frame->javalocals = DMNEW(u8, count);
774         frame->javalocaltype = DMNEW(u1, count);
775
776 #if !defined(NDEBUG)
777         /* mark values as undefined */
778         for (i=0; i<count; ++i) {
779                 frame->javalocals[i] = (u8) 0x00dead0000dead00ULL;
780                 frame->javalocaltype[i] = TYPE_VOID;
781         }
782
783         /* some entries in the intregs array are not meaningful */
784         /*es->intregs[REG_ITMP3] = (u8) 0x11dead1111dead11ULL;*/
785         es->intregs[REG_SP   ] = (u8) 0x11dead1111dead11ULL;
786 #ifdef REG_PV
787         es->intregs[REG_PV   ] = (u8) 0x11dead1111dead11ULL;
788 #endif
789 #endif /* !defined(NDEBUG) */
790
791         /* read javalocals */
792
793         count = rp->regalloccount;
794         ra = rp->regalloc;
795
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;
801                 else
802                         replace_read_value(es, sp, ra, frame->javalocals + i);
803                 ra++;
804                 count--;
805         }
806
807         /* read stack slots */
808
809         frame->javastackdepth = count;
810         frame->javastack = DMNEW(u8, count);
811         frame->javastacktype = DMNEW(u1, count);
812
813 #if !defined(NDEBUG)
814         /* mark values as undefined */
815         for (i=0; i<count; ++i) {
816                 frame->javastack[i] = (u8) 0x00dead0000dead00ULL;
817                 frame->javastacktype[i] = TYPE_VOID;
818         }
819 #endif /* !defined(NDEBUG) */
820
821         i = 0;
822
823         /* the first stack slot is special in SBR and EXH blocks */
824
825         if (topslot == TOP_IS_ON_STACK) {
826                 assert(count);
827
828                 assert(ra->index == RPLALLOC_STACK);
829                 frame->javastack[i] = sp[-1];
830                 frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
831                 count--;
832                 i++;
833                 ra++;
834         }
835         else if (topslot == TOP_IS_IN_ITMP1) {
836                 assert(count);
837
838                 assert(ra->index == RPLALLOC_STACK);
839                 frame->javastack[i] = es->intregs[REG_ITMP1];
840                 frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
841                 count--;
842                 i++;
843                 ra++;
844         }
845         else if (topslot == TOP_IS_VOID) {
846                 assert(count);
847
848                 assert(ra->index == RPLALLOC_STACK);
849                 frame->javastack[i] = 0;
850                 frame->javastacktype[i] = TYPE_VOID;
851                 count--;
852                 i++;
853                 ra++;
854         }
855
856         /* read remaining stack slots */
857
858         for (; count--; ra++) {
859                 if (ra->index == RPLALLOC_SYNC) {
860                         assert(rp->type == RPLPOINT_TYPE_INLINE);
861
862                         /* only read synchronization slots when traversing an inline point */
863
864                         if (!topframe) {
865                                 sourceframe_t *calleeframe = frame->up;
866                                 assert(calleeframe);
867                                 assert(calleeframe->syncslotcount == 0);
868                                 assert(calleeframe->syncslots == NULL);
869
870                                 calleeframe->syncslotcount = 1;
871                                 calleeframe->syncslots = DMNEW(u8, 1);
872                                 replace_read_value(es,sp,ra,calleeframe->syncslots);
873                         }
874
875                         frame->javastackdepth--;
876                         continue;
877                 }
878
879                 assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
880
881                 /* do not read parameters of calls down the call chain */
882
883                 if (!topframe && ra->index == RPLALLOC_PARAM) {
884                         frame->javastackdepth--;
885                 }
886                 else {
887                         if (ra->type == TYPE_RET)
888                                 frame->javastack[i] = ra->regoff;
889                         else
890                                 replace_read_value(es,sp,ra,frame->javastack + i);
891                         frame->javastacktype[i] = ra->type;
892                         i++;
893                 }
894         }
895 }
896
897
898 /* replace_write_executionstate ************************************************
899
900    Translate the given source state into an execution state.
901    
902    IN:
903        rp...............replacement point for which execution state should be
904                             creates
905            es...............where to put the execution state
906            ss...............the given source state
907
908    OUT:
909        *es..............the execution state derived from the source state
910   
911 *******************************************************************************/
912
913 static void replace_write_executionstate(rplpoint *rp,
914                                                                                  executionstate_t *es,
915                                                                                  sourcestate_t *ss,
916                                                                                  bool topframe)
917 {
918         methodinfo     *m;
919         codeinfo       *code;
920         int             count;
921         int             i;
922         rplalloc       *ra;
923         sourceframe_t  *frame;
924         int             topslot;
925         stackslot_t    *sp;
926         stackslot_t    *basesp;
927
928         code = rp->code;
929         m = rp->method;
930         topslot = TOP_IS_NORMAL;
931
932         /* pop a source frame */
933
934         frame = ss->frames;
935         assert(frame);
936         ss->frames = frame->up;
937
938         /* calculate stack pointer */
939
940         sp = (stackslot_t *) es->sp;
941
942         basesp = sp + code_get_stack_frame_size(code);
943
944         /* in some cases the top stack slot is passed in REG_ITMP1 */
945
946         if (rp->type == BBTYPE_EXH) {
947                 topslot = TOP_IS_IN_ITMP1;
948         }
949
950         /* write javalocals */
951
952         ra = rp->regalloc;
953         count = rp->regalloccount;
954
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 */
961                 }
962                 else
963                         replace_write_value(es, sp, ra, frame->javalocals + i);
964                 count--;
965                 ra++;
966         }
967
968         /* write stack slots */
969
970         i = 0;
971
972         /* the first stack slot is special in SBR and EXH blocks */
973
974         if (topslot == TOP_IS_ON_STACK) {
975                 assert(count);
976
977                 assert(ra->index == RPLALLOC_STACK);
978                 assert(i < frame->javastackdepth);
979                 assert(frame->javastacktype[i] == TYPE_ADR);
980                 sp[-1] = frame->javastack[i];
981                 count--;
982                 i++;
983                 ra++;
984         }
985         else if (topslot == TOP_IS_IN_ITMP1) {
986                 assert(count);
987
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];
992                 count--;
993                 i++;
994                 ra++;
995         }
996         else if (topslot == TOP_IS_VOID) {
997                 assert(count);
998
999                 assert(ra->index == RPLALLOC_STACK);
1000                 assert(i < frame->javastackdepth);
1001                 assert(frame->javastacktype[i] == TYPE_VOID);
1002                 count--;
1003                 i++;
1004                 ra++;
1005         }
1006
1007         /* write remaining stack slots */
1008
1009         for (; count--; ra++) {
1010                 if (ra->index == RPLALLOC_SYNC) {
1011                         assert(rp->type == RPLPOINT_TYPE_INLINE);
1012
1013                         /* only write synchronization slots when traversing an inline point */
1014
1015                         if (!topframe) {
1016                                 assert(frame->syncslotcount == 1); /* XXX need to understand more cases */
1017                                 assert(frame->syncslots != NULL);
1018
1019                                 replace_write_value(es,sp,ra,frame->syncslots);
1020                         }
1021                         continue;
1022                 }
1023
1024                 assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
1025
1026                 /* do not write parameters of calls down the call chain */
1027
1028                 if (!topframe && ra->index == RPLALLOC_PARAM) {
1029                         /* skip it */
1030                 }
1031                 else {
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 */
1036                         }
1037                         else {
1038                                 replace_write_value(es,sp,ra,frame->javastack + i);
1039                         }
1040                         i++;
1041                 }
1042         }
1043
1044         /* set new pc */
1045
1046         es->pc = rp->pc;
1047 }
1048
1049
1050 /* replace_pop_activation_record ***********************************************
1051
1052    Peel a stack frame from the execution state.
1053    
1054    *** This function imitates the effects of the method epilog ***
1055    *** and returning from the method call.                     ***
1056
1057    IN:
1058            es...............execution state
1059            frame............source frame, receives synchronization slots
1060
1061    OUT:
1062        *es..............the execution state after popping the stack frame
1063   
1064 *******************************************************************************/
1065
1066 bool replace_pop_activation_record(executionstate_t *es,
1067                                                                    sourceframe_t *frame)
1068 {
1069         u1 *ra;
1070         u1 *pv;
1071         s4 reg;
1072         s4 i;
1073         s4 count;
1074         codeinfo *code;
1075         stackslot_t *basesp;
1076         stackslot_t *sp;
1077
1078         assert(es->code);
1079         assert(frame);
1080
1081         /* read the return address */
1082
1083         ra = md_stacktrace_get_returnaddress(es->sp,
1084                         SIZE_OF_STACKSLOT * es->code->stackframesize);
1085
1086         DOLOG( printf("return address: %p\n", (void*)ra); );
1087
1088         /* find the new codeinfo */
1089
1090         pv = md_codegen_get_pv_from_pc(ra);
1091
1092         DOLOG( printf("PV = %p\n", (void*) pv); );
1093
1094         if (pv == NULL)
1095                 return false;
1096
1097         code = *(codeinfo **)(pv + CodeinfoPointer);
1098
1099         DOLOG( printf("CODE = %p\n", (void*) code); );
1100
1101         if (code == NULL)
1102                 return false;
1103
1104         /* calculate the base of the stack frame */
1105
1106         sp = (stackslot_t *) es->sp;
1107         basesp = sp + es->code->stackframesize;
1108
1109         /* read slots used for synchronization */
1110
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];
1118         }
1119
1120         /* restore saved int registers */
1121
1122         reg = INT_REG_CNT;
1123         for (i=0; i<es->code->savedintcount; ++i) {
1124                 while (nregdescint[--reg] != REG_SAV)
1125                         ;
1126                 es->intregs[reg] = *--basesp;
1127         }
1128
1129         /* restore saved flt registers */
1130
1131         /* XXX align? */
1132         reg = FLT_REG_CNT;
1133         for (i=0; i<es->code->savedfltcount; ++i) {
1134                 while (nregdescfloat[--reg] != REG_SAV)
1135                         ;
1136                 basesp -= STACK_SLOTS_PER_FLOAT;
1137                 es->fltregs[reg] = *(u8*)basesp;
1138         }
1139
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.             */
1142
1143         es->pc = ra - 1;
1144
1145         /* adjust the stackpointer */
1146
1147         es->sp += SIZE_OF_STACKSLOT * es->code->stackframesize;
1148         es->sp += SIZE_OF_STACKSLOT; /* skip return address */
1149
1150         es->pv = pv;
1151         es->code = code;
1152
1153 #if !defined(NDEBUG)
1154         /* for debugging */
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) */
1162
1163         return true;
1164 }
1165
1166
1167 /* replace_push_activation_record **********************************************
1168
1169    Push a stack frame onto the execution state.
1170    
1171    *** This function imitates the effects of a call and the ***
1172    *** method prolog of the callee.                         ***
1173
1174    IN:
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
1179
1180    OUT:
1181        *es..............the execution state after pushing the stack frame
1182   
1183 *******************************************************************************/
1184
1185 void replace_push_activation_record(executionstate_t *es,
1186                                                                         rplpoint *rpcall,
1187                                                                         codeinfo *calleecode,
1188                                                                         sourceframe_t *frame)
1189 {
1190         s4 reg;
1191         s4 i;
1192         s4 count;
1193         stackslot_t *basesp;
1194         stackslot_t *sp;
1195
1196         assert(es);
1197         assert(rpcall && rpcall->type == RPLPOINT_TYPE_CALL);
1198         assert(calleecode);
1199         assert(frame);
1200
1201         /* write the return address */
1202
1203         es->sp -= SIZE_OF_STACKSLOT;
1204
1205         DOLOG( printf("writing return address %p to %p\n",
1206                                 (void*) (rpcall->pc + rpcall->callsize),
1207                                 (void*) es->sp); );
1208
1209         *((stackslot_t *)es->sp) = (stackslot_t) (rpcall->pc + rpcall->callsize);
1210
1211         /* we move into a new code unit */
1212
1213         es->code = calleecode;
1214
1215         /* set the new pc XXX not needed */
1216
1217         es->pc = es->code->entrypoint;
1218
1219         /* build the stackframe */
1220
1221         DOLOG( printf("building stackframe of %d words at %p\n",
1222                                 es->code->stackframesize, (void*)es->sp); );
1223
1224         sp = (stackslot_t *) es->sp;
1225         basesp = sp;
1226
1227         sp -= es->code->stackframesize;
1228         es->sp = (u1*) sp;
1229
1230         /* in debug mode, invalidate stack frame first */
1231
1232 #if !defined(NDEBUG)
1233         for (i=0; i<(basesp - sp); ++i) {
1234                 sp[i] = 0xdeaddeadU;
1235         }
1236 #endif
1237
1238         /* save int registers */
1239
1240         reg = INT_REG_CNT;
1241         for (i=0; i<es->code->savedintcount; ++i) {
1242                 while (nregdescint[--reg] != REG_SAV)
1243                         ;
1244                 *--basesp = es->intregs[reg];
1245
1246 #if !defined(NDEBUG)
1247                 es->intregs[reg] = 0x44dead4444dead44ULL;
1248 #endif
1249         }
1250
1251         /* save flt registers */
1252
1253         /* XXX align? */
1254         reg = FLT_REG_CNT;
1255         for (i=0; i<es->code->savedfltcount; ++i) {
1256                 while (nregdescfloat[--reg] != REG_SAV)
1257                         ;
1258                 basesp -= STACK_SLOTS_PER_FLOAT;
1259                 *(u8*)basesp = es->fltregs[reg];
1260
1261 #if !defined(NDEBUG)
1262                 es->fltregs[reg] = 0x44dead4444dead44ULL;
1263 #endif
1264         }
1265
1266         /* write slots used for synchronization */
1267
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];
1272         }
1273
1274         /* set the PV */
1275
1276         es->pv = es->code->entrypoint;
1277 }
1278
1279
1280 /* replace_find_replacement_point **********************************************
1281
1282    Find the replacement point in the given code corresponding to the
1283    position given in the source frame.
1284    
1285    IN:
1286            code.............the codeinfo in which to search the rplpoint
1287            ss...............the source state defining the position to look for
1288
1289    RETURN VALUE:
1290        the replacement point
1291   
1292 *******************************************************************************/
1293
1294 rplpoint * replace_find_replacement_point(codeinfo *code, sourcestate_t *ss)
1295 {
1296         sourceframe_t *frame;
1297         methodinfo *m;
1298         rplpoint *rp;
1299         s4        i;
1300         s4        j;
1301         s4        stacki;
1302         rplalloc *ra;
1303
1304         assert(ss);
1305
1306         frame = ss->frames;
1307         assert(frame);
1308
1309         DOLOG( printf("searching replacement point for:\n");
1310                    replace_source_frame_println(frame); );
1311
1312         m = frame->method;
1313
1314         DOLOG( printf("code = %p\n", (void*)code); );
1315
1316         rp = code->rplpoints;
1317         i = code->rplpointcount;
1318         while (i--) {
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); );
1324                         ra = rp->regalloc;
1325                         stacki = 0;
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)
1331                                                         goto no_match;
1332                                                 stacki++;
1333                                         }
1334                                         else {
1335                                                 assert(ra->index >= 0 && ra->index < frame->javalocalcount);
1336                                                 if (frame->javalocals[ra->index] != ra->regoff)
1337                                                         goto no_match;
1338                                         }
1339                                 }
1340                         }
1341
1342                         /* found */
1343                         return rp;
1344                 }
1345 no_match:
1346                 rp++;
1347         }
1348
1349         assert(0);
1350         return NULL; /* NOT REACHED */
1351 }
1352
1353
1354 /* replace_me ******************************************************************
1355  
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.
1359
1360    This function never returns!
1361   
1362    IN:
1363        rp...............replacement point that has been reached
1364            es...............execution state read by asm_replacement_out
1365   
1366 *******************************************************************************/
1367
1368 void replace_me(rplpoint *rp, executionstate_t *es)
1369 {
1370         rplpoint     *target;
1371         sourcestate_t ss;
1372         s4            dumpsize;
1373         rplpoint     *candidate;
1374         codeinfo     *code;
1375         s4            i;
1376
1377         es->code = rp->code;
1378
1379         DOLOG( printf("REPLACING: "); method_println(es->code->m); );
1380
1381         /* mark start of dump memory area */
1382
1383         dumpsize = dump_size();
1384
1385         /* fetch the target of the replacement */
1386
1387         target = rp->target;
1388
1389         /* XXX DEBUG turn off self-replacement */
1390         if (target == rp)
1391                 replace_deactivate_replacement_point(rp);
1392
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); );
1396
1397         /* read execution state of old code */
1398
1399         ss.frames = NULL;
1400
1401         /* XXX testing */
1402
1403         candidate = rp;
1404         do {
1405                 DOLOG( printf("recovering source state for%s:\n",
1406                                         (ss.frames == NULL) ? " TOPFRAME" : "");
1407                            replace_replacement_point_println(candidate, 1); );
1408
1409                 replace_read_executionstate(candidate, es, &ss, ss.frames == NULL);
1410
1411                 if (candidate->parent) {
1412                         DOLOG( printf("INLINED!\n"); );
1413                         candidate = candidate->parent;
1414                         assert(candidate->type == RPLPOINT_TYPE_INLINE);
1415                 }
1416                 else {
1417                         DOLOG( printf("UNWIND\n"); );
1418                         if (!replace_pop_activation_record(es, ss.frames)) {
1419                                 DOLOG( printf("BREAKING\n"); );
1420                                 break;
1421                         }
1422                         DOLOG( replace_executionstate_println(es); );
1423                         candidate = NULL;
1424                         rp = es->code->rplpoints;
1425                         for (i=0; i<es->code->rplpointcount; ++i, ++rp)
1426                                 if (rp->pc <= es->pc)
1427                                         candidate = rp;
1428                         if (!candidate)
1429                                 DOLOG( printf("NO CANDIDATE!\n"); );
1430                         else {
1431                                 DOLOG( printf("found replacement point.\n");
1432                                            replace_replacement_point_println(candidate, 1); );
1433                                 assert(candidate->type == RPLPOINT_TYPE_CALL);
1434                         }
1435                 }
1436         } while (candidate);
1437
1438         DOLOG( replace_sourcestate_println(&ss); );
1439
1440         /* write execution state of new code */
1441
1442         DOLOG( replace_executionstate_println(es); );
1443
1444         code = es->code;
1445
1446         /* XXX get new code */
1447
1448         while (ss.frames) {
1449
1450                 candidate = replace_find_replacement_point(code, &ss);
1451
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); );
1456
1457                 replace_write_executionstate(candidate, es, &ss, ss.frames->up == NULL);
1458                 if (ss.frames == NULL)
1459                         break;
1460                 DOLOG( replace_executionstate_println(es); );
1461
1462                 if (candidate->type == RPLPOINT_TYPE_CALL) {
1463                         jit_recompile(ss.frames->method);
1464                         code = ss.frames->method->code;
1465                         assert(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);
1469                 }
1470                 DOLOG( replace_executionstate_println(es); );
1471         }
1472
1473         DOLOG( replace_executionstate_println(es); );
1474
1475         /* release dump area */
1476
1477         dump_release(dumpsize);
1478
1479         /* enter new code */
1480
1481         DOLOG( printf("JUMPING IN!\n"); fflush(stdout); );
1482
1483 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
1484         asm_replacement_in(es);
1485 #endif
1486         abort(); /* NOT REACHED */
1487 }
1488
1489
1490 /* replace_replacement_point_println *******************************************
1491  
1492    Print replacement point info.
1493   
1494    IN:
1495        rp...............the replacement point to print
1496   
1497 *******************************************************************************/
1498
1499 #if !defined(NDEBUG)
1500
1501 #define TYPECHAR(t)  (((t) >= 0 && (t) <= TYPE_RET) ? show_jit_type_letters[t] : '?')
1502
1503 static char *replace_type_str[] = {
1504         "STD",
1505         "EXH",
1506         "SBR",
1507         "CALL",
1508         "INLINE",
1509         "RETURN"
1510 };
1511
1512 void replace_replacement_point_println(rplpoint *rp, int depth)
1513 {
1514         int j;
1515         int index;
1516
1517         if (!rp) {
1518                 printf("(rplpoint *)NULL\n");
1519                 return;
1520         }
1521
1522         for (j=0; j<depth; ++j)
1523                 putchar('\t');
1524
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,
1528                         (void*)rp->parent);
1529         for (j=0; j<depth; ++j)
1530                 putchar('\t');
1531         printf("ra:%d = [",     rp->regalloccount);
1532
1533         for (j=0; j<rp->regalloccount; ++j) {
1534                 if (j)
1535                         putchar(' ');
1536                 index = rp->regalloc[j].index;
1537                 switch (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);
1542                 }
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);
1546                 }
1547                 else {
1548                         show_allocation(rp->regalloc[j].type, rp->regalloc[j].flags, rp->regalloc[j].regoff);
1549                 }
1550         }
1551
1552         printf("]\n");
1553         for (j=0; j<depth; ++j)
1554                 putchar('\t');
1555         printf("method: ");
1556         method_print(rp->method);
1557
1558         printf("\n");
1559 }
1560 #endif
1561
1562
1563 /* replace_show_replacement_points *********************************************
1564  
1565    Print replacement point info.
1566   
1567    IN:
1568        code.............codeinfo whose replacement points should be printed.
1569   
1570 *******************************************************************************/
1571
1572 #if !defined(NDEBUG)
1573 void replace_show_replacement_points(codeinfo *code)
1574 {
1575         int i;
1576         int depth;
1577         rplpoint *rp;
1578         rplpoint *parent;
1579
1580         if (!code) {
1581                 printf("(codeinfo *)NULL\n");
1582                 return;
1583         }
1584
1585         printf("\treplacement points: %d\n",code->rplpointcount);
1586
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);
1591
1592         printf("\n");
1593
1594         for (i=0; i<code->rplpointcount; ++i) {
1595                 rp = code->rplpoints + i;
1596
1597                 assert(rp->code == code);
1598
1599                 depth = 1;
1600                 parent = rp->parent;
1601                 while (parent) {
1602                         depth++;
1603                         parent = parent->parent;
1604                 }
1605                 replace_replacement_point_println(rp, depth);
1606         }
1607 }
1608 #endif
1609
1610
1611 /* replace_executionstate_println **********************************************
1612  
1613    Print execution state
1614   
1615    IN:
1616        es...............the execution state to print
1617   
1618 *******************************************************************************/
1619
1620 #if !defined(NDEBUG)
1621 void replace_executionstate_println(executionstate_t *es)
1622 {
1623         int i;
1624         int slots;
1625         stackslot_t *sp;
1626         int extraslots;
1627         
1628         if (!es) {
1629                 printf("(executionstate_t *)NULL\n");
1630                 return;
1631         }
1632
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) {
1639                 if (i%4 == 0)
1640                         printf("\t");
1641                 else
1642                         printf(" ");
1643                 printf("%-3s = %016llx",regs[i],(unsigned long long)es->intregs[i]);
1644                 if (i%4 == 3)
1645                         printf("\n");
1646         }
1647         for (i=0; i<FLT_REG_CNT; ++i) {
1648                 if (i%4 == 0)
1649                         printf("\t");
1650                 else
1651                         printf(" ");
1652                 printf("F%02d = %016llx",i,(unsigned long long)es->fltregs[i]);
1653                 if (i%4 == 3)
1654                         printf("\n");
1655         }
1656 #endif
1657
1658         sp = (stackslot_t *) es->sp;
1659
1660         extraslots = 2;
1661
1662         if (es->code) {
1663                 methoddesc *md = es->code->m->parseddesc;
1664                 slots = code_get_stack_frame_size(es->code);
1665                 extraslots = 1 + md->memuse;
1666         }
1667         else
1668                 slots = 0;
1669
1670
1671         if (slots) {
1672                 printf("\tstack slots(+%d) at sp:", extraslots);
1673                 for (i=0; i<slots+extraslots; ++i) {
1674                         if (i%4 == 0)
1675                                 printf("\n\t\t");
1676                         printf("M%02d%c", i, (i >= slots) ? '(' : ' ');
1677 #ifdef HAS_4BYTE_STACKSLOT
1678                         printf("%08lx",(unsigned long)*sp++);
1679 #else
1680                         printf("%016llx",(unsigned long long)*sp++);
1681 #endif
1682                         printf("%c", (i >= slots) ? ')' : ' ');
1683                 }
1684                 printf("\n");
1685         }
1686
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);
1691         }
1692         printf("\n");
1693
1694         printf("\n");
1695 }
1696 #endif
1697
1698 #if !defined(NDEBUG)
1699 void java_value_print(s4 type, u8 value)
1700 {
1701         java_objectheader *obj;
1702         utf               *u;
1703
1704         printf("%016llx",(unsigned long long) value);
1705
1706         if (type < 0 || type > TYPE_RET)
1707                 printf(" <INVALID TYPE:%d>", type);
1708         else
1709                 printf(" %s", show_jit_type_names[type]);
1710
1711         if (type == TYPE_ADR && value != 0) {
1712                 obj = (java_objectheader *) (ptrint) value;
1713                 putchar(' ');
1714                 utf_display_printable_ascii_classname(obj->vftbl->class->name);
1715
1716                 if (obj->vftbl->class == class_java_lang_String) {
1717                         printf(" \"");
1718                         u = javastring_toutf((java_lang_String *)obj, false);
1719                         utf_display_printable_ascii(u);
1720                         printf("\"");
1721                 }
1722         }
1723         else if (type == TYPE_INT || type == TYPE_LNG) {
1724                 printf(" %lld", (long long) value);
1725         }
1726 }
1727 #endif /* !defined(NDEBUG) */
1728
1729
1730 #if !defined(NDEBUG)
1731 void replace_source_frame_println(sourceframe_t *frame)
1732 {
1733         s4 i;
1734         s4 t;
1735
1736         printf("\t");
1737         method_println(frame->method);
1738         printf("\tid: %d\n", frame->id);
1739         printf("\n");
1740
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);
1747                         }
1748                         else {
1749                                 printf("\tlocal[%c%2d] = ",TYPECHAR(t),i);
1750                                 java_value_print(t, frame->javalocals[i]);
1751                                 printf("\n");
1752                         }
1753                 }
1754                 printf("\n");
1755         }
1756
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);
1763                         }
1764                         else {
1765                                 printf("\tstack[%2d] = ",i);
1766                                 java_value_print(frame->javastacktype[i], frame->javastack[i]);
1767                                 printf("\n");
1768                         }
1769                 }
1770                 printf("\n");
1771         }
1772
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]);
1779 #else
1780                         printf("%016llx\n",(unsigned long long) frame->syncslots[i]);
1781 #endif
1782                 }
1783                 printf("\n");
1784         }
1785 }
1786 #endif /* !defined(NDEBUG) */
1787
1788
1789 /* replace_sourcestate_println *************************************************
1790  
1791    Print source state
1792   
1793    IN:
1794        ss...............the source state to print
1795   
1796 *******************************************************************************/
1797
1798 #if !defined(NDEBUG)
1799 void replace_sourcestate_println(sourcestate_t *ss)
1800 {
1801         int i;
1802         sourceframe_t *frame;
1803
1804         if (!ss) {
1805                 printf("(sourcestate_t *)NULL\n");
1806                 return;
1807         }
1808
1809         printf("sourcestate_t:\n");
1810
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);
1814         }
1815 }
1816 #endif
1817
1818 /*
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  * ---------------------------------------------------------------------
1823  * Local variables:
1824  * mode: c
1825  * indent-tabs-mode: t
1826  * c-basic-offset: 4
1827  * tab-width: 4
1828  * End:
1829  * vim:noexpandtab:sw=4:ts=4:
1830  */