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