* src/vm/exceptions.c (exceptions_handle_exception): Typo.
[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 5059 2006-06-28 21:51:56Z 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_asm_new_abstractmethoderror **************************************
523
524    Generates a java.lang.AbstractMethodError for
525    asm_abstractmethoderror.
526
527 *******************************************************************************/
528
529 java_objectheader *exceptions_asm_new_abstractmethoderror(u1 *sp, u1 *ra)
530 {
531         stackframeinfo     sfi;
532         java_objectheader *e;
533
534         /* create the stackframeinfo (XPC is equal to RA) */
535
536         stacktrace_create_extern_stackframeinfo(&sfi, NULL, sp, ra, ra);
537
538         /* create the exception */
539
540         e = exceptions_new_abstractmethoderror();
541
542         /* remove the stackframeinfo */
543
544         stacktrace_remove_stackframeinfo(&sfi);
545
546         return e;
547 }
548
549
550 /* exceptions_throw_abstractmethoderror ****************************************
551
552    Generates a java.lang.AbstractMethodError for the VM and throws it.
553
554 *******************************************************************************/
555
556 void exceptions_throw_abstractmethoderror(void)
557 {
558         *exceptionptr = exceptions_new_abstractmethoderror();
559 }
560
561
562 /* new_classformaterror ********************************************************
563
564    generates a java.lang.ClassFormatError for the classloader
565
566    IN:
567       c............the class in which the error was found
568           message......UTF-8 format string
569
570    RETURN VALUE:
571       an exception pointer (in any case -- either it is the newly created
572           exception, or an exception thrown while trying to create it).
573
574 *******************************************************************************/
575
576 java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
577 {
578         java_objectheader *o;
579         char              *msg;
580         s4                 msglen;
581         va_list            ap;
582
583         /* calculate message length */
584
585         msglen = 0;
586
587         if (c)
588                 msglen += utf_bytes(c->name) + strlen(" (");
589
590         va_start(ap, message);
591         msglen += get_variable_message_length(message, ap);
592         va_end(ap);
593
594         if (c)
595                 msglen += strlen(")");
596
597         msglen += strlen("0");
598
599         /* allocate a buffer */
600
601         msg = MNEW(char, msglen);
602
603         /* print message into allocated buffer */
604
605         if (c) {
606                 utf_copy_classname(msg, c->name);
607                 strcat(msg, " (");
608         }
609
610         va_start(ap, message);
611         vsprintf(msg + strlen(msg), message, ap);
612         va_end(ap);
613
614         if (c)
615                 strcat(msg, ")");
616
617         o = new_exception_message(string_java_lang_ClassFormatError, msg);
618
619         MFREE(msg, char, msglen);
620
621         return o;
622 }
623
624
625 /* exceptions_throw_classformaterror *******************************************
626
627    Generate a java.lang.ClassFormatError for the VM system and throw it.
628
629    IN:
630       c............the class in which the error was found
631           message......UTF-8 format string
632
633    RETURN VALUE:
634       an exception pointer (in any case -- either it is the newly created
635           exception, or an exception thrown while trying to create it).
636
637 *******************************************************************************/
638
639 void exceptions_throw_classformaterror(classinfo *c, const char *message, ...)
640 {
641         va_list ap;
642
643         va_start(ap, message);
644         *exceptionptr = new_classformaterror(c, message, ap);
645         va_end(ap);
646 }
647
648
649 /* new_classnotfoundexception **************************************************
650
651    Generates a java.lang.ClassNotFoundException for the classloader.
652
653    IN:
654       name.........name of the class not found as a utf *
655
656    RETURN VALUE:
657       an exception pointer (in any case -- either it is the newly created
658           exception, or an exception thrown while trying to create it).
659
660 *******************************************************************************/
661
662 java_objectheader *new_classnotfoundexception(utf *name)
663 {
664         java_objectheader *o;
665         java_lang_String  *s;
666
667         s = javastring_new(name);
668         if (!s)
669                 return *exceptionptr;
670
671         o = native_new_and_init_string(class_java_lang_ClassNotFoundException, s);
672
673         if (!o)
674                 return *exceptionptr;
675
676         return o;
677 }
678
679
680 /* new_noclassdeffounderror ****************************************************
681
682    Generates a java.lang.NoClassDefFoundError
683
684    IN:
685       name.........name of the class not found as a utf *
686
687    RETURN VALUE:
688       an exception pointer (in any case -- either it is the newly created
689           exception, or an exception thrown while trying to create it).
690
691 *******************************************************************************/
692
693 java_objectheader *new_noclassdeffounderror(utf *name)
694 {
695         java_objectheader *o;
696         java_lang_String  *s;
697
698         s = javastring_new(name);
699         if (!s)
700                 return *exceptionptr;
701
702         o = native_new_and_init_string(class_java_lang_NoClassDefFoundError, s);
703
704         if (!o)
705                 return *exceptionptr;
706
707         return o;
708 }
709
710
711 /* classnotfoundexception_to_noclassdeffounderror ******************************
712
713    Check the *exceptionptr for a ClassNotFoundException. If it is one,
714    convert it to a NoClassDefFoundError.
715
716 *******************************************************************************/
717
718 void classnotfoundexception_to_noclassdeffounderror(void)
719 {
720         java_objectheader *xptr;
721         java_objectheader *cause;
722
723         /* get the cause */
724
725         cause = *exceptionptr;
726
727         /* convert ClassNotFoundException's to NoClassDefFoundError's */
728
729         if (builtin_instanceof(cause, class_java_lang_ClassNotFoundException)) {
730                 /* clear exception, because we are calling jit code again */
731
732                 *exceptionptr = NULL;
733
734                 /* create new error */
735
736                 xptr =
737                         new_exception_javastring(string_java_lang_NoClassDefFoundError,
738                                         ((java_lang_Throwable *) cause)->detailMessage);
739
740                 /* we had an exception while creating the error */
741
742                 if (*exceptionptr)
743                         return;
744
745                 /* set new exception */
746
747                 *exceptionptr = xptr;
748         }
749 }
750
751
752 /* new_internalerror ***********************************************************
753
754    Generates a java.lang.InternalError for the VM.
755
756    IN:
757       message......UTF-8 message format string
758
759    RETURN VALUE:
760       an exception pointer (in any case -- either it is the newly created
761           exception, or an exception thrown while trying to create it).
762
763 *******************************************************************************/
764
765 java_objectheader *new_internalerror(const char *message, ...)
766 {
767         java_objectheader *o;
768         va_list            ap;
769         char              *msg;
770         s4                 msglen;
771
772         /* calculate exception message length */
773
774         va_start(ap, message);
775         msglen = get_variable_message_length(message, ap);
776         va_end(ap);
777
778         /* allocate memory */
779
780         msg = MNEW(char, msglen);
781
782         /* generate message */
783
784         va_start(ap, message);
785         vsprintf(msg, message, ap);
786         va_end(ap);
787
788         /* create exception object */
789
790         o = new_exception_message(string_java_lang_InternalError, msg);
791
792         /* free memory */
793
794         MFREE(msg, char, msglen);
795
796         return o;
797 }
798
799
800 /* exceptions_new_linkageerror *************************************************
801
802    Generates a java.lang.LinkageError with an error message.
803
804    IN:
805       message......UTF-8 message
806           c............class related to the error. If this is != NULL
807                        the name of c is appended to the error message.
808
809    RETURN VALUE:
810       an exception pointer (in any case -- either it is the newly created
811           exception, or an exception thrown while trying to create it).
812
813 *******************************************************************************/
814
815 java_objectheader *exceptions_new_linkageerror(const char *message,
816                                                                                            classinfo *c)
817 {
818         java_objectheader *o;
819         char              *msg;
820         s4                 msglen;
821
822         /* calculate exception message length */
823
824         msglen = strlen(message) + 1;
825         if (c) {
826                 msglen += utf_bytes(c->name);
827         }
828                 
829         /* allocate memory */
830
831         msg = MNEW(char, msglen);
832
833         /* generate message */
834
835         strcpy(msg,message);
836         if (c) {
837                 utf_cat_classname(msg, c->name);
838         }
839
840         o = native_new_and_init_string(class_java_lang_LinkageError,
841                                                                    javastring_new_from_utf_string(msg));
842
843         /* free memory */
844
845         MFREE(msg, char, msglen);
846
847         if (!o)
848                 return *exceptionptr;
849
850         return o;
851 }
852
853
854 /* exceptions_new_nosuchmethoderror ********************************************
855
856    Generates a java.lang.NoSuchMethodError with an error message.
857
858    IN:
859       c............class in which the method was not found
860           name.........name of the method
861           desc.........descriptor of the method
862
863    RETURN VALUE:
864       an exception pointer (in any case -- either it is the newly created
865           exception, or an exception thrown while trying to create it).
866
867 *******************************************************************************/
868
869 java_objectheader *exceptions_new_nosuchmethoderror(classinfo *c,
870                                                                                                         utf *name, utf *desc)
871 {
872         java_objectheader *o;
873         char              *msg;
874         s4                 msglen;
875
876         /* calculate exception message length */
877
878         msglen = utf_bytes(c->name) + strlen(".") + utf_bytes(name) +
879                 utf_bytes(desc) + strlen("0");
880
881         /* allocate memory */
882
883         msg = MNEW(char, msglen);
884
885         /* generate message */
886
887         utf_copy_classname(msg, c->name);
888         strcat(msg, ".");
889         utf_cat(msg, name);
890         utf_cat(msg, desc);
891
892         o = native_new_and_init_string(class_java_lang_NoSuchMethodError,
893                                                                    javastring_new_from_utf_string(msg));
894
895         /* free memory */
896
897         MFREE(msg, char, msglen);
898
899         if (!o)
900                 return *exceptionptr;
901
902         return o;
903 }
904
905
906 /* exceptions_throw_nosuchmethoderror ******************************************
907
908    Generates a java.lang.NoSuchMethodError with an error message.
909
910    IN:
911       c............class in which the method was not found
912           name.........name of the method
913           desc.........descriptor of the method
914
915 *******************************************************************************/
916
917 void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc)
918 {
919         *exceptionptr = exceptions_new_nosuchmethoderror(c, name, desc);
920 }
921
922
923 /* new_unsupportedclassversionerror ********************************************
924
925    Generate a java.lang.UnsupportedClassVersionError for the classloader
926
927    IN:
928       c............class in which the method was not found
929           message......UTF-8 format string
930
931    RETURN VALUE:
932       an exception pointer (in any case -- either it is the newly created
933           exception, or an exception thrown while trying to create it).
934
935 *******************************************************************************/
936
937 java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *message, ...)
938 {
939         java_objectheader *o;
940         va_list            ap;
941         char              *msg;
942     s4                 msglen;
943
944         /* calculate exception message length */
945
946         msglen = utf_bytes(c->name) + strlen(" (") + strlen(")") + strlen("0");
947
948         va_start(ap, message);
949         msglen += get_variable_message_length(message, ap);
950         va_end(ap);
951
952         /* allocate memory */
953
954         msg = MNEW(char, msglen);
955
956         /* generate message */
957
958         utf_copy_classname(msg, c->name);
959         strcat(msg, " (");
960
961         va_start(ap, message);
962         vsprintf(msg + strlen(msg), message, ap);
963         va_end(ap);
964
965         strcat(msg, ")");
966
967         /* create exception object */
968
969         o = new_exception_message(string_java_lang_UnsupportedClassVersionError,
970                                                           msg);
971
972         /* free memory */
973
974         MFREE(msg, char, msglen);
975
976         return o;
977 }
978
979
980 /* new_verifyerror *************************************************************
981
982    Generates a java.lang.VerifyError for the JIT compiler.
983
984    IN:
985       m............method in which the error was found
986           message......UTF-8 format string
987
988    RETURN VALUE:
989       an exception pointer (in any case -- either it is the newly created
990           exception, or an exception thrown while trying to create it).
991
992 *******************************************************************************/
993
994 java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
995 {
996         java_objectheader *o;
997         va_list            ap;
998         char              *msg;
999         s4                 msglen;
1000
1001         useinlining = false; /* at least until sure inlining works with exceptions*/
1002
1003         /* calculate exception message length */
1004
1005         msglen = 0;
1006
1007         if (m)
1008                 msglen = strlen("(class: ") + utf_bytes(m->class->name) +
1009                         strlen(", method: ") + utf_bytes(m->name) +
1010                         strlen(" signature: ") + utf_bytes(m->descriptor) +
1011                         strlen(") ") + strlen("0");
1012
1013         va_start(ap, message);
1014         msglen += get_variable_message_length(message, ap);
1015         va_end(ap);
1016
1017         /* allocate memory */
1018
1019         msg = MNEW(char, msglen);
1020
1021         /* generate message */
1022
1023         if (m) {
1024                 strcpy(msg, "(class: ");
1025                 utf_cat_classname(msg, m->class->name);
1026                 strcat(msg, ", method: ");
1027                 utf_cat(msg, m->name);
1028                 strcat(msg, " signature: ");
1029                 utf_cat(msg, m->descriptor);
1030                 strcat(msg, ") ");
1031         }
1032
1033         va_start(ap, message);
1034         vsprintf(msg + strlen(msg), message, ap);
1035         va_end(ap);
1036
1037         /* create exception object */
1038
1039         o = new_exception_message(string_java_lang_VerifyError, msg);
1040
1041         /* free memory */
1042
1043         MFREE(msg, char, msglen);
1044
1045         return o;
1046 }
1047
1048
1049 /* exceptions_throw_verifyerror_for_stack **************************************
1050
1051    throws a java.lang.VerifyError for an invalid stack slot type
1052
1053    IN:
1054       m............method in which the error was found
1055           type.........the expected type
1056
1057    RETURN VALUE:
1058       an exception pointer (in any case -- either it is the newly created
1059           exception, or an exception thrown while trying to create it).
1060
1061 *******************************************************************************/
1062
1063 void exceptions_throw_verifyerror_for_stack(methodinfo *m,int type)
1064 {
1065         java_objectheader *o;
1066         char              *msg;
1067         s4                 msglen;
1068         char              *typename;
1069
1070         /* calculate exception message length */
1071
1072         msglen = 0;
1073
1074         if (m)
1075                 msglen = strlen("(class: ") + utf_bytes(m->class->name) +
1076                         strlen(", method: ") + utf_bytes(m->name) +
1077                         strlen(" signature: ") + utf_bytes(m->descriptor) +
1078                         strlen(") Expecting to find longest-------typename on stack") 
1079                         + strlen("0");
1080
1081         /* allocate memory */
1082
1083         msg = MNEW(char, msglen);
1084
1085         /* generate message */
1086
1087         if (m) {
1088                 strcpy(msg, "(class: ");
1089                 utf_cat_classname(msg, m->class->name);
1090                 strcat(msg, ", method: ");
1091                 utf_cat(msg, m->name);
1092                 strcat(msg, " signature: ");
1093                 utf_cat(msg, m->descriptor);
1094                 strcat(msg, ") ");
1095         }
1096         else {
1097                 msg[0] = 0;
1098         }
1099
1100         strcat(msg,"Expecting to find ");
1101         switch (type) {
1102                 case TYPE_INT: typename = "integer"; break;
1103                 case TYPE_LNG: typename = "long"; break;
1104                 case TYPE_FLT: typename = "float"; break;
1105                 case TYPE_DBL: typename = "double"; break;
1106                 case TYPE_ADR: typename = "object/array"; break;
1107                 default:       typename = "<INVALID>"; assert(0); break;
1108         }
1109         strcat(msg, typename);
1110         strcat(msg, " on stack");
1111
1112         /* create exception object */
1113
1114         o = new_exception_message(string_java_lang_VerifyError, msg);
1115
1116         /* free memory */
1117
1118         MFREE(msg, char, msglen);
1119
1120         *exceptionptr = o;
1121 }
1122
1123
1124 /* new_arithmeticexception *****************************************************
1125
1126    Generates a java.lang.ArithmeticException for the jit compiler.
1127
1128 *******************************************************************************/
1129
1130 java_objectheader *new_arithmeticexception(void)
1131 {
1132         java_objectheader *e;
1133
1134         e = new_exception_message(string_java_lang_ArithmeticException,
1135                                                           string_java_lang_ArithmeticException_message);
1136
1137         if (!e)
1138                 return *exceptionptr;
1139
1140         return e;
1141 }
1142
1143
1144 /* exceptions_new_arrayindexoutofboundsexception *******************************
1145
1146    Generates a java.lang.ArrayIndexOutOfBoundsException for the VM
1147    system.
1148
1149 *******************************************************************************/
1150
1151 java_objectheader *new_arrayindexoutofboundsexception(s4 index)
1152 {
1153         java_objectheader *e;
1154         methodinfo        *m;
1155         java_objectheader *o;
1156         java_lang_String  *s;
1157
1158         /* convert the index into a String, like Sun does */
1159
1160         m = class_resolveclassmethod(class_java_lang_String,
1161                                                                  utf_new_char("valueOf"),
1162                                                                  utf_new_char("(I)Ljava/lang/String;"),
1163                                                                  class_java_lang_Object,
1164                                                                  true);
1165
1166         if (m == NULL)
1167                 return *exceptionptr;
1168
1169         o = vm_call_method(m, NULL, index);
1170
1171         s = (java_lang_String *) o;
1172
1173         if (s == NULL)
1174                 return *exceptionptr;
1175
1176         e = new_exception_javastring(string_java_lang_ArrayIndexOutOfBoundsException,
1177                                                                  s);
1178
1179         if (e == NULL)
1180                 return *exceptionptr;
1181
1182         return e;
1183 }
1184
1185
1186 /* exceptions_throw_arrayindexoutofboundsexception *****************************
1187
1188    Generates a java.lang.ArrayIndexOutOfBoundsException for the VM
1189    system.
1190
1191 *******************************************************************************/
1192
1193 void exceptions_throw_arrayindexoutofboundsexception(void)
1194 {
1195         java_objectheader *e;
1196
1197         e = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
1198
1199         if (!e)
1200                 return;
1201
1202         *exceptionptr = e;
1203 }
1204
1205
1206 /* new_arraystoreexception *****************************************************
1207
1208    generates a java.lang.ArrayStoreException for the jit compiler
1209
1210 *******************************************************************************/
1211
1212 java_objectheader *new_arraystoreexception(void)
1213 {
1214         java_objectheader *e;
1215
1216         e = new_exception(string_java_lang_ArrayStoreException);
1217 /*      e = native_new_and_init(class_java_lang_ArrayStoreException); */
1218
1219         if (!e)
1220                 return *exceptionptr;
1221
1222         return e;
1223 }
1224
1225
1226 /* new_classcastexception ******************************************************
1227
1228    generates a java.lang.ClassCastException for the jit compiler
1229
1230 *******************************************************************************/
1231
1232 java_objectheader *new_classcastexception(void)
1233 {
1234         java_objectheader *e;
1235
1236         e = new_exception(string_java_lang_ClassCastException);
1237
1238         if (!e)
1239                 return *exceptionptr;
1240
1241         return e;
1242 }
1243
1244
1245 /* exceptions_new_illegalargumentexception *************************************
1246
1247    Generates a java.lang.IllegalArgumentException for the VM system.
1248
1249 *******************************************************************************/
1250
1251 java_objectheader *new_illegalargumentexception(void)
1252 {
1253         java_objectheader *e;
1254
1255         e = native_new_and_init(class_java_lang_IllegalArgumentException);
1256
1257         if (!e)
1258                 return *exceptionptr;
1259
1260         return e;
1261 }
1262
1263
1264 /* exceptions_throw_illegalargumentexception ***********************************
1265
1266    Generates a java.lang.IllegalArgumentException for the VM system
1267    and throw it in the VM system.
1268
1269 *******************************************************************************/
1270
1271 void exceptions_throw_illegalargumentexception(void)
1272 {
1273         *exceptionptr = new_illegalargumentexception();
1274 }
1275
1276
1277 /* new_illegalmonitorstateexception ********************************************
1278
1279    Generates a java.lang.IllegalMonitorStateException for the VM
1280    thread system.
1281
1282 *******************************************************************************/
1283
1284 java_objectheader *new_illegalmonitorstateexception(void)
1285 {
1286         java_objectheader *e;
1287
1288         e = native_new_and_init(class_java_lang_IllegalMonitorStateException);
1289
1290         if (!e)
1291                 return *exceptionptr;
1292
1293         return e;
1294 }
1295
1296
1297 /* exceptions_new_negativearraysizeexception ***********************************
1298
1299    Generates a java.lang.NegativeArraySizeException for the VM system.
1300
1301 *******************************************************************************/
1302
1303 java_objectheader *new_negativearraysizeexception(void)
1304 {
1305         java_objectheader *e;
1306
1307         e = new_exception(string_java_lang_NegativeArraySizeException);
1308
1309         if (!e)
1310                 return *exceptionptr;
1311
1312         return e;
1313 }
1314
1315
1316 /* exceptions_throw_negativearraysizeexception *********************************
1317
1318    Generates a java.lang.NegativeArraySizeException for the VM system.
1319
1320 *******************************************************************************/
1321
1322 void exceptions_throw_negativearraysizeexception(void)
1323 {
1324         *exceptionptr = new_negativearraysizeexception();
1325 }
1326
1327
1328 /* new_nullpointerexception ****************************************************
1329
1330    generates a java.lang.NullPointerException for the jit compiler
1331
1332 *******************************************************************************/
1333
1334 java_objectheader *new_nullpointerexception(void)
1335 {
1336         java_objectheader *e;
1337
1338         e = native_new_and_init(class_java_lang_NullPointerException);
1339
1340         if (!e)
1341                 return *exceptionptr;
1342
1343         return e;
1344 }
1345
1346
1347 /* exceptions_throw_nullpointerexception ***************************************
1348
1349    Generates a java.lang.NullPointerException for the VM system and
1350    throw it in the VM system.
1351
1352 *******************************************************************************/
1353
1354 void exceptions_throw_nullpointerexception(void)
1355 {
1356         *exceptionptr = new_nullpointerexception();
1357 }
1358
1359
1360 /* exceptions_new_stringindexoutofboundsexception ******************************
1361
1362    Generates a java.lang.StringIndexOutOfBoundsException for the VM
1363    system.
1364
1365 *******************************************************************************/
1366
1367 java_objectheader *exceptions_new_stringindexoutofboundsexception(void)
1368 {
1369         java_objectheader *e;
1370
1371         e = new_exception(string_java_lang_StringIndexOutOfBoundsException);
1372
1373         if (e == NULL)
1374                 return *exceptionptr;
1375
1376         return e;
1377 }
1378
1379
1380 /* exceptions_throw_stringindexoutofboundsexception ****************************
1381
1382    Throws a java.lang.StringIndexOutOfBoundsException for the VM
1383    system.
1384
1385 *******************************************************************************/
1386
1387 void exceptions_throw_stringindexoutofboundsexception(void)
1388 {
1389         *exceptionptr = exceptions_new_stringindexoutofboundsexception();
1390 }
1391
1392
1393 /* exceptions_handle_exception *************************************************
1394
1395    Try to find an exception handler for the given exception and return it.
1396    If no handler is found, exit the monitor of the method (if any)
1397    and return NULL.
1398
1399    IN:
1400       xptr.........the exception object
1401           xpc..........PC of where the exception was thrown
1402           pv...........Procedure Value of the current method
1403           sp...........current stack pointer
1404
1405    RETURN VALUE:
1406       the address of the first matching exception handler, or
1407           NULL if no handler was found
1408
1409 *******************************************************************************/
1410
1411 u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp)
1412 {
1413         methodinfo            *m;
1414         codeinfo              *code;
1415         s4                     framesize;
1416         s4                     issync;
1417         exceptionentry        *ex;
1418         s4                     exceptiontablelength;
1419         s4                     i;
1420         classref_or_classinfo  cr;
1421         classinfo             *c;
1422 #if defined(ENABLE_THREADS)
1423         java_objectheader     *o;
1424 #endif
1425
1426         /* get info from the method header */
1427
1428         code                 = *((codeinfo **)      (pv + CodeinfoPointer));
1429         framesize            = *((s4 *)             (pv + FrameSize));
1430         issync               = *((s4 *)             (pv + IsSync));
1431         ex                   =   (exceptionentry *) (pv + ExTableStart);
1432         exceptiontablelength = *((s4 *)             (pv + ExTableSize));
1433
1434         /* Get the methodinfo pointer from the codeinfo pointer. For
1435            asm_vm_call_method the codeinfo pointer is NULL. */
1436
1437         m = (code == NULL) ? NULL : code->m;
1438
1439 #if !defined(NDEBUG)
1440         /* print exception trace */
1441
1442         if (opt_verbose || opt_verbosecall || opt_verboseexception)
1443                 builtin_trace_exception(xptr, m, xpc, 1);
1444 #endif
1445
1446         for (i = 0; i < exceptiontablelength; i++) {
1447                 /* ATTENTION: keep this here, as we need to decrement the
1448            pointer before the loop executes! */
1449
1450                 ex--;
1451
1452                 /* If the start and end PC is NULL, this means we have the
1453                    special case of asm_vm_call_method.  So, just return the
1454                    proper exception handler. */
1455
1456                 if ((ex->startpc == NULL) && (ex->endpc == NULL))
1457                         return (u1 *) (ptrint) &asm_vm_call_method_exception_handler;
1458
1459                 /* is the xpc is the current catch range */
1460
1461                 if ((ex->startpc <= xpc) && (xpc < ex->endpc)) {
1462                         cr = ex->catchtype;
1463
1464                         /* NULL catches everything */
1465
1466                         if (cr.any == NULL) {
1467 #if !defined(NDEBUG)
1468                                 /* Print stacktrace of exception when caught. */
1469
1470                                 if (opt_verboseexception) {
1471                                         exceptions_print_exception(xptr);
1472                                         stacktrace_print_trace(xptr);
1473                                 }
1474 #endif
1475
1476                                 return ex->handlerpc;
1477                         }
1478
1479                         /* resolve or load/link the exception class */
1480
1481                         if (IS_CLASSREF(cr)) {
1482                                 c = resolve_classref_eager(cr.ref);
1483
1484                         } else {
1485                                 c = cr.cls;
1486
1487                                 if (!(c->state & CLASS_LOADED))
1488                                         /* use the methods' classloader */
1489                                         if (!load_class_from_classloader(c->name,
1490                                                                                                          m->class->classloader))
1491                                                 return NULL;
1492
1493                                 if (!(c->state & CLASS_LINKED))
1494                                         if (!link_class(c))
1495                                                 return NULL;
1496                         }
1497
1498                         /* is the thrown exception an instance of the catch class? */
1499
1500                         if (builtin_instanceof(xptr, c)) {
1501 #if !defined(NDEBUG)
1502                                 /* Print stacktrace of exception when caught. */
1503
1504                                 if (opt_verboseexception) {
1505                                         exceptions_print_exception(xptr);
1506                                         stacktrace_print_trace(xptr);
1507                                 }
1508 #endif
1509
1510                                 return ex->handlerpc;
1511                         }
1512                 }
1513         }
1514
1515 #if defined(ENABLE_THREADS)
1516         /* is this method synchronized? */
1517
1518         if (issync) {
1519                 /* get synchronization object */
1520
1521 # if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1522                 /* XXX change this if we ever want to use 4-byte stackslots */
1523                 o = *((java_objectheader **) (sp + issync - 8));
1524 # else
1525                 o = *((java_objectheader **) (sp + issync - SIZEOF_VOID_P));
1526 #endif
1527
1528                 assert(o != NULL);
1529
1530                 builtin_monitorexit(o);
1531         }
1532 #endif
1533
1534         /* none of the exceptions catch this one */
1535
1536         return NULL;
1537 }
1538
1539
1540 /* exceptions_print_exception **************************************************
1541
1542    Prints an exception, the detail message and the cause, if
1543    available, with CACAO internal functions to stdout.
1544
1545 *******************************************************************************/
1546
1547 #if !defined(NDEBUG)
1548 void exceptions_print_exception(java_objectheader *xptr)
1549 {
1550         java_lang_Throwable   *t;
1551         java_lang_Throwable   *cause;
1552         utf                   *u;
1553
1554         t = (java_lang_Throwable *) xptr;
1555
1556         if (t == NULL) {
1557                 puts("NULL\n");
1558                 return;
1559         }
1560
1561         cause = t->cause;
1562
1563         /* print the root exception */
1564
1565         utf_display_printable_ascii_classname(t->header.vftbl->class->name);
1566
1567         if (t->detailMessage) {
1568                 u = javastring_toutf(t->detailMessage, false);
1569
1570                 printf(": ");
1571                 utf_display_printable_ascii(u);
1572         }
1573
1574         putc('\n', stdout);
1575
1576         /* print the cause if available */
1577
1578         if (cause && (cause != t)) {
1579                 printf("Caused by: ");
1580                 utf_display_printable_ascii_classname(cause->header.vftbl->class->name);
1581
1582                 if (cause->detailMessage) {
1583                         u = javastring_toutf(cause->detailMessage, false);
1584
1585                         printf(": ");
1586                         utf_display_printable_ascii(u);
1587                 }
1588
1589                 putc('\n', stdout);
1590         }
1591 }
1592 #endif /* !defined(NDEBUG) */
1593
1594
1595 /*
1596  * These are local overrides for various environment variables in Emacs.
1597  * Please do not remove this and leave it at the end of the file, where
1598  * Emacs will automagically detect them.
1599  * ---------------------------------------------------------------------
1600  * Local variables:
1601  * mode: c
1602  * indent-tabs-mode: t
1603  * c-basic-offset: 4
1604  * tab-width: 4
1605  * End:
1606  * vim:noexpandtab:sw=4:ts=4:
1607  */