1 /* src/vm/jit/executionstate.c - execution-state handling
3 Copyright (C) 2007, 2008, 2009
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
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.
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.
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
35 #include "vm/descriptor.hpp"
38 #include "vm/jit/abi.h"
39 #include "vm/jit/executionstate.h"
43 * Restore callee-saved registers (including the RA register),
44 * set the stack pointer to the next stackframe,
45 * set the PC to the return address of the popped frame.
47 * *** This function imitates the effects of the method epilog ***
48 * *** and returning from the method call. ***
50 * @param es Execution state to be modified.
51 * NOTE: es->code and es->pv are NOT updated.
53 void executionstate_pop_stackframe(executionstate_t *es)
59 assert(es->code != NULL);
61 // Calculate the size of the stackframe.
62 int32_t framesize = md_stacktrace_get_framesize(es->code);
64 // Read the return address.
66 #if STACKFRAME_LEAFMETHODS_RA_REGISTER
67 if (code_is_leafmethod(es->code))
71 ra = (u1*) md_stacktrace_get_returnaddress(es->sp, framesize);
73 // Calculate the base of the stack frame.
74 uintptr_t sp = (uintptr_t) es->sp;
75 uintptr_t basesp = sp + es->code->stackframesize * SIZE_OF_STACKSLOT;
77 // Restore return address, if part of frame.
78 #if STACKFRAME_RA_TOP_OF_FRAME
79 # if STACKFRAME_LEAFMETHODS_RA_REGISTER
80 if (!code_is_leafmethod(es->code)) {
82 basesp -= 1 * SIZE_OF_STACKSLOT;
83 es->ra = *((uint8_t**) basesp);
84 # if STACKFRAME_LEAFMETHODS_RA_REGISTER
87 #endif /* STACKFRAME_RA_TOP_OF_FRAME */
89 // Restore return address, if inside linkage area.
90 #if STACKFRAME_RA_LINKAGE_AREA
91 # if STACKFRAME_LEAFMETHODS_RA_REGISTER
92 if (!code_is_leafmethod(es->code))
94 es->ra = *((uint8_t**) (basesp + LA_LR_OFFSET));
95 #endif /* STACKFRAME_RA_LINKAGE_AREA */
97 // Restore saved int registers.
99 for (i=0; i<es->code->savedintcount; ++i) {
100 while (nregdescint[--reg] != REG_SAV)
102 basesp -= 1 * SIZE_OF_STACKSLOT;
103 es->intregs[reg] = *((uintptr_t*) basesp);
106 // Restore saved flt registers.
109 for (i=0; i<es->code->savedfltcount; ++i) {
110 while (nregdescfloat[--reg] != REG_SAV)
112 basesp -= STACK_SLOTS_PER_FLOAT * SIZE_OF_STACKSLOT;
113 es->fltregs[reg] = *((double*) basesp);
116 #if defined(HAS_ADDRESS_REGISTER_FILE)
117 // Restore saved adr registers.
119 for (i=0; i<es->code->savedadrcount; ++i) {
120 while (nregdescadr[--reg] != REG_SAV)
122 basesp -= 1 * SIZE_OF_STACKSLOT;
123 es->adrregs[reg] = *((uintptr_t*) basesp);
127 // Adjust the stackpointer.
129 #if STACKFRMAE_RA_BETWEEN_FRAMES
130 es->sp += SIZEOF_VOID_P; /* skip return address */
133 // Set the program counter to the return address.
136 // In debugging mode clobber non-saved registers.
138 for (i=0; i<INT_REG_CNT; ++i)
139 if (nregdescint[i] != REG_SAV)
140 es->intregs[i] = (ptrint) 0x33dead3333dead33ULL;
141 for (i=0; i<FLT_REG_CNT; ++i)
142 if (nregdescfloat[i] != REG_SAV)
143 *(u8*)&(es->fltregs[i]) = 0x33dead3333dead33ULL;
144 # if defined(HAS_ADDRESS_REGISTER_FILE)
145 for (i=0; i<ADR_REG_CNT; ++i)
146 if (nregdescadr[i] != REG_SAV)
147 es->adrregs[i] = (ptrint) 0x33dead3333dead33ULL;
149 #endif /* !defined(NDEBUG) */
153 // XXX Move this prototype somewhere else!
154 void *exceptions_handle_exception(java_object_t *xptro, void *xpc, void *pv, void *sp);
158 * Performs stack unwinding in case of an exception. This is done by
159 * popping frames off the given execution state until a frame is reached
160 * for which there is a handler. Execution will continue at the handler
161 * site once the execution state is written back to the machine.
163 * @param es Execution state to be modified.
164 * @param e The thrown exception object.
166 * This is specified in:
167 * The Java(TM) Virtual Machine Specification, Second Edition
168 * Section 3.6.5: Abrupt Method Invocation Completion
170 void executionstate_unwind_exception(executionstate_t* es, java_handle_t* e)
172 void* handler = NULL;
174 // Iterate until we find an exception handler.
175 while (handler == NULL) {
177 // Search an exception handler in the current frame.
178 handler = exceptions_handle_exception(e, es->pc, es->pv, es->sp);
180 // Jump directly into the handler in case we found one.
184 // Find the codeinfo structure for the current frame.
185 es->code = code_get_codeinfo_for_pv(es->pv);
187 // Pop one frame off the stack.
188 executionstate_pop_stackframe(es);
190 // Get the PV for the parent Java method.
191 es->pv = md_codegen_get_pv_from_pc(es->pc);
193 // After popping the frame the PC points to the instruction just after
194 // the invocation. To get the XPC we need to correct the PC to point
195 // just before the invocation. But we do not know how big the
196 // invocation site actually is, so we subtract one, which should be
197 // sufficient for our purposes.
201 // Update the execution state to continue at the handler site.
202 es->pc = (uint8_t*) handler;
206 /* executionstate_sanity_check *************************************************
208 Perform some sanity checks for the md_executionstate_read and
209 md_executionstate_write functions.
211 *******************************************************************************/
214 void executionstate_sanity_check(void *context)
216 /* estimate a minimum for the context size */
218 #if defined(HAS_ADDRESS_REGISTER_FILE)
219 #define MINIMUM_CONTEXT_SIZE (SIZEOF_VOID_P * ADR_REG_CNT \
220 + sizeof(double) * FLT_REG_CNT \
221 + sizeof(int) * INT_REG_CNT)
223 #define MINIMUM_CONTEXT_SIZE (SIZEOF_VOID_P * INT_REG_CNT \
224 + sizeof(double) * FLT_REG_CNT)
227 executionstate_t es1;
228 executionstate_t es2;
229 executionstate_t es3;
231 unsigned char reference[MINIMUM_CONTEXT_SIZE];
233 /* keep a copy of (a prefix of) the context for reference */
235 os_memcpy(&reference, context, MINIMUM_CONTEXT_SIZE);
237 /* different poisons */
239 os_memset(&es1, 0xc9, sizeof(executionstate_t));
240 os_memset(&es2, 0xb5, sizeof(executionstate_t));
241 os_memset(&es3, 0x6f, sizeof(executionstate_t));
243 md_executionstate_read(&es1, context);
245 /* verify that item-by-item copying preserves the state */
252 for (i = 0; i < INT_REG_CNT; ++i)
253 es2.intregs[i] = es1.intregs[i];
254 for (i = 0; i < FLT_REG_CNT; ++i)
255 es2.fltregs[i] = es1.fltregs[i];
256 #if defined(HAS_ADDRESS_REGISTER_FILE)
257 for (i = 0; i < ADR_REG_CNT; ++i)
258 es2.adrregs[i] = es1.adrregs[i];
261 /* write it back - this should not change the context */
262 /* We cannot check that completely, unfortunately, as we don't know */
263 /* the size of the (OS-dependent) context. */
265 md_executionstate_write(&es2, context);
267 /* Read it again, Sam! */
269 md_executionstate_read(&es3, context);
271 /* Compare. Note: Because of the NAN madness, we cannot compare
272 * doubles using '=='. */
274 assert(es3.pc == es1.pc);
275 assert(es3.sp == es1.sp);
276 assert(es3.pv == es1.pv);
277 for (i = 0; i < INT_REG_CNT; ++i)
278 assert(es3.intregs[i] == es1.intregs[i]);
279 for (i = 0; i < FLT_REG_CNT; ++i)
280 assert(memcmp(es3.fltregs+i, es1.fltregs+i, sizeof(double)) == 0);
281 #if defined(HAS_ADDRESS_REGISTER_FILE)
282 for (i = 0; i < ADR_REG_CNT; ++i)
283 assert(es3.adrregs[i] == es1.adrregs[i]);
286 /* i386 and x86_64 do not have an RA register */
288 #if defined(__I386__) || defined(__X86_64__)
289 assert(es3.ra != es1.ra);
291 assert(es3.ra == es1.ra);
294 /* "code" is not set by the md_* functions */
296 assert(es3.code != es1.code);
298 /* assert that we have not messed up the context */
300 assert(memcmp(&reference, context, MINIMUM_CONTEXT_SIZE) == 0);
305 /* executionstate_println ******************************************************
307 Print execution state
310 es...............the execution state to print
312 *******************************************************************************/
315 void executionstate_println(executionstate_t *es)
323 printf("(executionstate_t *)NULL\n");
327 printf("executionstate_t:\n");
328 printf("\tpc = %p", es->pc);
329 printf(" sp = %p", es->sp);
330 printf(" pv = %p", es->pv);
331 printf(" ra = %p\n", es->ra);
333 #if defined(ENABLE_DISASSEMBLER)
334 for (i=0; i<INT_REG_CNT; ++i) {
339 # if SIZEOF_VOID_P == 8
340 printf("%-3s = %016lx", abi_registers_integer_name[i], es->intregs[i]);
342 printf("%-3s = %08x", abi_registers_integer_name[i], (unsigned) es->intregs[i]);
348 for (i=0; i<FLT_REG_CNT; ++i) {
353 printf("F%02d = %016llx",i,(unsigned long long)es->fltregs[i]);
358 # if defined(HAS_ADDRESS_REGISTER_FILE)
359 for (i=0; i<ADR_REG_CNT; ++i) {
364 printf("A%02d = %016llx",i,(unsigned long long)es->adrregs[i]);
371 sp = (uint64_t *) es->sp;
376 methoddesc *md = es->code->m->parseddesc;
377 slots = es->code->stackframesize;
378 extraslots = 1 + md->memuse;
385 printf("\tstack slots(+%d) at sp:", extraslots);
386 for (i=0; i<slots+extraslots; ++i) {
389 printf("M%02d%c", i, (i >= slots) ? '(' : ' ');
390 printf("%016llx",(unsigned long long)*sp++);
391 printf("%c", (i >= slots) ? ')' : ' ');
396 printf("\tcode: %p", (void*)es->code);
397 if (es->code != NULL) {
398 printf(" stackframesize=%d ", es->code->stackframesize);
399 method_print(es->code->m);
409 * These are local overrides for various environment variables in Emacs.
410 * Please do not remove this and leave it at the end of the file, where
411 * Emacs will automagically detect them.
412 * ---------------------------------------------------------------------
415 * indent-tabs-mode: t
419 * vim:noexpandtab:sw=4:ts=4: