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