* src/vm/exceptions.c, src/vm/exceptions.h
[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 4484 2006-02-12 00:25:12Z 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 /* exceptions_throw_nosuchmethoderror ******************************************
736
737    Generates a java.lang.NoSuchMethodError with an error message.
738
739 *******************************************************************************/
740
741 void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc)
742 {
743         *exceptionptr = exceptions_new_nosuchmethoderror(c, name, desc);
744 }
745
746
747 /* new_unsupportedclassversionerror ********************************************
748
749    generates a java.lang.UnsupportedClassVersionError for the classloader
750
751 *******************************************************************************/
752
753 java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *message, ...)
754 {
755         java_objectheader *o;
756         va_list            ap;
757         char              *msg;
758     s4                 msglen;
759
760         /* calculate exception message length */
761
762         msglen = utf_strlen(c->name) + strlen(" (") + strlen(")") + strlen("0");
763
764         va_start(ap, message);
765         msglen += get_variable_message_length(message, ap);
766         va_end(ap);
767
768         /* allocate memory */
769
770         msg = MNEW(char, msglen);
771
772         /* generate message */
773
774         utf_sprint_classname(msg, c->name);
775         strcat(msg, " (");
776
777         va_start(ap, message);
778         vsprintf(msg + strlen(msg), message, ap);
779         va_end(ap);
780
781         strcat(msg, ")");
782
783         /* create exception object */
784
785         o = new_exception_message(string_java_lang_UnsupportedClassVersionError,
786                                                           msg);
787
788         /* free memory */
789
790         MFREE(msg, char, msglen);
791
792         return o;
793 }
794
795
796 /* new_verifyerror *************************************************************
797
798    generates a java.lang.VerifyError for the jit compiler
799
800 *******************************************************************************/
801
802 java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
803 {
804         java_objectheader *o;
805         va_list            ap;
806         char              *msg;
807         s4                 msglen;
808
809         useinlining = false; /* at least until sure inlining works with exceptions*/
810
811         /* calculate exception message length */
812
813         msglen = 0;
814
815         if (m)
816                 msglen = strlen("(class: ") + utf_strlen(m->class->name) +
817                         strlen(", method: ") + utf_strlen(m->name) +
818                         strlen(" signature: ") + utf_strlen(m->descriptor) +
819                         strlen(") ") + strlen("0");
820
821         va_start(ap, message);
822         msglen += get_variable_message_length(message, ap);
823         va_end(ap);
824
825         /* allocate memory */
826
827         msg = MNEW(char, msglen);
828
829         /* generate message */
830
831         if (m) {
832                 strcpy(msg, "(class: ");
833                 utf_strcat(msg, m->class->name);
834                 strcat(msg, ", method: ");
835                 utf_strcat(msg, m->name);
836                 strcat(msg, " signature: ");
837                 utf_strcat(msg, m->descriptor);
838                 strcat(msg, ") ");
839         }
840
841         va_start(ap, message);
842         vsprintf(msg + strlen(msg), message, ap);
843         va_end(ap);
844
845         /* create exception object */
846
847         o = new_exception_message(string_java_lang_VerifyError, msg);
848
849         /* free memory */
850
851         MFREE(msg, char, msglen);
852
853         return o;
854 }
855
856
857 /* exceptions_throw_verifyerror_for_stack **************************************
858
859    throws a java.lang.VerifyError for an invalid stack slot type
860
861 *******************************************************************************/
862
863 void exceptions_throw_verifyerror_for_stack(methodinfo *m,int type)
864 {
865         java_objectheader *o;
866         char              *msg;
867         s4                 msglen;
868         char              *typename;
869
870         /* calculate exception message length */
871
872         msglen = 0;
873
874         if (m)
875                 msglen = strlen("(class: ") + utf_strlen(m->class->name) +
876                         strlen(", method: ") + utf_strlen(m->name) +
877                         strlen(" signature: ") + utf_strlen(m->descriptor) +
878                         strlen(") Expecting to find longest-------typename on stack") 
879                         + strlen("0");
880
881         /* allocate memory */
882
883         msg = MNEW(char, msglen);
884
885         /* generate message */
886
887         if (m) {
888                 strcpy(msg, "(class: ");
889                 utf_strcat(msg, m->class->name);
890                 strcat(msg, ", method: ");
891                 utf_strcat(msg, m->name);
892                 strcat(msg, " signature: ");
893                 utf_strcat(msg, m->descriptor);
894                 strcat(msg, ") ");
895         }
896         else {
897                 msg[0] = 0;
898         }
899
900         strcat(msg,"Expecting to find ");
901         switch (type) {
902                 case TYPE_INT: typename = "integer"; break;
903                 case TYPE_LNG: typename = "long"; break;
904                 case TYPE_FLT: typename = "float"; break;
905                 case TYPE_DBL: typename = "double"; break;
906                 case TYPE_ADR: typename = "object/array"; break;
907                 default: assert(0);
908         }
909         strcat(msg, typename);
910         strcat(msg, " on stack");
911
912         /* create exception object */
913
914         o = new_exception_message(string_java_lang_VerifyError, msg);
915
916         /* free memory */
917
918         MFREE(msg, char, msglen);
919
920         *exceptionptr = o;
921 }
922
923 /* new_arithmeticexception *****************************************************
924
925    Generates a java.lang.ArithmeticException for the jit compiler.
926
927 *******************************************************************************/
928
929 java_objectheader *new_arithmeticexception(void)
930 {
931         java_objectheader *e;
932
933         e = new_exception_message(string_java_lang_ArithmeticException,
934                                                           string_java_lang_ArithmeticException_message);
935
936         if (!e)
937                 return *exceptionptr;
938
939         return e;
940 }
941
942
943 /* exceptions_new_arrayindexoutofboundsexception *******************************
944
945    Generates a java.lang.ArrayIndexOutOfBoundsException for the VM
946    system.
947
948 *******************************************************************************/
949
950 java_objectheader *new_arrayindexoutofboundsexception(s4 index)
951 {
952         java_objectheader *e;
953         methodinfo        *m;
954         java_objectheader *o;
955         java_lang_String  *s;
956
957         /* convert the index into a String, like Sun does */
958
959         m = class_resolveclassmethod(class_java_lang_String,
960                                                                  utf_new_char("valueOf"),
961                                                                  utf_new_char("(I)Ljava/lang/String;"),
962                                                                  class_java_lang_Object,
963                                                                  true);
964
965         if (!m)
966                 return *exceptionptr;
967
968         ASM_CALLJAVAFUNCTION_ADR(o, m, (void *) (ptrint) index, NULL, NULL, NULL);
969
970         s = (java_lang_String *) o;
971
972         if (!s)
973                 return *exceptionptr;
974
975         e = new_exception_javastring(string_java_lang_ArrayIndexOutOfBoundsException,
976                                                                  s);
977
978         if (!e)
979                 return *exceptionptr;
980
981         return e;
982 }
983
984
985 /* exceptions_throw_arrayindexoutofboundsexception *****************************
986
987    Generates a java.lang.ArrayIndexOutOfBoundsException for the VM
988    system.
989
990 *******************************************************************************/
991
992 void exceptions_throw_arrayindexoutofboundsexception(void)
993 {
994         java_objectheader *e;
995
996         e = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
997
998         if (!e)
999                 return;
1000
1001         *exceptionptr = e;
1002 }
1003
1004
1005 /* new_arraystoreexception *****************************************************
1006
1007    generates a java.lang.ArrayStoreException for the jit compiler
1008
1009 *******************************************************************************/
1010
1011 java_objectheader *new_arraystoreexception(void)
1012 {
1013         java_objectheader *e;
1014
1015         e = new_exception(string_java_lang_ArrayStoreException);
1016 /*      e = native_new_and_init(class_java_lang_ArrayStoreException); */
1017
1018         if (!e)
1019                 return *exceptionptr;
1020
1021         return e;
1022 }
1023
1024
1025 /* new_classcastexception ******************************************************
1026
1027    generates a java.lang.ClassCastException for the jit compiler
1028
1029 *******************************************************************************/
1030
1031 java_objectheader *new_classcastexception(void)
1032 {
1033         java_objectheader *e;
1034
1035         e = new_exception(string_java_lang_ClassCastException);
1036
1037         if (!e)
1038                 return *exceptionptr;
1039
1040         return e;
1041 }
1042
1043
1044 /* exceptions_new_illegalargumentexception *************************************
1045
1046    Generates a java.lang.IllegalArgumentException for the VM system.
1047
1048 *******************************************************************************/
1049
1050 java_objectheader *new_illegalargumentexception(void)
1051 {
1052         java_objectheader *e;
1053
1054         e = native_new_and_init(class_java_lang_IllegalArgumentException);
1055
1056         if (!e)
1057                 return *exceptionptr;
1058
1059         return e;
1060 }
1061
1062
1063 /* exceptions_throw_illegalargumentexception ***********************************
1064
1065    Generates a java.lang.IllegalArgumentException for the VM system
1066    and throw it in the VM system.
1067
1068 *******************************************************************************/
1069
1070 void exceptions_throw_illegalargumentexception(void)
1071 {
1072         *exceptionptr = new_illegalargumentexception();
1073 }
1074
1075
1076 /* new_illegalmonitorstateexception ********************************************
1077
1078    Generates a java.lang.IllegalMonitorStateException for the VM
1079    thread system.
1080
1081 *******************************************************************************/
1082
1083 java_objectheader *new_illegalmonitorstateexception(void)
1084 {
1085         java_objectheader *e;
1086
1087         e = native_new_and_init(class_java_lang_IllegalMonitorStateException);
1088
1089         if (!e)
1090                 return *exceptionptr;
1091
1092         return e;
1093 }
1094
1095
1096 /* exceptions_new_negativearraysizeexception ***********************************
1097
1098    Generates a java.lang.NegativeArraySizeException for the VM system.
1099
1100 *******************************************************************************/
1101
1102 java_objectheader *new_negativearraysizeexception(void)
1103 {
1104         java_objectheader *e;
1105
1106         e = new_exception(string_java_lang_NegativeArraySizeException);
1107
1108         if (!e)
1109                 return *exceptionptr;
1110
1111         return e;
1112 }
1113
1114
1115 /* exceptions_throw_negativearraysizeexception *********************************
1116
1117    Generates a java.lang.NegativeArraySizeException for the VM system.
1118
1119 *******************************************************************************/
1120
1121 void exceptions_throw_negativearraysizeexception(void)
1122 {
1123         *exceptionptr = new_negativearraysizeexception();
1124 }
1125
1126
1127 /* new_nullpointerexception ****************************************************
1128
1129    generates a java.lang.NullPointerException for the jit compiler
1130
1131 *******************************************************************************/
1132
1133 java_objectheader *new_nullpointerexception(void)
1134 {
1135         java_objectheader *e;
1136
1137         e = native_new_and_init(class_java_lang_NullPointerException);
1138
1139         if (!e)
1140                 return *exceptionptr;
1141
1142         return e;
1143 }
1144
1145
1146 /* exceptions_throw_nullpointerexception ***************************************
1147
1148    Generates a java.lang.NullPointerException for the VM system and
1149    throw it in the VM system.
1150
1151 *******************************************************************************/
1152
1153 void exceptions_throw_nullpointerexception(void)
1154 {
1155         *exceptionptr = new_nullpointerexception();
1156 }
1157
1158
1159 /* exceptions_handle_exception *************************************************
1160
1161    XXX
1162
1163 *******************************************************************************/
1164
1165 u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp)
1166 {
1167         methodinfo            *m;
1168         s4                     framesize;
1169         s4                     issync;
1170         exceptionentry        *ex;
1171         s4                     exceptiontablelength;
1172         s4                     i;
1173         classref_or_classinfo  cr;
1174         classinfo             *c;
1175 #if defined(USE_THREADS)
1176         java_objectheader     *o;
1177 #endif
1178
1179         /* get methodinfo pointer from method header */
1180
1181         m                    = *((methodinfo **)    (pv + MethodPointer));
1182         framesize            = *((s4 *)             (pv + FrameSize));
1183         issync               = *((s4 *)             (pv + IsSync));
1184         ex                   =   (exceptionentry *) (pv + ExTableStart);
1185         exceptiontablelength = *((s4 *)             (pv + ExTableSize));
1186
1187 #if 0
1188         if (m != NULL) {
1189                 printf("exceptions_handle_exception(%p, %p, %p, %p): ", xptr, xpc, pv, sp);
1190                 utf_display(m->class->name);
1191                 printf(".");
1192                 utf_display(m->name);
1193                 utf_display(m->descriptor);
1194                 printf(", %d\n", exceptiontablelength);
1195         }
1196 #endif
1197
1198         /* print exception trace */
1199
1200         if (opt_verbose || runverbose || opt_verboseexception)
1201                 builtin_trace_exception(xptr, m, xpc, 1);
1202
1203         for (i = 0; i < exceptiontablelength; i++) {
1204                 /* ATTENTION: keep this here, as we need to decrement the
1205            pointer before the loop executes! */
1206
1207                 ex--;
1208
1209                 /* is the xpc is the current catch range */
1210
1211                 if (ex->startpc <= xpc && xpc < ex->endpc) {
1212                         cr = ex->catchtype;
1213
1214                         /* NULL catches everything */
1215
1216                         if (cr.any == NULL)
1217                                 return ex->handlerpc;
1218
1219                         /* resolve or load/link the exception class */
1220
1221                         if (IS_CLASSREF(cr)) {
1222                                 c = resolve_classref_eager(cr.ref);
1223
1224                         } else {
1225                                 c = cr.cls;
1226
1227                                 if (!(c->state & CLASS_LOADED))
1228                                         /* use the methods' classloader */
1229                                         if (!load_class_from_classloader(c->name,
1230                                                                                                          m->class->classloader))
1231                                                 return NULL;
1232
1233                                 if (!(c->state & CLASS_LINKED))
1234                                         if (!link_class(c))
1235                                                 return NULL;
1236                         }
1237
1238                         /* is the thrown exception an instance of the catch class? */
1239
1240                         if (builtin_instanceof(xptr, c))
1241                                 return ex->handlerpc;
1242                 }
1243         }
1244
1245 #if defined(USE_THREADS)
1246         /* is this method synchronized? */
1247
1248         if (issync) {
1249                 /* get synchronization object */
1250
1251 # if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1252                 /* XXX change this if we ever want to use 4-byte stackslots */
1253                 o = *((java_objectheader **) (sp + issync - 8));
1254 # else
1255                 o = *((java_objectheader **) (sp + issync - SIZEOF_VOID_P));
1256 #endif
1257
1258                 assert(o != NULL);
1259
1260                 builtin_monitorexit(o);
1261         }
1262 #endif
1263
1264         /* none of the exceptions catch this one */
1265
1266         return NULL;
1267 }
1268
1269
1270 /* exceptions_print_exception **************************************************
1271
1272    Prints an exception, the detail message and the cause, if
1273    available, with CACAO internal functions to stdout.
1274
1275 *******************************************************************************/
1276
1277 #if !defined(NDEBUG)
1278 void exceptions_print_exception(java_objectheader *xptr)
1279 {
1280         java_lang_Throwable   *t;
1281         java_lang_Throwable   *cause;
1282         utf                   *u;
1283
1284         t = (java_lang_Throwable *) xptr;
1285
1286         if (t == NULL) {
1287                 puts("NULL\n");
1288                 return;
1289         }
1290
1291         cause = t->cause;
1292
1293         /* print the root exception */
1294
1295         utf_display_classname(t->header.vftbl->class->name);
1296
1297         if (t->detailMessage) {
1298                 u = javastring_toutf(t->detailMessage, false);
1299
1300                 printf(": ");
1301                 utf_display(u);
1302         }
1303
1304         putc('\n', stdout);
1305
1306         /* print the cause if available */
1307
1308         if (cause && (cause != t)) {
1309                 printf("Caused by: ");
1310                 utf_display_classname(cause->header.vftbl->class->name);
1311
1312                 if (cause->detailMessage) {
1313                         u = javastring_toutf(cause->detailMessage, false);
1314
1315                         printf(": ");
1316                         utf_display(u);
1317                 }
1318
1319                 putc('\n', stdout);
1320         }
1321 }
1322 #endif /* !defined(NDEBUG) */
1323
1324
1325 /*
1326  * These are local overrides for various environment variables in Emacs.
1327  * Please do not remove this and leave it at the end of the file, where
1328  * Emacs will automagically detect them.
1329  * ---------------------------------------------------------------------
1330  * Local variables:
1331  * mode: c
1332  * indent-tabs-mode: t
1333  * c-basic-offset: 4
1334  * tab-width: 4
1335  * End:
1336  * vim:noexpandtab:sw=4:ts=4:
1337  */