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