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