CACAO
replace.cpp
Go to the documentation of this file.
1 /* src/vm/jit/replace.cpp - on-stack replacement of methods
2 
3  Copyright (C) 1996-2013
4  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 
6  This file is part of CACAO.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2, or (at
11  your option) any later version.
12 
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  02110-1301, USA.
22 
23 */
24 
25 
26 #include "config.h"
27 #include "vm/types.hpp"
28 
29 #include <assert.h>
30 #include <stdint.h>
31 #include <stdlib.h>
32 
33 #include "arch.hpp"
34 #include "md.hpp"
35 
36 #if defined(ENABLE_GC_CACAO)
37 # include "mm/cacao-gc/gc.h"
38 #endif
39 
40 #include "mm/dumpmemory.hpp"
41 #include "mm/memory.hpp"
42 
43 #include "threads/thread.hpp"
44 
45 #include "toolbox/logging.hpp"
46 
47 #include "vm/classcache.hpp"
48 #include "vm/descriptor.hpp"
49 #include "vm/globals.hpp"
50 #include "vm/options.hpp"
51 #include "vm/string.hpp"
52 
53 #if defined(ENABLE_RT_TIMING)
54 # include "vm/rt-timing.hpp"
55 #endif
56 
57 #include "vm/jit/abi.hpp"
58 #include "vm/jit/asmpart.hpp"
59 #include "vm/jit/disass.hpp"
61 #include "vm/jit/jit.hpp"
62 #include "vm/jit/methodheader.hpp"
63 #include "vm/jit/replace.hpp"
64 #include "vm/jit/show.hpp"
65 #include "vm/jit/stack.hpp"
66 #include "vm/jit/stacktrace.hpp"
67 
69 
70 
71 #define REPLACE_PATCH_DYNAMIC_CALL
72 /*#define REPLACE_PATCH_ALL*/
73 
74 
75 /*** debugging ****************************************************************/
76 
77 #if !defined(NDEBUG)
78 static void java_value_print(s4 type, replace_val_t value);
80 #endif
81 
82 #if !defined(NDEBUG)
83 #define DOLOG(code) do{ if (opt_TraceReplacement > 1) { code; } } while(0)
84 #define DOLOG_SHORT(code) do{ if (opt_TraceReplacement > 0) { code; } } while(0)
85 #else
86 #define DOLOG(code)
87 #define DOLOG_SHORT(code)
88 #endif
89 
90 
91 /*** statistics ***************************************************************/
92 
93 #define REPLACE_STATISTICS
94 
95 #if defined(REPLACE_STATISTICS)
96 
97 static int stat_replacements = 0;
98 static int stat_frames = 0;
99 static int stat_recompile = 0;
100 static int stat_staticpatch = 0;
101 static int stat_unroll_inline = 0;
102 static int stat_unroll_call = 0;
103 static int stat_dist_frames[20] = { 0 };
104 static int stat_dist_locals[20] = { 0 };
105 static int stat_dist_locals_adr[10] = { 0 };
106 static int stat_dist_locals_prim[10] = { 0 };
107 static int stat_dist_locals_ret[10] = { 0 };
108 static int stat_dist_locals_void[10] = { 0 };
109 static int stat_dist_stack[10] = { 0 };
110 static int stat_dist_stack_adr[10] = { 0 };
111 static int stat_dist_stack_prim[10] = { 0 };
112 static int stat_dist_stack_ret[10] = { 0 };
113 static int stat_methods = 0;
114 static int stat_rploints = 0;
115 static int stat_regallocs = 0;
116 static int stat_dist_method_rplpoints[20] = { 0 };
117 
118 #define REPLACE_COUNT(cnt) (cnt)++
119 #define REPLACE_COUNT_IF(cnt, cond) do{ if(cond) (cnt)++; } while(0)
120 #define REPLACE_COUNT_INC(cnt, inc) ((cnt) += (inc))
121 
122 #define REPLACE_COUNT_DIST(array, val) \
123  do { \
124  int limit = (sizeof(array) / sizeof(int)) - 1; \
125  if ((val) < (limit)) (array)[val]++; \
126  else (array)[limit]++; \
127  } while (0)
128 
129 static void replace_statistics_source_frame(sourceframe_t *frame);
130 
131 #else
132 
133 #define REPLACE_COUNT(cnt)
134 #define REPLACE_COUNT_IF(cnt, cond)
135 #define REPLACE_COUNT_INC(cnt, inc)
136 #define REPLACE_COUNT_DIST(array, val)
137 
138 #endif /* defined(REPLACE_STATISTICS) */
139 
140 
141 /*** constants used internally ************************************************/
142 
143 #define TOP_IS_NORMAL 0
144 #define TOP_IS_ON_STACK 1
145 #define TOP_IS_IN_ITMP1 2
146 #define TOP_IS_VOID 3
147 
148 
149 /******************************************************************************/
150 /* PART I: Creating / freeing replacement points */
151 /******************************************************************************/
152 
153 
154 /* replace_create_replacement_point ********************************************
155 
156  Create a replacement point.
157 
158  IN:
159  jd...............current jitdata
160  iinfo............inlining info for the current position
161  rp...............pre-allocated (uninitialized) rplpoint
162  type.............rplpoint::TYPE constant
163  iptr.............current instruction
164  *pra.............current rplalloc pointer
165  javalocals.......the javalocals at the current point
166  stackvars........the stack variables at the current point
167  stackdepth.......the stack depth at the current point
168  paramcount.......number of parameters at the start of stackvars
169 
170  OUT:
171  *rpa.............points to the next free rplalloc
172 
173 *******************************************************************************/
174 
176  insinfo_inline *iinfo,
177  rplpoint *rp,
178  rplpoint::Type type,
179  instruction *iptr,
180  rplalloc **pra,
181  s4 *javalocals,
182  s4 *stackvars,
183  s4 stackdepth,
184  s4 paramcount)
185 {
186  rplalloc *ra;
187  s4 i;
188  varinfo *v;
189  s4 index;
190 
191  ra = *pra;
192 
194 
195  rp->method = (iinfo) ? iinfo->method : jd->m;
196  rp->pc = NULL; /* set by codegen */
197  rp->callsize = 0; /* set by codegen */
198  rp->regalloc = ra;
199  rp->flags = 0;
200  rp->type = type;
201  rp->id = iptr->flags.bits >> INS_FLAG_ID_SHIFT;
202 
203  /* XXX unify these two fields */
204  rp->parent = (iinfo) ? iinfo->rp : NULL;
205 
206  /* store local allocation info of javalocals */
207 
208  if (javalocals) {
209  for (i = 0; i < rp->method->maxlocals; ++i) {
210  index = javalocals[i];
211  if (index == jitdata::UNUSED)
212  continue;
213 
214  ra->index = i;
215  if (index >= 0) {
216  v = VAR(index);
217  ra->flags = v->flags & (INMEMORY);
218  ra->regoff = v->vv.regoff;
219  ra->type = v->type;
220  }
221  else {
222  ra->regoff = RETADDR_FROM_JAVALOCAL(index);
223  ra->type = TYPE_RET;
224  ra->flags = 0;
225  }
226  ra++;
227  }
228  }
229 
230  /* store allocation info of java stack vars */
231 
232  for (i = 0; i < stackdepth; ++i) {
233  v = VAR(stackvars[i]);
234  ra->flags = v->flags & (INMEMORY);
235  ra->index = (i < paramcount) ? RPLALLOC_PARAM : RPLALLOC_STACK;
236  ra->type = v->type;
237  /* XXX how to handle locals on the stack containing returnAddresses? */
238  if (v->type == TYPE_RET) {
239  assert(stackvars[i] >= jd->localcount);
240  ra->regoff = v->vv.retaddr->nr;
241  }
242  else
243  ra->regoff = v->vv.regoff;
244  ra++;
245  }
246 
247  /* total number of allocations */
248 
249  rp->regalloccount = ra - rp->regalloc;
250 
251  *pra = ra;
252 }
253 
254 
255 /* replace_create_inline_start_replacement_point *******************************
256 
257  Create an INLINE_START replacement point.
258 
259  IN:
260  jd...............current jitdata
261  rp...............pre-allocated (uninitialized) rplpoint
262  iptr.............current instruction
263  *pra.............current rplalloc pointer
264  javalocals.......the javalocals at the current point
265 
266  OUT:
267  *rpa.............points to the next free rplalloc
268 
269  RETURN VALUE:
270  the insinfo_inline * for the following inlined body
271 
272 *******************************************************************************/
273 
275  jitdata *jd,
276  rplpoint *rp,
277  instruction *iptr,
278  rplalloc **pra,
279  s4 *javalocals)
280 {
281  insinfo_inline *calleeinfo;
282  rplalloc *ra;
283 
284  calleeinfo = iptr->sx.s23.s3.inlineinfo;
285 
286  calleeinfo->rp = rp;
287 
288  replace_create_replacement_point(jd, calleeinfo->parent, rp,
289  rplpoint::TYPE_INLINE, iptr, pra,
290  javalocals,
291  calleeinfo->stackvars, calleeinfo->stackvarscount,
292  calleeinfo->paramcount);
293 
294  if (calleeinfo->synclocal != jitdata::UNUSED) {
295  ra = (*pra)++;
296  ra->index = RPLALLOC_SYNC;
297  ra->regoff = jd->var[calleeinfo->synclocal].vv.regoff;
298  ra->flags = jd->var[calleeinfo->synclocal].flags & INMEMORY;
299  ra->type = TYPE_ADR;
300 
301  rp->regalloccount++;
302  }
303 
304  return calleeinfo;
305 }
306 
307 
308 /* replace_create_replacement_points *******************************************
309 
310  Create the replacement points for the given code.
311 
312  IN:
313  jd...............current jitdata, must not have any replacement points
314 
315  OUT:
316  code->rplpoints.......set to the list of replacement points
317  code->rplpointcount...number of replacement points
318  code->regalloc........list of allocation info
319  code->regalloccount...total length of allocation info list
320  code->globalcount.....number of global allocations at the
321  start of code->regalloc
322 
323  RETURN VALUE:
324  true.............everything ok
325  false............an exception has been thrown
326 
327 *******************************************************************************/
328 
329 #define CLEAR_javalocals(array, method) \
330  do { \
331  for (i=0; i<(method)->maxlocals; ++i) \
332  (array)[i] = jitdata::UNUSED; \
333  } while (0)
334 
335 #define COPY_OR_CLEAR_javalocals(dest, array, method) \
336  do { \
337  if ((array) != NULL) \
338  MCOPY((dest), (array), s4, (method)->maxlocals); \
339  else \
340  CLEAR_javalocals((dest), (method)); \
341  } while (0)
342 
343 #define COUNT_javalocals(array, method, counter) \
344  do { \
345  for (i=0; i<(method)->maxlocals; ++i) \
346  if ((array)[i] != jitdata::UNUSED) \
347  (counter)++; \
348  } while (0)
349 
351 {
352  codeinfo *code;
353  registerdata *rd;
354  basicblock *bptr;
355  int count;
356  methodinfo *m;
357  rplpoint *rplpoints;
358  rplpoint *rp;
359  int alloccount;
360  rplalloc *regalloc;
361  rplalloc *ra;
362  int i;
363  instruction *iptr;
364  instruction *iend;
365  s4 *javalocals;
366  s4 *jl;
367  methoddesc *md;
368  insinfo_inline *iinfo;
369  s4 startcount;
370  s4 firstcount;
371 #if defined(REPLACE_PATCH_DYNAMIC_CALL)
372  bool needentry;
373 #endif
374 
376 
377  /* get required compiler data */
378 
379  code = jd->code;
380  rd = jd->rd;
381 
382  /* assert that we wont overwrite already allocated data */
383 
384  assert(code);
385  assert(code->m);
386  assert(code->rplpoints == NULL);
387  assert(code->rplpointcount == 0);
388  assert(code->regalloc == NULL);
389  assert(code->regalloccount == 0);
390  assert(code->globalcount == 0);
391 
392  m = code->m;
393 
394  /* in instance methods, we may need a rplpoint at the method entry */
395 
396 #if defined(REPLACE_PATCH_DYNAMIC_CALL)
397  if (!(m->flags & ACC_STATIC)) {
399  needentry = true;
400  }
401  else {
402  needentry = false;
403  }
404 #endif /* defined(REPLACE_PATCH_DYNAMIC_CALL) */
405 
406  /* iterate over the basic block list to find replacement points */
407 
408  count = 0;
409  alloccount = 0;
410 
411  javalocals = (s4*) DumpMemory::allocate(sizeof(s4) * jd->maxlocals);
412 
413  for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
414 
415  /* skip dead code */
416 
417  if (bptr->state < basicblock::FINISHED)
418  continue;
419 
420  /* get info about this block */
421 
422  m = bptr->method;
423  iinfo = bptr->inlineinfo;
424 
425  /* initialize javalocals at the start of this block */
426 
427  COPY_OR_CLEAR_javalocals(javalocals, bptr->javalocals, m);
428 
429  /* iterate over the instructions */
430 
431  iptr = bptr->iinstr;
432  iend = iptr + bptr->icount;
433  startcount = count;
434  firstcount = count;
435 
436  for (; iptr != iend; ++iptr) {
437  switch (iptr->opc) {
438 #if defined(ENABLE_GC_CACAO)
439  case ICMD_BUILTIN:
440  md = iptr->sx.s23.s3.bte->md;
441  count++;
442  COUNT_javalocals(javalocals, m, alloccount);
443  alloccount += iptr->s1.argcount;
444  if (iinfo)
445  alloccount -= iinfo->throughcount;
446  break;
447 #endif
448 
449  case ICMD_INVOKESTATIC:
450  case ICMD_INVOKESPECIAL:
451  case ICMD_INVOKEVIRTUAL:
453  INSTRUCTION_GET_METHODDESC(iptr, md);
454  count++;
455  COUNT_javalocals(javalocals, m, alloccount);
456  alloccount += iptr->s1.argcount;
457  if (iinfo)
458  alloccount -= iinfo->throughcount;
459  break;
460 
461  case ICMD_ISTORE:
462  case ICMD_LSTORE:
463  case ICMD_FSTORE:
464  case ICMD_DSTORE:
465  case ICMD_ASTORE:
466  stack_javalocals_store(iptr, javalocals);
467  break;
468 
469  case ICMD_IRETURN:
470  case ICMD_LRETURN:
471  case ICMD_FRETURN:
472  case ICMD_DRETURN:
473  case ICMD_ARETURN:
474  alloccount += 1;
475  /* FALLTHROUGH! */
476  case ICMD_RETURN:
477  count++;
478  break;
479 
480  case ICMD_INLINE_START:
481  iinfo = iptr->sx.s23.s3.inlineinfo;
482 
483  count++;
484  COUNT_javalocals(javalocals, m, alloccount);
485  alloccount += iinfo->stackvarscount;
486  if (iinfo->synclocal != jitdata::UNUSED)
487  alloccount++;
488 
489  m = iinfo->method;
490  /* javalocals may be set at next block start, or now */
491  COPY_OR_CLEAR_javalocals(javalocals, iinfo->javalocals_start, m);
492  break;
493 
494  case ICMD_INLINE_BODY:
495  assert(iinfo == iptr->sx.s23.s3.inlineinfo);
496 
497  jl = iinfo->javalocals_start;
498  if (jl == NULL) {
499  /* get the javalocals from the following block start */
500  assert(bptr->next);
501  jl = bptr->next->javalocals;
502  }
503  count++;
504  COUNT_javalocals(jl, m, alloccount);
505  break;
506 
507  case ICMD_INLINE_END:
508  assert(iinfo == iptr->sx.s23.s3.inlineinfo ||
509  iinfo == iptr->sx.s23.s3.inlineinfo->parent);
510  iinfo = iptr->sx.s23.s3.inlineinfo;
511  m = iinfo->outer;
512  if (iinfo->javalocals_end)
513  MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
514  iinfo = iinfo->parent;
515  break;
516  default:
517  break;
518  }
519 
520  if (iptr == bptr->iinstr)
521  firstcount = count;
522  } /* end instruction loop */
523 
524  /* create replacement points at targets of backward branches */
525  /* We only need the replacement point there, if there is no */
526  /* replacement point inside the block. */
527 
528  if (bptr->bitflags & BBFLAG_REPLACEMENT) {
529 #if defined(REPLACE_PATCH_DYNAMIC_CALL)
530  int test = (needentry && bptr == jd->basicblocks) ? firstcount : count;
531 #else
532  int test = count;
533 #endif
534  if (test > startcount) {
535  /* we don't need an extra rplpoint */
536  bptr->bitflags &= ~BBFLAG_REPLACEMENT;
537  }
538  else {
539  count++;
540  alloccount += bptr->indepth;
541  if (bptr->inlineinfo)
542  alloccount -= bptr->inlineinfo->throughcount;
543 
544  COUNT_javalocals(bptr->javalocals, bptr->method, alloccount);
545  }
546  }
547 
548  } /* end basicblock loop */
549 
550  /* if no points were found, there's nothing to do */
551 
552  if (!count)
553  return true;
554 
555  /* allocate replacement point array and allocation array */
556 
557  rplpoints = MNEW(rplpoint, count);
558  regalloc = MNEW(rplalloc, alloccount);
559  ra = regalloc;
560 
561  /* initialize replacement point structs */
562 
563  rp = rplpoints;
564 
565  /* XXX try to share code with the counting loop! */
566 
567  for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
568  /* skip dead code */
569 
570  if (bptr->state < basicblock::FINISHED)
571  continue;
572 
573  /* get info about this block */
574 
575  m = bptr->method;
576  iinfo = bptr->inlineinfo;
577 
578  /* initialize javalocals at the start of this block */
579 
580  COPY_OR_CLEAR_javalocals(javalocals, bptr->javalocals, m);
581 
582  /* create replacement points at targets of backward branches */
583 
584  if (bptr->bitflags & BBFLAG_REPLACEMENT) {
585 
586  i = (iinfo) ? iinfo->throughcount : 0;
587  replace_create_replacement_point(jd, iinfo, rp++,
588  (rplpoint::Type) bptr->type, bptr->iinstr, &ra,
589  bptr->javalocals, bptr->invars + i, bptr->indepth - i, 0);
590 
592  rp[-1].flags |= rplpoint::FLAG_COUNTDOWN;
593  }
594 
595  /* iterate over the instructions */
596 
597  iptr = bptr->iinstr;
598  iend = iptr + bptr->icount;
599 
600  for (; iptr != iend; ++iptr) {
601  switch (iptr->opc) {
602 #if defined(ENABLE_GC_CACAO)
603  case ICMD_BUILTIN:
604  md = iptr->sx.s23.s3.bte->md;
605 
606  i = (iinfo) ? iinfo->throughcount : 0;
607  replace_create_replacement_point(jd, iinfo, rp++,
608  rplpoint::TYPE_CALL, iptr, &ra,
609  javalocals, iptr->sx.s23.s2.args,
610  iptr->s1.argcount - i,
611  md->paramcount);
612  break;
613 #endif
614 
615  case ICMD_INVOKESTATIC:
616  case ICMD_INVOKESPECIAL:
617  case ICMD_INVOKEVIRTUAL:
619  INSTRUCTION_GET_METHODDESC(iptr, md);
620 
621  i = (iinfo) ? iinfo->throughcount : 0;
622  replace_create_replacement_point(jd, iinfo, rp++,
623  rplpoint::TYPE_CALL, iptr, &ra,
624  javalocals, iptr->sx.s23.s2.args,
625  iptr->s1.argcount - i,
626  md->paramcount);
627  break;
628 
629  case ICMD_ISTORE:
630  case ICMD_LSTORE:
631  case ICMD_FSTORE:
632  case ICMD_DSTORE:
633  case ICMD_ASTORE:
634  stack_javalocals_store(iptr, javalocals);
635  break;
636 
637  case ICMD_IRETURN:
638  case ICMD_LRETURN:
639  case ICMD_FRETURN:
640  case ICMD_DRETURN:
641  case ICMD_ARETURN:
642  replace_create_replacement_point(jd, iinfo, rp++,
643  rplpoint::TYPE_RETURN, iptr, &ra,
644  NULL, &(iptr->s1.varindex), 1, 0);
645  break;
646 
647  case ICMD_RETURN:
648  replace_create_replacement_point(jd, iinfo, rp++,
649  rplpoint::TYPE_RETURN, iptr, &ra,
650  NULL, NULL, 0, 0);
651  break;
652 
653  case ICMD_INLINE_START:
655  jd, rp++, iptr, &ra, javalocals);
656  m = iinfo->method;
657  /* javalocals may be set at next block start, or now */
658  COPY_OR_CLEAR_javalocals(javalocals, iinfo->javalocals_start, m);
659  break;
660 
661  case ICMD_INLINE_BODY:
662  assert(iinfo == iptr->sx.s23.s3.inlineinfo);
663 
664  jl = iinfo->javalocals_start;
665  if (jl == NULL) {
666  /* get the javalocals from the following block start */
667  assert(bptr->next);
668  jl = bptr->next->javalocals;
669  }
670  /* create a non-trappable rplpoint */
671  replace_create_replacement_point(jd, iinfo, rp++,
672  rplpoint::TYPE_BODY, iptr, &ra,
673  jl, NULL, 0, 0);
674  rp[-1].flags |= rplpoint::FLAG_NOTRAP;
675  break;
676 
677  case ICMD_INLINE_END:
678  assert(iinfo == iptr->sx.s23.s3.inlineinfo ||
679  iinfo == iptr->sx.s23.s3.inlineinfo->parent);
680  iinfo = iptr->sx.s23.s3.inlineinfo;
681  m = iinfo->outer;
682  if (iinfo->javalocals_end)
683  MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
684  iinfo = iinfo->parent;
685  break;
686  default:
687  break;
688  }
689  } /* end instruction loop */
690  } /* end basicblock loop */
691 
692  assert((rp - rplpoints) == count);
693  assert((ra - regalloc) == alloccount);
694 
695  /* store the data in the codeinfo */
696 
697  code->rplpoints = rplpoints;
698  code->rplpointcount = count;
699  code->regalloc = regalloc;
700  code->regalloccount = alloccount;
701  code->globalcount = 0;
702  code->memuse = rd->memuse;
703 
705  REPLACE_COUNT_INC(stat_regallocs, alloccount);
706 
707  /* everything alright */
708 
709  return true;
710 }
711 
712 
713 /* replace_free_replacement_points *********************************************
714 
715  Free memory used by replacement points.
716 
717  IN:
718  code.............codeinfo whose replacement points should be freed.
719 
720 *******************************************************************************/
721 
723 {
724  assert(code);
725 
726  if (code->rplpoints)
727  MFREE(code->rplpoints,rplpoint,code->rplpointcount);
728 
729  if (code->regalloc)
730  MFREE(code->regalloc,rplalloc,code->regalloccount);
731 
732  code->rplpoints = NULL;
733  code->rplpointcount = 0;
734  code->regalloc = NULL;
735  code->regalloccount = 0;
736  code->globalcount = 0;
737 }
738 
739 
740 /******************************************************************************/
741 /* PART II: Activating / deactivating replacement points */
742 /******************************************************************************/
743 
744 
745 /* replace_activate_replacement_points *****************************************
746 
747  Activate the replacement points of the given compilation unit. When this
748  function returns, the replacement points are "armed", so each thread
749  reaching one of the points will enter the replacement mechanism.
750 
751  IN:
752  code.............codeinfo of which replacement points should be
753  activated
754  mappable.........if true, only mappable replacement points are
755  activated
756 
757 *******************************************************************************/
758 
760 {
761  rplpoint *rp;
762  s4 i;
763  s4 count;
764  u1 *savedmcode;
765 
766  assert(code->savedmcode == NULL);
767 
768  /* count trappable replacement points */
769 
770  count = 0;
771  i = code->rplpointcount;
772  rp = code->rplpoints;
773  for (; i--; rp++) {
774  if (rp->flags & rplpoint::FLAG_NOTRAP)
775  continue;
776 
777  if (mappable && (rp->type == rplpoint::TYPE_RETURN))
778  continue;
779 
780  count++;
781  }
782 
783  /* allocate buffer for saved machine code */
784 
785  savedmcode = MNEW(u1, count * REPLACEMENT_PATCH_SIZE);
786  code->savedmcode = savedmcode;
787  savedmcode += count * REPLACEMENT_PATCH_SIZE;
788 
789  /* activate trappable replacement points */
790  /* (in reverse order to handle overlapping points within basic blocks) */
791 
792  i = code->rplpointcount;
793  rp = code->rplpoints + i;
794  while (rp--, i--) {
795  assert(!(rp->flags & rplpoint::FLAG_ACTIVE));
796 
797  if (rp->flags & rplpoint::FLAG_NOTRAP)
798  continue;
799 
800  if (mappable && (rp->type == rplpoint::TYPE_RETURN))
801  continue;
802 
803  DOLOG( printf("activate replacement point:\n");
804  replace_replacement_point_println(rp, 1); fflush(stdout); );
805 
806  savedmcode -= REPLACEMENT_PATCH_SIZE;
807 
808 #if defined(ENABLE_JIT)
809 # if defined(ENABLE_DISASSEMBLER)
810  DOLOG( printf("\tinstruction before: ");
811  disassinstr(rp->pc); fflush(stdout); );
812 # endif
813 
814  md_patch_replacement_point(rp->pc, savedmcode, false);
815 
816 # if defined(ENABLE_DISASSEMBLER)
817  DOLOG( printf("\tinstruction after : ");
818  disassinstr(rp->pc); fflush(stdout); );
819 # endif
820 #endif
821 
822  rp->flags |= rplpoint::FLAG_ACTIVE;
823  }
824 
825  assert(savedmcode == code->savedmcode);
826 }
827 
828 
829 /* replace_deactivate_replacement_points ***************************************
830 
831  Deactivate a replacement points in the given compilation unit.
832  When this function returns, the replacement points will be "un-armed",
833  that is a each thread reaching a point will just continue normally.
834 
835  IN:
836  code.............the compilation unit
837 
838 *******************************************************************************/
839 
841 {
842  rplpoint *rp;
843  s4 i;
844  s4 count;
845  u1 *savedmcode;
846 
847  if (code->savedmcode == NULL) {
848  /* disarm countdown points by patching the branches */
849 
850  i = code->rplpointcount;
851  rp = code->rplpoints;
852  for (; i--; rp++) {
853  if ((rp->flags & (rplpoint::FLAG_ACTIVE | rplpoint::FLAG_COUNTDOWN))
854  == rplpoint::FLAG_COUNTDOWN)
855  {
856 #if 0
857  *(s4*) (rp->pc + 9) = 0; /* XXX machine dependent! */
858 #endif
859  }
860  }
861  return;
862  }
863 
864  assert(code->savedmcode != NULL);
865  savedmcode = code->savedmcode;
866 
867  /* de-activate each trappable replacement point */
868 
869  i = code->rplpointcount;
870  rp = code->rplpoints;
871  count = 0;
872  for (; i--; rp++) {
873  if (!(rp->flags & rplpoint::FLAG_ACTIVE))
874  continue;
875 
876  count++;
877 
878  DOLOG( printf("deactivate replacement point:\n");
879  replace_replacement_point_println(rp, 1); fflush(stdout); );
880 
881 #if defined(ENABLE_JIT)
882 # if defined(ENABLE_DISASSEMBLER)
883  DOLOG( printf("\tinstruction before: ");
884  disassinstr(rp->pc); fflush(stdout); );
885 # endif
886 
887  md_patch_replacement_point(rp->pc, savedmcode, true);
888 
889 # if defined(ENABLE_DISASSEMBLER)
890  DOLOG( printf("\tinstruction before: ");
891  disassinstr(rp->pc); fflush(stdout); );
892 # endif
893 #endif
894 
895  rp->flags &= ~rplpoint::FLAG_ACTIVE;
896 
897  savedmcode += REPLACEMENT_PATCH_SIZE;
898  }
899 
900  assert(savedmcode == code->savedmcode + count * REPLACEMENT_PATCH_SIZE);
901 
902  /* free saved machine code */
903 
904  MFREE(code->savedmcode, u1, count * REPLACEMENT_PATCH_SIZE);
905  code->savedmcode = NULL;
906 }
907 
908 
909 /******************************************************************************/
910 /* PART III: The replacement mechanism */
911 /******************************************************************************/
912 
913 
914 /* replace_read_value **********************************************************
915 
916  Read a value with the given allocation from the execution state.
917 
918  IN:
919  es...............execution state
920  ra...............allocation
921  javaval..........where to put the value
922 
923  OUT:
924  *javaval.........the value
925 
926 *******************************************************************************/
927 
929  rplalloc *ra,
930  replace_val_t *javaval)
931 {
932  if (ra->flags & INMEMORY) {
933  /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
934 #ifdef HAS_4BYTE_STACKSLOT
935  if (IS_2_WORD_TYPE(ra->type)) {
936  javaval->l = *(u8*)(es->sp + ra->regoff);
937  }
938  else {
939 #endif
940  javaval->p = *(ptrint*)(es->sp + ra->regoff);
941 #ifdef HAS_4BYTE_STACKSLOT
942  }
943 #endif
944  }
945  else {
946  /* allocated register */
947  if (IS_FLT_DBL_TYPE(ra->type)) {
948  javaval->d = es->fltregs[ra->regoff];
949 
950  if (ra->type == TYPE_FLT)
951  javaval->f = javaval->d;
952  }
953  else {
954 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
955  if (ra->type == TYPE_LNG) {
956  javaval->words.lo = es->intregs[GET_LOW_REG(ra->regoff)];
957  javaval->words.hi = es->intregs[GET_HIGH_REG(ra->regoff)];
958  }
959  else
960 #endif /* defined(SUPPORT_COMBINE_INTEGER_REGISTERS) */
961  javaval->p = es->intregs[ra->regoff];
962  }
963  }
964 }
965 
966 
967 /* replace_write_value *********************************************************
968 
969  Write a value to the given allocation in the execution state.
970 
971  IN:
972  es...............execution state
973  ra...............allocation
974  *javaval.........the value
975 
976 *******************************************************************************/
977 
979  rplalloc *ra,
980  replace_val_t *javaval)
981 {
982  if (ra->flags & INMEMORY) {
983  /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
984 #ifdef HAS_4BYTE_STACKSLOT
985  if (IS_2_WORD_TYPE(ra->type)) {
986  *(u8*)(es->sp + ra->regoff) = javaval->l;
987  }
988  else {
989 #endif
990  *(ptrint*)(es->sp + ra->regoff) = javaval->p;
991 #ifdef HAS_4BYTE_STACKSLOT
992  }
993 #endif
994  }
995  else {
996  /* allocated register */
997  switch (ra->type) {
998  case TYPE_FLT:
999  es->fltregs[ra->regoff] = (double) javaval->f;
1000  break;
1001  case TYPE_DBL:
1002  es->fltregs[ra->regoff] = javaval->d;
1003  break;
1005  case TYPE_LNG:
1006  es->intregs[GET_LOW_REG(ra->regoff)] = javaval->words.lo;
1007  es->intregs[GET_HIGH_REG(ra->regoff)] = javaval->words.hi;
1008  break;
1009 #endif
1010  default:
1011  es->intregs[ra->regoff] = javaval->p;
1012  }
1013  }
1014 }
1015 
1016 
1017 /* replace_new_sourceframe *****************************************************
1018 
1019  Allocate a new source frame and insert it at the front of the frame list.
1020 
1021  IN:
1022  ss...............the source state
1023 
1024  OUT:
1025  ss->frames.......set to new frame (the new head of the frame list).
1026 
1027  RETURN VALUE:
1028  returns the new frame
1029 
1030 *******************************************************************************/
1031 
1032 static sourceframe_t *replace_new_sourceframe(sourcestate_t *ss)
1033 {
1034  sourceframe_t *frame;
1035 
1036  frame = (sourceframe_t*) DumpMemory::allocate(sizeof(sourceframe_t));
1037  MZERO(frame, sourceframe_t, 1);
1038 
1039  frame->down = ss->frames;
1040  ss->frames = frame;
1041 
1042  return frame;
1043 }
1044 
1045 
1046 /* replace_read_executionstate *************************************************
1047 
1048  Read a source frame from the given executions state.
1049  The new source frame is pushed to the front of the frame list of the
1050  source state.
1051 
1052  IN:
1053  rp...............replacement point at which `es` was taken
1054  es...............execution state
1055  ss...............the source state to add the source frame to
1056  topframe.........true, if the first (top-most) source frame on the
1057  stack is to be read
1058 
1059  OUT:
1060  *ss..............the source state with the newly created source frame
1061  added
1062 
1063 *******************************************************************************/
1064 
1066 /* rplpoint::TYPE_STD |--> */ rplpoint::TYPE_STD,
1067 /* rplpoint::TYPE_EXH |--> */ rplpoint::TYPE_STD,
1068 /* rplpoint::TYPE_SBR |--> */ rplpoint::TYPE_STD,
1069 /* rplpoint::TYPE_CALL |--> */ rplpoint::TYPE_CALL,
1070 /* rplpoint::TYPE_INLINE |--> */ rplpoint::TYPE_CALL,
1071 /* rplpoint::TYPE_RETURN |--> */ rplpoint::TYPE_RETURN,
1072 /* rplpoint::TYPE_BODY |--> */ rplpoint::TYPE_STD
1073 };
1074 
1075 
1076 static void replace_read_executionstate(rplpoint *rp,
1077  executionstate_t *es,
1078  sourcestate_t *ss,
1079  bool topframe)
1080 {
1081  methodinfo *m;
1082  codeinfo *code;
1083  int count;
1084  int i;
1085  rplalloc *ra;
1086  sourceframe_t *frame;
1087  int topslot;
1088  stackslot_t *sp;
1089 #if defined(__I386__)
1090  stackslot_t *basesp;
1091 #endif
1092 
1093  code = code_find_codeinfo_for_pc(rp->pc);
1094  m = rp->method;
1095  topslot = TOP_IS_NORMAL;
1096 
1097  /* stack pointer */
1098 
1099  sp = (stackslot_t *) es->sp;
1100 
1101  /* in some cases the top stack slot is passed in REG_ITMP1 */
1102 
1103  if (rp->type == rplpoint::TYPE_EXH) {
1104  topslot = TOP_IS_IN_ITMP1;
1105  }
1106 
1107  /* calculate base stack pointer */
1108 
1109 #if defined(__I386__)
1110  basesp = sp + code->stackframesize;
1111 #endif
1112 
1113  /* create the source frame */
1114 
1115  frame = replace_new_sourceframe(ss);
1116  frame->method = rp->method;
1117  frame->id = rp->id;
1118  assert(rp->type >= 0 && rp->type < sizeof(replace_normalize_type_map)/sizeof(s4));
1119  frame->type = replace_normalize_type_map[rp->type];
1120  frame->fromrp = rp;
1121  frame->fromcode = code;
1122 
1123  /* read local variables */
1124 
1125  count = m->maxlocals;
1126  frame->javalocalcount = count;
1127  frame->javalocals = (replace_val_t*) DumpMemory::allocate(sizeof(replace_val_t) * count);
1128  frame->javalocaltype = (u1*) DumpMemory::allocate(sizeof(u1) * count);
1129 
1130  /* mark values as undefined */
1131  for (i=0; i<count; ++i) {
1132 #if !defined(NDEBUG)
1133  frame->javalocals[i].l = (u8) 0x00dead0000dead00ULL;
1134 #endif
1135  frame->javalocaltype[i] = TYPE_VOID;
1136  }
1137 
1138  /* some entries in the intregs array are not meaningful */
1139  /*es->intregs[REG_ITMP3] = (u8) 0x11dead1111dead11ULL;*/
1140 #if !defined(NDEBUG)
1141  es->intregs[REG_SP ] = (ptrint) 0x11dead1111dead11ULL;
1142 #ifdef REG_PV
1143  es->intregs[REG_PV ] = (ptrint) 0x11dead1111dead11ULL;
1144 #endif
1145 #endif /* !defined(NDEBUG) */
1146 
1147  /* read javalocals */
1148 
1149  count = rp->regalloccount;
1150  ra = rp->regalloc;
1151 
1152  while (count && (i = ra->index) >= 0) {
1153  assert(i < m->maxlocals);
1154  frame->javalocaltype[i] = ra->type;
1155  if (ra->type == TYPE_RET)
1156  frame->javalocals[i].i = ra->regoff;
1157  else
1158  replace_read_value(es, ra, frame->javalocals + i);
1159  ra++;
1160  count--;
1161  }
1162 
1163  /* read instance, if this is the first rplpoint */
1164 
1165 #if defined(REPLACE_PATCH_DYNAMIC_CALL)
1166  if (topframe && !(rp->method->flags & ACC_STATIC) && rp == code->rplpoints) {
1167 #if 1
1168  /* we are at the start of the method body, so if local 0 is set, */
1169  /* it is the instance. */
1170  if (frame->javalocaltype[0] == TYPE_ADR)
1171  frame->instance = frame->javalocals[0];
1172 #else
1173  rplalloc instra;
1174  methoddesc *md;
1175 
1176  md = rp->method->parseddesc;
1177  assert(md->params);
1178  assert(md->paramcount >= 1);
1179  instra.type = TYPE_ADR;
1180  instra.regoff = md->params[0].regoff;
1181  if (md->params[0].inmemory) {
1182  instra.flags = INMEMORY;
1183  instra.regoff += (1 + code->stackframesize) * SIZE_OF_STACKSLOT;
1184  }
1185  else {
1186  instra.flags = 0;
1187  }
1188  replace_read_value(es, &instra, &(frame->instance));
1189 #endif
1190  }
1191 #if defined(__I386__)
1192  else if (!(rp->method->flags & ACC_STATIC)) {
1193  /* On i386 we always pass the first argument on stack. */
1194  frame->instance.a = *(java_object_t **)(basesp + 1);
1195  }
1196 #endif
1197 #endif /* defined(REPLACE_PATCH_DYNAMIC_CALL) */
1198 
1199  /* read stack slots */
1200 
1201  frame->javastackdepth = count;
1202  frame->javastack = (replace_val_t*) DumpMemory::allocate(sizeof(replace_val_t) * count);
1203  frame->javastacktype = (u1*) DumpMemory::allocate(sizeof(u1) * count);
1204 
1205 #if !defined(NDEBUG)
1206  /* mark values as undefined */
1207  for (i=0; i<count; ++i) {
1208  frame->javastack[i].l = (u8) 0x00dead0000dead00ULL;
1209  frame->javastacktype[i] = TYPE_VOID;
1210  }
1211 #endif /* !defined(NDEBUG) */
1212 
1213  i = 0;
1214 
1215  /* the first stack slot is special in SBR and EXH blocks */
1216 
1217  if (topslot == TOP_IS_ON_STACK) {
1218  assert(count);
1219 
1220  assert(ra->index == RPLALLOC_STACK);
1221  assert(ra->type == TYPE_ADR);
1222  frame->javastack[i].p = sp[-1];
1223  frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
1224  count--;
1225  i++;
1226  ra++;
1227  }
1228  else if (topslot == TOP_IS_IN_ITMP1) {
1229  assert(count);
1230 
1231  assert(ra->index == RPLALLOC_STACK);
1232  assert(ra->type == TYPE_ADR);
1233  frame->javastack[i].p = es->intregs[REG_ITMP1];
1234  frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
1235  count--;
1236  i++;
1237  ra++;
1238  }
1239  else if (topslot == TOP_IS_VOID) {
1240  assert(count);
1241 
1242  assert(ra->index == RPLALLOC_STACK);
1243  frame->javastack[i].l = 0;
1244  frame->javastacktype[i] = TYPE_VOID;
1245  count--;
1246  i++;
1247  ra++;
1248  }
1249 
1250  /* read remaining stack slots */
1251 
1252  for (; count--; ra++) {
1253  if (ra->index == RPLALLOC_SYNC) {
1254  assert(rp->type == rplpoint::TYPE_INLINE);
1255 
1256  /* only read synchronization slots when traversing an inline point */
1257 
1258  if (!topframe) {
1259  sourceframe_t *calleeframe = frame->down;
1260  assert(calleeframe);
1261  assert(calleeframe->syncslotcount == 0);
1262  assert(calleeframe->syncslots == NULL);
1263 
1264  calleeframe->syncslotcount = 1;
1265  calleeframe->syncslots = (replace_val_t*) DumpMemory::allocate(sizeof(replace_val_t));
1266  replace_read_value(es,ra,calleeframe->syncslots);
1267  }
1268 
1269  frame->javastackdepth--;
1270  continue;
1271  }
1272 
1273  assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
1274 
1275  /* do not read parameters of calls down the call chain */
1276 
1277  if (!topframe && ra->index == RPLALLOC_PARAM) {
1278  frame->javastackdepth--;
1279  }
1280  else {
1281  if (ra->type == TYPE_RET)
1282  frame->javastack[i].i = ra->regoff;
1283  else
1284  replace_read_value(es,ra,frame->javastack + i);
1285  frame->javastacktype[i] = ra->type;
1286  i++;
1287  }
1288  }
1289 }
1290 
1291 
1292 /* replace_write_executionstate ************************************************
1293 
1294  Pop a source frame from the front of the frame list of the given source state
1295  and write its values into the execution state.
1296 
1297  IN:
1298  rp...............replacement point for which execution state should be
1299  created
1300  es...............the execution state to modify
1301  ss...............the given source state
1302  topframe.........true, if this is the last (top-most) source frame to be
1303  translated
1304 
1305  OUT:
1306  *es..............the execution state derived from the source state
1307 
1308 *******************************************************************************/
1309 
1310 static void replace_write_executionstate(rplpoint *rp,
1311  executionstate_t *es,
1312  sourcestate_t *ss,
1313  bool topframe)
1314 {
1315  methodinfo *m;
1316  //codeinfo *code;
1317  int count;
1318  int i;
1319  rplalloc *ra;
1320  sourceframe_t *frame;
1321  int topslot;
1322  stackslot_t *sp;
1323  //stackslot_t *basesp;
1324 
1325  //code = code_find_codeinfo_for_pc(rp->pc);
1326  m = rp->method;
1327  topslot = TOP_IS_NORMAL;
1328 
1329  /* pop a source frame */
1330 
1331  frame = ss->frames;
1332  assert(frame);
1333  ss->frames = frame->down;
1334 
1335  /* calculate stack pointer */
1336 
1337  sp = (stackslot_t *) es->sp;
1338 
1339  //basesp = sp + code->stackframesize;
1340 
1341  /* in some cases the top stack slot is passed in REG_ITMP1 */
1342 
1343  if (rp->type == rplpoint::TYPE_EXH) {
1344  topslot = TOP_IS_IN_ITMP1;
1345  }
1346 
1347  /* write javalocals */
1348 
1349  ra = rp->regalloc;
1350  count = rp->regalloccount;
1351 
1352  while (count && (i = ra->index) >= 0) {
1353  assert(i < m->maxlocals);
1354  assert(i < frame->javalocalcount);
1355  assert(ra->type == frame->javalocaltype[i]);
1356  if (ra->type == TYPE_RET) {
1357  /* XXX assert that it matches this rplpoint */
1358  }
1359  else
1360  replace_write_value(es, ra, frame->javalocals + i);
1361  count--;
1362  ra++;
1363  }
1364 
1365  /* write stack slots */
1366 
1367  i = 0;
1368 
1369  /* the first stack slot is special in SBR and EXH blocks */
1370 
1371  if (topslot == TOP_IS_ON_STACK) {
1372  assert(count);
1373 
1374  assert(ra->index == RPLALLOC_STACK);
1375  assert(i < frame->javastackdepth);
1376  assert(frame->javastacktype[i] == TYPE_ADR);
1377  sp[-1] = frame->javastack[i].p;
1378  count--;
1379  i++;
1380  ra++;
1381  }
1382  else if (topslot == TOP_IS_IN_ITMP1) {
1383  assert(count);
1384 
1385  assert(ra->index == RPLALLOC_STACK);
1386  assert(i < frame->javastackdepth);
1387  assert(frame->javastacktype[i] == TYPE_ADR);
1388  es->intregs[REG_ITMP1] = frame->javastack[i].p;
1389  count--;
1390  i++;
1391  ra++;
1392  }
1393  else if (topslot == TOP_IS_VOID) {
1394  assert(count);
1395 
1396  assert(ra->index == RPLALLOC_STACK);
1397  assert(i < frame->javastackdepth);
1398  assert(frame->javastacktype[i] == TYPE_VOID);
1399  count--;
1400  i++;
1401  ra++;
1402  }
1403 
1404  /* write remaining stack slots */
1405 
1406  for (; count--; ra++) {
1407  if (ra->index == RPLALLOC_SYNC) {
1408  assert(rp->type == rplpoint::TYPE_INLINE);
1409 
1410  /* only write synchronization slots when traversing an inline point */
1411 
1412  if (!topframe) {
1413  assert(frame->down);
1414  assert(frame->down->syncslotcount == 1); /* XXX need to understand more cases */
1415  assert(frame->down->syncslots != NULL);
1416 
1417  replace_write_value(es,ra,frame->down->syncslots);
1418  }
1419  continue;
1420  }
1421 
1422  assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
1423 
1424  /* do not write parameters of calls down the call chain */
1425 
1426  if (!topframe && ra->index == RPLALLOC_PARAM) {
1427  /* skip it */
1428  /*
1429  ra->index = RPLALLOC_PARAM;
1430  replace_val_t v;
1431  v.l = 0;
1432  replace_write_value(es,ra,&v);
1433  */
1434  }
1435  else {
1436  assert(i < frame->javastackdepth);
1437  assert(ra->type == frame->javastacktype[i]);
1438  if (ra->type == TYPE_RET) {
1439  /* XXX assert that it matches this rplpoint */
1440  }
1441  else {
1442  replace_write_value(es,ra,frame->javastack + i);
1443  }
1444  i++;
1445  }
1446  }
1447 
1448  /* set new pc */
1449 
1450  es->pc = rp->pc;
1451 }
1452 
1453 
1454 /* md_push_stackframe **********************************************************
1455 
1456  Save the given return address, build the new stackframe,
1457  and store callee-saved registers.
1458 
1459  *** This function imitates the effects of a call and the ***
1460  *** method prolog of the callee. ***
1461 
1462  IN:
1463  es...............execution state
1464  calleecode.......the code we are "calling"
1465  ra...............the return address to save
1466 
1467  OUT:
1468  *es..............the execution state after pushing the stack frame
1469  NOTE: es->pc, es->code, and es->pv are NOT updated.
1470 
1471 *******************************************************************************/
1472 
1474 {
1475  s4 reg;
1476  s4 i;
1477  stackslot_t *basesp;
1478  stackslot_t *sp;
1479 
1480  assert(es);
1481  assert(calleecode);
1482 
1483  /* write the return address */
1484 
1485 #if STACKFRAME_RA_BETWEEN_FRAMES
1486  es->sp -= SIZEOF_VOID_P;
1487  *((void **)es->sp) = (void *) ra;
1488  if (calleecode->stackframesize)
1489  es->sp -= (SIZE_OF_STACKSLOT - SIZEOF_VOID_P);
1490 #endif /* STACKFRAME_RA_BETWEEN_FRAMES */
1491 
1492  es->ra = (u1*) (ptrint) ra;
1493 
1494  /* build the stackframe */
1495 
1496  DOLOG( printf("building stackframe of %d words at %p\n",
1497  calleecode->stackframesize, (void*)es->sp); );
1498 
1499  sp = (stackslot_t *) es->sp;
1500  basesp = sp;
1501 
1502  sp -= calleecode->stackframesize;
1503  es->sp = (u1*) sp;
1504 
1505  /* in debug mode, invalidate stack frame first */
1506 
1507  /* XXX may not invalidate linkage area used by native code! */
1508 
1509 #if !defined(NDEBUG) && 0
1510  for (i=0; i< (basesp - sp) && i < 1; ++i) {
1511  sp[i] = 0xdeaddeadU;
1512  }
1513 #endif
1514 
1515 #if defined(__I386__)
1516  /* Stackslot 0 may contain the object instance for vftbl patching.
1517  Destroy it, so there's no undefined value used. */
1518  if ((basesp - sp) > 0) {
1519  sp[0] = 0;
1520  }
1521 #endif
1522 
1523  /* save the return address register */
1524 
1525 #if STACKFRAME_RA_TOP_OF_FRAME
1526 # if STACKFRAME_LEAFMETHODS_RA_REGISTER
1527  if (!code_is_leafmethod(calleecode))
1528 # endif
1529  *--basesp = (ptrint) ra;
1530 #endif /* STACKFRAME_RA_TOP_OF_FRAME */
1531 
1532 #if STACKFRAME_RA_LINKAGE_AREA
1533 # if STACKFRAME_LEAFMETHODS_RA_REGISTER
1534  if (!code_is_leafmethod(calleecode))
1535 # endif
1536  *((uint8_t**) ((intptr_t) basesp + LA_LR_OFFSET)) = ra;
1537 #endif /* STACKFRAME_RA_LINKAGE_AREA */
1538 
1539  /* save int registers */
1540 
1541  reg = INT_REG_CNT;
1542  for (i=0; i<calleecode->savedintcount; ++i) {
1543  while (nregdescint[--reg] != REG_SAV)
1544  ;
1545  basesp -= 1;
1546  *((uintptr_t*) basesp) = es->intregs[reg];
1547 
1548  /* XXX may not clobber saved regs used by native code! */
1549 #if !defined(NDEBUG) && 0
1550  es->intregs[reg] = (ptrint) 0x44dead4444dead44ULL;
1551 #endif
1552  }
1553 
1554  /* save flt registers */
1555 
1556  /* XXX align? */
1557  reg = FLT_REG_CNT;
1558  for (i=0; i<calleecode->savedfltcount; ++i) {
1559  while (nregdescfloat[--reg] != REG_SAV)
1560  ;
1561  basesp -= STACK_SLOTS_PER_FLOAT;
1562  *((double*) basesp) = es->fltregs[reg];
1563 
1564  /* XXX may not clobber saved regs used by native code! */
1565 #if !defined(NDEBUG) && 0
1566  *(u8*)&(es->fltregs[reg]) = 0x44dead4444dead44ULL;
1567 #endif
1568  }
1569 }
1570 
1571 
1572 /* replace_pop_activation_record ***********************************************
1573 
1574  Peel a stack frame from the execution state.
1575 
1576  *** This function imitates the effects of the method epilog ***
1577  *** and returning from the method call. ***
1578 
1579  IN:
1580  es...............execution state
1581  frame............source frame, receives synchronization slots
1582 
1583  OUT:
1584  *es..............the execution state after popping the stack frame
1585 
1586  RETURN VALUE:
1587  the return address of the poped activation record
1588 
1589 *******************************************************************************/
1590 
1592  sourceframe_t *frame)
1593 {
1594  u1 *ra;
1595  s4 i;
1596  s4 count;
1597  codeinfo *code;
1598  stackslot_t *sp;
1599 
1600  assert(es->code);
1601  assert(frame);
1602 
1603  /* calculate the base of the stack frame */
1604 
1605  sp = (stackslot_t *) es->sp;
1606  assert(frame->syncslotcount == 0);
1607  assert(frame->syncslots == NULL);
1608  count = code_get_sync_slot_count(es->code);
1609  frame->syncslotcount = count;
1610  frame->syncslots = (replace_val_t*) DumpMemory::allocate(sizeof(replace_val_t) * count);
1611  for (i=0; i<count; ++i) {
1612  frame->syncslots[i].p = *((intptr_t*) (sp + es->code->memuse + i)); /* XXX md_ function */
1613  }
1614 
1615  /* pop the stackframe */
1616 
1618 
1619  ra = es->pc;
1620 
1621  DOLOG( printf("RA = %p\n", (void*)ra); );
1622 
1623  /* Subtract one from the PC so we do not hit the replacement point */
1624  /* of the instruction following the call, if there is one. */
1625 
1626  es->pc--;
1627 
1628  /* find the new codeinfo */
1629 
1630  void* pv = md_codegen_get_pv_from_pc(ra);
1631  DOLOG( printf("PV = %p\n", pv); );
1632 
1633  code = code_get_codeinfo_for_pv(pv);
1634  DOLOG( printf("CODE = %p\n", (void*) code); );
1635 
1636  /* return NULL if we reached native code */
1637 
1638  es->pv = (uint8_t*) pv;
1639  es->code = code;
1640 
1641  return (code) ? ra : NULL;
1642 }
1643 
1644 
1645 /* replace_patch_method_pointer ************************************************
1646 
1647  Patch a method pointer (may be in code, data segment, vftbl, or interface
1648  table).
1649 
1650  IN:
1651  mpp..............address of the method pointer to patch
1652  entrypoint.......the new entrypoint of the method
1653  kind.............kind of call to patch, used only for debugging
1654 
1655 *******************************************************************************/
1656 
1658  methodptr entrypoint,
1659  const char *kind)
1660 {
1661 #if !defined(NDEBUG)
1662  codeinfo *oldcode;
1663  codeinfo *newcode;
1664 #endif
1665 
1666  DOLOG( printf("patch method pointer from: %p to %p\n",
1667  (void*) *mpp, (void*)entrypoint); );
1668 
1669 #if !defined(NDEBUG)
1670  oldcode = code_get_codeinfo_for_pv(*mpp);
1671  newcode = code_get_codeinfo_for_pv(entrypoint);
1672 
1673  DOLOG_SHORT( printf("\tpatch %s %p ", kind, (void*) oldcode);
1674  method_println(oldcode->m);
1675  printf("\t with %p ", (void*) newcode);
1676  method_println(newcode->m); );
1677 
1678  assert(oldcode->m == newcode->m);
1679 #endif
1680 
1681  /* write the new entrypoint */
1682 
1683  *mpp = (methodptr) entrypoint;
1684 }
1685 
1686 
1687 /* replace_patch_class *********************************************************
1688 
1689  Patch a method in the given class.
1690 
1691  IN:
1692  vftbl............vftbl of the class
1693  m................the method to patch
1694  oldentrypoint....the old entrypoint to replace
1695  entrypoint.......the new entrypoint
1696 
1697 *******************************************************************************/
1698 
1700  methodinfo *m,
1701  u1 *oldentrypoint,
1702  u1 *entrypoint)
1703 {
1704  s4 i;
1705  methodptr *mpp;
1706  methodptr *mppend;
1707 
1708  /* patch the vftbl of the class */
1709 
1711  entrypoint,
1712  "virtual ");
1713 
1714  /* patch the interface tables */
1715 
1716  assert(oldentrypoint);
1717 
1718  for (i=0; i < vftbl->interfacetablelength; ++i) {
1719  mpp = vftbl->interfacetable[-i];
1720  mppend = mpp + vftbl->interfacevftbllength[i];
1721  for (; mpp != mppend; ++mpp)
1722  if (*mpp == oldentrypoint) {
1723  replace_patch_method_pointer(mpp, entrypoint, "interface");
1724  }
1725  }
1726 }
1727 
1728 
1729 /* replace_patch_class_hierarchy ***********************************************
1730 
1731  Patch a method in all loaded classes.
1732 
1733  IN:
1734  m................the method to patch
1735  oldentrypoint....the old entrypoint to replace
1736  entrypoint.......the new entrypoint
1737 
1738 *******************************************************************************/
1739 
1744 };
1745 
1747 {
1748  vftbl_t *vftbl = c->vftbl;
1749 
1750  if (vftbl != NULL
1751  && vftbl->vftbllength > pd->m->vftblindex
1752  && (void*) vftbl->table[pd->m->vftblindex] != (void*) (uintptr_t) &asm_abstractmethoderror
1753  && code_get_methodinfo_for_pv(vftbl->table[pd->m->vftblindex]) == pd->m)
1754  {
1755  replace_patch_class(c->vftbl, pd->m, pd->oldentrypoint, pd->entrypoint);
1756  }
1757 }
1758 
1760  u1 *oldentrypoint,
1761  u1 *entrypoint)
1762 {
1763  struct replace_patch_data_t pd;
1764 
1765  pd.m = m;
1767  pd.entrypoint = entrypoint;
1768 
1769  DOLOG_SHORT( printf("patching class hierarchy: ");
1770  method_println(m); );
1771 
1774  (void*) &pd);
1775 }
1776 
1777 
1778 /* replace_patch_future_calls **************************************************
1779 
1780  Analyse a call site and depending on the kind of call patch the call, the
1781  virtual function table, or the interface table.
1782 
1783  IN:
1784  ra...............return address pointing after the call site
1785  callerframe......source frame of the caller
1786  calleeframe......source frame of the callee, must have been mapped
1787 
1788 *******************************************************************************/
1789 
1791  sourceframe_t *callerframe,
1792  sourceframe_t *calleeframe)
1793 {
1794  u1 *patchpos;
1797 #if !defined(__I386__)
1798  bool atentry;
1799 #endif
1800  void *pv;
1801  codeinfo *calleecode;
1802  methodinfo *calleem;
1803  java_object_t *obj;
1804  vftbl_t *vftbl;
1805 
1806  assert(ra);
1807  assert(callerframe->down == calleeframe);
1808 
1809  /* get the new codeinfo and the method that shall be entered */
1810 
1811  calleecode = calleeframe->tocode;
1812  assert(calleecode);
1813 
1814  calleem = calleeframe->method;
1815  assert(calleem == calleecode->m);
1816 
1817  entrypoint = (methodptr) calleecode->entrypoint;
1818 
1819  /* check if we are at an method entry rplpoint at the innermost frame */
1820 
1821 #if !defined(__I386__)
1822  atentry = (calleeframe->down == NULL)
1823  && !(calleem->flags & ACC_STATIC)
1824  && (calleeframe->fromrp->id == 0); /* XXX */
1825 #endif
1826 
1827  /* get the position to patch, in case it was a statically bound call */
1828 
1829  pv = callerframe->fromcode->entrypoint;
1830  patchpos = (u1*) md_jit_method_patch_address(pv, ra, NULL);
1831 
1832  if (patchpos == NULL) {
1833  /* the call was dispatched dynamically */
1834 
1835  /* we can only patch such calls if we are at the entry point */
1836 
1837 #if !defined(__I386__)
1838  /* On i386 we always know the instance argument. */
1839  if (!atentry)
1840  return;
1841 #endif
1842 
1843  assert((calleem->flags & ACC_STATIC) == 0);
1844 
1845  oldentrypoint = calleeframe->fromcode->entrypoint;
1846 
1847  /* we need to know the instance */
1848 
1849  if (!calleeframe->instance.a) {
1850  DOLOG_SHORT( printf("WARNING: object instance unknown!\n"); );
1851  replace_patch_class_hierarchy(calleem, oldentrypoint, entrypoint);
1852  return;
1853  }
1854 
1855  /* get the vftbl */
1856 
1857  obj = calleeframe->instance.a;
1858  vftbl = obj->vftbl;
1859 
1860  assert(vftbl->clazz->vftbl == vftbl);
1861 
1862  DOLOG_SHORT( printf("\tclass: "); class_println(vftbl->clazz); );
1863 
1864  replace_patch_class(vftbl, calleem, oldentrypoint, entrypoint);
1865  }
1866  else {
1867  /* the call was statically bound */
1868 
1869 #if defined(__I386__)
1870  /* It happens that there is a patcher trap. (pm) */
1871  if (*(u2 *)(patchpos - 1) == 0x0b0f) {
1872  } else
1873 #endif
1874  replace_patch_method_pointer((methodptr *) patchpos, entrypoint, "static ");
1875  }
1876 }
1877 
1878 
1879 /* replace_push_activation_record **********************************************
1880 
1881  Push a stack frame onto the execution state.
1882 
1883  *** This function imitates the effects of a call and the ***
1884  *** method prolog of the callee. ***
1885 
1886  IN:
1887  es...............execution state
1888  rpcall...........the replacement point at the call site
1889  callerframe......source frame of the caller, or NULL for creating the
1890  first frame
1891  calleeframe......source frame of the callee, must have been mapped
1892 
1893  OUT:
1894  *es..............the execution state after pushing the stack frame
1895 
1896 *******************************************************************************/
1897 
1899  rplpoint *rpcall,
1900  sourceframe_t *callerframe,
1901  sourceframe_t *calleeframe)
1902 {
1903  s4 i;
1904  s4 count;
1905  stackslot_t *sp;
1906  u1 *ra;
1907  codeinfo *calleecode;
1908 
1909  assert(es);
1910  assert(!rpcall || callerframe);
1911  assert(!rpcall || rpcall->type == rplpoint::TYPE_CALL);
1912  assert(!rpcall || rpcall == callerframe->torp);
1913  assert(calleeframe);
1914  assert(!callerframe || calleeframe == callerframe->down);
1915 
1916  /* the compilation unit we are entering */
1917 
1918  calleecode = calleeframe->tocode;
1919  assert(calleecode);
1920 
1921  /* calculate the return address */
1922 
1923  if (rpcall)
1924  ra = rpcall->pc + rpcall->callsize;
1925  else
1926  ra = es->pc + 1 /* XXX this is ugly */;
1927 
1928  /* push the stackframe */
1929 
1930  md_push_stackframe(es, calleecode, ra);
1931 
1932  /* we move into a new code unit, set code, PC, PV */
1933 
1934  es->code = calleecode;
1935  es->pc = calleecode->entrypoint; /* XXX not needed? */
1936  es->pv = calleecode->entrypoint;
1937 
1938  /* write slots used for synchronization */
1939 
1940  sp = (stackslot_t *) es->sp;
1941  count = code_get_sync_slot_count(calleecode);
1942  assert(count == calleeframe->syncslotcount);
1943  for (i=0; i<count; ++i) {
1944  *((intptr_t*) (sp + calleecode->memuse + i)) = calleeframe->syncslots[i].p;
1945  }
1946 
1947  /* redirect future invocations */
1948 
1949  if (callerframe && rpcall) {
1950 #if defined(REPLACE_PATCH_ALL)
1951  if (rpcall->type == callerframe->fromrp->type)
1952 #else
1953  if (rpcall == callerframe->fromrp)
1954 #endif
1955  replace_patch_future_calls(ra, callerframe, calleeframe);
1956  }
1957 }
1958 
1959 
1960 /* replace_find_replacement_point **********************************************
1961 
1962  Find the replacement point in the given code corresponding to the
1963  position given in the source frame.
1964 
1965  IN:
1966  code.............the codeinfo in which to search the rplpoint
1967  frame............the source frame defining the position to look for
1968  parent...........parent replacement point to match
1969 
1970  RETURN VALUE:
1971  the replacement point
1972 
1973 *******************************************************************************/
1974 
1976  sourceframe_t *frame,
1977  rplpoint *parent)
1978 {
1979  //methodinfo *m;
1980  rplpoint *rp;
1981  s4 i;
1982  s4 j;
1983  s4 stacki;
1984  rplalloc *ra;
1985 
1986  assert(code);
1987  assert(frame);
1988 
1989  DOLOG( printf("searching replacement point for:\n");
1990  replace_source_frame_println(frame); );
1991 
1992  //m = frame->method;
1993 
1994  DOLOG( printf("code = %p\n", (void*)code); );
1995 
1996  rp = code->rplpoints;
1997  i = code->rplpointcount;
1998  while (i--) {
1999  if (rp->id == frame->id && rp->method == frame->method
2000  && rp->parent == parent
2001  && replace_normalize_type_map[rp->type] == frame->type)
2002  {
2003  /* check if returnAddresses match */
2004  /* XXX optimize: only do this if JSRs in method */
2005  DOLOG( printf("checking match for:");
2006  replace_replacement_point_println(rp, 1); fflush(stdout); );
2007  ra = rp->regalloc;
2008  stacki = 0;
2009  for (j = rp->regalloccount; j--; ++ra) {
2010  if (ra->type == TYPE_RET) {
2011  if (ra->index == RPLALLOC_STACK) {
2012  assert(stacki < frame->javastackdepth);
2013  if (frame->javastack[stacki].i != ra->regoff)
2014  goto no_match;
2015  stacki++;
2016  }
2017  else {
2018  assert(ra->index >= 0 && ra->index < frame->javalocalcount);
2019  if (frame->javalocals[ra->index].i != ra->regoff)
2020  goto no_match;
2021  }
2022  }
2023  }
2024 
2025  /* found */
2026  return rp;
2027  }
2028 no_match:
2029  rp++;
2030  }
2031 
2032 #if !defined(NDEBUG)
2033  printf("candidate replacement points were:\n");
2034  rp = code->rplpoints;
2035  i = code->rplpointcount;
2036  for (; i--; ++rp) {
2038  }
2039 #endif
2040 
2041  vm_abort("no matching replacement point found");
2042  return NULL; /* NOT REACHED */
2043 }
2044 
2045 
2046 /* replace_find_replacement_point_for_pc ***************************************
2047 
2048  Find the nearest replacement point at or before the given PC. The
2049  given PC has to be between (rp->pc) and (rp->pc+rp->callsize) for
2050  the replacement point to be found.
2051 
2052  IN:
2053  code.............compilation unit the PC is in
2054  pc...............the machine code PC
2055 
2056  RETURN VALUE:
2057  the replacement point found, or
2058  NULL if no replacement point was found
2059 
2060 *******************************************************************************/
2061 
2062 rplpoint *replace_find_replacement_point_for_pc(codeinfo *code, u1 *pc, unsigned desired_flags)
2063 {
2064  rplpoint *found;
2065  rplpoint *rp;
2066  s4 i;
2067 
2068  DOLOG( printf("searching for rp at pc:%p in %p ", (void*)pc, (void*)code);
2069  method_println(code->m); );
2070 
2071  found = NULL;
2072 
2073  rp = code->rplpoints;
2074  for (i=0; i<code->rplpointcount; ++i, ++rp) {
2076  if (rp->pc <= pc && rp->pc + rp->callsize >= pc) {
2077  if (desired_flags) {
2078  if (rp->flags & desired_flags) {
2079  found = rp;
2080  }
2081  } else {
2082  found = rp;
2083  }
2084  }
2085  }
2086 
2087  return found;
2088 }
2089 
2090 /* replace_pop_native_frame ****************************************************
2091 
2092  Unroll a native frame in the execution state and create a source frame
2093  for it.
2094 
2095  IN:
2096  es...............current execution state
2097  ss...............the current source state
2098  sfi..............stackframeinfo for the native frame
2099 
2100  OUT:
2101  es...............execution state after unrolling the native frame
2102  ss...............gets the added native source frame
2103 
2104 *******************************************************************************/
2105 
2107  sourcestate_t *ss,
2108  stackframeinfo_t *sfi)
2109 {
2110  sourceframe_t *frame;
2111  codeinfo *code;
2112  s4 i,j;
2113 
2114  assert(sfi);
2115 
2116  frame = replace_new_sourceframe(ss);
2117 
2118  frame->sfi = sfi;
2119 
2120  /* remember pc and size of native frame */
2121 
2122  frame->nativepc = es->pc;
2123  frame->nativeframesize = (es->sp != 0) ? (((uintptr_t) sfi->sp) - ((uintptr_t) es->sp)) : 0;
2124  assert(frame->nativeframesize >= 0);
2125 
2126  /* remember values of saved registers */
2127 
2128  j = 0;
2129  for (i=0; i<INT_REG_CNT; ++i) {
2130  if (nregdescint[i] == REG_SAV)
2131  frame->nativesavint[j++] = es->intregs[i];
2132  }
2133 
2134  j = 0;
2135  for (i=0; i<FLT_REG_CNT; ++i) {
2136  if (nregdescfloat[i] == REG_SAV)
2137  frame->nativesavflt[j++] = es->fltregs[i];
2138  }
2139 
2140  /* restore saved registers */
2141 
2142 #if defined(ENABLE_GC_CACAO)
2143  j = 0;
2144  for (i=0; i<INT_REG_CNT; ++i) {
2145  if (nregdescint[i] == REG_SAV)
2146  es->intregs[i] = sfi->intregs[j++];
2147  }
2148 #else
2149  /* XXX we don't have them, yet, in the sfi, so clear them */
2150 
2151  for (i=0; i<INT_REG_CNT; ++i) {
2152  if (nregdescint[i] == REG_SAV)
2153  es->intregs[i] = 0;
2154  }
2155 #endif
2156 
2157  /* XXX we don't have float registers in the sfi, so clear them */
2158 
2159  for (i=0; i<FLT_REG_CNT; ++i) {
2160  if (nregdescfloat[i] == REG_SAV)
2161  es->fltregs[i] = 0.0;
2162  }
2163 
2164  /* restore codeinfo of the native stub */
2165 
2166  code = code_get_codeinfo_for_pv(sfi->pv);
2167 
2168  /* restore sp, pv, pc and codeinfo of the parent method */
2169 
2170  es->sp = (uint8_t*) (((uintptr_t) sfi->sp) + md_stacktrace_get_framesize(code));
2171 #if STACKFRAME_RA_BETWEEN_FRAMES
2172  es->sp += SIZEOF_VOID_P; /* skip return address */
2173 #endif
2174  es->pv = (uint8_t*) md_codegen_get_pv_from_pc(sfi->ra);
2175  es->pc = (uint8_t*) (((uintptr_t) ((sfi->xpc) ? sfi->xpc : sfi->ra)) - 1);
2176  es->code = code_get_codeinfo_for_pv(es->pv);
2177 }
2178 
2179 
2180 /* replace_push_native_frame ***************************************************
2181 
2182  Rebuild a native frame onto the execution state and remove its source frame.
2183 
2184  Note: The native frame is "rebuild" by setting fields like PC and stack
2185  pointer in the execution state accordingly. Values in the
2186  stackframeinfo may be modified, but the actual stack frame of the
2187  native code is not touched.
2188 
2189  IN:
2190  es...............current execution state
2191  ss...............the current source state
2192 
2193  OUT:
2194  es...............execution state after re-rolling the native frame
2195  ss...............the native source frame is removed
2196 
2197 *******************************************************************************/
2198 
2199 static void replace_push_native_frame(executionstate_t *es, sourcestate_t *ss)
2200 {
2201  sourceframe_t *frame;
2202  s4 i,j;
2203 
2204  assert(es);
2205  assert(ss);
2206 
2207  DOLOG( printf("pushing native frame\n"); );
2208 
2209  /* remove the frame from the source state */
2210 
2211  frame = ss->frames;
2212  assert(frame);
2213  assert(REPLACE_IS_NATIVE_FRAME(frame));
2214 
2215  ss->frames = frame->down;
2216 
2217  /* skip sp for the native stub */
2218 
2219  es->sp -= md_stacktrace_get_framesize(frame->sfi->code);
2220 #if STACKFRAME_RA_BETWEEN_FRAMES
2221  es->sp -= SIZEOF_VOID_P; /* skip return address */
2222 #endif
2223 
2224  /* assert that the native frame has not moved */
2225 
2226  assert(es->sp == frame->sfi->sp);
2227 
2228  /* update saved registers in the stackframeinfo */
2229 
2230 #if defined(ENABLE_GC_CACAO)
2231  j = 0;
2232  for (i=0; i<INT_REG_CNT; ++i) {
2233  if (nregdescint[i] == REG_SAV)
2234  frame->sfi->intregs[j++] = es->intregs[i];
2235  }
2236 
2237  /* XXX leave float registers untouched here */
2238 #endif
2239 
2240  /* restore saved registers */
2241 
2242  j = 0;
2243  for (i=0; i<INT_REG_CNT; ++i) {
2244  if (nregdescint[i] == REG_SAV)
2245  es->intregs[i] = frame->nativesavint[j++];
2246  }
2247 
2248  j = 0;
2249  for (i=0; i<FLT_REG_CNT; ++i) {
2250  if (nregdescfloat[i] == REG_SAV)
2251  es->fltregs[i] = frame->nativesavflt[j++];
2252  }
2253 
2254  /* skip the native frame on the machine stack */
2255 
2256  es->sp -= frame->nativeframesize;
2257 
2258  /* set the pc the next frame must return to */
2259 
2260  es->pc = frame->nativepc;
2261 }
2262 
2263 
2264 /* replace_recover_source_state ************************************************
2265 
2266  Recover the source state from the given replacement point and execution
2267  state.
2268 
2269  IN:
2270  rp...............replacement point that has been reached, if any
2271  sfi..............stackframeinfo, if called from native code
2272  es...............execution state at the replacement point rp
2273 
2274  RETURN VALUE:
2275  the source state
2276 
2277 *******************************************************************************/
2278 
2279 sourcestate_t *replace_recover_source_state(rplpoint *rp,
2280  stackframeinfo_t *sfi,
2281  executionstate_t *es)
2282 {
2283  sourcestate_t *ss;
2284  u1 *ra;
2285  bool locked;
2286 #if defined(REPLACE_STATISTICS)
2287  s4 depth;
2288 #endif
2289 
2290  /* create the source frame structure in dump memory */
2291 
2292  ss = (sourcestate_t*) DumpMemory::allocate(sizeof(sourcestate_t));
2293  ss->frames = NULL;
2294 
2295  /* each iteration of the loop recovers one source frame */
2296 
2297  depth = 0;
2298  locked = false;
2299 
2300  while (rp || sfi) {
2301 
2302  DOLOG( executionstate_println(es); );
2303 
2304  /* if we are not at a replacement point, it is a native frame */
2305 
2306  if (rp == NULL) {
2307  DOLOG( printf("native frame: sfi: "); replace_stackframeinfo_println(sfi); );
2308 
2309  locked = true;
2310  replace_pop_native_frame(es, ss, sfi);
2311  sfi = sfi->prev;
2312 
2313  if (es->code == NULL)
2314  continue;
2315 
2316  goto after_machine_frame;
2317  }
2318 
2319  /* read the values for this source frame from the execution state */
2320 
2321  DOLOG( printf("recovering source state for%s:\n",
2322  (ss->frames == NULL) ? " TOPFRAME" : "");
2324 
2325  replace_read_executionstate(rp, es, ss, ss->frames == NULL);
2326 
2327 #if defined(REPLACE_STATISTICS)
2329  depth++;
2330  replace_statistics_source_frame(ss->frames);
2331 #endif
2332 
2333  /* in locked areas (below native frames), identity map the frame */
2334 
2335  if (locked) {
2336  ss->frames->torp = ss->frames->fromrp;
2337  ss->frames->tocode = ss->frames->fromcode;
2338  }
2339 
2340  /* unroll to the next (outer) frame */
2341 
2342  if (rp->parent) {
2343  /* this frame is in inlined code */
2344 
2345  DOLOG( printf("INLINED!\n"); );
2346 
2347  rp = rp->parent;
2348 
2349  assert(rp->type == rplpoint::TYPE_INLINE);
2351  }
2352  else {
2353  /* this frame had been called at machine-level. pop it. */
2354 
2355  DOLOG( printf("UNWIND\n"); );
2356 
2357  ra = replace_pop_activation_record(es, ss->frames);
2358  if (ra == NULL) {
2359  DOLOG( printf("REACHED NATIVE CODE\n"); );
2360 
2361  rp = NULL;
2362 
2363 #if !defined(ENABLE_GC_CACAO)
2364  break; /* XXX remove to activate native frames */
2365 #endif
2366  continue;
2367  }
2368 
2369  /* find the replacement point at the call site */
2370 
2371 after_machine_frame:
2372  rp = replace_find_replacement_point_for_pc(es->code, es->pc, 0);
2373 
2374  if (rp == NULL)
2375  vm_abort("could not find replacement point while unrolling call");
2376 
2377  DOLOG( printf("found replacement point.\n");
2379 
2380  assert(rp->type == rplpoint::TYPE_CALL);
2382  }
2383  } /* end loop over source frames */
2384 
2386 
2387  return ss;
2388 }
2389 
2390 
2391 /* replace_map_source_state ****************************************************
2392 
2393  Map each source frame in the given source state to a target replacement
2394  point and compilation unit. If no valid code is available for a source
2395  frame, it is (re)compiled.
2396 
2397  IN:
2398  ss...............the source state
2399 
2400  OUT:
2401  ss...............the source state, modified: The `torp` and `tocode`
2402  fields of each source frame are set.
2403 
2404  RETURN VALUE:
2405  true.............everything went ok
2406  false............an exception has been thrown
2407 
2408 *******************************************************************************/
2409 
2410 static bool replace_map_source_state(sourcestate_t *ss)
2411 {
2412  sourceframe_t *frame;
2413  codeinfo *code;
2414  rplpoint *rp;
2415  rplpoint *parent; /* parent of inlined rplpoint */
2416 #if defined(REPLACE_STATISTICS)
2417  codeinfo *oldcode;
2418 #endif
2419 
2420  parent = NULL;
2421  code = NULL;
2422 
2423  /* iterate over the source frames from outermost to innermost */
2424 
2425  for (frame = ss->frames; frame != NULL; frame = frame->down) {
2426 
2427  /* XXX skip native frames */
2428 
2429  if (REPLACE_IS_NATIVE_FRAME(frame)) {
2430  parent = NULL;
2431  continue;
2432  }
2433 
2434  /* map frames which are not already mapped */
2435 
2436  if (frame->tocode) {
2437  code = frame->tocode;
2438  rp = frame->torp;
2439  assert(rp);
2440  }
2441  else {
2442  assert(frame->torp == NULL);
2443 
2444  if (parent == NULL) {
2445  /* find code for this frame */
2446 
2447 #if defined(REPLACE_STATISTICS)
2448  oldcode = frame->method->code;
2449 #endif
2450  /* request optimization of hot methods and their callers */
2451 
2452  if (frame->method->hitcountdown < 0
2453  || (frame->down && frame->down->method->hitcountdown < 0))
2454  jit_request_optimization(frame->method);
2455 
2456  code = jit_get_current_code(frame->method);
2457 
2458  if (code == NULL)
2459  return false; /* exception */
2460 
2461  REPLACE_COUNT_IF(stat_recompile, code != oldcode);
2462  }
2463 
2464  assert(code);
2465 
2466  /* map this frame */
2467 
2468  rp = replace_find_replacement_point(code, frame, parent);
2469 
2470  frame->tocode = code;
2471  frame->torp = rp;
2472  }
2473 
2474  if (rp->type == rplpoint::TYPE_CALL) {
2475  parent = NULL;
2476  }
2477  else {
2478  /* inlining */
2479  parent = rp;
2480  }
2481  }
2482 
2483  return true;
2484 }
2485 
2486 
2487 /* replace_map_source_state_identity *******************************************
2488 
2489  Map each source frame in the given source state to the same replacement
2490  point and compilation unit it was derived from. This is mainly used for
2491  garbage collection.
2492 
2493  IN:
2494  ss...............the source state
2495 
2496  OUT:
2497  ss...............the source state, modified: The `torp` and `tocode`
2498  fields of each source frame are set.
2499 
2500 *******************************************************************************/
2501 
2502 #if defined(ENABLE_GC_CACAO)
2503 static void replace_map_source_state_identity(sourcestate_t *ss)
2504 {
2505  sourceframe_t *frame;
2506 
2507  /* iterate over the source frames from outermost to innermost */
2508 
2509  for (frame = ss->frames; frame != NULL; frame = frame->down) {
2510 
2511  /* skip native frames */
2512 
2513  if (REPLACE_IS_NATIVE_FRAME(frame)) {
2514  continue;
2515  }
2516 
2517  /* map frames using the identity mapping */
2518 
2519  if (frame->tocode) {
2520  assert(frame->tocode == frame->fromcode);
2521  assert(frame->torp == frame->fromrp);
2522  } else {
2523  assert(frame->tocode == NULL);
2524  assert(frame->torp == NULL);
2525  frame->tocode = frame->fromcode;
2526  frame->torp = frame->fromrp;
2527  }
2528  }
2529 }
2530 #endif
2531 
2532 
2533 /* replace_build_execution_state ***********************************************
2534 
2535  Build an execution state for the given (mapped) source state.
2536 
2537  !!! CAUTION: This function rewrites the machine stack !!!
2538 
2539  THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA!
2540 
2541  IN:
2542  ss...............the source state. Must have been mapped by
2543  replace_map_source_state before.
2544  es...............the base execution state on which to build
2545 
2546  OUT:
2547  *es..............the new execution state
2548 
2549 *******************************************************************************/
2550 
2551 static void replace_build_execution_state(sourcestate_t *ss,
2552  executionstate_t *es)
2553 {
2554  rplpoint *rp;
2555  sourceframe_t *prevframe;
2556  rplpoint *parent;
2557 
2558  parent = NULL;
2559  prevframe = NULL;
2560  rp = NULL;
2561 
2562  while (ss->frames) {
2563 
2564  if (REPLACE_IS_NATIVE_FRAME(ss->frames)) {
2565  prevframe = ss->frames;
2566  replace_push_native_frame(es, ss);
2567  parent = NULL;
2568  rp = NULL;
2569  continue;
2570  }
2571 
2572  if (parent == NULL) {
2573  /* create a machine-level stack frame */
2574 
2575  DOLOG( printf("pushing activation record for:\n");
2576  if (rp) replace_replacement_point_println(rp, 1);
2577  else printf("\tfirst frame\n"); );
2578 
2579  replace_push_activation_record(es, rp, prevframe, ss->frames);
2580 
2581  DOLOG( executionstate_println(es); );
2582  }
2583 
2584  rp = ss->frames->torp;
2585  assert(rp);
2586 
2587  DOLOG( printf("creating execution state for%s:\n",
2588  (ss->frames->down == NULL) ? " TOPFRAME" : "");
2589  replace_replacement_point_println(ss->frames->fromrp, 1);
2591 
2592  es->code = ss->frames->tocode;
2593  prevframe = ss->frames;
2594 
2595  replace_write_executionstate(rp, es, ss, ss->frames->down == NULL);
2596 
2597  DOLOG( executionstate_println(es); );
2598 
2599  if (rp->type == rplpoint::TYPE_CALL) {
2600  parent = NULL;
2601  }
2602  else {
2603  /* inlining */
2604  parent = rp;
2605  }
2606  }
2607 }
2608 
2609 
2610 /* replace_me ******************************************************************
2611 
2612  This function is called by the signal handler when a thread reaches
2613  a replacement point. `replace_me` must map the execution state to the
2614  target replacement point and let execution continue there.
2615 
2616  THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA!
2617 
2618  IN:
2619  rp...............replacement point that has been reached
2620  es...............execution state read by signal handler
2621 
2622 *******************************************************************************/
2623 
2624 static void replace_me(rplpoint *rp, executionstate_t *es)
2625 {
2626  stackframeinfo_t *sfi;
2627  sourcestate_t *ss;
2628  codeinfo *origcode;
2629  rplpoint *origrp;
2630 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
2632 #endif
2633 
2634  origcode = es->code;
2635  origrp = rp;
2636 
2637 #if defined(ENABLE_TLH)
2638  /*printf("Replacing in %s/%s\n", UTF_TEXT(rp->method->clazz->name), UTF_TEXT(rp->method->name));*/
2639 #endif
2640 
2641  /*if (strcmp(UTF_TEXT(rp->method->clazz->name), "antlr/AlternativeElement") == 0 && strcmp(UTF_TEXT(rp->method->name), "getAutoGenType") ==0) opt_TraceReplacement = 2; else opt_TraceReplacement = 0;*/
2642 
2643  DOLOG_SHORT( printf("REPLACING(%d %p): (id %d %p) ",
2645  rp->id, (void*)rp);
2646  method_println(es->code->m); );
2647 
2649 
2651 
2652  // Create new dump memory area.
2653  DumpMemoryArea dma;
2654 
2655  /* Get the stackframeinfo for the current thread. */
2656 
2658 
2659  /* recover source state */
2660 
2661  ss = replace_recover_source_state(rp, sfi, es);
2662 
2663 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
2664  /* if there is a collection pending, we assume the replacement point should
2665  suspend this thread */
2666 
2667  if (gc_pending) {
2668 
2669  thread = THREADOBJECT;
2670 
2671  DOLOG_SHORT( printf("REPLACEMENT: Suspending thread for GC now!\n"); );
2672 
2673  /* map the sourcestate using the identity mapping */
2674  replace_map_source_state_identity(ss);
2675 
2676  /* since we enter the same method again, we turn off rps now */
2677  /* XXX michi: can we really do this? what if the rp was active before
2678  we activated it for the gc? */
2680 
2681  /* remember executionstate and sourcestate for this thread */
2682  GC_EXECUTIONSTATE = es;
2683  GC_SOURCESTATE = ss;
2684 
2685  /* really suspend this thread now (PC = 0) */
2686  threads_suspend_ack(NULL, NULL);
2687 
2688  DOLOG_SHORT( printf("REPLACEMENT: Resuming thread after GC now!\n"); );
2689 
2690  } else {
2691 #endif /*defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)*/
2692 
2693  /* map the source state */
2694 
2695  if (!replace_map_source_state(ss))
2696  vm_abort("exception during method replacement");
2697 
2699 
2701 
2702 #if !defined(NDEBUG)
2703  /* avoid infinite loops by self-replacement, only if not in testing mode */
2704 
2705  if (!opt_TestReplacement) {
2706  sourceframe_t *frame = ss->frames;
2707  while (frame->down)
2708  frame = frame->down;
2709 
2710  if (frame->torp == origrp) {
2711  DOLOG_SHORT(
2712  printf("WARNING: identity replacement, turning off rps to avoid infinite loop\n");
2713  );
2715  }
2716  }
2717 #endif
2718 
2719 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
2720  }
2721 #endif
2722 
2723  /* build the new execution state */
2724 
2726 
2727 #if !defined(NDEBUG)
2728  /* continue execution after patched machine code, if testing mode enabled */
2729 
2730  if (opt_TestReplacement)
2731  es->pc += REPLACEMENT_PATCH_SIZE;
2732 #endif
2733 }
2734 
2735 
2736 /* replace_handler *************************************************************
2737 
2738  This function is called by the signal handler. It determines if there
2739  is an active replacement point pending at the given PC and returns
2740  accordingly.
2741 
2742  THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA!
2743 
2744  IN:
2745  pc...............the program counter that triggered the replacement.
2746  es...............the execution state (machine state) to which the
2747  replacement should be applied.
2748 
2749  OUT:
2750  es...............the execution state after replacement finished.
2751 
2752  RETURN VALUE:
2753  true.............replacement done, everything went ok
2754  false............no replacement done, execution state unchanged
2755 
2756 *******************************************************************************/
2757 
2759 {
2760  codeinfo *code;
2761  rplpoint *rp;
2762 
2763  /* search the codeinfo for the given PC */
2764 
2765  code = code_find_codeinfo_for_pc(pc);
2766  assert(code);
2767 
2768  /* search for a replacement point at the given PC */
2769 
2770  rp = replace_find_replacement_point_for_pc(code, pc, (rplpoint::FLAG_ACTIVE | rplpoint::FLAG_COUNTDOWN));
2771 
2772  /* check if the replacement point belongs to given PC and is active */
2773 
2774  if ((rp != NULL) && (rp->pc == pc)
2775  && (rp->flags & (rplpoint::FLAG_ACTIVE | rplpoint::FLAG_COUNTDOWN))) {
2776 
2777  DOLOG( printf("valid replacement point\n"); );
2778 
2779  /* set codeinfo pointer in execution state */
2780 
2781  es->code = code;
2782 
2783  /* do the actual replacement */
2784 
2785  replace_me(rp, es);
2786 
2787  /* new code is entered after returning */
2788 
2789  DOLOG( printf("JUMPING IN!\n"); fflush(stdout); );
2790  return true;
2791  }
2792  else
2793  return false;
2794 }
2795 
2796 
2797 /******************************************************************************/
2798 /* NOTE: Stuff specific to the exact GC is below. */
2799 /******************************************************************************/
2800 
2801 #if defined(ENABLE_GC_CACAO)
2802 void replace_gc_from_native(threadobject *thread, u1 *pc, u1 *sp)
2803 {
2804  stackframeinfo_t *sfi;
2805  executionstate_t *es;
2806  sourcestate_t *ss;
2807 
2808  /* Get the stackframeinfo of this thread. */
2809 
2810  assert(thread == THREADOBJECT);
2811 
2813 
2814  /* create the execution state */
2816  es->pc = pc;
2817  es->sp = sp;
2818  es->pv = 0; /* since we are in a native, PV is invalid! */
2819  es->code = NULL; /* since we are in a native, we do not have a codeinfo */
2820 
2821  /* we assume we are in a native (no replacement point)! */
2822  ss = replace_recover_source_state(NULL, sfi, es);
2823 
2824  /* map the sourcestate using the identity mapping */
2825  replace_map_source_state_identity(ss);
2826 
2827  /* remember executionstate and sourcestate for this thread */
2828  GC_EXECUTIONSTATE = es;
2829  GC_SOURCESTATE = ss;
2830 }
2831 #endif
2832 
2833 #if defined(ENABLE_GC_CACAO)
2834 void replace_gc_into_native(threadobject *thread)
2835 {
2836  executionstate_t *es;
2837  sourcestate_t *ss;
2838 
2839  /* get the executionstate and sourcestate for the given thread */
2840  es = GC_EXECUTIONSTATE;
2841  ss = GC_SOURCESTATE;
2842 
2843  /* rebuild the stack of the given thread */
2845 }
2846 #endif
2847 
2848 
2849 /******************************************************************************/
2850 /* NOTE: No important code below. */
2851 /******************************************************************************/
2852 
2853 
2854 /* statistics *****************************************************************/
2855 
2856 #if defined(REPLACE_STATISTICS)
2857 static void print_freq(FILE *file,int *array,int limit)
2858 {
2859  int i;
2860  int sum = 0;
2861  int cum = 0;
2862  for (i=0; i<limit; ++i)
2863  sum += array[i];
2864  sum += array[limit];
2865  for (i=0; i<limit; ++i) {
2866  cum += array[i];
2867  fprintf(file," %3d: %8d (cum %3d%%)\n",
2868  i, array[i], (sum) ? ((100*cum)/sum) : 0);
2869  }
2870  fprintf(file," >=%3d: %8d\n",limit,array[limit]);
2871 }
2872 #endif /* defined(REPLACE_STATISTICS) */
2873 
2874 
2875 #if defined(REPLACE_STATISTICS)
2876 
2877 #define REPLACE_PRINT_DIST(name, array) \
2878  printf(" " name " distribution:\n"); \
2879  print_freq(stdout, (array), sizeof(array)/sizeof(int) - 1);
2880 
2882 {
2883  printf("replacement statistics:\n");
2884  printf(" # of replacements: %d\n", stat_replacements);
2885  printf(" # of frames: %d\n", stat_frames);
2886  printf(" # of recompilations: %d\n", stat_recompile);
2887  printf(" patched static calls:%d\n", stat_staticpatch);
2888  printf(" unrolled inlines: %d\n", stat_unroll_inline);
2889  printf(" unrolled calls: %d\n", stat_unroll_call);
2890  REPLACE_PRINT_DIST("frame depth", stat_dist_frames);
2891  REPLACE_PRINT_DIST("locals per frame", stat_dist_locals);
2892  REPLACE_PRINT_DIST("ADR locals per frame", stat_dist_locals_adr);
2893  REPLACE_PRINT_DIST("primitive locals per frame", stat_dist_locals_prim);
2894  REPLACE_PRINT_DIST("RET locals per frame", stat_dist_locals_ret);
2895  REPLACE_PRINT_DIST("void locals per frame", stat_dist_locals_void);
2896  REPLACE_PRINT_DIST("stack slots per frame", stat_dist_stack);
2897  REPLACE_PRINT_DIST("ADR stack slots per frame", stat_dist_stack_adr);
2898  REPLACE_PRINT_DIST("primitive stack slots per frame", stat_dist_stack_prim);
2899  REPLACE_PRINT_DIST("RET stack slots per frame", stat_dist_stack_ret);
2900  printf("\n");
2901  printf(" # of methods: %d\n", stat_methods);
2902  printf(" # of replacement points: %d\n", stat_rploints);
2903  printf(" # of regallocs: %d\n", stat_regallocs);
2904  printf(" per rplpoint: %f\n", (double)stat_regallocs / stat_rploints);
2905  printf(" per method: %f\n", (double)stat_regallocs / stat_methods);
2906  REPLACE_PRINT_DIST("replacement points per method", stat_dist_method_rplpoints);
2907  printf("\n");
2908 
2909 }
2910 #endif /* defined(REPLACE_STATISTICS) */
2911 
2912 
2913 #if defined(REPLACE_STATISTICS)
2914 static void replace_statistics_source_frame(sourceframe_t *frame)
2915 {
2916  int adr = 0;
2917  int ret = 0;
2918  int prim = 0;
2919  int vd = 0;
2920  int n = 0;
2921  int i;
2922 
2923  for (i=0; i<frame->javalocalcount; ++i) {
2924  switch (frame->javalocaltype[i]) {
2925  case TYPE_ADR: adr++; break;
2926  case TYPE_RET: ret++; break;
2927  case TYPE_INT: case TYPE_LNG: case TYPE_FLT: case TYPE_DBL: prim++; break;
2928  case TYPE_VOID: vd++; break;
2929  default: assert(0);
2930  }
2931  n++;
2932  }
2938  adr = ret = prim = n = 0;
2939  for (i=0; i<frame->javastackdepth; ++i) {
2940  switch (frame->javastacktype[i]) {
2941  case TYPE_ADR: adr++; break;
2942  case TYPE_RET: ret++; break;
2943  case TYPE_INT: case TYPE_LNG: case TYPE_FLT: case TYPE_DBL: prim++; break;
2944  }
2945  n++;
2946  }
2951 }
2952 #endif /* defined(REPLACE_STATISTICS) */
2953 
2954 
2955 /* debugging helpers **********************************************************/
2956 
2957 /* replace_replacement_point_println *******************************************
2958 
2959  Print replacement point info.
2960 
2961  IN:
2962  rp...............the replacement point to print
2963 
2964 *******************************************************************************/
2965 
2966 #if !defined(NDEBUG)
2967 
2968 #define TYPECHAR(t) (((t) >= 0 && (t) <= TYPE_RET) ? show_jit_type_letters[t] : '?')
2969 
2970 static const char *replace_type_str[] = {
2971  "STD",
2972  "EXH",
2973  "SBR",
2974  "CALL",
2975  "INLINE",
2976  "RETURN",
2977  "BODY"
2978 };
2979 
2981 {
2982  int j;
2983  int index;
2984 
2985  if (!rp) {
2986  printf("(rplpoint *)NULL\n");
2987  return;
2988  }
2989 
2990  for (j=0; j<depth; ++j)
2991  putchar('\t');
2992 
2993  printf("rplpoint (id %d) %p pc:%p+%d type:%s",
2994  rp->id, (void*)rp,rp->pc,rp->callsize,
2995  replace_type_str[rp->type]);
2996  if (rp->flags & rplpoint::FLAG_NOTRAP)
2997  printf(" NOTRAP");
2998  if (rp->flags & rplpoint::FLAG_COUNTDOWN)
2999  printf(" COUNTDOWN");
3000  if (rp->flags & rplpoint::FLAG_ACTIVE)
3001  printf(" ACTIVE");
3002  printf(" parent:%p\n", (void*)rp->parent);
3003  for (j=0; j<depth; ++j)
3004  putchar('\t');
3005  printf("ra:%d = [", rp->regalloccount);
3006 
3007  for (j=0; j<rp->regalloccount; ++j) {
3008  if (j)
3009  putchar(' ');
3010  index = rp->regalloc[j].index;
3011  switch (index) {
3012  case RPLALLOC_STACK: printf("S"); break;
3013  case RPLALLOC_PARAM: printf("P"); break;
3014  case RPLALLOC_SYNC : printf("Y"); break;
3015  default: printf("%d", index);
3016  }
3017  printf(":%1c:", TYPECHAR(rp->regalloc[j].type));
3018  if (rp->regalloc[j].type == TYPE_RET) {
3019  printf("ret(L%03d)", rp->regalloc[j].regoff);
3020  }
3021  else {
3022  show_allocation(rp->regalloc[j].type, rp->regalloc[j].flags, rp->regalloc[j].regoff);
3023  }
3024  }
3025 
3026  printf("]\n");
3027  for (j=0; j<depth; ++j)
3028  putchar('\t');
3029  printf("method: ");
3030  method_print(rp->method);
3031 
3032  printf("\n");
3033 }
3034 #endif /* !defined(NDEBUG) */
3035 
3036 
3037 /* replace_show_replacement_points *********************************************
3038 
3039  Print replacement point info.
3040 
3041  IN:
3042  code.............codeinfo whose replacement points should be printed.
3043 
3044 *******************************************************************************/
3045 
3046 #if !defined(NDEBUG)
3048 {
3049  int i;
3050  int depth;
3051  rplpoint *rp;
3052  rplpoint *parent;
3053 
3054  if (!code) {
3055  printf("(codeinfo *)NULL\n");
3056  return;
3057  }
3058 
3059  printf("\treplacement points: %d\n",code->rplpointcount);
3060 
3061  printf("\ttotal allocations : %d\n",code->regalloccount);
3062  printf("\tsaved int regs : %d\n",code->savedintcount);
3063  printf("\tsaved flt regs : %d\n",code->savedfltcount);
3064  printf("\tmemuse : %d\n",code->memuse);
3065 
3066  printf("\n");
3067 
3068  for (i=0; i<code->rplpointcount; ++i) {
3069  rp = code->rplpoints + i;
3070 
3071  depth = 1;
3072  parent = rp->parent;
3073  while (parent) {
3074  depth++;
3075  parent = parent->parent;
3076  }
3078  }
3079 }
3080 #endif
3081 
3082 
3083 #if !defined(NDEBUG)
3084 static void java_value_print(s4 type, replace_val_t value)
3085 {
3086  java_object_t *obj;
3087  Utf8String u;
3088 
3089  printf("%016llx",(unsigned long long) value.l);
3090 
3091  if (type < 0 || type > TYPE_RET)
3092  printf(" <INVALID TYPE:%d>", type);
3093  else
3094  printf(" %s", show_jit_type_names[type]);
3095 
3096  if (type == TYPE_ADR && value.a != NULL) {
3097  obj = value.a;
3098  putchar(' ');
3100 
3101  if (obj->vftbl->clazz == class_java_lang_String) {
3102  printf(" \"");
3103  u = JavaString(obj).to_utf8();
3105  printf("\"");
3106  }
3107  }
3108  else if (type == TYPE_INT) {
3109  printf(" %ld", (long) value.i);
3110  }
3111  else if (type == TYPE_LNG) {
3112  printf(" %lld", (long long) value.l);
3113  }
3114  else if (type == TYPE_FLT) {
3115  printf(" %f", value.f);
3116  }
3117  else if (type == TYPE_DBL) {
3118  printf(" %f", value.d);
3119  }
3120 }
3121 #endif /* !defined(NDEBUG) */
3122 
3123 
3124 #if !defined(NDEBUG)
3125 void replace_source_frame_println(sourceframe_t *frame)
3126 {
3127  s4 i,j;
3128  s4 t;
3129 
3130  if (REPLACE_IS_NATIVE_FRAME(frame)) {
3131  printf("\tNATIVE\n");
3132  printf("\tsfi: "); replace_stackframeinfo_println(frame->sfi);
3133  printf("\tnativepc: %p\n", frame->nativepc);
3134  printf("\tframesize: %d\n", frame->nativeframesize);
3135 
3136  j = 0;
3137  for (i=0; i<INT_REG_CNT; ++i) {
3138  if (nregdescint[i] == REG_SAV)
3139  printf("\t%s = %p\n", abi_registers_integer_name[i], (void*)frame->nativesavint[j++]);
3140  }
3141 
3142  j = 0;
3143  for (i=0; i<FLT_REG_CNT; ++i) {
3144  if (nregdescfloat[i] == REG_SAV)
3145  printf("\tF%02d = %f\n", i, frame->nativesavflt[j++]);
3146  }
3147 
3148  printf("\n");
3149  return;
3150  }
3151 
3152  printf("\t");
3153  method_println(frame->method);
3154  printf("\tid: %d\n", frame->id);
3155  printf("\ttype: %s\n", replace_type_str[frame->type]);
3156  printf("\n");
3157 
3158  if (frame->instance.a) {
3159  printf("\tinstance: ");
3160  java_value_print(TYPE_ADR, frame->instance);
3161  printf("\n");
3162  }
3163 
3164  if (frame->javalocalcount) {
3165  printf("\tlocals (%d):\n",frame->javalocalcount);
3166  for (i=0; i<frame->javalocalcount; ++i) {
3167  t = frame->javalocaltype[i];
3168  if (t == TYPE_VOID) {
3169  printf("\tlocal[ %2d] = void\n",i);
3170  }
3171  else {
3172  printf("\tlocal[%c%2d] = ",TYPECHAR(t),i);
3173  java_value_print(t, frame->javalocals[i]);
3174  printf("\n");
3175  }
3176  }
3177  printf("\n");
3178  }
3179 
3180  if (frame->javastackdepth) {
3181  printf("\tstack (depth %d):\n",frame->javastackdepth);
3182  for (i=0; i<frame->javastackdepth; ++i) {
3183  t = frame->javastacktype[i];
3184  if (t == TYPE_VOID) {
3185  printf("\tstack[%2d] = void", i);
3186  }
3187  else {
3188  printf("\tstack[%2d] = ",i);
3189  java_value_print(frame->javastacktype[i], frame->javastack[i]);
3190  printf("\n");
3191  }
3192  }
3193  printf("\n");
3194  }
3195 
3196  if (frame->syncslotcount) {
3197  printf("\tsynchronization slots (%d):\n",frame->syncslotcount);
3198  for (i=0; i<frame->syncslotcount; ++i) {
3199  printf("\tslot[%2d] = %016llx\n",i,(unsigned long long) frame->syncslots[i].p);
3200  }
3201  printf("\n");
3202  }
3203 
3204  if (frame->fromcode) {
3205  printf("\tfrom %p ", (void*)frame->fromcode);
3206  method_println(frame->fromcode->m);
3207  }
3208  if (frame->tocode) {
3209  printf("\tto %p ", (void*)frame->tocode);
3210  method_println(frame->tocode->m);
3211  }
3212 
3213  if (frame->fromrp) {
3214  printf("\tfrom replacement point:\n");
3215  replace_replacement_point_println(frame->fromrp, 2);
3216  }
3217  if (frame->torp) {
3218  printf("\tto replacement point:\n");
3219  replace_replacement_point_println(frame->torp, 2);
3220  }
3221 
3222  printf("\n");
3223 }
3224 #endif /* !defined(NDEBUG) */
3225 
3226 
3227 /* replace_sourcestate_println *************************************************
3228 
3229  Print source state
3230 
3231  IN:
3232  ss...............the source state to print
3233 
3234 *******************************************************************************/
3235 
3236 #if !defined(NDEBUG)
3237 void replace_sourcestate_println(sourcestate_t *ss)
3238 {
3239  int i;
3240  sourceframe_t *frame;
3241 
3242  if (!ss) {
3243  printf("(sourcestate_t *)NULL\n");
3244  return;
3245  }
3246 
3247  printf("sourcestate_t:\n");
3248 
3249  for (i=0, frame = ss->frames; frame != NULL; frame = frame->down, ++i) {
3250  printf(" frame %d:\n", i);
3252  }
3253 }
3254 #endif
3255 
3256 
3257 /* replace_sourcestate_println_short *******************************************
3258 
3259  Print a compact representation of the given source state.
3260 
3261  IN:
3262  ss...............the source state to print
3263 
3264 *******************************************************************************/
3265 
3266 #if !defined(NDEBUG)
3267 void replace_sourcestate_println_short(sourcestate_t *ss)
3268 {
3269  sourceframe_t *frame;
3270 
3271  for (frame = ss->frames; frame != NULL; frame = frame->down) {
3272  printf("\t");
3273 
3274  if (REPLACE_IS_NATIVE_FRAME(frame)) {
3275  printf("NATIVE (pc %p size %d) ",
3276  (void*)frame->nativepc, frame->nativeframesize);
3277  replace_stackframeinfo_println(frame->sfi);
3278  continue;
3279  }
3280 
3281  if (frame->torp) {
3282  printf("%c", (frame->torp == frame->fromrp) ? '=' : '+');
3283  }
3284 
3285  printf("%s", replace_type_str[frame->fromrp->type]);
3286 
3287  if (frame->torp && frame->torp->type != frame->fromrp->type)
3288  printf("->%s", replace_type_str[frame->torp->type]);
3289 
3290  if (frame->tocode != frame->fromcode)
3291  printf(" (%p->%p/%d) ",
3292  (void*) frame->fromcode, (void*) frame->tocode,
3293  frame->fromrp->id);
3294  else
3295  printf(" (%p/%d) ", (void*) frame->fromcode, frame->fromrp->id);
3296 
3297  method_println(frame->method);
3298  }
3299 }
3300 #endif
3301 
3302 #if !defined(NDEBUG)
3304 {
3305  printf("prev=%p pv=%p sp=%p ra=%p xpc=%p method=",
3306  (void*)sfi->prev, (void*)sfi->pv, (void*)sfi->sp,
3307  (void*)sfi->ra, (void*)sfi->xpc);
3308 
3309  if (sfi->code)
3310  method_println(sfi->code->m);
3311  else
3312  printf("(nil)\n");
3313 }
3314 #endif
3315 
3316 
3317 /*
3318  * These are local overrides for various environment variables in Emacs.
3319  * Please do not remove this and leave it at the end of the file, where
3320  * Emacs will automagically detect them.
3321  * ---------------------------------------------------------------------
3322  * Local variables:
3323  * mode: c++
3324  * indent-tabs-mode: t
3325  * c-basic-offset: 4
3326  * tab-width: 4
3327  * End:
3328  * vim:noexpandtab:sw=4:ts=4:
3329  */
methodptr * interfacetable[1]
Definition: vftbl.hpp:99
#define REG_SP
Definition: md-abi.hpp:53
static void replace_push_native_frame(executionstate_t *es, sourcestate_t *ss)
Definition: replace.cpp:2199
#define TOP_IS_ON_STACK
Definition: replace.cpp:144
#define GET_HIGH_REG(a)
std::size_t index
methodinfo * outer
#define pv
Definition: md-asm.hpp:65
union varinfo::@19 vv
#define REG_PV
Definition: md-abi.hpp:42
#define REPLACE_COUNT_IF(cnt, cond)
Definition: replace.cpp:119
codeinfo * jit_get_current_code(methodinfo *m)
Definition: jit.cpp:968
codeinfo * code
Definition: stacktrace.hpp:50
void replace_replacement_point_println(rplpoint *rp, int depth)
Definition: replace.cpp:2980
void replace_show_replacement_points(codeinfo *code)
Definition: replace.cpp:3047
void replace_free_replacement_points(codeinfo *code)
Definition: replace.cpp:722
basicblock * basicblocks
Definition: jit.hpp:141
insinfo_inline * parent
static int stat_dist_locals_prim[10]
Definition: replace.cpp:106
Definition: jit.hpp:126
#define ra
Definition: md-asm.hpp:62
void method_print(methodinfo *m)
Definition: method.cpp:1189
paramdesc * params
Definition: descriptor.hpp:164
void executionstate_pop_stackframe(executionstate_t *es)
Restore callee-saved registers (including the RA register), set the stack pointer to the next stackfr...
static struct stackframeinfo_t * threads_get_current_stackframeinfo(void)
Definition: thread.hpp:313
u1 * disassinstr(u1 *code)
Definition: disass.cpp:48
methodinfo * code_get_methodinfo_for_pv(void *pv)
Definition: code.cpp:150
static int stat_dist_frames[20]
Definition: replace.cpp:103
void replace_activate_replacement_points(codeinfo *code, bool mappable)
Definition: replace.cpp:759
s4 localcount
Definition: jit.hpp:152
#define REG_SAV
Definition: jit.hpp:442
Utf8String to_utf8() const
Definition: string.cpp:437
static int stat_dist_stack_prim[10]
Definition: replace.cpp:111
s4 bitflags
Definition: jit.hpp:314
#define SUPPORT_COMBINE_INTEGER_REGISTERS
Definition: arch.hpp:94
State state
Definition: jit.hpp:313
static int stat_dist_locals[20]
Definition: replace.cpp:104
sourcestate_t * replace_recover_source_state(rplpoint *rp, stackframeinfo_t *sfi, executionstate_t *es)
Definition: replace.cpp:2279
uint8_t savedfltcount
Definition: code.hpp:91
#define GC_SOURCESTATE
Definition: gc.h:149
s4 maxlocals
Definition: jit.hpp:162
s4 * invars
Definition: jit.hpp:323
basicblock * next
Definition: jit.hpp:337
int32_t stackframesize
Definition: code.hpp:88
static sourceframe_t * replace_new_sourceframe(sourcestate_t *ss)
Definition: replace.cpp:1032
void utf_display_printable_ascii_classname(Utf8String u)
Definition: utf8.cpp:552
static int stat_dist_method_rplpoints[20]
Definition: replace.cpp:116
codeinfo * code
Definition: jit.hpp:128
insinfo_inline * inlineinfo
Definition: jit.hpp:343
s4 nregdescint[]
Definition: md-abi.cpp:41
int32_t * stackvars
void replace_deactivate_replacement_points(codeinfo *code)
Definition: replace.cpp:840
static int stat_staticpatch
Definition: replace.cpp:100
int32_t argcount
Definition: instruction.hpp:64
static s4 replace_normalize_type_map[]
Definition: replace.cpp:1065
#define REPLACE_COUNT_DIST(array, val)
Definition: replace.cpp:122
varinfo * var
Definition: jit.hpp:148
static void replace_pop_native_frame(executionstate_t *es, sourcestate_t *ss, stackframeinfo_t *sfi)
Definition: replace.cpp:2106
bool replace_create_replacement_points(jitdata *jd)
Definition: replace.cpp:350
static void replace_write_executionstate(rplpoint *rp, executionstate_t *es, sourcestate_t *ss, bool topframe)
Definition: replace.cpp:1310
void replace_patch_future_calls(u1 *ra, sourceframe_t *callerframe, sourceframe_t *calleeframe)
Definition: replace.cpp:1790
int32_t varindex
Definition: instruction.hpp:63
static int stat_replacements
Definition: replace.cpp:97
void replace_patch_callback(classinfo *c, struct replace_patch_data_t *pd)
Definition: replace.cpp:1746
static int stat_unroll_inline
Definition: replace.cpp:101
#define DOLOG(code)
Definition: replace.cpp:83
void replace_sourcestate_println_short(sourcestate_t *ss)
Definition: replace.cpp:3267
#define COUNT_javalocals(array, method, counter)
Definition: replace.cpp:343
static void replace_build_execution_state(sourcestate_t *ss, executionstate_t *es)
Definition: replace.cpp:2551
#define LA_LR_OFFSET
Definition: md-abi.hpp:97
#define INT_REG_CNT
Definition: md-abi.hpp:72
#define BBFLAG_REPLACEMENT
Definition: jit.hpp:285
uint8_t u1
Definition: types.hpp:40
u1 * methodptr
Definition: global.hpp:40
Type type
Definition: reg.hpp:44
#define REPLACE_COUNT(cnt)
Definition: replace.cpp:118
s4 * interfacevftbllength
Definition: vftbl.hpp:115
void(* classcache_foreach_functionptr_t)(classinfo *, void *)
Definition: classcache.hpp:115
#define JITDATA_HAS_FLAG_COUNTDOWN(jd)
Definition: jit.hpp:218
static int stat_recompile
Definition: replace.cpp:99
instruction * iinstr
Definition: jit.hpp:319
#define VAR(i)
Definition: jit.hpp:252
Definition: reg.hpp:43
void replace_sourcestate_println(sourcestate_t *ss)
Definition: replace.cpp:3237
rplpoint * replace_find_replacement_point(codeinfo *code, sourceframe_t *frame, rplpoint *parent)
Definition: replace.cpp:1975
s4 icount
Definition: jit.hpp:318
void jit_request_optimization(methodinfo *m)
Definition: jit.cpp:943
static int code_is_leafmethod(codeinfo *code)
Definition: code.hpp:151
void replace_patch_class_hierarchy(methodinfo *m, u1 *oldentrypoint, u1 *entrypoint)
Definition: replace.cpp:1759
static void replace_read_value(executionstate_t *es, rplalloc *ra, replace_val_t *javaval)
Definition: replace.cpp:928
#define MZERO(ptr, type, num)
Definition: memory.hpp:105
void vm_abort(const char *text,...)
Definition: vm.cpp:2586
s4 regoff
Definition: reg.hpp:47
methodinfo * m
Definition: code.hpp:75
s4 * javalocals
Definition: jit.hpp:322
#define IS_2_WORD_TYPE(a)
Definition: global.hpp:132
#define GET_LOW_REG(a)
static void replace_write_value(executionstate_t *es, rplalloc *ra, replace_val_t *javaval)
Definition: replace.cpp:978
static void replace_read_executionstate(rplpoint *rp, executionstate_t *es, sourcestate_t *ss, bool topframe)
Definition: replace.cpp:1076
#define TYPECHAR(t)
Definition: replace.cpp:2968
s4 interfacetablelength
Definition: vftbl.hpp:103
jlong jlong jlong jlong jint depth
Definition: jvmti.h:497
codeinfo * code_find_codeinfo_for_pc(void *pc)
Definition: code.cpp:101
s4 vftblindex
Definition: method.hpp:81
void executionstate_println(executionstate_t *es)
#define REPLACE_COUNT_INC(cnt, inc)
Definition: replace.cpp:120
static int stat_rploints
Definition: replace.cpp:114
static void print_freq(FILE *file, int *array, int limit)
Definition: replace.cpp:2857
flags_operand_t flags
static int stat_dist_locals_ret[10]
Definition: replace.cpp:107
Dump memory area.
Definition: dumpmemory.hpp:90
void replace_source_frame_println(sourceframe_t *frame)
Definition: replace.cpp:3125
uint16_t u2
Definition: types.hpp:43
methodinfo * method
void method_println(methodinfo *m)
Definition: method.cpp:1218
s4 vftbllength
Definition: vftbl.hpp:102
uint64_t u8
Definition: types.hpp:49
Utf8String name
Definition: class.hpp:91
void replace_patch_class(vftbl_t *vftbl, methodinfo *m, u1 *oldentrypoint, u1 *entrypoint)
Definition: replace.cpp:1699
classinfo * clazz
Definition: vftbl.hpp:100
void class_println(classinfo *c)
Definition: class.cpp:2276
static codeinfo * code_get_codeinfo_for_pv(void *pv)
Definition: code.hpp:201
const char * show_jit_type_names[]
Definition: show.cpp:105
#define IS_FLT_DBL_TYPE(a)
Definition: global.hpp:131
int32_t paramcount
bool gc_pending
Definition: gc.c:54
Type
Types used internally by JITTED code.
Definition: global.hpp:117
static int stat_regallocs
Definition: replace.cpp:115
#define RETADDR_FROM_JAVALOCAL(jl)
Definition: jit.hpp:417
s4 indepth
Definition: jit.hpp:325
JNIEnv jthread thread
Definition: jvmti.h:207
static void replace_create_replacement_point(jitdata *jd, insinfo_inline *iinfo, rplpoint *rp, rplpoint::Type type, instruction *iptr, rplalloc **pra, s4 *javalocals, s4 *stackvars, s4 stackdepth, s4 paramcount)
Definition: replace.cpp:175
MIIterator i
#define SIZE_OF_STACKSLOT
Definition: simplereg.cpp:80
#define TOP_IS_VOID
Definition: replace.cpp:146
int32_t s4
Definition: types.hpp:45
int32_t * javalocals_start
registerdata * rd
Definition: jit.hpp:130
void threads_suspend_ack()
static void * md_codegen_get_pv_from_pc(void *ra)
Definition: md.hpp:99
void md_push_stackframe(executionstate_t *es, codeinfo *calleecode, u1 *ra)
Definition: replace.cpp:1473
s4 maxlocals
Definition: method.hpp:84
union instruction::@12 sx
static void java_value_print(s4 type, replace_val_t value)
Definition: replace.cpp:3084
#define STACK_SLOTS_PER_FLOAT
void stack_javalocals_store(instruction *iptr, s4 *javalocals)
Definition: stack.cpp:4692
u1 * replace_pop_activation_record(executionstate_t *es, sourceframe_t *frame)
Definition: replace.cpp:1591
bool inmemory
Definition: descriptor.hpp:151
const char * abi_registers_integer_name[]
Definition: md-abi.cpp:57
#define INSTRUCTION_GET_METHODDESC(iptr, md)
This file contains the real-time timing utilities.
void utf_display_printable_ascii(Utf8String u)
Definition: utf8.cpp:532
void replace_push_activation_record(executionstate_t *es, rplpoint *rpcall, sourceframe_t *callerframe, sourceframe_t *calleeframe)
Definition: replace.cpp:1898
static int stat_dist_stack_ret[10]
Definition: replace.cpp:112
s1_operand_t s1
static insinfo_inline * replace_create_inline_start_replacement_point(jitdata *jd, rplpoint *rp, instruction *iptr, rplalloc **pra, s4 *javalocals)
Definition: replace.cpp:274
void * md_jit_method_patch_address(void *pv, void *ra, void *mptr)
Definition: md.cpp:83
bool regalloc(jitdata *jd)
Definition: simplereg.cpp:262
methodinfo * m
Definition: replace.cpp:1741
#define REPLACEMENT_PATCH_SIZE
Definition: arch.hpp:111
vftbl_t * vftbl
Definition: class.hpp:121
classinfo * class_java_lang_String
Definition: globals.cpp:39
static int stat_unroll_call
Definition: replace.cpp:102
#define sp
Definition: md-asm.hpp:81
int memuse
Definition: reg.hpp:84
static int stat_frames
Definition: replace.cpp:98
void replace_print_statistics(void)
Definition: replace.cpp:2881
#define pc
Definition: md-asm.hpp:56
#define MNEW(type, num)
Definition: memory.hpp:96
methodinfo * m
Definition: jit.hpp:127
void show_allocation(s4 type, s4 flags, s4 regoff)
Definition: show.cpp:760
static int stat_dist_locals_void[10]
Definition: replace.cpp:108
stackframeinfo_t * prev
Definition: stacktrace.hpp:49
methodinfo * method
Definition: jit.hpp:342
bool replace_handler(u1 *pc, executionstate_t *es)
Definition: replace.cpp:2758
#define TOP_IS_NORMAL
Definition: replace.cpp:143
s4 flags
Definition: reg.hpp:45
rplpoint * replace_find_replacement_point_for_pc(codeinfo *code, u1 *pc, unsigned desired_flags)
Definition: replace.cpp:2062
static void replace_stackframeinfo_println(stackframeinfo_t *sfi)
Definition: replace.cpp:3303
static void * allocate(size_t size)
Definition: dumpmemory.hpp:251
s4 nr
Definition: jit.hpp:312
static void replace_patch_method_pointer(methodptr *mpp, methodptr entrypoint, const char *kind)
Definition: replace.cpp:1657
basicblock * retaddr
Definition: reg.hpp:52
void classcache_foreach_loaded_class(classcache_foreach_functionptr_t func, void *data)
#define TOP_IS_IN_ITMP1
Definition: replace.cpp:145
struct instruction::@12::@13 s23
uintptr_t intregs[INT_REG_CNT]
#define REPLACE_PRINT_DIST(name, array)
Definition: replace.cpp:2877
#define GC_EXECUTIONSTATE
Definition: gc.h:148
#define DOLOG_SHORT(code)
Definition: replace.cpp:84
int32_t throughcount
static int stat_dist_stack_adr[10]
Definition: replace.cpp:110
methodptr table[1]
Definition: vftbl.hpp:116
s4 nregdescfloat[]
Definition: md-abi.cpp:98
#define MCOPY(dest, src, type, num)
Definition: memory.hpp:103
s4 flags
Definition: method.hpp:70
static void replace_me(rplpoint *rp, executionstate_t *es)
Definition: replace.cpp:2624
uintptr_t ptrint
Definition: types.hpp:54
int32_t stackvarscount
vftbl_t * vftbl
Definition: global.hpp:264
#define COPY_OR_CLEAR_javalocals(dest, array, method)
Definition: replace.cpp:335
double fltregs[FLT_REG_CNT]
static int stat_dist_stack[10]
Definition: replace.cpp:109
uint32_t regoff
Definition: descriptor.hpp:153
static int stat_dist_locals_adr[10]
Definition: replace.cpp:105
#define MFREE(ptr, type, num)
Definition: memory.hpp:97
Type type
Definition: jit.hpp:315
#define printf(...)
Definition: ssa2.cpp:40
#define THREADOBJECT
Definition: thread-none.hpp:47
uint64_t stackslot_t
LoopTreeGraph * parent
uint8_t savedintcount
Definition: code.hpp:90
static void replace_statistics_source_frame(sourceframe_t *frame)
Definition: replace.cpp:2914
#define FLT_REG_CNT
Definition: md-abi.hpp:79
static bool replace_map_source_state(sourcestate_t *ss)
Definition: replace.cpp:2410
static int stat_methods
Definition: replace.cpp:113
static int32_t md_stacktrace_get_framesize(codeinfo *code)
Returns the size (in bytes) of the current stackframe, specified by the passed codeinfo structure...
Definition: md.hpp:56
#define REG_ITMP1
Definition: md-abi.hpp:46
int32_t * javalocals_end
u1 * entrypoint
Definition: code.hpp:84
#define asm_abstractmethoderror
Definition: md-asm.hpp:86
static const char * replace_type_str[]
Definition: replace.cpp:2970
#define INS_FLAG_ID_SHIFT