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