* src/vm/jit/code.c (code_codeinfo_new): Commented.
[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 "mm/memory.h"
42 #include "toolbox/logging.h"
43 #include "vm/options.h"
44 #include "vm/jit/jit.h"
45 #include "vm/jit/replace.h"
46 #include "vm/jit/asmpart.h"
47 #include "vm/jit/disass.h"
48 #include "arch.h"
49
50 /* replace_create_replacement_points *******************************************
51  
52    Create the replacement points for the given code.
53   
54    IN:
55        code.............codeinfo where replacement points should be stored
56                             code->rplpoints must be NULL.
57                                                 code->rplpointcount must be 0.
58            rd...............registerdata containing allocation info.
59   
60    OUT:
61        code->rplpoints.......set to the list of replacement points
62            code->rplpointcount...number of replacement points
63            code->regalloc........list of allocation info
64            code->regalloccount...total length of allocation info list
65            code->globalcount.....number of global allocations at the
66                                  start of code->regalloc
67   
68    RETURN VALUE:
69        true.............everything ok 
70        false............an exception has been thrown
71    
72 *******************************************************************************/
73
74 bool replace_create_replacement_points(codeinfo *code,registerdata *rd)
75 {
76         basicblock *bptr;
77         int count;
78         methodinfo *m;
79         rplpoint *rplpoints;
80         rplpoint *rp;
81         int alloccount;
82         int globalcount;
83         rplalloc *regalloc;
84         rplalloc *ra;
85         int i;
86         int t;
87         stackptr sp;
88         bool indexused;
89
90         /* assert that we wont overwrite already allocated data */
91         
92         assert(code);
93         assert(code->m);
94         assert(code->rplpoints == NULL);
95         assert(code->rplpointcount == 0);
96         assert(code->regalloc == NULL);
97         assert(code->regalloccount == 0);
98         assert(code->globalcount == 0);
99
100         /* iterate over the basic block list to find replacement points */
101
102         m = code->m;
103
104         count = 0;
105         alloccount = 0;
106         for (bptr = m->basicblocks; bptr; bptr = bptr->next) {
107                 if (!(bptr->bitflags & BBFLAG_REPLACEMENT))
108                         continue;
109
110                 /* there will be a replacement point at the start of this block */
111                 
112                 count++;
113                 alloccount += bptr->indepth;
114         }
115
116         /* if no points were found, there's nothing to do */
117         
118         if (!count)
119                 return true;
120
121         /* count global register allocations */
122
123         globalcount = 0;
124
125         for (i=0; i<m->maxlocals; ++i) {
126                 indexused = false;
127                 for (t=0; t<5; ++t) {
128 #if defined(ENABLE_INTRP)
129                         if (!opt_intrp) {
130 #endif
131                                 if (rd->locals[i][t].type == t) {
132                                         globalcount++;
133                                         indexused = true;
134                                 }
135 #if defined(ENABLE_INTRP)
136                         }
137 #endif
138                 }
139                 if (!indexused)
140                         globalcount++; /* dummy rplalloc */
141         }
142
143         alloccount += globalcount;
144
145         /* allocate replacement point array and allocation array */
146         
147         rplpoints = MNEW(rplpoint,count);
148         regalloc = MNEW(rplalloc,alloccount);
149         ra = regalloc;
150
151         /* store global register allocations */
152
153         for (i=0; i<m->maxlocals; ++i) {
154                 indexused = false;
155                 for (t=0; t<5; ++t) {
156 #if defined(ENABLE_INTRP)
157                         if (!opt_intrp) {
158 #endif
159                                 if (rd->locals[i][t].type == t) {
160                                         ra->flags = rd->locals[i][t].flags & (INMEMORY);
161                                         ra->index = rd->locals[i][t].regoff;
162                                         ra->type  = t;
163                                         ra->next = (indexused) ? 0 : 1;
164                                         ra++;
165                                         indexused = true;
166                                 }
167 #if defined(ENABLE_INTRP)
168                         }
169 #endif
170                 }
171                 if (!indexused) {
172                         /* dummy rplalloc */
173                         ra->type = -1;
174                         ra->flags = 0;
175                         ra->index = 0;
176                         ra->next = 1;
177                         ra++;
178                 }
179         }
180
181         /* initialize replacement point structs */
182
183         rp = rplpoints;
184         for (bptr = m->basicblocks; bptr; bptr = bptr->next) {
185                 if (!(bptr->bitflags & BBFLAG_REPLACEMENT))
186                         continue;
187
188                 /* there will be a replacement point at the start of this block */
189
190                 rp->pc = NULL;        /* set by codegen */
191                 rp->outcode = NULL;   /* set by codegen */
192                 rp->code = code;
193                 rp->target = NULL;
194                 rp->regalloc = ra;
195                 rp->flags = 0;
196                 rp->type = bptr->type;
197
198                 /* store local allocation info */
199
200                 for (sp = bptr->instack; sp; sp = sp->prev) {
201                         ra->flags = sp->flags & (INMEMORY);
202                         ra->index = sp->regoff;
203                         ra->type  = sp->type;
204                         ra->next  = 1;
205                         ra++;
206                 }
207
208                 rp->regalloccount = ra - rp->regalloc;
209                 
210                 rp++;
211         }
212
213         /* store the data in the codeinfo */
214
215         code->rplpoints = rplpoints;
216         code->rplpointcount = count;
217         code->regalloc = regalloc;
218         code->regalloccount = alloccount;
219         code->globalcount = globalcount;
220         code->savedintcount = INT_SAV_CNT - rd->savintreguse;
221         code->savedfltcount = FLT_SAV_CNT - rd->savfltreguse;
222         code->memuse = rd->memuse;
223
224         /* everything alright */
225
226         return true;
227 }
228
229 /* replace_free_replacement_points *********************************************
230  
231    Free memory used by replacement points.
232   
233    IN:
234        code.............codeinfo whose replacement points should be freed.
235   
236 *******************************************************************************/
237
238 void replace_free_replacement_points(codeinfo *code)
239 {
240         assert(code);
241
242         if (code->rplpoints)
243                 MFREE(code->rplpoints,rplpoint,code->rplpointcount);
244
245         if (code->regalloc)
246                 MFREE(code->regalloc,rplalloc,code->regalloccount);
247
248         code->rplpoints = NULL;
249         code->rplpointcount = 0;
250         code->regalloc = NULL;
251         code->regalloccount = 0;
252         code->globalcount = 0;
253 }
254
255 /* replace_activate_replacement_point ******************************************
256  
257    Activate a replacement point. When this function returns, the
258    replacement point is "armed", that is each thread reaching this point
259    will be replace to `target`.
260    
261    IN:
262        rp...............replacement point to activate
263            target...........target of replacement
264   
265 *******************************************************************************/
266
267 void replace_activate_replacement_point(rplpoint *rp,rplpoint *target)
268 {
269         assert(rp->target == NULL);
270         
271 #ifndef NDEBUG
272         printf("activate replacement point: ");
273         replace_replacement_point_println(rp);
274         fflush(stdout);
275 #endif
276         
277         rp->target = target;
278         
279 #if (defined(__I386__) || defined(__X86_64__)) && defined(ENABLE_JIT)
280         md_patch_replacement_point(rp);
281 #endif
282 }
283
284 /* replace_deactivate_replacement_point ****************************************
285  
286    Deactivate a replacement point. When this function returns, the
287    replacement point is "un-armed", that is a each thread reaching this point
288    will just continue normally.
289    
290    IN:
291        rp...............replacement point to deactivate
292   
293 *******************************************************************************/
294
295 void replace_deactivate_replacement_point(rplpoint *rp)
296 {
297         assert(rp->target);
298         
299 #ifndef NDEBUG
300         printf("deactivate replacement point: ");
301         replace_replacement_point_println(rp);
302         fflush(stdout);
303 #endif
304         
305         rp->target = NULL;
306         
307 #if (defined(__I386__) || defined(__X86_64__)) && defined(ENABLE_JIT)
308         md_patch_replacement_point(rp);
309 #endif
310 }
311
312 /* replace_read_executionstate *************************************************
313
314    Read the given executions state and translate it to a source state.
315    
316    IN:
317        rp...............replacement point at which `es` was taken
318            es...............execution state
319            ss...............where to put the source state
320
321    OUT:
322        *ss..............the source state derived from the execution state
323   
324 *******************************************************************************/
325
326 static void replace_read_executionstate(rplpoint *rp,executionstate *es,
327                                                                          sourcestate *ss)
328 {
329         methodinfo *m;
330         codeinfo *code;
331         int count;
332         int i;
333         int t;
334         int allocs;
335         rplalloc *ra;
336         methoddesc *md;
337 #ifdef HAS_4BYTE_STACKSLOT
338         u4 *sp;
339         u4 *basesp;
340 #else
341         u8 *sp;
342         u8 *basesp;
343 #endif
344
345         code = rp->code;
346         m = code->m;
347         md = m->parseddesc;
348
349         /* calculate stack pointers */
350
351 #ifdef HAS_4BYTE_STACKSLOT
352         sp = (u4*) es->sp;
353 #else
354         sp = (u8*) es->sp;
355 #endif
356
357         /* XXX only on i386? */
358         if (rp->type == BBTYPE_SBR)
359                 sp++;
360         
361         basesp = sp + code_get_stack_frame_size(code);
362
363         /* read local variables */
364
365         count = m->maxlocals;
366         ss->javalocalcount = count;
367         ss->javalocals = DMNEW(u8,count * 5);
368
369 #ifndef NDEBUG
370         /* mark values as undefined */
371         for (i=0; i<count*5; ++i)
372                 ss->javalocals[i] = (u8) 0x00dead0000dead00ULL;
373 #endif
374         
375         ra = code->regalloc;
376
377         i = -1;
378         for (allocs = code->globalcount; allocs--; ra++) {
379                 if (ra->next)
380                         i++;
381                 t = ra->type;
382                 if (t == -1)
383                         continue; /* dummy rplalloc */
384
385 #ifdef HAS_4BYTE_STACKSLOT
386                 if (IS_2_WORD_TYPE(ra->type)) {
387                         if (ra->flags & INMEMORY) {
388                                 ss->javalocals[i*5+t] = *(u8*)(sp + ra->index);
389                         }
390                         else {
391                                 dolog("XXX split 2-word types in registers are not supported");
392                                 assert(0);
393                         }
394                 }
395                 else {
396 #endif
397                         if (ra->flags & INMEMORY) {
398                                 ss->javalocals[i*5+t] = sp[ra->index];
399                         }
400                         else {
401                                 ss->javalocals[i*5+t] = es->intregs[ra->index];
402                         }
403 #ifdef HAS_4BYTE_STACKSLOT
404                 }
405 #endif
406         }
407
408         /* read stack slots */
409
410         count = rp->regalloccount;
411         ss->javastackdepth = count;
412         ss->javastack = DMNEW(u8,count);
413
414         i = 0;
415         ra = rp->regalloc;
416
417         /* the first stack slot is special in SBR and EXH blocks */
418
419         if (rp->type == BBTYPE_SBR) {
420                 assert(count);
421                 
422                 ss->javastack[i] = sp[-1];
423                 count--;
424                 i++;
425                 ra++;
426         }
427         else if (rp->type == BBTYPE_EXH) {
428                 assert(count);
429
430                 ss->javastack[i] = es->intregs[REG_ITMP1]; /* XXX all platforms? */
431                 count--;
432                 i++;
433                 ra++;
434         }
435         
436         for (; count--; ra++, i++) {
437                 assert(ra->next);
438
439                 if (ra->flags & INMEMORY) {
440                         ss->javastack[i] = sp[ra->index];
441                 }
442                 else {
443                         ss->javastack[i] = es->intregs[ra->index];
444                 }
445         }
446
447         /* read unused callee saved int regs */
448         
449         count = INT_SAV_CNT;
450         for (i=0; count > code->savedintcount; ++i) {
451                 assert(i < INT_REG_CNT);
452                 if (nregdescint[i] == REG_SAV)
453                         ss->savedintregs[--count] = es->intregs[i];
454         }
455
456         /* read saved int regs */
457
458         for (i=0; i<code->savedintcount; ++i) {
459                 ss->savedintregs[i] = *--basesp;
460         }
461
462         /* read saved flt regs */
463
464         for (i=0; i<code->savedfltcount; ++i) {
465 #ifdef HAS_4BYTE_STACKSLOT
466                 basesp -= 2;
467 #else
468                 basesp--;
469 #endif
470                 ss->savedfltregs[i] = *(u8*)basesp;
471         }
472
473         /* read unused callee saved flt regs */
474         
475         count = FLT_SAV_CNT;
476         for (i=0; count > code->savedfltcount; ++i) {
477                 assert(i < FLT_REG_CNT);
478                 if (nregdescfloat[i] == REG_SAV)
479                         ss->savedfltregs[--count] = es->fltregs[i];
480         }
481
482         /* read slots used for synchronization */
483
484         count = code_get_sync_slot_count(code);
485         ss->syncslotcount = count;
486         ss->syncslots = DMNEW(u8,count);
487         for (i=0; i<count; ++i) {
488                 ss->syncslots[i] = *--basesp;
489         }
490 }
491
492 /* replace_write_executionstate ************************************************
493
494    Translate the given source state into an execution state.
495    
496    IN:
497        rp...............replacement point for which execution state should be
498                             creates
499            es...............where to put the execution state
500            ss...............the given source state
501
502    OUT:
503        *es..............the execution state derived from the source state
504   
505 *******************************************************************************/
506
507 static void replace_write_executionstate(rplpoint *rp,executionstate *es,sourcestate *ss)
508 {
509         methodinfo *m;
510         codeinfo *code;
511         int count;
512         int i;
513         int t;
514         int allocs;
515         rplalloc *ra;
516         methoddesc *md;
517 #ifdef HAS_4BYTE_STACKSLOT
518         u4 *sp;
519         u4 *basesp;
520 #else
521         u8 *sp;
522         u8 *basesp;
523 #endif
524
525         code = rp->code;
526         m = code->m;
527         md = m->parseddesc;
528         
529         /* calculate stack pointers */
530
531 #ifdef HAS_4BYTE_STACKSLOT
532         sp = (u4*) es->sp;
533 #else
534         sp = (u8*) es->sp;
535 #endif
536
537         if (rp->type == BBTYPE_SBR)
538                 sp++;
539         
540         basesp = sp + code_get_stack_frame_size(code);
541
542         /* in debug mode, invalidate stack frame first */
543
544 #ifndef NDEBUG
545         for (i=0; i<(basesp - sp); ++i) {
546                 sp[i] = 0xdeaddeadU;
547         }
548 #endif
549
550         /* write local variables */
551
552         count = m->maxlocals;
553
554         ra = code->regalloc;
555
556         i = -1;
557         for (allocs = code->globalcount; allocs--; ra++) {
558                 if (ra->next)
559                         i++;
560
561                 assert(i >= 0 && i < m->maxlocals);
562                 
563                 t = ra->type;
564                 if (t == -1)
565                         continue; /* dummy rplalloc */
566
567 #ifdef HAS_4BYTE_STACKSLOT
568                 if (IS_2_WORD_TYPE(ra->type)) {
569                         if (ra->flags & INMEMORY) {
570                                 *(u8*)(sp + ra->index) = ss->javalocals[i*5+t];
571                         }
572                         else {
573                                 dolog("XXX split 2-word types in registers are not supported");
574                                 assert(0);
575                         }
576                 }
577                 else {
578 #endif
579                         if (ra->flags & INMEMORY) {
580                                 sp[ra->index] = ss->javalocals[i*5+t];
581                         }
582                         else {
583                                 es->intregs[ra->index] = ss->javalocals[i*5+t];
584                         }
585 #ifdef HAS_4BYTE_STACKSLOT
586                 }
587 #endif
588         }
589
590         /* write stack slots */
591
592         count = rp->regalloccount;
593
594         i = 0;
595         ra = rp->regalloc;
596
597         /* the first stack slot is special in SBR and EXH blocks */
598
599         if (rp->type == BBTYPE_SBR) {
600                 assert(count);
601                 
602                 sp[-1] = ss->javastack[i];
603                 count--;
604                 i++;
605                 ra++;
606         }
607         else if (rp->type == BBTYPE_EXH) {
608                 assert(count);
609
610                 es->intregs[REG_ITMP1] = ss->javastack[i]; /* XXX all platforms? */
611                 count--;
612                 i++;
613                 ra++;
614         }
615         
616         for (; count--; ra++, i++) {
617                 assert(ra->next);
618
619                 if (ra->flags & INMEMORY) {
620                         sp[ra->index] = ss->javastack[i];
621                 }
622                 else {
623                         es->intregs[ra->index] = ss->javastack[i];
624                 }
625         }
626         
627         /* write unused callee saved int regs */
628         
629         count = INT_SAV_CNT;
630         for (i=0; count > code->savedintcount; ++i) {
631                 assert(i < INT_REG_CNT);
632                 if (nregdescint[i] == REG_SAV)
633                         es->intregs[i] = ss->savedintregs[--count];
634         }
635
636         /* write saved int regs */
637
638         for (i=0; i<code->savedintcount; ++i) {
639                 *--basesp = ss->savedintregs[i];
640         }
641
642         /* write unused callee saved flt regs */
643         
644         count = FLT_SAV_CNT;
645         for (i=0; count > code->savedfltcount; ++i) {
646                 assert(i < FLT_REG_CNT);
647                 if (nregdescfloat[i] == REG_SAV)
648                         es->fltregs[i] = ss->savedfltregs[--count];
649         }
650
651         /* write saved flt regs */
652
653         for (i=0; i<code->savedfltcount; ++i) {
654 #ifdef HAS_4BYTE_STACKSLOT
655                 basesp -= 2;
656 #else
657                 basesp--;
658 #endif
659                 *(u8*)basesp = ss->savedfltregs[i];
660         }
661
662         /* write slots used for synchronization */
663
664         count = code_get_sync_slot_count(code);
665         assert(count == ss->syncslotcount);
666         for (i=0; i<count; ++i) {
667                 *--basesp = ss->syncslots[i];
668         }
669
670         /* set new pc */
671
672         es->pc = rp->pc;
673 }
674
675 /* replace_me ******************************************************************
676  
677    This function is called by asm_replacement_out when a thread reaches
678    a replacement point. `replace_me` must map the execution state to the
679    target replacement point and let execution continue there.
680
681    This function never returns!
682   
683    IN:
684        rp...............replacement point that has been reached
685            es...............execution state read by asm_replacement_out
686   
687 *******************************************************************************/
688
689 void replace_me(rplpoint *rp,executionstate *es)
690 {
691         rplpoint *target;
692         sourcestate ss;
693         s4 dumpsize;
694         
695         /* mark start of dump memory area */
696
697         dumpsize = dump_size();
698
699         /* fetch the target of the replacement */
700
701         target = rp->target;
702
703         /* XXX DEBUG turn of self-replacement */
704         if (target == rp)
705                 replace_deactivate_replacement_point(rp);
706         
707 #ifndef NDEBUG
708         printf("replace_me(%p,%p)\n",(void*)rp,(void*)es);
709         fflush(stdout);
710         replace_replacement_point_println(rp);
711         replace_executionstate_println(es,rp->code);
712 #endif
713
714         /* read execution state of old code */
715
716         replace_read_executionstate(rp,es,&ss);
717
718 #ifndef NDEBUG
719         replace_sourcestate_println(&ss);
720 #endif
721
722         /* write execution state of new code */
723
724         replace_write_executionstate(target,es,&ss);
725
726 #ifndef NDEBUG
727         replace_executionstate_println(es,target->code);
728 #endif
729         
730         /* release dump area */
731
732         dump_release(dumpsize);
733
734         /* enter new code */
735
736 #if (defined(__I386__) || defined(__X86_64__)) && defined(ENABLE_JIT)
737         asm_replacement_in(es);
738 #endif
739         abort();
740 }
741
742 /* replace_replacement_point_println *******************************************
743  
744    Print replacement point info.
745   
746    IN:
747        rp...............the replacement point to print
748   
749 *******************************************************************************/
750
751 #ifndef NDEBUG
752 static const char *type_char = "IJFDA";
753
754 #define TYPECHAR(t)  (((t) >= 0 && (t) <= 4) ? type_char[t] : '?')
755
756 void replace_replacement_point_println(rplpoint *rp)
757 {
758         int j;
759
760         if (!rp) {
761                 printf("(rplpoint *)NULL\n");
762                 return;
763         }
764
765         printf("rplpoint %p pc:%p out:%p target:%p mcode:%016llx type:%01d flags:%01x ra:%d = [",
766                         (void*)rp,rp->pc,rp->outcode,(void*)rp->target,
767                         (unsigned long long)rp->mcode,rp->type,rp->flags,rp->regalloccount);
768
769         for (j=0; j<rp->regalloccount; ++j)
770                 printf("%c%1c%01x:%02d",
771                                 (rp->regalloc[j].next) ? '^' : ' ',
772                                 TYPECHAR(rp->regalloc[j].type),
773                                 rp->regalloc[j].flags,
774                                 rp->regalloc[j].index);
775
776         printf("]\n          method: ");
777         method_print(rp->code->m);
778
779         printf("\n");
780 }
781 #endif
782
783 /* replace_show_replacement_points *********************************************
784  
785    Print replacement point info.
786   
787    IN:
788        code.............codeinfo whose replacement points should be printed.
789   
790 *******************************************************************************/
791
792 #ifndef NDEBUG
793 void replace_show_replacement_points(codeinfo *code)
794 {
795         int i;
796         rplpoint *rp;
797         
798         if (!code) {
799                 printf("(codeinfo *)NULL\n");
800                 return;
801         }
802
803         printf("\treplacement points: %d\n",code->rplpointcount);
804         printf("\tglobal allocations: %d = [",code->globalcount);
805
806         for (i=0; i<code->globalcount; ++i)
807                 printf("%c%1c%01x:%02d",
808                                 (code->regalloc[i].next) ? '^' : ' ',
809                                 TYPECHAR(code->regalloc[i].type),
810                                 code->regalloc[i].flags,code->regalloc[i].index);
811
812         printf("]\n");
813
814         printf("\ttotal allocations : %d\n",code->regalloccount);
815         printf("\tsaved int regs    : %d\n",code->savedintcount);
816         printf("\tsaved flt regs    : %d\n",code->savedfltcount);
817         printf("\tmemuse            : %d\n",code->memuse);
818
819         printf("\n");
820
821         for (i=0; i<code->rplpointcount; ++i) {
822                 rp = code->rplpoints + i;
823
824                 assert(rp->code == code);
825                 
826                 printf("\t");
827                 replace_replacement_point_println(rp);
828         }
829 }
830 #endif
831
832 /* replace_executionstate_println **********************************************
833  
834    Print execution state
835   
836    IN:
837        es...............the execution state to print
838            code.............the codeinfo for which this execution state is meant
839                             (may be NULL)
840   
841 *******************************************************************************/
842
843 #ifndef NDEBUG
844 void replace_executionstate_println(executionstate *es,codeinfo *code)
845 {
846         int i;
847         int slots;
848 #ifdef HAS_4BYTE_STACKSLOT
849         u4 *sp;
850 #else
851         u8 *sp;
852 #endif
853
854         if (!es) {
855                 printf("(executionstate *)NULL\n");
856                 return;
857         }
858
859         printf("executionstate %p:\n",(void*)es);
860         printf("\tpc = %p\n",(void*)es->pc);
861         printf("\tsp = %p\n",(void*)es->sp);
862         for (i=0; i<INT_REG_CNT; ++i) {
863                 printf("\t%-3s = %016llx\n",regs[i],(unsigned long long)es->intregs[i]);
864         }
865         for (i=0; i<FLT_REG_CNT; ++i) {
866                 printf("\tfltregs[%2d] = %016llx\n",i,(unsigned long long)es->fltregs[i]);
867         }
868
869 #ifdef HAS_4BYTE_STACKSLOT
870         sp = (u4*) es->sp;
871 #else
872         sp = (u8*) es->sp;
873 #endif
874
875         if (code)
876                 slots = code_get_stack_frame_size(code);
877         else
878                 slots = 0;
879
880         printf("\tstack slots at sp:\n");
881         for (i=0; i<slots; ++i) {
882 #ifdef HAS_4BYTE_STACKSLOT
883                 printf("\t\t%08lx\n",(unsigned long)*sp++);
884 #else
885                 printf("\t\t%016llx\n",(unsigned long long)*sp++);
886 #endif
887         }
888
889         printf("\n");
890 }
891 #endif
892
893 /* replace_sourcestate_println *************************************************
894  
895    Print source state
896   
897    IN:
898        ss...............the source state to print
899   
900 *******************************************************************************/
901
902 #ifndef NDEBUG
903 void replace_sourcestate_println(sourcestate *ss)
904 {
905         int i;
906         int t;
907         int reg;
908
909         if (!ss) {
910                 printf("(sourcestate *)NULL\n");
911                 return;
912         }
913
914         printf("sourcestate %p:\n",(void*)ss);
915
916         printf("\tlocals (%d):\n",ss->javalocalcount);
917         for (i=0; i<ss->javalocalcount; ++i) {
918                 for (t=0; t<5; ++t) {
919                         if (ss->javalocals[i*5+t] != 0x00dead0000dead00ULL) {
920                                 printf("\tlocal[%c%2d] = ",TYPECHAR(t),i);
921                                 printf("%016llx\n",(unsigned long long) ss->javalocals[i*5+t]);
922                         }
923                 }
924         }
925
926         printf("\n");
927
928         printf("\tstack (depth %d):\n",ss->javastackdepth);
929         for (i=0; i<ss->javastackdepth; ++i) {
930                 printf("\tstack[%2d] = ",i);
931                 printf("%016llx\n",(unsigned long long) ss->javastack[i]);
932         }
933
934         printf("\n");
935
936         printf("\tsaved int registers (%d):\n",INT_SAV_CNT);
937         reg = INT_REG_CNT;
938         for (i=0; i<INT_SAV_CNT; ++i) {
939                 while (nregdescint[--reg] != REG_SAV)
940                         ;
941                 if (ss->savedintregs[i] != 0x00dead0000dead00ULL) {
942                         printf("\t%-3s = ",regs[reg]);
943                         printf("%016llx\n",(unsigned long long) ss->savedintregs[i]);
944                 }
945         }
946
947         printf("\n");
948
949         printf("\tsaved float registers (%d):\n",FLT_SAV_CNT);
950         for (i=0; i<FLT_SAV_CNT; ++i) {
951                 if (ss->savedfltregs[i] != 0x00dead0000dead00ULL) {
952                         printf("\tsavedfltreg[%2d] = ",i);
953                         printf("%016llx\n",(unsigned long long) ss->savedfltregs[i]);
954                 }
955         }
956         
957         printf("\n");
958
959         printf("\tsynchronization slots (%d):\n",ss->syncslotcount);
960         for (i=0; i<ss->syncslotcount; ++i) {
961                 printf("\tslot[%2d] = ",i);
962 #ifdef HAS_4BYTE_STACKSLOT
963                 printf("%08lx\n",(unsigned long) ss->syncslots[i]);
964 #else
965                 printf("%016llx\n",(unsigned long long) ss->syncslots[i]);
966 #endif
967         }
968         
969         printf("\n");
970 }
971 #endif
972
973 /*
974  * These are local overrides for various environment variables in Emacs.
975  * Please do not remove this and leave it at the end of the file, where
976  * Emacs will automagically detect them.
977  * ---------------------------------------------------------------------
978  * Local variables:
979  * mode: c
980  * indent-tabs-mode: t
981  * c-basic-offset: 4
982  * tab-width: 4
983  * End:
984  * vim:noexpandtab:sw=4:ts=4:
985  */