a2054e4c3d2fcf9ea8a1b2c1c3f6b7398003da52
[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 /*** debugging ****************************************************************/
85
86 #define REPLACE_STATISTICS
87
88 #if defined(REPLACE_STATISTICS)
89
90 static int stat_replacements = 0;
91 static int stat_frames = 0;
92 static int stat_recompile = 0;
93 static int stat_unroll_inline = 0;
94 static int stat_unroll_call = 0;
95 static int stat_dist_frames[20] = { 0 };
96 static int stat_dist_locals[20] = { 0 };
97 static int stat_dist_locals_adr[10] = { 0 };
98 static int stat_dist_locals_prim[10] = { 0 };
99 static int stat_dist_locals_ret[10] = { 0 };
100 static int stat_dist_locals_void[10] = { 0 };
101 static int stat_dist_stack[10] = { 0 };
102 static int stat_dist_stack_adr[10] = { 0 };
103 static int stat_dist_stack_prim[10] = { 0 };
104 static int stat_dist_stack_ret[10] = { 0 };
105 static int stat_methods = 0;
106 static int stat_rploints = 0;
107 static int stat_regallocs = 0;
108 static int stat_dist_method_rplpoints[20] = { 0 };
109
110 #define REPLACE_COUNT(cnt)  (cnt)++
111 #define REPLACE_COUNT_INC(cnt, inc)  ((cnt) += (inc))
112
113 #define REPLACE_COUNT_DIST(array, val)                               \
114     do {                                                             \
115         int limit = (sizeof(array) / sizeof(int)) - 1;               \
116         if ((val) < (limit)) (array)[val]++;                         \
117         else (array)[limit]++;                                       \
118     } while (0)
119
120 #define REPLACE_PRINT_DIST(name, array) \
121         printf("    " name " distribution:\n"); \
122         print_freq(stdout, (array), sizeof(array)/sizeof(int) - 1);
123
124 static void print_freq(FILE *file,int *array,int limit)
125 {
126         int i;
127         int sum = 0;
128         int cum = 0;
129         for (i=0; i<limit; ++i)
130                 sum += array[i];
131         sum += array[limit];
132         for (i=0; i<limit; ++i) {
133                 cum += array[i];
134                 fprintf(file,"      %3d: %8d (cum %3d%%)\n",
135                                 i, array[i], (sum) ? ((100*cum)/sum) : 0);
136         }
137         fprintf(file,"    >=%3d: %8d\n",limit,array[limit]);
138 }
139
140 void replace_print_statistics(void)
141 {
142         printf("replacement statistics:\n");
143         printf("    # of replacements:   %d\n", stat_replacements);
144         printf("    # of frames:         %d\n", stat_frames);
145         printf("    # of recompilations: %d\n", stat_recompile);
146         printf("    unrolled inlines:    %d\n", stat_unroll_inline);
147         printf("    unrolled calls:      %d\n", stat_unroll_call);
148         REPLACE_PRINT_DIST("frame depth", stat_dist_frames);
149         REPLACE_PRINT_DIST("locals per frame", stat_dist_locals);
150         REPLACE_PRINT_DIST("ADR locals per frame", stat_dist_locals_adr);
151         REPLACE_PRINT_DIST("primitive locals per frame", stat_dist_locals_prim);
152         REPLACE_PRINT_DIST("RET locals per frame", stat_dist_locals_ret);
153         REPLACE_PRINT_DIST("void locals per frame", stat_dist_locals_void);
154         REPLACE_PRINT_DIST("stack slots per frame", stat_dist_stack);
155         REPLACE_PRINT_DIST("ADR stack slots per frame", stat_dist_stack_adr);
156         REPLACE_PRINT_DIST("primitive stack slots per frame", stat_dist_stack_prim);
157         REPLACE_PRINT_DIST("RET stack slots per frame", stat_dist_stack_ret);
158         printf("\n");
159         printf("    # of methods:            %d\n", stat_methods);
160         printf("    # of replacement points: %d\n", stat_rploints);
161         printf("    # of regallocs:          %d\n", stat_regallocs);
162         printf("        per rplpoint:        %f\n", (double)stat_regallocs / stat_rploints);
163         printf("        per method:          %f\n", (double)stat_regallocs / stat_methods);
164         REPLACE_PRINT_DIST("replacement points per method", stat_dist_method_rplpoints);
165         printf("\n");
166
167 }
168
169 #else
170
171 #define REPLACE_COUNT(cnt)
172 #define REPLACE_COUNT_INC(cnt, inc)
173 #define REPLACE_COUNT_DIST(array, val)
174
175 #endif /* defined(REPLACE_STATISTICS) */
176
177 /*** constants used internally ************************************************/
178
179 #define TOP_IS_NORMAL    0
180 #define TOP_IS_ON_STACK  1
181 #define TOP_IS_IN_ITMP1  2
182 #define TOP_IS_VOID      3
183
184
185 /* replace_create_replacement_point ********************************************
186  
187    Create a replacement point.
188   
189    IN:
190        jd...............current jitdata
191            iinfo............inlining info for the current position
192            rp...............pre-allocated (uninitialized) rplpoint
193            type.............RPLPOINT_TYPE constant
194            *pra.............current rplalloc pointer
195            javalocals.......the javalocals at the current point
196            stackvars........the stack variables at the current point
197            stackdepth.......the stack depth at the current point
198            paramcount.......number of parameters at the start of stackvars
199   
200    OUT:
201        *rpa.............points to the next free rplalloc
202   
203 *******************************************************************************/
204
205 static void replace_create_replacement_point(jitdata *jd,
206                                                                                          insinfo_inline *iinfo,
207                                                                                          rplpoint *rp,
208                                                                                          s4 type,
209                                                                                          instruction *iptr,
210                                                                                          rplalloc **pra,
211                                                                                          s4 *javalocals,
212                                                                                          s4 *stackvars,
213                                                                                          s4 stackdepth,
214                                                                                          s4 paramcount)
215 {
216         rplalloc *ra;
217         s4        i;
218         varinfo  *v;
219         s4        index;
220
221         ra = *pra;
222
223         REPLACE_COUNT(stat_rploints);
224
225         rp->method = (iinfo) ? iinfo->method : jd->m;
226         rp->pc = NULL;        /* set by codegen */
227         rp->outcode = NULL;   /* set by codegen */
228         rp->callsize = 0;     /* set by codegen */
229         rp->target = NULL;
230         rp->regalloc = ra;
231         rp->flags = 0;
232         rp->type = type;
233         rp->id = iptr->flags.bits >> INS_FLAG_ID_SHIFT;
234
235         /* XXX unify these two fields */
236         rp->code = jd->code;
237         rp->parent = (iinfo) ? iinfo->rp : NULL;
238
239         /* store local allocation info of javalocals */
240
241         if (javalocals) {
242                 for (i = 0; i < rp->method->maxlocals; ++i) {
243                         index = javalocals[i];
244                         if (index == UNUSED)
245                                 continue;
246
247                         ra->index = i;
248                         if (index < UNUSED) {
249                                 ra->regoff = (UNUSED - index) - 1;
250                                 ra->type = TYPE_RET;
251                                 ra->flags = 0;
252                         }
253                         else {
254                                 v = VAR(index);
255                                 ra->flags = v->flags & (INMEMORY);
256                                 ra->regoff = v->vv.regoff;
257                                 ra->type = v->type;
258                         }
259                         ra++;
260                 }
261         }
262
263         /* store allocation info of java stack vars */
264
265         for (i = 0; i < stackdepth; ++i) {
266                 v = VAR(stackvars[i]);
267                 ra->flags = v->flags & (INMEMORY);
268                 ra->index = (i < paramcount) ? RPLALLOC_PARAM : RPLALLOC_STACK;
269                 ra->type  = v->type;
270                 /* XXX how to handle locals on the stack containing returnAddresses? */
271                 if (v->type == TYPE_RET) {
272                         assert(stackvars[i] >= jd->localcount);
273                         ra->regoff = v->vv.retaddr->nr;
274                 }
275                 else
276                         ra->regoff = v->vv.regoff;
277                 ra++;
278         }
279
280         /* total number of allocations */
281
282         rp->regalloccount = ra - rp->regalloc;
283
284         *pra = ra;
285 }
286
287
288 /* replace_create_replacement_points *******************************************
289  
290    Create the replacement points for the given code.
291   
292    IN:
293        jd...............current jitdata, must not have any replacement points
294   
295    OUT:
296        code->rplpoints.......set to the list of replacement points
297            code->rplpointcount...number of replacement points
298            code->regalloc........list of allocation info
299            code->regalloccount...total length of allocation info list
300            code->globalcount.....number of global allocations at the
301                                  start of code->regalloc
302   
303    RETURN VALUE:
304        true.............everything ok 
305        false............an exception has been thrown
306    
307 *******************************************************************************/
308
309 bool replace_create_replacement_points(jitdata *jd)
310 {
311         codeinfo        *code;
312         registerdata    *rd;
313         basicblock      *bptr;
314         int              count;
315         methodinfo      *m;
316         rplpoint        *rplpoints;
317         rplpoint        *rp;
318         int              alloccount;
319         rplalloc        *regalloc;
320         rplalloc        *ra;
321         int              i;
322         instruction     *iptr;
323         instruction     *iend;
324         s4              *javalocals;
325         methoddesc      *md;
326         s4               j;
327         insinfo_inline  *iinfo;
328         insinfo_inline  *calleeinfo;
329         s4               startcount;
330
331         REPLACE_COUNT(stat_methods);
332
333         /* get required compiler data */
334
335         code = jd->code;
336         rd   = jd->rd;
337
338         /* assert that we wont overwrite already allocated data */
339
340         assert(code);
341         assert(code->m);
342         assert(code->rplpoints == NULL);
343         assert(code->rplpointcount == 0);
344         assert(code->regalloc == NULL);
345         assert(code->regalloccount == 0);
346         assert(code->globalcount == 0);
347
348         /* iterate over the basic block list to find replacement points */
349
350         m = code->m;
351
352         count = 0;
353         alloccount = 0;
354
355         javalocals = DMNEW(s4, jd->maxlocals);
356
357         for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
358
359                 /* skip dead code */
360
361                 if (bptr->flags < BBFINISHED)
362                         continue;
363
364                 /* get info about this block */
365
366                 m = bptr->method;
367                 iinfo = bptr->inlineinfo;
368
369                 /* initialize javalocals at the start of this block */
370
371                 if (bptr->javalocals)
372                         MCOPY(javalocals, bptr->javalocals, s4, m->maxlocals);
373                 else
374                         for (i=0; i<m->maxlocals; ++i)
375                                 javalocals[i] = UNUSED;
376
377                 /* iterate over the instructions */
378
379                 iptr = bptr->iinstr;
380                 iend = iptr + bptr->icount;
381                 startcount = count;
382
383                 for (; iptr != iend; ++iptr) {
384                         switch (iptr->opc) {
385                                 case ICMD_INVOKESTATIC:
386                                 case ICMD_INVOKESPECIAL:
387                                 case ICMD_INVOKEVIRTUAL:
388                                 case ICMD_INVOKEINTERFACE:
389                                         INSTRUCTION_GET_METHODDESC(iptr, md);
390                                         count++;
391                                         for (i=0; i<m->maxlocals; ++i)
392                                                 if (javalocals[i] != UNUSED)
393                                                         alloccount++;
394                                         alloccount += iptr->s1.argcount;
395                                         if (iinfo)
396                                                 alloccount -= iinfo->throughcount;
397                                         break;
398
399                                 case ICMD_ISTORE:
400                                 case ICMD_LSTORE:
401                                 case ICMD_FSTORE:
402                                 case ICMD_DSTORE:
403                                 case ICMD_ASTORE:
404                                         /* XXX share code with stack.c */
405                                         j = iptr->dst.varindex;
406                                         i = iptr->sx.s23.s3.javaindex;
407                                         if (i != UNUSED) {
408                                                 if (iptr->flags.bits & INS_FLAG_RETADDR)
409                                                         javalocals[i] = iptr->sx.s23.s2.retaddrnr;
410                                                 else
411                                                         javalocals[i] = j;
412                                                 if (iptr->flags.bits & INS_FLAG_KILL_PREV)
413                                                         javalocals[i-1] = UNUSED;
414                                                 if (iptr->flags.bits & INS_FLAG_KILL_NEXT)
415                                                         javalocals[i+1] = UNUSED;
416                                         }
417                                         break;
418
419                                 case ICMD_IRETURN:
420                                 case ICMD_LRETURN:
421                                 case ICMD_FRETURN:
422                                 case ICMD_DRETURN:
423                                 case ICMD_ARETURN:
424                                         alloccount += 1;
425                                         /* FALLTHROUGH! */
426                                 case ICMD_RETURN:
427                                         count++;
428                                         break;
429
430                                 case ICMD_INLINE_START:
431                                         iinfo = iptr->sx.s23.s3.inlineinfo;
432
433                                         count++;
434                                         for (i=0; i<m->maxlocals; ++i)
435                                                 if (javalocals[i] != UNUSED)
436                                                         alloccount++;
437                                         alloccount += iinfo->stackvarscount;
438                                         if (iinfo->synclocal != UNUSED)
439                                                 alloccount++;
440
441                                         m = iinfo->method;
442                                         if (iinfo->javalocals_start)
443                                                 MCOPY(javalocals, iinfo->javalocals_start, s4, m->maxlocals);
444                                         break;
445
446                                 case ICMD_INLINE_END:
447                                         iinfo = iptr->sx.s23.s3.inlineinfo;
448                                         m = iinfo->outer;
449                                         if (iinfo->javalocals_end)
450                                                 MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
451                                         iinfo = iinfo->parent;
452                                         break;
453                         }
454                 } /* end instruction loop */
455
456                 /* create replacement points at targets of backward branches */
457                 /* We only need the replacement point there, if there is no  */
458                 /* replacement point inside the block.                       */
459
460                 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
461                         if (count > startcount) {
462                                 /* we don't need it */
463                                 bptr->bitflags &= ~BBFLAG_REPLACEMENT;
464                         }
465                         else {
466                                 count++;
467                                 alloccount += bptr->indepth;
468                                 if (bptr->inlineinfo)
469                                         alloccount -= bptr->inlineinfo->throughcount;
470
471                                 for (i=0; i<bptr->method->maxlocals; ++i)
472                                         if (bptr->javalocals[i] != UNUSED)
473                                                 alloccount++;
474                         }
475                 }
476
477         } /* end basicblock loop */
478
479         /* if no points were found, there's nothing to do */
480
481         if (!count)
482                 return true;
483
484         /* allocate replacement point array and allocation array */
485
486         rplpoints = MNEW(rplpoint, count);
487         regalloc = MNEW(rplalloc, alloccount);
488         ra = regalloc;
489
490         /* initialize replacement point structs */
491
492         rp = rplpoints;
493
494         /* XXX try to share code with the counting loop! */
495
496         for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
497                 /* skip dead code */
498
499                 if (bptr->flags < BBFINISHED)
500                         continue;
501
502                 /* get info about this block */
503
504                 m = bptr->method;
505                 iinfo = bptr->inlineinfo;
506
507                 /* initialize javalocals at the start of this block */
508
509                 if (bptr->javalocals)
510                         MCOPY(javalocals, bptr->javalocals, s4, m->maxlocals);
511                 else
512                         for (i=0; i<m->maxlocals; ++i)
513                                 javalocals[i] = UNUSED;
514
515                 /* create replacement points at targets of backward branches */
516
517                 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
518
519                         i = (iinfo) ? iinfo->throughcount : 0;
520                         replace_create_replacement_point(jd, iinfo, rp++,
521                                         bptr->type, bptr->iinstr, &ra,
522                                         bptr->javalocals, bptr->invars + i, bptr->indepth - i, 0);
523                 }
524
525                 /* iterate over the instructions */
526
527                 iptr = bptr->iinstr;
528                 iend = iptr + bptr->icount;
529
530                 for (; iptr != iend; ++iptr) {
531                         switch (iptr->opc) {
532                                 case ICMD_INVOKESTATIC:
533                                 case ICMD_INVOKESPECIAL:
534                                 case ICMD_INVOKEVIRTUAL:
535                                 case ICMD_INVOKEINTERFACE:
536                                         INSTRUCTION_GET_METHODDESC(iptr, md);
537
538                                         i = (iinfo) ? iinfo->throughcount : 0;
539                                         replace_create_replacement_point(jd, iinfo, rp++,
540                                                         RPLPOINT_TYPE_CALL, iptr, &ra,
541                                                         javalocals, iptr->sx.s23.s2.args,
542                                                         iptr->s1.argcount - i,
543                                                         md->paramcount);
544                                         break;
545
546                                 case ICMD_ISTORE:
547                                 case ICMD_LSTORE:
548                                 case ICMD_FSTORE:
549                                 case ICMD_DSTORE:
550                                 case ICMD_ASTORE:
551                                         /* XXX share code with stack.c */
552                                         j = iptr->dst.varindex;
553                                         i = iptr->sx.s23.s3.javaindex;
554                                         if (i != UNUSED) {
555                                                 if (iptr->flags.bits & INS_FLAG_RETADDR)
556                                                         javalocals[i] = iptr->sx.s23.s2.retaddrnr;
557                                                 else
558                                                         javalocals[i] = j;
559                                                 if (iptr->flags.bits & INS_FLAG_KILL_PREV)
560                                                         javalocals[i-1] = UNUSED;
561                                                 if (iptr->flags.bits & INS_FLAG_KILL_NEXT)
562                                                         javalocals[i+1] = UNUSED;
563                                         }
564                                         break;
565
566                                 case ICMD_IRETURN:
567                                 case ICMD_LRETURN:
568                                 case ICMD_FRETURN:
569                                 case ICMD_DRETURN:
570                                 case ICMD_ARETURN:
571                                         replace_create_replacement_point(jd, iinfo, rp++,
572                                                         RPLPOINT_TYPE_RETURN, iptr, &ra,
573                                                         NULL, &(iptr->s1.varindex), 1, 0);
574                                         break;
575
576                                 case ICMD_RETURN:
577                                         replace_create_replacement_point(jd, iinfo, rp++,
578                                                         RPLPOINT_TYPE_RETURN, iptr, &ra,
579                                                         NULL, NULL, 0, 0);
580                                         break;
581
582                                 case ICMD_INLINE_START:
583                                         calleeinfo = iptr->sx.s23.s3.inlineinfo;
584
585                                         calleeinfo->rp = rp;
586                                         replace_create_replacement_point(jd, iinfo, rp++,
587                                                         RPLPOINT_TYPE_INLINE, iptr, &ra,
588                                                         javalocals,
589                                                         calleeinfo->stackvars, calleeinfo->stackvarscount,
590                                                         calleeinfo->paramcount);
591
592                                         if (calleeinfo->synclocal != UNUSED) {
593                                                 ra->index = RPLALLOC_SYNC;
594                                                 ra->regoff = jd->var[calleeinfo->synclocal].vv.regoff;
595                                                 ra->flags  = jd->var[calleeinfo->synclocal].flags & INMEMORY;
596                                                 ra->type = TYPE_ADR;
597                                                 ra++;
598                                                 rp[-1].regalloccount++;
599                                         }
600
601                                         iinfo = calleeinfo;
602                                         m = iinfo->method;
603                                         if (iinfo->javalocals_start)
604                                                 MCOPY(javalocals, iinfo->javalocals_start, s4, m->maxlocals);
605                                         break;
606
607                                 case ICMD_INLINE_END:
608                                         iinfo = iptr->sx.s23.s3.inlineinfo;
609                                         m = iinfo->outer;
610                                         if (iinfo->javalocals_end)
611                                                 MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
612                                         iinfo = iinfo->parent;
613                                         break;
614                         }
615                 } /* end instruction loop */
616         } /* end basicblock loop */
617
618         assert((rp - rplpoints) == count);
619         assert((ra - regalloc) == alloccount);
620
621         /* store the data in the codeinfo */
622
623         code->rplpoints     = rplpoints;
624         code->rplpointcount = count;
625         code->regalloc      = regalloc;
626         code->regalloccount = alloccount;
627         code->globalcount   = 0;
628         code->savedintcount = INT_SAV_CNT - rd->savintreguse;
629         code->savedfltcount = FLT_SAV_CNT - rd->savfltreguse;
630         code->memuse        = rd->memuse;
631         code->stackframesize = jd->cd->stackframesize;
632
633         REPLACE_COUNT_DIST(stat_dist_method_rplpoints, count);
634         REPLACE_COUNT_INC(stat_regallocs, alloccount);
635
636         /* everything alright */
637
638         return true;
639 }
640
641
642 /* replace_free_replacement_points *********************************************
643  
644    Free memory used by replacement points.
645   
646    IN:
647        code.............codeinfo whose replacement points should be freed.
648   
649 *******************************************************************************/
650
651 void replace_free_replacement_points(codeinfo *code)
652 {
653         assert(code);
654
655         if (code->rplpoints)
656                 MFREE(code->rplpoints,rplpoint,code->rplpointcount);
657
658         if (code->regalloc)
659                 MFREE(code->regalloc,rplalloc,code->regalloccount);
660
661         code->rplpoints = NULL;
662         code->rplpointcount = 0;
663         code->regalloc = NULL;
664         code->regalloccount = 0;
665         code->globalcount = 0;
666 }
667
668
669 /* replace_activate_replacement_point ******************************************
670  
671    Activate a replacement point. When this function returns, the
672    replacement point is "armed", that is each thread reaching this point
673    will be replace to `target`.
674    
675    IN:
676        rp...............replacement point to activate
677            target...........target of replacement
678   
679 *******************************************************************************/
680
681 void replace_activate_replacement_point(rplpoint *rp,rplpoint *target)
682 {
683         assert(rp->target == NULL);
684
685         DOLOG( printf("activate replacement point:\n");
686                    replace_replacement_point_println(rp, 1); fflush(stdout); );
687
688         rp->target = target;
689
690 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
691         md_patch_replacement_point(rp);
692 #endif
693 }
694
695
696 /* replace_deactivate_replacement_point ****************************************
697  
698    Deactivate a replacement point. When this function returns, the
699    replacement point is "un-armed", that is a each thread reaching this point
700    will just continue normally.
701    
702    IN:
703        rp...............replacement point to deactivate
704   
705 *******************************************************************************/
706
707 void replace_deactivate_replacement_point(rplpoint *rp)
708 {
709         assert(rp->target);
710
711         DOLOG( printf("deactivate replacement point:\n");
712                    replace_replacement_point_println(rp, 1); fflush(stdout); );
713
714         rp->target = NULL;
715
716 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
717         md_patch_replacement_point(rp);
718 #endif
719 }
720
721
722 /* replace_read_value **********************************************************
723
724    Read a value with the given allocation from the execution state.
725    
726    IN:
727            es...............execution state
728            sp...............stack pointer of the execution state (XXX eliminate?)
729            ra...............allocation
730            javaval..........where to put the value
731
732    OUT:
733        *javaval.........the value
734   
735 *******************************************************************************/
736
737 static void replace_read_value(executionstate_t *es,
738                                                            stackslot_t *sp,
739                                                            rplalloc *ra,
740                                                            u8 *javaval)
741 {
742         if (ra->flags & INMEMORY) {
743                 /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
744 #ifdef HAS_4BYTE_STACKSLOT
745                 if (IS_2_WORD_TYPE(ra->type)) {
746                         *javaval = *(u8*)(sp + ra->regoff);
747                 }
748                 else {
749 #endif
750                         *javaval = sp[ra->regoff];
751 #ifdef HAS_4BYTE_STACKSLOT
752                 }
753 #endif
754         }
755         else {
756                 /* allocated register */
757                 if (IS_FLT_DBL_TYPE(ra->type)) {
758                         *javaval = es->fltregs[ra->regoff];
759                 }
760                 else {
761                         *javaval = es->intregs[ra->regoff];
762                 }
763         }
764 }
765
766
767 /* replace_write_value *********************************************************
768
769    Write a value to the given allocation in the execution state.
770    
771    IN:
772            es...............execution state
773            sp...............stack pointer of the execution state (XXX eliminate?)
774            ra...............allocation
775            *javaval.........the value
776
777 *******************************************************************************/
778
779 static void replace_write_value(executionstate_t *es,
780                                                             stackslot_t *sp,
781                                                             rplalloc *ra,
782                                                             u8 *javaval)
783 {
784         if (ra->flags & INMEMORY) {
785                 /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
786 #ifdef HAS_4BYTE_STACKSLOT
787                 if (IS_2_WORD_TYPE(ra->type)) {
788                         *(u8*)(sp + ra->regoff) = *javaval;
789                 }
790                 else {
791 #endif
792                         sp[ra->regoff] = *javaval;
793 #ifdef HAS_4BYTE_STACKSLOT
794                 }
795 #endif
796         }
797         else {
798                 /* allocated register */
799                 if (IS_FLT_DBL_TYPE(ra->type)) {
800                         es->fltregs[ra->regoff] = *javaval;
801                 }
802                 else {
803                         es->intregs[ra->regoff] = *javaval;
804                 }
805         }
806 }
807
808
809 /* replace_read_executionstate *************************************************
810
811    Read the given executions state and translate it to a source frame.
812    
813    IN:
814        rp...............replacement point at which `es` was taken
815            es...............execution state
816            ss...............where to put the source state
817
818    OUT:
819        *ss..............the source state derived from the execution state
820   
821 *******************************************************************************/
822
823 static void replace_read_executionstate(rplpoint *rp,
824                                                                                 executionstate_t *es,
825                                                                                 sourcestate_t *ss,
826                                                                                 bool topframe)
827 {
828         methodinfo    *m;
829         codeinfo      *code;
830         int            count;
831         int            i;
832         rplalloc      *ra;
833         sourceframe_t *frame;
834         int            topslot;
835         stackslot_t   *sp;
836         stackslot_t   *basesp;
837
838         code = rp->code;
839         m = rp->method;
840         topslot = TOP_IS_NORMAL;
841
842         /* stack pointer */
843
844         sp = (stackslot_t *) es->sp;
845
846         /* in some cases the top stack slot is passed in REG_ITMP1 */
847
848         if (rp->type == BBTYPE_EXH) {
849                 topslot = TOP_IS_IN_ITMP1;
850         }
851
852         /* calculate base stack pointer */
853
854         basesp = sp + code_get_stack_frame_size(code);
855
856         /* create the source frame */
857
858         frame = DNEW(sourceframe_t);
859         frame->up = ss->frames;
860         frame->method = rp->method;
861         frame->id = rp->id;
862         frame->syncslotcount = 0;
863         frame->syncslots = NULL;
864 #if !defined(NDEBUG)
865         frame->debug_rp = rp;
866 #endif
867
868         ss->frames = frame;
869
870         /* read local variables */
871
872         count = m->maxlocals;
873         frame->javalocalcount = count;
874         frame->javalocals = DMNEW(u8, count);
875         frame->javalocaltype = DMNEW(u1, count);
876
877 #if !defined(NDEBUG)
878         /* mark values as undefined */
879         for (i=0; i<count; ++i) {
880                 frame->javalocals[i] = (u8) 0x00dead0000dead00ULL;
881                 frame->javalocaltype[i] = TYPE_VOID;
882         }
883
884         /* some entries in the intregs array are not meaningful */
885         /*es->intregs[REG_ITMP3] = (u8) 0x11dead1111dead11ULL;*/
886         es->intregs[REG_SP   ] = (u8) 0x11dead1111dead11ULL;
887 #ifdef REG_PV
888         es->intregs[REG_PV   ] = (u8) 0x11dead1111dead11ULL;
889 #endif
890 #endif /* !defined(NDEBUG) */
891
892         /* read javalocals */
893
894         count = rp->regalloccount;
895         ra = rp->regalloc;
896
897         while (count && (i = ra->index) >= 0) {
898                 assert(i < m->maxlocals);
899                 frame->javalocaltype[i] = ra->type;
900                 if (ra->type == TYPE_RET)
901                         frame->javalocals[i] = ra->regoff;
902                 else
903                         replace_read_value(es, sp, ra, frame->javalocals + i);
904                 ra++;
905                 count--;
906         }
907
908         /* read stack slots */
909
910         frame->javastackdepth = count;
911         frame->javastack = DMNEW(u8, count);
912         frame->javastacktype = DMNEW(u1, count);
913
914 #if !defined(NDEBUG)
915         /* mark values as undefined */
916         for (i=0; i<count; ++i) {
917                 frame->javastack[i] = (u8) 0x00dead0000dead00ULL;
918                 frame->javastacktype[i] = TYPE_VOID;
919         }
920 #endif /* !defined(NDEBUG) */
921
922         i = 0;
923
924         /* the first stack slot is special in SBR and EXH blocks */
925
926         if (topslot == TOP_IS_ON_STACK) {
927                 assert(count);
928
929                 assert(ra->index == RPLALLOC_STACK);
930                 frame->javastack[i] = sp[-1];
931                 frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
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                 frame->javastack[i] = es->intregs[REG_ITMP1];
941                 frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
942                 count--;
943                 i++;
944                 ra++;
945         }
946         else if (topslot == TOP_IS_VOID) {
947                 assert(count);
948
949                 assert(ra->index == RPLALLOC_STACK);
950                 frame->javastack[i] = 0;
951                 frame->javastacktype[i] = TYPE_VOID;
952                 count--;
953                 i++;
954                 ra++;
955         }
956
957         /* read remaining stack slots */
958
959         for (; count--; ra++) {
960                 if (ra->index == RPLALLOC_SYNC) {
961                         assert(rp->type == RPLPOINT_TYPE_INLINE);
962
963                         /* only read synchronization slots when traversing an inline point */
964
965                         if (!topframe) {
966                                 sourceframe_t *calleeframe = frame->up;
967                                 assert(calleeframe);
968                                 assert(calleeframe->syncslotcount == 0);
969                                 assert(calleeframe->syncslots == NULL);
970
971                                 calleeframe->syncslotcount = 1;
972                                 calleeframe->syncslots = DMNEW(u8, 1);
973                                 replace_read_value(es,sp,ra,calleeframe->syncslots);
974                         }
975
976                         frame->javastackdepth--;
977                         continue;
978                 }
979
980                 assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
981
982                 /* do not read parameters of calls down the call chain */
983
984                 if (!topframe && ra->index == RPLALLOC_PARAM) {
985                         frame->javastackdepth--;
986                 }
987                 else {
988                         if (ra->type == TYPE_RET)
989                                 frame->javastack[i] = ra->regoff;
990                         else
991                                 replace_read_value(es,sp,ra,frame->javastack + i);
992                         frame->javastacktype[i] = ra->type;
993                         i++;
994                 }
995         }
996 }
997
998
999 /* replace_write_executionstate ************************************************
1000
1001    Translate the given source state into an execution state.
1002    
1003    IN:
1004        rp...............replacement point for which execution state should be
1005                             creates
1006            es...............where to put the execution state
1007            ss...............the given source state
1008
1009    OUT:
1010        *es..............the execution state derived from the source state
1011   
1012 *******************************************************************************/
1013
1014 static void replace_write_executionstate(rplpoint *rp,
1015                                                                                  executionstate_t *es,
1016                                                                                  sourcestate_t *ss,
1017                                                                                  bool topframe)
1018 {
1019         methodinfo     *m;
1020         codeinfo       *code;
1021         int             count;
1022         int             i;
1023         rplalloc       *ra;
1024         sourceframe_t  *frame;
1025         int             topslot;
1026         stackslot_t    *sp;
1027         stackslot_t    *basesp;
1028
1029         code = rp->code;
1030         m = rp->method;
1031         topslot = TOP_IS_NORMAL;
1032
1033         /* pop a source frame */
1034
1035         frame = ss->frames;
1036         assert(frame);
1037         ss->frames = frame->up;
1038
1039         /* calculate stack pointer */
1040
1041         sp = (stackslot_t *) es->sp;
1042
1043         basesp = sp + code_get_stack_frame_size(code);
1044
1045         /* in some cases the top stack slot is passed in REG_ITMP1 */
1046
1047         if (rp->type == BBTYPE_EXH) {
1048                 topslot = TOP_IS_IN_ITMP1;
1049         }
1050
1051         /* write javalocals */
1052
1053         ra = rp->regalloc;
1054         count = rp->regalloccount;
1055
1056         while (count && (i = ra->index) >= 0) {
1057                 assert(i < m->maxlocals);
1058                 assert(i < frame->javalocalcount);
1059                 assert(ra->type == frame->javalocaltype[i]);
1060                 if (ra->type == TYPE_RET) {
1061                         /* XXX assert that it matches this rplpoint */
1062                 }
1063                 else
1064                         replace_write_value(es, sp, ra, frame->javalocals + i);
1065                 count--;
1066                 ra++;
1067         }
1068
1069         /* write stack slots */
1070
1071         i = 0;
1072
1073         /* the first stack slot is special in SBR and EXH blocks */
1074
1075         if (topslot == TOP_IS_ON_STACK) {
1076                 assert(count);
1077
1078                 assert(ra->index == RPLALLOC_STACK);
1079                 assert(i < frame->javastackdepth);
1080                 assert(frame->javastacktype[i] == TYPE_ADR);
1081                 sp[-1] = frame->javastack[i];
1082                 count--;
1083                 i++;
1084                 ra++;
1085         }
1086         else if (topslot == TOP_IS_IN_ITMP1) {
1087                 assert(count);
1088
1089                 assert(ra->index == RPLALLOC_STACK);
1090                 assert(i < frame->javastackdepth);
1091                 assert(frame->javastacktype[i] == TYPE_ADR);
1092                 es->intregs[REG_ITMP1] = frame->javastack[i];
1093                 count--;
1094                 i++;
1095                 ra++;
1096         }
1097         else if (topslot == TOP_IS_VOID) {
1098                 assert(count);
1099
1100                 assert(ra->index == RPLALLOC_STACK);
1101                 assert(i < frame->javastackdepth);
1102                 assert(frame->javastacktype[i] == TYPE_VOID);
1103                 count--;
1104                 i++;
1105                 ra++;
1106         }
1107
1108         /* write remaining stack slots */
1109
1110         for (; count--; ra++) {
1111                 if (ra->index == RPLALLOC_SYNC) {
1112                         assert(rp->type == RPLPOINT_TYPE_INLINE);
1113
1114                         /* only write synchronization slots when traversing an inline point */
1115
1116                         if (!topframe) {
1117                                 assert(frame->up);
1118                                 assert(frame->up->syncslotcount == 1); /* XXX need to understand more cases */
1119                                 assert(frame->up->syncslots != NULL);
1120
1121                                 replace_write_value(es,sp,ra,frame->up->syncslots);
1122                         }
1123                         continue;
1124                 }
1125
1126                 assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
1127
1128                 /* do not write parameters of calls down the call chain */
1129
1130                 if (!topframe && ra->index == RPLALLOC_PARAM) {
1131                         /* skip it */
1132                 }
1133                 else {
1134                         assert(i < frame->javastackdepth);
1135                         assert(ra->type == frame->javastacktype[i]);
1136                         if (ra->type == TYPE_RET) {
1137                                 /* XXX assert that it matches this rplpoint */
1138                         }
1139                         else {
1140                                 replace_write_value(es,sp,ra,frame->javastack + i);
1141                         }
1142                         i++;
1143                 }
1144         }
1145
1146         /* set new pc */
1147
1148         es->pc = rp->pc;
1149 }
1150
1151
1152 /* replace_pop_activation_record ***********************************************
1153
1154    Peel a stack frame from the execution state.
1155    
1156    *** This function imitates the effects of the method epilog ***
1157    *** and returning from the method call.                     ***
1158
1159    IN:
1160            es...............execution state
1161            frame............source frame, receives synchronization slots
1162
1163    OUT:
1164        *es..............the execution state after popping the stack frame
1165   
1166 *******************************************************************************/
1167
1168 bool replace_pop_activation_record(executionstate_t *es,
1169                                                                    sourceframe_t *frame)
1170 {
1171         u1 *ra;
1172         u1 *pv;
1173         s4 reg;
1174         s4 i;
1175         s4 count;
1176         codeinfo *code;
1177         stackslot_t *basesp;
1178         stackslot_t *sp;
1179
1180         assert(es->code);
1181         assert(frame);
1182
1183         /* read the return address */
1184
1185         ra = md_stacktrace_get_returnaddress(es->sp,
1186                         SIZE_OF_STACKSLOT * es->code->stackframesize);
1187
1188         DOLOG( printf("return address: %p\n", (void*)ra); );
1189
1190         /* find the new codeinfo */
1191
1192         pv = md_codegen_get_pv_from_pc(ra);
1193
1194         DOLOG( printf("PV = %p\n", (void*) pv); );
1195
1196         if (pv == NULL)
1197                 return false;
1198
1199         code = *(codeinfo **)(pv + CodeinfoPointer);
1200
1201         DOLOG( printf("CODE = %p\n", (void*) code); );
1202
1203         if (code == NULL)
1204                 return false;
1205
1206         /* calculate the base of the stack frame */
1207
1208         sp = (stackslot_t *) es->sp;
1209         basesp = sp + es->code->stackframesize;
1210
1211         /* read slots used for synchronization */
1212
1213         assert(frame->syncslotcount == 0);
1214         assert(frame->syncslots == NULL);
1215         count = code_get_sync_slot_count(es->code);
1216         frame->syncslotcount = count;
1217         frame->syncslots = DMNEW(u8, count);
1218         for (i=0; i<count; ++i) {
1219                 frame->syncslots[i] = sp[es->code->memuse + i];
1220         }
1221
1222         /* restore saved int registers */
1223
1224         reg = INT_REG_CNT;
1225         for (i=0; i<es->code->savedintcount; ++i) {
1226                 while (nregdescint[--reg] != REG_SAV)
1227                         ;
1228                 es->intregs[reg] = *--basesp;
1229         }
1230
1231         /* restore saved flt registers */
1232
1233         /* XXX align? */
1234         reg = FLT_REG_CNT;
1235         for (i=0; i<es->code->savedfltcount; ++i) {
1236                 while (nregdescfloat[--reg] != REG_SAV)
1237                         ;
1238                 basesp -= STACK_SLOTS_PER_FLOAT;
1239                 es->fltregs[reg] = *(u8*)basesp;
1240         }
1241
1242         /* Set the new pc. Subtract one so we do not hit the replacement point */
1243         /* of the instruction following the call, if there is one.             */
1244
1245         es->pc = ra - 1;
1246
1247         /* adjust the stackpointer */
1248
1249         es->sp += SIZE_OF_STACKSLOT * es->code->stackframesize;
1250         es->sp += SIZE_OF_STACKSLOT; /* skip return address */
1251
1252         es->pv = pv;
1253         es->code = code;
1254
1255 #if !defined(NDEBUG)
1256         /* for debugging */
1257         for (i=0; i<INT_REG_CNT; ++i)
1258                 if (nregdescint[i] != REG_SAV)
1259                         es->intregs[i] = 0x33dead3333dead33ULL;
1260         for (i=0; i<FLT_REG_CNT; ++i)
1261                 if (nregdescfloat[i] != REG_SAV)
1262                         es->fltregs[i] = 0x33dead3333dead33ULL;
1263 #endif /* !defined(NDEBUG) */
1264
1265         return true;
1266 }
1267
1268
1269 /* replace_push_activation_record **********************************************
1270
1271    Push a stack frame onto the execution state.
1272    
1273    *** This function imitates the effects of a call and the ***
1274    *** method prolog of the callee.                         ***
1275
1276    IN:
1277            es...............execution state
1278            rpcall...........the replacement point at the call site
1279            calleecode.......the codeinfo of the callee
1280            frame............source frame, only the synch. slots are used
1281
1282    OUT:
1283        *es..............the execution state after pushing the stack frame
1284   
1285 *******************************************************************************/
1286
1287 void replace_push_activation_record(executionstate_t *es,
1288                                                                         rplpoint *rpcall,
1289                                                                         codeinfo *calleecode,
1290                                                                         sourceframe_t *frame)
1291 {
1292         s4 reg;
1293         s4 i;
1294         s4 count;
1295         stackslot_t *basesp;
1296         stackslot_t *sp;
1297
1298         assert(es);
1299         assert(rpcall && rpcall->type == RPLPOINT_TYPE_CALL);
1300         assert(calleecode);
1301         assert(frame);
1302
1303         /* write the return address */
1304
1305         es->sp -= SIZE_OF_STACKSLOT;
1306
1307         DOLOG( printf("writing return address %p to %p\n",
1308                                 (void*) (rpcall->pc + rpcall->callsize),
1309                                 (void*) es->sp); );
1310
1311         *((stackslot_t *)es->sp) = (stackslot_t) (rpcall->pc + rpcall->callsize);
1312
1313         /* we move into a new code unit */
1314
1315         es->code = calleecode;
1316
1317         /* set the new pc XXX not needed */
1318
1319         es->pc = es->code->entrypoint;
1320
1321         /* build the stackframe */
1322
1323         DOLOG( printf("building stackframe of %d words at %p\n",
1324                                 es->code->stackframesize, (void*)es->sp); );
1325
1326         sp = (stackslot_t *) es->sp;
1327         basesp = sp;
1328
1329         sp -= es->code->stackframesize;
1330         es->sp = (u1*) sp;
1331
1332         /* in debug mode, invalidate stack frame first */
1333
1334 #if !defined(NDEBUG)
1335         for (i=0; i<(basesp - sp); ++i) {
1336                 sp[i] = 0xdeaddeadU;
1337         }
1338 #endif
1339
1340         /* save int registers */
1341
1342         reg = INT_REG_CNT;
1343         for (i=0; i<es->code->savedintcount; ++i) {
1344                 while (nregdescint[--reg] != REG_SAV)
1345                         ;
1346                 *--basesp = es->intregs[reg];
1347
1348 #if !defined(NDEBUG)
1349                 es->intregs[reg] = 0x44dead4444dead44ULL;
1350 #endif
1351         }
1352
1353         /* save flt registers */
1354
1355         /* XXX align? */
1356         reg = FLT_REG_CNT;
1357         for (i=0; i<es->code->savedfltcount; ++i) {
1358                 while (nregdescfloat[--reg] != REG_SAV)
1359                         ;
1360                 basesp -= STACK_SLOTS_PER_FLOAT;
1361                 *(u8*)basesp = es->fltregs[reg];
1362
1363 #if !defined(NDEBUG)
1364                 es->fltregs[reg] = 0x44dead4444dead44ULL;
1365 #endif
1366         }
1367
1368         /* write slots used for synchronization */
1369
1370         count = code_get_sync_slot_count(es->code);
1371         assert(count == frame->syncslotcount);
1372         for (i=0; i<count; ++i) {
1373                 sp[es->code->memuse + i] = frame->syncslots[i];
1374         }
1375
1376         /* set the PV */
1377
1378         es->pv = es->code->entrypoint;
1379 }
1380
1381
1382 /* replace_find_replacement_point **********************************************
1383
1384    Find the replacement point in the given code corresponding to the
1385    position given in the source frame.
1386    
1387    IN:
1388            code.............the codeinfo in which to search the rplpoint
1389            ss...............the source state defining the position to look for
1390            parent...........parent replacement point to match
1391
1392    RETURN VALUE:
1393        the replacement point
1394   
1395 *******************************************************************************/
1396
1397 rplpoint * replace_find_replacement_point(codeinfo *code,
1398                                                                                   sourcestate_t *ss,
1399                                                                                   rplpoint *parent)
1400 {
1401         sourceframe_t *frame;
1402         methodinfo *m;
1403         rplpoint *rp;
1404         s4        i;
1405         s4        j;
1406         s4        stacki;
1407         rplalloc *ra;
1408
1409         assert(ss);
1410
1411         frame = ss->frames;
1412         assert(frame);
1413
1414         DOLOG( printf("searching replacement point for:\n");
1415                    replace_source_frame_println(frame); );
1416
1417         m = frame->method;
1418
1419         DOLOG( printf("code = %p\n", (void*)code); );
1420
1421         rp = code->rplpoints;
1422         i = code->rplpointcount;
1423         while (i--) {
1424                 if (rp->id == frame->id && rp->method == frame->method
1425                                 && rp->parent == parent)
1426                 {
1427                         /* check if returnAddresses match */
1428                         /* XXX optimize: only do this if JSRs in method */
1429                         DOLOG( printf("checking match for:");
1430                                    replace_replacement_point_println(rp, 1); fflush(stdout); );
1431                         ra = rp->regalloc;
1432                         stacki = 0;
1433                         for (j = rp->regalloccount; j--; ++ra) {
1434                                 if (ra->type == TYPE_RET) {
1435                                         if (ra->index == RPLALLOC_STACK) {
1436                                                 assert(stacki < frame->javastackdepth);
1437                                                 if (frame->javastack[stacki] != ra->regoff)
1438                                                         goto no_match;
1439                                                 stacki++;
1440                                         }
1441                                         else {
1442                                                 assert(ra->index >= 0 && ra->index < frame->javalocalcount);
1443                                                 if (frame->javalocals[ra->index] != ra->regoff)
1444                                                         goto no_match;
1445                                         }
1446                                 }
1447                         }
1448
1449                         /* found */
1450                         return rp;
1451                 }
1452 no_match:
1453                 rp++;
1454         }
1455
1456         assert(0);
1457         return NULL; /* NOT REACHED */
1458 }
1459
1460
1461 /* replace_me ******************************************************************
1462  
1463    This function is called by asm_replacement_out when a thread reaches
1464    a replacement point. `replace_me` must map the execution state to the
1465    target replacement point and let execution continue there.
1466
1467    This function never returns!
1468   
1469    IN:
1470        rp...............replacement point that has been reached
1471            es...............execution state read by asm_replacement_out
1472   
1473 *******************************************************************************/
1474
1475 void replace_me(rplpoint *rp, executionstate_t *es)
1476 {
1477         rplpoint     *target;
1478         sourcestate_t ss;
1479         s4            dumpsize;
1480         rplpoint     *candidate;
1481         codeinfo     *code;
1482         s4            i;
1483         s4            depth;
1484         rplpoint     *origrp;
1485         rplpoint     *parent;
1486
1487         origrp = rp;
1488
1489         es->code = rp->code;
1490
1491         DOLOG( printf("REPLACING: "); method_println(es->code->m); );
1492         REPLACE_COUNT(stat_replacements);
1493
1494         /* mark start of dump memory area */
1495
1496         dumpsize = dump_size();
1497
1498         /* fetch the target of the replacement */
1499
1500         target = rp->target;
1501
1502         DOLOG( printf("replace_me(%p,%p)\n",(void*)rp,(void*)es); fflush(stdout);
1503                    replace_replacement_point_println(rp, 1);
1504                    replace_executionstate_println(es); );
1505
1506         /* read execution state of old code */
1507
1508         ss.frames = NULL;
1509
1510         /* XXX testing */
1511
1512         depth = 0;
1513         candidate = rp;
1514         do {
1515                 DOLOG( printf("recovering source state for%s:\n",
1516                                         (ss.frames == NULL) ? " TOPFRAME" : "");
1517                            replace_replacement_point_println(candidate, 1); );
1518
1519                 replace_read_executionstate(candidate, es, &ss, ss.frames == NULL);
1520                 REPLACE_COUNT(stat_frames);
1521                 depth++;
1522
1523 #if defined(REPLACE_STATISTICS)
1524                 int adr = 0; int ret = 0; int prim = 0; int vd = 0; int n = 0;
1525                 for (i=0; i<ss.frames->javalocalcount; ++i) {
1526                         switch (ss.frames->javalocaltype[i]) {
1527                                 case TYPE_ADR: adr++; break;
1528                                 case TYPE_RET: ret++; break;
1529                                 case TYPE_INT: case TYPE_LNG: case TYPE_FLT: case TYPE_DBL: prim++; break;
1530                                 case TYPE_VOID: vd++; break;
1531                                 default: assert(0);
1532                         }
1533                         n++;
1534                 }
1535                 REPLACE_COUNT_DIST(stat_dist_locals, n);
1536                 REPLACE_COUNT_DIST(stat_dist_locals_adr, adr);
1537                 REPLACE_COUNT_DIST(stat_dist_locals_void, vd);
1538                 REPLACE_COUNT_DIST(stat_dist_locals_ret, ret);
1539                 REPLACE_COUNT_DIST(stat_dist_locals_prim, prim);
1540                 adr = ret = prim = n = 0;
1541                 for (i=0; i<ss.frames->javastackdepth; ++i) {
1542                         switch (ss.frames->javastacktype[i]) {
1543                                 case TYPE_ADR: adr++; break;
1544                                 case TYPE_RET: ret++; break;
1545                                 case TYPE_INT: case TYPE_LNG: case TYPE_FLT: case TYPE_DBL: prim++; break;
1546                         }
1547                         n++;
1548                 }
1549                 REPLACE_COUNT_DIST(stat_dist_stack, n);
1550                 REPLACE_COUNT_DIST(stat_dist_stack_adr, adr);
1551                 REPLACE_COUNT_DIST(stat_dist_stack_ret, ret);
1552                 REPLACE_COUNT_DIST(stat_dist_stack_prim, prim);
1553 #endif /* defined(REPLACE_STATISTICS) */
1554
1555                 if (candidate->parent) {
1556                         DOLOG( printf("INLINED!\n"); );
1557                         candidate = candidate->parent;
1558                         assert(candidate->type == RPLPOINT_TYPE_INLINE);
1559                         REPLACE_COUNT(stat_unroll_inline);
1560                 }
1561                 else {
1562                         DOLOG( printf("UNWIND\n"); );
1563                         REPLACE_COUNT(stat_unroll_call);
1564                         if (!replace_pop_activation_record(es, ss.frames)) {
1565                                 DOLOG( printf("BREAKING\n"); );
1566                                 break;
1567                         }
1568                         DOLOG( replace_executionstate_println(es); );
1569                         candidate = NULL;
1570                         rp = es->code->rplpoints;
1571                         for (i=0; i<es->code->rplpointcount; ++i, ++rp)
1572                                 if (rp->pc <= es->pc)
1573                                         candidate = rp;
1574                         if (!candidate)
1575                                 DOLOG( printf("NO CANDIDATE!\n"); );
1576                         else {
1577                                 DOLOG( printf("found replacement point.\n");
1578                                            replace_replacement_point_println(candidate, 1); );
1579                                 assert(candidate->type == RPLPOINT_TYPE_CALL);
1580                         }
1581                 }
1582         } while (candidate);
1583
1584         REPLACE_COUNT_DIST(stat_dist_frames, depth);
1585         DOLOG( replace_sourcestate_println(&ss); );
1586
1587         /* write execution state of new code */
1588
1589         DOLOG( replace_executionstate_println(es); );
1590
1591         code = es->code;
1592
1593         /* XXX get new code */
1594
1595         parent = NULL;
1596         while (ss.frames) {
1597
1598                 candidate = replace_find_replacement_point(code, &ss, parent);
1599
1600                 DOLOG( printf("creating execution state for%s:\n",
1601                                 (ss.frames->up == NULL) ? " TOPFRAME" : "");
1602                            replace_replacement_point_println(ss.frames->debug_rp, 1);
1603                            replace_replacement_point_println(candidate, 1); );
1604
1605                 replace_write_executionstate(candidate, es, &ss, ss.frames->up == NULL);
1606                 if (ss.frames == NULL)
1607                         break;
1608                 DOLOG( replace_executionstate_println(es); );
1609
1610                 if (candidate->type == RPLPOINT_TYPE_CALL) {
1611                         if (!ss.frames->method->code || ss.frames->method->code->invalid) {
1612                                 REPLACE_COUNT(stat_recompile);
1613                                 if (!jit_recompile(ss.frames->method))
1614                                         /* XXX exception */;
1615                         }
1616                         code = ss.frames->method->code;
1617                         assert(code);
1618                         DOLOG( printf("pushing activation record for:\n");
1619                                    replace_replacement_point_println(candidate, 1); );
1620                         replace_push_activation_record(es, candidate, code, ss.frames);
1621                         parent = NULL;
1622                 }
1623                 else {
1624                         parent = candidate;
1625                 }
1626                 DOLOG( replace_executionstate_println(es); );
1627         }
1628
1629         DOLOG( replace_executionstate_println(es); );
1630
1631         assert(candidate);
1632         if (candidate == origrp) {
1633                 printf("WARNING: identity replacement, turning off rp to avoid infinite loop");
1634                 replace_deactivate_replacement_point(origrp);
1635         }
1636
1637         /* release dump area */
1638
1639         dump_release(dumpsize);
1640
1641         /* enter new code */
1642
1643         DOLOG( printf("JUMPING IN!\n"); fflush(stdout); );
1644
1645 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
1646         asm_replacement_in(es);
1647 #endif
1648         abort(); /* NOT REACHED */
1649 }
1650
1651
1652 /* replace_replacement_point_println *******************************************
1653  
1654    Print replacement point info.
1655   
1656    IN:
1657        rp...............the replacement point to print
1658   
1659 *******************************************************************************/
1660
1661 #if !defined(NDEBUG)
1662
1663 #define TYPECHAR(t)  (((t) >= 0 && (t) <= TYPE_RET) ? show_jit_type_letters[t] : '?')
1664
1665 static char *replace_type_str[] = {
1666         "STD",
1667         "EXH",
1668         "SBR",
1669         "CALL",
1670         "INLINE",
1671         "RETURN",
1672         "BODY"
1673 };
1674
1675 void replace_replacement_point_println(rplpoint *rp, int depth)
1676 {
1677         int j;
1678         int index;
1679
1680         if (!rp) {
1681                 printf("(rplpoint *)NULL\n");
1682                 return;
1683         }
1684
1685         for (j=0; j<depth; ++j)
1686                 putchar('\t');
1687
1688         printf("rplpoint (id %d) %p pc:%p+%d out:%p target:%p mcode:%016llx type:%s",
1689                         rp->id, (void*)rp,rp->pc,rp->callsize,rp->outcode,(void*)rp->target,
1690                         (unsigned long long)rp->mcode,replace_type_str[rp->type]);
1691         if (rp->flags & RPLPOINT_FLAG_NOTRAP)
1692                 printf(" NOTRAP");
1693         printf(" parent:%p\n", (void*)rp->parent);
1694         for (j=0; j<depth; ++j)
1695                 putchar('\t');
1696         printf("ra:%d = [",     rp->regalloccount);
1697
1698         for (j=0; j<rp->regalloccount; ++j) {
1699                 if (j)
1700                         putchar(' ');
1701                 index = rp->regalloc[j].index;
1702                 switch (index) {
1703                         case RPLALLOC_STACK: printf("S"); break;
1704                         case RPLALLOC_PARAM: printf("P"); break;
1705                         case RPLALLOC_SYNC : printf("Y"); break;
1706                         default: printf("%d", index);
1707                 }
1708                 printf(":%1c:", TYPECHAR(rp->regalloc[j].type));
1709                 if (rp->regalloc[j].type == TYPE_RET) {
1710                         printf("ret(L%03d)", rp->regalloc[j].regoff);
1711                 }
1712                 else {
1713                         show_allocation(rp->regalloc[j].type, rp->regalloc[j].flags, rp->regalloc[j].regoff);
1714                 }
1715         }
1716
1717         printf("]\n");
1718         for (j=0; j<depth; ++j)
1719                 putchar('\t');
1720         printf("method: ");
1721         method_print(rp->method);
1722
1723         printf("\n");
1724 }
1725 #endif
1726
1727
1728 /* replace_show_replacement_points *********************************************
1729  
1730    Print replacement point info.
1731   
1732    IN:
1733        code.............codeinfo whose replacement points should be printed.
1734   
1735 *******************************************************************************/
1736
1737 #if !defined(NDEBUG)
1738 void replace_show_replacement_points(codeinfo *code)
1739 {
1740         int i;
1741         int depth;
1742         rplpoint *rp;
1743         rplpoint *parent;
1744
1745         if (!code) {
1746                 printf("(codeinfo *)NULL\n");
1747                 return;
1748         }
1749
1750         printf("\treplacement points: %d\n",code->rplpointcount);
1751
1752         printf("\ttotal allocations : %d\n",code->regalloccount);
1753         printf("\tsaved int regs    : %d\n",code->savedintcount);
1754         printf("\tsaved flt regs    : %d\n",code->savedfltcount);
1755         printf("\tmemuse            : %d\n",code->memuse);
1756
1757         printf("\n");
1758
1759         for (i=0; i<code->rplpointcount; ++i) {
1760                 rp = code->rplpoints + i;
1761
1762                 assert(rp->code == code);
1763
1764                 depth = 1;
1765                 parent = rp->parent;
1766                 while (parent) {
1767                         depth++;
1768                         parent = parent->parent;
1769                 }
1770                 replace_replacement_point_println(rp, depth);
1771         }
1772 }
1773 #endif
1774
1775
1776 /* replace_executionstate_println **********************************************
1777  
1778    Print execution state
1779   
1780    IN:
1781        es...............the execution state to print
1782   
1783 *******************************************************************************/
1784
1785 #if !defined(NDEBUG)
1786 void replace_executionstate_println(executionstate_t *es)
1787 {
1788         int i;
1789         int slots;
1790         stackslot_t *sp;
1791         int extraslots;
1792         
1793         if (!es) {
1794                 printf("(executionstate_t *)NULL\n");
1795                 return;
1796         }
1797
1798         printf("executionstate_t:\n");
1799         printf("\tpc = %p",(void*)es->pc);
1800         printf("  sp = %p",(void*)es->sp);
1801         printf("  pv = %p\n",(void*)es->pv);
1802 #if defined(ENABLE_DISASSEMBLER)
1803         for (i=0; i<INT_REG_CNT; ++i) {
1804                 if (i%4 == 0)
1805                         printf("\t");
1806                 else
1807                         printf(" ");
1808                 printf("%-3s = %016llx",regs[i],(unsigned long long)es->intregs[i]);
1809                 if (i%4 == 3)
1810                         printf("\n");
1811         }
1812         for (i=0; i<FLT_REG_CNT; ++i) {
1813                 if (i%4 == 0)
1814                         printf("\t");
1815                 else
1816                         printf(" ");
1817                 printf("F%02d = %016llx",i,(unsigned long long)es->fltregs[i]);
1818                 if (i%4 == 3)
1819                         printf("\n");
1820         }
1821 #endif
1822
1823         sp = (stackslot_t *) es->sp;
1824
1825         extraslots = 2;
1826
1827         if (es->code) {
1828                 methoddesc *md = es->code->m->parseddesc;
1829                 slots = code_get_stack_frame_size(es->code);
1830                 extraslots = 1 + md->memuse;
1831         }
1832         else
1833                 slots = 0;
1834
1835
1836         if (slots) {
1837                 printf("\tstack slots(+%d) at sp:", extraslots);
1838                 for (i=0; i<slots+extraslots; ++i) {
1839                         if (i%4 == 0)
1840                                 printf("\n\t\t");
1841                         printf("M%02d%c", i, (i >= slots) ? '(' : ' ');
1842 #ifdef HAS_4BYTE_STACKSLOT
1843                         printf("%08lx",(unsigned long)*sp++);
1844 #else
1845                         printf("%016llx",(unsigned long long)*sp++);
1846 #endif
1847                         printf("%c", (i >= slots) ? ')' : ' ');
1848                 }
1849                 printf("\n");
1850         }
1851
1852         printf("\tcode: %p", (void*)es->code);
1853         if (es->code != NULL) {
1854                 printf(" stackframesize=%d ", es->code->stackframesize);
1855                 method_print(es->code->m);
1856         }
1857         printf("\n");
1858
1859         printf("\n");
1860 }
1861 #endif
1862
1863 #if !defined(NDEBUG)
1864 void java_value_print(s4 type, u8 value)
1865 {
1866         java_objectheader *obj;
1867         utf               *u;
1868
1869         printf("%016llx",(unsigned long long) value);
1870
1871         if (type < 0 || type > TYPE_RET)
1872                 printf(" <INVALID TYPE:%d>", type);
1873         else
1874                 printf(" %s", show_jit_type_names[type]);
1875
1876         if (type == TYPE_ADR && value != 0) {
1877                 obj = (java_objectheader *) (ptrint) value;
1878                 putchar(' ');
1879                 utf_display_printable_ascii_classname(obj->vftbl->class->name);
1880
1881                 if (obj->vftbl->class == class_java_lang_String) {
1882                         printf(" \"");
1883                         u = javastring_toutf((java_lang_String *)obj, false);
1884                         utf_display_printable_ascii(u);
1885                         printf("\"");
1886                 }
1887         }
1888         else if (type == TYPE_INT || type == TYPE_LNG) {
1889                 printf(" %lld", (long long) value);
1890         }
1891 }
1892 #endif /* !defined(NDEBUG) */
1893
1894
1895 #if !defined(NDEBUG)
1896 void replace_source_frame_println(sourceframe_t *frame)
1897 {
1898         s4 i;
1899         s4 t;
1900
1901         printf("\t");
1902         method_println(frame->method);
1903         printf("\tid: %d\n", frame->id);
1904         printf("\n");
1905
1906         if (frame->javalocalcount) {
1907                 printf("\tlocals (%d):\n",frame->javalocalcount);
1908                 for (i=0; i<frame->javalocalcount; ++i) {
1909                         t = frame->javalocaltype[i];
1910                         if (t == TYPE_VOID) {
1911                                 printf("\tlocal[ %2d] = void\n",i);
1912                         }
1913                         else {
1914                                 printf("\tlocal[%c%2d] = ",TYPECHAR(t),i);
1915                                 java_value_print(t, frame->javalocals[i]);
1916                                 printf("\n");
1917                         }
1918                 }
1919                 printf("\n");
1920         }
1921
1922         if (frame->javastackdepth) {
1923                 printf("\tstack (depth %d):\n",frame->javastackdepth);
1924                 for (i=0; i<frame->javastackdepth; ++i) {
1925                         t = frame->javastacktype[i];
1926                         if (t == TYPE_VOID) {
1927                                 printf("\tstack[%2d] = void", i);
1928                         }
1929                         else {
1930                                 printf("\tstack[%2d] = ",i);
1931                                 java_value_print(frame->javastacktype[i], frame->javastack[i]);
1932                                 printf("\n");
1933                         }
1934                 }
1935                 printf("\n");
1936         }
1937
1938         if (frame->syncslotcount) {
1939                 printf("\tsynchronization slots (%d):\n",frame->syncslotcount);
1940                 for (i=0; i<frame->syncslotcount; ++i) {
1941                         printf("\tslot[%2d] = ",i);
1942 #ifdef HAS_4BYTE_STACKSLOT
1943                         printf("%08lx\n",(unsigned long) frame->syncslots[i]);
1944 #else
1945                         printf("%016llx\n",(unsigned long long) frame->syncslots[i]);
1946 #endif
1947                 }
1948                 printf("\n");
1949         }
1950 }
1951 #endif /* !defined(NDEBUG) */
1952
1953
1954 /* replace_sourcestate_println *************************************************
1955  
1956    Print source state
1957   
1958    IN:
1959        ss...............the source state to print
1960   
1961 *******************************************************************************/
1962
1963 #if !defined(NDEBUG)
1964 void replace_sourcestate_println(sourcestate_t *ss)
1965 {
1966         int i;
1967         sourceframe_t *frame;
1968
1969         if (!ss) {
1970                 printf("(sourcestate_t *)NULL\n");
1971                 return;
1972         }
1973
1974         printf("sourcestate_t:\n");
1975
1976         for (i=0, frame = ss->frames; frame != NULL; frame = frame->up, ++i) {
1977                 printf("    frame %d:\n", i);
1978                 replace_source_frame_println(frame);
1979         }
1980 }
1981 #endif
1982
1983 /*
1984  * These are local overrides for various environment variables in Emacs.
1985  * Please do not remove this and leave it at the end of the file, where
1986  * Emacs will automagically detect them.
1987  * ---------------------------------------------------------------------
1988  * Local variables:
1989  * mode: c
1990  * indent-tabs-mode: t
1991  * c-basic-offset: 4
1992  * tab-width: 4
1993  * End:
1994  * vim:noexpandtab:sw=4:ts=4:
1995  */