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