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