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