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