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