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