CACAO
executionstate.cpp
Go to the documentation of this file.
1 /* src/vm/jit/executionstate.cpp - execution-state handling
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 
26 #include <stdint.h> // for uintptr_t, int32_t, uint8_t, etc
27 #include <string.h> // for memcmp
28 #include <cstdio> // for printf
29 #include "config.h" // for SIZEOF_VOID_P
30 #include "arch.hpp"
31 #include "md-abi.hpp" // for FLT_REG_CNT, INT_REG_CNT
32 #include "md.hpp" // for md_codegen_get_pv_from_pc, etc
33 #include "vm/descriptor.hpp" // for methoddesc
34 #include "vm/exceptions.hpp" // for exceptions_handle_exception
35 #include "vm/jit/abi.hpp" // for nregdescfloat, nregdescint
36 #include "vm/jit/code.hpp" // for codeinfo, etc
37 #include "vm/method.hpp" // for method_print, methodinfo
38 #include "vm/os.hpp" // for os
39 #include "vm/types.hpp" // for s4, ptrint, u1, u8
40 
41 /**
42  * Restore callee-saved registers (including the RA register),
43  * set the stack pointer to the next stackframe,
44  * set the PC to the return address of the popped frame.
45  *
46  * *** This function imitates the effects of the method epilog ***
47  * *** and returning from the method call. ***
48  *
49  * @param es Execution state to be modified.
50  * NOTE: es->code and es->pv are NOT updated.
51  */
53 {
54  int32_t reg;
55  int32_t i;
56 
57  // Sanity checks.
58  assert(es->code != NULL);
59 
60  // Calculate the size of the stackframe.
61  int32_t framesize = md_stacktrace_get_framesize(es->code);
62 
63  // Read the return address.
64  uint8_t* ra;
65 #if STACKFRAME_LEAFMETHODS_RA_REGISTER
66  if (code_is_leafmethod(es->code))
67  ra = es->ra;
68  else
69 #endif
70  ra = (u1*) md_stacktrace_get_returnaddress(es->sp, framesize);
71 
72  // Calculate the base of the stack frame.
73  uintptr_t sp = (uintptr_t) es->sp;
74  uintptr_t basesp = sp + es->code->stackframesize * SIZE_OF_STACKSLOT;
75 
76  // Restore return address, if part of frame.
79  if (!code_is_leafmethod(es->code)) {
80 # endif
81 # if STACKFRAME_PACKED_SAVED_REGISTERS
82  basesp -= 1 * SIZEOF_VOID_P;
83 # else
84  basesp -= 1 * SIZE_OF_STACKSLOT;
85 # endif
86  es->ra = *((uint8_t**) basesp);
87 # if STACKFRAME_LEAFMETHODS_RA_REGISTER
88  }
89 # endif
90 #endif /* STACKFRAME_RA_TOP_OF_FRAME */
91 
92  // Restore return address, if inside linkage area.
93 #if STACKFRAME_RA_LINKAGE_AREA
94 # if STACKFRAME_LEAFMETHODS_RA_REGISTER
95  if (!code_is_leafmethod(es->code))
96 # endif
97  es->ra = *((uint8_t**) (basesp + LA_LR_OFFSET));
98 #endif /* STACKFRAME_RA_LINKAGE_AREA */
99 
100  // Restore saved int registers.
101  reg = INT_REG_CNT;
102  for (i=0; i<es->code->savedintcount; ++i) {
103  while (nregdescint[--reg] != REG_SAV)
104  ;
105 #if STACKFRAME_PACKED_SAVED_REGISTERS
106  basesp -= 1 * SIZEOF_VOID_P;
107 #else
108  basesp -= 1 * SIZE_OF_STACKSLOT;
109 #endif
110  es->intregs[reg] = *((uintptr_t*) basesp);
111  }
112 
113  // Restore saved flt registers.
114  // XXX align?
115  reg = FLT_REG_CNT;
116  for (i=0; i<es->code->savedfltcount; ++i) {
117  while (nregdescfloat[--reg] != REG_SAV)
118  ;
120  es->fltregs[reg] = *((double*) basesp);
121  }
122 
123  // Adjust the stackpointer.
124  es->sp += framesize;
125 #if STACKFRAME_RA_BETWEEN_FRAMES
126  es->sp += SIZEOF_VOID_P; /* skip return address */
127 #endif
128 
129  // Set the program counter to the return address.
130  es->pc = ra;
131 
132  // In debugging mode clobber non-saved registers.
133 #if !defined(NDEBUG)
134  for (i=0; i<INT_REG_CNT; ++i)
135  if (nregdescint[i] != REG_SAV && nregdescint[i] != REG_RES)
136  es->intregs[i] = (ptrint) 0x33dead3333dead33ULL;
137  for (i=0; i<FLT_REG_CNT; ++i)
138  if (nregdescfloat[i] != REG_SAV && nregdescfloat[i] != REG_RES)
139  *(u8*)&(es->fltregs[i]) = 0x33dead3333dead33ULL;
140 #endif /* !defined(NDEBUG) */
141 }
142 
143 /**
144  * Performs stack unwinding in case of an exception. This is done by
145  * popping frames off the given execution state until a frame is reached
146  * for which there is a handler. Execution will continue at the handler
147  * site once the execution state is written back to the machine.
148  *
149  * @param es Execution state to be modified.
150  * @param e The thrown exception object.
151  *
152  * This is specified in:
153  * The Java(TM) Virtual Machine Specification, Second Edition
154  * Section 3.6.5: Abrupt Method Invocation Completion
155  */
157 {
158  void* handler = NULL;
159 
160  // Iterate until we find an exception handler.
161  while (handler == NULL) {
162 
163  // Search an exception handler in the current frame.
164  handler = exceptions_handle_exception(e, es->pc, es->pv, es->sp);
165 
166  // Jump directly into the handler in case we found one.
167  if (handler != NULL)
168  break;
169 
170  // Find the codeinfo structure for the current frame.
171  es->code = code_get_codeinfo_for_pv(es->pv);
172 
173  // Pop one frame off the stack.
175 
176  // Get the PV for the parent Java method.
177  es->pv = (uint8_t*) md_codegen_get_pv_from_pc(es->pc);
178 
179  // After popping the frame the PC points to the instruction just after
180  // the invocation. To get the XPC we need to correct the PC to point
181  // just before the invocation. But we do not know how big the
182  // invocation site actually is, so we subtract one, which should be
183  // sufficient for our purposes.
184  es->pc -= 1;
185  }
186 
187  // Update the execution state to continue at the handler site.
188  es->pc = (uint8_t*) handler;
189 }
190 
191 
192 /* executionstate_sanity_check *************************************************
193 
194  Perform some sanity checks for the md_executionstate_read and
195  md_executionstate_write functions.
196 
197 *******************************************************************************/
198 
199 #if !defined(NDEBUG)
200 void executionstate_sanity_check(void *context)
201 {
202  /* estimate a minimum for the context size */
203 
204 #define MINIMUM_CONTEXT_SIZE (SIZEOF_VOID_P * INT_REG_CNT \
205  + sizeof(double) * FLT_REG_CNT)
206 
207  executionstate_t es1;
208  executionstate_t es2;
209  executionstate_t es3;
210  unsigned int i;
211  unsigned char reference[MINIMUM_CONTEXT_SIZE];
212 
213  /* keep a copy of (a prefix of) the context for reference */
214 
215  os::memcpy(&reference, context, MINIMUM_CONTEXT_SIZE);
216 
217  /* different poisons */
218 
219  os::memset(&es1, 0xc9, sizeof(executionstate_t));
220  os::memset(&es2, 0xb5, sizeof(executionstate_t));
221  os::memset(&es3, 0x6f, sizeof(executionstate_t));
222 
223  md_executionstate_read(&es1, context);
224 
225  /* verify that item-by-item copying preserves the state */
226 
227  es2.pc = es1.pc;
228  es2.sp = es1.sp;
229  es2.pv = es1.pv;
230  es2.ra = es1.ra;
231  es2.code = es1.code;
232  for (i = 0; i < INT_REG_CNT; ++i)
233  es2.intregs[i] = es1.intregs[i];
234  for (i = 0; i < FLT_REG_CNT; ++i)
235  es2.fltregs[i] = es1.fltregs[i];
236 
237  /* write it back - this should not change the context */
238  /* We cannot check that completely, unfortunately, as we don't know */
239  /* the size of the (OS-dependent) context. */
240 
241  md_executionstate_write(&es2, context);
242 
243  /* Read it again, Sam! */
244 
245  md_executionstate_read(&es3, context);
246 
247  /* Compare. Note: Because of the NAN madness, we cannot compare
248  * doubles using '=='. */
249 
250  assert(es3.pc == es1.pc);
251  assert(es3.sp == es1.sp);
252  assert(es3.pv == es1.pv);
253  for (i = 0; i < INT_REG_CNT; ++i)
254  assert(es3.intregs[i] == es1.intregs[i]);
255  for (i = 0; i < FLT_REG_CNT; ++i)
256  assert(memcmp(es3.fltregs+i, es1.fltregs+i, sizeof(double)) == 0);
257 
258  /* i386 and x86_64 do not have an RA register */
259 
260 #if defined(__I386__) || defined(__X86_64__)
261  assert(es3.ra != es1.ra);
262 #else
263  assert(es3.ra == es1.ra);
264 #endif
265 
266  /* "code" is not set by the md_* functions */
267 
268  assert(es3.code != es1.code);
269 
270  /* assert that we have not messed up the context */
271 
272  assert(memcmp(&reference, context, MINIMUM_CONTEXT_SIZE) == 0);
273 }
274 #endif
275 
276 
277 /* executionstate_println ******************************************************
278 
279  Print execution state
280 
281  IN:
282  es...............the execution state to print
283 
284 *******************************************************************************/
285 
286 #if !defined(NDEBUG)
288 {
289  uint64_t *sp;
290  int slots;
291  int extraslots;
292  int i;
293 
294  if (!es) {
295  printf("(executionstate_t *)NULL\n");
296  return;
297  }
298 
299  printf("executionstate_t:\n");
300  printf("\tpc = %p", es->pc);
301  printf(" sp = %p", es->sp);
302  printf(" pv = %p", es->pv);
303  printf(" ra = %p\n", es->ra);
304 
305 #if defined(ENABLE_DISASSEMBLER)
306  for (i=0; i<INT_REG_CNT; ++i) {
307  if (i%4 == 0)
308  printf("\t");
309  else
310  printf(" ");
311 # if SIZEOF_VOID_P == 8
312  printf("%-3s = %016lx", abi_registers_integer_name[i], es->intregs[i]);
313 # else
314  printf("%-3s = %08x", abi_registers_integer_name[i], (unsigned) es->intregs[i]);
315 # endif
316  if (i%4 == 3)
317  printf("\n");
318  }
319 
320  for (i=0; i<FLT_REG_CNT; ++i) {
321  if (i%4 == 0)
322  printf("\t");
323  else
324  printf(" ");
325  printf("F%02d = %016llx",i,(unsigned long long)es->fltregs[i]);
326  if (i%4 == 3)
327  printf("\n");
328  }
329 #endif
330 
331  sp = (uint64_t *) es->sp;
332 
333  extraslots = 2;
334 
335  if (es->code) {
336  methoddesc *md = es->code->m->parseddesc;
337  slots = es->code->stackframesize;
338  extraslots = 1 + md->memuse;
339  }
340  else
341  slots = 0;
342 
343 
344  if (slots) {
345  printf("\tstack slots(+%d) at sp:", extraslots);
346  for (i=0; i<slots+extraslots; ++i) {
347  if (i%4 == 0)
348  printf("\n\t\t");
349  printf("M%02d%c", i, (i >= slots) ? '(' : ' ');
350  printf("%016llx",(unsigned long long)*sp++);
351  printf("%c", (i >= slots) ? ')' : ' ');
352  }
353  printf("\n");
354  }
355 
356  printf("\tcode: %p", (void*)es->code);
357  if (es->code != NULL) {
358  printf(" stackframesize=%d ", es->code->stackframesize);
359  method_print(es->code->m);
360  }
361  printf("\n");
362 
363  printf("\n");
364 }
365 #endif
366 
367 
368 /*
369  * These are local overrides for various environment variables in Emacs.
370  * Please do not remove this and leave it at the end of the file, where
371  * Emacs will automagically detect them.
372  * ---------------------------------------------------------------------
373  * Local variables:
374  * mode: c++
375  * indent-tabs-mode: t
376  * c-basic-offset: 4
377  * tab-width: 4
378  * End:
379  * vim:noexpandtab:sw=4:ts=4:
380  */
static void * memset(void *s, int c, size_t n)
Definition: os.hpp:501
#define ra
Definition: md-asm.hpp:62
void method_print(methodinfo *m)
Definition: method.cpp:1189
void executionstate_pop_stackframe(executionstate_t *es)
Restore callee-saved registers (including the RA register), set the stack pointer to the next stackfr...
#define REG_SAV
Definition: jit.hpp:442
uint8_t savedfltcount
Definition: code.hpp:91
int32_t stackframesize
Definition: code.hpp:88
s4 nregdescint[]
Definition: md-abi.cpp:41
#define STACKFRAME_RA_TOP_OF_FRAME
Definition: arch.hpp:103
#define LA_LR_OFFSET
Definition: md-abi.hpp:97
#define MINIMUM_CONTEXT_SIZE
#define INT_REG_CNT
Definition: md-abi.hpp:72
#define STACKFRAME_LEAFMETHODS_RA_REGISTER
Definition: arch.hpp:105
#define REG_RES
Definition: jit.hpp:439
uint8_t u1
Definition: types.hpp:40
static int code_is_leafmethod(codeinfo *code)
Definition: code.hpp:151
#define exceptions_handle_exception
Definition: md-asm.hpp:102
methodinfo * m
Definition: code.hpp:75
void executionstate_println(executionstate_t *es)
uint64_t u8
Definition: types.hpp:49
static codeinfo * code_get_codeinfo_for_pv(void *pv)
Definition: code.hpp:201
MIIterator i
void executionstate_unwind_exception(executionstate_t *es, java_handle_t *e)
Performs stack unwinding in case of an exception.
#define SIZE_OF_STACKSLOT
Definition: simplereg.cpp:80
static void * memcpy(void *dest, const void *src, size_t n)
Definition: os.hpp:492
void md_executionstate_write(executionstate_t *es, void *context)
Definition: md-os.cpp:147
static void * md_codegen_get_pv_from_pc(void *ra)
Definition: md.hpp:99
#define STACK_SLOTS_PER_FLOAT
const char * abi_registers_integer_name[]
Definition: md-abi.cpp:57
MIIterator e
methoddesc * parseddesc
Definition: method.hpp:78
#define sp
Definition: md-asm.hpp:81
void md_executionstate_read(executionstate_t *es, void *context)
Definition: md-os.cpp:107
static void * md_stacktrace_get_returnaddress(void *sp, int32_t stackframesize)
Definition: md.hpp:76
void executionstate_sanity_check(void *context)
uintptr_t intregs[INT_REG_CNT]
s4 nregdescfloat[]
Definition: md-abi.cpp:98
uintptr_t ptrint
Definition: types.hpp:54
double fltregs[FLT_REG_CNT]
#define printf(...)
Definition: ssa2.cpp:40
uint8_t savedintcount
Definition: code.hpp:90
#define FLT_REG_CNT
Definition: md-abi.hpp:79
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