dc897b5ad7304efbcc910c454a3ef2244939a6c2
[cacao.git] / src / vm / exceptions.c
1 /* src/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    Changes:
30
31    $Id: exceptions.c 3264 2005-09-21 20:18:24Z twisti $
32
33 */
34
35
36 #include <string.h>
37 #include <stdarg.h>
38 #include <stdlib.h>
39
40 #include "config.h"
41
42 #include "mm/memory.h"
43 #include "native/native.h"
44 #include "native/include/java_lang_String.h"
45 #include "native/include/java_lang_Throwable.h"
46 #include "toolbox/logging.h"
47 #include "toolbox/util.h"
48 #include "vm/class.h"
49 #include "vm/exceptions.h"
50 #include "vm/global.h"
51 #include "vm/loader.h"
52 #include "vm/options.h"
53 #include "vm/stringlocal.h"
54 #include "vm/tables.h"
55 #include "vm/jit/asmpart.h"
56 #include "vm/jit/jit.h"
57
58
59 /* for raising exceptions from native methods *********************************/
60
61 #if !defined(USE_THREADS) || !defined(NATIVE_THREADS)
62 java_objectheader *_no_threads_exceptionptr = NULL;
63 #endif
64
65
66 /* init_system_exceptions ******************************************************
67
68    Load and link exceptions used in the system.
69
70 *******************************************************************************/
71
72 bool exceptions_init(void)
73 {
74         /* java/lang/Throwable */
75
76         if (!(class_java_lang_Throwable =
77                   load_class_bootstrap(utf_java_lang_Throwable)) ||
78                 !link_class(class_java_lang_Throwable))
79                 return false;
80
81
82         /* java/lang/VMThrowable */
83
84         if (!(class_java_lang_VMThrowable =
85                   load_class_bootstrap(utf_java_lang_VMThrowable)) ||
86                 !link_class(class_java_lang_VMThrowable))
87                 return false;
88
89
90         /* java/lang/Error */
91
92         if (!(class_java_lang_Error = load_class_bootstrap(utf_java_lang_Error)) ||
93                 !link_class(class_java_lang_Error))
94                 return false;
95
96
97         /* java/lang/Exception */
98
99         if (!(class_java_lang_Exception =
100                   load_class_bootstrap(utf_java_lang_Exception)) ||
101                 !link_class(class_java_lang_Exception))
102                 return false;
103
104
105         /* java/lang/NoClassDefFoundError */
106
107         if (!(class_java_lang_NoClassDefFoundError =
108                   load_class_bootstrap(utf_java_lang_NoClassDefFoundError)) ||
109                 !link_class(class_java_lang_NoClassDefFoundError))
110                 return false;
111
112
113         /* java/lang/OutOfMemoryError */
114
115         if (!(class_java_lang_OutOfMemoryError =
116                   load_class_bootstrap(utf_java_lang_OutOfMemoryError)) ||
117                 !link_class(class_java_lang_OutOfMemoryError))
118                 return false;
119
120
121         /* java/lang/ClassNotFoundException */
122
123         if (!(class_java_lang_ClassNotFoundException =
124                   load_class_bootstrap(utf_java_lang_ClassNotFoundException)) ||
125                 !link_class(class_java_lang_ClassNotFoundException))
126                 return false;
127
128         return true;
129 }
130
131
132 static void throw_exception_exit_intern(bool doexit)
133 {
134         java_objectheader *xptr;
135         classinfo *c;
136         methodinfo *pss;
137
138         xptr = *exceptionptr;
139
140         if (xptr) {
141                 /* clear exception, because we are calling jit code again */
142                 *exceptionptr = NULL;
143
144                 c = xptr->vftbl->class;
145
146                 pss = class_resolveclassmethod(c,
147                                                                            utf_printStackTrace,
148                                                                            utf_void__void,
149                                                                            class_java_lang_Object,
150                                                                            false);
151
152                 /* print the stacktrace */
153                 if (pss) {
154                         asm_calljavafunction(pss, xptr, NULL, NULL, NULL);
155
156                         /* This normally means, we are EXTREMLY out of memory or have a   */
157                         /* serious problem while printStackTrace. But may be another      */
158                         /* exception, so print it.                                        */
159
160                         if (*exceptionptr) {
161                                 java_lang_Throwable *t;
162
163                                 t = (java_lang_Throwable *) *exceptionptr;
164
165                                 fprintf(stderr, "Exception while printStackTrace(): ");
166                                 utf_fprint_classname(stderr, t->header.vftbl->class->name);
167
168                                 if (t->detailMessage) {
169                                         char *buf;
170
171                                         buf = javastring_tochar((java_objectheader *) t->detailMessage);
172                                         fprintf(stderr, ": %s", buf);
173                                         MFREE(buf, char, strlen(buf));
174                                 }
175                                         
176                                 fprintf(stderr, "\n");
177                         }
178
179                 } else {
180                         utf_fprint_classname(stderr, c->name);
181                         fprintf(stderr, ": printStackTrace()V not found!\n");
182                 }
183
184                 fflush(stderr);
185
186                 /* good bye! */
187
188                 if (doexit)
189                         exit(1);
190         }
191 }
192
193
194 void throw_exception(void)
195 {
196         throw_exception_exit_intern(false);
197 }
198
199
200 void throw_exception_exit(void)
201 {
202         throw_exception_exit_intern(true);
203 }
204
205
206 void throw_main_exception(void)
207 {
208         fprintf(stderr, "Exception in thread \"main\" ");
209         fflush(stderr);
210
211         throw_exception_exit_intern(false);
212 }
213
214
215 void throw_main_exception_exit(void)
216 {
217         fprintf(stderr, "Exception in thread \"main\" ");
218         fflush(stderr);
219
220         throw_exception_exit_intern(true);
221 }
222
223
224 void throw_cacao_exception_exit(const char *exception, const char *message, ...)
225 {
226         s4 i;
227         char *tmp;
228         s4 len;
229         va_list ap;
230
231         len = strlen(exception);
232         tmp = MNEW(char, len + 1);
233         strncpy(tmp, exception, len);
234         tmp[len] = '\0';
235
236         /* convert to classname */
237
238         for (i = len - 1; i >= 0; i--)
239                 if (tmp[i] == '/') tmp[i] = '.';
240
241         fprintf(stderr, "Exception in thread \"main\" %s", tmp);
242
243         MFREE(tmp, char, len);
244
245         if (strlen(message) > 0) {
246                 fprintf(stderr, ": ");
247
248                 va_start(ap, message);
249                 vfprintf(stderr, message, ap);
250                 va_end(ap);
251         }
252
253         fprintf(stderr, "\n");
254         fflush(stderr);
255
256         /* good bye! */
257
258         exit(1);
259 }
260
261
262 /* new_exception ***************************************************************
263
264    Creates an exception object with the given name and initalizes it.
265
266 *******************************************************************************/
267
268 java_objectheader *new_exception(const char *classname)
269 {
270         java_objectheader *o;
271         classinfo         *c;
272
273         if (!(c = load_class_bootstrap(utf_new_char(classname))))
274                 return *exceptionptr;
275
276         o = native_new_and_init(c);
277
278         if (!o)
279                 return *exceptionptr;
280
281         return o;
282 }
283
284
285 /* new_exception_message *******************************************************
286
287    Creates an exception object with the given name and initalizes it
288    with the given char message.
289
290 *******************************************************************************/
291
292 java_objectheader *new_exception_message(const char *classname,
293                                                                                  const char *message)
294 {
295         java_objectheader *o;
296         classinfo         *c;
297    
298         if (!(c = load_class_bootstrap(utf_new_char(classname))))
299                 return *exceptionptr;
300
301         o = native_new_and_init_string(c, javastring_new_char(message));
302
303         if (!o)
304                 return *exceptionptr;
305
306         return o;
307 }
308
309
310 /* new_exception_throwable *****************************************************
311
312    Creates an exception object with the given name and initalizes it
313    with the given java/lang/Throwable exception.
314
315 *******************************************************************************/
316
317 java_objectheader *new_exception_throwable(const char *classname,
318                                                                                    java_lang_Throwable *throwable)
319 {
320         java_objectheader *o;
321         classinfo         *c;
322    
323         if (!(c = load_class_bootstrap(utf_new_char(classname))))
324                 return *exceptionptr;
325
326         o = native_new_and_init_throwable(c, throwable);
327
328         if (!o)
329                 return *exceptionptr;
330
331         return o;
332 }
333
334
335 /* new_exception_utfmessage ****************************************************
336
337    Creates an exception object with the given name and initalizes it
338    with the given utf message.
339
340 *******************************************************************************/
341
342 java_objectheader *new_exception_utfmessage(const char *classname, utf *message)
343 {
344         java_objectheader *o;
345         classinfo         *c;
346    
347         if (!(c = load_class_bootstrap(utf_new_char(classname))))
348                 return *exceptionptr;
349
350         o = native_new_and_init_string(c, javastring_new(message));
351
352         if (!o)
353                 return *exceptionptr;
354
355         return o;
356 }
357
358
359 /* new_exception_javastring ****************************************************
360
361    Creates an exception object with the given name and initalizes it
362    with the given java/lang/String message.
363
364 *******************************************************************************/
365
366 java_objectheader *new_exception_javastring(const char *classname,
367                                                                                         java_lang_String *message)
368 {
369         java_objectheader *o;
370         classinfo         *c;
371    
372         if (!(c = load_class_bootstrap(utf_new_char(classname))))
373                 return *exceptionptr;
374
375         o = native_new_and_init_string(c, message);
376
377         if (!o)
378                 return *exceptionptr;
379
380         return o;
381 }
382
383
384 /* new_exception_int ***********************************************************
385
386    Creates an exception object with the given name and initalizes it
387    with the given int value.
388
389 *******************************************************************************/
390
391 java_objectheader *new_exception_int(const char *classname, s4 i)
392 {
393         java_objectheader *o;
394         classinfo         *c;
395    
396         if (!(c = load_class_bootstrap(utf_new_char(classname))))
397                 return *exceptionptr;
398
399         o = native_new_and_init_int(c, i);
400
401         if (!o)
402                 return *exceptionptr;
403
404         return o;
405 }
406
407
408 /* new_classformaterror ********************************************************
409
410    generates a java.lang.ClassFormatError for the classloader
411
412 *******************************************************************************/
413
414 java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
415 {
416         java_objectheader *o;
417         char              *msg;
418         s4                 msglen;
419         va_list            ap;
420
421         /* calculate message length */
422
423         msglen = 0;
424
425         if (c)
426                 msglen += utf_strlen(c->name) + strlen(" (");
427
428         va_start(ap, message);
429         msglen += get_variable_message_length(message, ap);
430         va_end(ap);
431
432         if (c)
433                 msglen += strlen(")");
434
435         msglen += strlen("0");
436
437         /* allocate a buffer */
438
439         msg = MNEW(char, msglen);
440
441         /* print message into allocated buffer */
442
443         if (c) {
444                 utf_sprint_classname(msg, c->name);
445                 strcat(msg, " (");
446         }
447
448         va_start(ap, message);
449         vsprintf(msg + strlen(msg), message, ap);
450         va_end(ap);
451
452         if (c)
453                 strcat(msg, ")");
454
455         o = new_exception_message(string_java_lang_ClassFormatError, msg);
456
457         MFREE(msg, char, msglen);
458
459         return o;
460 }
461
462
463 /* new_classnotfoundexception **************************************************
464
465    Generates a java.lang.ClassNotFoundException for the classloader.
466
467 *******************************************************************************/
468
469 java_objectheader *new_classnotfoundexception(utf *name)
470 {
471         java_objectheader *o;
472
473         o = native_new_and_init_string(class_java_lang_ClassNotFoundException,
474                                                                    javastring_new(name));
475
476         if (!o)
477                 return *exceptionptr;
478
479         return o;
480 }
481
482
483 /* new_internalerror ***********************************************************
484
485    Generates a java.lang.InternalError for the VM.
486
487 *******************************************************************************/
488
489 java_objectheader *new_internalerror(const char *message, ...)
490 {
491         java_objectheader *o;
492         va_list            ap;
493         char              *msg;
494         s4                 msglen;
495
496         /* calculate exception message length */
497
498         va_start(ap, message);
499         msglen = get_variable_message_length(message, ap);
500         va_end(ap);
501
502         /* allocate memory */
503
504         msg = MNEW(char, msglen);
505
506         /* generate message */
507
508         va_start(ap, message);
509         vsprintf(msg, message, ap);
510         va_end(ap);
511
512         /* create exception object */
513
514         o = new_exception_message(string_java_lang_InternalError, msg);
515
516         /* free memory */
517
518         MFREE(msg, char, msglen);
519
520         return o;
521 }
522
523
524 /* new_unsupportedclassversionerror ********************************************
525
526    generates a java.lang.UnsupportedClassVersionError for the classloader
527
528 *******************************************************************************/
529
530 java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *message, ...)
531 {
532         java_objectheader *o;
533         va_list            ap;
534         char              *msg;
535     s4                 msglen;
536
537         /* calculate exception message length */
538
539         msglen = utf_strlen(c->name) + strlen(" (") + strlen(")") + strlen("0");
540
541         va_start(ap, message);
542         msglen += get_variable_message_length(message, ap);
543         va_end(ap);
544
545         /* allocate memory */
546
547         msg = MNEW(char, msglen);
548
549         /* generate message */
550
551         utf_sprint_classname(msg, c->name);
552         strcat(msg, " (");
553
554         va_start(ap, message);
555         vsprintf(msg + strlen(msg), message, ap);
556         va_end(ap);
557
558         strcat(msg, ")");
559
560         /* create exception object */
561
562         o = new_exception_message(string_java_lang_UnsupportedClassVersionError,
563                                                           msg);
564
565         /* free memory */
566
567         MFREE(msg, char, msglen);
568
569         return o;
570 }
571
572
573 /* new_verifyerror *************************************************************
574
575    generates a java.lang.VerifyError for the jit compiler
576
577 *******************************************************************************/
578
579 java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
580 {
581         java_objectheader *o;
582         va_list            ap;
583         char              *msg;
584         s4                 msglen;
585
586         useinlining = false; /* at least until sure inlining works with exceptions*/
587
588         /* calculate exception message length */
589
590         msglen = strlen("(class: ") + utf_strlen(m->class->name) +
591                 strlen(", method: ") + utf_strlen(m->name) +
592                 strlen(" signature: ") + utf_strlen(m->descriptor) +
593                 strlen(") ") + strlen("0");
594
595         va_start(ap, message);
596         msglen += get_variable_message_length(message, ap);
597         va_end(ap);
598
599         /* allocate memory */
600
601         msg = MNEW(char, msglen);
602
603         /* generate message */
604
605         strcpy(msg, "(class: ");
606         utf_strcat(msg, m->class->name);
607         strcat(msg, ", method: ");
608         utf_strcat(msg, m->name);
609         strcat(msg, " signature: ");
610         utf_strcat(msg, m->descriptor);
611         strcat(msg, ") ");
612
613         va_start(ap, message);
614         vsprintf(msg + strlen(msg), message, ap);
615         va_end(ap);
616
617         /* create exception object */
618
619         o = new_exception_message(string_java_lang_VerifyError, msg);
620
621         /* free memory */
622
623         MFREE(msg, char, msglen);
624
625         return o;
626 }
627
628
629 /* new_arithmeticexception *****************************************************
630
631    Generates a java.lang.ArithmeticException for the jit compiler.
632
633 *******************************************************************************/
634
635 java_objectheader *new_arithmeticexception(void)
636 {
637         java_objectheader *e;
638
639         e = new_exception_message(string_java_lang_ArithmeticException,
640                                                           string_java_lang_ArithmeticException_message);
641
642         if (!e)
643                 return *exceptionptr;
644
645         return e;
646 }
647
648
649 /* new_arrayindexoutofboundsexception ******************************************
650
651    Generates a java.lang.ArrayIndexOutOfBoundsException for the JIT
652    compiler.
653
654 *******************************************************************************/
655
656 java_objectheader *new_arrayindexoutofboundsexception(s4 index)
657 {
658         java_objectheader *e;
659         methodinfo *m;
660         java_lang_String *s;
661
662         /* convert the index into a String, like Sun does */
663
664         m = class_resolveclassmethod(class_java_lang_String,
665                                                                  utf_new_char("valueOf"),
666                                                                  utf_new_char("(I)Ljava/lang/String;"),
667                                                                  class_java_lang_Object,
668                                                                  true);
669
670         if (!m)
671                 return *exceptionptr;
672
673         s = (java_lang_String *) asm_calljavafunction(m,
674                                                                                                   (void *) (ptrint) index,
675                                                                                                   NULL,
676                                                                                                   NULL,
677                                                                                                   NULL);
678
679         if (!s)
680                 return *exceptionptr;
681
682         e = new_exception_javastring(string_java_lang_ArrayIndexOutOfBoundsException,
683                                                                  s);
684
685         if (!e)
686                 return *exceptionptr;
687
688         return e;
689 }
690
691
692 /* new_arraystoreexception *****************************************************
693
694    generates a java.lang.ArrayStoreException for the jit compiler
695
696 *******************************************************************************/
697
698 java_objectheader *new_arraystoreexception(void)
699 {
700         java_objectheader *e;
701
702         e = new_exception(string_java_lang_ArrayStoreException);
703
704         if (!e)
705                 return *exceptionptr;
706
707         return e;
708 }
709
710
711 /* new_classcastexception ******************************************************
712
713    generates a java.lang.ClassCastException for the jit compiler
714
715 *******************************************************************************/
716
717 java_objectheader *new_classcastexception(void)
718 {
719         java_objectheader *e;
720
721         e = new_exception(string_java_lang_ClassCastException);
722
723         if (!e)
724                 return *exceptionptr;
725
726         return e;
727 }
728
729
730 /* new_negativearraysizeexception **********************************************
731
732    generates a java.lang.NegativeArraySizeException for the jit compiler
733
734 *******************************************************************************/
735
736 java_objectheader *new_negativearraysizeexception(void)
737 {
738         java_objectheader *e;
739
740         e = new_exception(string_java_lang_NegativeArraySizeException);
741
742         if (!e)
743                 return *exceptionptr;
744
745         return e;
746 }
747
748
749 /* new_nullpointerexception ****************************************************
750
751    generates a java.lang.NullPointerException for the jit compiler
752
753 *******************************************************************************/
754
755 java_objectheader *new_nullpointerexception(void)
756 {
757         java_objectheader *e;
758
759         e = new_exception(string_java_lang_NullPointerException);
760
761         if (!e)
762                 return *exceptionptr;
763
764         return e;
765 }
766
767
768 /*
769  * These are local overrides for various environment variables in Emacs.
770  * Please do not remove this and leave it at the end of the file, where
771  * Emacs will automagically detect them.
772  * ---------------------------------------------------------------------
773  * Local variables:
774  * mode: c
775  * indent-tabs-mode: t
776  * c-basic-offset: 4
777  * tab-width: 4
778  * End:
779  */