* tests/Makefile.am: Cleanup, removed checkall, added build target.
[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_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 void *exceptions_handle_exception(java_object_t *xptro, void *xpc, void *pv, void *sp)
1711 {
1712         stackframeinfo_t        sfi;
1713         java_handle_t          *xptr;
1714         methodinfo             *m;
1715         codeinfo               *code;
1716         exceptiontable_t       *et;
1717         exceptiontable_entry_t *ete;
1718         s4                      i;
1719         classref_or_classinfo   cr;
1720         classinfo              *c;
1721 #if defined(ENABLE_THREADS)
1722         java_object_t          *o;
1723 #endif
1724         void                   *result;
1725
1726 #ifdef __S390__
1727         /* Addresses are 31 bit integers */
1728 #       define ADDR_MASK(x) (void *) ((uintptr_t) (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         /* Get the methodinfo pointer from the codeinfo pointer. For
1747            asm_vm_call_method the codeinfo pointer is NULL and we simply
1748            can return the proper exception handler. */
1749
1750         if (code == NULL) {
1751                 result = (void *) (uintptr_t) &asm_vm_call_method_exception_handler;
1752                 goto exceptions_handle_exception_return;
1753         }
1754
1755         m = code->m;
1756
1757 #if !defined(NDEBUG)
1758         /* print exception trace */
1759
1760         if (opt_TraceExceptions)
1761                 trace_exception(LLNI_DIRECT(xptr), m, xpc);
1762
1763 # if defined(ENABLE_VMLOG)
1764         vmlog_cacao_throw(xptr);
1765 # endif
1766 #endif
1767
1768         /* Get the exception table. */
1769
1770         et = code->exceptiontable;
1771
1772         if (et != NULL) {
1773         /* Iterate over all exception table entries. */
1774
1775         ete = et->entries;
1776
1777         for (i = 0; i < et->length; i++, ete++) {
1778                 /* is the xpc is the current catch range */
1779
1780                 if ((ADDR_MASK(ete->startpc) <= xpc) && (xpc < ADDR_MASK(ete->endpc))) {
1781                         cr = ete->catchtype;
1782
1783                         /* NULL catches everything */
1784
1785                         if (cr.any == NULL) {
1786 #if !defined(NDEBUG)
1787                                 /* Print stacktrace of exception when caught. */
1788
1789 # if defined(ENABLE_VMLOG)
1790                                 vmlog_cacao_catch(xptr);
1791 # endif
1792
1793                                 if (opt_TraceExceptions) {
1794                                         exceptions_print_exception(xptr);
1795                                         stacktrace_print_exception(xptr);
1796                                 }
1797 #endif
1798
1799                                 result = ete->handlerpc;
1800                                 goto exceptions_handle_exception_return;
1801                         }
1802
1803                         /* resolve or load/link the exception class */
1804
1805                         if (IS_CLASSREF(cr)) {
1806                                 /* The exception class reference is unresolved. */
1807                                 /* We have to do _eager_ resolving here. While the
1808                                    class of the exception object is guaranteed to be
1809                                    loaded, it may well have been loaded by a different
1810                                    loader than the defining loader of m's class, which
1811                                    is the one we must use to resolve the catch
1812                                    class. Thus lazy resolving might fail, even if the
1813                                    result of the resolution would be an already loaded
1814                                    class. */
1815
1816                                 c = resolve_classref_eager(cr.ref);
1817
1818                                 if (c == NULL) {
1819                                         /* Exception resolving the exception class, argh! */
1820                                         goto exceptions_handle_exception_return;
1821                                 }
1822
1823                                 /* Ok, we resolved it. Enter it in the table, so we
1824                                    don't have to do this again. */
1825                                 /* XXX this write should be atomic. Is it? */
1826
1827                                 ete->catchtype.cls = c;
1828                         }
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
1840                                    that the exception object is no (indirect) instance
1841                                    of it, no?  -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_exception(xptr);
1860                                 }
1861 #endif
1862
1863                                 result = ete->handlerpc;
1864                                 goto exceptions_handle_exception_return;
1865                         }
1866                 }
1867         }
1868         }
1869
1870 #if defined(ENABLE_THREADS)
1871         /* Is this method realization synchronized? */
1872
1873         if (code_is_synchronized(code)) {
1874                 /* Get synchronization object. */
1875
1876                 o = *((java_object_t **) (((uintptr_t) sp) + code->synchronizedoffset));
1877
1878                 assert(o != NULL);
1879
1880                 lock_monitor_exit(LLNI_QUICKWRAP(o));
1881         }
1882 #endif
1883
1884         /* none of the exceptions catch this one */
1885
1886 #if !defined(NDEBUG)
1887 # if defined(ENABLE_VMLOG)
1888         vmlog_cacao_unwnd_method(m);
1889 # endif
1890
1891 # if defined(ENABLE_DEBUG_FILTER)
1892         if (show_filters_test_verbosecall_exit(m)) {
1893 # endif
1894
1895         /* outdent the log message */
1896
1897         if (opt_verbosecall) {
1898                 if (TRACEJAVACALLINDENT)
1899                         TRACEJAVACALLINDENT--;
1900                 else
1901                         log_text("exceptions_handle_exception: WARNING: unmatched unindent");
1902         }
1903
1904 # if defined(ENABLE_DEBUG_FILTER)
1905         }
1906 # endif
1907 #endif /* !defined(NDEBUG) */
1908
1909         result = NULL;
1910
1911 exceptions_handle_exception_return:
1912
1913         /* Remove the stackframeinfo. */
1914
1915         stacktrace_stackframeinfo_remove(&sfi);
1916
1917         return result;
1918 }
1919 #endif /* defined(ENABLE_JIT) */
1920
1921
1922 /* exceptions_print_exception **************************************************
1923
1924    Prints an exception, the detail message and the cause, if
1925    available, with CACAO internal functions to stdout.
1926
1927 *******************************************************************************/
1928
1929 void exceptions_print_exception(java_handle_t *xptr)
1930 {
1931         java_lang_Throwable   *t;
1932 #if defined(ENABLE_JAVASE)
1933         java_lang_Throwable   *cause;
1934 #endif
1935         java_lang_String      *s;
1936         classinfo             *c;
1937         utf                   *u;
1938
1939         t = (java_lang_Throwable *) xptr;
1940
1941         if (t == NULL) {
1942                 puts("NULL\n");
1943                 return;
1944         }
1945
1946 #if defined(ENABLE_JAVASE)
1947         LLNI_field_get_ref(t, cause, cause);
1948 #endif
1949
1950         /* print the root exception */
1951
1952         LLNI_class_get(t, c);
1953         utf_display_printable_ascii_classname(c->name);
1954
1955         LLNI_field_get_ref(t, detailMessage, s);
1956
1957         if (s != NULL) {
1958                 u = javastring_toutf((java_handle_t *) s, false);
1959
1960                 printf(": ");
1961                 utf_display_printable_ascii(u);
1962         }
1963
1964         putc('\n', stdout);
1965
1966 #if defined(ENABLE_JAVASE)
1967         /* print the cause if available */
1968
1969         if ((cause != NULL) && (cause != t)) {
1970                 printf("Caused by: ");
1971                 
1972                 LLNI_class_get(cause, c);
1973                 utf_display_printable_ascii_classname(c->name);
1974
1975                 LLNI_field_get_ref(cause, detailMessage, s);
1976
1977                 if (s != NULL) {
1978                         u = javastring_toutf((java_handle_t *) s, false);
1979
1980                         printf(": ");
1981                         utf_display_printable_ascii(u);
1982                 }
1983
1984                 putc('\n', stdout);
1985         }
1986 #endif
1987 }
1988
1989
1990 /* exceptions_print_current_exception ******************************************
1991
1992    Prints the current pending exception, the detail message and the
1993    cause, if available, with CACAO internal functions to stdout.
1994
1995 *******************************************************************************/
1996
1997 void exceptions_print_current_exception(void)
1998 {
1999         java_handle_t *o;
2000
2001         o = exceptions_get_exception();
2002
2003         exceptions_print_exception(o);
2004 }
2005
2006
2007 /* exceptions_print_stacktrace *************************************************
2008
2009    Prints a pending exception with Throwable.printStackTrace().  If
2010    there happens an exception during printStackTrace(), we print the
2011    thrown exception and the original one.
2012
2013    NOTE: This function calls Java code.
2014
2015 *******************************************************************************/
2016
2017 void exceptions_print_stacktrace(void)
2018 {
2019         java_handle_t *oxptr;
2020         java_handle_t *xptr;
2021         classinfo     *c;
2022         methodinfo    *m;
2023
2024         /* get original exception */
2025
2026         oxptr = exceptions_get_and_clear_exception();
2027
2028         if (oxptr == NULL)
2029                 vm_abort("exceptions_print_stacktrace: no exception thrown");
2030
2031         /* clear exception, because we are calling jit code again */
2032
2033         LLNI_class_get(oxptr, c);
2034
2035         /* find the printStackTrace() method */
2036
2037         m = class_resolveclassmethod(c,
2038                                                                  utf_printStackTrace,
2039                                                                  utf_void__void,
2040                                                                  class_java_lang_Object,
2041                                                                  false);
2042
2043         if (m == NULL)
2044                 vm_abort("exceptions_print_stacktrace: printStackTrace()V not found");
2045
2046         /* print compatibility message */
2047
2048         fprintf(stderr, "Exception in thread \"main\" ");
2049
2050         /* print the stacktrace */
2051
2052         (void) vm_call_method(m, oxptr);
2053
2054         /* This normally means, we are EXTREMLY out of memory or
2055            have a serious problem while printStackTrace. But may
2056            be another exception, so print it. */
2057
2058         xptr = exceptions_get_exception();
2059
2060         if (xptr != NULL) {
2061                 fprintf(stderr, "Exception while printStackTrace(): ");
2062
2063                 /* now print original exception */
2064
2065                 exceptions_print_exception(xptr);
2066                 stacktrace_print_exception(xptr);
2067
2068                 /* now print original exception */
2069
2070                 fprintf(stderr, "Original exception was: ");
2071                 exceptions_print_exception(oxptr);
2072                 stacktrace_print_exception(oxptr);
2073         }
2074
2075         fflush(stderr);
2076 }
2077
2078
2079 /*
2080  * These are local overrides for various environment variables in Emacs.
2081  * Please do not remove this and leave it at the end of the file, where
2082  * Emacs will automagically detect them.
2083  * ---------------------------------------------------------------------
2084  * Local variables:
2085  * mode: c
2086  * indent-tabs-mode: t
2087  * c-basic-offset: 4
2088  * tab-width: 4
2089  * End:
2090  * vim:noexpandtab:sw=4:ts=4:
2091  */