161879f16f30fc931c20f6ca5aa8a5f6c6c2cc27
[cacao.git] / src / vm / exceptions.c
1 /* src/vm/exceptions.c - exception related functions
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, 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., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Christian Thalinger
28
29    Changes: Edwin Steiner
30
31    $Id: exceptions.c 4921 2006-05-15 14:24:36Z twisti $
32
33 */
34
35
36 #include "config.h"
37
38 #include <assert.h>
39 #include <string.h>
40 #include <stdarg.h>
41 #include <stdlib.h>
42
43 #include "vm/types.h"
44
45 #include "mm/memory.h"
46 #include "native/native.h"
47 #include "native/include/java_lang_String.h"
48 #include "native/include/java_lang_Throwable.h"
49 #include "toolbox/logging.h"
50 #include "toolbox/util.h"
51 #include "vm/class.h"
52 #include "vm/exceptions.h"
53 #include "vm/global.h"
54 #include "vm/loader.h"
55 #include "vm/options.h"
56 #include "vm/stringlocal.h"
57 #include "vm/vm.h"
58 #include "vm/jit/asmpart.h"
59 #include "vm/jit/jit.h"
60 #include "vm/jit/methodheader.h"
61
62
63 /* for raising exceptions from native methods *********************************/
64
65 #if !defined(ENABLE_THREADS)
66 java_objectheader *_no_threads_exceptionptr = NULL;
67 #endif
68
69
70 /* init_system_exceptions ******************************************************
71
72    Load and link exceptions used in the system.
73
74 *******************************************************************************/
75
76 bool exceptions_init(void)
77 {
78         /* java/lang/Throwable */
79
80         if (!(class_java_lang_Throwable =
81                   load_class_bootstrap(utf_java_lang_Throwable)) ||
82                 !link_class(class_java_lang_Throwable))
83                 return false;
84
85
86         /* java/lang/VMThrowable */
87
88         if (!(class_java_lang_VMThrowable =
89                   load_class_bootstrap(utf_java_lang_VMThrowable)) ||
90                 !link_class(class_java_lang_VMThrowable))
91                 return false;
92
93
94         /* java/lang/Error */
95
96         if (!(class_java_lang_Error = load_class_bootstrap(utf_java_lang_Error)) ||
97                 !link_class(class_java_lang_Error))
98                 return false;
99
100         /* java/lang/NoClassDefFoundError */
101
102         if (!(class_java_lang_NoClassDefFoundError =
103                   load_class_bootstrap(utf_java_lang_NoClassDefFoundError)) ||
104                 !link_class(class_java_lang_NoClassDefFoundError))
105                 return false;
106
107         /* java/lang/LinkageError */
108
109         if (!(class_java_lang_LinkageError =
110                   load_class_bootstrap(utf_java_lang_LinkageError)) ||
111                 !link_class(class_java_lang_LinkageError))
112                 return false;
113
114         /* java/lang/NoSuchMethodError */
115
116         if (!(class_java_lang_NoSuchMethodError =
117                   load_class_bootstrap(utf_java_lang_NoSuchMethodError)) ||
118                 !link_class(class_java_lang_NoSuchMethodError))
119                 return false;
120
121         /* java/lang/OutOfMemoryError */
122
123         if (!(class_java_lang_OutOfMemoryError =
124                   load_class_bootstrap(utf_java_lang_OutOfMemoryError)) ||
125                 !link_class(class_java_lang_OutOfMemoryError))
126                 return false;
127
128
129         /* java/lang/Exception */
130
131         if (!(class_java_lang_Exception =
132                   load_class_bootstrap(utf_java_lang_Exception)) ||
133                 !link_class(class_java_lang_Exception))
134                 return false;
135
136         /* java/lang/ClassNotFoundException */
137
138         if (!(class_java_lang_ClassNotFoundException =
139                   load_class_bootstrap(utf_java_lang_ClassNotFoundException)) ||
140                 !link_class(class_java_lang_ClassNotFoundException))
141                 return false;
142
143         /* java/lang/IllegalArgumentException */
144
145         if (!(class_java_lang_IllegalArgumentException =
146                   load_class_bootstrap(utf_java_lang_IllegalArgumentException)) ||
147                 !link_class(class_java_lang_IllegalArgumentException))
148                 return false;
149
150         /* java/lang/IllegalMonitorStateException */
151
152         if (!(class_java_lang_IllegalMonitorStateException =
153                   load_class_bootstrap(utf_java_lang_IllegalMonitorStateException)) ||
154                 !link_class(class_java_lang_IllegalMonitorStateException))
155                 return false;
156
157         /* java/lang/NullPointerException */
158
159         if (!(class_java_lang_NullPointerException =
160                   load_class_bootstrap(utf_java_lang_NullPointerException)) ||
161                 !link_class(class_java_lang_NullPointerException))
162                 return false;
163
164
165         return true;
166 }
167
168
169 static void throw_exception_exit_intern(bool doexit)
170 {
171         java_objectheader *xptr;
172         classinfo *c;
173         methodinfo *pss;
174
175         xptr = *exceptionptr;
176
177         if (xptr) {
178                 /* clear exception, because we are calling jit code again */
179                 *exceptionptr = NULL;
180
181                 c = xptr->vftbl->class;
182
183                 pss = class_resolveclassmethod(c,
184                                                                            utf_printStackTrace,
185                                                                            utf_void__void,
186                                                                            class_java_lang_Object,
187                                                                            false);
188
189                 /* print the stacktrace */
190
191                 if (pss) {
192                         (void) vm_call_method(pss, xptr);
193
194                         /* This normally means, we are EXTREMLY out of memory or have a   */
195                         /* serious problem while printStackTrace. But may be another      */
196                         /* exception, so print it.                                        */
197
198                         if (*exceptionptr) {
199                                 java_lang_Throwable *t;
200
201                                 t = (java_lang_Throwable *) *exceptionptr;
202
203                                 fprintf(stderr, "Exception while printStackTrace(): ");
204                                 utf_fprint_printable_ascii_classname(stderr, t->header.vftbl->class->name);
205
206                                 if (t->detailMessage) {
207                                         char *buf;
208
209                                         buf = javastring_tochar((java_objectheader *) t->detailMessage);
210                                         fprintf(stderr, ": %s", buf);
211                                         MFREE(buf, char, strlen(buf));
212                                 }
213                                         
214                                 fprintf(stderr, "\n");
215                         }
216
217                 } else {
218                         utf_fprint_printable_ascii_classname(stderr, c->name);
219                         fprintf(stderr, ": printStackTrace()V not found!\n");
220                 }
221
222                 fflush(stderr);
223
224                 /* good bye! */
225
226                 if (doexit)
227                         exit(1);
228         }
229 }
230
231
232 void throw_exception(void)
233 {
234         throw_exception_exit_intern(false);
235 }
236
237
238 void throw_exception_exit(void)
239 {
240         throw_exception_exit_intern(true);
241 }
242
243
244 void throw_main_exception(void)
245 {
246         fprintf(stderr, "Exception in thread \"main\" ");
247         fflush(stderr);
248
249         throw_exception_exit_intern(false);
250 }
251
252
253 void throw_main_exception_exit(void)
254 {
255         fprintf(stderr, "Exception in thread \"main\" ");
256         fflush(stderr);
257
258         throw_exception_exit_intern(true);
259 }
260
261
262 void throw_cacao_exception_exit(const char *exception, const char *message, ...)
263 {
264         s4 i;
265         char *tmp;
266         s4 len;
267         va_list ap;
268
269         len = strlen(exception);
270         tmp = MNEW(char, len + 1);
271         strncpy(tmp, exception, len);
272         tmp[len] = '\0';
273
274         /* convert to classname */
275
276         for (i = len - 1; i >= 0; i--)
277                 if (tmp[i] == '/') tmp[i] = '.';
278
279         fprintf(stderr, "Exception in thread \"main\" %s", tmp);
280
281         MFREE(tmp, char, len);
282
283         if (strlen(message) > 0) {
284                 fprintf(stderr, ": ");
285
286                 va_start(ap, message);
287                 vfprintf(stderr, message, ap);
288                 va_end(ap);
289         }
290
291         fprintf(stderr, "\n");
292         fflush(stderr);
293
294         /* good bye! */
295
296         exit(1);
297 }
298
299
300 /* exceptions_throw_outofmemory_exit *******************************************
301
302    Just print an: java.lang.InternalError: Out of memory
303
304 *******************************************************************************/
305
306 void exceptions_throw_outofmemory_exit(void)
307 {
308         throw_cacao_exception_exit(string_java_lang_InternalError,
309                                                            "Out of memory");
310 }
311
312
313 /* new_exception ***************************************************************
314
315    Creates an exception object with the given name and initalizes it.
316
317    IN:
318       classname....class name in UTF-8
319
320    RETURN VALUE:
321       an exception pointer (in any case -- either it is the newly created
322           exception, or an exception thrown while trying to create it).
323
324 *******************************************************************************/
325
326 java_objectheader *new_exception(const char *classname)
327 {
328         java_objectheader *o;
329         classinfo         *c;
330
331         if (!(c = load_class_bootstrap(utf_new_char(classname))))
332                 return *exceptionptr;
333
334         o = native_new_and_init(c);
335
336         if (!o)
337                 return *exceptionptr;
338
339         return o;
340 }
341
342
343 /* new_exception_message *******************************************************
344
345    Creates an exception object with the given name and initalizes it
346    with the given char message.
347
348    IN:
349       classname....class name in UTF-8
350           message......message in UTF-8
351
352    RETURN VALUE:
353       an exception pointer (in any case -- either it is the newly created
354           exception, or an exception thrown while trying to create it).
355
356 *******************************************************************************/
357
358 java_objectheader *new_exception_message(const char *classname,
359                                                                                  const char *message)
360 {
361         java_lang_String *s;
362
363         s = javastring_new_from_utf_string(message);
364         if (!s)
365                 return *exceptionptr;
366
367         return new_exception_javastring(classname, s);
368 }
369
370
371 /* new_exception_throwable *****************************************************
372
373    Creates an exception object with the given name and initalizes it
374    with the given java/lang/Throwable exception.
375
376    IN:
377       classname....class name in UTF-8
378           throwable....the given Throwable
379
380    RETURN VALUE:
381       an exception pointer (in any case -- either it is the newly created
382           exception, or an exception thrown while trying to create it).
383
384 *******************************************************************************/
385
386 java_objectheader *new_exception_throwable(const char *classname,
387                                                                                    java_lang_Throwable *throwable)
388 {
389         java_objectheader *o;
390         classinfo         *c;
391    
392         if (!(c = load_class_bootstrap(utf_new_char(classname))))
393                 return *exceptionptr;
394
395         o = native_new_and_init_throwable(c, throwable);
396
397         if (!o)
398                 return *exceptionptr;
399
400         return o;
401 }
402
403
404 /* new_exception_utfmessage ****************************************************
405
406    Creates an exception object with the given name and initalizes it
407    with the given utf message.
408
409    IN:
410       classname....class name in UTF-8
411           message......the message as an utf *
412
413    RETURN VALUE:
414       an exception pointer (in any case -- either it is the newly created
415           exception, or an exception thrown while trying to create it).
416
417 *******************************************************************************/
418
419 java_objectheader *new_exception_utfmessage(const char *classname, utf *message)
420 {
421         java_lang_String *s;
422
423         s = javastring_new(message);
424         if (!s)
425                 return *exceptionptr;
426
427         return new_exception_javastring(classname, s);
428 }
429
430
431 /* new_exception_javastring ****************************************************
432
433    Creates an exception object with the given name and initalizes it
434    with the given java/lang/String message.
435
436    IN:
437       classname....class name in UTF-8
438           message......the message as a java.lang.String
439
440    RETURN VALUE:
441       an exception pointer (in any case -- either it is the newly created
442           exception, or an exception thrown while trying to create it).
443
444 *******************************************************************************/
445
446 java_objectheader *new_exception_javastring(const char *classname,
447                                                                                         java_lang_String *message)
448 {
449         java_objectheader *o;
450         classinfo         *c;
451    
452         if (!(c = load_class_bootstrap(utf_new_char(classname))))
453                 return *exceptionptr;
454
455         o = native_new_and_init_string(c, message);
456
457         if (!o)
458                 return *exceptionptr;
459
460         return o;
461 }
462
463
464 /* new_exception_int ***********************************************************
465
466    Creates an exception object with the given name and initalizes it
467    with the given int value.
468
469    IN:
470       classname....class name in UTF-8
471           i............the integer
472
473    RETURN VALUE:
474       an exception pointer (in any case -- either it is the newly created
475           exception, or an exception thrown while trying to create it).
476
477 *******************************************************************************/
478
479 java_objectheader *new_exception_int(const char *classname, s4 i)
480 {
481         java_objectheader *o;
482         classinfo         *c;
483    
484         if (!(c = load_class_bootstrap(utf_new_char(classname))))
485                 return *exceptionptr;
486
487         o = native_new_and_init_int(c, i);
488
489         if (!o)
490                 return *exceptionptr;
491
492         return o;
493 }
494
495
496 /* new_classformaterror ********************************************************
497
498    generates a java.lang.ClassFormatError for the classloader
499
500    IN:
501       c............the class in which the error was found
502           message......UTF-8 format string
503
504    RETURN VALUE:
505       an exception pointer (in any case -- either it is the newly created
506           exception, or an exception thrown while trying to create it).
507
508 *******************************************************************************/
509
510 java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
511 {
512         java_objectheader *o;
513         char              *msg;
514         s4                 msglen;
515         va_list            ap;
516
517         /* calculate message length */
518
519         msglen = 0;
520
521         if (c)
522                 msglen += utf_bytes(c->name) + strlen(" (");
523
524         va_start(ap, message);
525         msglen += get_variable_message_length(message, ap);
526         va_end(ap);
527
528         if (c)
529                 msglen += strlen(")");
530
531         msglen += strlen("0");
532
533         /* allocate a buffer */
534
535         msg = MNEW(char, msglen);
536
537         /* print message into allocated buffer */
538
539         if (c) {
540                 utf_copy_classname(msg, c->name);
541                 strcat(msg, " (");
542         }
543
544         va_start(ap, message);
545         vsprintf(msg + strlen(msg), message, ap);
546         va_end(ap);
547
548         if (c)
549                 strcat(msg, ")");
550
551         o = new_exception_message(string_java_lang_ClassFormatError, msg);
552
553         MFREE(msg, char, msglen);
554
555         return o;
556 }
557
558
559 /* exceptions_throw_classformaterror *******************************************
560
561    Generate a java.lang.ClassFormatError for the VM system and throw it.
562
563    IN:
564       c............the class in which the error was found
565           message......UTF-8 format string
566
567    RETURN VALUE:
568       an exception pointer (in any case -- either it is the newly created
569           exception, or an exception thrown while trying to create it).
570
571 *******************************************************************************/
572
573 void exceptions_throw_classformaterror(classinfo *c, const char *message, ...)
574 {
575         va_list ap;
576
577         va_start(ap, message);
578         *exceptionptr = new_classformaterror(c, message, ap);
579         va_end(ap);
580 }
581
582
583 /* new_classnotfoundexception **************************************************
584
585    Generates a java.lang.ClassNotFoundException for the classloader.
586
587    IN:
588       name.........name of the class not found as a utf *
589
590    RETURN VALUE:
591       an exception pointer (in any case -- either it is the newly created
592           exception, or an exception thrown while trying to create it).
593
594 *******************************************************************************/
595
596 java_objectheader *new_classnotfoundexception(utf *name)
597 {
598         java_objectheader *o;
599         java_lang_String  *s;
600
601         s = javastring_new(name);
602         if (!s)
603                 return *exceptionptr;
604
605         o = native_new_and_init_string(class_java_lang_ClassNotFoundException, s);
606
607         if (!o)
608                 return *exceptionptr;
609
610         return o;
611 }
612
613
614 /* new_noclassdeffounderror ****************************************************
615
616    Generates a java.lang.NoClassDefFoundError
617
618    IN:
619       name.........name of the class not found as a utf *
620
621    RETURN VALUE:
622       an exception pointer (in any case -- either it is the newly created
623           exception, or an exception thrown while trying to create it).
624
625 *******************************************************************************/
626
627 java_objectheader *new_noclassdeffounderror(utf *name)
628 {
629         java_objectheader *o;
630         java_lang_String  *s;
631
632         s = javastring_new(name);
633         if (!s)
634                 return *exceptionptr;
635
636         o = native_new_and_init_string(class_java_lang_NoClassDefFoundError, s);
637
638         if (!o)
639                 return *exceptionptr;
640
641         return o;
642 }
643
644
645 /* classnotfoundexception_to_noclassdeffounderror ******************************
646
647    Check the *exceptionptr for a ClassNotFoundException. If it is one,
648    convert it to a NoClassDefFoundError.
649
650 *******************************************************************************/
651
652 void classnotfoundexception_to_noclassdeffounderror(void)
653 {
654         java_objectheader *xptr;
655         java_objectheader *cause;
656
657         /* get the cause */
658
659         cause = *exceptionptr;
660
661         /* convert ClassNotFoundException's to NoClassDefFoundError's */
662
663         if (builtin_instanceof(cause, class_java_lang_ClassNotFoundException)) {
664                 /* clear exception, because we are calling jit code again */
665
666                 *exceptionptr = NULL;
667
668                 /* create new error */
669
670                 xptr =
671                         new_exception_javastring(string_java_lang_NoClassDefFoundError,
672                                         ((java_lang_Throwable *) cause)->detailMessage);
673
674                 /* we had an exception while creating the error */
675
676                 if (*exceptionptr)
677                         return;
678
679                 /* set new exception */
680
681                 *exceptionptr = xptr;
682         }
683 }
684
685
686 /* new_internalerror ***********************************************************
687
688    Generates a java.lang.InternalError for the VM.
689
690    IN:
691       message......UTF-8 message format string
692
693    RETURN VALUE:
694       an exception pointer (in any case -- either it is the newly created
695           exception, or an exception thrown while trying to create it).
696
697 *******************************************************************************/
698
699 java_objectheader *new_internalerror(const char *message, ...)
700 {
701         java_objectheader *o;
702         va_list            ap;
703         char              *msg;
704         s4                 msglen;
705
706         /* calculate exception message length */
707
708         va_start(ap, message);
709         msglen = get_variable_message_length(message, ap);
710         va_end(ap);
711
712         /* allocate memory */
713
714         msg = MNEW(char, msglen);
715
716         /* generate message */
717
718         va_start(ap, message);
719         vsprintf(msg, message, ap);
720         va_end(ap);
721
722         /* create exception object */
723
724         o = new_exception_message(string_java_lang_InternalError, msg);
725
726         /* free memory */
727
728         MFREE(msg, char, msglen);
729
730         return o;
731 }
732
733
734 /* exceptions_new_linkageerror *************************************************
735
736    Generates a java.lang.LinkageError with an error message.
737
738    IN:
739       message......UTF-8 message
740           c............class related to the error. If this is != NULL
741                        the name of c is appended to the error message.
742
743    RETURN VALUE:
744       an exception pointer (in any case -- either it is the newly created
745           exception, or an exception thrown while trying to create it).
746
747 *******************************************************************************/
748
749 java_objectheader *exceptions_new_linkageerror(const char *message,
750                                                                                            classinfo *c)
751 {
752         java_objectheader *o;
753         char              *msg;
754         s4                 msglen;
755
756         /* calculate exception message length */
757
758         msglen = strlen(message) + 1;
759         if (c) {
760                 msglen += utf_bytes(c->name);
761         }
762                 
763         /* allocate memory */
764
765         msg = MNEW(char, msglen);
766
767         /* generate message */
768
769         strcpy(msg,message);
770         if (c) {
771                 utf_cat_classname(msg, c->name);
772         }
773
774         o = native_new_and_init_string(class_java_lang_LinkageError,
775                                                                    javastring_new_from_utf_string(msg));
776
777         /* free memory */
778
779         MFREE(msg, char, msglen);
780
781         if (!o)
782                 return *exceptionptr;
783
784         return o;
785 }
786
787
788 /* exceptions_new_nosuchmethoderror ********************************************
789
790    Generates a java.lang.NoSuchMethodError with an error message.
791
792    IN:
793       c............class in which the method was not found
794           name.........name of the method
795           desc.........descriptor of the method
796
797    RETURN VALUE:
798       an exception pointer (in any case -- either it is the newly created
799           exception, or an exception thrown while trying to create it).
800
801 *******************************************************************************/
802
803 java_objectheader *exceptions_new_nosuchmethoderror(classinfo *c,
804                                                                                                         utf *name, utf *desc)
805 {
806         java_objectheader *o;
807         char              *msg;
808         s4                 msglen;
809
810         /* calculate exception message length */
811
812         msglen = utf_bytes(c->name) + strlen(".") + utf_bytes(name) +
813                 utf_bytes(desc) + strlen("0");
814
815         /* allocate memory */
816
817         msg = MNEW(char, msglen);
818
819         /* generate message */
820
821         utf_copy_classname(msg, c->name);
822         strcat(msg, ".");
823         utf_cat(msg, name);
824         utf_cat(msg, desc);
825
826         o = native_new_and_init_string(class_java_lang_NoSuchMethodError,
827                                                                    javastring_new_from_utf_string(msg));
828
829         /* free memory */
830
831         MFREE(msg, char, msglen);
832
833         if (!o)
834                 return *exceptionptr;
835
836         return o;
837 }
838
839
840 /* exceptions_throw_nosuchmethoderror ******************************************
841
842    Generates a java.lang.NoSuchMethodError with an error message.
843
844    IN:
845       c............class in which the method was not found
846           name.........name of the method
847           desc.........descriptor of the method
848
849 *******************************************************************************/
850
851 void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc)
852 {
853         *exceptionptr = exceptions_new_nosuchmethoderror(c, name, desc);
854 }
855
856
857 /* new_unsupportedclassversionerror ********************************************
858
859    Generate a java.lang.UnsupportedClassVersionError for the classloader
860
861    IN:
862       c............class in which the method was not found
863           message......UTF-8 format string
864
865    RETURN VALUE:
866       an exception pointer (in any case -- either it is the newly created
867           exception, or an exception thrown while trying to create it).
868
869 *******************************************************************************/
870
871 java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *message, ...)
872 {
873         java_objectheader *o;
874         va_list            ap;
875         char              *msg;
876     s4                 msglen;
877
878         /* calculate exception message length */
879
880         msglen = utf_bytes(c->name) + strlen(" (") + strlen(")") + strlen("0");
881
882         va_start(ap, message);
883         msglen += get_variable_message_length(message, ap);
884         va_end(ap);
885
886         /* allocate memory */
887
888         msg = MNEW(char, msglen);
889
890         /* generate message */
891
892         utf_copy_classname(msg, c->name);
893         strcat(msg, " (");
894
895         va_start(ap, message);
896         vsprintf(msg + strlen(msg), message, ap);
897         va_end(ap);
898
899         strcat(msg, ")");
900
901         /* create exception object */
902
903         o = new_exception_message(string_java_lang_UnsupportedClassVersionError,
904                                                           msg);
905
906         /* free memory */
907
908         MFREE(msg, char, msglen);
909
910         return o;
911 }
912
913
914 /* new_verifyerror *************************************************************
915
916    Generates a java.lang.VerifyError for the JIT compiler.
917
918    IN:
919       m............method in which the error was found
920           message......UTF-8 format string
921
922    RETURN VALUE:
923       an exception pointer (in any case -- either it is the newly created
924           exception, or an exception thrown while trying to create it).
925
926 *******************************************************************************/
927
928 java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
929 {
930         java_objectheader *o;
931         va_list            ap;
932         char              *msg;
933         s4                 msglen;
934
935         useinlining = false; /* at least until sure inlining works with exceptions*/
936
937         /* calculate exception message length */
938
939         msglen = 0;
940
941         if (m)
942                 msglen = strlen("(class: ") + utf_bytes(m->class->name) +
943                         strlen(", method: ") + utf_bytes(m->name) +
944                         strlen(" signature: ") + utf_bytes(m->descriptor) +
945                         strlen(") ") + strlen("0");
946
947         va_start(ap, message);
948         msglen += get_variable_message_length(message, ap);
949         va_end(ap);
950
951         /* allocate memory */
952
953         msg = MNEW(char, msglen);
954
955         /* generate message */
956
957         if (m) {
958                 strcpy(msg, "(class: ");
959                 utf_cat_classname(msg, m->class->name);
960                 strcat(msg, ", method: ");
961                 utf_cat(msg, m->name);
962                 strcat(msg, " signature: ");
963                 utf_cat(msg, m->descriptor);
964                 strcat(msg, ") ");
965         }
966
967         va_start(ap, message);
968         vsprintf(msg + strlen(msg), message, ap);
969         va_end(ap);
970
971         /* create exception object */
972
973         o = new_exception_message(string_java_lang_VerifyError, msg);
974
975         /* free memory */
976
977         MFREE(msg, char, msglen);
978
979         return o;
980 }
981
982
983 /* exceptions_throw_verifyerror_for_stack **************************************
984
985    throws a java.lang.VerifyError for an invalid stack slot type
986
987    IN:
988       m............method in which the error was found
989           type.........the expected type
990
991    RETURN VALUE:
992       an exception pointer (in any case -- either it is the newly created
993           exception, or an exception thrown while trying to create it).
994
995 *******************************************************************************/
996
997 void exceptions_throw_verifyerror_for_stack(methodinfo *m,int type)
998 {
999         java_objectheader *o;
1000         char              *msg;
1001         s4                 msglen;
1002         char              *typename;
1003
1004         /* calculate exception message length */
1005
1006         msglen = 0;
1007
1008         if (m)
1009                 msglen = strlen("(class: ") + utf_bytes(m->class->name) +
1010                         strlen(", method: ") + utf_bytes(m->name) +
1011                         strlen(" signature: ") + utf_bytes(m->descriptor) +
1012                         strlen(") Expecting to find longest-------typename on stack") 
1013                         + strlen("0");
1014
1015         /* allocate memory */
1016
1017         msg = MNEW(char, msglen);
1018
1019         /* generate message */
1020
1021         if (m) {
1022                 strcpy(msg, "(class: ");
1023                 utf_cat_classname(msg, m->class->name);
1024                 strcat(msg, ", method: ");
1025                 utf_cat(msg, m->name);
1026                 strcat(msg, " signature: ");
1027                 utf_cat(msg, m->descriptor);
1028                 strcat(msg, ") ");
1029         }
1030         else {
1031                 msg[0] = 0;
1032         }
1033
1034         strcat(msg,"Expecting to find ");
1035         switch (type) {
1036                 case TYPE_INT: typename = "integer"; break;
1037                 case TYPE_LNG: typename = "long"; break;
1038                 case TYPE_FLT: typename = "float"; break;
1039                 case TYPE_DBL: typename = "double"; break;
1040                 case TYPE_ADR: typename = "object/array"; break;
1041                 default:       typename = "<INVALID>"; assert(0); break;
1042         }
1043         strcat(msg, typename);
1044         strcat(msg, " on stack");
1045
1046         /* create exception object */
1047
1048         o = new_exception_message(string_java_lang_VerifyError, msg);
1049
1050         /* free memory */
1051
1052         MFREE(msg, char, msglen);
1053
1054         *exceptionptr = o;
1055 }
1056
1057 /* new_arithmeticexception *****************************************************
1058
1059    Generates a java.lang.ArithmeticException for the jit compiler.
1060
1061 *******************************************************************************/
1062
1063 java_objectheader *new_arithmeticexception(void)
1064 {
1065         java_objectheader *e;
1066
1067         e = new_exception_message(string_java_lang_ArithmeticException,
1068                                                           string_java_lang_ArithmeticException_message);
1069
1070         if (!e)
1071                 return *exceptionptr;
1072
1073         return e;
1074 }
1075
1076
1077 /* exceptions_new_arrayindexoutofboundsexception *******************************
1078
1079    Generates a java.lang.ArrayIndexOutOfBoundsException for the VM
1080    system.
1081
1082 *******************************************************************************/
1083
1084 java_objectheader *new_arrayindexoutofboundsexception(s4 index)
1085 {
1086         java_objectheader *e;
1087         methodinfo        *m;
1088         java_objectheader *o;
1089         java_lang_String  *s;
1090
1091         /* convert the index into a String, like Sun does */
1092
1093         m = class_resolveclassmethod(class_java_lang_String,
1094                                                                  utf_new_char("valueOf"),
1095                                                                  utf_new_char("(I)Ljava/lang/String;"),
1096                                                                  class_java_lang_Object,
1097                                                                  true);
1098
1099         if (m == NULL)
1100                 return *exceptionptr;
1101
1102         o = vm_call_method(m, NULL, index);
1103
1104         s = (java_lang_String *) o;
1105
1106         if (s == NULL)
1107                 return *exceptionptr;
1108
1109         e = new_exception_javastring(string_java_lang_ArrayIndexOutOfBoundsException,
1110                                                                  s);
1111
1112         if (e == NULL)
1113                 return *exceptionptr;
1114
1115         return e;
1116 }
1117
1118
1119 /* exceptions_throw_arrayindexoutofboundsexception *****************************
1120
1121    Generates a java.lang.ArrayIndexOutOfBoundsException for the VM
1122    system.
1123
1124 *******************************************************************************/
1125
1126 void exceptions_throw_arrayindexoutofboundsexception(void)
1127 {
1128         java_objectheader *e;
1129
1130         e = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
1131
1132         if (!e)
1133                 return;
1134
1135         *exceptionptr = e;
1136 }
1137
1138
1139 /* new_arraystoreexception *****************************************************
1140
1141    generates a java.lang.ArrayStoreException for the jit compiler
1142
1143 *******************************************************************************/
1144
1145 java_objectheader *new_arraystoreexception(void)
1146 {
1147         java_objectheader *e;
1148
1149         e = new_exception(string_java_lang_ArrayStoreException);
1150 /*      e = native_new_and_init(class_java_lang_ArrayStoreException); */
1151
1152         if (!e)
1153                 return *exceptionptr;
1154
1155         return e;
1156 }
1157
1158
1159 /* new_classcastexception ******************************************************
1160
1161    generates a java.lang.ClassCastException for the jit compiler
1162
1163 *******************************************************************************/
1164
1165 java_objectheader *new_classcastexception(void)
1166 {
1167         java_objectheader *e;
1168
1169         e = new_exception(string_java_lang_ClassCastException);
1170
1171         if (!e)
1172                 return *exceptionptr;
1173
1174         return e;
1175 }
1176
1177
1178 /* exceptions_new_illegalargumentexception *************************************
1179
1180    Generates a java.lang.IllegalArgumentException for the VM system.
1181
1182 *******************************************************************************/
1183
1184 java_objectheader *new_illegalargumentexception(void)
1185 {
1186         java_objectheader *e;
1187
1188         e = native_new_and_init(class_java_lang_IllegalArgumentException);
1189
1190         if (!e)
1191                 return *exceptionptr;
1192
1193         return e;
1194 }
1195
1196
1197 /* exceptions_throw_illegalargumentexception ***********************************
1198
1199    Generates a java.lang.IllegalArgumentException for the VM system
1200    and throw it in the VM system.
1201
1202 *******************************************************************************/
1203
1204 void exceptions_throw_illegalargumentexception(void)
1205 {
1206         *exceptionptr = new_illegalargumentexception();
1207 }
1208
1209
1210 /* new_illegalmonitorstateexception ********************************************
1211
1212    Generates a java.lang.IllegalMonitorStateException for the VM
1213    thread system.
1214
1215 *******************************************************************************/
1216
1217 java_objectheader *new_illegalmonitorstateexception(void)
1218 {
1219         java_objectheader *e;
1220
1221         e = native_new_and_init(class_java_lang_IllegalMonitorStateException);
1222
1223         if (!e)
1224                 return *exceptionptr;
1225
1226         return e;
1227 }
1228
1229
1230 /* exceptions_new_negativearraysizeexception ***********************************
1231
1232    Generates a java.lang.NegativeArraySizeException for the VM system.
1233
1234 *******************************************************************************/
1235
1236 java_objectheader *new_negativearraysizeexception(void)
1237 {
1238         java_objectheader *e;
1239
1240         e = new_exception(string_java_lang_NegativeArraySizeException);
1241
1242         if (!e)
1243                 return *exceptionptr;
1244
1245         return e;
1246 }
1247
1248
1249 /* exceptions_throw_negativearraysizeexception *********************************
1250
1251    Generates a java.lang.NegativeArraySizeException for the VM system.
1252
1253 *******************************************************************************/
1254
1255 void exceptions_throw_negativearraysizeexception(void)
1256 {
1257         *exceptionptr = new_negativearraysizeexception();
1258 }
1259
1260
1261 /* new_nullpointerexception ****************************************************
1262
1263    generates a java.lang.NullPointerException for the jit compiler
1264
1265 *******************************************************************************/
1266
1267 java_objectheader *new_nullpointerexception(void)
1268 {
1269         java_objectheader *e;
1270
1271         e = native_new_and_init(class_java_lang_NullPointerException);
1272
1273         if (!e)
1274                 return *exceptionptr;
1275
1276         return e;
1277 }
1278
1279
1280 /* exceptions_throw_nullpointerexception ***************************************
1281
1282    Generates a java.lang.NullPointerException for the VM system and
1283    throw it in the VM system.
1284
1285 *******************************************************************************/
1286
1287 void exceptions_throw_nullpointerexception(void)
1288 {
1289         *exceptionptr = new_nullpointerexception();
1290 }
1291
1292
1293 /* exceptions_new_stringindexoutofboundsexception ******************************
1294
1295    Generates a java.lang.StringIndexOutOfBoundsException for the VM
1296    system.
1297
1298 *******************************************************************************/
1299
1300 java_objectheader *exceptions_new_stringindexoutofboundsexception(void)
1301 {
1302         java_objectheader *e;
1303
1304         e = new_exception(string_java_lang_StringIndexOutOfBoundsException);
1305
1306         if (e == NULL)
1307                 return *exceptionptr;
1308
1309         return e;
1310 }
1311
1312
1313 /* exceptions_throw_stringindexoutofboundsexception ****************************
1314
1315    Throws a java.lang.StringIndexOutOfBoundsException for the VM
1316    system.
1317
1318 *******************************************************************************/
1319
1320 void exceptions_throw_stringindexoutofboundsexception(void)
1321 {
1322         *exceptionptr = exceptions_new_stringindexoutofboundsexception();
1323 }
1324
1325
1326 /* exceptions_handle_exception *************************************************
1327
1328    Try to find an exception handler for the given exception and return it.
1329    If no handler is found, exit the monitor of the method (if any)
1330    and return NULL.
1331
1332    IN:
1333       xptr.........the exception object
1334           xpc..........PC of where the exception was thrown
1335           pv...........Procedure Value of the current method
1336           sp...........current stack pointer
1337
1338    RETURN VALUE:
1339       the address of the first matching exception handler, or
1340           NULL if no handler was found
1341
1342 *******************************************************************************/
1343
1344 u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp)
1345 {
1346         methodinfo            *m;
1347         s4                     framesize;
1348         s4                     issync;
1349         exceptionentry        *ex;
1350         s4                     exceptiontablelength;
1351         s4                     i;
1352         classref_or_classinfo  cr;
1353         classinfo             *c;
1354 #if defined(ENABLE_THREADS)
1355         java_objectheader     *o;
1356 #endif
1357
1358         /* get methodinfo pointer from method header */
1359
1360         m                    = *((methodinfo **)    (pv + MethodPointer));
1361         framesize            = *((s4 *)             (pv + FrameSize));
1362         issync               = *((s4 *)             (pv + IsSync));
1363         ex                   =   (exceptionentry *) (pv + ExTableStart);
1364         exceptiontablelength = *((s4 *)             (pv + ExTableSize));
1365
1366 #if !defined(NDEBUG)
1367         /* print exception trace */
1368
1369         if (opt_verbose || opt_verbosecall || opt_verboseexception)
1370                 builtin_trace_exception(xptr, m, xpc, 1);
1371 #endif
1372
1373         for (i = 0; i < exceptiontablelength; i++) {
1374                 /* ATTENTION: keep this here, as we need to decrement the
1375            pointer before the loop executes! */
1376
1377                 ex--;
1378
1379                 /* If the start and end PC is NULL, this means we have the
1380                    special case of asm_vm_call_method.  So, just return the
1381                    proper exception handler. */
1382
1383                 if ((ex->startpc == NULL) && (ex->endpc == NULL))
1384                         return (u1 *) (ptrint) &asm_vm_call_method_exception_handler;
1385
1386                 /* is the xpc is the current catch range */
1387
1388                 if ((ex->startpc <= xpc) && (xpc < ex->endpc)) {
1389                         cr = ex->catchtype;
1390
1391                         /* NULL catches everything */
1392
1393                         if (cr.any == NULL) {
1394 #if !defined(NDEBUG)
1395                                 /* Print stacktrace of exception when caught. */
1396
1397                                 if (opt_verboseexception) {
1398                                         exceptions_print_exception(xptr);
1399                                         stacktrace_print_trace(xptr);
1400                                 }
1401 #endif
1402
1403                                 return ex->handlerpc;
1404                         }
1405
1406                         /* resolve or load/link the exception class */
1407
1408                         if (IS_CLASSREF(cr)) {
1409                                 c = resolve_classref_eager(cr.ref);
1410
1411                         } else {
1412                                 c = cr.cls;
1413
1414                                 if (!(c->state & CLASS_LOADED))
1415                                         /* use the methods' classloader */
1416                                         if (!load_class_from_classloader(c->name,
1417                                                                                                          m->class->classloader))
1418                                                 return NULL;
1419
1420                                 if (!(c->state & CLASS_LINKED))
1421                                         if (!link_class(c))
1422                                                 return NULL;
1423                         }
1424
1425                         /* is the thrown exception an instance of the catch class? */
1426
1427                         if (builtin_instanceof(xptr, c)) {
1428 #if !defined(NDEBUG)
1429                                 /* Print stacktrace of exception when caught. */
1430
1431                                 if (opt_verboseexception) {
1432                                         exceptions_print_exception(xptr);
1433                                         stacktrace_print_trace(xptr);
1434                                 }
1435 #endif
1436
1437                                 return ex->handlerpc;
1438                         }
1439                 }
1440         }
1441
1442 #if defined(ENABLE_THREADS)
1443         /* is this method synchronized? */
1444
1445         if (issync) {
1446                 /* get synchronization object */
1447
1448 # if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1449                 /* XXX change this if we ever want to use 4-byte stackslots */
1450                 o = *((java_objectheader **) (sp + issync - 8));
1451 # else
1452                 o = *((java_objectheader **) (sp + issync - SIZEOF_VOID_P));
1453 #endif
1454
1455                 assert(o != NULL);
1456
1457                 builtin_monitorexit(o);
1458         }
1459 #endif
1460
1461         /* none of the exceptions catch this one */
1462
1463         return NULL;
1464 }
1465
1466
1467 /* exceptions_print_exception **************************************************
1468
1469    Prints an exception, the detail message and the cause, if
1470    available, with CACAO internal functions to stdout.
1471
1472 *******************************************************************************/
1473
1474 #if !defined(NDEBUG)
1475 void exceptions_print_exception(java_objectheader *xptr)
1476 {
1477         java_lang_Throwable   *t;
1478         java_lang_Throwable   *cause;
1479         utf                   *u;
1480
1481         t = (java_lang_Throwable *) xptr;
1482
1483         if (t == NULL) {
1484                 puts("NULL\n");
1485                 return;
1486         }
1487
1488         cause = t->cause;
1489
1490         /* print the root exception */
1491
1492         utf_display_printable_ascii_classname(t->header.vftbl->class->name);
1493
1494         if (t->detailMessage) {
1495                 u = javastring_toutf(t->detailMessage, false);
1496
1497                 printf(": ");
1498                 utf_display_printable_ascii(u);
1499         }
1500
1501         putc('\n', stdout);
1502
1503         /* print the cause if available */
1504
1505         if (cause && (cause != t)) {
1506                 printf("Caused by: ");
1507                 utf_display_printable_ascii_classname(cause->header.vftbl->class->name);
1508
1509                 if (cause->detailMessage) {
1510                         u = javastring_toutf(cause->detailMessage, false);
1511
1512                         printf(": ");
1513                         utf_display_printable_ascii(u);
1514                 }
1515
1516                 putc('\n', stdout);
1517         }
1518 }
1519 #endif /* !defined(NDEBUG) */
1520
1521
1522 /*
1523  * These are local overrides for various environment variables in Emacs.
1524  * Please do not remove this and leave it at the end of the file, where
1525  * Emacs will automagically detect them.
1526  * ---------------------------------------------------------------------
1527  * Local variables:
1528  * mode: c
1529  * indent-tabs-mode: t
1530  * c-basic-offset: 4
1531  * tab-width: 4
1532  * End:
1533  * vim:noexpandtab:sw=4:ts=4:
1534  */