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