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