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