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