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