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 #include "mm/dumpmemory.hpp"
37 #include "mm/memory.hpp"
38 
39 #include "threads/thread.hpp"
40 
41 #include "toolbox/logging.hpp"
42 
43 #include "vm/classcache.hpp"
44 #include "vm/descriptor.hpp"
45 #include "vm/globals.hpp"
46 #include "vm/options.hpp"
47 #include "vm/string.hpp"
48 
49 #if defined(ENABLE_RT_TIMING)
50 # include "vm/rt-timing.hpp"
51 #endif
52 
53 #include "vm/jit/abi.hpp"
54 #include "vm/jit/asmpart.hpp"
55 #include "vm/jit/disass.hpp"
57 #include "vm/jit/jit.hpp"
58 #include "vm/jit/methodheader.hpp"
59 #include "vm/jit/replace.hpp"
60 #include "vm/jit/show.hpp"
61 #include "vm/jit/stack.hpp"
62 #include "vm/jit/stacktrace.hpp"
63 
65 
66 #define DEBUG_NAME "replace"
67 
68 using namespace cacao;
69 
70 #define REPLACE_PATCH_DYNAMIC_CALL
71 /*#define REPLACE_PATCH_ALL*/
72 
73 /*** constants used internally ************************************************/
74 
75 #define TOP_IS_NORMAL 0
76 #define TOP_IS_ON_STACK 1
77 #define TOP_IS_IN_ITMP1 2
78 #define TOP_IS_VOID 3
79 
80 /**
81  * Determines whether a given `sourceframe` represents a frame of a
82  * native method.
83  */
84 #define REPLACE_IS_NATIVE_FRAME(frame) ((frame)->sfi != NULL)
85 
86 /**
87  * Determeines whether the given replacement point is at a call site.
88  */
89 #define REPLACE_IS_CALL_SITE(rp) ((rp)->callsize > 0)
90 
91 /* replace_free_replacement_points *********************************************
92 
93  Free memory used by replacement points.
94 
95  IN:
96  code.............codeinfo whose replacement points should be freed.
97 
98 *******************************************************************************/
99 
101 {
102  assert(code);
103 
104  if (code->rplpoints)
105  MFREE(code->rplpoints,rplpoint,code->rplpointcount);
106 
107  if (code->regalloc)
108  MFREE(code->regalloc,rplalloc,code->regalloccount);
109 
110  code->rplpoints = NULL;
111  code->rplpointcount = 0;
112  code->regalloc = NULL;
113  code->regalloccount = 0;
114  code->globalcount = 0;
115 }
116 
117 
118 /* replace_activate_replacement_points *****************************************
119 
120  Activate the replacement points of the given compilation unit. When this
121  function returns, the replacement points are "armed", so each thread
122  reaching one of the points will enter the replacement mechanism.
123 
124  IN:
125  code.............codeinfo of which replacement points should be
126  activated
127  mappable.........if true, only mappable replacement points are
128  activated
129 
130 *******************************************************************************/
131 
133 {
134  rplpoint *rp;
135  s4 i;
136  s4 count;
137  u1 *savedmcode;
138 
139  assert(code->savedmcode == NULL);
140 
141  /* count trappable replacement points */
142 
143  count = 0;
144  i = code->rplpointcount;
145  rp = code->rplpoints;
146  for (; i--; rp++) {
147  if (!(rp->flags & rplpoint::FLAG_TRAPPABLE))
148  continue;
149 
150 #if 0
151  if (mappable && (rp->type == rplpoint::TYPE_RETURN))
152  continue;
153 #endif
154 
155  count++;
156  }
157 
158  /* allocate buffer for saved machine code */
159 
160  savedmcode = MNEW(u1, count * REPLACEMENT_PATCH_SIZE);
161  code->savedmcode = savedmcode;
162  savedmcode += count * REPLACEMENT_PATCH_SIZE;
163 
164  /* activate trappable replacement points */
165  /* (in reverse order to handle overlapping points within basic blocks) */
166 
167  i = code->rplpointcount;
168  rp = code->rplpoints + i;
169  while (rp--, i--) {
170  assert(!(rp->flags & rplpoint::FLAG_ACTIVE));
171 
172  if (!(rp->flags & rplpoint::FLAG_TRAPPABLE))
173  continue;
174 
175 #if 0
176  if (mappable && (rp->type == rplpoint::TYPE_RETURN))
177  continue;
178 #endif
179 
180  LOG2("activate replacement point: " << rp << nl);
181 
182  savedmcode -= REPLACEMENT_PATCH_SIZE;
183  md_patch_replacement_point(rp->pc, savedmcode, false);
184  rp->flags |= rplpoint::FLAG_ACTIVE;
185  }
186 
187  assert(savedmcode == code->savedmcode);
188 }
189 
190 
191 /* replace_deactivate_replacement_points ***************************************
192 
193  Deactivate a replacement points in the given compilation unit.
194  When this function returns, the replacement points will be "un-armed",
195  that is a each thread reaching a point will just continue normally.
196 
197  IN:
198  code.............the compilation unit
199 
200 *******************************************************************************/
201 
203 {
204  rplpoint *rp;
205  s4 i;
206  s4 count;
207  u1 *savedmcode;
208 
209  assert(code->savedmcode != NULL);
210  savedmcode = code->savedmcode;
211 
212  /* de-activate each trappable replacement point */
213 
214  i = code->rplpointcount;
215  rp = code->rplpoints;
216  count = 0;
217  for (; i--; rp++) {
218  if (!(rp->flags & rplpoint::FLAG_ACTIVE))
219  continue;
220 
221  count++;
222 
223  LOG2("deactivate replacement point: " << rp << nl);
224  md_patch_replacement_point(rp->pc, savedmcode, true);
225  rp->flags &= ~rplpoint::FLAG_ACTIVE;
226  savedmcode += REPLACEMENT_PATCH_SIZE;
227  }
228 
229  assert(savedmcode == code->savedmcode + count * REPLACEMENT_PATCH_SIZE);
230 
231  /* free saved machine code */
232 
233  MFREE(code->savedmcode, u1, count * REPLACEMENT_PATCH_SIZE);
234  code->savedmcode = NULL;
235 }
236 
237 
238 /* replace_read_value **********************************************************
239 
240  Read a value with the given allocation from the execution state.
241 
242  IN:
243  es...............execution state
244  ra...............allocation
245  javaval..........where to put the value
246 
247  OUT:
248  *javaval.........the value
249 
250 *******************************************************************************/
251 
253  rplalloc *ra,
254  replace_val_t *javaval)
255 {
256  if (ra->inmemory) {
257  /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
258 #ifdef HAS_4BYTE_STACKSLOT
259  if (IS_2_WORD_TYPE(ra->type)) {
260  javaval->l = *(u8*)(es->sp + ra->regoff);
261  }
262  else {
263 #endif
264  javaval->p = *(ptrint*)(es->sp + ra->regoff);
265 #ifdef HAS_4BYTE_STACKSLOT
266  }
267 #endif
268  }
269  else {
270  /* allocated register */
271  if (IS_FLT_DBL_TYPE(ra->type)) {
272  javaval->d = es->fltregs[ra->regoff];
273 
274  if (ra->type == TYPE_FLT)
275  javaval->f = javaval->d;
276  }
277  else {
278 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
279  if (ra->type == TYPE_LNG) {
280  javaval->words.lo = es->intregs[GET_LOW_REG(ra->regoff)];
281  javaval->words.hi = es->intregs[GET_HIGH_REG(ra->regoff)];
282  }
283  else
284 #endif /* defined(SUPPORT_COMBINE_INTEGER_REGISTERS) */
285  javaval->p = es->intregs[ra->regoff];
286  }
287  }
288 }
289 
290 
291 /* replace_write_value *********************************************************
292 
293  Write a value to the given allocation in the execution state.
294 
295  IN:
296  es...............execution state
297  ra...............allocation
298  *javaval.........the value
299 
300 *******************************************************************************/
301 
303  rplalloc *ra,
304  replace_val_t *javaval)
305 {
306  if (ra->inmemory) {
307  /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
308 #ifdef HAS_4BYTE_STACKSLOT
309  if (IS_2_WORD_TYPE(ra->type)) {
310  *(u8*)(es->sp + ra->regoff) = javaval->l;
311  }
312  else {
313 #endif
314  *(ptrint*)(es->sp + ra->regoff) = javaval->p;
315 #ifdef HAS_4BYTE_STACKSLOT
316  }
317 #endif
318  }
319  else {
320  /* allocated register */
321  switch (ra->type) {
322  case TYPE_FLT:
323  es->fltregs[ra->regoff] = (double) javaval->f;
324  break;
325  case TYPE_DBL:
326  es->fltregs[ra->regoff] = javaval->d;
327  break;
329  case TYPE_LNG:
330  es->intregs[GET_LOW_REG(ra->regoff)] = javaval->words.lo;
331  es->intregs[GET_HIGH_REG(ra->regoff)] = javaval->words.hi;
332  break;
333 #endif
334  default:
335  es->intregs[ra->regoff] = javaval->p;
336  }
337  }
338 }
339 
340 
341 /* replace_new_sourceframe *****************************************************
342 
343  Allocate a new source frame and insert it at the front of the frame list.
344 
345  IN:
346  ss...............the source state
347 
348  OUT:
349  ss->frames.......set to new frame (the new head of the frame list).
350 
351  RETURN VALUE:
352  returns the new frame
353 
354 *******************************************************************************/
355 
356 static sourceframe_t *replace_new_sourceframe(sourcestate_t *ss)
357 {
358  sourceframe_t *frame;
359 
360  frame = (sourceframe_t*) DumpMemory::allocate(sizeof(sourceframe_t));
361  MZERO(frame, sourceframe_t, 1);
362 
363  frame->down = ss->frames;
364  ss->frames = frame;
365 
366  return frame;
367 }
368 
369 
370 /* replace_read_executionstate *************************************************
371 
372  Read a source frame from the given executions state.
373  The new source frame is pushed to the front of the frame list of the
374  source state.
375 
376  IN:
377  rp...............replacement point at which `es` was taken
378  es...............execution state
379  ss...............the source state to add the source frame to
380 
381  OUT:
382  *ss..............the source state with the newly created source frame
383  added
384 
385 *******************************************************************************/
386 
388 /* rplpoint::TYPE_STD |--> */ rplpoint::TYPE_STD,
389 /* rplpoint::TYPE_EXH |--> */ rplpoint::TYPE_STD,
390 /* rplpoint::TYPE_SBR |--> */ rplpoint::TYPE_STD,
391 /* rplpoint::TYPE_CALL |--> */ rplpoint::TYPE_CALL,
392 /* rplpoint::TYPE_INLINE |--> */ rplpoint::TYPE_CALL,
393 /* rplpoint::TYPE_RETURN |--> */ rplpoint::TYPE_RETURN,
394 /* rplpoint::TYPE_BODY |--> */ rplpoint::TYPE_STD
395 };
396 
397 
398 static void replace_read_executionstate(rplpoint *rp,
399  executionstate_t *es,
400  sourcestate_t *ss)
401 {
402  methodinfo *m;
403  codeinfo *code;
404  rplalloc *ra;
405  sourceframe_t *frame;
406  int topslot;
407  stackslot_t *sp;
408 #if defined(__I386__)
409  stackslot_t *basesp;
410 #endif
411  bool topframe;
412 
413  LOG("read execution state at replacement point " << rp << nl);
414 
415  code = code_find_codeinfo_for_pc(rp->pc);
416  m = rp->method;
417  topslot = TOP_IS_NORMAL;
418  topframe = ss->frames == NULL;
419 
420  /* stack pointer */
421 
422  sp = (stackslot_t *) es->sp;
423 
424  /* in some cases the top stack slot is passed in REG_ITMP1 */
425 
426 #if 0
427  if (rp->type == rplpoint::TYPE_EXH) {
428  topslot = TOP_IS_IN_ITMP1;
429  }
430 #endif
431 
432  /* calculate base stack pointer */
433 
434 #if defined(__I386__)
435  basesp = sp + code->stackframesize;
436 #endif
437 
438  /* create the source frame */
439 
440  frame = replace_new_sourceframe(ss);
441  frame->method = rp->method;
442  frame->id = rp->id;
443 #if 0
444  assert(rp->type >= 0 && rp->type < sizeof(replace_normalize_type_map)/sizeof(s4));
445  frame->type = replace_normalize_type_map[rp->type];
446 #endif
447  frame->fromrp = rp;
448  frame->fromcode = code;
449 
450  /* read local variables */
451 
452  frame->javalocalcount = m->maxlocals;
453  frame->javalocals = (replace_val_t*) DumpMemory::allocate(sizeof(replace_val_t) * frame->javalocalcount);
454  frame->javalocaltype = (u1*) DumpMemory::allocate(sizeof(u1) * frame->javalocalcount);
455 
456  /* mark values as undefined */
457  for (int javalocal_index = 0; javalocal_index < frame->javalocalcount;
458  ++javalocal_index) {
459 #if !defined(NDEBUG)
460  frame->javalocals[javalocal_index].l = (u8) 0x00dead0000dead00ULL;
461 #endif
462  frame->javalocaltype[javalocal_index] = TYPE_VOID;
463  }
464 
465  /* some entries in the intregs array are not meaningful */
466  /*es->intregs[REG_ITMP3] = (u8) 0x11dead1111dead11ULL;*/
467 #if !defined(NDEBUG)
468  es->intregs[REG_SP ] = (ptrint) 0x11dead1111dead11ULL;
469 #ifdef REG_PV
470  es->intregs[REG_PV ] = (ptrint) 0x11dead1111dead11ULL;
471 #endif
472 #endif /* !defined(NDEBUG) */
473 
474  /* read javalocals */
475 
476  ra = rp->regalloc;
477  int remaining_allocations = rp->regalloccount;
478 
479  while (remaining_allocations && ra->index >= 0) {
480  assert(ra->index < m->maxlocals);
481  frame->javalocaltype[ra->index] = ra->type;
482  if (ra->type == TYPE_RET)
483  frame->javalocals[ra->index].i = ra->regoff;
484  else
485  replace_read_value(es, ra, frame->javalocals + ra->index);
486  ra++;
487  remaining_allocations--;
488  }
489 
490  /* read instance, if this is the first rplpoint */
491 
492 #if defined(REPLACE_PATCH_DYNAMIC_CALL)
493  if (topframe && !(rp->method->flags & ACC_STATIC) && rp == code->rplpoints) {
494 #if 1
495  /* we are at the start of the method body, so if local 0 is set, */
496  /* it is the instance. */
497  if (frame->javalocaltype[0] == TYPE_ADR)
498  frame->instance = frame->javalocals[0];
499 #else
500  rplalloc instra;
501  methoddesc *md;
502 
503  md = rp->method->parseddesc;
504  assert(md->params);
505  assert(md->paramcount >= 1);
506  instra.type = TYPE_ADR;
507  instra.regoff = md->params[0].regoff;
508  if (md->params[0].inmemory) {
509  instra.flags = INMEMORY;
510  instra.regoff += (1 + code->stackframesize) * SIZE_OF_STACKSLOT;
511  }
512  else {
513  instra.flags = 0;
514  }
515  replace_read_value(es, &instra, &(frame->instance));
516 #endif
517  }
518 #if defined(__I386__)
519  else if (!(rp->method->flags & ACC_STATIC)) {
520  /* On i386 we always pass the first argument on stack. */
521  frame->instance.a = *(java_object_t **)(basesp + 1);
522  }
523 #endif
524 #endif /* defined(REPLACE_PATCH_DYNAMIC_CALL) */
525 
526  /* read stack slots */
527 
528  frame->javastackdepth = remaining_allocations;
529  frame->javastack = (replace_val_t*) DumpMemory::allocate(sizeof(replace_val_t) * frame->javastackdepth);
530  frame->javastacktype = (u1*) DumpMemory::allocate(sizeof(u1) * frame->javastackdepth);
531 
532 #if !defined(NDEBUG)
533  /* mark values as undefined */
534  for (int stack_index = 0; stack_index < frame->javastackdepth; ++stack_index) {
535  frame->javastack[stack_index].l = (u8) 0x00dead0000dead00ULL;
536  frame->javastacktype[stack_index] = TYPE_VOID;
537  }
538 #endif /* !defined(NDEBUG) */
539 
540  int stack_index = 0;
541 
542  /* the first stack slot is special in SBR and EXH blocks */
543 
544  if (topslot == TOP_IS_ON_STACK) {
545  assert(remaining_allocations);
546 
547  assert(ra->index == RPLALLOC_STACK);
548  assert(ra->type == TYPE_ADR);
549  frame->javastack[stack_index].p = sp[-1];
550  frame->javastacktype[stack_index] = TYPE_ADR; /* XXX RET */
551  remaining_allocations--;
552  stack_index++;
553  ra++;
554  }
555  else if (topslot == TOP_IS_IN_ITMP1) {
556  assert(remaining_allocations);
557 
558  assert(ra->index == RPLALLOC_STACK);
559  assert(ra->type == TYPE_ADR);
560  frame->javastack[stack_index].p = es->intregs[REG_ITMP1];
561  frame->javastacktype[stack_index] = TYPE_ADR; /* XXX RET */
562  remaining_allocations--;
563  stack_index++;
564  ra++;
565  }
566  else if (topslot == TOP_IS_VOID) {
567  assert(remaining_allocations);
568 
569  assert(ra->index == RPLALLOC_STACK);
570  frame->javastack[stack_index].l = 0;
571  frame->javastacktype[stack_index] = TYPE_VOID;
572  remaining_allocations--;
573  stack_index++;
574  ra++;
575  }
576 
577  /* read remaining stack slots */
578 
579  for (; remaining_allocations--; ra++) {
580  if (ra->index == RPLALLOC_SYNC) {
581  assert(rp->type == rplpoint::TYPE_INLINE);
582 
583  /* only read synchronization slots when traversing an inline point */
584 
585  if (!topframe) {
586  sourceframe_t *calleeframe = frame->down;
587  assert(calleeframe);
588  assert(calleeframe->syncslotcount == 0);
589  assert(calleeframe->syncslots == NULL);
590 
591  calleeframe->syncslotcount = 1;
592  calleeframe->syncslots = (replace_val_t*) DumpMemory::allocate(sizeof(replace_val_t));
593  replace_read_value(es,ra,calleeframe->syncslots);
594  }
595 
596  frame->javastackdepth--;
597  continue;
598  }
599 
600  assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
601 
602  /* do not read parameters of calls down the call chain */
603 
604  if (!topframe && ra->index == RPLALLOC_PARAM) {
605  frame->javastackdepth--;
606  } else {
607  if (ra->type == TYPE_RET)
608  frame->javastack[stack_index].i = ra->regoff;
609  else
610  replace_read_value(es,ra,frame->javastack + stack_index);
611  frame->javastacktype[stack_index] = ra->type;
612  stack_index++;
613  }
614  }
615 
616  LOG("recovered source frame: [" << frame << "]" << nl);
617 }
618 
619 
620 /* replace_write_executionstate ************************************************
621 
622  Pop a source frame from the front of the frame list of the given source state
623  and write its values into the execution state.
624 
625  IN:
626  rp...............replacement point for which execution state should be
627  created
628  es...............the execution state to modify
629  ss...............the given source state
630  topframe.........true, if this is the last (top-most) source frame to be
631  translated
632 
633  OUT:
634  *es..............the execution state derived from the source state
635 
636 *******************************************************************************/
637 
638 static void replace_write_executionstate(rplpoint *rp,
639  executionstate_t *es,
640  sourcestate_t *ss)
641 {
642  methodinfo *m;
643  rplalloc *ra;
644  sourceframe_t *frame;
645  int topslot;
646  stackslot_t *sp;
647  bool topframe;
648 
649  LOG("write execution state for " << rp << nl);
650 
651  m = rp->method;
652  topslot = TOP_IS_NORMAL;
653  topframe = ss->frames->down == NULL;
654 
655  /* pop a source frame */
656 
657  frame = ss->frames;
658  assert(frame);
659  ss->frames = frame->down;
660 
661  /* calculate stack pointer */
662 
663  sp = (stackslot_t *) es->sp;
664 
665 #if defined(__AARCH64__) || defined(__X86_64__)
666  if (code_is_using_frameptr(frame->tocode)) {
667  /* The frame pointer has to point to the beginning of the stack
668  frame. */
669 # if defined(__X86_64__)
670  es->intregs[RBP] = (uintptr_t) (sp + frame->tocode->stackframesize - 1);
671  LOG2("set RBP to " << (uintptr_t*) es->intregs[RBP] << nl);
672 # elif defined(__AARCH64__)
673  auto stackframesize = frame->tocode->stackframesize + (frame->tocode->stackframesize % 2);
674  es->intregs[REG_FP] = (uintptr_t) (sp + stackframesize - 2);
675  LOG2("set REG_FP to " << (uintptr_t*) es->intregs[REG_FP] << nl);
676 # endif
677  }
678 #endif
679 
680  /* in some cases the top stack slot is passed in REG_ITMP1 */
681 
682 #if 0
683  if (rp->type == rplpoint::TYPE_EXH) {
684  topslot = TOP_IS_IN_ITMP1;
685  }
686 #endif
687 
688  /* write javalocals */
689 
690  ra = rp->regalloc;
691  int remaining_allocations = rp->regalloccount;
692 
693  while (remaining_allocations && ra->index >= 0) {
694  assert(ra->index < m->maxlocals);
695  assert(ra->index < frame->javalocalcount);
696  assert(ra->type == frame->javalocaltype[ra->index]);
697  if (ra->type == TYPE_RET) {
698  /* XXX assert that it matches this rplpoint */
699  } else {
700  replace_write_value(es, ra, frame->javalocals + ra->index);
701  }
702  remaining_allocations--;
703  ra++;
704  }
705 
706  /* write stack slots */
707 
708  int stack_index = 0;
709 
710  /* the first stack slot is special in SBR and EXH blocks */
711 
712  if (topslot == TOP_IS_ON_STACK) {
713  assert(remaining_allocations);
714 
715  assert(ra->index == RPLALLOC_STACK);
716  assert(stack_index < frame->javastackdepth);
717  assert(frame->javastacktype[stack_index] == TYPE_ADR);
718  sp[-1] = frame->javastack[stack_index].p;
719  remaining_allocations--;
720  stack_index++;
721  ra++;
722  }
723  else if (topslot == TOP_IS_IN_ITMP1) {
724  assert(remaining_allocations);
725 
726  assert(ra->index == RPLALLOC_STACK);
727  assert(stack_index < frame->javastackdepth);
728  assert(frame->javastacktype[stack_index] == TYPE_ADR);
729  es->intregs[REG_ITMP1] = frame->javastack[stack_index].p;
730  remaining_allocations--;
731  stack_index++;
732  ra++;
733  }
734  else if (topslot == TOP_IS_VOID) {
735  assert(remaining_allocations);
736 
737  assert(ra->index == RPLALLOC_STACK);
738  assert(stack_index < frame->javastackdepth);
739  assert(frame->javastacktype[stack_index] == TYPE_VOID);
740  remaining_allocations--;
741  stack_index++;
742  ra++;
743  }
744 
745  /* write remaining stack slots */
746 
747  for (; remaining_allocations--; ra++) {
748  if (ra->index == RPLALLOC_SYNC) {
749  assert(rp->type == rplpoint::TYPE_INLINE);
750 
751  /* only write synchronization slots when traversing an inline point */
752 
753  if (!topframe) {
754  assert(frame->down);
755  assert(frame->down->syncslotcount == 1); /* XXX need to understand more cases */
756  assert(frame->down->syncslots != NULL);
757 
758  replace_write_value(es,ra,frame->down->syncslots);
759  }
760  continue;
761  }
762 
763  assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
764 
765  /* do not write parameters of calls down the call chain */
766 
767  if (!topframe && ra->index == RPLALLOC_PARAM) {
768  /* skip it */
769  /*
770  ra->index = RPLALLOC_PARAM;
771  replace_val_t v;
772  v.l = 0;
773  replace_write_value(es,ra,&v);
774  */
775  }
776  else {
777  assert(stack_index < frame->javastackdepth);
778  assert(ra->type == frame->javastacktype[stack_index]);
779  if (ra->type == TYPE_RET) {
780  /* XXX assert that it matches this rplpoint */
781  }
782  else {
783  replace_write_value(es,ra,frame->javastack + stack_index);
784  }
785  stack_index++;
786  }
787  }
788 
789  /* set new pc */
790 
791  es->pc = rp->pc;
792 }
793 
794 
795 /* md_push_stackframe **********************************************************
796 
797  Save the given return address, build the new stackframe,
798  and store callee-saved registers.
799 
800  *** This function imitates the effects of a call and the ***
801  *** method prolog of the callee. ***
802 
803  IN:
804  es...............execution state
805  calleecode.......the code we are "calling"
806  ra...............the return address to save
807 
808  OUT:
809  *es..............the execution state after pushing the stack frame
810  NOTE: es->pc, es->code, and es->pv are NOT updated.
811 
812 *******************************************************************************/
813 
815 {
816  s4 reg;
817  s4 i;
818  stackslot_t *basesp;
819  stackslot_t *sp;
820 
821  assert(es);
822  assert(calleecode);
823 
824  /* write the return address */
825 
826 #if STACKFRAME_RA_BETWEEN_FRAMES
827  es->sp -= SIZEOF_VOID_P;
828  *((void **)es->sp) = (void *) ra;
829  if (calleecode->stackframesize)
830  es->sp -= (SIZE_OF_STACKSLOT - SIZEOF_VOID_P);
831 #endif /* STACKFRAME_RA_BETWEEN_FRAMES */
832 
833  es->ra = (u1*) (ptrint) ra;
834 
835  /* build the stackframe */
836 
837  LOG("building stackframe of " << calleecode->stackframesize << " words at "
838  << es->sp << nl);
839 
840  sp = (stackslot_t *) es->sp;
841  basesp = sp;
842 
843  /* on aarch64, we need to quad-word align the stackframesize */
844 #if defined(__AARCH64__)
845  sp -= (calleecode->stackframesize + calleecode->stackframesize % 2);
846 #else
847  sp -= calleecode->stackframesize;
848 #endif
849  es->sp = (u1*) sp;
850 
851  /* in debug mode, invalidate stack frame first */
852 
853  /* XXX may not invalidate linkage area used by native code! */
854 
855 #if !defined(NDEBUG) && 0
856  for (i=0; i< (basesp - sp) && i < 1; ++i) {
857  sp[i] = 0xdeaddeadU;
858  }
859 #endif
860 
861 #if defined(__I386__)
862  /* Stackslot 0 may contain the object instance for vftbl patching.
863  Destroy it, so there's no undefined value used. */
864  // XXX Is this also true for x86_64?
865  if ((basesp - sp) > 0) {
866  sp[0] = 0;
867  }
868 #endif
869 
870  /* save the return address register */
871 
872 #if STACKFRAME_RA_TOP_OF_FRAME
873 # if STACKFRAME_LEAFMETHODS_RA_REGISTER
874  if (!code_is_leafmethod(calleecode))
875 # endif
876  *--basesp = (ptrint) ra;
877 #endif /* STACKFRAME_RA_TOP_OF_FRAME */
878 
879 #if STACKFRAME_RA_LINKAGE_AREA
880 # if STACKFRAME_LEAFMETHODS_RA_REGISTER
881  if (!code_is_leafmethod(calleecode))
882 # endif
883  *((uint8_t**) ((intptr_t) basesp + LA_LR_OFFSET)) = ra;
884 #endif /* STACKFRAME_RA_LINKAGE_AREA */
885 
886 #if defined(__AARCH64__) || defined(__X86_64__)
887  if (code_is_using_frameptr(calleecode)) {
888 # if defined(__X86_64__)
889  *((uintptr_t*) --basesp) = es->intregs[RBP];
890  LOG2("push rbp onto stack " << (uintptr_t*) es->intregs[RBP] << nl);
891 # elif defined(__AARCH64__)
892  *((uintptr_t*) --basesp) = es->intregs[REG_FP];
893  LOG2("push REG_FP onto stack " << (uintptr_t*) es->intregs[REG_FP] << nl);
894 # endif
895  }
896 #endif
897 
898 #if defined(__AARCH64__)
899  // If the framesize was padded for 16-byte alignment, add the padding
900  if (calleecode->stackframesize % 2) {
901  basesp--;
902  }
903 #endif
904 
905  /* save int registers */
906  reg = INT_REG_CNT;
907  for (i=0; i<calleecode->savedintcount; ++i) {
908  while (nregdescint[--reg] != REG_SAV)
909  ;
910  basesp -= 1;
911  *((uintptr_t*) basesp) = es->intregs[reg];
912 
913  /* XXX may not clobber saved regs used by native code! */
914 #if !defined(NDEBUG) && 0
915  es->intregs[reg] = (ptrint) 0x44dead4444dead44ULL;
916 #endif
917 
918  LOG2("push " << abi_registers_integer_name[reg] << " onto stack" << nl);
919  }
920 
921  /* save flt registers */
922 
923  /* XXX align? */
924  reg = FLT_REG_CNT;
925  for (i=0; i<calleecode->savedfltcount; ++i) {
926  while (nregdescfloat[--reg] != REG_SAV)
927  ;
928  basesp -= STACK_SLOTS_PER_FLOAT;
929  *((double*) basesp) = es->fltregs[reg];
930 
931  /* XXX may not clobber saved regs used by native code! */
932 #if !defined(NDEBUG) && 0
933  *(u8*)&(es->fltregs[reg]) = 0x44dead4444dead44ULL;
934 #endif
935  }
936 
937  md_dcacheflush(es->sp, (calleecode->stackframesize + (calleecode->stackframesize % 2)) * SIZE_OF_STACKSLOT);
938 }
939 
940 
941 /* replace_pop_activation_record ***********************************************
942 
943  Peel a stack frame from the execution state.
944 
945  *** This function imitates the effects of the method epilog ***
946  *** and returning from the method call. ***
947 
948  IN:
949  es...............execution state
950  frame............source frame, receives synchronization slots
951 
952  OUT:
953  *es..............the execution state after popping the stack frame
954 
955 *******************************************************************************/
956 
958  sourceframe_t *frame)
959 {
960  u1 *ra;
961  s4 i;
962  s4 count;
963  codeinfo *code;
964  stackslot_t *sp;
965 
966  assert(es->code);
967  assert(frame);
968 
969  LOG("pop activation record for method [" << frame->method->name << "]" << nl);
970 
971  /* calculate the base of the stack frame */
972 
973  sp = (stackslot_t *) es->sp;
974  assert(frame->syncslotcount == 0);
975  assert(frame->syncslots == NULL);
976  count = code_get_sync_slot_count(es->code);
977  frame->syncslotcount = count;
978  frame->syncslots = (replace_val_t*) DumpMemory::allocate(sizeof(replace_val_t) * count);
979  for (i=0; i<count; ++i) {
980  frame->syncslots[i].p = *((intptr_t*) (sp + es->code->memuse + i)); /* XXX md_ function */
981  }
982 
983  /* pop the stackframe */
984 
986 
987  /* Subtract one from the PC so we do not hit the replacement point */
988  /* of the instruction following the call, if there is one. */
989 
990 #if defined(__AARCH64__)
991  if (((u8)es->pc) % 4) {
992  es->pc--;
993  }
994 #else
995  es->pc--;
996 #endif
997 
998  ra = es->pc;
999 
1000  /* find the new codeinfo */
1001 
1002  void* pv = md_codegen_get_pv_from_pc(ra);
1003 
1004  code = code_get_codeinfo_for_pv(pv);
1005 
1006  es->pv = (uint8_t*) pv;
1007  es->code = code;
1008 }
1009 
1010 
1011 /* replace_patch_method_pointer ************************************************
1012 
1013  Patch a method pointer (may be in code, data segment, vftbl, or interface
1014  table).
1015 
1016  IN:
1017  mpp..............address of the method pointer to patch
1018  entrypoint.......the new entrypoint of the method
1019  kind.............kind of call to patch, used only for debugging
1020 
1021 *******************************************************************************/
1022 
1024  methodptr entrypoint,
1025  const char *kind)
1026 {
1027 #if !defined(NDEBUG)
1028  codeinfo *oldcode = code_get_codeinfo_for_pv(*mpp);
1029  codeinfo *newcode = code_get_codeinfo_for_pv(entrypoint);
1030 
1031  assert(oldcode->m == newcode->m);
1032 #endif
1033 
1034  LOG("patch method pointer from " << (void *) *mpp << " to "
1035  << (void *) entrypoint << nl);
1036 
1037  /* write the new entrypoint */
1038 
1039  *mpp = (methodptr) entrypoint;
1040 
1041  md_cacheflush(mpp, SIZEOF_VOID_P);
1042 }
1043 
1044 
1045 /* replace_patch_class *********************************************************
1046 
1047  Patch a method in the given class.
1048 
1049  IN:
1050  vftbl............vftbl of the class
1051  m................the method to patch
1052  oldentrypoint....the old entrypoint to replace
1053  entrypoint.......the new entrypoint
1054 
1055 *******************************************************************************/
1056 
1058  methodinfo *m,
1059  u1 *oldentrypoint,
1060  u1 *entrypoint)
1061 {
1062  s4 i;
1063  methodptr *mpp;
1064  methodptr *mppend;
1065 
1066  LOG("patch class " << vftbl->clazz->name << nl);
1067 
1068  /* patch the vftbl of the class */
1069 
1071  entrypoint,
1072  "virtual ");
1073 
1074  /* patch the interface tables */
1075 
1076  assert(oldentrypoint);
1077 
1078  for (i=0; i < vftbl->interfacetablelength; ++i) {
1079  mpp = vftbl->interfacetable[-i];
1080  mppend = mpp + vftbl->interfacevftbllength[i];
1081  for (; mpp != mppend; ++mpp)
1082  if (*mpp == oldentrypoint) {
1083  replace_patch_method_pointer(mpp, entrypoint, "interface");
1084  }
1085  }
1086 }
1087 
1088 
1089 /* replace_patch_class_hierarchy ***********************************************
1090 
1091  Patch a method in all loaded classes.
1092 
1093  IN:
1094  m................the method to patch
1095  oldentrypoint....the old entrypoint to replace
1096  entrypoint.......the new entrypoint
1097 
1098 *******************************************************************************/
1099 
1104 };
1105 
1107 {
1108  vftbl_t *vftbl = c->vftbl;
1109 
1110  if (vftbl != NULL
1111  && vftbl->vftbllength > pd->m->vftblindex
1112  // TODO understand
1113  //&& (void*) vftbl->table[pd->m->vftblindex] != (void*) (uintptr_t) &asm_abstractmethoderror
1114  && code_get_methodinfo_for_pv(vftbl->table[pd->m->vftblindex]) == pd->m)
1115  {
1116  replace_patch_class(c->vftbl, pd->m, pd->oldentrypoint, pd->entrypoint);
1117  }
1118 }
1119 
1121  u1 *oldentrypoint,
1122  u1 *entrypoint)
1123 {
1124  struct replace_patch_data_t pd;
1125 
1126  pd.m = m;
1128  pd.entrypoint = entrypoint;
1129 
1130  LOG("patching class hierarchy: " << *m << nl);
1131 
1134  (void*) &pd);
1135 }
1136 
1137 
1138 /* replace_patch_future_calls **************************************************
1139 
1140  Analyse a call site and depending on the kind of call patch the call, the
1141  virtual function table, or the interface table.
1142 
1143  IN:
1144  ra...............return address pointing after the call site
1145  callerframe......source frame of the caller
1146  calleeframe......source frame of the callee, must have been mapped
1147 
1148 *******************************************************************************/
1149 
1151  sourceframe_t *callerframe,
1152  sourceframe_t *calleeframe)
1153 {
1154  u1 *patchpos;
1157 #if !defined(__I386__)
1158  bool atentry;
1159 #endif
1160  void *pv;
1161  codeinfo *calleecode;
1162  methodinfo *calleem;
1163  java_object_t *obj;
1164  vftbl_t *vftbl;
1165 
1166  assert(ra);
1167  assert(callerframe->down == calleeframe);
1168 
1169  /* get the new codeinfo and the method that shall be entered */
1170 
1171  calleecode = calleeframe->tocode;
1172  assert(calleecode);
1173 
1174  calleem = calleeframe->method;
1175  assert(calleem == calleecode->m);
1176 
1177  entrypoint = (methodptr) calleecode->entrypoint;
1178 
1179  /* check if we are at an method entry rplpoint at the innermost frame */
1180 
1181 #if !defined(__I386__)
1182  atentry = (calleeframe->down == NULL)
1183  && !(calleem->flags & ACC_STATIC)
1184  && (calleeframe->fromrp->id == 0); /* XXX */
1185 #endif
1186 
1187  /* get the position to patch, in case it was a statically bound call */
1188 
1189  pv = callerframe->fromcode->entrypoint;
1190  if (callerframe->fromcode->optlevel > 0) {
1191  patchpos = (u1*) callerframe->fromrp->patch_target_addr;
1192  } else {
1193  patchpos = (u1*) md_jit_method_patch_address(pv, ra, NULL);
1194  }
1195 
1196  if (patchpos == NULL) {
1197  /* the call was dispatched dynamically */
1198 
1199  /* we can only patch such calls if we are at the entry point */
1200 
1201 #if !defined(__I386__)
1202  /* On i386 we always know the instance argument. */
1203  if (!atentry)
1204  return;
1205 #endif
1206 
1207  assert((calleem->flags & ACC_STATIC) == 0);
1208 
1209  oldentrypoint = calleeframe->fromcode->entrypoint;
1210 
1211  /* we need to know the instance */
1212 
1213  if (!calleeframe->instance.a) {
1214  LOG(BoldYellow << "WARNING: " << reset_color << "object instance unknown!" << nl);
1215  replace_patch_class_hierarchy(calleem, oldentrypoint, entrypoint);
1216  return;
1217  }
1218 
1219  /* get the vftbl */
1220 
1221  obj = calleeframe->instance.a;
1222  vftbl = obj->vftbl;
1223 
1224  assert(vftbl->clazz->vftbl == vftbl);
1225 
1226  LOG("class: " << vftbl->clazz);
1227 
1228  replace_patch_class(vftbl, calleem, oldentrypoint, entrypoint);
1229  } else {
1230  /* the call was statically bound */
1231 
1232 #if defined(__I386__) || defined(__X86_64__)
1233  /* It happens that there is a patcher trap. (pm) */
1234  if (*(u2 *)(patchpos - 1) == 0x0b0f) {
1235  LOG2("enountered patcher trap, not patching static call");
1236  return;
1237  }
1238 #endif
1239 
1240 #if defined(__AARCH64__)
1241  /* Iit happens that there is a patcher trap. */
1242  if ((*(u4 *)(patchpos - 4) & (0xE7000700)) == 0xE7000700) {
1243  LOG2(BoldYellow << "Encountered trap, not patching static call" << reset_color << nl);
1244  assert(false);
1245  return;
1246  }
1247 #endif
1248  LOG2("patch static call of [" << *calleem << "] in ["
1249  << *callerframe->method << "]" << nl);
1250 
1251  replace_patch_method_pointer((methodptr *) patchpos, entrypoint, "static ");
1252  }
1253 }
1254 
1255 
1256 /* replace_push_activation_record **********************************************
1257 
1258  Push a stack frame onto the execution state.
1259 
1260  *** This function imitates the effects of a call and the ***
1261  *** method prolog of the callee. ***
1262 
1263  IN:
1264  es...............execution state
1265  rpcall...........the replacement point at the call site
1266  callerframe......source frame of the caller, or NULL for creating the
1267  first frame
1268  calleeframe......source frame of the callee, must have been mapped
1269 
1270  OUT:
1271  *es..............the execution state after pushing the stack frame
1272 
1273 *******************************************************************************/
1274 
1276  rplpoint *rpcall,
1277  sourceframe_t *callerframe,
1278  sourceframe_t *calleeframe)
1279 {
1280  s4 count;
1281  stackslot_t *sp;
1282  u1 *ra;
1283  codeinfo *calleecode;
1284 
1285  assert(es);
1286  assert(!rpcall || callerframe);
1287 #if 0
1288  assert(!rpcall || rpcall->type == rplpoint::TYPE_CALL);
1289 #endif
1290  assert(!rpcall || rpcall == callerframe->torp);
1291  assert(calleeframe);
1292  assert(!callerframe || calleeframe == callerframe->down);
1293 
1294  LOG("push activation record for " << *calleeframe->method << nl);
1295 
1296  /* the compilation unit we are entering */
1297 
1298  calleecode = calleeframe->tocode;
1299  assert(calleecode);
1300 
1301  /* calculate the return address */
1302 
1303  // XXX why is ra == es->pc for native frames but not for
1304  // non-native ones?
1305  if (rpcall) {
1306  ra = rpcall->pc + rpcall->callsize;
1307  } else {
1308 #if defined(__X86_64__)
1309  // XXX we only need to do this if we decrement the pc in
1310  // `replace_pop_activation_record`
1311  ra = es->pc + 1;
1312 #else
1313  ra = es->pc;
1314 #endif
1315  }
1316 
1317  /* push the stackframe */
1318 
1319  md_push_stackframe(es, calleecode, ra);
1320 
1321  /* we move into a new code unit, set code, PC, PV */
1322 
1323  es->code = calleecode;
1324 #if 0
1325  es->pc = calleecode->entrypoint; /* XXX not needed? */
1326 #endif
1327  es->pv = calleecode->entrypoint;
1328 
1329  /* write slots used for synchronization */
1330 
1331  sp = (stackslot_t *) es->sp;
1332  count = code_get_sync_slot_count(calleecode);
1333  assert(count == calleeframe->syncslotcount);
1334  for (s4 slot_index = 0; slot_index < count; ++slot_index) {
1335  *((intptr_t*) (sp + calleecode->memuse + slot_index)) = calleeframe->syncslots[slot_index].p;
1336  }
1337 
1338  /* redirect future invocations */
1339 
1340  if (callerframe && rpcall) {
1341 #if !defined(REPLACE_PATCH_ALL)
1342  if (rpcall == callerframe->fromrp)
1343 #endif
1344  replace_patch_future_calls(ra, callerframe, calleeframe);
1345  }
1346 }
1347 
1349  sourceframe_t *frame)
1350 {
1351  assert(code);
1352  assert(frame);
1353 
1354  LOG("searching for call site rp for source id " << frame->id
1355  << " in method [" << *frame->method << "]" << nl);
1356 
1357  rplpoint *rp = code->rplpoints;
1358 
1359  for (s4 i = 0; i < code->rplpointcount; i++, rp++) {
1360  if (rp->id == frame->id
1361  && rp->method == frame->method
1362  && REPLACE_IS_CALL_SITE(rp)) {
1363  return rp;
1364  }
1365  }
1366 
1367  ABORT_MSG("no matching replacement point found", "");
1368  return NULL; /* NOT REACHED */
1369 }
1370 
1371 /* replace_find_replacement_point **********************************************
1372 
1373  Find the replacement point in the given code corresponding to the
1374  position given in the source frame.
1375 
1376  IN:
1377  code.............the codeinfo in which to search the rplpoint
1378  frame............the source frame defining the position to look for
1379  parent...........parent replacement point to match
1380 
1381  RETURN VALUE:
1382  the replacement point
1383 
1384 *******************************************************************************/
1385 
1387  sourceframe_t *frame)
1388 {
1389  rplpoint *rp;
1390  s4 stacki;
1391  rplalloc *ra;
1392 
1393  assert(code);
1394  assert(frame);
1395 
1396  LOG("searching for rp for source id " << frame->id
1397  << " in method [" << *frame->method << "]" << nl);
1398 
1399  rp = code->rplpoints;
1400  for (s4 i = 0; i < code->rplpointcount; i++, rp++) {
1401  if (rp->id == frame->id && rp->method == frame->method) {
1402  /* check if returnAddresses match */
1403  /* XXX optimize: only do this if JSRs in method */
1404  ra = rp->regalloc;
1405  stacki = 0;
1406  for (s4 j = rp->regalloccount; j--; ++ra) {
1407  if (ra->type == TYPE_RET) {
1408  if (ra->index == RPLALLOC_STACK) {
1409  assert(stacki < frame->javastackdepth);
1410  if (frame->javastack[stacki].i != ra->regoff)
1411  continue;
1412  stacki++;
1413  } else {
1414  assert(ra->index >= 0 && ra->index < frame->javalocalcount);
1415  if (frame->javalocals[ra->index].i != ra->regoff)
1416  continue;
1417  }
1418  }
1419  }
1420 
1421  /* found */
1422  return rp;
1423  }
1424  }
1425 
1426  ABORT_MSG("no matching replacement point found", "");
1427  return NULL; /* NOT REACHED */
1428 }
1429 
1430 /* replace_find_replacement_point_at_or_before_pc ******************************
1431 
1432  Find the nearest replacement point at or before the given PC.
1433 
1434  IN:
1435  code.............compilation unit the PC is in
1436  pc...............the machine code PC
1437 
1438  RETURN VALUE:
1439  the replacement point found, or NULL if no replacement point was found
1440 
1441 *******************************************************************************/
1442 
1443 
1445  codeinfo *code,
1446  u1 *pc,
1447  unsigned int desired_flags) {
1448  LOG("searching for nearest rp before pc " << pc
1449  << " in method [" << *code->m << "]" << nl);
1450 
1451  rplpoint *nearest = NULL;
1452  rplpoint *rp = code->rplpoints;
1453 
1454  for (s4 i = 0; i < code->rplpointcount; ++i, ++rp) {
1455  if (rp->pc <= pc && (rp->flags & desired_flags)) {
1456  if (nearest == NULL || nearest->pc < rp->pc) {
1457  nearest = rp;
1458  }
1459  }
1460  }
1461 
1462  return nearest;
1463 }
1464 
1465 /* replace_find_replacement_point_for_pc ***************************************
1466 
1467  Find the nearest replacement point whose PC is between (rp->pc) and
1468  (rp->pc+rp->callsize).
1469 
1470  IN:
1471  code.............compilation unit the PC is in
1472  pc...............the machine code PC
1473 
1474  RETURN VALUE:
1475  the replacement point found, or
1476  NULL if no replacement point was found
1477 
1478 *******************************************************************************/
1479 
1481 {
1482  rplpoint *rp;
1483  s4 i;
1484 
1485  LOG("searching for rp at pc " << pc << " in method [" << *code->m << "]"
1486  << nl);
1487 
1488  rp = code->rplpoints;
1489  for (i=0; i<code->rplpointcount; ++i, ++rp) {
1490  if (rp->pc <= pc && rp->pc + rp->callsize >= pc) {
1491  return rp;
1492  }
1493  }
1494 
1495  return NULL;
1496 }
1497 
1498 /* replace_pop_native_frame ****************************************************
1499 
1500  Unroll a native frame in the execution state and create a source frame
1501  for it.
1502 
1503  IN:
1504  es...............current execution state
1505  ss...............the current source state
1506  sfi..............stackframeinfo for the native frame
1507 
1508  OUT:
1509  es...............execution state after unrolling the native frame
1510  ss...............gets the added native source frame
1511 
1512 *******************************************************************************/
1513 
1515  sourcestate_t *ss,
1516  stackframeinfo_t *sfi)
1517 {
1518  sourceframe_t *frame;
1519  codeinfo *code;
1520  s4 i,j;
1521 
1522  assert(sfi);
1523 
1524  frame = replace_new_sourceframe(ss);
1525 
1526  frame->sfi = sfi;
1527 
1528  /* remember pc and size of native frame */
1529 
1530  frame->nativepc = es->pc;
1531  frame->nativeframesize = (es->sp != 0) ? (((uintptr_t) sfi->sp) - ((uintptr_t) es->sp)) : 0;
1532  assert(frame->nativeframesize >= 0);
1533 
1534  /* remember values of saved registers */
1535 
1536  j = 0;
1537  for (i=0; i<INT_REG_CNT; ++i) {
1538  if (nregdescint[i] == REG_SAV)
1539  frame->nativesavint[j++] = es->intregs[i];
1540  }
1541 
1542  j = 0;
1543  for (i=0; i<FLT_REG_CNT; ++i) {
1544  if (nregdescfloat[i] == REG_SAV)
1545  frame->nativesavflt[j++] = es->fltregs[i];
1546  }
1547 
1548  /* restore saved registers */
1549 
1550  /* XXX we don't have them, yet, in the sfi, so clear them */
1551 
1552  for (i=0; i<INT_REG_CNT; ++i) {
1553  if (nregdescint[i] == REG_SAV)
1554  es->intregs[i] = 0;
1555  }
1556 
1557  /* XXX we don't have float registers in the sfi, so clear them */
1558 
1559  for (i=0; i<FLT_REG_CNT; ++i) {
1560  if (nregdescfloat[i] == REG_SAV)
1561  es->fltregs[i] = 0.0;
1562  }
1563 
1564  /* restore codeinfo of the native stub */
1565 
1566  code = code_get_codeinfo_for_pv(sfi->pv);
1567 
1568  /* restore sp, pv, pc and codeinfo of the parent method */
1569 
1570  es->sp = (uint8_t*) (((uintptr_t) sfi->sp) + md_stacktrace_get_framesize(code));
1571 #if STACKFRAME_RA_BETWEEN_FRAMES
1572  es->sp += SIZEOF_VOID_P; /* skip return address */
1573 #endif
1574  es->pv = (uint8_t*) md_codegen_get_pv_from_pc(sfi->ra);
1575  es->pc = (uint8_t*) (((uintptr_t) ((sfi->xpc) ? sfi->xpc : sfi->ra)) - 1);
1576  es->code = code_get_codeinfo_for_pv(es->pv);
1577 }
1578 
1579 
1580 /* replace_push_native_frame ***************************************************
1581 
1582  Rebuild a native frame onto the execution state and remove its source frame.
1583 
1584  Note: The native frame is "rebuild" by setting fields like PC and stack
1585  pointer in the execution state accordingly. Values in the
1586  stackframeinfo may be modified, but the actual stack frame of the
1587  native code is not touched.
1588 
1589  IN:
1590  es...............current execution state
1591  ss...............the current source state
1592 
1593  OUT:
1594  es...............execution state after re-rolling the native frame
1595  ss...............the native source frame is removed
1596 
1597 *******************************************************************************/
1598 
1599 static void replace_push_native_frame(executionstate_t *es, sourcestate_t *ss)
1600 {
1601  sourceframe_t *frame;
1602  s4 i,j;
1603 
1604  assert(es);
1605  assert(ss);
1606 
1607  LOG("push native frame" << nl);
1608 
1609  /* remove the frame from the source state */
1610 
1611  frame = ss->frames;
1612  assert(frame);
1613  assert(REPLACE_IS_NATIVE_FRAME(frame));
1614 
1615  ss->frames = frame->down;
1616 
1617  /* skip sp for the native stub */
1618 
1619  es->sp -= md_stacktrace_get_framesize(frame->sfi->code);
1620 #if STACKFRAME_RA_BETWEEN_FRAMES
1621  es->sp -= SIZEOF_VOID_P; /* skip return address */
1622 #endif
1623 
1624  /* assert that the native frame has not moved */
1625 
1626  assert(es->sp == frame->sfi->sp);
1627 
1628  /* restore saved registers */
1629 
1630  j = 0;
1631  for (i=0; i<INT_REG_CNT; ++i) {
1632  if (nregdescint[i] == REG_SAV)
1633  es->intregs[i] = frame->nativesavint[j++];
1634  }
1635 
1636  j = 0;
1637  for (i=0; i<FLT_REG_CNT; ++i) {
1638  if (nregdescfloat[i] == REG_SAV)
1639  es->fltregs[i] = frame->nativesavflt[j++];
1640  }
1641 
1642  /* skip the native frame on the machine stack */
1643 
1644  es->sp -= frame->nativeframesize;
1645 
1646  /* set the pc the next frame must return to */
1647 
1648  es->pc = frame->nativepc;
1649 }
1650 
1651 /* replace_recover_source_frame ************************************************
1652 
1653  Recovers a source frame from the given replacement point and execution
1654  state and pushes is to the front of the source state.
1655 
1656  IN:
1657  rp...............replacement point that has been reached, if any
1658  es...............execution state at the replacement point rp
1659  es...............the source state
1660 
1661  OUT:
1662  es...............the modified execution state
1663  ss...............the new source state
1664 
1665  RETURN VALUE:
1666  the replacement point at the call site within the caller frame or NULL
1667  if it was called from a native method
1668 
1669 *******************************************************************************/
1670 
1671 rplpoint *replace_recover_source_frame(rplpoint *rp,
1672  executionstate_t *es,
1673  sourcestate_t *ss) {
1674  /* read the values for this source frame from the execution state */
1675 
1676  replace_read_executionstate(rp, es, ss);
1677 
1678  /* unroll to the next (outer) frame */
1679 
1680  rplpoint *next_rp = NULL;
1681  if (rp->parent) {
1682  /* this frame is in inlined code */
1683 
1684  LOG("INLINED!" << nl);
1685 
1686  next_rp = rp->parent;
1687 
1688 #if 0
1689  assert(next_rp->type == rplpoint::TYPE_INLINE);
1690 #endif
1691  } else {
1692  /* this frame had been called at machine-level. pop it. */
1693 
1694  replace_pop_activation_record(es, ss->frames);
1695  if (es->code == NULL) {
1696  LOG("REACHED NATIVE CODE" << nl);
1697  next_rp = NULL;
1698  } else {
1699  /* find the replacement point at the call site */
1700 
1701  next_rp = replace_find_replacement_point_for_pc(es->code, es->pc);
1702 
1703  assert(next_rp);
1704  assert(REPLACE_IS_CALL_SITE(next_rp));
1705  }
1706  }
1707 
1708  return next_rp;
1709 }
1710 
1711 
1712 /* replace_recover_source_state ************************************************
1713 
1714  Recover the source state from the given replacement point and execution
1715  state. The bottom-most source frame of the returned source state represents
1716  the method that triggered on-stack replacement. Additionally, the source
1717  frame of the caller is recovered (in case it's not native) to be able
1718  to patch the call-site if necessary, i.e., the source state will contain at
1719  most two source frames.
1720 
1721  IN:
1722  rp...............replacement point that has been reached, if any
1723  es...............execution state at the replacement point rp
1724 
1725  OUT:
1726  es...............the modified execution state
1727 
1728  RETURN VALUE:
1729  the source state
1730 
1731 *******************************************************************************/
1732 
1733 sourcestate_t *replace_recover_source_state(rplpoint *rp, executionstate_t *es)
1734 {
1735  sourcestate_t *ss = (sourcestate_t*) DumpMemory::allocate(sizeof(sourcestate_t));
1736  ss->frames = NULL;
1737 
1738  /* recover the source frame of the method that triggered on-stack replacement */
1739 
1740  rplpoint *rpcall = replace_recover_source_frame(rp, es, ss);
1741 
1742  /* recover the frame of the calling method (if it's not native) so that the
1743  call can be patched if necessary */
1744 
1745  if (rpcall != NULL) {
1746  replace_recover_source_frame(rpcall, es, ss);
1747  }
1748 
1749  return ss;
1750 }
1751 
1752 
1753 /* replace_build_execution_state ***********************************************
1754 
1755  Build an execution state for the given (mapped) source state.
1756 
1757  !!! CAUTION: This function rewrites the machine stack !!!
1758 
1759  THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA!
1760 
1761  IN:
1762  ss...............the source state. Must have been mapped by
1763  replace_map_source_state before.
1764  es...............the base execution state on which to build
1765 
1766  OUT:
1767  *es..............the new execution state
1768 
1769 *******************************************************************************/
1770 
1771 static void replace_build_execution_state(sourcestate_t *ss,
1772  executionstate_t *es)
1773 {
1774  rplpoint *rp;
1775  sourceframe_t *prevframe;
1776  rplpoint *parent;
1777 
1778  parent = NULL;
1779  prevframe = NULL;
1780  rp = NULL;
1781 
1782  while (ss->frames) {
1783  if (REPLACE_IS_NATIVE_FRAME(ss->frames)) {
1784  prevframe = ss->frames;
1785  replace_push_native_frame(es, ss);
1786  parent = NULL;
1787  rp = NULL;
1788  } else {
1789  if (parent == NULL) {
1790  /* create a machine-level stack frame */
1791 
1792  replace_push_activation_record(es, rp, prevframe, ss->frames);
1793  }
1794 
1795  rp = ss->frames->torp;
1796  assert(rp);
1797 
1798  es->code = ss->frames->tocode;
1799  prevframe = ss->frames;
1800 
1801  replace_write_executionstate(rp, es, ss);
1802 
1803  if (REPLACE_IS_CALL_SITE(rp)) {
1804  parent = NULL;
1805  } else {
1806  /* inlining */
1807  parent = rp;
1808  }
1809  }
1810  }
1811 }
1812 
1813 
1814 /* replace_on_stack ************************************************************
1815 
1816  Performs on-stack replacement.
1817 
1818  THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA!
1819 
1820  IN:
1821  code.............the code of the method to be replaced.
1822  rp...............replacement point that has been reached
1823  es...............current execution state
1824 
1825  OUT:
1826  es...............the execution state after replacement finished.
1827 
1828 *******************************************************************************/
1829 
1830 static void replace_optimize(codeinfo *code, rplpoint *rp, executionstate_t *es)
1831 {
1832  LOG(BoldCyan << "perform replacement" << reset_color << " at " << rp << nl);
1833 
1834  DumpMemoryArea dma;
1835  es->code = code;
1836  sourcestate_t *ss = replace_recover_source_state(rp, es);
1837 
1838  sourceframe_t *topframe;
1839  sourceframe_t *callerframe;
1840 
1841  if (ss->frames->down) {
1842  callerframe = ss->frames;
1843  topframe = ss->frames->down;
1844  } else {
1845  callerframe = NULL;
1846  topframe = ss->frames;
1847  }
1848 
1849  /* map the topmost frame to a replacement point in the optimized code */
1850 
1851  jit_request_optimization(topframe->method);
1852  topframe->tocode = jit_get_current_code(topframe->method);
1853  topframe->torp = replace_find_replacement_point(topframe->tocode, topframe);
1854 
1855  /* identity map the calling frame */
1856 
1857  if (callerframe) {
1858  callerframe->tocode = callerframe->fromcode;
1859  callerframe->torp = callerframe->fromrp;
1860  }
1861 
1862  /* rebuild execution state */
1863 
1865 
1866  LOG(BoldGreen << "finished replacement: " << reset_color << "jump into optimized code" << nl);
1867 }
1868 
1869 
1870 /* replace_handle_countdown_trap ***********************************************
1871 
1872  This function is called by the signal handler. It recompiles the method that
1873  triggered the countdown trap and initiates on-stack replacement.
1874 
1875  THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA!
1876 
1877  IN:
1878  pc...............the program counter that triggered the countdown trap.
1879  es...............the execution state (machine state) at the countdown
1880  trap.
1881 
1882  OUT:
1883  es...............the execution state after replacement finished.
1884 
1885 *******************************************************************************/
1886 
1888 {
1889  LOG("handle countdown trap" << nl);
1890 
1891  /* search the codeinfo for the given PC */
1892 
1893  codeinfo *code = code_find_codeinfo_for_pc(pc);
1894  assert(code);
1895 
1896  /* search for a replacement point at the given PC */
1897 
1898  methodinfo *method = code->m;
1899  rplpoint *rp = replace_find_replacement_point_at_or_before_pc(code, pc, rplpoint::FLAG_COUNTDOWN);
1900 
1901  assert(rp);
1902  assert(rp->flags & rplpoint::FLAG_COUNTDOWN);
1903  assert(method->hitcountdown <= 0);
1904 
1905  /* perform on-stack replacement */
1906 
1907  replace_optimize(code, rp, es);
1908 }
1909 
1910 /* replace_handle_replacement_trap *********************************************
1911 
1912  This function is called by the signal handler. Initiates on-stack replacement
1913  if there is an active replacement trap at the given PC.
1914 
1915  THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA!
1916 
1917  IN:
1918  pc...............the program counter that triggered the replacement trap
1919  es...............the execution state (machine state) at the
1920  replacement trap.
1921 
1922  OUT:
1923  es...............the execution state after replacement finished.
1924 
1925  RETURNS:
1926  true.............if replacement was performed at the given pc.
1927  false............otherwise.
1928 
1929 *******************************************************************************/
1930 
1932 {
1933  /* search the codeinfo for the given PC */
1934 
1935  codeinfo *code = code_find_codeinfo_for_pc(pc);
1936  assert(code);
1937 
1938  /* search for a replacement point at the given PC */
1939 
1940  rplpoint *rp = replace_find_replacement_point_for_pc(code, pc);
1941 
1942  if (rp != NULL && (rp->flags & rplpoint::FLAG_ACTIVE)) {
1943 
1944  LOG("handle replacement trap" << nl);
1945 
1946  /* perform on-stack replacement */
1947 
1948  replace_optimize(code, rp, es);
1949 
1950  return true;
1951  }
1952 
1953  return false;
1954 }
1955 
1956 
1957 /* replace_handle_deoptimization_trap ******************************************
1958 
1959  This function is called by the signal handler. It deoptimizes the method that
1960  triggered the deopimization trap and initiates on-stack replacement.
1961 
1962  THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA!
1963 
1964  IN:
1965  pc...............the program counter that triggered the countdown trap.
1966  es...............the execution state (machine state) at the countdown
1967  trap.
1968 
1969  OUT:
1970  es...............the execution state after replacement finished.
1971 
1972 *******************************************************************************/
1973 
1975  LOG("handle deopimization trap" << nl);
1976 
1977  DumpMemoryArea dma;
1978 
1979  /* search the codeinfo for the given PC */
1980 
1981  codeinfo *code = code_find_codeinfo_for_pc(pc);
1982  es->code = code;
1983  assert(code);
1984 
1985  /* search for a replacement point at the given PC */
1986 
1987  methodinfo *method = code->m;
1988  rplpoint *rp = replace_find_replacement_point_at_or_before_pc(code, pc, rplpoint::FLAG_DEOPTIMIZE);
1989  assert(rp);
1990  assert(rp->flags & rplpoint::FLAG_DEOPTIMIZE);
1991 
1992  LOG(BoldCyan << "perform deoptimization at " << reset_color << rp << nl);
1993 
1994  sourcestate_t *ss = replace_recover_source_state(rp, es);
1995 
1996  sourceframe_t *topframe;
1997  sourceframe_t *callerframe;
1998 
1999  if (ss->frames->down) {
2000  callerframe = ss->frames;
2001  topframe = ss->frames->down;
2002  } else {
2003  callerframe = NULL;
2004  topframe = ss->frames;
2005  }
2006 
2007  /* map the topmost frame to a replacement point in the deoptimized code */
2008 
2009  if (topframe->method->deopttarget == NULL) {
2010  /* reinvoke baseline compiler and save depotimized code for
2011  future replacements */
2012 
2013  LOG("reinvoke baseline compiler" << nl);
2014  jit_recompile_for_deoptimization(topframe->method);
2015  topframe->method->deopttarget = topframe->method->code;
2016  assert(topframe->method->deopttarget);
2017  }
2018 
2019  topframe->tocode = topframe->method->deopttarget;
2020  topframe->torp = replace_find_replacement_point(topframe->tocode, topframe);
2021 
2022  /* identity map the calling frame */
2023 
2024  if (callerframe) {
2025  callerframe->tocode = callerframe->fromcode;
2026  callerframe->torp = callerframe->fromrp;
2027  }
2028 
2029  /* rebuild execution state */
2030 
2032 
2033  LOG(BoldGreen << "finished deoptimization: " << reset_color << "jump into code" << nl);
2034 }
2035 
2036 
2037 /******************************************************************************/
2038 /* NOTE: No important code below. */
2039 /******************************************************************************/
2040 
2041 #define TYPECHAR(t) (((t) >= 0 && (t) <= TYPE_RET) ? show_jit_type_letters[t] : '?')
2042 
2043 namespace cacao {
2044 
2045 OStream& operator<<(OStream &OS, const rplpoint *rp) {
2046  if (!rp) {
2047  return OS << "(rplpoint *) NULL";
2048  }
2049  return OS << *rp;
2050 }
2051 
2052 OStream& operator<<(OStream &OS, const rplpoint &rp) {
2053  OS << "[";
2054 
2055  OS << "id=" << rp.id << ", pc=" << rp.pc;
2056 
2057  OS << " flags=[";
2058  if (rp.flags & rplpoint::FLAG_ACTIVE) {
2059  OS << " ACTIVE ";
2060  }
2061  if (rp.flags & rplpoint::FLAG_TRAPPABLE) {
2062  OS << " TRAPPABLE ";
2063  }
2064  if (rp.flags & rplpoint::FLAG_COUNTDOWN) {
2065  OS << " COUNTDOWN ";
2066  }
2067  if (rp.flags & rplpoint::FLAG_DEOPTIMIZE) {
2068  OS << " DEOPTIMIZE ";
2069  }
2070  OS << "]";
2071 
2072  OS << ", parent=" << rp.parent << ", ";
2073  OS << "allocations=[";
2074 
2075  for (int j=0; j < rp.regalloccount; ++j) {
2076  if (j > 0) {
2077  OS << ", ";
2078  }
2079  OS << rp.regalloc[j];
2080  }
2081 
2082  OS << "], ";
2083  OS << "method=[" << *rp.method << "], ";
2084  OS << "callsize=" << rp.callsize;
2085 
2086  OS << "]";
2087 
2088  return OS;
2089 }
2090 
2091 OStream& operator<<(OStream &OS, const rplalloc *ra) {
2092  if (!ra) {
2093  return OS << "(rplalloc *) NULL";
2094  }
2095  return OS << *ra;
2096 }
2097 
2098 OStream& operator<<(OStream &OS, const rplalloc &ra) {
2099  OS << "[";
2100 
2101  switch (ra.index) {
2102  case RPLALLOC_STACK: OS << "S"; break;
2103  case RPLALLOC_PARAM: OS << "P"; break;
2104  case RPLALLOC_SYNC : OS << "Y"; break;
2105  default: OS << ra.index;
2106  }
2107 
2108  OS << ":" << TYPECHAR(ra.type) << ", ";
2109 
2110  if (ra.type == TYPE_RET) {
2111  OS << "ret(L" << ra.regoff << ")";
2112  } else if (ra.inmemory) {
2113  OS << "M" << ra.regoff;
2114  } else if (IS_FLT_DBL_TYPE(ra.type)) {
2115  OS << "F" << ra.regoff;
2116  } else {
2117  /* integer register */
2118 
2119 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
2120  if (IS_2_WORD_TYPE(ra.type)) {
2121 # if defined(ENABLE_JIT)
2122  OS << abi_registers_integer_name[GET_LOW_REG(ra.regoff)];
2123  OS << "/";
2124  OS << abi_registers_integer_name[GET_HIGH_REG(ra.regoff)];
2125 # else /* defined(ENABLE_JIT) */
2126  OS << GET_LOW_REG(ra.regoff) << "/" << GET_HIGH_REG(ra.regoff);
2127 # endif /* defined(ENABLE_JIT) */
2128  } else {
2129 #endif /* defined(SUPPORT_COMBINE_INTEGER_REGISTERS) */
2130 
2131  OS << abi_registers_integer_name[ra.regoff];
2132 
2133 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
2134  }
2135 #endif /* defined(SUPPORT_COMBINE_INTEGER_REGISTERS) */
2136  }
2137 
2138  OS << "]";
2139 
2140  return OS;
2141 }
2142 
2143 OStream& operator<<(OStream &OS, const sourceframe_t *frame) {
2144  if (!frame) {
2145  return OS << "(sourceframe_t *) NULL";
2146  }
2147  return OS << *frame;
2148 }
2149 
2150 static OStream& replace_val_print(OStream &OS, s4 type, replace_val_t value) {
2151  java_object_t *obj;
2152  Utf8String u;
2153 
2154  OS << "type=";
2155  if (type < 0 || type > TYPE_RET) {
2156  OS << "<INVALID TYPE:" << type << ">";
2157  } else {
2158  OS << show_jit_type_names[type];
2159  }
2160 
2161  OS << ", raw=" << value.l << ", value=";
2162 
2163  if (type == TYPE_ADR && value.a != NULL) {
2164  obj = value.a;
2165  OS << obj->vftbl->clazz->name;
2166 
2167 #if 0
2168  if (obj->vftbl->clazz == class_java_lang_String) {
2169  printf(" \"");
2170  u = JavaString(obj).to_utf8();
2172  printf("\"");
2173  }
2174 #endif
2175  } else if (type == TYPE_INT) {
2176  OS << value.i;
2177  } else if (type == TYPE_LNG) {
2178  OS << value.l;
2179  } else if (type == TYPE_FLT) {
2180  OS << value.f;
2181  } else if (type == TYPE_DBL) {
2182  OS << value.d;
2183  }
2184 
2185  return OS;
2186 }
2187 
2188 static OStream& print_replace_vals(OStream &OS, replace_val_t *values, u1 *types, s4 count) {
2189  for (s4 i = 0; i < count; ++i) {
2190  s4 type = types[i];
2191  OS << "[";
2192  if (type == TYPE_VOID) {
2193  OS << "type=void";
2194  } else {
2195  replace_val_print(OS, type, values[i]);
2196  }
2197  OS << "]";
2198 
2199  if (i + 1 < count) {
2200  OS << ", ";
2201  }
2202  }
2203  return OS;
2204 }
2205 
2206 OStream& operator<<(OStream &OS, const sourceframe_t &frame) {
2207  OS << "[";
2208 
2209  if (REPLACE_IS_NATIVE_FRAME(&frame)) {
2210  OS << "NATIVE, ";
2211  OS << "nativepc=" << frame.nativepc << nl;
2212  OS << "framesize=" << frame.nativeframesize << nl;
2213 
2214  OS << "registers (integer)=[";
2215  for (s4 i = 0, j = 0; i < INT_REG_CNT; ++i) {
2216  if (nregdescint[i] == REG_SAV) {
2217  OS << abi_registers_integer_name[i] << ": " << (void*)frame.nativesavint[j++] << ", ";
2218  }
2219  }
2220  OS << "] ";
2221 
2222  OS << "registers (float)=[";
2223  for (s4 i = 0, j = 0; i < FLT_REG_CNT; ++i) {
2224  if (nregdescfloat[i] == REG_SAV) {
2225  OS << "F" << i << ": " << frame.nativesavflt[j++] << ", ";
2226  }
2227  }
2228  OS << "]";
2229  } else {
2230  OS << "method=" << frame.method->name << ", ";
2231  OS << "id=" << frame.id;
2232 
2233 #if 0
2234  if (frame->instance.a) {
2235  printf("\tinstance: ");
2236  java_value_print(TYPE_ADR, frame->instance);
2237  printf("\n");
2238  }
2239 #endif
2240 
2241  if (frame.javalocalcount) {
2242  OS << ", locals (" << frame.javalocalcount << ")=[";
2243  print_replace_vals(OS, frame.javalocals, frame.javalocaltype,
2244  frame.javalocalcount);
2245  OS << "]";
2246  }
2247 
2248  if (frame.javastackdepth) {
2249  OS << ", stack (depth=" << frame.javastackdepth << ")=[";
2250  print_replace_vals(OS, frame.javastack, frame.javastacktype,
2251  frame.javastackdepth);
2252  OS << "]";
2253  }
2254 
2255 #if 0
2256  if (frame->syncslotcount) {
2257  printf("\tsynchronization slots (%d):\n",frame->syncslotcount);
2258  for (i=0; i<frame->syncslotcount; ++i) {
2259  printf("\tslot[%2d] = %016llx\n",i,(unsigned long long) frame->syncslots[i].p);
2260  }
2261  printf("\n");
2262  }
2263 #endif
2264 
2265  if (frame.fromcode) {
2266  OS << ", from=" << (void*) frame.fromcode;
2267  }
2268  if (frame.tocode) {
2269  OS << ", to=" << (void*) frame.tocode;
2270  }
2271 
2272  }
2273 
2274  OS << "]";
2275 
2276  return OS;
2277 }
2278 
2279 OStream& operator<<(OStream &OS, const sourcestate_t *ss) {
2280  if (!ss) {
2281  return OS << "(sourcestate_t *) NULL" << nl;
2282  }
2283  return OS << *ss;
2284 }
2285 
2286 OStream& operator<<(OStream &OS, const sourcestate_t &ss) {
2287  OS << "sourcestate_t:" << nl;
2288  int i;
2289  sourceframe_t *frame;
2290  for (i = 0, frame = ss.frames; frame != NULL; frame = frame->down, ++i) {
2291  OS << "frame " << i << ": [" << frame << "]" << nl;
2292  }
2293  return OS;
2294 }
2295 
2296 
2297 } // end namespace cacao
2298 
2299 
2300 /*
2301  * These are local overrides for various environment variables in Emacs.
2302  * Please do not remove this and leave it at the end of the file, where
2303  * Emacs will automagically detect them.
2304  * ---------------------------------------------------------------------
2305  * Local variables:
2306  * mode: c++
2307  * indent-tabs-mode: t
2308  * c-basic-offset: 4
2309  * tab-width: 4
2310  * End:
2311  * vim:noexpandtab:sw=4:ts=4:
2312  */
methodptr * interfacetable[1]
Definition: vftbl.hpp:99
#define REG_SP
Definition: md-abi.hpp:55
static void replace_push_native_frame(executionstate_t *es, sourcestate_t *ss)
Definition: replace.cpp:1599
#define TOP_IS_ON_STACK
Definition: replace.cpp:76
#define GET_HIGH_REG(a)
#define pv
Definition: md-asm.hpp:65
#define REG_PV
Definition: md-abi.hpp:42
codeinfo * jit_get_current_code(methodinfo *m)
Definition: jit.cpp:992
sourcestate_t * replace_recover_source_state(rplpoint *rp, executionstate_t *es)
Definition: replace.cpp:1733
void replace_free_replacement_points(codeinfo *code)
Definition: replace.cpp:100
#define ra
Definition: md-asm.hpp:62
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 void replace_optimize(codeinfo *code, rplpoint *rp, executionstate_t *es)
Definition: replace.cpp:1830
rplpoint * replace_find_replacement_point(codeinfo *code, sourceframe_t *frame)
Definition: replace.cpp:1386
methodinfo * code_get_methodinfo_for_pv(void *pv)
Definition: code.cpp:150
void replace_activate_replacement_points(codeinfo *code, bool mappable)
Definition: replace.cpp:132
#define REG_SAV
Definition: jit.hpp:449
Utf8String to_utf8() const
Definition: string.cpp:437
#define SUPPORT_COMBINE_INTEGER_REGISTERS
Definition: arch.hpp:94
uint8_t savedfltcount
Definition: code.hpp:90
void replace_handle_deoptimization_trap(u1 *pc, executionstate_t *es)
Definition: replace.cpp:1974
int32_t stackframesize
Definition: code.hpp:87
static sourceframe_t * replace_new_sourceframe(sourcestate_t *ss)
Definition: replace.cpp:356
rplpoint * replace_recover_source_frame(rplpoint *rp, executionstate_t *es, sourcestate_t *ss)
Definition: replace.cpp:1671
s4 nregdescint[]
Definition: md-abi.cpp:41
void replace_deactivate_replacement_points(codeinfo *code)
Definition: replace.cpp:202
static s4 replace_normalize_type_map[]
Definition: replace.cpp:387
static void replace_pop_native_frame(executionstate_t *es, sourcestate_t *ss, stackframeinfo_t *sfi)
Definition: replace.cpp:1514
void replace_patch_future_calls(u1 *ra, sourceframe_t *callerframe, sourceframe_t *calleeframe)
Definition: replace.cpp:1150
void replace_patch_callback(classinfo *c, struct replace_patch_data_t *pd)
Definition: replace.cpp:1106
static void md_dcacheflush(void *addr, int nbytes)
Definition: md.hpp:167
static void replace_build_execution_state(sourcestate_t *ss, executionstate_t *es)
Definition: replace.cpp:1771
#define LA_LR_OFFSET
Definition: md-abi.hpp:97
#define INT_REG_CNT
Definition: md-abi.hpp:74
uint8_t u1
Definition: types.hpp:40
u1 * methodptr
Definition: global.hpp:40
rplpoint * replace_find_replacement_point_at_or_before_pc(codeinfo *code, u1 *pc, unsigned int desired_flags)
Definition: replace.cpp:1444
s4 * interfacevftbllength
Definition: vftbl.hpp:115
void(* classcache_foreach_functionptr_t)(classinfo *, void *)
Definition: classcache.hpp:115
static int code_is_using_frameptr(codeinfo *code)
Definition: code.hpp:194
void jit_request_optimization(methodinfo *m)
Definition: jit.cpp:967
static int code_is_leafmethod(codeinfo *code)
Definition: code.hpp:150
void replace_patch_class_hierarchy(methodinfo *m, u1 *oldentrypoint, u1 *entrypoint)
Definition: replace.cpp:1120
static void replace_read_value(executionstate_t *es, rplalloc *ra, replace_val_t *javaval)
Definition: replace.cpp:252
void md_cacheflush(u1 *addr, s4 nbytes)
Definition: md.c:49
methodinfo * m
Definition: code.hpp:74
#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:302
#define TYPECHAR(t)
Definition: replace.cpp:2041
s4 interfacetablelength
Definition: vftbl.hpp:103
codeinfo * code_find_codeinfo_for_pc(void *pc)
Definition: code.cpp:101
s4 vftblindex
Definition: method.hpp:81
#define MFREE(ptr, type, num)
Definition: memory.hpp:97
JNIEnv jthread jmethodID method
Definition: jvmti.h:207
Dump memory area.
Definition: dumpmemory.hpp:90
uint16_t u2
Definition: types.hpp:43
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:1057
classinfo * clazz
Definition: vftbl.hpp:100
static codeinfo * code_get_codeinfo_for_pv(void *pv)
Definition: code.hpp:222
const char * show_jit_type_names[]
Definition: show.cpp:104
#define IS_FLT_DBL_TYPE(a)
Definition: global.hpp:131
#define MZERO(ptr, type, num)
Definition: memory.hpp:105
Simple stream class for formatted output.
Definition: OStream.hpp:141
MIIterator i
#define LOG2(STMT)
Definition: logging.hpp:93
#define SIZE_OF_STACKSLOT
Definition: simplereg.cpp:80
#define TOP_IS_VOID
Definition: replace.cpp:78
int32_t s4
Definition: types.hpp:45
ResetColor reset_color
Definition: OStream.cpp:61
static void * md_codegen_get_pv_from_pc(void *ra)
Definition: md.hpp:100
void md_push_stackframe(executionstate_t *es, codeinfo *calleecode, u1 *ra)
Definition: replace.cpp:814
rplpoint * replace_find_replacement_point_for_pc(codeinfo *code, u1 *pc)
Definition: replace.cpp:1480
s4 maxlocals
Definition: method.hpp:84
OStream & OS
OStream & operator<<(OStream &OS, const std::string &t)
Definition: OStream.hpp:459
#define STACK_SLOTS_PER_FLOAT
void replace_pop_activation_record(executionstate_t *es, sourceframe_t *frame)
Definition: replace.cpp:957
bool inmemory
Definition: descriptor.hpp:151
const char * abi_registers_integer_name[]
Definition: md-abi.cpp:57
This file contains the real-time timing utilities.
#define MNEW(type, num)
Definition: memory.hpp:96
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:1275
#define LOG(STMT)
Analogous to DEBUG.
Definition: logging.hpp:91
void * md_jit_method_patch_address(void *pv, void *ra, void *mptr)
Definition: md.cpp:83
uint32_t u4
Definition: types.hpp:46
methodinfo * m
Definition: replace.cpp:1101
#define REPLACEMENT_PATCH_SIZE
Definition: arch.hpp:119
vftbl_t * vftbl
Definition: class.hpp:121
classinfo * class_java_lang_String
Definition: globals.cpp:39
static void replace_write_executionstate(rplpoint *rp, executionstate_t *es, sourcestate_t *ss)
Definition: replace.cpp:638
#define sp
Definition: md-asm.hpp:81
bool replace_handle_replacement_trap(u1 *pc, executionstate_t *es)
Definition: replace.cpp:1931
#define pc
Definition: md-asm.hpp:56
static OStream & replace_val_print(OStream &OS, s4 type, replace_val_t value)
Definition: replace.cpp:2150
void replace_handle_countdown_trap(u1 *pc, executionstate_t *es)
Definition: replace.cpp:1887
#define TOP_IS_NORMAL
Definition: replace.cpp:75
static void * allocate(size_t size)
Definition: dumpmemory.hpp:251
static void replace_patch_method_pointer(methodptr *mpp, methodptr entrypoint, const char *kind)
Definition: replace.cpp:1023
void classcache_foreach_loaded_class(classcache_foreach_functionptr_t func, void *data)
#define TOP_IS_IN_ITMP1
Definition: replace.cpp:77
#define REPLACE_IS_NATIVE_FRAME(frame)
Determines whether a given sourceframe represents a frame of a native method.
Definition: replace.cpp:84
uintptr_t intregs[INT_REG_CNT]
#define REG_FP
Definition: md-abi.hpp:53
#define REPLACE_IS_CALL_SITE(rp)
Determeines whether the given replacement point is at a call site.
Definition: replace.cpp:89
methodptr table[1]
Definition: vftbl.hpp:116
s4 nregdescfloat[]
Definition: md-abi.cpp:98
s4 flags
Definition: method.hpp:70
uintptr_t ptrint
Definition: types.hpp:54
rplpoint * replace_find_replacement_point_at_call_site(codeinfo *code, sourceframe_t *frame)
Definition: replace.cpp:1348
#define ABORT_MSG(EXPR_SHORT, EXPR_LONG)
Definition: logging.hpp:133
vftbl_t * vftbl
Definition: global.hpp:264
Nl nl
Definition: OStream.cpp:56
double fltregs[FLT_REG_CNT]
uint32_t regoff
Definition: descriptor.hpp:153
u1 * jit_recompile_for_deoptimization(methodinfo *m)
Definition: jit.cpp:538
static void replace_read_executionstate(rplpoint *rp, executionstate_t *es, sourcestate_t *ss)
Definition: replace.cpp:398
#define printf(...)
Definition: ssa2.cpp:40
uint64_t stackslot_t
LoopTreeGraph * parent
uint8_t savedintcount
Definition: code.hpp:89
#define FLT_REG_CNT
Definition: md-abi.hpp:81
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:57
#define REG_ITMP1
Definition: md-abi.hpp:46
u1 * entrypoint
Definition: code.hpp:83
static OStream & print_replace_vals(OStream &OS, replace_val_t *values, u1 *types, s4 count)
Definition: replace.cpp:2188
#define RBP
Definition: md-abi.hpp:37