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