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