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