Comment added why integer return register is not precoloured
[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: Edwin Steiner
30
31    $Id: exceptions.c 3547 2005-11-03 20:38:59Z 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         /* java/lang/NoClassDefFoundError */
97
98         if (!(class_java_lang_NoClassDefFoundError =
99                   load_class_bootstrap(utf_java_lang_NoClassDefFoundError)) ||
100                 !link_class(class_java_lang_NoClassDefFoundError))
101                 return false;
102
103         /* java/lang/OutOfMemoryError */
104
105         if (!(class_java_lang_OutOfMemoryError =
106                   load_class_bootstrap(utf_java_lang_OutOfMemoryError)) ||
107                 !link_class(class_java_lang_OutOfMemoryError))
108                 return false;
109
110
111         /* java/lang/Exception */
112
113         if (!(class_java_lang_Exception =
114                   load_class_bootstrap(utf_java_lang_Exception)) ||
115                 !link_class(class_java_lang_Exception))
116                 return false;
117
118         /* java/lang/ClassNotFoundException */
119
120         if (!(class_java_lang_ClassNotFoundException =
121                   load_class_bootstrap(utf_java_lang_ClassNotFoundException)) ||
122                 !link_class(class_java_lang_ClassNotFoundException))
123                 return false;
124
125         /* java/lang/IllegalArgumentException */
126
127         if (!(class_java_lang_IllegalArgumentException =
128                   load_class_bootstrap(utf_java_lang_IllegalArgumentException)) ||
129                 !link_class(class_java_lang_IllegalArgumentException))
130                 return false;
131
132         /* java/lang/IllegalMonitorStateException */
133
134         if (!(class_java_lang_IllegalMonitorStateException =
135                   load_class_bootstrap(utf_java_lang_IllegalMonitorStateException)) ||
136                 !link_class(class_java_lang_IllegalMonitorStateException))
137                 return false;
138
139         /* java/lang/NullPointerException */
140
141         if (!(class_java_lang_NullPointerException =
142                   load_class_bootstrap(utf_java_lang_NullPointerException)) ||
143                 !link_class(class_java_lang_NullPointerException))
144                 return false;
145
146
147         return true;
148 }
149
150
151 static void throw_exception_exit_intern(bool doexit)
152 {
153         java_objectheader *xptr;
154         classinfo *c;
155         methodinfo *pss;
156
157         xptr = *exceptionptr;
158
159         if (xptr) {
160                 /* clear exception, because we are calling jit code again */
161                 *exceptionptr = NULL;
162
163                 c = xptr->vftbl->class;
164
165                 pss = class_resolveclassmethod(c,
166                                                                            utf_printStackTrace,
167                                                                            utf_void__void,
168                                                                            class_java_lang_Object,
169                                                                            false);
170
171                 /* print the stacktrace */
172                 if (pss) {
173                         asm_calljavafunction(pss, xptr, NULL, NULL, NULL);
174
175                         /* This normally means, we are EXTREMLY out of memory or have a   */
176                         /* serious problem while printStackTrace. But may be another      */
177                         /* exception, so print it.                                        */
178
179                         if (*exceptionptr) {
180                                 java_lang_Throwable *t;
181
182                                 t = (java_lang_Throwable *) *exceptionptr;
183
184                                 fprintf(stderr, "Exception while printStackTrace(): ");
185                                 utf_fprint_classname(stderr, t->header.vftbl->class->name);
186
187                                 if (t->detailMessage) {
188                                         char *buf;
189
190                                         buf = javastring_tochar((java_objectheader *) t->detailMessage);
191                                         fprintf(stderr, ": %s", buf);
192                                         MFREE(buf, char, strlen(buf));
193                                 }
194                                         
195                                 fprintf(stderr, "\n");
196                         }
197
198                 } else {
199                         utf_fprint_classname(stderr, c->name);
200                         fprintf(stderr, ": printStackTrace()V not found!\n");
201                 }
202
203                 fflush(stderr);
204
205                 /* good bye! */
206
207                 if (doexit)
208                         exit(1);
209         }
210 }
211
212
213 void throw_exception(void)
214 {
215         throw_exception_exit_intern(false);
216 }
217
218
219 void throw_exception_exit(void)
220 {
221         throw_exception_exit_intern(true);
222 }
223
224
225 void throw_main_exception(void)
226 {
227         fprintf(stderr, "Exception in thread \"main\" ");
228         fflush(stderr);
229
230         throw_exception_exit_intern(false);
231 }
232
233
234 void throw_main_exception_exit(void)
235 {
236         fprintf(stderr, "Exception in thread \"main\" ");
237         fflush(stderr);
238
239         throw_exception_exit_intern(true);
240 }
241
242
243 void throw_cacao_exception_exit(const char *exception, const char *message, ...)
244 {
245         s4 i;
246         char *tmp;
247         s4 len;
248         va_list ap;
249
250         len = strlen(exception);
251         tmp = MNEW(char, len + 1);
252         strncpy(tmp, exception, len);
253         tmp[len] = '\0';
254
255         /* convert to classname */
256
257         for (i = len - 1; i >= 0; i--)
258                 if (tmp[i] == '/') tmp[i] = '.';
259
260         fprintf(stderr, "Exception in thread \"main\" %s", tmp);
261
262         MFREE(tmp, char, len);
263
264         if (strlen(message) > 0) {
265                 fprintf(stderr, ": ");
266
267                 va_start(ap, message);
268                 vfprintf(stderr, message, ap);
269                 va_end(ap);
270         }
271
272         fprintf(stderr, "\n");
273         fflush(stderr);
274
275         /* good bye! */
276
277         exit(1);
278 }
279
280
281 /* new_exception ***************************************************************
282
283    Creates an exception object with the given name and initalizes it.
284
285 *******************************************************************************/
286
287 java_objectheader *new_exception(const char *classname)
288 {
289         java_objectheader *o;
290         classinfo         *c;
291
292         if (!(c = load_class_bootstrap(utf_new_char(classname))))
293                 return *exceptionptr;
294
295         o = native_new_and_init(c);
296
297         if (!o)
298                 return *exceptionptr;
299
300         return o;
301 }
302
303
304 /* new_exception_message *******************************************************
305
306    Creates an exception object with the given name and initalizes it
307    with the given char message.
308
309 *******************************************************************************/
310
311 java_objectheader *new_exception_message(const char *classname,
312                                                                                  const char *message)
313 {
314         java_objectheader *o;
315         classinfo         *c;
316    
317         if (!(c = load_class_bootstrap(utf_new_char(classname))))
318                 return *exceptionptr;
319
320         o = native_new_and_init_string(c, javastring_new_char(message));
321
322         if (!o)
323                 return *exceptionptr;
324
325         return o;
326 }
327
328
329 /* new_exception_throwable *****************************************************
330
331    Creates an exception object with the given name and initalizes it
332    with the given java/lang/Throwable exception.
333
334 *******************************************************************************/
335
336 java_objectheader *new_exception_throwable(const char *classname,
337                                                                                    java_lang_Throwable *throwable)
338 {
339         java_objectheader *o;
340         classinfo         *c;
341    
342         if (!(c = load_class_bootstrap(utf_new_char(classname))))
343                 return *exceptionptr;
344
345         o = native_new_and_init_throwable(c, throwable);
346
347         if (!o)
348                 return *exceptionptr;
349
350         return o;
351 }
352
353
354 /* new_exception_utfmessage ****************************************************
355
356    Creates an exception object with the given name and initalizes it
357    with the given utf message.
358
359 *******************************************************************************/
360
361 java_objectheader *new_exception_utfmessage(const char *classname, utf *message)
362 {
363         java_objectheader *o;
364         classinfo         *c;
365    
366         if (!(c = load_class_bootstrap(utf_new_char(classname))))
367                 return *exceptionptr;
368
369         o = native_new_and_init_string(c, javastring_new(message));
370
371         if (!o)
372                 return *exceptionptr;
373
374         return o;
375 }
376
377
378 /* new_exception_javastring ****************************************************
379
380    Creates an exception object with the given name and initalizes it
381    with the given java/lang/String message.
382
383 *******************************************************************************/
384
385 java_objectheader *new_exception_javastring(const char *classname,
386                                                                                         java_lang_String *message)
387 {
388         java_objectheader *o;
389         classinfo         *c;
390    
391         if (!(c = load_class_bootstrap(utf_new_char(classname))))
392                 return *exceptionptr;
393
394         o = native_new_and_init_string(c, message);
395
396         if (!o)
397                 return *exceptionptr;
398
399         return o;
400 }
401
402
403 /* new_exception_int ***********************************************************
404
405    Creates an exception object with the given name and initalizes it
406    with the given int value.
407
408 *******************************************************************************/
409
410 java_objectheader *new_exception_int(const char *classname, s4 i)
411 {
412         java_objectheader *o;
413         classinfo         *c;
414    
415         if (!(c = load_class_bootstrap(utf_new_char(classname))))
416                 return *exceptionptr;
417
418         o = native_new_and_init_int(c, i);
419
420         if (!o)
421                 return *exceptionptr;
422
423         return o;
424 }
425
426
427 /* new_classformaterror ********************************************************
428
429    generates a java.lang.ClassFormatError for the classloader
430
431 *******************************************************************************/
432
433 java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
434 {
435         java_objectheader *o;
436         char              *msg;
437         s4                 msglen;
438         va_list            ap;
439
440         /* calculate message length */
441
442         msglen = 0;
443
444         if (c)
445                 msglen += utf_strlen(c->name) + strlen(" (");
446
447         va_start(ap, message);
448         msglen += get_variable_message_length(message, ap);
449         va_end(ap);
450
451         if (c)
452                 msglen += strlen(")");
453
454         msglen += strlen("0");
455
456         /* allocate a buffer */
457
458         msg = MNEW(char, msglen);
459
460         /* print message into allocated buffer */
461
462         if (c) {
463                 utf_sprint_classname(msg, c->name);
464                 strcat(msg, " (");
465         }
466
467         va_start(ap, message);
468         vsprintf(msg + strlen(msg), message, ap);
469         va_end(ap);
470
471         if (c)
472                 strcat(msg, ")");
473
474         o = new_exception_message(string_java_lang_ClassFormatError, msg);
475
476         MFREE(msg, char, msglen);
477
478         return o;
479 }
480
481
482 /* new_classnotfoundexception **************************************************
483
484    Generates a java.lang.ClassNotFoundException for the classloader.
485
486 *******************************************************************************/
487
488 java_objectheader *new_classnotfoundexception(utf *name)
489 {
490         java_objectheader *o;
491
492         o = native_new_and_init_string(class_java_lang_ClassNotFoundException,
493                                                                    javastring_new(name));
494
495         if (!o)
496                 return *exceptionptr;
497
498         return o;
499 }
500
501
502 /* new_noclassdeffounderror ****************************************************
503
504    Generates a java.lang.NoClassDefFoundError
505
506 *******************************************************************************/
507
508 java_objectheader *new_noclassdeffounderror(utf *name)
509 {
510         java_objectheader *o;
511
512         o = native_new_and_init_string(class_java_lang_NoClassDefFoundError,
513                                                                    javastring_new(name));
514
515         if (!o)
516                 return *exceptionptr;
517
518         return o;
519 }
520
521
522 /* classnotfoundexception_to_noclassdeffounderror ******************************
523
524    Check the *exceptionptr for a ClassNotFoundException. If it is one,
525    convert it to a NoClassDefFoundError.
526
527 *******************************************************************************/
528
529 void classnotfoundexception_to_noclassdeffounderror(void)
530 {
531         java_objectheader *xptr;
532         java_objectheader *cause;
533
534         /* get the cause */
535
536         cause = *exceptionptr;
537
538         /* convert ClassNotFoundException's to NoClassDefFoundError's */
539
540         if (builtin_instanceof(cause, class_java_lang_ClassNotFoundException)) {
541                 /* clear exception, because we are calling jit code again */
542
543                 *exceptionptr = NULL;
544
545                 /* create new error */
546
547                 xptr =
548                         new_exception_javastring(string_java_lang_NoClassDefFoundError,
549                                         ((java_lang_Throwable *) cause)->detailMessage);
550
551                 /* we had an exception while creating the error */
552
553                 if (*exceptionptr)
554                         return;
555
556                 /* set new exception */
557
558                 *exceptionptr = xptr;
559         }
560 }
561
562
563 /* new_internalerror ***********************************************************
564
565    Generates a java.lang.InternalError for the VM.
566
567 *******************************************************************************/
568
569 java_objectheader *new_internalerror(const char *message, ...)
570 {
571         java_objectheader *o;
572         va_list            ap;
573         char              *msg;
574         s4                 msglen;
575
576         /* calculate exception message length */
577
578         va_start(ap, message);
579         msglen = get_variable_message_length(message, ap);
580         va_end(ap);
581
582         /* allocate memory */
583
584         msg = MNEW(char, msglen);
585
586         /* generate message */
587
588         va_start(ap, message);
589         vsprintf(msg, message, ap);
590         va_end(ap);
591
592         /* create exception object */
593
594         o = new_exception_message(string_java_lang_InternalError, msg);
595
596         /* free memory */
597
598         MFREE(msg, char, msglen);
599
600         return o;
601 }
602
603
604 /* new_unsupportedclassversionerror ********************************************
605
606    generates a java.lang.UnsupportedClassVersionError for the classloader
607
608 *******************************************************************************/
609
610 java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *message, ...)
611 {
612         java_objectheader *o;
613         va_list            ap;
614         char              *msg;
615     s4                 msglen;
616
617         /* calculate exception message length */
618
619         msglen = utf_strlen(c->name) + strlen(" (") + strlen(")") + strlen("0");
620
621         va_start(ap, message);
622         msglen += get_variable_message_length(message, ap);
623         va_end(ap);
624
625         /* allocate memory */
626
627         msg = MNEW(char, msglen);
628
629         /* generate message */
630
631         utf_sprint_classname(msg, c->name);
632         strcat(msg, " (");
633
634         va_start(ap, message);
635         vsprintf(msg + strlen(msg), message, ap);
636         va_end(ap);
637
638         strcat(msg, ")");
639
640         /* create exception object */
641
642         o = new_exception_message(string_java_lang_UnsupportedClassVersionError,
643                                                           msg);
644
645         /* free memory */
646
647         MFREE(msg, char, msglen);
648
649         return o;
650 }
651
652
653 /* new_verifyerror *************************************************************
654
655    generates a java.lang.VerifyError for the jit compiler
656
657 *******************************************************************************/
658
659 java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
660 {
661         java_objectheader *o;
662         va_list            ap;
663         char              *msg;
664         s4                 msglen;
665
666         useinlining = false; /* at least until sure inlining works with exceptions*/
667
668         /* calculate exception message length */
669
670         msglen = strlen("(class: ") + utf_strlen(m->class->name) +
671                 strlen(", method: ") + utf_strlen(m->name) +
672                 strlen(" signature: ") + utf_strlen(m->descriptor) +
673                 strlen(") ") + strlen("0");
674
675         va_start(ap, message);
676         msglen += get_variable_message_length(message, ap);
677         va_end(ap);
678
679         /* allocate memory */
680
681         msg = MNEW(char, msglen);
682
683         /* generate message */
684
685         strcpy(msg, "(class: ");
686         utf_strcat(msg, m->class->name);
687         strcat(msg, ", method: ");
688         utf_strcat(msg, m->name);
689         strcat(msg, " signature: ");
690         utf_strcat(msg, m->descriptor);
691         strcat(msg, ") ");
692
693         va_start(ap, message);
694         vsprintf(msg + strlen(msg), message, ap);
695         va_end(ap);
696
697         /* create exception object */
698
699         o = new_exception_message(string_java_lang_VerifyError, msg);
700
701         /* free memory */
702
703         MFREE(msg, char, msglen);
704
705         return o;
706 }
707
708
709 /* new_arithmeticexception *****************************************************
710
711    Generates a java.lang.ArithmeticException for the jit compiler.
712
713 *******************************************************************************/
714
715 java_objectheader *new_arithmeticexception(void)
716 {
717         java_objectheader *e;
718
719         e = new_exception_message(string_java_lang_ArithmeticException,
720                                                           string_java_lang_ArithmeticException_message);
721
722         if (!e)
723                 return *exceptionptr;
724
725         return e;
726 }
727
728
729 /* new_arrayindexoutofboundsexception ******************************************
730
731    Generates a java.lang.ArrayIndexOutOfBoundsException for the JIT
732    compiler.
733
734 *******************************************************************************/
735
736 java_objectheader *new_arrayindexoutofboundsexception(s4 index)
737 {
738         java_objectheader *e;
739         methodinfo *m;
740         java_lang_String *s;
741
742         /* convert the index into a String, like Sun does */
743
744         m = class_resolveclassmethod(class_java_lang_String,
745                                                                  utf_new_char("valueOf"),
746                                                                  utf_new_char("(I)Ljava/lang/String;"),
747                                                                  class_java_lang_Object,
748                                                                  true);
749
750         if (!m)
751                 return *exceptionptr;
752
753         s = (java_lang_String *) asm_calljavafunction(m,
754                                                                                                   (void *) (ptrint) index,
755                                                                                                   NULL,
756                                                                                                   NULL,
757                                                                                                   NULL);
758
759         if (!s)
760                 return *exceptionptr;
761
762         e = new_exception_javastring(string_java_lang_ArrayIndexOutOfBoundsException,
763                                                                  s);
764
765         if (!e)
766                 return *exceptionptr;
767
768         return e;
769 }
770
771
772 /* new_arraystoreexception *****************************************************
773
774    generates a java.lang.ArrayStoreException for the jit compiler
775
776 *******************************************************************************/
777
778 java_objectheader *new_arraystoreexception(void)
779 {
780         java_objectheader *e;
781
782         e = new_exception(string_java_lang_ArrayStoreException);
783 /*      e = native_new_and_init(class_java_lang_ArrayStoreException); */
784
785         if (!e)
786                 return *exceptionptr;
787
788         return e;
789 }
790
791
792 /* new_classcastexception ******************************************************
793
794    generates a java.lang.ClassCastException for the jit compiler
795
796 *******************************************************************************/
797
798 java_objectheader *new_classcastexception(void)
799 {
800         java_objectheader *e;
801
802         e = new_exception(string_java_lang_ClassCastException);
803
804         if (!e)
805                 return *exceptionptr;
806
807         return e;
808 }
809
810
811 /* new_illegalargumentexception ************************************************
812
813    Generates a java.lang.IllegalArgumentException for the VM system.
814
815 *******************************************************************************/
816
817 java_objectheader *new_illegalargumentexception(void)
818 {
819         java_objectheader *e;
820
821         if (!(e = native_new_and_init(class_java_lang_IllegalArgumentException)))
822                 return *exceptionptr;
823
824         return e;
825 }
826
827
828 /* new_illegalmonitorstateexception ********************************************
829
830    Generates a java.lang.IllegalMonitorStateException for the VM
831    thread system.
832
833 *******************************************************************************/
834
835 java_objectheader *new_illegalmonitorstateexception(void)
836 {
837         java_objectheader *e;
838
839         if (!(e = native_new_and_init(class_java_lang_IllegalMonitorStateException)))
840                 return *exceptionptr;
841
842         return e;
843 }
844
845
846 /* new_negativearraysizeexception **********************************************
847
848    generates a java.lang.NegativeArraySizeException for the jit compiler
849
850 *******************************************************************************/
851
852 java_objectheader *new_negativearraysizeexception(void)
853 {
854         java_objectheader *e;
855
856         e = new_exception(string_java_lang_NegativeArraySizeException);
857
858         if (!e)
859                 return *exceptionptr;
860
861         return e;
862 }
863
864
865 /* new_nullpointerexception ****************************************************
866
867    generates a java.lang.NullPointerException for the jit compiler
868
869 *******************************************************************************/
870
871 java_objectheader *new_nullpointerexception(void)
872 {
873         java_objectheader *e;
874
875         e = native_new_and_init(class_java_lang_NullPointerException);
876
877         if (!e)
878                 return *exceptionptr;
879
880         return e;
881 }
882
883
884 /*
885  * These are local overrides for various environment variables in Emacs.
886  * Please do not remove this and leave it at the end of the file, where
887  * Emacs will automagically detect them.
888  * ---------------------------------------------------------------------
889  * Local variables:
890  * mode: c
891  * indent-tabs-mode: t
892  * c-basic-offset: 4
893  * tab-width: 4
894  * End:
895  */