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