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