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