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