* Updated header: Added 2006. Changed address of FSF. Changed email
[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 4357 2006-01-22 23:33:38Z 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
190                 if (pss) {
191                         ASM_CALLJAVAFUNCTION(pss, xptr, NULL, NULL, NULL);
192
193                         /* This normally means, we are EXTREMLY out of memory or have a   */
194                         /* serious problem while printStackTrace. But may be another      */
195                         /* exception, so print it.                                        */
196
197                         if (*exceptionptr) {
198                                 java_lang_Throwable *t;
199
200                                 t = (java_lang_Throwable *) *exceptionptr;
201
202                                 fprintf(stderr, "Exception while printStackTrace(): ");
203                                 utf_fprint_classname(stderr, t->header.vftbl->class->name);
204
205                                 if (t->detailMessage) {
206                                         char *buf;
207
208                                         buf = javastring_tochar((java_objectheader *) t->detailMessage);
209                                         fprintf(stderr, ": %s", buf);
210                                         MFREE(buf, char, strlen(buf));
211                                 }
212                                         
213                                 fprintf(stderr, "\n");
214                         }
215
216                 } else {
217                         utf_fprint_classname(stderr, c->name);
218                         fprintf(stderr, ": printStackTrace()V not found!\n");
219                 }
220
221                 fflush(stderr);
222
223                 /* good bye! */
224
225                 if (doexit)
226                         exit(1);
227         }
228 }
229
230
231 void throw_exception(void)
232 {
233         throw_exception_exit_intern(false);
234 }
235
236
237 void throw_exception_exit(void)
238 {
239         throw_exception_exit_intern(true);
240 }
241
242
243 void throw_main_exception(void)
244 {
245         fprintf(stderr, "Exception in thread \"main\" ");
246         fflush(stderr);
247
248         throw_exception_exit_intern(false);
249 }
250
251
252 void throw_main_exception_exit(void)
253 {
254         fprintf(stderr, "Exception in thread \"main\" ");
255         fflush(stderr);
256
257         throw_exception_exit_intern(true);
258 }
259
260
261 void throw_cacao_exception_exit(const char *exception, const char *message, ...)
262 {
263         s4 i;
264         char *tmp;
265         s4 len;
266         va_list ap;
267
268         len = strlen(exception);
269         tmp = MNEW(char, len + 1);
270         strncpy(tmp, exception, len);
271         tmp[len] = '\0';
272
273         /* convert to classname */
274
275         for (i = len - 1; i >= 0; i--)
276                 if (tmp[i] == '/') tmp[i] = '.';
277
278         fprintf(stderr, "Exception in thread \"main\" %s", tmp);
279
280         MFREE(tmp, char, len);
281
282         if (strlen(message) > 0) {
283                 fprintf(stderr, ": ");
284
285                 va_start(ap, message);
286                 vfprintf(stderr, message, ap);
287                 va_end(ap);
288         }
289
290         fprintf(stderr, "\n");
291         fflush(stderr);
292
293         /* good bye! */
294
295         exit(1);
296 }
297
298
299 /* exceptions_throw_outofmemory_exit *******************************************
300
301    Just print an: java.lang.InternalError: Out of memory
302
303 *******************************************************************************/
304
305 void exceptions_throw_outofmemory_exit(void)
306 {
307         throw_cacao_exception_exit(string_java_lang_InternalError,
308                                                            "Out of memory");
309 }
310
311
312 /* new_exception ***************************************************************
313
314    Creates an exception object with the given name and initalizes it.
315
316 *******************************************************************************/
317
318 java_objectheader *new_exception(const char *classname)
319 {
320         java_objectheader *o;
321         classinfo         *c;
322
323         if (!(c = load_class_bootstrap(utf_new_char(classname))))
324                 return *exceptionptr;
325
326         o = native_new_and_init(c);
327
328         if (!o)
329                 return *exceptionptr;
330
331         return o;
332 }
333
334
335 /* new_exception_message *******************************************************
336
337    Creates an exception object with the given name and initalizes it
338    with the given char message.
339
340 *******************************************************************************/
341
342 java_objectheader *new_exception_message(const char *classname,
343                                                                                  const char *message)
344 {
345         java_objectheader *o;
346         classinfo         *c;
347    
348         if (!(c = load_class_bootstrap(utf_new_char(classname))))
349                 return *exceptionptr;
350
351         o = native_new_and_init_string(c, javastring_new_char(message));
352
353         if (!o)
354                 return *exceptionptr;
355
356         return o;
357 }
358
359
360 /* new_exception_throwable *****************************************************
361
362    Creates an exception object with the given name and initalizes it
363    with the given java/lang/Throwable exception.
364
365 *******************************************************************************/
366
367 java_objectheader *new_exception_throwable(const char *classname,
368                                                                                    java_lang_Throwable *throwable)
369 {
370         java_objectheader *o;
371         classinfo         *c;
372    
373         if (!(c = load_class_bootstrap(utf_new_char(classname))))
374                 return *exceptionptr;
375
376         o = native_new_and_init_throwable(c, throwable);
377
378         if (!o)
379                 return *exceptionptr;
380
381         return o;
382 }
383
384
385 /* new_exception_utfmessage ****************************************************
386
387    Creates an exception object with the given name and initalizes it
388    with the given utf message.
389
390 *******************************************************************************/
391
392 java_objectheader *new_exception_utfmessage(const char *classname, utf *message)
393 {
394         java_objectheader *o;
395         classinfo         *c;
396    
397         if (!(c = load_class_bootstrap(utf_new_char(classname))))
398                 return *exceptionptr;
399
400         o = native_new_and_init_string(c, javastring_new(message));
401
402         if (!o)
403                 return *exceptionptr;
404
405         return o;
406 }
407
408
409 /* new_exception_javastring ****************************************************
410
411    Creates an exception object with the given name and initalizes it
412    with the given java/lang/String message.
413
414 *******************************************************************************/
415
416 java_objectheader *new_exception_javastring(const char *classname,
417                                                                                         java_lang_String *message)
418 {
419         java_objectheader *o;
420         classinfo         *c;
421    
422         if (!(c = load_class_bootstrap(utf_new_char(classname))))
423                 return *exceptionptr;
424
425         o = native_new_and_init_string(c, message);
426
427         if (!o)
428                 return *exceptionptr;
429
430         return o;
431 }
432
433
434 /* new_exception_int ***********************************************************
435
436    Creates an exception object with the given name and initalizes it
437    with the given int value.
438
439 *******************************************************************************/
440
441 java_objectheader *new_exception_int(const char *classname, s4 i)
442 {
443         java_objectheader *o;
444         classinfo         *c;
445    
446         if (!(c = load_class_bootstrap(utf_new_char(classname))))
447                 return *exceptionptr;
448
449         o = native_new_and_init_int(c, i);
450
451         if (!o)
452                 return *exceptionptr;
453
454         return o;
455 }
456
457
458 /* new_classformaterror ********************************************************
459
460    generates a java.lang.ClassFormatError for the classloader
461
462 *******************************************************************************/
463
464 java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
465 {
466         java_objectheader *o;
467         char              *msg;
468         s4                 msglen;
469         va_list            ap;
470
471         /* calculate message length */
472
473         msglen = 0;
474
475         if (c)
476                 msglen += utf_strlen(c->name) + strlen(" (");
477
478         va_start(ap, message);
479         msglen += get_variable_message_length(message, ap);
480         va_end(ap);
481
482         if (c)
483                 msglen += strlen(")");
484
485         msglen += strlen("0");
486
487         /* allocate a buffer */
488
489         msg = MNEW(char, msglen);
490
491         /* print message into allocated buffer */
492
493         if (c) {
494                 utf_sprint_classname(msg, c->name);
495                 strcat(msg, " (");
496         }
497
498         va_start(ap, message);
499         vsprintf(msg + strlen(msg), message, ap);
500         va_end(ap);
501
502         if (c)
503                 strcat(msg, ")");
504
505         o = new_exception_message(string_java_lang_ClassFormatError, msg);
506
507         MFREE(msg, char, msglen);
508
509         return o;
510 }
511
512
513 /* exceptions_throw_classformaterror *******************************************
514
515    Generates a java.lang.ClassFormatError for the VM system throw it
516    in the VM system.
517
518 *******************************************************************************/
519
520 void exceptions_throw_classformaterror(classinfo *c, const char *message, ...)
521 {
522         va_list ap;
523
524         va_start(ap, message);
525         *exceptionptr = new_classformaterror(c, message, ap);
526         va_end(ap);
527 }
528
529
530 /* new_classnotfoundexception **************************************************
531
532    Generates a java.lang.ClassNotFoundException for the classloader.
533
534 *******************************************************************************/
535
536 java_objectheader *new_classnotfoundexception(utf *name)
537 {
538         java_objectheader *o;
539
540         o = native_new_and_init_string(class_java_lang_ClassNotFoundException,
541                                                                    javastring_new(name));
542
543         if (!o)
544                 return *exceptionptr;
545
546         return o;
547 }
548
549
550 /* new_noclassdeffounderror ****************************************************
551
552    Generates a java.lang.NoClassDefFoundError
553
554 *******************************************************************************/
555
556 java_objectheader *new_noclassdeffounderror(utf *name)
557 {
558         java_objectheader *o;
559
560         o = native_new_and_init_string(class_java_lang_NoClassDefFoundError,
561                                                                    javastring_new(name));
562
563         if (!o)
564                 return *exceptionptr;
565
566         return o;
567 }
568
569
570 /* classnotfoundexception_to_noclassdeffounderror ******************************
571
572    Check the *exceptionptr for a ClassNotFoundException. If it is one,
573    convert it to a NoClassDefFoundError.
574
575 *******************************************************************************/
576
577 void classnotfoundexception_to_noclassdeffounderror(void)
578 {
579         java_objectheader *xptr;
580         java_objectheader *cause;
581
582         /* get the cause */
583
584         cause = *exceptionptr;
585
586         /* convert ClassNotFoundException's to NoClassDefFoundError's */
587
588         if (builtin_instanceof(cause, class_java_lang_ClassNotFoundException)) {
589                 /* clear exception, because we are calling jit code again */
590
591                 *exceptionptr = NULL;
592
593                 /* create new error */
594
595                 xptr =
596                         new_exception_javastring(string_java_lang_NoClassDefFoundError,
597                                         ((java_lang_Throwable *) cause)->detailMessage);
598
599                 /* we had an exception while creating the error */
600
601                 if (*exceptionptr)
602                         return;
603
604                 /* set new exception */
605
606                 *exceptionptr = xptr;
607         }
608 }
609
610
611 /* new_internalerror ***********************************************************
612
613    Generates a java.lang.InternalError for the VM.
614
615 *******************************************************************************/
616
617 java_objectheader *new_internalerror(const char *message, ...)
618 {
619         java_objectheader *o;
620         va_list            ap;
621         char              *msg;
622         s4                 msglen;
623
624         /* calculate exception message length */
625
626         va_start(ap, message);
627         msglen = get_variable_message_length(message, ap);
628         va_end(ap);
629
630         /* allocate memory */
631
632         msg = MNEW(char, msglen);
633
634         /* generate message */
635
636         va_start(ap, message);
637         vsprintf(msg, message, ap);
638         va_end(ap);
639
640         /* create exception object */
641
642         o = new_exception_message(string_java_lang_InternalError, msg);
643
644         /* free memory */
645
646         MFREE(msg, char, msglen);
647
648         return o;
649 }
650
651
652 /* exceptions_new_linkageerror *************************************************
653
654    Generates a java.lang.LinkageError with an error message.
655    If c != NULL, the name of c is appended to the error message.
656
657 *******************************************************************************/
658
659 java_objectheader *exceptions_new_linkageerror(const char *message,
660                                                                                            classinfo *c)
661 {
662         java_objectheader *o;
663         char              *msg;
664         s4                 msglen;
665
666         /* calculate exception message length */
667
668         msglen = strlen(message) + 1;
669         if (c) {
670                 msglen += utf_strlen(c->name);
671         }
672                 
673         /* allocate memory */
674
675         msg = MNEW(char, msglen);
676
677         /* generate message */
678
679         strcpy(msg,message);
680         if (c) {
681                 utf_strcat(msg, c->name);
682         }
683
684         o = native_new_and_init_string(class_java_lang_LinkageError,
685                                                                    javastring_new_char(msg));
686
687         /* free memory */
688
689         MFREE(msg, char, msglen);
690
691         return o;
692 }
693
694
695 /* exceptions_new_nosuchmethoderror ********************************************
696
697    Generates a java.lang.NoSuchMethodError with an error message.
698
699 *******************************************************************************/
700
701 java_objectheader *exceptions_new_nosuchmethoderror(classinfo *c,
702                                                                                                         utf *name, utf *desc)
703 {
704         java_objectheader *o;
705         char              *msg;
706         s4                 msglen;
707
708         /* calculate exception message length */
709
710         msglen = utf_strlen(c->name) + strlen(".") + utf_strlen(name) +
711                 utf_strlen(desc) + strlen("0");
712
713         /* allocate memory */
714
715         msg = MNEW(char, msglen);
716
717         /* generate message */
718
719         utf_sprint(msg, c->name);
720         strcat(msg, ".");
721         utf_strcat(msg, name);
722         utf_strcat(msg, desc);
723
724         o = native_new_and_init_string(class_java_lang_NoSuchMethodError,
725                                                                    javastring_new_char(msg));
726
727         /* free memory */
728
729         MFREE(msg, char, msglen);
730
731         return o;
732 }
733
734
735 /* new_unsupportedclassversionerror ********************************************
736
737    generates a java.lang.UnsupportedClassVersionError for the classloader
738
739 *******************************************************************************/
740
741 java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *message, ...)
742 {
743         java_objectheader *o;
744         va_list            ap;
745         char              *msg;
746     s4                 msglen;
747
748         /* calculate exception message length */
749
750         msglen = utf_strlen(c->name) + strlen(" (") + strlen(")") + strlen("0");
751
752         va_start(ap, message);
753         msglen += get_variable_message_length(message, ap);
754         va_end(ap);
755
756         /* allocate memory */
757
758         msg = MNEW(char, msglen);
759
760         /* generate message */
761
762         utf_sprint_classname(msg, c->name);
763         strcat(msg, " (");
764
765         va_start(ap, message);
766         vsprintf(msg + strlen(msg), message, ap);
767         va_end(ap);
768
769         strcat(msg, ")");
770
771         /* create exception object */
772
773         o = new_exception_message(string_java_lang_UnsupportedClassVersionError,
774                                                           msg);
775
776         /* free memory */
777
778         MFREE(msg, char, msglen);
779
780         return o;
781 }
782
783
784 /* new_verifyerror *************************************************************
785
786    generates a java.lang.VerifyError for the jit compiler
787
788 *******************************************************************************/
789
790 java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
791 {
792         java_objectheader *o;
793         va_list            ap;
794         char              *msg;
795         s4                 msglen;
796
797         useinlining = false; /* at least until sure inlining works with exceptions*/
798
799         /* calculate exception message length */
800
801         msglen = 0;
802
803         if (m)
804                 msglen = strlen("(class: ") + utf_strlen(m->class->name) +
805                         strlen(", method: ") + utf_strlen(m->name) +
806                         strlen(" signature: ") + utf_strlen(m->descriptor) +
807                         strlen(") ") + strlen("0");
808
809         va_start(ap, message);
810         msglen += get_variable_message_length(message, ap);
811         va_end(ap);
812
813         /* allocate memory */
814
815         msg = MNEW(char, msglen);
816
817         /* generate message */
818
819         if (m) {
820                 strcpy(msg, "(class: ");
821                 utf_strcat(msg, m->class->name);
822                 strcat(msg, ", method: ");
823                 utf_strcat(msg, m->name);
824                 strcat(msg, " signature: ");
825                 utf_strcat(msg, m->descriptor);
826                 strcat(msg, ") ");
827         }
828
829         va_start(ap, message);
830         vsprintf(msg + strlen(msg), message, ap);
831         va_end(ap);
832
833         /* create exception object */
834
835         o = new_exception_message(string_java_lang_VerifyError, msg);
836
837         /* free memory */
838
839         MFREE(msg, char, msglen);
840
841         return o;
842 }
843
844
845 /* new_arithmeticexception *****************************************************
846
847    Generates a java.lang.ArithmeticException for the jit compiler.
848
849 *******************************************************************************/
850
851 java_objectheader *new_arithmeticexception(void)
852 {
853         java_objectheader *e;
854
855         e = new_exception_message(string_java_lang_ArithmeticException,
856                                                           string_java_lang_ArithmeticException_message);
857
858         if (!e)
859                 return *exceptionptr;
860
861         return e;
862 }
863
864
865 /* exceptions_new_arrayindexoutofboundsexception *******************************
866
867    Generates a java.lang.ArrayIndexOutOfBoundsException for the VM
868    system.
869
870 *******************************************************************************/
871
872 java_objectheader *new_arrayindexoutofboundsexception(s4 index)
873 {
874         java_objectheader *e;
875         methodinfo        *m;
876         java_objectheader *o;
877         java_lang_String  *s;
878
879         /* convert the index into a String, like Sun does */
880
881         m = class_resolveclassmethod(class_java_lang_String,
882                                                                  utf_new_char("valueOf"),
883                                                                  utf_new_char("(I)Ljava/lang/String;"),
884                                                                  class_java_lang_Object,
885                                                                  true);
886
887         if (!m)
888                 return *exceptionptr;
889
890         ASM_CALLJAVAFUNCTION_ADR(o, m, (void *) (ptrint) index, NULL, NULL, NULL);
891
892         s = (java_lang_String *) o;
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  */