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