Line data Source code
1 : /* src/vm/exceptions.cpp - exception related functions
2 :
3 : Copyright (C) 1996-2014
4 : CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 :
6 : This file is part of CACAO.
7 :
8 : This program is free software; you can redistribute it and/or
9 : modify it under the terms of the GNU General Public License as
10 : published by the Free Software Foundation; either version 2, or (at
11 : your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful, but
14 : WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program; if not, write to the Free Software
20 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 : 02110-1301, USA.
22 :
23 : */
24 :
25 : #include "vm/exceptions.hpp"
26 : #include <stdint.h> // for uintptr_t
27 : #include <cassert> // for assert
28 : #include <cstring>
29 : #include <cstdio> // for fprintf, printf, putc, etc
30 : #include <cstdarg> // for va_list
31 : #include "config.h"
32 : #include "md-abi.hpp"
33 : #include "jit/code.hpp" // for codeinfo, etc
34 : #include "native/llni.hpp"
35 : #include "native/native.hpp" // for native_new_and_init_string, etc
36 : #include "threads/lock.hpp" // for lock_monitor_exit
37 : #include "threads/thread.hpp" // for threadobject, etc
38 : #include "toolbox/buffer.hpp" // for Buffer
39 : #include "toolbox/logging.hpp" // for log_finish, log_print, etc
40 : #include "vm/class.hpp" // for classinfo, etc
41 : #include "vm/global.hpp" // for java_handle_t, etc
42 : #include "vm/globals.hpp" // for class_java_lang_Object, etc
43 : #include "vm/javaobjects.hpp" // for java_lang_Throwable, etc
44 : #include "vm/jit/asmpart.hpp"
45 : #include "vm/jit/builtin.hpp" // for builtin_new, etc
46 : #include "vm/jit/exceptiontable.hpp" // for exceptiontable_entry_t, etc
47 : #include "vm/jit/methodheader.hpp"
48 : #include "vm/jit/patcher-common.hpp"
49 : #include "vm/jit/show.hpp"
50 : #include "vm/jit/stacktrace.hpp" // for stacktrace_print_exception, etc
51 : #include "vm/jit/trace.hpp" // for trace_exception
52 : #include "vm/linker.hpp" // for link_class
53 : #include "vm/loader.hpp" // for load_class_bootstrap, etc
54 : #include "vm/method.hpp" // for methodinfo
55 : #include "vm/options.hpp" // for opt_TraceExceptions, etc
56 : #include "vm/os.hpp" // for os
57 : #include "vm/references.hpp" // for classref_or_classinfo
58 : #include "vm/resolve.hpp" // for resolve_classref_eager
59 : #include "vm/string.hpp" // for JavaString
60 : #include "vm/types.hpp" // for s4, u1, u4
61 : #include "vm/vm.hpp" // for VM, vm_call_method
62 :
63 : #define DEBUG_NAME "exceptions"
64 :
65 : /***
66 : * Get the the name of a classinfo* for an exception message
67 : */
68 : static inline Utf8String get_classname_for_exception(classinfo *c);
69 :
70 : /* exceptions_get_exception ****************************************************
71 :
72 : Returns the current exception pointer of the current thread.
73 :
74 : *******************************************************************************/
75 :
76 3195331 : java_handle_t *exceptions_get_exception(void)
77 : {
78 3195331 : threadobject *t = THREADOBJECT;
79 :
80 : /* Get the exception. */
81 :
82 : LLNI_CRITICAL_START;
83 :
84 3195331 : java_object_t *o = t->_exceptionptr;
85 3195331 : java_handle_t *e = LLNI_WRAP(o);
86 :
87 : LLNI_CRITICAL_END;
88 :
89 : /* Return the exception. */
90 :
91 3195331 : return e;
92 : }
93 :
94 :
95 : /* exceptions_set_exception ****************************************************
96 :
97 : Sets the exception pointer of the current thread.
98 :
99 : *******************************************************************************/
100 :
101 20918 : void exceptions_set_exception(java_handle_t *e)
102 : {
103 20918 : threadobject *t = THREADOBJECT;
104 :
105 : /* Set the exception. */
106 :
107 : LLNI_CRITICAL_START;
108 :
109 20918 : java_object_t *o = LLNI_UNWRAP(e);
110 :
111 : LOG("[exceptions_set_exception : t=" << (void *) t
112 : << ", o=" << (void *) o
113 : << ", class=" << o->vftbl->clazz << "]" << cacao::nl);
114 :
115 20918 : t->_exceptionptr = o;
116 :
117 : LLNI_CRITICAL_END;
118 20918 : }
119 :
120 :
121 : /* exceptions_clear_exception **************************************************
122 :
123 : Clears the current exception pointer of the current thread.
124 :
125 : *******************************************************************************/
126 :
127 33827 : void exceptions_clear_exception(void)
128 : {
129 33827 : threadobject *t = THREADOBJECT;
130 :
131 : /* Set the exception. */
132 :
133 : LOG("[exceptions_clear_exception: t=" << (void *) t << cacao::nl);
134 :
135 33827 : t->_exceptionptr = NULL;
136 33827 : }
137 :
138 :
139 : /* exceptions_get_and_clear_exception ******************************************
140 :
141 : Gets the exception pointer of the current thread and clears it.
142 : This function may return NULL.
143 :
144 : *******************************************************************************/
145 :
146 3100849 : java_handle_t *exceptions_get_and_clear_exception(void)
147 : {
148 : java_handle_t *o;
149 :
150 : /* Get the exception... */
151 :
152 3100849 : o = exceptions_get_exception();
153 :
154 : /* ...and clear the exception if it is set. */
155 :
156 3100911 : if (o != NULL)
157 20869 : exceptions_clear_exception();
158 :
159 : /* return the exception */
160 :
161 3100911 : return o;
162 : }
163 :
164 :
165 : /* exceptions_abort ************************************************************
166 :
167 : Prints exception to be thrown and aborts.
168 :
169 : IN:
170 : classname....class name
171 : message......exception message
172 :
173 : *******************************************************************************/
174 :
175 0 : static void exceptions_abort(Utf8String classname, Utf8String message)
176 : {
177 0 : log_println("exception thrown while VM is initializing: ");
178 :
179 0 : log_start();
180 0 : utf_display_printable_ascii_classname(classname);
181 :
182 0 : if (message != NULL) {
183 0 : log_print(": ");
184 0 : utf_display_printable_ascii_classname(message);
185 : }
186 :
187 0 : log_finish();
188 :
189 0 : os::abort("Aborting...");
190 0 : }
191 :
192 :
193 : /* exceptions_new_class_Utf8String ***************************************************
194 :
195 : Creates an exception object with the given class and initalizes it
196 : with the given utf message.
197 :
198 : IN:
199 : c ......... exception class
200 : message ... the message as an Utf8String
201 :
202 : RETURN VALUE:
203 : an exception pointer (in any case -- either it is the newly
204 : created exception, or an exception thrown while trying to create
205 : it).
206 :
207 : *******************************************************************************/
208 :
209 839 : static java_handle_t *exceptions_new_class_utf(classinfo *c, Utf8String message)
210 : {
211 : java_handle_t *s;
212 : java_handle_t *o;
213 :
214 839 : if (VM::get_current()->is_initializing()) {
215 : /* This can happen when global class variables are used which
216 : are not initialized yet. */
217 :
218 0 : if (c == NULL)
219 0 : exceptions_abort(NULL, message);
220 : else
221 0 : exceptions_abort(c->name, message);
222 : }
223 :
224 839 : s = JavaString::from_utf8(message);
225 :
226 839 : if (s == NULL)
227 0 : return exceptions_get_exception();
228 :
229 839 : o = native_new_and_init_string(c, s);
230 :
231 839 : if (o == NULL)
232 0 : return exceptions_get_exception();
233 :
234 839 : return o;
235 : }
236 :
237 :
238 : /* exceptions_new_Utf8String *********************************************************
239 :
240 : Creates an exception object with the given name and initalizes it.
241 :
242 : IN:
243 : classname....class name in UTF-8
244 :
245 : *******************************************************************************/
246 :
247 20040 : static java_handle_t *exceptions_new_utf(Utf8String classname)
248 : {
249 : classinfo *c;
250 : java_handle_t *o;
251 :
252 20040 : if (VM::get_current()->is_initializing())
253 0 : exceptions_abort(classname, NULL);
254 :
255 20040 : c = load_class_bootstrap(classname);
256 :
257 20040 : if (c == NULL)
258 0 : return exceptions_get_exception();
259 :
260 20040 : o = native_new_and_init(c);
261 :
262 20040 : if (o == NULL)
263 0 : return exceptions_get_exception();
264 :
265 20040 : return o;
266 : }
267 :
268 :
269 : /* exceptions_new_utf_javastring ***********************************************
270 :
271 : Creates an exception object with the given name and initalizes it
272 : with the given java/lang/String message.
273 :
274 : IN:
275 : classname....class name in UTF-8
276 : message......the message as a java.lang.String
277 :
278 : RETURN VALUE:
279 : an exception pointer (in any case -- either it is the newly created
280 : exception, or an exception thrown while trying to create it).
281 :
282 : *******************************************************************************/
283 :
284 25 : static java_handle_t *exceptions_new_utf_javastring(Utf8String classname,
285 : java_handle_t *message)
286 : {
287 : java_handle_t *o;
288 : classinfo *c;
289 :
290 25 : if (VM::get_current()->is_initializing())
291 0 : exceptions_abort(classname, NULL);
292 :
293 25 : c = load_class_bootstrap(classname);
294 :
295 25 : if (c == NULL)
296 0 : return exceptions_get_exception();
297 :
298 25 : o = native_new_and_init_string(c, message);
299 :
300 25 : if (o == NULL)
301 0 : return exceptions_get_exception();
302 :
303 25 : return o;
304 : }
305 :
306 :
307 : /* exceptions_new_utf_Utf8String *****************************************************
308 :
309 : Creates an exception object with the given name and initalizes it
310 : with the given utf message.
311 :
312 : IN:
313 : classname....class name in UTF-8
314 : message......the message as an Utf8String
315 :
316 : RETURN VALUE:
317 : an exception pointer (in any case -- either it is the newly created
318 : exception, or an exception thrown while trying to create it).
319 :
320 : *******************************************************************************/
321 :
322 839 : static java_handle_t *exceptions_new_utf_utf(Utf8String classname, Utf8String message)
323 : {
324 : classinfo *c;
325 : java_handle_t *o;
326 :
327 839 : if (VM::get_current()->is_initializing())
328 0 : exceptions_abort(classname, message);
329 :
330 839 : c = load_class_bootstrap(classname);
331 :
332 839 : if (c == NULL)
333 0 : return exceptions_get_exception();
334 :
335 839 : o = exceptions_new_class_utf(c, message);
336 :
337 839 : return o;
338 : }
339 :
340 :
341 : /* exceptions_throw_Utf8String *******************************************************
342 :
343 : Creates an exception object with the given name, initalizes and
344 : throws it.
345 :
346 : IN:
347 : classname....class name in UTF-8
348 :
349 : *******************************************************************************/
350 :
351 20011 : static void exceptions_throw_utf(Utf8String classname)
352 : {
353 : java_handle_t *o;
354 :
355 20011 : o = exceptions_new_utf(classname);
356 :
357 20011 : if (o == NULL)
358 0 : return;
359 :
360 20011 : exceptions_set_exception(o);
361 : }
362 :
363 :
364 : /* exceptions_throw_utf_throwable **********************************************
365 :
366 : Creates an exception object with the given name and initalizes it
367 : with the given java/lang/Throwable exception.
368 :
369 : IN:
370 : classname....class name in UTF-8
371 : cause........the given Throwable
372 :
373 : *******************************************************************************/
374 :
375 14 : static void exceptions_throw_utf_throwable(Utf8String classname,
376 : java_handle_t *cause)
377 : {
378 : classinfo *c;
379 : methodinfo *m;
380 :
381 14 : if (VM::get_current()->is_initializing())
382 0 : exceptions_abort(classname, NULL);
383 :
384 14 : java_lang_Throwable jlt(cause);
385 :
386 14 : c = load_class_bootstrap(classname);
387 :
388 14 : if (c == NULL)
389 : return;
390 :
391 : /* create object */
392 :
393 14 : java_handle_t* h = builtin_new(c);
394 :
395 14 : if (h == NULL)
396 : return;
397 :
398 : /* call initializer */
399 :
400 : m = class_resolveclassmethod(c,
401 : utf8::init,
402 : utf8::java_lang_Throwable__void,
403 : NULL,
404 14 : true);
405 :
406 14 : if (m == NULL)
407 : return;
408 :
409 14 : (void) vm_call_method(m, h, jlt.get_handle());
410 :
411 14 : exceptions_set_exception(h);
412 : }
413 :
414 :
415 : /* exceptions_throw_utf_exception **********************************************
416 :
417 : Creates an exception object with the given name and initalizes it
418 : with the given java/lang/Exception exception.
419 :
420 : IN:
421 : classname....class name in UTF-8
422 : exception....the given Exception
423 :
424 : *******************************************************************************/
425 :
426 0 : static void exceptions_throw_utf_exception(Utf8String classname,
427 : java_handle_t *exception)
428 : {
429 : classinfo *c;
430 : java_handle_t *o;
431 : methodinfo *m;
432 :
433 0 : if (VM::get_current()->is_initializing())
434 0 : exceptions_abort(classname, NULL);
435 :
436 0 : c = load_class_bootstrap(classname);
437 :
438 0 : if (c == NULL)
439 0 : return;
440 :
441 : /* create object */
442 :
443 0 : o = builtin_new(c);
444 :
445 0 : if (o == NULL)
446 0 : return;
447 :
448 : /* call initializer */
449 :
450 : m = class_resolveclassmethod(c,
451 : utf8::init,
452 : utf8::java_lang_Exception__V,
453 : NULL,
454 0 : true);
455 :
456 0 : if (m == NULL)
457 0 : return;
458 :
459 0 : (void) vm_call_method(m, o, exception);
460 :
461 0 : exceptions_set_exception(o);
462 : }
463 :
464 :
465 : /* exceptions_throw_utf_cause **************************************************
466 :
467 : Creates an exception object with the given name and initalizes it
468 : with the given java/lang/Throwable exception with initCause.
469 :
470 : IN:
471 : classname....class name in UTF-8
472 : cause........the given Throwable
473 :
474 : *******************************************************************************/
475 :
476 3 : static void exceptions_throw_utf_cause(Utf8String classname, java_handle_t *cause)
477 : {
478 3 : if (VM::get_current()->is_initializing())
479 0 : exceptions_abort(classname, NULL);
480 :
481 3 : java_lang_Throwable jltcause(cause);
482 :
483 3 : classinfo* c = load_class_bootstrap(classname);
484 :
485 3 : if (c == NULL)
486 : return;
487 :
488 : /* create object */
489 :
490 3 : java_handle_t* h = builtin_new(c);
491 :
492 3 : if (h == NULL)
493 : return;
494 :
495 : /* call initializer */
496 :
497 : methodinfo* m = class_resolveclassmethod(c,
498 : utf8::init,
499 : utf8::java_lang_String__void,
500 : NULL,
501 3 : true);
502 :
503 3 : if (m == NULL)
504 : return;
505 :
506 3 : (void) vm_call_method(m, h, jltcause.get_detailMessage());
507 :
508 : /* call initCause */
509 :
510 : m = class_resolveclassmethod(c,
511 : utf8::initCause,
512 : utf8::java_lang_Throwable__java_lang_Throwable,
513 : NULL,
514 3 : true);
515 :
516 3 : if (m == NULL)
517 : return;
518 :
519 3 : (void) vm_call_method(m, h, jltcause.get_handle());
520 :
521 3 : exceptions_set_exception(h);
522 : }
523 :
524 :
525 : /* exceptions_throw_utf_Utf8String ***************************************************
526 :
527 : Creates an exception object with the given name, initalizes and
528 : throws it with the given utf message.
529 :
530 : IN:
531 : classname....class name in UTF-8
532 : message......the message as an Utf8String
533 :
534 : *******************************************************************************/
535 :
536 821 : static void exceptions_throw_utf_utf(Utf8String classname, Utf8String message)
537 : {
538 : java_handle_t *o;
539 :
540 821 : o = exceptions_new_utf_utf(classname, message);
541 :
542 821 : exceptions_set_exception(o);
543 821 : }
544 :
545 :
546 : /* exceptions_new_abstractmethoderror ****************************************
547 :
548 : Generates a java.lang.AbstractMethodError for the VM.
549 :
550 : *******************************************************************************/
551 :
552 1 : java_handle_t *exceptions_new_abstractmethoderror(void)
553 : {
554 : java_handle_t *o;
555 :
556 1 : o = exceptions_new_utf(utf8::java_lang_AbstractMethodError);
557 :
558 1 : return o;
559 : }
560 :
561 :
562 : /* exceptions_new_error ********************************************************
563 :
564 : Generates a java.lang.Error for the VM.
565 :
566 : *******************************************************************************/
567 :
568 : #if defined(ENABLE_JAVAME_CLDC1_1)
569 : static java_handle_t *exceptions_new_error(Utf8String message)
570 : {
571 : java_handle_t *o;
572 :
573 : o = exceptions_new_utf_utf(utf8::java_lang_Error, message);
574 :
575 : return o;
576 : }
577 : #endif
578 :
579 :
580 : /* exceptions_asm_new_abstractmethoderror **************************************
581 :
582 : Generates a java.lang.AbstractMethodError for
583 : asm_abstractmethoderror.
584 :
585 : *******************************************************************************/
586 :
587 1 : java_object_t *exceptions_asm_new_abstractmethoderror(u1 *sp, u1 *ra)
588 : {
589 : stackframeinfo_t sfi;
590 : java_handle_t *e;
591 : java_object_t *o;
592 :
593 : /* Fill and add a stackframeinfo (XPC is equal to RA). */
594 :
595 1 : stacktrace_stackframeinfo_add(&sfi, NULL, sp, ra, ra);
596 :
597 : /* create the exception */
598 :
599 : #if defined(ENABLE_JAVASE)
600 1 : e = exceptions_new_abstractmethoderror();
601 : #else
602 : e = exceptions_new_error(utf8::java_lang_AbstractMethodError);
603 : #endif
604 :
605 : /* Remove the stackframeinfo. */
606 :
607 1 : stacktrace_stackframeinfo_remove(&sfi);
608 :
609 : /* unwrap the exception */
610 : /* ATTENTION: do the this _after_ the stackframeinfo was removed */
611 :
612 1 : o = LLNI_UNWRAP(e);
613 :
614 1 : return o;
615 : }
616 :
617 :
618 : /* exceptions_new_arraystoreexception ******************************************
619 :
620 : Generates a java.lang.ArrayStoreException for the VM.
621 :
622 : *******************************************************************************/
623 :
624 6 : java_handle_t *exceptions_new_arraystoreexception(void)
625 : {
626 : java_handle_t *o;
627 :
628 6 : o = exceptions_new_utf(utf8::java_lang_ArrayStoreException);
629 :
630 6 : return o;
631 : }
632 :
633 :
634 : /* exceptions_throw_abstractmethoderror ****************************************
635 :
636 : Generates and throws a java.lang.AbstractMethodError for the VM.
637 :
638 : *******************************************************************************/
639 :
640 0 : void exceptions_throw_abstractmethoderror(void)
641 : {
642 0 : exceptions_throw_utf(utf8::java_lang_AbstractMethodError);
643 0 : }
644 :
645 :
646 : /* exceptions_throw_classcircularityerror **************************************
647 :
648 : Generates and throws a java.lang.ClassCircularityError for the
649 : classloader.
650 :
651 : IN:
652 : c....the class in which the error was found
653 :
654 : *******************************************************************************/
655 :
656 0 : void exceptions_throw_classcircularityerror(classinfo *c)
657 : {
658 0 : exceptions_throw_utf_utf(utf8::java_lang_ClassCircularityError, c->name);
659 0 : }
660 :
661 :
662 : /* exceptions_throw_classformaterror *******************************************
663 :
664 : Generates and throws a java.lang.ClassFormatError for the VM.
665 :
666 : IN:
667 : c............the class in which the error was found
668 : message......UTF-8 format string
669 :
670 : *******************************************************************************/
671 :
672 0 : void exceptions_throw_classformaterror(classinfo *c, const char *message, ...)
673 : {
674 : va_list ap;
675 :
676 : /* allocate a buffer */
677 :
678 0 : Buffer<> buf;
679 :
680 : /* print message into allocated buffer */
681 :
682 0 : if (c != NULL)
683 0 : buf.write_slash_to_dot(c->name).write('(');
684 :
685 0 : va_start(ap, message);
686 0 : buf.writevf(message,ap);
687 0 : va_end(ap);
688 :
689 0 : if (c != NULL)
690 0 : buf.write(')');
691 :
692 0 : Utf8String u = buf.utf8_str();
693 0 : assert(u);
694 :
695 : /* throw exception */
696 :
697 0 : exceptions_throw_classformaterror(c, u);
698 0 : }
699 :
700 0 : void exceptions_throw_classformaterror(classinfo *c, Utf8String message)
701 : {
702 : /* throw exception */
703 :
704 0 : assert(message);
705 :
706 0 : exceptions_throw_utf_utf(utf8::java_lang_ClassFormatError, message);
707 0 : }
708 :
709 : /* exceptions_throw_classnotfoundexception *************************************
710 :
711 : Generates and throws a java.lang.ClassNotFoundException for the
712 : VM.
713 :
714 : IN:
715 : name.........name of the class not found as a Utf8String
716 :
717 : *******************************************************************************/
718 :
719 769 : void exceptions_throw_classnotfoundexception(Utf8String name)
720 : {
721 : // We can't use the cached class_java_lang_ClassNotFoundException because
722 : // when there are bootstrap classpath problems it has not been set yet,
723 : // which leads to confusing error messages.
724 :
725 769 : exceptions_throw_utf_utf(utf8::java_lang_ClassNotFoundException, name);
726 769 : }
727 :
728 :
729 : /* exceptions_throw_noclassdeffounderror ***************************************
730 :
731 : Generates and throws a java.lang.NoClassDefFoundError.
732 :
733 : IN:
734 : name.........name of the class not found as a Utf8String
735 :
736 : *******************************************************************************/
737 :
738 0 : void exceptions_throw_noclassdeffounderror(Utf8String name)
739 : {
740 0 : exceptions_throw_utf_utf(utf8::java_lang_NoClassDefFoundError, name);
741 0 : }
742 :
743 :
744 : /* exceptions_throw_noclassdeffounderror_cause *********************************
745 :
746 : Generates and throws a java.lang.NoClassDefFoundError with the
747 : given cause.
748 :
749 : *******************************************************************************/
750 :
751 3 : void exceptions_throw_noclassdeffounderror_cause(java_handle_t *cause)
752 : {
753 3 : exceptions_throw_utf_cause(utf8::java_lang_NoClassDefFoundError, cause);
754 3 : }
755 :
756 :
757 : /* exceptions_throw_noclassdeffounderror_wrong_name ****************************
758 :
759 : Generates and throws a java.lang.NoClassDefFoundError with a
760 : specific message:
761 :
762 : IN:
763 : name.........name of the class not found as a Utf8String
764 :
765 : *******************************************************************************/
766 :
767 0 : void exceptions_throw_noclassdeffounderror_wrong_name(classinfo *c, Utf8String name)
768 : {
769 0 : Buffer<> buf;
770 :
771 : buf.write_slash_to_dot(c->name)
772 : .write(" (wrong name: ", 14)
773 : .write_slash_to_dot(name)
774 0 : .write(')');
775 :
776 0 : exceptions_throw_noclassdeffounderror(buf.utf8_str());
777 0 : }
778 :
779 :
780 : /* exceptions_throw_exceptionininitializererror ********************************
781 :
782 : Generates and throws a java.lang.ExceptionInInitializerError for
783 : the VM.
784 :
785 : IN:
786 : cause......cause exception object
787 :
788 : *******************************************************************************/
789 :
790 3 : void exceptions_throw_exceptionininitializererror(java_handle_t *cause)
791 : {
792 : exceptions_throw_utf_throwable(utf8::java_lang_ExceptionInInitializerError,
793 3 : cause);
794 3 : }
795 :
796 :
797 : /* exceptions_throw_incompatibleclasschangeerror *******************************
798 :
799 : Generates and throws a java.lang.IncompatibleClassChangeError for
800 : the VM.
801 :
802 : IN:
803 : message......UTF-8 message format string
804 :
805 : *******************************************************************************/
806 :
807 0 : void exceptions_throw_incompatibleclasschangeerror(classinfo *c, const char *message)
808 : {
809 : /* allocate memory */
810 :
811 0 : Buffer<> buf;
812 :
813 : buf.write_slash_to_dot(c->name)
814 0 : .write(message);
815 :
816 : /* throw exception */
817 :
818 0 : exceptions_throw_utf_utf(utf8::java_lang_IncompatibleClassChangeError, buf.utf8_str());
819 0 : }
820 :
821 :
822 : /* exceptions_throw_instantiationerror *****************************************
823 :
824 : Generates and throws a java.lang.InstantiationError for the VM.
825 :
826 : *******************************************************************************/
827 :
828 0 : void exceptions_throw_instantiationerror(classinfo *c)
829 : {
830 0 : exceptions_throw_utf_utf(utf8::java_lang_InstantiationError, c->name);
831 0 : }
832 :
833 :
834 : /* exceptions_throw_internalerror **********************************************
835 :
836 : Generates and throws a java.lang.InternalError for the VM.
837 :
838 : IN:
839 : message......UTF-8 message format string
840 :
841 : *******************************************************************************/
842 :
843 0 : void exceptions_throw_internalerror(const char *message, ...)
844 : {
845 : va_list ap;
846 0 : Buffer<> buf;
847 :
848 : /* generate message */
849 :
850 0 : va_start(ap, message);
851 0 : buf.writevf(message,ap);
852 0 : va_end(ap);
853 :
854 : /* throw exception */
855 :
856 0 : exceptions_throw_utf_utf(utf8::java_lang_InternalError, buf.utf8_str());
857 0 : }
858 :
859 :
860 : /* exceptions_throw_linkageerror ***********************************************
861 :
862 : Generates and throws java.lang.LinkageError with an error message.
863 :
864 : IN:
865 : message......UTF-8 message, can be freed after the call
866 : c............class related to the error. If this is != NULL
867 : the name of c is appended to the error message.
868 :
869 : *******************************************************************************/
870 :
871 8 : void exceptions_throw_linkageerror(const char *message, classinfo *c)
872 : {
873 : /* generate message */
874 :
875 8 : Buffer<> buf;
876 :
877 8 : if (c) {
878 : buf.write_slash_to_dot(c->name)
879 3 : .write(": ");
880 : }
881 :
882 8 : buf.write(message);
883 :
884 8 : Utf8String msg = buf.utf8_str();
885 :
886 8 : exceptions_throw_utf_utf(utf8::java_lang_LinkageError, msg);
887 8 : }
888 :
889 :
890 : /* exceptions_throw_nosuchfielderror *******************************************
891 :
892 : Generates and throws a java.lang.NoSuchFieldError with an error
893 : message.
894 :
895 : IN:
896 : c............class in which the field was not found
897 : name.........name of the field
898 :
899 : *******************************************************************************/
900 :
901 4 : void exceptions_throw_nosuchfielderror(classinfo *c, Utf8String name)
902 : {
903 : /* generate message */
904 :
905 4 : Buffer<> buf;
906 :
907 : buf.write_slash_to_dot(c->name)
908 : .write('.')
909 4 : .write(name);
910 :
911 4 : exceptions_throw_utf_utf(utf8::java_lang_NoSuchFieldError, buf.utf8_str());
912 4 : }
913 :
914 :
915 : /* exceptions_throw_nosuchmethoderror ******************************************
916 :
917 : Generates and throws a java.lang.NoSuchMethodError with an error
918 : message.
919 :
920 : IN:
921 : c............class in which the method was not found
922 : name.........name of the method
923 : desc.........descriptor of the method
924 :
925 : *******************************************************************************/
926 :
927 0 : void exceptions_throw_nosuchmethoderror(classinfo *c, Utf8String name, Utf8String desc)
928 : {
929 : /* generate message */
930 :
931 0 : Buffer<> buf;
932 :
933 : buf.write_slash_to_dot(c->name)
934 : .write('.')
935 : .write(name)
936 0 : .write(desc);
937 :
938 : #if defined(ENABLE_JAVASE)
939 0 : exceptions_throw_utf_utf(utf8::java_lang_NoSuchMethodError, buf.utf8_str());
940 : #else
941 : exceptions_throw_utf_utf(utf8::java_lang_Error, buf.utf8_str());
942 : #endif
943 0 : }
944 :
945 :
946 : /* exceptions_throw_outofmemoryerror *******************************************
947 :
948 : Generates and throws an java.lang.OutOfMemoryError for the VM.
949 :
950 : *******************************************************************************/
951 :
952 3 : void exceptions_throw_outofmemoryerror(void)
953 : {
954 : exceptions_throw_utf_utf(utf8::java_lang_OutOfMemoryError,
955 3 : Utf8String::from_utf8("Java heap space"));
956 3 : }
957 :
958 :
959 : /* exceptions_throw_unsatisfiedlinkerror ***************************************
960 :
961 : Generates and throws a java.lang.UnsatisfiedLinkError for the
962 : classloader.
963 :
964 : IN:
965 : name......UTF-8 name string
966 :
967 : *******************************************************************************/
968 :
969 1 : void exceptions_throw_unsatisfiedlinkerror(Utf8String name)
970 : {
971 : #if defined(ENABLE_JAVASE)
972 1 : exceptions_throw_utf_utf(utf8::java_lang_UnsatisfiedLinkError, name);
973 : #else
974 : exceptions_throw_utf_utf(utf8::java_lang_Error, name);
975 : #endif
976 1 : }
977 :
978 :
979 : /* exceptions_throw_unsupportedclassversionerror *******************************
980 :
981 : Generates and throws a java.lang.UnsupportedClassVersionError for
982 : the classloader.
983 :
984 : *******************************************************************************/
985 :
986 0 : void exceptions_throw_unsupportedclassversionerror(classinfo *c)
987 : {
988 : /* generate message */
989 :
990 0 : Buffer<> buf;
991 :
992 : buf.write_slash_to_dot(c->name)
993 0 : .writef(" (Unsupported major.minor version %d.%d)", c->version.majr(), c->version.minr());
994 :
995 : /* throw exception */
996 :
997 0 : exceptions_throw_utf_utf(utf8::java_lang_UnsupportedClassVersionError, buf.utf8_str());
998 0 : }
999 :
1000 :
1001 : /* exceptions_throw_verifyerror ************************************************
1002 :
1003 : Generates and throws a java.lang.VerifyError for the JIT compiler.
1004 :
1005 : IN:
1006 : m............method in which the error was found
1007 : message......UTF-8 format string
1008 :
1009 : *******************************************************************************/
1010 :
1011 28 : void exceptions_throw_verifyerror(methodinfo *m, const char *message, ...)
1012 : {
1013 : va_list ap;
1014 28 : Buffer<> buf;
1015 :
1016 : /* generate message */
1017 :
1018 28 : if (m != NULL) {
1019 : buf.write("(class: ")
1020 : .write_slash_to_dot(m->clazz->name)
1021 : .write(", method: ")
1022 : .write(m->name)
1023 : .write(" signature: ")
1024 : .write(m->descriptor)
1025 28 : .write(") ");
1026 : }
1027 :
1028 28 : va_start(ap, message);
1029 28 : buf.writevf(message, ap);
1030 28 : va_end(ap);
1031 :
1032 : /* throw exception */
1033 :
1034 28 : exceptions_throw_utf_utf(utf8::java_lang_VerifyError, buf.utf8_str());
1035 28 : }
1036 :
1037 :
1038 : /* exceptions_throw_verifyerror_for_stack **************************************
1039 :
1040 : throws a java.lang.VerifyError for an invalid stack slot type
1041 :
1042 : IN:
1043 : m............method in which the error was found
1044 : type.........the expected type
1045 :
1046 : RETURN VALUE:
1047 : an exception pointer (in any case -- either it is the newly created
1048 : exception, or an exception thrown while trying to create it).
1049 :
1050 : *******************************************************************************/
1051 :
1052 8 : void exceptions_throw_verifyerror_for_stack(methodinfo *m, int type)
1053 : {
1054 : /* generate message */
1055 :
1056 8 : Buffer<> buf;
1057 :
1058 8 : if (m != NULL) {
1059 : buf.write("(class: ")
1060 : .write_slash_to_dot(m->clazz->name)
1061 : .write(", method: ")
1062 : .write(m->name)
1063 : .write(" signature: ")
1064 : .write(m->descriptor)
1065 8 : .write(") ");
1066 : }
1067 :
1068 8 : buf.write("Expecting to find ");
1069 :
1070 8 : switch (type) {
1071 1 : case TYPE_INT: buf.write("integer"); break;
1072 0 : case TYPE_LNG: buf.write("long"); break;
1073 0 : case TYPE_FLT: buf.write("float"); break;
1074 0 : case TYPE_DBL: buf.write("double"); break;
1075 7 : case TYPE_ADR: buf.write("object/array"); break;
1076 0 : case TYPE_RET: buf.write("returnAddress"); break;
1077 0 : default: buf.write("<INVALID>"); assert(0); break;
1078 : }
1079 :
1080 8 : buf.write(" on stack");
1081 :
1082 : /* throw exception */
1083 :
1084 8 : exceptions_throw_utf_utf(utf8::java_lang_VerifyError, buf.utf8_str());
1085 8 : }
1086 :
1087 :
1088 : /* exceptions_new_arithmeticexception ******************************************
1089 :
1090 : Generates a java.lang.ArithmeticException for the JIT compiler.
1091 :
1092 : *******************************************************************************/
1093 :
1094 8 : java_handle_t *exceptions_new_arithmeticexception(void)
1095 : {
1096 : java_handle_t *o;
1097 :
1098 : o = exceptions_new_utf_utf(utf8::java_lang_ArithmeticException,
1099 8 : utf8::division_by_zero);
1100 :
1101 8 : return o;
1102 : }
1103 :
1104 :
1105 : /* exceptions_new_arrayindexoutofboundsexception *******************************
1106 :
1107 : Generates a java.lang.ArrayIndexOutOfBoundsException for the VM
1108 : system.
1109 :
1110 : *******************************************************************************/
1111 :
1112 25 : java_handle_t *exceptions_new_arrayindexoutofboundsexception(s4 index)
1113 : {
1114 : java_handle_t *o;
1115 : methodinfo *m;
1116 : java_handle_t *s;
1117 :
1118 : /* convert the index into a String, like Sun does */
1119 :
1120 : m = class_resolveclassmethod(class_java_lang_String,
1121 : Utf8String::from_utf8("valueOf"),
1122 : Utf8String::from_utf8("(I)Ljava/lang/String;"),
1123 : class_java_lang_Object,
1124 25 : true);
1125 :
1126 25 : if (m == NULL)
1127 0 : return exceptions_get_exception();
1128 :
1129 25 : s = vm_call_method(m, NULL, index);
1130 :
1131 25 : if (s == NULL)
1132 0 : return exceptions_get_exception();
1133 :
1134 : o = exceptions_new_utf_javastring(utf8::java_lang_ArrayIndexOutOfBoundsException,
1135 25 : s);
1136 :
1137 25 : if (o == NULL)
1138 0 : return exceptions_get_exception();
1139 :
1140 25 : return o;
1141 : }
1142 :
1143 :
1144 : /* exceptions_throw_arrayindexoutofboundsexception *****************************
1145 :
1146 : Generates and throws a java.lang.ArrayIndexOutOfBoundsException for
1147 : the VM.
1148 :
1149 : *******************************************************************************/
1150 :
1151 1 : void exceptions_throw_arrayindexoutofboundsexception(void)
1152 : {
1153 1 : exceptions_throw_utf(utf8::java_lang_ArrayIndexOutOfBoundsException);
1154 1 : }
1155 :
1156 :
1157 : /* exceptions_throw_arraystoreexception ****************************************
1158 :
1159 : Generates and throws a java.lang.ArrayStoreException for the VM.
1160 :
1161 : *******************************************************************************/
1162 :
1163 1 : void exceptions_throw_arraystoreexception(void)
1164 : {
1165 1 : exceptions_throw_utf(utf8::java_lang_ArrayStoreException);
1166 1 : }
1167 :
1168 :
1169 : /* exceptions_new_classcastexception *******************************************
1170 :
1171 : Generates a java.lang.ClassCastException for the JIT compiler.
1172 :
1173 : *******************************************************************************/
1174 :
1175 10 : java_handle_t *exceptions_new_classcastexception(java_handle_t *o)
1176 : {
1177 : classinfo *c;
1178 :
1179 10 : LLNI_class_get(o, c);
1180 :
1181 10 : Utf8String classname = get_classname_for_exception(c);
1182 :
1183 10 : return exceptions_new_utf_utf(utf8::java_lang_ClassCastException, classname);
1184 : }
1185 :
1186 :
1187 : /* exceptions_throw_clonenotsupportedexception *********************************
1188 :
1189 : Generates and throws a java.lang.CloneNotSupportedException for the
1190 : VM.
1191 :
1192 : *******************************************************************************/
1193 :
1194 0 : void exceptions_throw_clonenotsupportedexception(void)
1195 : {
1196 0 : exceptions_throw_utf(utf8::java_lang_CloneNotSupportedException);
1197 0 : }
1198 :
1199 :
1200 : /* exceptions_throw_illegalaccessexception *************************************
1201 :
1202 : Generates and throws a java.lang.IllegalAccessException for the VM.
1203 :
1204 : *******************************************************************************/
1205 :
1206 0 : void exceptions_throw_illegalaccessexception(Utf8String message)
1207 : {
1208 0 : exceptions_throw_utf_utf(utf8::java_lang_IllegalAccessException, message);
1209 0 : }
1210 :
1211 :
1212 : /* exceptions_throw_illegalargumentexception ***********************************
1213 :
1214 : Generates and throws a java.lang.IllegalArgumentException for the
1215 : VM.
1216 :
1217 : *******************************************************************************/
1218 :
1219 1 : void exceptions_throw_illegalargumentexception(void)
1220 : {
1221 1 : exceptions_throw_utf(utf8::java_lang_IllegalArgumentException);
1222 1 : }
1223 :
1224 :
1225 : /* exceptions_throw_illegalmonitorstateexception *******************************
1226 :
1227 : Generates and throws a java.lang.IllegalMonitorStateException for
1228 : the VM.
1229 :
1230 : *******************************************************************************/
1231 :
1232 0 : void exceptions_throw_illegalmonitorstateexception(void)
1233 : {
1234 0 : exceptions_throw_utf(utf8::java_lang_IllegalMonitorStateException);
1235 0 : }
1236 :
1237 :
1238 : /* exceptions_throw_instantiationexception *************************************
1239 :
1240 : Generates and throws a java.lang.InstantiationException for the VM.
1241 :
1242 : *******************************************************************************/
1243 :
1244 0 : void exceptions_throw_instantiationexception(classinfo *c)
1245 : {
1246 0 : exceptions_throw_utf_utf(utf8::java_lang_InstantiationException, c->name);
1247 0 : }
1248 :
1249 :
1250 : /* exceptions_throw_interruptedexception ***************************************
1251 :
1252 : Generates and throws a java.lang.InterruptedException for the VM.
1253 :
1254 : *******************************************************************************/
1255 :
1256 20000 : void exceptions_throw_interruptedexception(void)
1257 : {
1258 20000 : exceptions_throw_utf(utf8::java_lang_InterruptedException);
1259 20000 : }
1260 :
1261 :
1262 : /* exceptions_throw_invocationtargetexception **********************************
1263 :
1264 : Generates and throws a java.lang.reflect.InvocationTargetException
1265 : for the VM.
1266 :
1267 : IN:
1268 : cause......cause exception object
1269 :
1270 : *******************************************************************************/
1271 :
1272 11 : void exceptions_throw_invocationtargetexception(java_handle_t *cause)
1273 : {
1274 : exceptions_throw_utf_throwable(utf8::java_lang_reflect_InvocationTargetException,
1275 11 : cause);
1276 11 : }
1277 :
1278 :
1279 : /* exceptions_throw_negativearraysizeexception *********************************
1280 :
1281 : Generates and throws a java.lang.NegativeArraySizeException for the
1282 : VM.
1283 :
1284 : *******************************************************************************/
1285 :
1286 5 : void exceptions_throw_negativearraysizeexception(void)
1287 : {
1288 5 : exceptions_throw_utf(utf8::java_lang_NegativeArraySizeException);
1289 5 : }
1290 :
1291 :
1292 : /* exceptions_new_nullpointerexception *****************************************
1293 :
1294 : Generates a java.lang.NullPointerException for the VM system.
1295 :
1296 : *******************************************************************************/
1297 :
1298 22 : java_handle_t *exceptions_new_nullpointerexception(void)
1299 : {
1300 : java_handle_t *o;
1301 :
1302 22 : o = exceptions_new_utf(utf8::java_lang_NullPointerException);
1303 :
1304 22 : return o;
1305 : }
1306 :
1307 :
1308 : /* exceptions_throw_nullpointerexception ***************************************
1309 :
1310 : Generates a java.lang.NullPointerException for the VM system and
1311 : throw it in the VM system.
1312 :
1313 : *******************************************************************************/
1314 :
1315 3 : void exceptions_throw_nullpointerexception(void)
1316 : {
1317 3 : exceptions_throw_utf(utf8::java_lang_NullPointerException);
1318 3 : }
1319 :
1320 :
1321 : /* exceptions_throw_privilegedactionexception **********************************
1322 :
1323 : Generates and throws a java.security.PrivilegedActionException.
1324 :
1325 : *******************************************************************************/
1326 :
1327 0 : void exceptions_throw_privilegedactionexception(java_handle_t *exception)
1328 : {
1329 : exceptions_throw_utf_exception(utf8::java_security_PrivilegedActionException,
1330 0 : exception);
1331 0 : }
1332 :
1333 :
1334 : /* exceptions_throw_stringindexoutofboundsexception ****************************
1335 :
1336 : Generates and throws a java.lang.StringIndexOutOfBoundsException
1337 : for the VM.
1338 :
1339 : *******************************************************************************/
1340 :
1341 0 : void exceptions_throw_stringindexoutofboundsexception(void)
1342 : {
1343 0 : exceptions_throw_utf(utf8::java_lang_StringIndexOutOfBoundsException);
1344 0 : }
1345 :
1346 :
1347 : /* exceptions_fillinstacktrace *************************************************
1348 :
1349 : Calls the fillInStackTrace-method of the currently thrown
1350 : exception.
1351 :
1352 : *******************************************************************************/
1353 :
1354 3 : java_handle_t *exceptions_fillinstacktrace(void)
1355 : {
1356 : java_handle_t *o;
1357 : classinfo *c;
1358 : methodinfo *m;
1359 :
1360 : /* get exception */
1361 :
1362 3 : o = exceptions_get_and_clear_exception();
1363 :
1364 3 : assert(o);
1365 :
1366 : /* resolve methodinfo pointer from exception object */
1367 :
1368 3 : LLNI_class_get(o, c);
1369 :
1370 : #if defined(ENABLE_JAVASE)
1371 : m = class_resolvemethod(c,
1372 : utf8::fillInStackTrace,
1373 3 : utf8::void__java_lang_Throwable);
1374 : #elif defined(ENABLE_JAVAME_CLDC1_1)
1375 : m = class_resolvemethod(c,
1376 : utf8::fillInStackTrace,
1377 : utf8::void__void);
1378 : #else
1379 : #error IMPLEMENT ME!
1380 : #endif
1381 :
1382 : /* call function */
1383 :
1384 3 : (void) vm_call_method(m, o);
1385 :
1386 : /* return exception object */
1387 :
1388 3 : return o;
1389 : }
1390 :
1391 :
1392 : /* exceptions_handle_exception *************************************************
1393 :
1394 : Try to find an exception handler for the given exception and return it.
1395 : If no handler is found, exit the monitor of the method (if any)
1396 : and return NULL.
1397 :
1398 : IN:
1399 : xptr.........the exception object
1400 : xpc..........PC of where the exception was thrown
1401 : pv...........Procedure Value of the current method
1402 : sp...........current stack pointer
1403 :
1404 : RETURN VALUE:
1405 : the address of the first matching exception handler, or
1406 : NULL if no handler was found
1407 :
1408 : *******************************************************************************/
1409 :
1410 : #if defined(ENABLE_JIT)
1411 41546 : extern "C" void *exceptions_handle_exception(java_object_t *xptro, void *xpc, void *pv, void *sp)
1412 : {
1413 : stackframeinfo_t sfi;
1414 : java_handle_t *xptr;
1415 : methodinfo *m;
1416 : codeinfo *code;
1417 : exceptiontable_t *et;
1418 : exceptiontable_entry_t *ete;
1419 : s4 i;
1420 : classref_or_classinfo cr;
1421 : classinfo *c;
1422 : void *result;
1423 :
1424 : #ifdef __S390__
1425 : /* Addresses are 31 bit integers */
1426 : # define ADDR_MASK(x) (void *) ((uintptr_t) (x) & 0x7FFFFFFF)
1427 : #else
1428 : # define ADDR_MASK(x) (x)
1429 : #endif
1430 :
1431 41546 : xptr = LLNI_WRAP(xptro);
1432 41546 : xpc = ADDR_MASK(xpc);
1433 :
1434 : /* Fill and add a stackframeinfo (XPC is equal to RA). */
1435 :
1436 41546 : stacktrace_stackframeinfo_add(&sfi, pv, sp, xpc, xpc);
1437 :
1438 41546 : result = NULL;
1439 :
1440 : /* Get the codeinfo for the current method. */
1441 :
1442 41546 : code = code_get_codeinfo_for_pv(pv);
1443 :
1444 : /* Get the methodinfo pointer from the codeinfo pointer. For
1445 : asm_vm_call_method the codeinfo pointer is NULL and we simply
1446 : can return the proper exception handler. */
1447 :
1448 41546 : if (code == NULL) {
1449 60 : result = (void *) (uintptr_t) &asm_vm_call_method_exception_handler;
1450 60 : goto exceptions_handle_exception_return;
1451 : }
1452 :
1453 41486 : m = code->m;
1454 :
1455 : #if !defined(NDEBUG)
1456 : /* print exception trace */
1457 :
1458 41486 : if (opt_TraceExceptions)
1459 0 : trace_exception(LLNI_DIRECT(xptr), m, xpc);
1460 : #endif
1461 :
1462 : /* Get the exception table. */
1463 :
1464 41486 : et = code->exceptiontable;
1465 :
1466 41486 : if (et != NULL) {
1467 : /* Iterate over all exception table entries. */
1468 :
1469 21074 : ete = et->entries;
1470 :
1471 22501 : for (i = 0; i < et->length; i++, ete++) {
1472 : /* is the xpc is the current catch range */
1473 :
1474 22392 : if ((ADDR_MASK(ete->startpc) <= xpc) && (xpc < ADDR_MASK(ete->endpc))) {
1475 20987 : cr = ete->catchtype;
1476 :
1477 : /* NULL catches everything */
1478 :
1479 20987 : if (cr.any == NULL) {
1480 : #if !defined(NDEBUG)
1481 : /* Print stacktrace of exception when caught. */
1482 :
1483 0 : if (opt_TraceExceptions) {
1484 0 : exceptions_print_exception(xptr);
1485 0 : stacktrace_print_exception(xptr);
1486 : }
1487 : #endif
1488 :
1489 0 : result = ete->handlerpc;
1490 0 : goto exceptions_handle_exception_return;
1491 : }
1492 :
1493 : /* resolve or load/link the exception class */
1494 :
1495 20987 : if (cr.is_classref()) {
1496 : /* The exception class reference is unresolved. */
1497 : /* We have to do _eager_ resolving here. While the
1498 : class of the exception object is guaranteed to be
1499 : loaded, it may well have been loaded by a different
1500 : loader than the defining loader of m's class, which
1501 : is the one we must use to resolve the catch
1502 : class. Thus lazy resolving might fail, even if the
1503 : result of the resolution would be an already loaded
1504 : class. */
1505 :
1506 121 : c = resolve_classref_eager(cr.ref);
1507 :
1508 121 : if (c == NULL) {
1509 : /* Exception resolving the exception class, argh! */
1510 0 : goto exceptions_handle_exception_return;
1511 : }
1512 :
1513 : /* Ok, we resolved it. Enter it in the table, so we
1514 : don't have to do this again. */
1515 : /* XXX this write should be atomic. Is it? */
1516 :
1517 121 : ete->catchtype.cls = c;
1518 : }
1519 : else {
1520 20866 : c = cr.cls;
1521 :
1522 : /* XXX I don't think this case can ever happen. -Edwin */
1523 20866 : if (!(c->state & CLASS_LOADED))
1524 : /* use the methods' classloader */
1525 0 : if (!load_class_from_classloader(c->name,
1526 : m->clazz->classloader))
1527 0 : goto exceptions_handle_exception_return;
1528 :
1529 : /* XXX I think, if it is not linked, we can be sure
1530 : that the exception object is no (indirect) instance
1531 : of it, no? -Edwin */
1532 20866 : if (!(c->state & CLASS_LINKED))
1533 0 : if (!link_class(c))
1534 0 : goto exceptions_handle_exception_return;
1535 : }
1536 :
1537 : /* is the thrown exception an instance of the catch class? */
1538 :
1539 20987 : if (builtin_instanceof(xptr, c)) {
1540 : #if !defined(NDEBUG)
1541 : /* Print stacktrace of exception when caught. */
1542 :
1543 20965 : if (opt_TraceExceptions) {
1544 0 : exceptions_print_exception(xptr);
1545 0 : stacktrace_print_exception(xptr);
1546 : }
1547 : #endif
1548 :
1549 20965 : result = ete->handlerpc;
1550 20965 : goto exceptions_handle_exception_return;
1551 : }
1552 : }
1553 : }
1554 : }
1555 :
1556 : /* Is this method realization synchronized? */
1557 :
1558 20521 : if (code_is_synchronized(code)) {
1559 : /* Get synchronization object. */
1560 :
1561 87 : java_object_t *o = *((java_object_t **) (((uintptr_t) sp) + code->synchronizedoffset));
1562 :
1563 87 : assert(o != NULL);
1564 :
1565 87 : lock_monitor_exit(LLNI_QUICKWRAP(o));
1566 : }
1567 :
1568 : /* none of the exceptions catch this one */
1569 :
1570 : #if !defined(NDEBUG)
1571 :
1572 : # if defined(ENABLE_DEBUG_FILTER)
1573 20521 : if (show_filters_test_verbosecall_exit(m)) {
1574 : # endif
1575 :
1576 : /* outdent the log message */
1577 :
1578 0 : if (opt_verbosecall) {
1579 0 : if (TRACEJAVACALLINDENT)
1580 0 : TRACEJAVACALLINDENT--;
1581 : else
1582 0 : log_text("exceptions_handle_exception: WARNING: unmatched unindent");
1583 : }
1584 :
1585 : # if defined(ENABLE_DEBUG_FILTER)
1586 : }
1587 : # endif
1588 : #endif /* !defined(NDEBUG) */
1589 :
1590 20521 : result = NULL;
1591 :
1592 : exceptions_handle_exception_return:
1593 :
1594 : /* Remove the stackframeinfo. */
1595 :
1596 41546 : stacktrace_stackframeinfo_remove(&sfi);
1597 :
1598 41546 : return result;
1599 : }
1600 : #endif /* defined(ENABLE_JIT) */
1601 :
1602 :
1603 : /* exceptions_print_exception **************************************************
1604 :
1605 : Prints an exception, the detail message and the cause, if
1606 : available, with CACAO internal functions to stdout.
1607 :
1608 : *******************************************************************************/
1609 :
1610 0 : void exceptions_print_exception(java_handle_t *xptr)
1611 : {
1612 0 : java_lang_Throwable jlt(xptr);
1613 :
1614 0 : if (jlt.is_null()) {
1615 0 : puts("NULL\n");
1616 : return;
1617 : }
1618 :
1619 : #if defined(ENABLE_JAVASE)
1620 0 : java_lang_Throwable jltcause(jlt.get_cause());
1621 : #endif
1622 :
1623 : /* print the root exception */
1624 :
1625 0 : classinfo* c = jlt.get_Class();
1626 0 : utf_display_printable_ascii_classname(c->name);
1627 :
1628 0 : java_lang_String jls(jlt.get_detailMessage());
1629 :
1630 0 : if (!jls.is_null()) {
1631 0 : JavaString str = jls.get_handle();
1632 :
1633 0 : printf(": ");
1634 0 : str.fprint_printable_ascii(stdout);
1635 : }
1636 :
1637 0 : putc('\n', stdout);
1638 :
1639 : #if defined(ENABLE_JAVASE)
1640 : /* print the cause if available */
1641 :
1642 : // FIXME cause != t compare with operator override.
1643 0 : if ((!jltcause.is_null()) && (jltcause.get_handle() != jlt.get_handle())) {
1644 0 : printf("Caused by: ");
1645 :
1646 0 : c = jltcause.get_Class();
1647 0 : utf_display_printable_ascii_classname(c->name);
1648 :
1649 0 : java_lang_String jlscause(jlt.get_detailMessage());
1650 :
1651 0 : if (jlscause.get_handle() != NULL) {
1652 0 : JavaString str = jls.get_handle();
1653 :
1654 0 : printf(": ");
1655 0 : str.fprint_printable_ascii(stdout);
1656 : }
1657 :
1658 0 : putc('\n', stdout);
1659 0 : }
1660 : #endif
1661 : }
1662 :
1663 :
1664 : /* exceptions_print_current_exception ******************************************
1665 :
1666 : Prints the current pending exception, the detail message and the
1667 : cause, if available, with CACAO internal functions to stdout.
1668 :
1669 : *******************************************************************************/
1670 :
1671 0 : void exceptions_print_current_exception(void)
1672 : {
1673 : java_handle_t *o;
1674 :
1675 0 : o = exceptions_get_exception();
1676 :
1677 0 : exceptions_print_exception(o);
1678 0 : }
1679 :
1680 :
1681 : /* exceptions_print_stacktrace *************************************************
1682 :
1683 : Prints a pending exception with Throwable.printStackTrace(). If
1684 : there happens an exception during printStackTrace(), we print the
1685 : thrown exception and the original one.
1686 :
1687 : NOTE: This function calls Java code.
1688 :
1689 : *******************************************************************************/
1690 :
1691 41 : void exceptions_print_stacktrace(void)
1692 : {
1693 : java_handle_t *e;
1694 : java_handle_t *ne;
1695 : classinfo *c;
1696 : methodinfo *m;
1697 :
1698 : /* Get and clear exception because we are calling Java code
1699 : again. */
1700 :
1701 41 : e = exceptions_get_and_clear_exception();
1702 :
1703 41 : if (e == NULL)
1704 0 : return;
1705 :
1706 : #if 0
1707 : /* FIXME Enable me. */
1708 : if (builtin_instanceof(e, class_java_lang_ThreadDeath)) {
1709 : /* Don't print anything if we are being killed. */
1710 : }
1711 : else
1712 : #endif
1713 : {
1714 : /* Get the exception class. */
1715 :
1716 41 : LLNI_class_get(e, c);
1717 :
1718 : /* Find the printStackTrace() method. */
1719 :
1720 : m = class_resolveclassmethod(c,
1721 : utf8::printStackTrace,
1722 : utf8::void__void,
1723 : class_java_lang_Object,
1724 41 : false);
1725 :
1726 41 : if (m == NULL)
1727 0 : os::abort("exceptions_print_stacktrace: printStackTrace()V not found");
1728 :
1729 : /* Print message. */
1730 :
1731 41 : fprintf(stderr, "Exception ");
1732 :
1733 : /* Print thread name. We get the thread here explicitly as we
1734 : need it afterwards. */
1735 :
1736 41 : threadobject *t = thread_get_current();
1737 41 : java_lang_Thread *to = (java_lang_Thread *) LLNI_WRAP(t->object);
1738 :
1739 41 : if (to != NULL) {
1740 41 : fprintf(stderr, "in thread \"");
1741 41 : thread_fprint_name(t, stderr);
1742 41 : fprintf(stderr, "\" ");
1743 : }
1744 :
1745 : /* Print the stacktrace. */
1746 :
1747 41 : if (builtin_instanceof(e, class_java_lang_Throwable)) {
1748 41 : (void) vm_call_method(m, e);
1749 :
1750 : /* If this happens we are EXTREMLY out of memory or have a
1751 : serious problem while printStackTrace. But may be
1752 : another exception, so print it. */
1753 :
1754 41 : ne = exceptions_get_exception();
1755 :
1756 41 : if (ne != NULL) {
1757 0 : fprintf(stderr, "Exception while printStackTrace(): ");
1758 :
1759 : /* Print the current exception. */
1760 :
1761 0 : exceptions_print_exception(ne);
1762 0 : stacktrace_print_exception(ne);
1763 :
1764 : /* Now print the original exception. */
1765 :
1766 0 : fprintf(stderr, "Original exception was: ");
1767 0 : exceptions_print_exception(e);
1768 0 : stacktrace_print_exception(e);
1769 : }
1770 : }
1771 : else {
1772 0 : fprintf(stderr, ". Uncaught exception of type ");
1773 : #if !defined(NDEBUG)
1774 : /* FIXME This prints to stdout. */
1775 0 : class_print(c);
1776 : #else
1777 : fprintf(stderr, "UNKNOWN");
1778 : #endif
1779 0 : fprintf(stderr, ".");
1780 : }
1781 :
1782 41 : fflush(stderr);
1783 : }
1784 : }
1785 :
1786 10 : static inline Utf8String get_classname_for_exception(classinfo *c) {
1787 : #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
1788 : return Utf8String::from_utf8_slash_to_dot(c->name.begin(), c->name.size());
1789 : #else
1790 10 : return c->name;
1791 : #endif
1792 : }
1793 :
1794 : /*
1795 : * These are local overrides for various environment variables in Emacs.
1796 : * Please do not remove this and leave it at the end of the file, where
1797 : * Emacs will automagically detect them.
1798 : * ---------------------------------------------------------------------
1799 : * Local variables:
1800 : * mode: c++
1801 : * indent-tabs-mode: t
1802 : * c-basic-offset: 4
1803 : * tab-width: 4
1804 : * End:
1805 : * vim:noexpandtab:sw=4:ts=4:
1806 : */
|