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 20521 : void executionstate_pop_stackframe(executionstate_t *es)
53 : {
54 : int32_t reg;
55 : int32_t i;
56 :
57 : // Sanity checks.
58 20521 : assert(es->code != NULL);
59 :
60 : // Calculate the size of the stackframe.
61 20521 : 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 20521 : ra = (u1*) md_stacktrace_get_returnaddress(es->sp, framesize);
71 :
72 : // Calculate the base of the stack frame.
73 20521 : uintptr_t sp = (uintptr_t) es->sp;
74 20521 : 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 : # 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 20521 : reg = INT_REG_CNT;
102 42175 : for (i=0; i<es->code->savedintcount; ++i) {
103 22698 : while (nregdescint[--reg] != REG_SAV)
104 : ;
105 : #if STACKFRAME_PACKED_SAVED_REGISTERS
106 : basesp -= 1 * SIZEOF_VOID_P;
107 : #else
108 21654 : basesp -= 1 * SIZE_OF_STACKSLOT;
109 : #endif
110 21654 : es->intregs[reg] = *((uintptr_t*) basesp);
111 : }
112 :
113 : // Restore saved flt registers.
114 : // XXX align?
115 20521 : reg = FLT_REG_CNT;
116 20521 : for (i=0; i<es->code->savedfltcount; ++i) {
117 0 : while (nregdescfloat[--reg] != REG_SAV)
118 : ;
119 0 : basesp -= STACK_SLOTS_PER_FLOAT * SIZE_OF_STACKSLOT;
120 0 : es->fltregs[reg] = *((double*) basesp);
121 : }
122 :
123 : // Adjust the stackpointer.
124 20521 : es->sp += framesize;
125 : #if STACKFRAME_RA_BETWEEN_FRAMES
126 20521 : es->sp += SIZEOF_VOID_P; /* skip return address */
127 : #endif
128 :
129 : // Set the program counter to the return address.
130 20521 : es->pc = ra;
131 :
132 : // In debugging mode clobber non-saved registers.
133 : #if !defined(NDEBUG)
134 348857 : for (i=0; i<INT_REG_CNT; ++i)
135 328336 : if (nregdescint[i] != REG_SAV && nregdescint[i] != REG_RES)
136 164168 : es->intregs[i] = (ptrint) 0x33dead3333dead33ULL;
137 348857 : for (i=0; i<FLT_REG_CNT; ++i)
138 328336 : if (nregdescfloat[i] != REG_SAV && nregdescfloat[i] != REG_RES)
139 266773 : *(u8*)&(es->fltregs[i]) = 0x33dead3333dead33ULL;
140 : #endif /* !defined(NDEBUG) */
141 20521 : }
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 : */
156 21025 : void executionstate_unwind_exception(executionstate_t* es, java_handle_t* e)
157 : {
158 21025 : void* handler = NULL;
159 :
160 : // Iterate until we find an exception handler.
161 62571 : while (handler == NULL) {
162 :
163 : // Search an exception handler in the current frame.
164 41546 : handler = exceptions_handle_exception(e, es->pc, es->pv, es->sp);
165 :
166 : // Jump directly into the handler in case we found one.
167 41546 : if (handler != NULL)
168 21025 : break;
169 :
170 : // Find the codeinfo structure for the current frame.
171 20521 : es->code = code_get_codeinfo_for_pv(es->pv);
172 :
173 : // Pop one frame off the stack.
174 20521 : executionstate_pop_stackframe(es);
175 :
176 : // Get the PV for the parent Java method.
177 20521 : 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 20521 : es->pc -= 1;
185 : }
186 :
187 : // Update the execution state to continue at the handler site.
188 21025 : es->pc = (uint8_t*) handler;
189 21025 : }
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 218378 : 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 218378 : os::memcpy(&reference, context, MINIMUM_CONTEXT_SIZE);
216 :
217 : /* different poisons */
218 :
219 218378 : os::memset(&es1, 0xc9, sizeof(executionstate_t));
220 218377 : os::memset(&es2, 0xb5, sizeof(executionstate_t));
221 218378 : os::memset(&es3, 0x6f, sizeof(executionstate_t));
222 :
223 218377 : md_executionstate_read(&es1, context);
224 :
225 : /* verify that item-by-item copying preserves the state */
226 :
227 218378 : es2.pc = es1.pc;
228 218378 : es2.sp = es1.sp;
229 218378 : es2.pv = es1.pv;
230 218378 : es2.ra = es1.ra;
231 218378 : es2.code = es1.code;
232 3712421 : for (i = 0; i < INT_REG_CNT; ++i)
233 3494043 : es2.intregs[i] = es1.intregs[i];
234 3712419 : for (i = 0; i < FLT_REG_CNT; ++i)
235 3494041 : 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 218378 : md_executionstate_write(&es2, context);
242 :
243 : /* Read it again, Sam! */
244 :
245 218378 : md_executionstate_read(&es3, context);
246 :
247 : /* Compare. Note: Because of the NAN madness, we cannot compare
248 : * doubles using '=='. */
249 :
250 218377 : assert(es3.pc == es1.pc);
251 218377 : assert(es3.sp == es1.sp);
252 218377 : assert(es3.pv == es1.pv);
253 3712425 : for (i = 0; i < INT_REG_CNT; ++i)
254 3494048 : assert(es3.intregs[i] == es1.intregs[i]);
255 3712425 : for (i = 0; i < FLT_REG_CNT; ++i)
256 3494047 : 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 218378 : 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 218378 : assert(es3.code != es1.code);
269 :
270 : /* assert that we have not messed up the context */
271 :
272 218378 : assert(memcmp(&reference, context, MINIMUM_CONTEXT_SIZE) == 0);
273 218378 : }
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)
287 0 : void executionstate_println(executionstate_t *es)
288 : {
289 : uint64_t *sp;
290 : int slots;
291 : int extraslots;
292 : int i;
293 :
294 0 : if (!es) {
295 0 : printf("(executionstate_t *)NULL\n");
296 0 : return;
297 : }
298 :
299 0 : printf("executionstate_t:\n");
300 0 : printf("\tpc = %p", es->pc);
301 0 : printf(" sp = %p", es->sp);
302 0 : printf(" pv = %p", es->pv);
303 0 : 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 0 : sp = (uint64_t *) es->sp;
332 :
333 0 : extraslots = 2;
334 :
335 0 : if (es->code) {
336 0 : methoddesc *md = es->code->m->parseddesc;
337 0 : slots = es->code->stackframesize;
338 0 : extraslots = 1 + md->memuse;
339 : }
340 : else
341 0 : slots = 0;
342 :
343 :
344 0 : if (slots) {
345 0 : printf("\tstack slots(+%d) at sp:", extraslots);
346 0 : for (i=0; i<slots+extraslots; ++i) {
347 0 : if (i%4 == 0)
348 0 : printf("\n\t\t");
349 0 : printf("M%02d%c", i, (i >= slots) ? '(' : ' ');
350 0 : printf("%016llx",(unsigned long long)*sp++);
351 0 : printf("%c", (i >= slots) ? ')' : ' ');
352 : }
353 0 : printf("\n");
354 : }
355 :
356 0 : printf("\tcode: %p", (void*)es->code);
357 0 : if (es->code != NULL) {
358 0 : printf(" stackframesize=%d ", es->code->stackframesize);
359 0 : method_print(es->code->m);
360 : }
361 0 : printf("\n");
362 :
363 0 : 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 : */
|