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