ec712c6f2e87aac39c5a8c4b90ec8d3846639229
[cacao.git] / src / vm / exceptions.cpp
1 /* src/vm/exceptions.c - exception related functions
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <string.h>
30 #include <stdarg.h>
31 #include <stdlib.h>
32 #include <sys/mman.h>
33
34 #include "vm/types.h"
35
36 #include "md-abi.h"
37
38 #include "mm/memory.h"
39
40 #include "native/jni.h"
41 #include "native/llni.h"
42 #include "native/native.h"
43
44 #include "native/include/java_lang_String.h"
45 #include "native/include/java_lang_Thread.h"
46 #include "native/include/java_lang_Throwable.h"
47
48 #include "threads/lock-common.h"
49 #include "threads/thread.hpp"
50
51 #include "toolbox/util.h"
52
53 #include "vm/builtin.h"
54 #include "vm/exceptions.hpp"
55 #include "vm/global.h"
56 #include "vm/string.hpp"
57 #include "vm/vm.hpp"
58
59 #include "vm/jit/asmpart.h"
60 #include "vm/jit/jit.h"
61 #include "vm/jit/methodheader.h"
62 #include "vm/jit/patcher-common.h"
63 #include "vm/jit/show.h"
64 #include "vm/jit/stacktrace.hpp"
65 #include "vm/jit/trace.hpp"
66
67 #include "vmcore/class.h"
68 #include "vmcore/globals.hpp"
69 #include "vmcore/loader.h"
70 #include "vmcore/method.h"
71 #include "vmcore/options.h"
72 #include "vmcore/os.hpp"
73
74 #if defined(ENABLE_VMLOG)
75 #include <vmlog_cacao.h>
76 #endif
77
78
79 // FIXME
80 extern "C" {
81
82 /* for raising exceptions from native methods *********************************/
83
84 #if !defined(ENABLE_THREADS)
85 java_object_t *_no_threads_exceptionptr = NULL;
86 #endif
87
88
89 /* exceptions_get_exception ****************************************************
90
91    Returns the current exception pointer of the current thread.
92
93 *******************************************************************************/
94
95 java_handle_t *exceptions_get_exception(void)
96 {
97         java_object_t *o;
98         java_handle_t *e;
99 #if defined(ENABLE_THREADS)
100         threadobject  *t;
101
102         t = THREADOBJECT;
103 #endif
104
105         /* Get the exception. */
106
107         LLNI_CRITICAL_START;
108
109 #if defined(ENABLE_THREADS)
110         o = t->_exceptionptr;
111 #else
112         o = _no_threads_exceptionptr;
113 #endif
114
115         e = LLNI_WRAP(o);
116
117         LLNI_CRITICAL_END;
118
119         /* Return the exception. */
120
121         return e;
122 }
123
124
125 /* exceptions_set_exception ****************************************************
126
127    Sets the exception pointer of the current thread.
128
129 *******************************************************************************/
130
131 void exceptions_set_exception(java_handle_t *e)
132 {
133         threadobject  *t;
134         java_object_t *o;
135
136 #if defined(ENABLE_THREADS)
137         t = THREADOBJECT;
138 #else
139         t = NULL;
140 #endif
141
142         /* Set the exception. */
143
144         LLNI_CRITICAL_START;
145
146         o = LLNI_UNWRAP(e);
147
148 #if !defined(NDEBUG)
149         if (opt_DebugExceptions) {
150                 printf("[exceptions_set_exception  : t=%p, o=%p, class=",
151                            (void *) t, (void *) o);
152                 class_print(o->vftbl->clazz);
153                 printf("]\n");
154         }
155 #endif
156
157 #if defined(ENABLE_THREADS)
158         t->_exceptionptr = o;
159 #else
160         _no_threads_exceptionptr = o;
161 #endif
162
163         LLNI_CRITICAL_END;
164 }
165
166
167 /* exceptions_clear_exception **************************************************
168
169    Clears the current exception pointer of the current thread.
170
171 *******************************************************************************/
172
173 void exceptions_clear_exception(void)
174 {
175         threadobject *t;
176
177 #if defined(ENABLE_THREADS)
178         t = THREADOBJECT;
179 #else
180         t = NULL;
181 #endif
182
183         /* Set the exception. */
184
185 #if !defined(NDEBUG)
186         if (opt_DebugExceptions) {
187                 printf("[exceptions_clear_exception: t=%p]\n", (void *) t);
188         }
189 #endif
190
191 #if defined(ENABLE_THREADS)
192         t->_exceptionptr = NULL;
193 #else
194         _no_threads_exceptionptr = NULL;
195 #endif
196 }
197
198
199 /* exceptions_get_and_clear_exception ******************************************
200
201    Gets the exception pointer of the current thread and clears it.
202    This function may return NULL.
203
204 *******************************************************************************/
205
206 java_handle_t *exceptions_get_and_clear_exception(void)
207 {
208         java_handle_t *o;
209
210         /* Get the exception... */
211
212         o = exceptions_get_exception();
213
214         /* ...and clear the exception if it is set. */
215
216         if (o != NULL)
217                 exceptions_clear_exception();
218
219         /* return the exception */
220
221         return o;
222 }
223
224
225 /* exceptions_abort ************************************************************
226
227    Prints exception to be thrown and aborts.
228
229    IN:
230       classname....class name
231       message......exception message
232
233 *******************************************************************************/
234
235 static void exceptions_abort(utf *classname, utf *message)
236 {
237         log_println("exception thrown while VM is initializing: ");
238
239         log_start();
240         utf_display_printable_ascii_classname(classname);
241
242         if (message != NULL) {
243                 log_print(": ");
244                 utf_display_printable_ascii_classname(message);
245         }
246
247         log_finish();
248
249         vm_abort("Aborting...");
250 }
251
252
253 /* exceptions_new_class_utf ****************************************************
254
255    Creates an exception object with the given class and initalizes it
256    with the given utf message.
257
258    IN:
259       c ......... exception class
260           message ... the message as an utf *
261
262    RETURN VALUE:
263      an exception pointer (in any case -- either it is the newly
264      created exception, or an exception thrown while trying to create
265      it).
266
267 *******************************************************************************/
268
269 static java_handle_t *exceptions_new_class_utf(classinfo *c, utf *message)
270 {
271         java_handle_t *s;
272         java_handle_t *o;
273
274         if (vm->is_initializing()) {
275                 /* This can happen when global class variables are used which
276                    are not initialized yet. */
277
278                 if (c == NULL)
279                         exceptions_abort(NULL, message);
280                 else
281                         exceptions_abort(c->name, message);
282         }
283
284         s = javastring_new(message);
285
286         if (s == NULL)
287                 return exceptions_get_exception();
288
289         o = native_new_and_init_string(c, s);
290
291         if (o == NULL)
292                 return exceptions_get_exception();
293
294         return o;
295 }
296
297
298 /* exceptions_new_utf **********************************************************
299
300    Creates an exception object with the given name and initalizes it.
301
302    IN:
303       classname....class name in UTF-8
304
305 *******************************************************************************/
306
307 static java_handle_t *exceptions_new_utf(utf *classname)
308 {
309         classinfo     *c;
310         java_handle_t *o;
311
312         if (vm->is_initializing())
313                 exceptions_abort(classname, NULL);
314
315         c = load_class_bootstrap(classname);
316
317         if (c == NULL)
318                 return exceptions_get_exception();
319
320         o = native_new_and_init(c);
321
322         if (o == NULL)
323                 return exceptions_get_exception();
324
325         return o;
326 }
327
328
329 /* exceptions_new_utf_javastring ***********************************************
330
331    Creates an exception object with the given name and initalizes it
332    with the given java/lang/String message.
333
334    IN:
335       classname....class name in UTF-8
336           message......the message as a java.lang.String
337
338    RETURN VALUE:
339       an exception pointer (in any case -- either it is the newly created
340           exception, or an exception thrown while trying to create it).
341
342 *******************************************************************************/
343
344 static java_handle_t *exceptions_new_utf_javastring(utf *classname,
345                                                                                                         java_handle_t *message)
346 {
347         java_handle_t *o;
348         classinfo     *c;
349    
350         if (vm->is_initializing())
351                 exceptions_abort(classname, NULL);
352
353         c = load_class_bootstrap(classname);
354
355         if (c == NULL)
356                 return exceptions_get_exception();
357
358         o = native_new_and_init_string(c, message);
359
360         if (o == NULL)
361                 return exceptions_get_exception();
362
363         return o;
364 }
365
366
367 /* exceptions_new_utf_utf ******************************************************
368
369    Creates an exception object with the given name and initalizes it
370    with the given utf message.
371
372    IN:
373       classname....class name in UTF-8
374           message......the message as an utf *
375
376    RETURN VALUE:
377       an exception pointer (in any case -- either it is the newly created
378           exception, or an exception thrown while trying to create it).
379
380 *******************************************************************************/
381
382 static java_handle_t *exceptions_new_utf_utf(utf *classname, utf *message)
383 {
384         classinfo     *c;
385         java_handle_t *o;
386
387         if (vm->is_initializing())
388                 exceptions_abort(classname, message);
389
390         c = load_class_bootstrap(classname);
391
392         if (c == NULL)
393                 return exceptions_get_exception();
394
395         o = exceptions_new_class_utf(c, message);
396
397         return o;
398 }
399
400
401 /* exceptions_throw_class_utf **************************************************
402
403    Creates an exception object with the given class, initalizes and
404    throws it with the given utf message.
405
406    IN:
407       c ......... exception class
408           message ... the message as an utf *
409
410 *******************************************************************************/
411
412 static void exceptions_throw_class_utf(classinfo *c, utf *message)
413 {
414         java_handle_t *o;
415
416         o = exceptions_new_class_utf(c, message);
417
418         exceptions_set_exception(o);
419 }
420
421
422 /* exceptions_throw_utf ********************************************************
423
424    Creates an exception object with the given name, initalizes and
425    throws it.
426
427    IN:
428       classname....class name in UTF-8
429
430 *******************************************************************************/
431
432 static void exceptions_throw_utf(utf *classname)
433 {
434         java_handle_t *o;
435
436         o = exceptions_new_utf(classname);
437
438         if (o == NULL)
439                 return;
440
441         exceptions_set_exception(o);
442 }
443
444
445 /* exceptions_throw_utf_throwable **********************************************
446
447    Creates an exception object with the given name and initalizes it
448    with the given java/lang/Throwable exception.
449
450    IN:
451       classname....class name in UTF-8
452           cause........the given Throwable
453
454 *******************************************************************************/
455
456 static void exceptions_throw_utf_throwable(utf *classname,
457                                                                                    java_handle_t *cause)
458 {
459         classinfo           *c;
460         java_handle_t       *o;
461         methodinfo          *m;
462         java_lang_Throwable *object;
463
464         if (vm->is_initializing())
465                 exceptions_abort(classname, NULL);
466
467         object = (java_lang_Throwable *) cause;
468
469         c = load_class_bootstrap(classname);
470
471         if (c == NULL)
472                 return;
473
474         /* create object */
475
476         o = builtin_new(c);
477         
478         if (o == NULL)
479                 return;
480
481         /* call initializer */
482
483         m = class_resolveclassmethod(c,
484                                                                  utf_init,
485                                                                  utf_java_lang_Throwable__void,
486                                                                  NULL,
487                                                                  true);
488                                                       
489         if (m == NULL)
490                 return;
491
492         (void) vm_call_method(m, o, cause);
493
494         exceptions_set_exception(o);
495 }
496
497
498 /* exceptions_throw_utf_exception **********************************************
499
500    Creates an exception object with the given name and initalizes it
501    with the given java/lang/Exception exception.
502
503    IN:
504       classname....class name in UTF-8
505           exception....the given Exception
506
507 *******************************************************************************/
508
509 static void exceptions_throw_utf_exception(utf *classname,
510                                                                                    java_handle_t *exception)
511 {
512         classinfo     *c;
513         java_handle_t *o;
514         methodinfo    *m;
515
516         if (vm->is_initializing())
517                 exceptions_abort(classname, NULL);
518
519         c = load_class_bootstrap(classname);
520
521         if (c == NULL)
522                 return;
523
524         /* create object */
525
526         o = builtin_new(c);
527         
528         if (o == NULL)
529                 return;
530
531         /* call initializer */
532
533         m = class_resolveclassmethod(c,
534                                                                  utf_init,
535                                                                  utf_java_lang_Exception__V,
536                                                                  NULL,
537                                                                  true);
538                                                       
539         if (m == NULL)
540                 return;
541
542         (void) vm_call_method(m, o, exception);
543
544         exceptions_set_exception(o);
545 }
546
547
548 /* exceptions_throw_utf_cause **************************************************
549
550    Creates an exception object with the given name and initalizes it
551    with the given java/lang/Throwable exception with initCause.
552
553    IN:
554       classname....class name in UTF-8
555           cause........the given Throwable
556
557 *******************************************************************************/
558
559 static void exceptions_throw_utf_cause(utf *classname, java_handle_t *cause)
560 {
561         classinfo           *c;
562         java_handle_t       *o;
563         methodinfo          *m;
564         java_lang_String    *s;
565         java_lang_Throwable *object;
566
567         if (vm->is_initializing())
568                 exceptions_abort(classname, NULL);
569
570         object = (java_lang_Throwable *) cause;
571
572         c = load_class_bootstrap(classname);
573
574         if (c == NULL)
575                 return;
576
577         /* create object */
578
579         o = builtin_new(c);
580         
581         if (o == NULL)
582                 return;
583
584         /* call initializer */
585
586         m = class_resolveclassmethod(c,
587                                                                  utf_init,
588                                                                  utf_java_lang_String__void,
589                                                                  NULL,
590                                                                  true);
591                                                       
592         if (m == NULL)
593                 return;
594
595         LLNI_field_get_ref(object, detailMessage, s);
596
597         (void) vm_call_method(m, o, s);
598
599         /* call initCause */
600
601         m = class_resolveclassmethod(c,
602                                                                  utf_initCause,
603                                                                  utf_java_lang_Throwable__java_lang_Throwable,
604                                                                  NULL,
605                                                                  true);
606
607         if (m == NULL)
608                 return;
609
610         (void) vm_call_method(m, o, cause);
611
612         exceptions_set_exception(o);
613 }
614
615
616 /* exceptions_throw_utf_utf ****************************************************
617
618    Creates an exception object with the given name, initalizes and
619    throws it with the given utf message.
620
621    IN:
622       classname....class name in UTF-8
623           message......the message as an utf *
624
625 *******************************************************************************/
626
627 static void exceptions_throw_utf_utf(utf *classname, utf *message)
628 {
629         java_handle_t *o;
630
631         o = exceptions_new_utf_utf(classname, message);
632
633         exceptions_set_exception(o);
634 }
635
636
637 /* exceptions_new_abstractmethoderror ****************************************
638
639    Generates a java.lang.AbstractMethodError for the VM.
640
641 *******************************************************************************/
642
643 java_handle_t *exceptions_new_abstractmethoderror(void)
644 {
645         java_handle_t *o;
646
647         o = exceptions_new_utf(utf_java_lang_AbstractMethodError);
648
649         return o;
650 }
651
652
653 /* exceptions_new_error ********************************************************
654
655    Generates a java.lang.Error for the VM.
656
657 *******************************************************************************/
658
659 #if defined(ENABLE_JAVAME_CLDC1_1)
660 static java_handle_t *exceptions_new_error(utf *message)
661 {
662         java_handle_t *o;
663
664         o = exceptions_new_utf_utf(utf_java_lang_Error, message);
665
666         return o;
667 }
668 #endif
669
670
671 /* exceptions_asm_new_abstractmethoderror **************************************
672
673    Generates a java.lang.AbstractMethodError for
674    asm_abstractmethoderror.
675
676 *******************************************************************************/
677
678 java_object_t *exceptions_asm_new_abstractmethoderror(u1 *sp, u1 *ra)
679 {
680         stackframeinfo_t  sfi;
681         java_handle_t    *e;
682         java_object_t    *o;
683
684         /* Fill and add a stackframeinfo (XPC is equal to RA). */
685
686         stacktrace_stackframeinfo_add(&sfi, NULL, sp, ra, ra);
687
688         /* create the exception */
689
690 #if defined(ENABLE_JAVASE)
691         e = exceptions_new_abstractmethoderror();
692 #else
693         e = exceptions_new_error(utf_java_lang_AbstractMethodError);
694 #endif
695
696         /* Remove the stackframeinfo. */
697
698         stacktrace_stackframeinfo_remove(&sfi);
699
700         /* unwrap the exception */
701         /* ATTENTION: do the this _after_ the stackframeinfo was removed */
702
703         o = LLNI_UNWRAP(e);
704
705         return o;
706 }
707
708
709 /* exceptions_new_arraystoreexception ******************************************
710
711    Generates a java.lang.ArrayStoreException for the VM.
712
713 *******************************************************************************/
714
715 java_handle_t *exceptions_new_arraystoreexception(void)
716 {
717         java_handle_t *o;
718
719         o = exceptions_new_utf(utf_java_lang_ArrayStoreException);
720
721         return o;
722 }
723
724
725 /* exceptions_throw_abstractmethoderror ****************************************
726
727    Generates and throws a java.lang.AbstractMethodError for the VM.
728
729 *******************************************************************************/
730
731 void exceptions_throw_abstractmethoderror(void)
732 {
733         exceptions_throw_utf(utf_java_lang_AbstractMethodError);
734 }
735
736
737 /* exceptions_throw_classcircularityerror **************************************
738
739    Generates and throws a java.lang.ClassCircularityError for the
740    classloader.
741
742    IN:
743       c....the class in which the error was found
744
745 *******************************************************************************/
746
747 void exceptions_throw_classcircularityerror(classinfo *c)
748 {
749         exceptions_throw_utf_utf(utf_java_lang_ClassCircularityError, c->name);
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         char    *msg;
766         s4       msglen;
767         va_list  ap;
768         utf     *u;
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         u = utf_new_char(msg);
805
806         /* free memory */
807
808         MFREE(msg, char, msglen);
809
810         /* throw exception */
811
812         exceptions_throw_utf_utf(utf_java_lang_ClassFormatError, u);
813 }
814
815
816 /* exceptions_throw_classnotfoundexception *************************************
817
818    Generates and throws a java.lang.ClassNotFoundException for the
819    VM.
820
821    IN:
822       name.........name of the class not found as a utf *
823
824 *******************************************************************************/
825
826 void exceptions_throw_classnotfoundexception(utf *name)
827 {       
828         exceptions_throw_class_utf(class_java_lang_ClassNotFoundException, name);
829 }
830
831
832 /* exceptions_throw_noclassdeffounderror ***************************************
833
834    Generates and throws a java.lang.NoClassDefFoundError.
835
836    IN:
837       name.........name of the class not found as a utf *
838
839 *******************************************************************************/
840
841 void exceptions_throw_noclassdeffounderror(utf *name)
842 {
843         exceptions_throw_utf_utf(utf_java_lang_NoClassDefFoundError, name);
844 }
845
846
847 /* exceptions_throw_noclassdeffounderror_cause *********************************
848
849    Generates and throws a java.lang.NoClassDefFoundError with the
850    given cause.
851
852 *******************************************************************************/
853
854 void exceptions_throw_noclassdeffounderror_cause(java_handle_t *cause)
855 {
856         exceptions_throw_utf_cause(utf_java_lang_NoClassDefFoundError, cause);
857 }
858
859
860 /* exceptions_throw_noclassdeffounderror_wrong_name ****************************
861
862    Generates and throws a java.lang.NoClassDefFoundError with a
863    specific message:
864
865    IN:
866       name.........name of the class not found as a utf *
867
868 *******************************************************************************/
869
870 void exceptions_throw_noclassdeffounderror_wrong_name(classinfo *c, utf *name)
871 {
872         char *msg;
873         s4    msglen;
874         utf  *u;
875
876         msglen = utf_bytes(c->name) + strlen(" (wrong name: ") +
877                 utf_bytes(name) + strlen(")") + strlen("0");
878
879         msg = MNEW(char, msglen);
880
881         utf_copy_classname(msg, c->name);
882         strcat(msg, " (wrong name: ");
883         utf_cat_classname(msg, name);
884         strcat(msg, ")");
885
886         u = utf_new_char(msg);
887
888         MFREE(msg, char, msglen);
889
890         exceptions_throw_noclassdeffounderror(u);
891 }
892
893
894 /* exceptions_throw_exceptionininitializererror ********************************
895
896    Generates and throws a java.lang.ExceptionInInitializerError for
897    the VM.
898
899    IN:
900       cause......cause exception object
901
902 *******************************************************************************/
903
904 void exceptions_throw_exceptionininitializererror(java_handle_t *cause)
905 {
906         exceptions_throw_utf_throwable(utf_java_lang_ExceptionInInitializerError,
907                                                                    cause);
908 }
909
910
911 /* exceptions_throw_incompatibleclasschangeerror *******************************
912
913    Generates and throws a java.lang.IncompatibleClassChangeError for
914    the VM.
915
916    IN:
917       message......UTF-8 message format string
918
919 *******************************************************************************/
920
921 void exceptions_throw_incompatibleclasschangeerror(classinfo *c, const char *message)
922 {
923         char *msg;
924         s4    msglen;
925         utf  *u;
926
927         /* calculate exception message length */
928
929         msglen = utf_bytes(c->name) + strlen(message) + strlen("0");
930
931         /* allocate memory */
932
933         msg = MNEW(char, msglen);
934
935         utf_copy_classname(msg, c->name);
936         strcat(msg, message);
937
938         u = utf_new_char(msg);
939
940         /* free memory */
941
942         MFREE(msg, char, msglen);
943
944         /* throw exception */
945
946         exceptions_throw_utf_utf(utf_java_lang_IncompatibleClassChangeError, u);
947 }
948
949
950 /* exceptions_throw_instantiationerror *****************************************
951
952    Generates and throws a java.lang.InstantiationError for the VM.
953
954 *******************************************************************************/
955
956 void exceptions_throw_instantiationerror(classinfo *c)
957 {
958         exceptions_throw_utf_utf(utf_java_lang_InstantiationError, c->name);
959 }
960
961
962 /* exceptions_throw_internalerror **********************************************
963
964    Generates and throws a java.lang.InternalError for the VM.
965
966    IN:
967       message......UTF-8 message format string
968
969 *******************************************************************************/
970
971 void exceptions_throw_internalerror(const char *message, ...)
972 {
973         va_list  ap;
974         char    *msg;
975         s4       msglen;
976         utf     *u;
977
978         /* calculate exception message length */
979
980         va_start(ap, message);
981         msglen = get_variable_message_length(message, ap);
982         va_end(ap);
983
984         /* allocate memory */
985
986         msg = MNEW(char, msglen);
987
988         /* generate message */
989
990         va_start(ap, message);
991         vsprintf(msg, message, ap);
992         va_end(ap);
993
994         u = utf_new_char(msg);
995
996         /* free memory */
997
998         MFREE(msg, char, msglen);
999
1000         /* throw exception */
1001
1002         exceptions_throw_utf_utf(utf_java_lang_InternalError, u);
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         utf  *u;
1020         char *msg;
1021         int   len;
1022
1023         /* calculate exception message length */
1024
1025         len = strlen(message) + 1;
1026
1027         if (c != NULL)
1028                 len += utf_bytes(c->name);
1029                 
1030         /* allocate memory */
1031
1032         msg = MNEW(char, len);
1033
1034         /* generate message */
1035
1036         strcpy(msg, message);
1037
1038         if (c != NULL)
1039                 utf_cat_classname(msg, c->name);
1040
1041         u = utf_new_char(msg);
1042
1043         /* free memory */
1044
1045         MFREE(msg, char, len);
1046
1047         exceptions_throw_utf_utf(utf_java_lang_LinkageError, u);
1048 }
1049
1050
1051 /* exceptions_throw_nosuchfielderror *******************************************
1052
1053    Generates and throws a java.lang.NoSuchFieldError with an error
1054    message.
1055
1056    IN:
1057       c............class in which the field was not found
1058           name.........name of the field
1059
1060 *******************************************************************************/
1061
1062 void exceptions_throw_nosuchfielderror(classinfo *c, utf *name)
1063 {
1064         char *msg;
1065         s4    msglen;
1066         utf  *u;
1067
1068         /* calculate exception message length */
1069
1070         msglen = utf_bytes(c->name) + strlen(".") + utf_bytes(name) + strlen("0");
1071
1072         /* allocate memory */
1073
1074         msg = MNEW(char, msglen);
1075
1076         /* generate message */
1077
1078         utf_copy_classname(msg, c->name);
1079         strcat(msg, ".");
1080         utf_cat(msg, name);
1081
1082         u = utf_new_char(msg);
1083
1084         /* free memory */
1085
1086         MFREE(msg, char, msglen);
1087
1088         exceptions_throw_utf_utf(utf_java_lang_NoSuchFieldError, u);
1089 }
1090
1091
1092 /* exceptions_throw_nosuchmethoderror ******************************************
1093
1094    Generates and throws a java.lang.NoSuchMethodError with an error
1095    message.
1096
1097    IN:
1098       c............class in which the method was not found
1099           name.........name of the method
1100           desc.........descriptor of the method
1101
1102 *******************************************************************************/
1103
1104 void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc)
1105 {
1106         char *msg;
1107         s4    msglen;
1108         utf  *u;
1109
1110         /* calculate exception message length */
1111
1112         msglen = utf_bytes(c->name) + strlen(".") + utf_bytes(name) +
1113                 utf_bytes(desc) + strlen("0");
1114
1115         /* allocate memory */
1116
1117         msg = MNEW(char, msglen);
1118
1119         /* generate message */
1120
1121         utf_copy_classname(msg, c->name);
1122         strcat(msg, ".");
1123         utf_cat(msg, name);
1124         utf_cat(msg, desc);
1125
1126         u = utf_new_char(msg);
1127
1128         /* free memory */
1129
1130         MFREE(msg, char, msglen);
1131
1132 #if defined(ENABLE_JAVASE)
1133         exceptions_throw_utf_utf(utf_java_lang_NoSuchMethodError, u);
1134 #else
1135         exceptions_throw_utf_utf(utf_java_lang_Error, u);
1136 #endif
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_utf(utf_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_utf_utf(utf_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         char *msg;
1186     s4    msglen;
1187         utf  *u;
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         u = utf_new_char(msg);
1207
1208         /* free memory */
1209
1210         MFREE(msg, char, msglen);
1211
1212         /* throw exception */
1213
1214         exceptions_throw_utf_utf(utf_java_lang_UnsupportedClassVersionError, u);
1215 }
1216
1217
1218 /* exceptions_throw_verifyerror ************************************************
1219
1220    Generates and throws a java.lang.VerifyError for the JIT compiler.
1221
1222    IN:
1223       m............method in which the error was found
1224           message......UTF-8 format string
1225
1226 *******************************************************************************/
1227
1228 void exceptions_throw_verifyerror(methodinfo *m, const char *message, ...)
1229 {
1230         va_list  ap;
1231         char    *msg;
1232         s4       msglen;
1233         utf     *u;
1234
1235         /* calculate exception message length */
1236
1237         msglen = 0;
1238
1239         if (m != NULL)
1240                 msglen =
1241                         strlen("(class: ") + utf_bytes(m->clazz->name) +
1242                         strlen(", method: ") + utf_bytes(m->name) +
1243                         strlen(" signature: ") + utf_bytes(m->descriptor) +
1244                         strlen(") ") + strlen("0");
1245
1246         va_start(ap, message);
1247         msglen += get_variable_message_length(message, ap);
1248         va_end(ap);
1249
1250         /* allocate memory */
1251
1252         msg = MNEW(char, msglen);
1253
1254         /* generate message */
1255
1256         if (m != NULL) {
1257                 strcpy(msg, "(class: ");
1258                 utf_cat_classname(msg, m->clazz->name);
1259                 strcat(msg, ", method: ");
1260                 utf_cat(msg, m->name);
1261                 strcat(msg, " signature: ");
1262                 utf_cat(msg, m->descriptor);
1263                 strcat(msg, ") ");
1264         }
1265
1266         va_start(ap, message);
1267         vsprintf(msg + strlen(msg), message, ap);
1268         va_end(ap);
1269
1270         u = utf_new_char(msg);
1271
1272         /* free memory */
1273
1274         MFREE(msg, char, msglen);
1275
1276         /* throw exception */
1277
1278         exceptions_throw_utf_utf(utf_java_lang_VerifyError, u);
1279 }
1280
1281
1282 /* exceptions_throw_verifyerror_for_stack **************************************
1283
1284    throws a java.lang.VerifyError for an invalid stack slot type
1285
1286    IN:
1287       m............method in which the error was found
1288           type.........the expected type
1289
1290    RETURN VALUE:
1291       an exception pointer (in any case -- either it is the newly created
1292           exception, or an exception thrown while trying to create it).
1293
1294 *******************************************************************************/
1295
1296 void exceptions_throw_verifyerror_for_stack(methodinfo *m, int type)
1297 {
1298         char *msg;
1299         s4    msglen;
1300         utf  *u;
1301
1302         /* calculate exception message length */
1303
1304         msglen = 0;
1305
1306         if (m != NULL)
1307                 msglen = strlen("(class: ") + utf_bytes(m->clazz->name) +
1308                         strlen(", method: ") + utf_bytes(m->name) +
1309                         strlen(" signature: ") + utf_bytes(m->descriptor) +
1310                         strlen(") Expecting to find longest-------typename on stack") 
1311                         + strlen("0");
1312
1313         /* allocate memory */
1314
1315         msg = MNEW(char, msglen);
1316
1317         /* generate message */
1318
1319         if (m != NULL) {
1320                 strcpy(msg, "(class: ");
1321                 utf_cat_classname(msg, m->clazz->name);
1322                 strcat(msg, ", method: ");
1323                 utf_cat(msg, m->name);
1324                 strcat(msg, " signature: ");
1325                 utf_cat(msg, m->descriptor);
1326                 strcat(msg, ") ");
1327         }
1328         else {
1329                 msg[0] = 0;
1330         }
1331
1332         strcat(msg, "Expecting to find ");
1333
1334         const char *name;
1335
1336         switch (type) {
1337         case TYPE_INT: name = "integer";       break;
1338         case TYPE_LNG: name = "long";          break;
1339         case TYPE_FLT: name = "float";         break;
1340         case TYPE_DBL: name = "double";        break;
1341         case TYPE_ADR: name = "object/array";  break;
1342         case TYPE_RET: name = "returnAddress"; break;
1343         default:       name = "<INVALID>"; assert(0); break;
1344         }
1345
1346         strcat(msg, name);
1347         strcat(msg, " on stack");
1348
1349         u = utf_new_char(msg);
1350
1351         /* free memory */
1352
1353         MFREE(msg, char, msglen);
1354
1355         /* throw exception */
1356
1357         exceptions_throw_utf_utf(utf_java_lang_VerifyError, u);
1358 }
1359
1360
1361 /* exceptions_new_arithmeticexception ******************************************
1362
1363    Generates a java.lang.ArithmeticException for the JIT compiler.
1364
1365 *******************************************************************************/
1366
1367 java_handle_t *exceptions_new_arithmeticexception(void)
1368 {
1369         java_handle_t *o;
1370
1371         o = exceptions_new_utf_utf(utf_java_lang_ArithmeticException,
1372                                                            utf_division_by_zero);
1373
1374         return o;
1375 }
1376
1377
1378 /* exceptions_new_arrayindexoutofboundsexception *******************************
1379
1380    Generates a java.lang.ArrayIndexOutOfBoundsException for the VM
1381    system.
1382
1383 *******************************************************************************/
1384
1385 java_handle_t *exceptions_new_arrayindexoutofboundsexception(s4 index)
1386 {
1387         java_handle_t *o;
1388         methodinfo    *m;
1389         java_handle_t *s;
1390
1391         /* convert the index into a String, like Sun does */
1392
1393         m = class_resolveclassmethod(class_java_lang_String,
1394                                                                  utf_new_char("valueOf"),
1395                                                                  utf_new_char("(I)Ljava/lang/String;"),
1396                                                                  class_java_lang_Object,
1397                                                                  true);
1398
1399         if (m == NULL)
1400                 return exceptions_get_exception();
1401
1402         s = vm_call_method(m, NULL, index);
1403
1404         if (s == NULL)
1405                 return exceptions_get_exception();
1406
1407         o = exceptions_new_utf_javastring(utf_java_lang_ArrayIndexOutOfBoundsException,
1408                                                                           s);
1409
1410         if (o == NULL)
1411                 return exceptions_get_exception();
1412
1413         return o;
1414 }
1415
1416
1417 /* exceptions_throw_arrayindexoutofboundsexception *****************************
1418
1419    Generates and throws a java.lang.ArrayIndexOutOfBoundsException for
1420    the VM.
1421
1422 *******************************************************************************/
1423
1424 void exceptions_throw_arrayindexoutofboundsexception(void)
1425 {
1426         exceptions_throw_utf(utf_java_lang_ArrayIndexOutOfBoundsException);
1427 }
1428
1429
1430 /* exceptions_throw_arraystoreexception ****************************************
1431
1432    Generates and throws a java.lang.ArrayStoreException for the VM.
1433
1434 *******************************************************************************/
1435
1436 void exceptions_throw_arraystoreexception(void)
1437 {
1438         exceptions_throw_utf(utf_java_lang_ArrayStoreException);
1439 }
1440
1441
1442 /* exceptions_new_classcastexception *******************************************
1443
1444    Generates a java.lang.ClassCastException for the JIT compiler.
1445
1446 *******************************************************************************/
1447
1448 java_handle_t *exceptions_new_classcastexception(java_handle_t *o)
1449 {
1450         java_handle_t *e;
1451         classinfo     *c;
1452         utf           *classname;
1453
1454         LLNI_class_get(o, c);
1455
1456         classname = c->name;
1457
1458         e = exceptions_new_utf_utf(utf_java_lang_ClassCastException, classname);
1459
1460         return e;
1461 }
1462
1463
1464 /* exceptions_throw_clonenotsupportedexception *********************************
1465
1466    Generates and throws a java.lang.CloneNotSupportedException for the
1467    VM.
1468
1469 *******************************************************************************/
1470
1471 void exceptions_throw_clonenotsupportedexception(void)
1472 {
1473         exceptions_throw_utf(utf_java_lang_CloneNotSupportedException);
1474 }
1475
1476
1477 /* exceptions_throw_illegalaccessexception *************************************
1478
1479    Generates and throws a java.lang.IllegalAccessException for the VM.
1480
1481 *******************************************************************************/
1482
1483 void exceptions_throw_illegalaccessexception(utf *message)
1484 {
1485         exceptions_throw_utf_utf(utf_java_lang_IllegalAccessException, message);
1486 }
1487
1488
1489 /* exceptions_throw_illegalargumentexception ***********************************
1490
1491    Generates and throws a java.lang.IllegalArgumentException for the
1492    VM.
1493
1494 *******************************************************************************/
1495
1496 void exceptions_throw_illegalargumentexception(void)
1497 {
1498         exceptions_throw_utf(utf_java_lang_IllegalArgumentException);
1499 }
1500
1501
1502 /* exceptions_throw_illegalmonitorstateexception *******************************
1503
1504    Generates and throws a java.lang.IllegalMonitorStateException for
1505    the VM.
1506
1507 *******************************************************************************/
1508
1509 void exceptions_throw_illegalmonitorstateexception(void)
1510 {
1511         exceptions_throw_utf(utf_java_lang_IllegalMonitorStateException);
1512 }
1513
1514
1515 /* exceptions_throw_instantiationexception *************************************
1516
1517    Generates and throws a java.lang.InstantiationException for the VM.
1518
1519 *******************************************************************************/
1520
1521 void exceptions_throw_instantiationexception(classinfo *c)
1522 {
1523         exceptions_throw_utf_utf(utf_java_lang_InstantiationException, c->name);
1524 }
1525
1526
1527 /* exceptions_throw_interruptedexception ***************************************
1528
1529    Generates and throws a java.lang.InterruptedException for the VM.
1530
1531 *******************************************************************************/
1532
1533 void exceptions_throw_interruptedexception(void)
1534 {
1535         exceptions_throw_utf(utf_java_lang_InterruptedException);
1536 }
1537
1538
1539 /* exceptions_throw_invocationtargetexception **********************************
1540
1541    Generates and throws a java.lang.reflect.InvocationTargetException
1542    for the VM.
1543
1544    IN:
1545       cause......cause exception object
1546
1547 *******************************************************************************/
1548
1549 void exceptions_throw_invocationtargetexception(java_handle_t *cause)
1550 {
1551         exceptions_throw_utf_throwable(utf_java_lang_reflect_InvocationTargetException,
1552                                                                    cause);
1553 }
1554
1555
1556 /* exceptions_throw_negativearraysizeexception *********************************
1557
1558    Generates and throws a java.lang.NegativeArraySizeException for the
1559    VM.
1560
1561 *******************************************************************************/
1562
1563 void exceptions_throw_negativearraysizeexception(void)
1564 {
1565         exceptions_throw_utf(utf_java_lang_NegativeArraySizeException);
1566 }
1567
1568
1569 /* exceptions_new_nullpointerexception *****************************************
1570
1571    Generates a java.lang.NullPointerException for the VM system.
1572
1573 *******************************************************************************/
1574
1575 java_handle_t *exceptions_new_nullpointerexception(void)
1576 {
1577         java_handle_t *o;
1578
1579         o = exceptions_new_utf(utf_java_lang_NullPointerException);
1580
1581         return o;
1582 }
1583
1584
1585 /* exceptions_throw_nullpointerexception ***************************************
1586
1587    Generates a java.lang.NullPointerException for the VM system and
1588    throw it in the VM system.
1589
1590 *******************************************************************************/
1591
1592 void exceptions_throw_nullpointerexception(void)
1593 {
1594         exceptions_throw_utf(utf_java_lang_NullPointerException);
1595 }
1596
1597
1598 /* exceptions_throw_privilegedactionexception **********************************
1599
1600    Generates and throws a java.security.PrivilegedActionException.
1601
1602 *******************************************************************************/
1603
1604 void exceptions_throw_privilegedactionexception(java_handle_t *exception)
1605 {
1606         exceptions_throw_utf_exception(utf_java_security_PrivilegedActionException,
1607                                                                    exception);
1608 }
1609
1610
1611 /* exceptions_throw_stringindexoutofboundsexception ****************************
1612
1613    Generates and throws a java.lang.StringIndexOutOfBoundsException
1614    for the VM.
1615
1616 *******************************************************************************/
1617
1618 void exceptions_throw_stringindexoutofboundsexception(void)
1619 {
1620         exceptions_throw_utf(utf_java_lang_StringIndexOutOfBoundsException);
1621 }
1622
1623
1624 /* exceptions_fillinstacktrace *************************************************
1625
1626    Calls the fillInStackTrace-method of the currently thrown
1627    exception.
1628
1629 *******************************************************************************/
1630
1631 java_handle_t *exceptions_fillinstacktrace(void)
1632 {
1633         java_handle_t *o;
1634         classinfo     *c;
1635         methodinfo    *m;
1636
1637         /* get exception */
1638
1639         o = exceptions_get_and_clear_exception();
1640
1641         assert(o);
1642
1643         /* resolve methodinfo pointer from exception object */
1644
1645         LLNI_class_get(o, c);
1646
1647 #if defined(ENABLE_JAVASE)
1648         m = class_resolvemethod(c,
1649                                                         utf_fillInStackTrace,
1650                                                         utf_void__java_lang_Throwable);
1651 #elif defined(ENABLE_JAVAME_CLDC1_1)
1652         m = class_resolvemethod(c,
1653                                                         utf_fillInStackTrace,
1654                                                         utf_void__void);
1655 #else
1656 #error IMPLEMENT ME!
1657 #endif
1658
1659         /* call function */
1660
1661         (void) vm_call_method(m, o);
1662
1663         /* return exception object */
1664
1665         return o;
1666 }
1667
1668
1669 /* exceptions_handle_exception *************************************************
1670
1671    Try to find an exception handler for the given exception and return it.
1672    If no handler is found, exit the monitor of the method (if any)
1673    and return NULL.
1674
1675    IN:
1676       xptr.........the exception object
1677           xpc..........PC of where the exception was thrown
1678           pv...........Procedure Value of the current method
1679           sp...........current stack pointer
1680
1681    RETURN VALUE:
1682       the address of the first matching exception handler, or
1683           NULL if no handler was found
1684
1685 *******************************************************************************/
1686
1687 #if defined(ENABLE_JIT)
1688 void *exceptions_handle_exception(java_object_t *xptro, void *xpc, void *pv, void *sp)
1689 {
1690         stackframeinfo_t        sfi;
1691         java_handle_t          *xptr;
1692         methodinfo             *m;
1693         codeinfo               *code;
1694         exceptiontable_t       *et;
1695         exceptiontable_entry_t *ete;
1696         s4                      i;
1697         classref_or_classinfo   cr;
1698         classinfo              *c;
1699 #if defined(ENABLE_THREADS)
1700         java_object_t          *o;
1701 #endif
1702         void                   *result;
1703
1704 #ifdef __S390__
1705         /* Addresses are 31 bit integers */
1706 #       define ADDR_MASK(x) (void *) ((uintptr_t) (x) & 0x7FFFFFFF)
1707 #else
1708 #       define ADDR_MASK(x) (x)
1709 #endif
1710
1711         xptr = LLNI_WRAP(xptro);
1712         xpc  = ADDR_MASK(xpc);
1713
1714         /* Fill and add a stackframeinfo (XPC is equal to RA). */
1715
1716         stacktrace_stackframeinfo_add(&sfi, pv, sp, xpc, xpc);
1717
1718         result = NULL;
1719
1720         /* Get the codeinfo for the current method. */
1721
1722         code = code_get_codeinfo_for_pv(pv);
1723
1724         /* Get the methodinfo pointer from the codeinfo pointer. For
1725            asm_vm_call_method the codeinfo pointer is NULL and we simply
1726            can return the proper exception handler. */
1727
1728         if (code == NULL) {
1729                 result = (void *) (uintptr_t) &asm_vm_call_method_exception_handler;
1730                 goto exceptions_handle_exception_return;
1731         }
1732
1733         m = code->m;
1734
1735 #if !defined(NDEBUG)
1736         /* print exception trace */
1737
1738         if (opt_TraceExceptions)
1739                 trace_exception(LLNI_DIRECT(xptr), m, xpc);
1740
1741 # if defined(ENABLE_VMLOG)
1742         vmlog_cacao_throw(xptr);
1743 # endif
1744 #endif
1745
1746         /* Get the exception table. */
1747
1748         et = code->exceptiontable;
1749
1750         if (et != NULL) {
1751         /* Iterate over all exception table entries. */
1752
1753         ete = et->entries;
1754
1755         for (i = 0; i < et->length; i++, ete++) {
1756                 /* is the xpc is the current catch range */
1757
1758                 if ((ADDR_MASK(ete->startpc) <= xpc) && (xpc < ADDR_MASK(ete->endpc))) {
1759                         cr = ete->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 defined(ENABLE_VMLOG)
1768                                 vmlog_cacao_catch(xptr);
1769 # endif
1770
1771                                 if (opt_TraceExceptions) {
1772                                         exceptions_print_exception(xptr);
1773                                         stacktrace_print_exception(xptr);
1774                                 }
1775 #endif
1776
1777                                 result = ete->handlerpc;
1778                                 goto exceptions_handle_exception_return;
1779                         }
1780
1781                         /* resolve or load/link the exception class */
1782
1783                         if (IS_CLASSREF(cr)) {
1784                                 /* The exception class reference is unresolved. */
1785                                 /* We have to do _eager_ resolving here. While the
1786                                    class of the exception object is guaranteed to be
1787                                    loaded, it may well have been loaded by a different
1788                                    loader than the defining loader of m's class, which
1789                                    is the one we must use to resolve the catch
1790                                    class. Thus lazy resolving might fail, even if the
1791                                    result of the resolution would be an already loaded
1792                                    class. */
1793
1794                                 c = resolve_classref_eager(cr.ref);
1795
1796                                 if (c == NULL) {
1797                                         /* Exception resolving the exception class, argh! */
1798                                         goto exceptions_handle_exception_return;
1799                                 }
1800
1801                                 /* Ok, we resolved it. Enter it in the table, so we
1802                                    don't have to do this again. */
1803                                 /* XXX this write should be atomic. Is it? */
1804
1805                                 ete->catchtype.cls = c;
1806                         }
1807                         else {
1808                                 c = cr.cls;
1809
1810                                 /* XXX I don't think this case can ever happen. -Edwin */
1811                                 if (!(c->state & CLASS_LOADED))
1812                                         /* use the methods' classloader */
1813                                         if (!load_class_from_classloader(c->name,
1814                                                                                                          m->clazz->classloader))
1815                                                 goto exceptions_handle_exception_return;
1816
1817                                 /* XXX I think, if it is not linked, we can be sure
1818                                    that the exception object is no (indirect) instance
1819                                    of it, no?  -Edwin  */
1820                                 if (!(c->state & CLASS_LINKED))
1821                                         if (!link_class(c))
1822                                                 goto exceptions_handle_exception_return;
1823                         }
1824
1825                         /* is the thrown exception an instance of the catch class? */
1826
1827                         if (builtin_instanceof(xptr, c)) {
1828 #if !defined(NDEBUG)
1829                                 /* Print stacktrace of exception when caught. */
1830
1831 # if defined(ENABLE_VMLOG)
1832                                 vmlog_cacao_catch(xptr);
1833 # endif
1834
1835                                 if (opt_TraceExceptions) {
1836                                         exceptions_print_exception(xptr);
1837                                         stacktrace_print_exception(xptr);
1838                                 }
1839 #endif
1840
1841                                 result = ete->handlerpc;
1842                                 goto exceptions_handle_exception_return;
1843                         }
1844                 }
1845         }
1846         }
1847
1848 #if defined(ENABLE_THREADS)
1849         /* Is this method realization synchronized? */
1850
1851         if (code_is_synchronized(code)) {
1852                 /* Get synchronization object. */
1853
1854                 o = *((java_object_t **) (((uintptr_t) sp) + code->synchronizedoffset));
1855
1856                 assert(o != NULL);
1857
1858                 lock_monitor_exit(LLNI_QUICKWRAP(o));
1859         }
1860 #endif
1861
1862         /* none of the exceptions catch this one */
1863
1864 #if !defined(NDEBUG)
1865 # if defined(ENABLE_VMLOG)
1866         vmlog_cacao_unwnd_method(m);
1867 # endif
1868
1869 # if defined(ENABLE_DEBUG_FILTER)
1870         if (show_filters_test_verbosecall_exit(m)) {
1871 # endif
1872
1873         /* outdent the log message */
1874
1875         if (opt_verbosecall) {
1876                 if (TRACEJAVACALLINDENT)
1877                         TRACEJAVACALLINDENT--;
1878                 else
1879                         log_text("exceptions_handle_exception: WARNING: unmatched unindent");
1880         }
1881
1882 # if defined(ENABLE_DEBUG_FILTER)
1883         }
1884 # endif
1885 #endif /* !defined(NDEBUG) */
1886
1887         result = NULL;
1888
1889 exceptions_handle_exception_return:
1890
1891         /* Remove the stackframeinfo. */
1892
1893         stacktrace_stackframeinfo_remove(&sfi);
1894
1895         return result;
1896 }
1897 #endif /* defined(ENABLE_JIT) */
1898
1899
1900 /* exceptions_print_exception **************************************************
1901
1902    Prints an exception, the detail message and the cause, if
1903    available, with CACAO internal functions to stdout.
1904
1905 *******************************************************************************/
1906
1907 void exceptions_print_exception(java_handle_t *xptr)
1908 {
1909         java_lang_Throwable   *t;
1910 #if defined(ENABLE_JAVASE)
1911         java_lang_Throwable   *cause;
1912 #endif
1913         java_lang_String      *s;
1914         classinfo             *c;
1915         utf                   *u;
1916
1917         t = (java_lang_Throwable *) xptr;
1918
1919         if (t == NULL) {
1920                 puts("NULL\n");
1921                 return;
1922         }
1923
1924 #if defined(ENABLE_JAVASE)
1925         LLNI_field_get_ref(t, cause, cause);
1926 #endif
1927
1928         /* print the root exception */
1929
1930         LLNI_class_get(t, c);
1931         utf_display_printable_ascii_classname(c->name);
1932
1933         LLNI_field_get_ref(t, detailMessage, s);
1934
1935         if (s != NULL) {
1936                 u = javastring_toutf((java_handle_t *) s, false);
1937
1938                 printf(": ");
1939                 utf_display_printable_ascii(u);
1940         }
1941
1942         putc('\n', stdout);
1943
1944 #if defined(ENABLE_JAVASE)
1945         /* print the cause if available */
1946
1947         if ((cause != NULL) && (cause != t)) {
1948                 printf("Caused by: ");
1949                 
1950                 LLNI_class_get(cause, c);
1951                 utf_display_printable_ascii_classname(c->name);
1952
1953                 LLNI_field_get_ref(cause, detailMessage, s);
1954
1955                 if (s != NULL) {
1956                         u = javastring_toutf((java_handle_t *) s, false);
1957
1958                         printf(": ");
1959                         utf_display_printable_ascii(u);
1960                 }
1961
1962                 putc('\n', stdout);
1963         }
1964 #endif
1965 }
1966
1967
1968 /* exceptions_print_current_exception ******************************************
1969
1970    Prints the current pending exception, the detail message and the
1971    cause, if available, with CACAO internal functions to stdout.
1972
1973 *******************************************************************************/
1974
1975 void exceptions_print_current_exception(void)
1976 {
1977         java_handle_t *o;
1978
1979         o = exceptions_get_exception();
1980
1981         exceptions_print_exception(o);
1982 }
1983
1984
1985 /* exceptions_print_stacktrace *************************************************
1986
1987    Prints a pending exception with Throwable.printStackTrace().  If
1988    there happens an exception during printStackTrace(), we print the
1989    thrown exception and the original one.
1990
1991    NOTE: This function calls Java code.
1992
1993 *******************************************************************************/
1994
1995 void exceptions_print_stacktrace(void)
1996 {
1997         java_handle_t    *e;
1998         java_handle_t    *ne;
1999         classinfo        *c;
2000         methodinfo       *m;
2001
2002 #if defined(ENABLE_THREADS)
2003         threadobject     *t;
2004         java_lang_Thread *to;
2005 #endif
2006
2007         /* Get and clear exception because we are calling Java code
2008            again. */
2009
2010         e = exceptions_get_and_clear_exception();
2011
2012         if (e == NULL)
2013                 return;
2014
2015 #if 0
2016         /* FIXME Enable me. */
2017         if (builtin_instanceof(e, class_java_lang_ThreadDeath)) {
2018                 /* Don't print anything if we are being killed. */
2019         }
2020         else
2021 #endif
2022         {
2023                 /* Get the exception class. */
2024
2025                 LLNI_class_get(e, c);
2026
2027                 /* Find the printStackTrace() method. */
2028
2029                 m = class_resolveclassmethod(c,
2030                                                                          utf_printStackTrace,
2031                                                                          utf_void__void,
2032                                                                          class_java_lang_Object,
2033                                                                          false);
2034
2035                 if (m == NULL)
2036                         vm_abort("exceptions_print_stacktrace: printStackTrace()V not found");
2037
2038                 /* Print message. */
2039
2040                 fprintf(stderr, "Exception ");
2041
2042 #if defined(ENABLE_THREADS)
2043                 /* Print thread name.  We get the thread here explicitly as we
2044                    need it afterwards. */
2045
2046                 t  = thread_get_current();
2047                 to = (java_lang_Thread *) thread_get_object(t);
2048
2049                 if (to != NULL) {
2050                         fprintf(stderr, "in thread \"");
2051                         thread_fprint_name(t, stderr);
2052                         fprintf(stderr, "\" ");
2053                 }
2054 #endif
2055
2056                 /* Print the stacktrace. */
2057
2058                 if (builtin_instanceof(e, class_java_lang_Throwable)) {
2059                         (void) vm_call_method(m, e);
2060
2061                         /* If this happens we are EXTREMLY out of memory or have a
2062                            serious problem while printStackTrace.  But may be
2063                            another exception, so print it. */
2064
2065                         ne = exceptions_get_exception();
2066
2067                         if (ne != NULL) {
2068                                 fprintf(stderr, "Exception while printStackTrace(): ");
2069
2070                                 /* Print the current exception. */
2071
2072                                 exceptions_print_exception(ne);
2073                                 stacktrace_print_exception(ne);
2074
2075                                 /* Now print the original exception. */
2076
2077                                 fprintf(stderr, "Original exception was: ");
2078                                 exceptions_print_exception(e);
2079                                 stacktrace_print_exception(e);
2080                         }
2081                 }
2082                 else {
2083                         fprintf(stderr, ". Uncaught exception of type ");
2084 #if !defined(NDEBUG)
2085                         /* FIXME This prints to stdout. */
2086                         class_print(c);
2087 #else
2088                         fprintf(stderr, "UNKNOWN");
2089 #endif
2090                         fprintf(stderr, ".");
2091                 }
2092
2093                 fflush(stderr);
2094         }
2095 }
2096
2097 } // extern "C"
2098
2099
2100 /*
2101  * These are local overrides for various environment variables in Emacs.
2102  * Please do not remove this and leave it at the end of the file, where
2103  * Emacs will automagically detect them.
2104  * ---------------------------------------------------------------------
2105  * Local variables:
2106  * mode: c++
2107  * indent-tabs-mode: t
2108  * c-basic-offset: 4
2109  * tab-width: 4
2110  * End:
2111  * vim:noexpandtab:sw=4:ts=4:
2112  */