Save.
[cacao.git] / src / vm / exceptions.c
1 /* vm/exceptions.c - exception related functions
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Christian Thalinger
28
29    $Id: exceptions.c 1935 2005-02-10 11:01:26Z twisti $
30
31 */
32
33
34 #include <string.h>
35 #include <stdarg.h>
36 #include <stdlib.h>
37
38 #include "config.h"
39
40 #include "mm/memory.h"
41 #include "native/native.h"
42 #include "native/include/java_lang_String.h"
43 #include "native/include/java_lang_Throwable.h"
44 #include "toolbox/logging.h"
45 #include "vm/class.h"
46 #include "vm/exceptions.h"
47 #include "vm/global.h"
48 #include "vm/loader.h"
49 #include "vm/options.h"
50 #include "vm/stringlocal.h"
51 #include "vm/tables.h"
52 #include "vm/jit/asmpart.h"
53 #include "vm/jit/jit.h"
54
55
56 /* for raising exceptions from native methods */
57
58 #if !defined(USE_THREADS) || !defined(NATIVE_THREADS)
59 java_objectheader* _exceptionptr = NULL;
60 #endif
61
62
63 /* exception/error super class */
64
65 const char *string_java_lang_Throwable =
66     "java/lang/Throwable";
67
68 const char *string_java_lang_VMThrowable =
69     "java/lang/VMThrowable";
70
71
72 /* specify some exception strings for code generation */
73
74 const char *string_java_lang_ArithmeticException =
75     "java/lang/ArithmeticException";
76
77 const char *string_java_lang_ArithmeticException_message =
78     "/ by zero";
79
80 const char *string_java_lang_ArrayIndexOutOfBoundsException =
81     "java/lang/ArrayIndexOutOfBoundsException";
82
83 const char *string_java_lang_ArrayStoreException =
84     "java/lang/ArrayStoreException";
85
86 const char *string_java_lang_ClassCastException =
87     "java/lang/ClassCastException";
88
89 const char *string_java_lang_ClassNotFoundException =
90         "java/lang/ClassNotFoundException";
91
92 const char *string_java_lang_CloneNotSupportedException =
93     "java/lang/CloneNotSupportedException";
94
95 const char *string_java_lang_Exception =
96     "java/lang/Exception";
97
98 const char *string_java_lang_IllegalAccessException =
99     "java/lang/IllegalAccessException";
100
101 const char *string_java_lang_IllegalArgumentException =
102     "java/lang/IllegalArgumentException";
103
104 const char *string_java_lang_IllegalMonitorStateException =
105     "java/lang/IllegalMonitorStateException";
106
107 const char *string_java_lang_IndexOutOfBoundsException =
108     "java/lang/IndexOutOfBoundsException";
109
110 const char *string_java_lang_InstantiationException =
111     "java/lang/InstantiationException";
112
113 const char *string_java_lang_InterruptedException =
114     "java/lang/InterruptedException";
115
116 const char *string_java_lang_NegativeArraySizeException =
117     "java/lang/NegativeArraySizeException";
118
119 const char *string_java_lang_NoSuchFieldException =
120         "java/lang/NoSuchFieldException";
121
122 const char *string_java_lang_NoSuchMethodException =
123         "java/lang/NoSuchMethodException";
124
125 const char *string_java_lang_NullPointerException =
126     "java/lang/NullPointerException";
127
128
129 /* specify some error strings for code generation */
130
131 const char *string_java_lang_AbstractMethodError =
132     "java/lang/AbstractMethodError";
133
134 const char *string_java_lang_ClassCircularityError =
135     "java/lang/ClassCircularityError";
136
137 const char *string_java_lang_ClassFormatError =
138     "java/lang/ClassFormatError";
139
140 const char *string_java_lang_Error =
141     "java/lang/Error";
142
143 const char *string_java_lang_ExceptionInInitializerError =
144     "java/lang/ExceptionInInitializerError";
145
146 const char *string_java_lang_IncompatibleClassChangeError =
147     "java/lang/IncompatibleClassChangeError";
148
149 const char *string_java_lang_InternalError =
150     "java/lang/InternalError";
151
152 const char *string_java_lang_LinkageError =
153     "java/lang/LinkageError";
154
155 const char *string_java_lang_NoClassDefFoundError =
156     "java/lang/NoClassDefFoundError";
157
158 const char *string_java_lang_NoSuchFieldError =
159         "java/lang/NoSuchFieldError";
160
161 const char *string_java_lang_NoSuchMethodError =
162         "java/lang/NoSuchMethodError";
163
164 const char *string_java_lang_OutOfMemoryError =
165     "java/lang/OutOfMemoryError";
166
167 const char *string_java_lang_UnsupportedClassVersionError =
168     "java/lang/UnsupportedClassVersionError";
169
170 const char *string_java_lang_VerifyError =
171     "java/lang/VerifyError";
172
173 const char *string_java_lang_VirtualMachineError =
174     "java/lang/VirtualMachineError";
175
176
177 /* init_system_exceptions ******************************************************
178
179    Load and link exceptions used in the system.
180
181 *******************************************************************************/
182
183 bool exceptions_init(void)
184 {
185         /* java/lang/Throwable */
186
187         if (!class_load(class_java_lang_Throwable) ||
188                 !class_link(class_java_lang_Throwable))
189                 return false;
190
191
192         /* java/lang/Exception */
193
194         if (!class_load(class_java_lang_Exception) ||
195                 !class_link(class_java_lang_Exception))
196                 return false;
197
198
199         /* java/lang/Error */
200
201         if (!class_load(class_java_lang_Error) ||
202                 !class_link(class_java_lang_Error))
203                 return false;
204
205
206         /* java/lang/OutOfMemoryError */
207
208         if (!class_load(class_java_lang_OutOfMemoryError) ||
209                 !class_link(class_java_lang_OutOfMemoryError))
210                 return false;
211
212         return true;
213 }
214
215
216 static void throw_exception_exit_intern(bool doexit)
217 {
218         java_objectheader *xptr;
219         classinfo *c;
220         methodinfo *pss;
221
222         xptr = *exceptionptr;
223
224         if (xptr) {
225                 /* clear exception, because we are calling jit code again */
226                 *exceptionptr = NULL;
227
228                 c = xptr->vftbl->class;
229
230                 pss = class_resolveclassmethod(c,
231                                                                            utf_printStackTrace,
232                                                                            utf_void__void,
233                                                                            class_java_lang_Object,
234                                                                            false);
235
236                 /* print the stacktrace */
237                 if (pss) {
238                         asm_calljavafunction(pss, xptr, NULL, NULL, NULL);
239
240                         /* this normally means, we are EXTREMLY out of memory, but may be
241                            any other exception */
242                         if (*exceptionptr) {
243                                 utf_fprint_classname(stderr, c->name);
244                                 fprintf(stderr, "\n");
245                         }
246
247                 } else {
248                         utf_fprint_classname(stderr, c->name);
249                         fprintf(stderr, ": printStackTrace()V not found!\n");
250                 }
251
252                 fflush(stderr);
253
254                 /* good bye! */
255
256                 if (doexit)
257                         exit(1);
258         }
259 }
260
261
262 void throw_exception()
263 {
264         throw_exception_exit_intern(false);
265 }
266
267
268 void throw_exception_exit()
269 {
270         throw_exception_exit_intern(true);
271 }
272
273
274 void throw_main_exception()
275 {
276         fprintf(stderr, "Exception in thread \"main\" ");
277         fflush(stderr);
278
279         throw_exception_exit_intern(false);
280 }
281
282
283 void throw_main_exception_exit()
284 {
285         fprintf(stderr, "Exception in thread \"main\" ");
286         fflush(stderr);
287
288         throw_exception_exit_intern(true);
289 }
290
291
292 void throw_cacao_exception_exit(const char *exception, const char *message, ...)
293 {
294         s4 i;
295         char *tmp;
296         s4 len;
297         va_list ap;
298
299         len = strlen(exception);
300         tmp = MNEW(char, len + 1);
301         strncpy(tmp, exception, len);
302         tmp[len] = '\0';
303
304         /* convert to classname */
305
306         for (i = len - 1; i >= 0; i--)
307                 if (tmp[i] == '/') tmp[i] = '.';
308
309         fprintf(stderr, "Exception in thread \"main\" %s", tmp);
310
311         MFREE(tmp, char, len);
312
313         if (strlen(message) > 0) {
314                 fprintf(stderr, ": ");
315
316                 va_start(ap, message);
317                 vfprintf(stderr, message, ap);
318                 va_end(ap);
319         }
320
321         fprintf(stderr, "\n");
322         fflush(stderr);
323
324         /* good bye! */
325
326         exit(1);
327 }
328
329
330 java_objectheader *new_exception(const char *classname)
331 {
332         classinfo *c = class_new(utf_new_char(classname));
333
334         return native_new_and_init(c);
335 }
336
337 java_objectheader *new_exception_message(const char *classname, const char *message)
338 {
339         classinfo *c = class_new(utf_new_char(classname));
340
341         return native_new_and_init_string(c, javastring_new_char(message));
342 }
343
344
345 java_objectheader *new_exception_throwable(const char *classname, java_lang_Throwable *throwable)
346 {
347         classinfo *c = class_new(utf_new_char(classname));
348
349         return native_new_and_init_throwable(c, throwable);
350 }
351
352
353 java_objectheader *new_exception_utfmessage(const char *classname, utf *message)
354 {
355         classinfo *c = class_new(utf_new_char(classname));
356
357         return native_new_and_init_string(c, javastring_new(message));
358 }
359
360
361 java_objectheader *new_exception_javastring(const char *classname, java_lang_String *message)
362 {
363         classinfo *c = class_new(utf_new_char(classname));
364
365         return native_new_and_init_string(c, message);
366 }
367
368
369 java_objectheader *new_exception_int(const char *classname, s4 i)
370 {
371         classinfo *c;
372
373         c = class_new(utf_new_char(classname));
374
375         return native_new_and_init_int(c, i);
376 }
377
378
379 /* new_classformaterror ********************************************************
380
381    generates a java.lang.ClassFormatError for the classloader
382
383 *******************************************************************************/
384
385 java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
386 {
387         char msg[MAXLOGTEXT];
388         va_list ap;
389
390         utf_sprint_classname(msg, c->name);
391         sprintf(msg + strlen(msg), " (");
392
393         va_start(ap, message);
394         vsprintf(msg + strlen(msg), message, ap);
395         va_end(ap);
396
397         sprintf(msg + strlen(msg), ")");
398
399         return new_exception_message(string_java_lang_ClassFormatError, msg);
400 }
401
402
403 /* new_unsupportedclassversionerror ********************************************
404
405    generates a java.lang.UnsupportedClassVersionError for the classloader
406
407 *******************************************************************************/
408
409 java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *message, ...)
410 {
411         char msg[MAXLOGTEXT];
412         va_list ap;
413
414         utf_sprint_classname(msg, c->name);
415         sprintf(msg + strlen(msg), " (");
416
417         va_start(ap, message);
418         vsprintf(msg + strlen(msg), message, ap);
419         va_end(ap);
420
421         sprintf(msg + strlen(msg), ")");
422
423         return new_exception_message(string_java_lang_UnsupportedClassVersionError,
424                                                                  msg);
425 }
426
427
428 /* new_verifyerror *************************************************************
429
430    generates a java.lang.VerifyError for the jit compiler
431
432 *******************************************************************************/
433
434 java_objectheader *new_verifyerror(methodinfo *m, const char *message)
435 {
436         java_objectheader *o;
437         char *msg;
438         s4 len;
439
440         useinlining = false; /* at least until sure inlining works with exceptions*/
441         len = 8 + utf_strlen(m->class->name) +
442                 10 + utf_strlen(m->name) +
443                 13 + utf_strlen(m->descriptor) +
444                 2 + strlen(message) + 1;
445                 
446         msg = MNEW(char, len);
447
448         sprintf(msg, "(class: ");
449         utf_sprint(msg + strlen(msg), m->class->name);
450         sprintf(msg + strlen(msg), ", method: ");
451         utf_sprint(msg + strlen(msg), m->name);
452         sprintf(msg + strlen(msg), ", signature: ");
453         utf_sprint(msg + strlen(msg), m->descriptor);
454         sprintf(msg + strlen(msg), ") %s", message);
455
456         o = new_exception_message(string_java_lang_VerifyError, msg);
457
458         MFREE(msg, u1, len);
459
460         return o;
461 }
462
463
464 /* new_arithmeticexception *****************************************************
465
466    generates a java.lang.ArithmeticException for the jit compiler
467
468 *******************************************************************************/
469
470 java_objectheader *new_arithmeticexception()
471 {
472         java_objectheader *e;
473
474         e = new_exception_message(string_java_lang_ArithmeticException,
475                                                           string_java_lang_ArithmeticException_message);
476
477         if (!e)
478                 return *exceptionptr;
479
480         return e;
481 }
482
483
484 /* new_arrayindexoutofboundsexception ******************************************
485
486    generates a java.lang.ArrayIndexOutOfBoundsException for the jit compiler
487
488 *******************************************************************************/
489
490 java_objectheader *new_arrayindexoutofboundsexception(s4 index)
491 {
492         java_objectheader *e;
493         methodinfo *m;
494         java_lang_String *s;
495
496         /* convert the index into a String, like Sun does */
497
498         m = class_resolveclassmethod(class_java_lang_String,
499                                                                  utf_new_char("valueOf"),
500                                                                  utf_new_char("(I)Ljava/lang/String;"),
501                                                                  class_java_lang_Object,
502                                                                  true);
503
504         if (!m)
505                 return *exceptionptr;
506
507         s = (java_lang_String *) asm_calljavafunction(m,
508 #if POINTERSIZE == 8
509                                                                                                   (void *) (s8) index,
510 #else
511                                                                                                   (void *) index,
512 #endif
513                                                                                                   NULL,
514                                                                                                   NULL,
515                                                                                                   NULL);
516
517         if (!s)
518                 return *exceptionptr;
519
520         e = new_exception_javastring(string_java_lang_ArrayIndexOutOfBoundsException,
521                                                                  s);
522
523         if (!e)
524                 return *exceptionptr;
525
526         return e;
527 }
528
529
530 /* new_arraystoreexception *****************************************************
531
532    generates a java.lang.ArrayStoreException for the jit compiler
533
534 *******************************************************************************/
535
536 java_objectheader *new_arraystoreexception()
537 {
538         java_objectheader *e;
539
540         e = new_exception(string_java_lang_ArrayStoreException);
541
542         if (!e)
543                 return *exceptionptr;
544
545         return e;
546 }
547
548
549 /* new_classcastexception ******************************************************
550
551    generates a java.lang.ClassCastException for the jit compiler
552
553 *******************************************************************************/
554
555 java_objectheader *new_classcastexception()
556 {
557         java_objectheader *e;
558
559         e = new_exception(string_java_lang_ClassCastException);
560
561         if (!e)
562                 return *exceptionptr;
563
564         return e;
565 }
566
567
568 /* new_negativearraysizeexception **********************************************
569
570    generates a java.lang.NegativeArraySizeException for the jit compiler
571
572 *******************************************************************************/
573
574 java_objectheader *new_negativearraysizeexception()
575 {
576         java_objectheader *e;
577
578         e = new_exception(string_java_lang_NegativeArraySizeException);
579
580         if (!e)
581                 return *exceptionptr;
582
583         return e;
584 }
585
586
587 /* new_nullpointerexception ****************************************************
588
589    generates a java.lang.NullPointerException for the jit compiler
590
591 *******************************************************************************/
592
593 java_objectheader *new_nullpointerexception()
594 {
595         java_objectheader *e;
596
597         e = new_exception(string_java_lang_NullPointerException);
598
599         if (!e)
600                 return *exceptionptr;
601
602         return e;
603 }
604
605
606 /*
607  * These are local overrides for various environment variables in Emacs.
608  * Please do not remove this and leave it at the end of the file, where
609  * Emacs will automagically detect them.
610  * ---------------------------------------------------------------------
611  * Local variables:
612  * mode: c
613  * indent-tabs-mode: t
614  * c-basic-offset: 4
615  * tab-width: 4
616  * End:
617  */