* src/vm/jit/code.c: Moved to .cpp.
[cacao.git] / src / vm / jit / trap.c
1 /* src/vm/jit/trap.c - hardware traps
2
3    Copyright (C) 2008
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
28 #include <stdint.h>
29
30 /* Include machine dependent trap stuff. */
31
32 #include "md-trap.h"
33
34 #include "mm/memory.h"
35
36 #include "native/llni.h"
37
38 #include "toolbox/logging.h"
39
40 #include "vm/exceptions.hpp"
41 #include "vm/options.h"
42 #include "vm/os.hpp"
43 #include "vm/vm.hpp"
44
45 #include "vm/jit/code.hpp"
46 #include "vm/jit/disass.h"
47 #include "vm/jit/jit.hpp"
48 #include "vm/jit/methodtree.h"
49 #include "vm/jit/patcher-common.h"
50 #include "vm/jit/replace.hpp"
51 #include "vm/jit/stacktrace.hpp"
52
53
54 /**
55  * Mmap the first memory page to support hardware exceptions and check
56  * the maximum hardware trap displacement on the architectures where
57  * it is required (TRAP_INSTRUCTION_IS_LOAD defined to 1).
58  */
59 void trap_init(void)
60 {
61 #if !(defined(__ARM__) && defined(__LINUX__))
62         /* On arm-linux the first memory page can't be mmap'ed, as it
63            contains the exception vectors. */
64
65         int pagesize;
66
67         /* mmap a memory page at address 0x0, so our hardware-exceptions
68            work. */
69
70         pagesize = os_getpagesize();
71
72         (void) os_mmap_anonymous(NULL, pagesize, PROT_NONE, MAP_PRIVATE | MAP_FIXED);
73 #endif
74
75         TRACESUBSYSTEMINITIALIZATION("trap_init");
76
77 #if !defined(TRAP_INSTRUCTION_IS_LOAD)
78 # error TRAP_INSTRUCTION_IS_LOAD is not defined in your md-trap.h
79 #endif
80
81 #if TRAP_INSTRUCTION_IS_LOAD == 1
82         /* Check if we get into trouble with our hardware-exceptions. */
83
84         if (TRAP_END > OFFSET(java_bytearray_t, data))
85                 vm_abort("trap_init: maximum hardware trap displacement is greater than the array-data offset: %d > %d", TRAP_END, OFFSET(java_bytearray_t, data));
86 #endif
87 }
88
89
90 /**
91  * Handles the signal which is generated by trap instructions, caught
92  * by a signal handler and calls the correct function.
93  *
94  * @param type trap number
95  * @param 
96  */
97 void* trap_handle(int type, intptr_t val, void *pv, void *sp, void *ra, void *xpc, void *context)
98 {
99         stackframeinfo_t  sfi;
100         int32_t           index;
101         java_handle_t    *o;
102         methodinfo       *m;
103         java_handle_t    *p;
104
105 #if !defined(NDEBUG)
106         if (opt_TraceTraps)
107                 log_println("[signal_handle: trap %d]", type);
108 #endif
109         
110 #if defined(ENABLE_VMLOG)
111         vmlog_cacao_signl_type(type);
112 #endif
113
114         /* Prevent compiler warnings. */
115
116         o = NULL;
117         m = NULL;
118
119         /* wrap the value into a handle if it is a reference */
120         /* BEFORE: creating stackframeinfo */
121
122         switch (type) {
123         case TRAP_ClassCastException:
124                 o = LLNI_WRAP((java_object_t *) val);
125                 break;
126
127         case TRAP_COMPILER:
128                 /* In this case the passed PV points to the compiler stub.  We
129                    get the methodinfo pointer here and set PV to NULL so
130                    stacktrace_stackframeinfo_add determines the PV for the
131                    parent Java method. */
132
133                 m  = code_get_methodinfo_for_pv(pv);
134                 pv = NULL;
135                 break;
136
137         default:
138                 /* do nothing */
139                 break;
140         }
141
142         /* Fill and add a stackframeinfo. */
143
144         stacktrace_stackframeinfo_add(&sfi, pv, sp, ra, xpc);
145
146         switch (type) {
147         case TRAP_NullPointerException:
148                 p = exceptions_new_nullpointerexception();
149                 break;
150
151         case TRAP_ArithmeticException:
152                 p = exceptions_new_arithmeticexception();
153                 break;
154
155         case TRAP_ArrayIndexOutOfBoundsException:
156                 index = (s4) val;
157                 p = exceptions_new_arrayindexoutofboundsexception(index);
158                 break;
159
160         case TRAP_ArrayStoreException:
161                 p = exceptions_new_arraystoreexception();
162                 break;
163
164         case TRAP_ClassCastException:
165                 p = exceptions_new_classcastexception(o);
166                 break;
167
168         case TRAP_CHECK_EXCEPTION:
169                 p = exceptions_fillinstacktrace();
170                 break;
171
172         case TRAP_PATCHER:
173 #if defined(ENABLE_REPLACEMENT)
174                 if (replace_me_wrapper(xpc, context)) {
175                         p = NULL;
176                         break;
177                 }
178 #endif
179                 p = patcher_handler(xpc);
180                 break;
181
182         case TRAP_COMPILER:
183                 p = jit_compile_handle(m, sfi.pv, ra, (void *) val);
184                 break;
185
186 #if defined(ENABLE_REPLACEMENT)
187         case TRAP_COUNTDOWN:
188 #if defined(__I386__)
189                 replace_me_wrapper((char*)xpc - 13, context);
190 #endif
191                 p = NULL;
192                 break;
193 #endif
194
195         default:
196                 /* Let's try to get a backtrace. */
197
198                 (void) methodtree_find(xpc);
199
200                 /* If that does not work, print more debug info. */
201
202                 log_println("signal_handle: unknown hardware exception type %d", type);
203
204 #if SIZEOF_VOID_P == 8
205                 log_println("PC=0x%016lx", xpc);
206 #else
207                 log_println("PC=0x%08x", xpc);
208 #endif
209
210 #if defined(ENABLE_DISASSEMBLER)
211                 log_println("machine instruction at PC:");
212                 disassinstr(xpc);
213 #endif
214
215                 vm_abort("Exiting...");
216
217                 /* keep compiler happy */
218
219                 p = NULL;
220         }
221
222         /* Remove stackframeinfo. */
223
224         stacktrace_stackframeinfo_remove(&sfi);
225
226         /* unwrap and return the exception object */
227         /* AFTER: removing stackframeinfo */
228
229         if (type == TRAP_COMPILER)
230                 return p;
231         else
232                 return LLNI_UNWRAP(p);
233 }
234
235
236 /*
237  * These are local overrides for various environment variables in Emacs.
238  * Please do not remove this and leave it at the end of the file, where
239  * Emacs will automagically detect them.
240  * ---------------------------------------------------------------------
241  * Local variables:
242  * mode: c
243  * indent-tabs-mode: t
244  * c-basic-offset: 4
245  * tab-width: 4
246  * End:
247  */