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