* This is a rather huge commit, which changes the build order of
[cacao.git] / src / vm / exceptions.c
1 /* src/vm/exceptions.c - exception related functions
2
3    Copyright (C) 1996-2005, 2006, 2007 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    $Id: exceptions.c 7246 2007-01-29 18:49:05Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33 #include <string.h>
34 #include <stdarg.h>
35 #include <stdlib.h>
36
37 #include "vm/types.h"
38
39 #include "mm/memory.h"
40
41 #include "native/jni.h"
42 #include "native/native.h"
43 #include "native/include/java_lang_String.h"
44 #include "native/include/java_lang_Throwable.h"
45
46 #if defined(ENABLE_THREADS)
47 # include "threads/native/threads.h"
48 #else
49 # include "threads/none/threads.h"
50 #endif
51
52 #include "toolbox/logging.h"
53 #include "toolbox/util.h"
54
55 #include "vm/builtin.h"
56 #include "vm/exceptions.h"
57 #include "vm/global.h"
58 #include "vm/stringlocal.h"
59 #include "vm/vm.h"
60
61 #include "vm/jit/asmpart.h"
62 #include "vm/jit/jit.h"
63 #include "vm/jit/methodheader.h"
64
65 #include "vmcore/class.h"
66 #include "vmcore/loader.h"
67 #include "vmcore/options.h"
68
69
70 /* for raising exceptions from native methods *********************************/
71
72 #if !defined(ENABLE_THREADS)
73 java_objectheader *_no_threads_exceptionptr = NULL;
74 #endif
75
76
77 /* init_system_exceptions ******************************************************
78
79    Load and link exceptions used in the system.
80
81 *******************************************************************************/
82
83 bool exceptions_init(void)
84 {
85         /* java/lang/Throwable */
86
87         if (!(class_java_lang_Throwable =
88                   load_class_bootstrap(utf_java_lang_Throwable)) ||
89                 !link_class(class_java_lang_Throwable))
90                 return false;
91
92         /* java/lang/Error */
93
94         if (!(class_java_lang_Error = load_class_bootstrap(utf_java_lang_Error)) ||
95                 !link_class(class_java_lang_Error))
96                 return false;
97
98 #if defined(ENABLE_JAVASE)
99         /* java/lang/LinkageError */
100
101         if (!(class_java_lang_LinkageError =
102                   load_class_bootstrap(utf_java_lang_LinkageError)) ||
103                 !link_class(class_java_lang_LinkageError))
104                 return false;
105 #endif
106
107         /* java/lang/NoClassDefFoundError */
108
109         if (!(class_java_lang_NoClassDefFoundError =
110                   load_class_bootstrap(utf_java_lang_NoClassDefFoundError)) ||
111                 !link_class(class_java_lang_NoClassDefFoundError))
112                 return false;
113
114         /* java/lang/OutOfMemoryError */
115
116         if (!(class_java_lang_OutOfMemoryError =
117                   load_class_bootstrap(utf_java_lang_OutOfMemoryError)) ||
118                 !link_class(class_java_lang_OutOfMemoryError))
119                 return false;
120
121         /* java/lang/VirtualMachineError */
122
123         if (!(class_java_lang_VirtualMachineError =
124                   load_class_bootstrap(utf_java_lang_VirtualMachineError)) ||
125                 !link_class(class_java_lang_VirtualMachineError))
126                 return false;
127
128
129         /* java/lang/Exception */
130
131         if (!(class_java_lang_Exception =
132                   load_class_bootstrap(utf_java_lang_Exception)) ||
133                 !link_class(class_java_lang_Exception))
134                 return false;
135
136         /* java/lang/ClassCastException */
137
138         if (!(class_java_lang_ClassCastException =
139                   load_class_bootstrap(utf_java_lang_ClassCastException)) ||
140                 !link_class(class_java_lang_ClassCastException))
141                 return false;
142
143         /* java/lang/ClassNotFoundException */
144
145         if (!(class_java_lang_ClassNotFoundException =
146                   load_class_bootstrap(utf_java_lang_ClassNotFoundException)) ||
147                 !link_class(class_java_lang_ClassNotFoundException))
148                 return false;
149
150         /* java/lang/NullPointerException */
151
152         if (!(class_java_lang_NullPointerException =
153                   load_class_bootstrap(utf_java_lang_NullPointerException)) ||
154                 !link_class(class_java_lang_NullPointerException))
155                 return false;
156
157
158 #if defined(WITH_CLASSPATH_GNU)
159         /* java/lang/VMThrowable */
160
161         if (!(class_java_lang_VMThrowable =
162                   load_class_bootstrap(utf_java_lang_VMThrowable)) ||
163                 !link_class(class_java_lang_VMThrowable))
164                 return false;
165 #endif
166
167         return true;
168 }
169
170
171 static void throw_exception_exit_intern(bool doexit)
172 {
173         java_objectheader *xptr;
174         classinfo *c;
175         methodinfo *pss;
176
177         xptr = *exceptionptr;
178
179         if (xptr) {
180                 /* clear exception, because we are calling jit code again */
181                 *exceptionptr = NULL;
182
183                 c = xptr->vftbl->class;
184
185                 pss = class_resolveclassmethod(c,
186                                                                            utf_printStackTrace,
187                                                                            utf_void__void,
188                                                                            class_java_lang_Object,
189                                                                            false);
190
191                 /* print the stacktrace */
192
193                 if (pss) {
194                         (void) vm_call_method(pss, xptr);
195
196                         /* This normally means, we are EXTREMLY out of memory or have a   */
197                         /* serious problem while printStackTrace. But may be another      */
198                         /* exception, so print it.                                        */
199
200                         if (*exceptionptr) {
201                                 java_lang_Throwable *t;
202
203                                 t = (java_lang_Throwable *) *exceptionptr;
204
205                                 fprintf(stderr, "Exception while printStackTrace(): ");
206                                 utf_fprint_printable_ascii_classname(stderr, t->header.vftbl->class->name);
207
208                                 if (t->detailMessage) {
209                                         char *buf;
210
211                                         buf = javastring_tochar((java_objectheader *) t->detailMessage);
212                                         fprintf(stderr, ": %s", buf);
213                                         MFREE(buf, char, strlen(buf));
214                                 }
215                                         
216                                 fprintf(stderr, "\n");
217                         }
218
219                 } else {
220                         utf_fprint_printable_ascii_classname(stderr, c->name);
221                         fprintf(stderr, ": printStackTrace()V not found!\n");
222                 }
223
224                 fflush(stderr);
225
226                 /* good bye! */
227
228                 if (doexit)
229                         exit(1);
230         }
231 }
232
233
234 void throw_exception(void)
235 {
236         throw_exception_exit_intern(false);
237 }
238
239
240 void throw_exception_exit(void)
241 {
242         throw_exception_exit_intern(true);
243 }
244
245
246 void throw_main_exception(void)
247 {
248         fprintf(stderr, "Exception in thread \"main\" ");
249         fflush(stderr);
250
251         throw_exception_exit_intern(false);
252 }
253
254
255 void throw_main_exception_exit(void)
256 {
257         fprintf(stderr, "Exception in thread \"main\" ");
258         fflush(stderr);
259
260         throw_exception_exit_intern(true);
261 }
262
263
264 void throw_cacao_exception_exit(const char *exception, const char *message, ...)
265 {
266         s4 i;
267         char *tmp;
268         s4 len;
269         va_list ap;
270
271         len = strlen(exception);
272         tmp = MNEW(char, len + 1);
273         strncpy(tmp, exception, len);
274         tmp[len] = '\0';
275
276         /* convert to classname */
277
278         for (i = len - 1; i >= 0; i--)
279                 if (tmp[i] == '/') tmp[i] = '.';
280
281         fprintf(stderr, "Exception in thread \"main\" %s", tmp);
282
283         MFREE(tmp, char, len);
284
285         if (strlen(message) > 0) {
286                 fprintf(stderr, ": ");
287
288                 va_start(ap, message);
289                 vfprintf(stderr, message, ap);
290                 va_end(ap);
291         }
292
293         fprintf(stderr, "\n");
294         fflush(stderr);
295
296         /* good bye! */
297
298         exit(1);
299 }
300
301
302 /* exceptions_new_class ********************************************************
303
304    Creates an exception object from the given class and initalizes it.
305
306    IN:
307       class....class pointer
308
309 *******************************************************************************/
310
311 static java_objectheader *exceptions_new_class(classinfo *c)
312 {
313         java_objectheader *o;
314
315         o = native_new_and_init(c);
316
317         if (o == NULL)
318                 return *exceptionptr;
319
320         return o;
321 }
322
323
324 /* exceptions_new_utf **********************************************************
325
326    Creates an exception object with the given name and initalizes it.
327
328    IN:
329       classname....class name in UTF-8
330
331 *******************************************************************************/
332
333 static java_objectheader *exceptions_new_utf(utf *classname)
334 {
335         classinfo         *c;
336         java_objectheader *o;
337
338         c = load_class_bootstrap(classname);
339
340         if (c == NULL)
341                 return *exceptionptr;
342
343         o = exceptions_new_class(c);
344
345         return o;
346 }
347
348
349 /* exceptions_throw_class ******************************************************
350
351    Creates an exception object from the given class, initalizes and
352    throws it.
353
354    IN:
355       class....class pointer
356
357 *******************************************************************************/
358
359 static void exceptions_throw_class(classinfo *c)
360 {
361         java_objectheader *o;
362
363         o = exceptions_new_class(c);
364
365         if (o == NULL)
366                 return;
367
368         *exceptionptr = o;
369 }
370
371
372 /* exceptions_throw_utf ********************************************************
373
374    Creates an exception object with the given name, initalizes and
375    throws it.
376
377    IN:
378       classname....class name in UTF-8
379
380 *******************************************************************************/
381
382 static void exceptions_throw_utf(utf *classname)
383 {
384         classinfo *c;
385
386         c = load_class_bootstrap(classname);
387
388         if (c == NULL)
389                 return;
390
391         exceptions_throw_class(c);
392 }
393
394
395 /* exceptions_throw_utf_throwable **********************************************
396
397    Creates an exception object with the given name and initalizes it
398    with the given java/lang/Throwable exception.
399
400    IN:
401       classname....class name in UTF-8
402           cause........the given Throwable
403
404 *******************************************************************************/
405
406 static void exceptions_throw_utf_throwable(utf *classname,
407                                                                                    java_objectheader *cause)
408 {
409         java_objectheader *o;
410         classinfo         *c;
411    
412         c = load_class_bootstrap(classname);
413
414         if (c == NULL)
415                 return;
416
417         o = native_new_and_init_throwable(c, cause);
418
419         if (o == NULL)
420                 return;
421
422         *exceptionptr = o;
423 }
424
425
426 /* exceptions_new_utf_javastring ***********************************************
427
428    Creates an exception object with the given name and initalizes it
429    with the given java/lang/String message.
430
431    IN:
432       classname....class name in UTF-8
433           message......the message as a java.lang.String
434
435    RETURN VALUE:
436       an exception pointer (in any case -- either it is the newly created
437           exception, or an exception thrown while trying to create it).
438
439 *******************************************************************************/
440
441 static java_objectheader *exceptions_new_utf_javastring(utf *classname,
442                                                                                                                 java_objectheader *message)
443 {
444         java_objectheader *o;
445         classinfo         *c;
446    
447         c = load_class_bootstrap(classname);
448
449         if (c == NULL)
450                 return *exceptionptr;
451
452         o = native_new_and_init_string(c, message);
453
454         if (o == NULL)
455                 return *exceptionptr;
456
457         return o;
458 }
459
460
461 /* exceptions_new_class_utf ****************************************************
462
463    Creates an exception object of the given class and initalizes it.
464
465    IN:
466       c..........class pointer
467       message....the message as UTF-8 string
468
469 *******************************************************************************/
470
471 static java_objectheader *exceptions_new_class_utf(classinfo *c, utf *message)
472 {
473         java_objectheader *o;
474         java_objectheader *s;
475
476         s = javastring_new(message);
477
478         if (s == NULL)
479                 return *exceptionptr;
480
481         o = native_new_and_init_string(c, s);
482
483         if (o == NULL)
484                 return *exceptionptr;
485
486         return o;
487 }
488
489
490 /* exceptions_new_utf_utf ******************************************************
491
492    Creates an exception object with the given name and initalizes it
493    with the given utf message.
494
495    IN:
496       classname....class name in UTF-8
497           message......the message as an utf *
498
499    RETURN VALUE:
500       an exception pointer (in any case -- either it is the newly created
501           exception, or an exception thrown while trying to create it).
502
503 *******************************************************************************/
504
505 static java_objectheader *exceptions_new_utf_utf(utf *classname, utf *message)
506 {
507         classinfo         *c;
508         java_objectheader *o;
509
510         c = load_class_bootstrap(classname);
511
512         if (c == NULL)
513                 return *exceptionptr;
514
515         o = exceptions_new_class_utf(c, message);
516
517         return o;
518 }
519
520
521 /* new_exception_message *******************************************************
522
523    Creates an exception object with the given name and initalizes it
524    with the given char message.
525
526    IN:
527       classname....class name in UTF-8
528           message......message in UTF-8
529
530    RETURN VALUE:
531       an exception pointer (in any case -- either it is the newly created
532           exception, or an exception thrown while trying to create it).
533
534 *******************************************************************************/
535
536 static java_objectheader *new_exception_message(const char *classname,
537                                                                                                 const char *message)
538 {
539         java_objectheader *o;
540         java_objectheader *s;
541
542         s = javastring_new_from_utf_string(message);
543
544         if (s == NULL)
545                 return *exceptionptr;
546
547         o = exceptions_new_utf_javastring(classname, s);
548
549         return o;
550 }
551
552
553 /* exceptions_throw_class_utf **************************************************
554
555    Creates an exception object of the given class, initalizes and
556    throws it with the given utf message.
557
558    IN:
559       c..........class pointer
560           message....the message as an UTF-8
561
562 *******************************************************************************/
563
564 static void exceptions_throw_class_utf(classinfo *c, utf *message)
565 {
566         *exceptionptr = exceptions_new_class_utf(c, message);
567 }
568
569
570 /* exceptions_throw_utf_utf ****************************************************
571
572    Creates an exception object with the given name, initalizes and
573    throws it with the given utf message.
574
575    IN:
576       classname....class name in UTF-8
577           message......the message as an utf *
578
579 *******************************************************************************/
580
581 static void exceptions_throw_utf_utf(utf *classname, utf *message)
582 {
583         *exceptionptr = exceptions_new_utf_utf(classname, message);
584 }
585
586
587 /* new_exception_int ***********************************************************
588
589    Creates an exception object with the given name and initalizes it
590    with the given int value.
591
592    IN:
593       classname....class name in UTF-8
594           i............the integer
595
596    RETURN VALUE:
597       an exception pointer (in any case -- either it is the newly created
598           exception, or an exception thrown while trying to create it).
599
600 *******************************************************************************/
601
602 java_objectheader *new_exception_int(const char *classname, s4 i)
603 {
604         java_objectheader *o;
605         classinfo         *c;
606    
607         if (!(c = load_class_bootstrap(utf_new_char(classname))))
608                 return *exceptionptr;
609
610         o = native_new_and_init_int(c, i);
611
612         if (!o)
613                 return *exceptionptr;
614
615         return o;
616 }
617
618
619 /* exceptions_new_abstractmethoderror ****************************************
620
621    Generates a java.lang.AbstractMethodError for the VM.
622
623 *******************************************************************************/
624
625 java_objectheader *exceptions_new_abstractmethoderror(void)
626 {
627         java_objectheader *o;
628
629         o = exceptions_new_utf(utf_java_lang_AbstractMethodError);
630
631         return o;
632 }
633
634
635 /* exceptions_asm_new_abstractmethoderror **************************************
636
637    Generates a java.lang.AbstractMethodError for
638    asm_abstractmethoderror.
639
640 *******************************************************************************/
641
642 java_objectheader *exceptions_asm_new_abstractmethoderror(u1 *sp, u1 *ra)
643 {
644         stackframeinfo     sfi;
645         java_objectheader *e;
646
647         /* create the stackframeinfo (XPC is equal to RA) */
648
649         stacktrace_create_extern_stackframeinfo(&sfi, NULL, sp, ra, ra);
650
651         /* create the exception */
652
653 #if defined(ENABLE_JAVASE)
654         e = exceptions_new_abstractmethoderror();
655 #else
656         /* in the meantime we do this */
657
658         e = exceptions_new_virtualmachineerror();
659 #endif
660
661         /* remove the stackframeinfo */
662
663         stacktrace_remove_stackframeinfo(&sfi);
664
665         return e;
666 }
667
668
669 /* exceptions_new_arraystoreexception ******************************************
670
671    Generates a java.lang.ArrayStoreException for the VM.
672
673 *******************************************************************************/
674
675 java_objectheader *exceptions_new_arraystoreexception(void)
676 {
677         java_objectheader *o;
678
679         o = exceptions_new_utf(utf_java_lang_ArrayStoreException);
680
681         return o;
682 }
683
684
685 /* exceptions_throw_abstractmethoderror ****************************************
686
687    Generates and throws a java.lang.AbstractMethodError for the VM.
688
689 *******************************************************************************/
690
691 void exceptions_throw_abstractmethoderror(void)
692 {
693         exceptions_throw_utf(utf_java_lang_AbstractMethodError);
694 }
695
696
697 /* exceptions_throw_classcircularityerror **************************************
698
699    Generates and throws a java.lang.ClassCircularityError for the
700    classloader.
701
702    IN:
703       c............the class in which the error was found
704
705 *******************************************************************************/
706
707 void exceptions_throw_classcircularityerror(classinfo *c)
708 {
709         java_objectheader *o;
710         char              *msg;
711         s4                 msglen;
712
713         /* calculate message length */
714
715         msglen = utf_bytes(c->name) + strlen("0");
716
717         /* allocate a buffer */
718
719         msg = MNEW(char, msglen);
720
721         /* print message into allocated buffer */
722
723         utf_copy_classname(msg, c->name);
724
725         o = new_exception_message(utf_java_lang_ClassCircularityError, msg);
726
727         MFREE(msg, char, msglen);
728
729         if (o == NULL)
730                 return;
731
732         *exceptionptr = o;
733 }
734
735
736 /* exceptions_throw_classformaterror *******************************************
737
738    Generates and throws a java.lang.ClassFormatError for the VM.
739
740    IN:
741       c............the class in which the error was found
742           message......UTF-8 format string
743
744 *******************************************************************************/
745
746 void exceptions_throw_classformaterror(classinfo *c, const char *message, ...)
747 {
748         java_objectheader *o;
749         char              *msg;
750         s4                 msglen;
751         va_list            ap;
752
753         /* calculate message length */
754
755         msglen = 0;
756
757         if (c != NULL)
758                 msglen += utf_bytes(c->name) + strlen(" (");
759
760         va_start(ap, message);
761         msglen += get_variable_message_length(message, ap);
762         va_end(ap);
763
764         if (c != NULL)
765                 msglen += strlen(")");
766
767         msglen += strlen("0");
768
769         /* allocate a buffer */
770
771         msg = MNEW(char, msglen);
772
773         /* print message into allocated buffer */
774
775         if (c != NULL) {
776                 utf_copy_classname(msg, c->name);
777                 strcat(msg, " (");
778         }
779
780         va_start(ap, message);
781         vsprintf(msg + strlen(msg), message, ap);
782         va_end(ap);
783
784         if (c != NULL)
785                 strcat(msg, ")");
786
787         o = new_exception_message(utf_java_lang_ClassFormatError, msg);
788
789         MFREE(msg, char, msglen);
790
791         *exceptionptr = o;
792 }
793
794
795 /* exceptions_throw_classnotfoundexception *************************************
796
797    Generates and throws a java.lang.ClassNotFoundException for the
798    VM.
799
800    IN:
801       name.........name of the class not found as a utf *
802
803 *******************************************************************************/
804
805 void exceptions_throw_classnotfoundexception(utf *name)
806 {
807         /* we use class here, as this one is rather frequent */
808
809         exceptions_throw_class_utf(class_java_lang_ClassNotFoundException, name);
810 }
811
812
813 /* exceptions_throw_noclassdeffounderror ***************************************
814
815    Generates and throws a java.lang.NoClassDefFoundError.
816
817    IN:
818       name.........name of the class not found as a utf *
819
820 *******************************************************************************/
821
822 void exceptions_throw_noclassdeffounderror(utf *name)
823 {
824         exceptions_throw_class_utf(class_java_lang_NoClassDefFoundError, name);
825 }
826
827
828 /* classnotfoundexception_to_noclassdeffounderror ******************************
829
830    Check the *exceptionptr for a ClassNotFoundException. If it is one,
831    convert it to a NoClassDefFoundError.
832
833 *******************************************************************************/
834
835 void classnotfoundexception_to_noclassdeffounderror(void)
836 {
837         java_objectheader   *xptr;
838         java_objectheader   *cause;
839         java_lang_Throwable *t;
840         java_lang_String    *s;
841
842         /* get the cause */
843
844         cause = *exceptionptr;
845
846         /* convert ClassNotFoundException's to NoClassDefFoundError's */
847
848         if (builtin_instanceof(cause, class_java_lang_ClassNotFoundException)) {
849                 /* clear exception, because we are calling jit code again */
850
851                 *exceptionptr = NULL;
852
853                 /* create new error */
854
855                 t = (java_lang_Throwable *) cause;
856                 s = t->detailMessage;
857
858                 xptr = exceptions_new_utf_javastring(utf_java_lang_NoClassDefFoundError, s);
859
860                 /* we had an exception while creating the error */
861
862                 if (*exceptionptr)
863                         return;
864
865                 /* set new exception */
866
867                 *exceptionptr = xptr;
868         }
869 }
870
871
872 /* exceptions_throw_exceptionininitializererror ********************************
873
874    Generates and throws a java.lang.ExceptionInInitializerError for
875    the VM.
876
877    IN:
878       cause......cause exception object
879
880 *******************************************************************************/
881
882 void exceptions_throw_exceptionininitializererror(java_objectheader *cause)
883 {
884         exceptions_throw_utf_throwable(utf_java_lang_ExceptionInInitializerError,
885                                                                    cause);
886 }
887
888
889 /* exceptions_throw_incompatibleclasschangeerror *******************************
890
891    Generates and throws a java.lang.IncompatibleClassChangeError for
892    the VM.
893
894    IN:
895       message......UTF-8 message format string
896
897 *******************************************************************************/
898
899 void exceptions_throw_incompatibleclasschangeerror(classinfo *c, const char *message)
900 {
901         java_objectheader *o;
902         char              *msg;
903         s4                 msglen;
904
905         /* calculate exception message length */
906
907         msglen = utf_bytes(c->name) + strlen(message) + strlen("0");
908
909         /* allocate memory */
910
911         msg = MNEW(char, msglen);
912
913         utf_copy_classname(msg, c->name);
914         strcat(msg, message);
915
916         o = native_new_and_init_string(utf_java_lang_IncompatibleClassChangeError,
917                                                                    javastring_new_from_utf_string(msg));
918
919         /* free memory */
920
921         MFREE(msg, char, msglen);
922
923         if (o == NULL)
924                 return;
925
926         *exceptionptr = o;
927 }
928
929
930 /* exceptions_throw_instantiationerror *****************************************
931
932    Generates and throws a java.lang.InstantiationError for the VM.
933
934 *******************************************************************************/
935
936 void exceptions_throw_instantiationerror(classinfo *c)
937 {
938         exceptions_throw_utf_utf(utf_java_lang_InstantiationError, c->name);
939 }
940
941
942 /* exceptions_throw_internalerror **********************************************
943
944    Generates and throws a java.lang.InternalError for the VM.
945
946    IN:
947       message......UTF-8 message format string
948
949 *******************************************************************************/
950
951 void exceptions_throw_internalerror(const char *message, ...)
952 {
953         java_objectheader *o;
954         va_list            ap;
955         char              *msg;
956         s4                 msglen;
957
958         /* calculate exception message length */
959
960         va_start(ap, message);
961         msglen = get_variable_message_length(message, ap);
962         va_end(ap);
963
964         /* allocate memory */
965
966         msg = MNEW(char, msglen);
967
968         /* generate message */
969
970         va_start(ap, message);
971         vsprintf(msg, message, ap);
972         va_end(ap);
973
974         /* create exception object */
975
976         o = new_exception_message(utf_java_lang_InternalError, msg);
977
978         /* free memory */
979
980         MFREE(msg, char, msglen);
981
982         if (o == NULL)
983                 return;
984
985         *exceptionptr = o;
986 }
987
988
989 /* exceptions_throw_linkageerror ***********************************************
990
991    Generates and throws java.lang.LinkageError with an error message.
992
993    IN:
994       message......UTF-8 message
995           c............class related to the error. If this is != NULL
996                        the name of c is appended to the error message.
997
998 *******************************************************************************/
999
1000 void exceptions_throw_linkageerror(const char *message, classinfo *c)
1001 {
1002         java_objectheader *o;
1003         char              *msg;
1004         s4                 msglen;
1005
1006         /* calculate exception message length */
1007
1008         msglen = strlen(message) + 1;
1009
1010         if (c != NULL)
1011                 msglen += utf_bytes(c->name);
1012                 
1013         /* allocate memory */
1014
1015         msg = MNEW(char, msglen);
1016
1017         /* generate message */
1018
1019         strcpy(msg,message);
1020
1021         if (c != NULL)
1022                 utf_cat_classname(msg, c->name);
1023
1024         o = native_new_and_init_string(class_java_lang_LinkageError,
1025                                                                    javastring_new_from_utf_string(msg));
1026
1027         /* free memory */
1028
1029         MFREE(msg, char, msglen);
1030
1031         if (o == NULL)
1032                 return;
1033
1034         *exceptionptr = o;
1035 }
1036
1037
1038 /* exceptions_throw_nosuchfielderror *******************************************
1039
1040    Generates and throws a java.lang.NoSuchFieldError with an error
1041    message.
1042
1043    IN:
1044       c............class in which the field was not found
1045           name.........name of the field
1046
1047 *******************************************************************************/
1048
1049 void exceptions_throw_nosuchfielderror(classinfo *c, utf *name)
1050 {
1051         char *msg;
1052         s4    msglen;
1053         utf  *u;
1054
1055         /* calculate exception message length */
1056
1057         msglen = utf_bytes(c->name) + strlen(".") + utf_bytes(name) + strlen("0");
1058
1059         /* allocate memory */
1060
1061         msg = MNEW(char, msglen);
1062
1063         /* generate message */
1064
1065         utf_copy_classname(msg, c->name);
1066         strcat(msg, ".");
1067         utf_cat(msg, name);
1068
1069         u = utf_new_char(msg);
1070
1071         /* free memory */
1072
1073         MFREE(msg, char, msglen);
1074
1075         exceptions_throw_utf_utf(utf_java_lang_NoSuchFieldError, u);
1076 }
1077
1078
1079 /* exceptions_throw_nosuchmethoderror ******************************************
1080
1081    Generates and throws a java.lang.NoSuchMethodError with an error
1082    message.
1083
1084    IN:
1085       c............class in which the method was not found
1086           name.........name of the method
1087           desc.........descriptor of the method
1088
1089 *******************************************************************************/
1090
1091 void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc)
1092 {
1093         char *msg;
1094         s4    msglen;
1095         utf  *u;
1096
1097         /* calculate exception message length */
1098
1099         msglen = utf_bytes(c->name) + strlen(".") + utf_bytes(name) +
1100                 utf_bytes(desc) + strlen("0");
1101
1102         /* allocate memory */
1103
1104         msg = MNEW(char, msglen);
1105
1106         /* generate message */
1107
1108         utf_copy_classname(msg, c->name);
1109         strcat(msg, ".");
1110         utf_cat(msg, name);
1111         utf_cat(msg, desc);
1112
1113         u = utf_new_char(msg);
1114
1115         /* free memory */
1116
1117         MFREE(msg, char, msglen);
1118
1119         exceptions_throw_utf_utf(utf_java_lang_NoSuchMethodError, u);
1120 }
1121
1122
1123 /* exceptions_throw_outofmemoryerror *******************************************
1124
1125    Generates and throws an java.lang.OutOfMemoryError for the VM.
1126
1127 *******************************************************************************/
1128
1129 void exceptions_throw_outofmemoryerror(void)
1130 {
1131         exceptions_throw_class(class_java_lang_OutOfMemoryError);
1132 }
1133
1134
1135 /* exceptions_throw_unsatisfiedlinkerror ***************************************
1136
1137    Generates and throws a java.lang.UnsatisfiedLinkError for the
1138    classloader.
1139
1140    IN:
1141           name......UTF-8 name string
1142
1143 *******************************************************************************/
1144
1145 void exceptions_throw_unsatisfiedlinkerror(utf *name)
1146 {
1147         exceptions_throw_utf_utf(utf_java_lang_UnsatisfiedLinkError, name);
1148 }
1149
1150
1151 /* exceptions_throw_unsupportedclassversionerror *******************************
1152
1153    Generates and throws a java.lang.UnsupportedClassVersionError for
1154    the classloader.
1155
1156    IN:
1157       c............class in which the method was not found
1158           message......UTF-8 format string
1159
1160 *******************************************************************************/
1161
1162 void exceptions_throw_unsupportedclassversionerror(classinfo *c, u4 ma, u4 mi)
1163 {
1164         java_objectheader *o;
1165         char              *msg;
1166     s4                 msglen;
1167
1168         /* calculate exception message length */
1169
1170         msglen =
1171                 utf_bytes(c->name) +
1172                 strlen(" (Unsupported major.minor version 00.0)") +
1173                 strlen("0");
1174
1175         /* allocate memory */
1176
1177         msg = MNEW(char, msglen);
1178
1179         /* generate message */
1180
1181         utf_copy_classname(msg, c->name);
1182         sprintf(msg + strlen(msg), " (Unsupported major.minor version %d.%d)",
1183                         ma, mi);
1184
1185         /* create exception object */
1186
1187         o = new_exception_message(utf_java_lang_UnsupportedClassVersionError, msg);
1188
1189         /* free memory */
1190
1191         MFREE(msg, char, msglen);
1192
1193         if (o == NULL)
1194                 return;
1195
1196         *exceptionptr = o;
1197 }
1198
1199
1200 /* exceptions_throw_verifyerror ************************************************
1201
1202    Generates and throws a java.lang.VerifyError for the JIT compiler.
1203
1204    IN:
1205       m............method in which the error was found
1206           message......UTF-8 format string
1207
1208 *******************************************************************************/
1209
1210 void exceptions_throw_verifyerror(methodinfo *m, const char *message, ...)
1211 {
1212         java_objectheader *o;
1213         va_list            ap;
1214         char              *msg;
1215         s4                 msglen;
1216
1217         /* calculate exception message length */
1218
1219         msglen = 0;
1220
1221         if (m != NULL)
1222                 msglen =
1223                         strlen("(class: ") + utf_bytes(m->class->name) +
1224                         strlen(", method: ") + utf_bytes(m->name) +
1225                         strlen(" signature: ") + utf_bytes(m->descriptor) +
1226                         strlen(") ") + strlen("0");
1227
1228         va_start(ap, message);
1229         msglen += get_variable_message_length(message, ap);
1230         va_end(ap);
1231
1232         /* allocate memory */
1233
1234         msg = MNEW(char, msglen);
1235
1236         /* generate message */
1237
1238         if (m != NULL) {
1239                 strcpy(msg, "(class: ");
1240                 utf_cat_classname(msg, m->class->name);
1241                 strcat(msg, ", method: ");
1242                 utf_cat(msg, m->name);
1243                 strcat(msg, " signature: ");
1244                 utf_cat(msg, m->descriptor);
1245                 strcat(msg, ") ");
1246         }
1247
1248         va_start(ap, message);
1249         vsprintf(msg + strlen(msg), message, ap);
1250         va_end(ap);
1251
1252         /* create exception object */
1253
1254         o = new_exception_message(utf_java_lang_VerifyError, msg);
1255
1256         /* free memory */
1257
1258         MFREE(msg, char, msglen);
1259
1260         *exceptionptr = o;
1261 }
1262
1263
1264 /* exceptions_throw_verifyerror_for_stack **************************************
1265
1266    throws a java.lang.VerifyError for an invalid stack slot type
1267
1268    IN:
1269       m............method in which the error was found
1270           type.........the expected type
1271
1272    RETURN VALUE:
1273       an exception pointer (in any case -- either it is the newly created
1274           exception, or an exception thrown while trying to create it).
1275
1276 *******************************************************************************/
1277
1278 void exceptions_throw_verifyerror_for_stack(methodinfo *m,int type)
1279 {
1280         java_objectheader *o;
1281         char              *msg;
1282         s4                 msglen;
1283         char              *typename;
1284
1285         /* calculate exception message length */
1286
1287         msglen = 0;
1288
1289         if (m)
1290                 msglen = strlen("(class: ") + utf_bytes(m->class->name) +
1291                         strlen(", method: ") + utf_bytes(m->name) +
1292                         strlen(" signature: ") + utf_bytes(m->descriptor) +
1293                         strlen(") Expecting to find longest-------typename on stack") 
1294                         + strlen("0");
1295
1296         /* allocate memory */
1297
1298         msg = MNEW(char, msglen);
1299
1300         /* generate message */
1301
1302         if (m) {
1303                 strcpy(msg, "(class: ");
1304                 utf_cat_classname(msg, m->class->name);
1305                 strcat(msg, ", method: ");
1306                 utf_cat(msg, m->name);
1307                 strcat(msg, " signature: ");
1308                 utf_cat(msg, m->descriptor);
1309                 strcat(msg, ") ");
1310         }
1311         else {
1312                 msg[0] = 0;
1313         }
1314
1315         strcat(msg,"Expecting to find ");
1316         switch (type) {
1317                 case TYPE_INT: typename = "integer"; break;
1318                 case TYPE_LNG: typename = "long"; break;
1319                 case TYPE_FLT: typename = "float"; break;
1320                 case TYPE_DBL: typename = "double"; break;
1321                 case TYPE_ADR: typename = "object/array"; break;
1322                 case TYPE_RET: typename = "returnAddress"; break;
1323                 default:       typename = "<INVALID>"; assert(0); break;
1324         }
1325         strcat(msg, typename);
1326         strcat(msg, " on stack");
1327
1328         /* create exception object */
1329
1330         o = new_exception_message(utf_java_lang_VerifyError, msg);
1331
1332         /* free memory */
1333
1334         MFREE(msg, char, msglen);
1335
1336         *exceptionptr = o;
1337 }
1338
1339
1340 /* exceptions_throw_virtualmachineerror ****************************************
1341
1342    Generates and throws a java.lang.VirtualMachineError for the VM.
1343
1344 *******************************************************************************/
1345
1346 void exceptions_throw_virtualmachineerror(void)
1347 {
1348         exceptions_throw_class(class_java_lang_VirtualMachineError);
1349 }
1350
1351
1352 /* exceptions_new_arithmeticexception ******************************************
1353
1354    Generates a java.lang.ArithmeticException for the JIT compiler.
1355
1356 *******************************************************************************/
1357
1358 java_objectheader *exceptions_new_arithmeticexception(void)
1359 {
1360         java_objectheader *o;
1361
1362         o = new_exception_message(utf_java_lang_ArithmeticException, "/ by zero");
1363
1364         if (o == NULL)
1365                 return *exceptionptr;
1366
1367         return o;
1368 }
1369
1370
1371 /* exceptions_new_arrayindexoutofboundsexception *******************************
1372
1373    Generates a java.lang.ArrayIndexOutOfBoundsException for the VM
1374    system.
1375
1376 *******************************************************************************/
1377
1378 java_objectheader *exceptions_new_arrayindexoutofboundsexception(s4 index)
1379 {
1380         java_objectheader *o;
1381         methodinfo        *m;
1382         java_objectheader *s;
1383
1384         /* convert the index into a String, like Sun does */
1385
1386         m = class_resolveclassmethod(class_java_lang_String,
1387                                                                  utf_new_char("valueOf"),
1388                                                                  utf_new_char("(I)Ljava/lang/String;"),
1389                                                                  class_java_lang_Object,
1390                                                                  true);
1391
1392         if (m == NULL)
1393                 return *exceptionptr;
1394
1395         s = vm_call_method(m, NULL, index);
1396
1397         if (s == NULL)
1398                 return *exceptionptr;
1399
1400         o = exceptions_new_utf_javastring(utf_java_lang_ArrayIndexOutOfBoundsException,
1401                                                                           s);
1402
1403         if (o == NULL)
1404                 return *exceptionptr;
1405
1406         return o;
1407 }
1408
1409
1410 /* exceptions_throw_arrayindexoutofboundsexception *****************************
1411
1412    Generates and throws a java.lang.ArrayIndexOutOfBoundsException for
1413    the VM.
1414
1415 *******************************************************************************/
1416
1417 void exceptions_throw_arrayindexoutofboundsexception(void)
1418 {
1419         exceptions_throw_utf(utf_java_lang_ArrayIndexOutOfBoundsException);
1420 }
1421
1422
1423 /* exceptions_throw_arraystoreexception ****************************************
1424
1425    Generates and throws a java.lang.ArrayStoreException for the VM.
1426
1427 *******************************************************************************/
1428
1429 void exceptions_throw_arraystoreexception(void)
1430 {
1431         exceptions_throw_utf(utf_java_lang_ArrayStoreException);
1432 /*      e = native_new_and_init(class_java_lang_ArrayStoreException); */
1433 }
1434
1435
1436 /* exceptions_new_classcastexception *******************************************
1437
1438    Generates a java.lang.ClassCastException for the JIT compiler.
1439
1440 *******************************************************************************/
1441
1442 java_objectheader *exceptions_new_classcastexception(java_objectheader *o)
1443 {
1444         java_objectheader *e;
1445         utf               *classname;
1446         java_lang_String  *s;
1447
1448         classname = o->vftbl->class->name;
1449
1450         s = javastring_new(classname);
1451
1452         e = native_new_and_init_string(class_java_lang_ClassCastException, s);
1453
1454         if (e == NULL)
1455                 return *exceptionptr;
1456
1457         return e;
1458 }
1459
1460
1461 /* exceptions_throw_clonenotsupportedexception *********************************
1462
1463    Generates and throws a java.lang.CloneNotSupportedException for the
1464    VM.
1465
1466 *******************************************************************************/
1467
1468 void exceptions_throw_clonenotsupportedexception(void)
1469 {
1470         exceptions_throw_utf(utf_java_lang_CloneNotSupportedException);
1471 }
1472
1473
1474 /* exceptions_throw_illegalaccessexception *************************************
1475
1476    Generates and throws a java.lang.IllegalAccessException for the VM.
1477
1478 *******************************************************************************/
1479
1480 void exceptions_throw_illegalaccessexception(classinfo *c)
1481 {
1482         /* XXX handle argument */
1483
1484         exceptions_throw_utf(utf_java_lang_IllegalAccessException);
1485 }
1486
1487
1488 /* exceptions_throw_illegalargumentexception ***********************************
1489
1490    Generates and throws a java.lang.IllegalArgumentException for the
1491    VM.
1492
1493 *******************************************************************************/
1494
1495 void exceptions_throw_illegalargumentexception(void)
1496 {
1497         exceptions_throw_utf(utf_java_lang_IllegalArgumentException);
1498 }
1499
1500
1501 /* exceptions_throw_illegalmonitorstateexception *******************************
1502
1503    Generates and throws a java.lang.IllegalMonitorStateException for
1504    the VM.
1505
1506 *******************************************************************************/
1507
1508 void exceptions_throw_illegalmonitorstateexception(void)
1509 {
1510         exceptions_throw_utf(utf_java_lang_IllegalMonitorStateException);
1511 }
1512
1513
1514 /* exceptions_throw_instantiationexception *************************************
1515
1516    Generates and throws a java.lang.InstantiationException for the VM.
1517
1518 *******************************************************************************/
1519
1520 void exceptions_throw_instantiationexception(classinfo *c)
1521 {
1522         exceptions_throw_utf_utf(utf_java_lang_InstantiationException, c->name);
1523 }
1524
1525
1526 /* exceptions_throw_interruptedexception ***************************************
1527
1528    Generates and throws a java.lang.InterruptedException for the VM.
1529
1530 *******************************************************************************/
1531
1532 void exceptions_throw_interruptedexception(void)
1533 {
1534         exceptions_throw_utf(utf_java_lang_InterruptedException);
1535 }
1536
1537
1538 /* exceptions_throw_invocationtargetexception **********************************
1539
1540    Generates and throws a java.lang.InvocationTargetException for the
1541    VM.
1542
1543    IN:
1544       cause......cause exception object
1545
1546 *******************************************************************************/
1547
1548 void exceptions_throw_invocationtargetexception(java_objectheader *cause)
1549 {
1550         exceptions_throw_utf_throwable(utf_java_lang_InvocationTargetException,
1551                                                                    cause);
1552 }
1553
1554
1555 /* exceptions_throw_negativearraysizeexception *********************************
1556
1557    Generates and throws a java.lang.NegativeArraySizeException for the
1558    VM.
1559
1560 *******************************************************************************/
1561
1562 void exceptions_throw_negativearraysizeexception(void)
1563 {
1564         exceptions_throw_utf(utf_java_lang_NegativeArraySizeException);
1565 }
1566
1567
1568 /* exceptions_new_nullpointerexception *****************************************
1569
1570    Generates a java.lang.NullPointerException for the VM system.
1571
1572 *******************************************************************************/
1573
1574 java_objectheader *exceptions_new_nullpointerexception(void)
1575 {
1576         java_objectheader *o;
1577
1578         o = exceptions_new_class(class_java_lang_NullPointerException);
1579
1580         return o;
1581 }
1582
1583
1584 /* exceptions_throw_nullpointerexception ***************************************
1585
1586    Generates a java.lang.NullPointerException for the VM system and
1587    throw it in the VM system.
1588
1589 *******************************************************************************/
1590
1591 void exceptions_throw_nullpointerexception(void)
1592 {
1593         exceptions_throw_class(class_java_lang_NullPointerException);
1594 }
1595
1596
1597 /* exceptions_throw_stringindexoutofboundsexception ****************************
1598
1599    Generates and throws a java.lang.StringIndexOutOfBoundsException
1600    for the VM.
1601
1602 *******************************************************************************/
1603
1604 void exceptions_throw_stringindexoutofboundsexception(void)
1605 {
1606         exceptions_throw_utf(utf_java_lang_StringIndexOutOfBoundsException);
1607 }
1608
1609
1610 /* exceptions_get_exception ****************************************************
1611
1612    Returns the current exception pointer of the current thread.
1613
1614 *******************************************************************************/
1615
1616 java_objectheader *exceptions_get_exception(void)
1617 {
1618         /* return the exception */
1619
1620         return *exceptionptr;
1621 }
1622
1623
1624 /* exceptions_set_exception ****************************************************
1625
1626    Sets the exception pointer of the current thread.
1627
1628 *******************************************************************************/
1629
1630 void exceptions_set_exception(java_objectheader *o)
1631 {
1632         /* set the exception */
1633
1634         *exceptionptr = o;
1635 }
1636
1637
1638 /* exceptions_clear_exception **************************************************
1639
1640    Clears the current exception pointer of the current thread.
1641
1642 *******************************************************************************/
1643
1644 void exceptions_clear_exception(void)
1645 {
1646         /* and clear the exception */
1647
1648         *exceptionptr = NULL;
1649 }
1650
1651
1652 /* exceptions_get_and_clear_exception ******************************************
1653
1654    Gets the exception pointer of the current thread and clears it.
1655    This function may return NULL.
1656
1657 *******************************************************************************/
1658
1659 java_objectheader *exceptions_get_and_clear_exception(void)
1660 {
1661         java_objectheader **p;
1662         java_objectheader  *e;
1663
1664         /* get the pointer of the exception pointer */
1665
1666         p = exceptionptr;
1667
1668         /* get the exception */
1669
1670         e = *p;
1671
1672         /* and clear the exception */
1673
1674         *p = NULL;
1675
1676         /* return the exception */
1677
1678         return e;
1679 }
1680
1681
1682 /* exceptions_handle_exception *************************************************
1683
1684    Try to find an exception handler for the given exception and return it.
1685    If no handler is found, exit the monitor of the method (if any)
1686    and return NULL.
1687
1688    IN:
1689       xptr.........the exception object
1690           xpc..........PC of where the exception was thrown
1691           pv...........Procedure Value of the current method
1692           sp...........current stack pointer
1693
1694    RETURN VALUE:
1695       the address of the first matching exception handler, or
1696           NULL if no handler was found
1697
1698 *******************************************************************************/
1699
1700 #if defined(ENABLE_JIT)
1701 u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp)
1702 {
1703         methodinfo            *m;
1704         codeinfo              *code;
1705         s4                     issync;
1706         dseg_exception_entry  *ex;
1707         s4                     exceptiontablelength;
1708         s4                     i;
1709         classref_or_classinfo  cr;
1710         classinfo             *c;
1711 #if defined(ENABLE_THREADS)
1712         java_objectheader     *o;
1713 #endif
1714
1715         /* get info from the method header */
1716
1717         code                 = *((codeinfo **)            (pv + CodeinfoPointer));
1718         issync               = *((s4 *)                   (pv + IsSync));
1719         ex                   =   (dseg_exception_entry *) (pv + ExTableStart);
1720         exceptiontablelength = *((s4 *)                   (pv + ExTableSize));
1721
1722         /* Get the methodinfo pointer from the codeinfo pointer. For
1723            asm_vm_call_method the codeinfo pointer is NULL. */
1724
1725         m = (code == NULL) ? NULL : code->m;
1726
1727 #if !defined(NDEBUG)
1728         /* print exception trace */
1729
1730         if (opt_verbose || opt_verbosecall || opt_verboseexception)
1731                 builtin_trace_exception(xptr, m, xpc, 1);
1732 #endif
1733
1734         for (i = 0; i < exceptiontablelength; i++) {
1735                 /* ATTENTION: keep this here, as we need to decrement the
1736            pointer before the loop executes! */
1737
1738                 ex--;
1739
1740                 /* If the start and end PC is NULL, this means we have the
1741                    special case of asm_vm_call_method.  So, just return the
1742                    proper exception handler. */
1743
1744                 if ((ex->startpc == NULL) && (ex->endpc == NULL))
1745                         return (u1 *) (ptrint) &asm_vm_call_method_exception_handler;
1746
1747                 /* is the xpc is the current catch range */
1748
1749                 if ((ex->startpc <= xpc) && (xpc < ex->endpc)) {
1750                         cr = ex->catchtype;
1751
1752                         /* NULL catches everything */
1753
1754                         if (cr.any == NULL) {
1755 #if !defined(NDEBUG)
1756                                 /* Print stacktrace of exception when caught. */
1757
1758                                 if (opt_verboseexception) {
1759                                         exceptions_print_exception(xptr);
1760                                         stacktrace_print_trace(xptr);
1761                                 }
1762 #endif
1763
1764                                 return ex->handlerpc;
1765                         }
1766
1767                         /* resolve or load/link the exception class */
1768
1769                         if (IS_CLASSREF(cr)) {
1770                                 /* The exception class reference is unresolved. */
1771                                 /* We have to do _eager_ resolving here. While the class of */
1772                                 /* the exception object is guaranteed to be loaded, it may  */
1773                                 /* well have been loaded by a different loader than the     */
1774                                 /* defining loader of m's class, which is the one we must   */
1775                                 /* use to resolve the catch class. Thus lazy resolving      */
1776                                 /* might fail, even if the result of the resolution would   */
1777                                 /* be an already loaded class.                              */
1778
1779                                 c = resolve_classref_eager(cr.ref);
1780
1781                                 if (c == NULL) {
1782                                         /* Exception resolving the exception class, argh! */
1783                                         return NULL;
1784                                 }
1785
1786                                 /* Ok, we resolved it. Enter it in the table, so we don't */
1787                                 /* have to do this again.                                 */
1788                                 /* XXX this write should be atomic. Is it?                */
1789
1790                                 ex->catchtype.cls = c;
1791                         } else {
1792                                 c = cr.cls;
1793
1794                                 /* XXX I don't think this case can ever happen. -Edwin */
1795                                 if (!(c->state & CLASS_LOADED))
1796                                         /* use the methods' classloader */
1797                                         if (!load_class_from_classloader(c->name,
1798                                                                                                          m->class->classloader))
1799                                                 return NULL;
1800
1801                                 /* XXX I think, if it is not linked, we can be sure that     */
1802                                 /* the exception object is no (indirect) instance of it, no? */
1803                                 /* -Edwin                                                    */
1804                                 if (!(c->state & CLASS_LINKED))
1805                                         if (!link_class(c))
1806                                                 return NULL;
1807                         }
1808
1809                         /* is the thrown exception an instance of the catch class? */
1810
1811                         if (builtin_instanceof(xptr, c)) {
1812 #if !defined(NDEBUG)
1813                                 /* Print stacktrace of exception when caught. */
1814
1815                                 if (opt_verboseexception) {
1816                                         exceptions_print_exception(xptr);
1817                                         stacktrace_print_trace(xptr);
1818                                 }
1819 #endif
1820
1821                                 return ex->handlerpc;
1822                         }
1823                 }
1824         }
1825
1826 #if defined(ENABLE_THREADS)
1827         /* is this method synchronized? */
1828
1829         if (issync) {
1830                 /* get synchronization object */
1831
1832 # if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1833                 /* XXX change this if we ever want to use 4-byte stackslots */
1834                 o = *((java_objectheader **) (sp + issync - 8));
1835 # else
1836                 o = *((java_objectheader **) (sp + issync - SIZEOF_VOID_P));
1837 #endif
1838
1839                 assert(o != NULL);
1840
1841                 lock_monitor_exit(o);
1842         }
1843 #endif
1844
1845         /* none of the exceptions catch this one */
1846
1847         return NULL;
1848 }
1849 #endif /* defined(ENABLE_JIT) */
1850
1851
1852 /* exceptions_print_exception **************************************************
1853
1854    Prints an exception, the detail message and the cause, if
1855    available, with CACAO internal functions to stdout.
1856
1857 *******************************************************************************/
1858
1859 void exceptions_print_exception(java_objectheader *xptr)
1860 {
1861         java_lang_Throwable   *t;
1862 #if defined(ENABLE_JAVASE)
1863         java_lang_Throwable   *cause;
1864 #endif
1865         utf                   *u;
1866
1867         t = (java_lang_Throwable *) xptr;
1868
1869         if (t == NULL) {
1870                 puts("NULL\n");
1871                 return;
1872         }
1873
1874 #if defined(ENABLE_JAVASE)
1875         cause = t->cause;
1876 #endif
1877
1878         /* print the root exception */
1879
1880         utf_display_printable_ascii_classname(t->header.vftbl->class->name);
1881
1882         if (t->detailMessage != NULL) {
1883                 u = javastring_toutf(t->detailMessage, false);
1884
1885                 printf(": ");
1886                 utf_display_printable_ascii(u);
1887         }
1888
1889         putc('\n', stdout);
1890
1891 #if defined(ENABLE_JAVASE)
1892         /* print the cause if available */
1893
1894         if ((cause != NULL) && (cause != t)) {
1895                 printf("Caused by: ");
1896                 utf_display_printable_ascii_classname(cause->header.vftbl->class->name);
1897
1898                 if (cause->detailMessage) {
1899                         u = javastring_toutf(cause->detailMessage, false);
1900
1901                         printf(": ");
1902                         utf_display_printable_ascii(u);
1903                 }
1904
1905                 putc('\n', stdout);
1906         }
1907 #endif
1908 }
1909
1910
1911 /* exceptions_print_current_exception ******************************************
1912
1913    Prints the current pending exception, the detail message and the
1914    cause, if available, with CACAO internal functions to stdout.
1915
1916 *******************************************************************************/
1917
1918 void exceptions_print_current_exception(void)
1919 {
1920         java_objectheader *xptr;
1921
1922         xptr = *exceptionptr;
1923
1924         exceptions_print_exception(xptr);
1925 }
1926
1927
1928 /*
1929  * These are local overrides for various environment variables in Emacs.
1930  * Please do not remove this and leave it at the end of the file, where
1931  * Emacs will automagically detect them.
1932  * ---------------------------------------------------------------------
1933  * Local variables:
1934  * mode: c
1935  * indent-tabs-mode: t
1936  * c-basic-offset: 4
1937  * tab-width: 4
1938  * End:
1939  * vim:noexpandtab:sw=4:ts=4:
1940  */