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