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