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