* src/native/jni.h: Removed.
[cacao.git] / src / vm / jit / stacktrace.cpp
1 /* src/vm/jit/stacktrace.cpp - machine independent stacktrace system
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
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
26 #include "config.h"
27
28 #include <assert.h>
29 #include <stdint.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include "vm/types.h"
34
35 #include "md.h"
36
37 #include "mm/gc.hpp"
38 #include "mm/memory.h"
39
40 #include "vm/jit/stacktrace.hpp"
41
42 #include "native/llni.h"
43
44 #include "threads/thread.hpp"
45
46 #include "toolbox/logging.h"
47
48 #include "vm/array.h"
49 #include "vm/builtin.h"
50 #include "vm/class.h"
51 #include "vm/cycles-stats.h"
52 #include "vm/exceptions.hpp"
53 #include "vm/globals.hpp"
54 #include "vm/javaobjects.hpp"
55 #include "vm/loader.h"
56 #include "vm/method.h"
57 #include "vm/options.h"
58 #include "vm/string.hpp"
59 #include "vm/vm.hpp"
60
61 #include "vm/jit/asmpart.h"
62 #include "vm/jit/codegen-common.h"
63 #include "vm/jit/linenumbertable.h"
64 #include "vm/jit/methodheader.h"
65 #include "vm/jit/methodtree.h"
66
67
68 // FIXME Use C-linkage for now.
69 extern "C" {
70
71 /* global variables ***********************************************************/
72
73 CYCLES_STATS_DECLARE(stacktrace_overhead        , 100, 1)
74 CYCLES_STATS_DECLARE(stacktrace_fillInStackTrace, 40,  5000)
75 CYCLES_STATS_DECLARE(stacktrace_get,              40,  5000)
76 CYCLES_STATS_DECLARE(stacktrace_getClassContext , 40,  5000)
77 CYCLES_STATS_DECLARE(stacktrace_getCurrentClass , 40,  5000)
78 CYCLES_STATS_DECLARE(stacktrace_get_stack       , 40,  10000)
79
80
81 /* stacktrace_stackframeinfo_add ***********************************************
82
83    Fills a stackframe info structure with the given or calculated
84    values and adds it to the chain.
85
86 *******************************************************************************/
87
88 void stacktrace_stackframeinfo_add(stackframeinfo_t* sfi, void* pv, void* sp, void* ra, void* xpc)
89 {
90         stackframeinfo_t *currentsfi;
91         codeinfo         *code;
92 #if defined(ENABLE_JIT)
93         s4                 framesize;
94 #endif
95
96         /* Get current stackframe info. */
97
98         currentsfi = threads_get_current_stackframeinfo();
99
100         /* sometimes we don't have pv handy (e.g. in asmpart.S:
101        L_asm_call_jit_compiler_exception or in the interpreter). */
102
103         if (pv == NULL) {
104 #if defined(ENABLE_INTRP)
105                 if (opt_intrp)
106                         pv = methodtree_find(ra);
107                 else
108 #endif
109                         {
110 #if defined(ENABLE_JIT)
111 # if defined(__SPARC_64__)
112                                 pv = md_get_pv_from_stackframe(sp);
113 # else
114                                 pv = md_codegen_get_pv_from_pc(ra);
115 # endif
116 #endif
117                         }
118         }
119
120         /* Get codeinfo pointer for the parent Java method. */
121
122         code = code_get_codeinfo_for_pv(pv);
123
124         /* XXX */
125         /*      assert(m != NULL); */
126
127 #if defined(ENABLE_JIT)
128 # if defined(ENABLE_INTRP)
129         /* When using the interpreter, we pass RA to the function. */
130
131         if (!opt_intrp) {
132 # endif
133 # if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__M68K__)
134                 /* On i386 and x86_64 we always have to get the return address
135                    from the stack. */
136                 /* m68k has return address on stack always */
137                 /* On S390 we use REG_RA as REG_ITMP3, so we have always to get
138                    the RA from stack. */
139
140                 framesize = *((u4 *) (((uintptr_t) pv) + FrameSize));
141
142                 ra = md_stacktrace_get_returnaddress(sp, framesize);
143 # else
144                 /* If the method is a non-leaf function, we need to get the
145                    return address from the stack.  For leaf functions the
146                    return address is set correctly.  This makes the assembler
147                    and the signal handler code simpler.  The code is NULL is
148                    the asm_vm_call_method special case. */
149
150                 if ((code == NULL) || !code_is_leafmethod(code)) {
151                         framesize = *((u4 *) (((uintptr_t) pv) + FrameSize));
152
153                         ra = md_stacktrace_get_returnaddress(sp, framesize);
154                 }
155 # endif
156 # if defined(ENABLE_INTRP)
157         }
158 # endif
159 #endif
160
161         /* Calculate XPC when not given.  The XPC is then the return
162            address of the current method minus 1 because the RA points to
163            the instruction after the call instruction.  This is required
164            e.g. for method stubs. */
165
166         if (xpc == NULL) {
167                 xpc = (void *) (((intptr_t) ra) - 1);
168         }
169
170         /* Fill new stackframeinfo structure. */
171
172         sfi->prev = currentsfi;
173         sfi->code = code;
174         sfi->pv   = pv;
175         sfi->sp   = sp;
176         sfi->ra   = ra;
177         sfi->xpc  = xpc;
178
179 #if !defined(NDEBUG)
180         if (opt_DebugStackFrameInfo) {
181                 log_start();
182                 log_print("[stackframeinfo add   : sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
183                                   sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
184                 method_print(sfi->code->m);
185                 log_print("]");
186                 log_finish();
187         }
188 #endif
189
190         /* Store new stackframeinfo pointer. */
191
192         threads_set_current_stackframeinfo(sfi);
193
194         /* set the native world flag for the current thread */
195         /* ATTENTION: This flag tells the GC how to treat this thread in case of
196            a collection. Set this flag _after_ a valid stackframe info was set. */
197
198         THREAD_NATIVEWORLD_ENTER;
199 }
200
201
202 /* stacktrace_stackframeinfo_remove ********************************************
203
204    Remove the given stackframeinfo from the chain in the current
205    thread.
206
207 *******************************************************************************/
208
209 void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
210 {
211         /* Clear the native world flag for the current thread. */
212         /* ATTENTION: Clear this flag _before_ removing the stackframe info. */
213
214         THREAD_NATIVEWORLD_EXIT;
215
216 #if !defined(NDEBUG)
217         if (opt_DebugStackFrameInfo) {
218                 log_start();
219                 log_print("[stackframeinfo remove: sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
220                                   sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
221                 method_print(sfi->code->m);
222                 log_print("]");
223                 log_finish();
224         }
225 #endif
226
227         /* Set previous stackframe info. */
228
229         threads_set_current_stackframeinfo(sfi->prev);
230 }
231
232
233 /* stacktrace_stackframeinfo_fill **********************************************
234
235    Fill the temporary stackframeinfo structure with the values given
236    in sfi.
237
238    IN:
239        tmpsfi ... temporary stackframeinfo
240        sfi ...... stackframeinfo to be used in the next iteration
241
242 *******************************************************************************/
243
244 static inline void stacktrace_stackframeinfo_fill(stackframeinfo_t *tmpsfi, stackframeinfo_t *sfi)
245 {
246         /* Sanity checks. */
247
248         assert(tmpsfi != NULL);
249         assert(sfi != NULL);
250
251         /* Fill the temporary stackframeinfo. */
252
253         tmpsfi->code = sfi->code;
254         tmpsfi->pv   = sfi->pv;
255         tmpsfi->sp   = sfi->sp;
256         tmpsfi->ra   = sfi->ra;
257         tmpsfi->xpc  = sfi->xpc;
258
259         /* Set the previous stackframe info of the temporary one to the
260            next in the chain. */
261
262         tmpsfi->prev = sfi->prev;
263
264 #if !defined(NDEBUG)
265         if (opt_DebugStackTrace)
266                 log_println("[stacktrace fill]");
267 #endif
268 }
269
270
271 /* stacktrace_stackframeinfo_next **********************************************
272
273    Walk the stack (or the stackframeinfo-chain) to the next method and
274    return the new stackframe values in the temporary stackframeinfo
275    passed.
276
277    ATTENTION: This function does NOT skip builtin methods!
278
279    IN:
280        tmpsfi ... temporary stackframeinfo of current method
281
282 *******************************************************************************/
283
284 static inline void stacktrace_stackframeinfo_next(stackframeinfo_t *tmpsfi)
285 {
286         codeinfo         *code;
287         void             *pv;
288         void             *sp;
289         void             *ra;
290         void             *xpc;
291         uint32_t          framesize;
292         stackframeinfo_t *prevsfi;
293
294         /* Sanity check. */
295
296         assert(tmpsfi != NULL);
297
298         /* Get values from the stackframeinfo. */
299
300         code = tmpsfi->code;
301         pv   = tmpsfi->pv;
302         sp   = tmpsfi->sp;
303         ra   = tmpsfi->ra;
304         xpc  = tmpsfi->xpc;
305  
306         /* Get the current stack frame size. */
307
308         framesize = *((uint32_t *) (((intptr_t) pv) + FrameSize));
309
310         /* Get the RA of the current stack frame (RA to the parent Java
311            method) if the current method is a non-leaf method.  Otherwise
312            the value in the stackframeinfo is correct (from the signal
313            handler). */
314
315 #if defined(ENABLE_JIT)
316 # if defined(ENABLE_INTRP)
317         if (opt_intrp)
318                 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
319         else
320 # endif
321                 {
322                         if (!code_is_leafmethod(code))
323                                 ra = md_stacktrace_get_returnaddress(sp, framesize);
324                 }
325 #else
326         ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
327 #endif
328
329         /* Get the PV for the parent Java method. */
330
331 #if defined(ENABLE_INTRP)
332         if (opt_intrp)
333                 pv = methodtree_find(ra);
334         else
335 #endif
336                 {
337 #if defined(ENABLE_JIT)
338 # if defined(__SPARC_64__)
339                         sp = md_get_framepointer(sp);
340                         pv = md_get_pv_from_stackframe(sp);
341 # else
342                         pv = md_codegen_get_pv_from_pc(ra);
343 # endif
344 #endif
345                 }
346
347         /* Get the codeinfo pointer for the parent Java method. */
348
349         code = code_get_codeinfo_for_pv(pv);
350
351         /* Calculate the SP for the parent Java method. */
352
353 #if defined(ENABLE_INTRP)
354         if (opt_intrp)
355                 sp = *(u1 **) (sp - framesize);
356         else
357 #endif
358                 {
359 #if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
360                         sp = (void *) (((intptr_t) sp) + framesize + SIZEOF_VOID_P);
361 #elif defined(__SPARC_64__)
362                         /* already has the new sp */
363 #else
364                         sp = (void *) (((intptr_t) sp) + framesize);
365 #endif
366                 }
367
368         /* If the new codeinfo pointer is NULL we reached a
369            asm_vm_call_method function.  In this case we get the next
370            values from the previous stackframeinfo in the chain.
371            Otherwise the new values have been calculated before. */
372
373         if (code == NULL) {
374                 prevsfi = tmpsfi->prev;
375
376                 /* If the previous stackframeinfo in the chain is NULL we
377                    reached the top of the stacktrace.  We set code and prev to
378                    NULL to mark the end, which is checked in
379                    stacktrace_stackframeinfo_end_check. */
380
381                 if (prevsfi == NULL) {
382                         tmpsfi->code = NULL;
383                         tmpsfi->prev = NULL;
384                         return;
385                 }
386
387                 /* Fill the temporary stackframeinfo with the new values. */
388
389                 stacktrace_stackframeinfo_fill(tmpsfi, prevsfi);
390         }
391         else {
392                 /* Store the new values in the stackframeinfo.  NOTE: We
393                    subtract 1 from the RA to get the XPC, because the RA
394                    points to the instruction after the call instruction. */
395
396                 tmpsfi->code = code;
397                 tmpsfi->pv   = pv;
398                 tmpsfi->sp   = sp;
399                 tmpsfi->ra   = ra;
400                 tmpsfi->xpc  = (void *) (((intptr_t) ra) - 1);
401         }
402
403 #if !defined(NDEBUG)
404         /* Print current method information. */
405
406         if (opt_DebugStackTrace) {
407                 log_start();
408                 log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
409                                   tmpsfi->code->m, tmpsfi->pv, tmpsfi->sp, tmpsfi->ra,
410                                   tmpsfi->xpc);
411                 method_print(tmpsfi->code->m);
412                 log_print("]");
413                 log_finish();
414         }
415 #endif
416 }
417
418
419 /* stacktrace_stackframeinfo_end_check *****************************************
420
421    Check if we reached the end of the stacktrace.
422
423    IN:
424        tmpsfi ... temporary stackframeinfo of current method
425
426    RETURN:
427        true .... the end is reached
428            false ... the end is not reached
429
430 *******************************************************************************/
431
432 static inline bool stacktrace_stackframeinfo_end_check(stackframeinfo_t *tmpsfi)
433 {
434         /* Sanity check. */
435
436         assert(tmpsfi != NULL);
437
438         if ((tmpsfi->code == NULL) && (tmpsfi->prev == NULL)) {
439 #if !defined(NDEBUG)
440                 if (opt_DebugStackTrace)
441                         log_println("[stacktrace stop]");
442 #endif
443
444                 return true;
445         }
446
447         return false;
448 }
449
450
451 /* stacktrace_depth ************************************************************
452
453    Calculates and returns the depth of the current stacktrace.
454
455    IN:
456        sfi ... stackframeinfo where to start the stacktrace
457
458    RETURN:
459        depth of the stacktrace
460
461 *******************************************************************************/
462
463 static int stacktrace_depth(stackframeinfo_t *sfi)
464 {
465         stackframeinfo_t  tmpsfi;
466         int               depth;
467         methodinfo       *m;
468
469 #if !defined(NDEBUG)
470         if (opt_DebugStackTrace)
471                 log_println("[stacktrace_depth]");
472 #endif
473
474         /* XXX This is not correct, but a workaround for threads-dump for
475            now. */
476 /*      assert(sfi != NULL); */
477         if (sfi == NULL)
478                 return 0;
479
480         /* Iterate over all stackframes. */
481
482         depth = 0;
483
484         for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
485                  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
486                  stacktrace_stackframeinfo_next(&tmpsfi)) {
487                 /* Get methodinfo. */
488
489                 m = tmpsfi.code->m;
490
491                 /* Skip builtin methods. */
492
493                 if (m->flags & ACC_METHOD_BUILTIN)
494                         continue;
495
496                 depth++;
497         }
498
499         return depth;
500 }
501
502
503 /* stacktrace_get **************************************************************
504
505    Builds and returns a stacktrace starting from the given stackframe
506    info and returns the stacktrace structure wrapped in a Java
507    byte-array to not confuse the GC.
508
509    IN:
510        sfi ... stackframe info to start stacktrace from
511
512    RETURN:
513        stacktrace as Java byte-array
514
515 *******************************************************************************/
516
517 java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi)
518 {
519         stackframeinfo_t         tmpsfi;
520         int                      depth;
521         java_handle_bytearray_t *ba;
522         int32_t                  ba_size;
523         stacktrace_t            *st;
524         stacktrace_entry_t      *ste;
525         methodinfo              *m;
526         bool                     skip_fillInStackTrace;
527         bool                     skip_init;
528
529         CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
530
531 #if !defined(NDEBUG)
532         if (opt_DebugStackTrace)
533                 log_println("[stacktrace_get]");
534 #endif
535
536         skip_fillInStackTrace = true;
537         skip_init             = true;
538
539         depth = stacktrace_depth(sfi);
540
541         if (depth == 0)
542                 return NULL;
543
544         /* Allocate memory from the GC heap and copy the stacktrace
545            buffer. */
546         /* ATTENTION: Use a Java byte-array for this to not confuse the
547            GC. */
548         /* FIXME: We waste some memory here as we skip some entries
549            later. */
550
551         ba_size = sizeof(stacktrace_t) + sizeof(stacktrace_entry_t) * depth;
552
553         ba = builtin_newarray_byte(ba_size);
554
555         if (ba == NULL)
556                 goto return_NULL;
557
558         /* Get a stacktrace entry pointer. */
559         /* ATTENTION: We need a critical section here because we use the
560            byte-array data pointer directly. */
561
562         LLNI_CRITICAL_START;
563
564         st = (stacktrace_t *) LLNI_array_data(ba);
565
566         ste = st->entries;
567
568         /* Iterate over the whole stack. */
569
570         for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
571                  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
572                  stacktrace_stackframeinfo_next(&tmpsfi)) {
573                 /* Get the methodinfo. */
574
575                 m = tmpsfi.code->m;
576
577                 /* Skip builtin methods. */
578
579                 if (m->flags & ACC_METHOD_BUILTIN)
580                         continue;
581
582                 /* This logic is taken from
583                    hotspot/src/share/vm/classfile/javaClasses.cpp
584                    (java_lang_Throwable::fill_in_stack_trace). */
585
586                 if (skip_fillInStackTrace == true) {
587                         /* Check "fillInStackTrace" only once, so we negate the
588                            flag after the first time check. */
589
590 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
591                         /* For GNU Classpath we also need to skip
592                            VMThrowable.fillInStackTrace(). */
593
594                         if ((m->clazz == class_java_lang_VMThrowable) &&
595                                 (m->name  == utf_fillInStackTrace))
596                                 continue;
597 #endif
598
599                         skip_fillInStackTrace = false;
600
601                         if (m->name == utf_fillInStackTrace)
602                                 continue;
603                 }
604
605                 /* Skip <init> methods of the exceptions klass.  If there is
606                    <init> methods that belongs to a superclass of the
607                    exception we are going to skipping them in stack trace. */
608
609                 if (skip_init == true) {
610                         if ((m->name == utf_init) &&
611                                 (class_issubclass(m->clazz, class_java_lang_Throwable))) {
612                                 continue;
613                         }
614                         else {
615                                 /* If no "Throwable.init()" method found, we stop
616                                    checking it next time. */
617
618                                 skip_init = false;
619                         }
620                 }
621
622                 /* Store the stacktrace entry and increment the pointer. */
623
624                 ste->code = tmpsfi.code;
625                 ste->pc   = tmpsfi.xpc;
626
627                 ste++;
628         }
629
630         /* Store the number of entries in the stacktrace structure. */
631
632         st->length = ste - st->entries;
633
634         LLNI_CRITICAL_END;
635
636         /* release dump memory */
637
638 /*      dump_release(dumpsize); */
639
640         CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
641                                                                    stacktrace_overhead)
642         return ba;
643
644 return_NULL:
645 /*      dump_release(dumpsize); */
646
647         CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
648                                                                    stacktrace_overhead)
649
650         return NULL;
651 }
652
653
654 /* stacktrace_get_current ******************************************************
655
656    Builds and returns a stacktrace from the current thread and returns
657    the stacktrace structure wrapped in a Java byte-array to not
658    confuse the GC.
659
660    RETURN:
661        stacktrace as Java byte-array
662
663 *******************************************************************************/
664
665 java_handle_bytearray_t *stacktrace_get_current(void)
666 {
667         stackframeinfo_t        *sfi;
668         java_handle_bytearray_t *ba;
669
670         sfi = threads_get_current_stackframeinfo();
671         ba  = stacktrace_get(sfi);
672
673         return ba;
674 }
675
676
677 /* stacktrace_get_caller_class *************************************************
678
679    Get the class on the stack at the given depth.  This function skips
680    various special classes or methods.
681
682    ARGUMENTS:
683        depth ... depth to get caller class of
684
685    RETURN:
686        caller class
687
688 *******************************************************************************/
689
690 #if defined(ENABLE_JAVASE)
691 classinfo *stacktrace_get_caller_class(int depth)
692 {
693         stackframeinfo_t *sfi;
694         stackframeinfo_t  tmpsfi;
695         methodinfo       *m;
696         classinfo        *c;
697         int               i;
698
699 #if !defined(NDEBUG)
700         if (opt_DebugStackTrace)
701                 log_println("[stacktrace_get_caller_class]");
702 #endif
703
704         /* Get the stackframeinfo of the current thread. */
705
706         sfi = threads_get_current_stackframeinfo();
707
708         /* Iterate over the whole stack until we reached the requested
709            depth. */
710
711         i = 0;
712
713         for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
714                  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
715                  stacktrace_stackframeinfo_next(&tmpsfi)) {
716
717                 m = tmpsfi.code->m;
718                 c = m->clazz;
719
720                 /* Skip builtin methods. */
721
722                 if (m->flags & ACC_METHOD_BUILTIN)
723                         continue;
724
725 #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
726                 /* NOTE: See hotspot/src/share/vm/runtime/vframe.cpp
727                    (vframeStreamCommon::security_get_caller_frame). */
728
729                 /* This is java.lang.reflect.Method.invoke(), skip it. */
730
731                 if (m == method_java_lang_reflect_Method_invoke)
732                         continue;
733
734                 /* This is an auxiliary frame, skip it. */
735
736                 if (class_issubclass(c, class_sun_reflect_MagicAccessorImpl))
737                         continue;
738 #endif
739
740                 /* We reached the requested depth. */
741
742                 if (i >= depth)
743                         return c;
744
745                 i++;
746         }
747
748         return NULL;
749 }
750 #endif
751
752
753 /* stacktrace_first_nonnull_classloader ****************************************
754
755    Returns the first non-null (user-defined) classloader on the stack.
756    If none is found NULL is returned.
757
758    RETURN:
759        classloader
760
761 *******************************************************************************/
762
763 classloader_t *stacktrace_first_nonnull_classloader(void)
764 {
765         stackframeinfo_t *sfi;
766         stackframeinfo_t  tmpsfi;
767         methodinfo       *m;
768         classloader_t    *cl;
769
770 #if !defined(NDEBUG)
771         if (opt_DebugStackTrace)
772                 log_println("[stacktrace_first_nonnull_classloader]");
773 #endif
774
775         /* Get the stackframeinfo of the current thread. */
776
777         sfi = threads_get_current_stackframeinfo();
778
779         /* Iterate over the whole stack. */
780
781         for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
782                  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
783                  stacktrace_stackframeinfo_next(&tmpsfi)) {
784
785                 m  = tmpsfi.code->m;
786                 cl = class_get_classloader(m->clazz);
787
788                 if (cl != NULL)
789                         return cl;
790         }
791
792         return NULL;
793 }
794
795
796 /* stacktrace_getClassContext **************************************************
797
798    Creates a Class context array.
799
800    RETURN VALUE:
801       the array of java.lang.Class objects, or
802           NULL if an exception has been thrown
803
804 *******************************************************************************/
805
806 java_handle_objectarray_t *stacktrace_getClassContext(void)
807 {
808         stackframeinfo_t           *sfi;
809         stackframeinfo_t            tmpsfi;
810         int                         depth;
811         java_handle_objectarray_t  *oa;
812         java_object_t             **data;
813         int                         i;
814         methodinfo                 *m;
815
816         CYCLES_STATS_DECLARE_AND_START
817
818 #if !defined(NDEBUG)
819         if (opt_DebugStackTrace)
820                 log_println("[stacktrace_getClassContext]");
821 #endif
822
823         sfi = threads_get_current_stackframeinfo();
824
825         /* Get the depth of the current stack. */
826
827         depth = stacktrace_depth(sfi);
828
829         /* The first stackframe corresponds to the method whose
830            implementation calls this native function.  We remove that
831            entry. */
832
833         depth--;
834         stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
835         stacktrace_stackframeinfo_next(&tmpsfi);
836
837         /* Allocate the Class array. */
838
839         oa = builtin_anewarray(depth, class_java_lang_Class);
840
841         if (oa == NULL) {
842                 CYCLES_STATS_END(stacktrace_getClassContext);
843
844                 return NULL;
845         }
846
847         /* Fill the Class array from the stacktrace list. */
848
849         LLNI_CRITICAL_START;
850
851         data = LLNI_array_data(oa);
852
853         /* Iterate over the whole stack. */
854
855         i = 0;
856
857         for (;
858                  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
859                  stacktrace_stackframeinfo_next(&tmpsfi)) {
860                 /* Get methodinfo. */
861
862                 m = tmpsfi.code->m;
863
864                 /* Skip builtin methods. */
865
866                 if (m->flags & ACC_METHOD_BUILTIN)
867                         continue;
868
869                 /* Store the class in the array. */
870
871                 data[i] = (java_object_t *) m->clazz;
872
873                 i++;
874         }
875
876         LLNI_CRITICAL_END;
877
878         CYCLES_STATS_END(stacktrace_getClassContext)
879
880         return oa;
881 }
882
883
884 /* stacktrace_getCurrentClass **************************************************
885
886    Find the current class by walking the stack trace.
887
888    Quote from the JNI documentation:
889          
890    In the Java 2 Platform, FindClass locates the class loader
891    associated with the current native method.  If the native code
892    belongs to a system class, no class loader will be
893    involved. Otherwise, the proper class loader will be invoked to
894    load and link the named class. When FindClass is called through the
895    Invocation Interface, there is no current native method or its
896    associated class loader. In that case, the result of
897    ClassLoader.getBaseClassLoader is used."
898
899 *******************************************************************************/
900
901 #if defined(ENABLE_JAVASE)
902 classinfo *stacktrace_get_current_class(void)
903 {
904         stackframeinfo_t *sfi;
905         stackframeinfo_t  tmpsfi;
906         methodinfo       *m;
907
908         CYCLES_STATS_DECLARE_AND_START;
909
910 #if !defined(NDEBUG)
911         if (opt_DebugStackTrace)
912                 log_println("[stacktrace_get_current_class]");
913 #endif
914
915         /* Get the stackframeinfo of the current thread. */
916
917         sfi = threads_get_current_stackframeinfo();
918
919         /* If the stackframeinfo is NULL then FindClass is called through
920            the Invocation Interface and we return NULL */
921
922         if (sfi == NULL) {
923                 CYCLES_STATS_END(stacktrace_getCurrentClass);
924
925                 return NULL;
926         }
927
928         /* Iterate over the whole stack. */
929
930         for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
931                  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
932                  stacktrace_stackframeinfo_next(&tmpsfi)) {
933                 /* Get the methodinfo. */
934
935                 m = tmpsfi.code->m;
936
937                 if (m->clazz == class_java_security_PrivilegedAction) {
938                         CYCLES_STATS_END(stacktrace_getCurrentClass);
939
940                         return NULL;
941                 }
942
943                 if (m->clazz != NULL) {
944                         CYCLES_STATS_END(stacktrace_getCurrentClass);
945
946                         return m->clazz;
947                 }
948         }
949
950         /* No Java method found on the stack. */
951
952         CYCLES_STATS_END(stacktrace_getCurrentClass);
953
954         return NULL;
955 }
956 #endif /* ENABLE_JAVASE */
957
958
959 /* stacktrace_get_stack ********************************************************
960
961    Create a 2-dimensional array for java.security.VMAccessControler.
962
963    RETURN VALUE:
964       the arrary, or
965          NULL if an exception has been thrown
966
967 *******************************************************************************/
968
969 #if defined(ENABLE_JAVASE) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
970 java_handle_objectarray_t *stacktrace_get_stack(void)
971 {
972         stackframeinfo_t          *sfi;
973         stackframeinfo_t           tmpsfi;
974         int                        depth;
975         java_handle_objectarray_t *oa;
976         java_handle_objectarray_t *classes;
977         java_handle_objectarray_t *methodnames;
978         methodinfo                *m;
979         java_handle_t             *string;
980         int                        i;
981
982         CYCLES_STATS_DECLARE_AND_START
983
984 #if !defined(NDEBUG)
985         if (opt_DebugStackTrace)
986                 log_println("[stacktrace_get_stack]");
987 #endif
988
989         /* Get the stackframeinfo of the current thread. */
990
991         sfi = threads_get_current_stackframeinfo();
992
993         /* Get the depth of the current stack. */
994
995         depth = stacktrace_depth(sfi);
996
997         if (depth == 0)
998                 return NULL;
999
1000         /* Allocate the required arrays. */
1001
1002         oa = builtin_anewarray(2, arrayclass_java_lang_Object);
1003
1004         if (oa == NULL)
1005                 goto return_NULL;
1006
1007         classes = builtin_anewarray(depth, class_java_lang_Class);
1008
1009         if (classes == NULL)
1010                 goto return_NULL;
1011
1012         methodnames = builtin_anewarray(depth, class_java_lang_String);
1013
1014         if (methodnames == NULL)
1015                 goto return_NULL;
1016
1017         /* Set up the 2-dimensional array. */
1018
1019         array_objectarray_element_set(oa, 0, (java_handle_t *) classes);
1020         array_objectarray_element_set(oa, 1, (java_handle_t *) methodnames);
1021
1022         /* Iterate over the whole stack. */
1023         /* TODO We should use a critical section here to speed things
1024            up. */
1025
1026         i = 0;
1027
1028         for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1029                  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1030                  stacktrace_stackframeinfo_next(&tmpsfi)) {
1031                 /* Get the methodinfo. */
1032
1033                 m = tmpsfi.code->m;
1034
1035                 /* Skip builtin methods. */
1036
1037                 if (m->flags & ACC_METHOD_BUILTIN)
1038                         continue;
1039
1040                 /* Store the class in the array. */
1041                 /* NOTE: We use a LLNI-macro here, because a classinfo is not
1042                    a handle. */
1043
1044                 LLNI_array_direct(classes, i) = (java_object_t *) m->clazz;
1045
1046                 /* Store the name in the array. */
1047
1048                 string = javastring_new(m->name);
1049
1050                 if (string == NULL)
1051                         goto return_NULL;
1052
1053                 array_objectarray_element_set(methodnames, i, string);
1054
1055                 i++;
1056         }
1057
1058         CYCLES_STATS_END(stacktrace_get_stack)
1059
1060         return oa;
1061
1062 return_NULL:
1063         CYCLES_STATS_END(stacktrace_get_stack)
1064
1065         return NULL;
1066 }
1067 #endif
1068
1069
1070 /* stacktrace_print_entry ****************************************************
1071
1072    Print line for a stacktrace entry.
1073
1074    ARGUMENTS:
1075        m ............ methodinfo of the entry
1076        linenumber ... linenumber of the entry
1077
1078 *******************************************************************************/
1079
1080 static void stacktrace_print_entry(methodinfo *m, int32_t linenumber)
1081 {
1082         /* Sanity check. */
1083
1084         assert(m != NULL);
1085
1086         printf("\tat ");
1087
1088         if (m->flags & ACC_METHOD_BUILTIN)
1089                 printf("NULL");
1090         else
1091                 utf_display_printable_ascii_classname(m->clazz->name);
1092
1093         printf(".");
1094         utf_display_printable_ascii(m->name);
1095         utf_display_printable_ascii(m->descriptor);
1096
1097         if (m->flags & ACC_NATIVE) {
1098                 puts("(Native Method)");
1099         }
1100         else {
1101                 if (m->flags & ACC_METHOD_BUILTIN) {
1102                         puts("(builtin)");
1103                 }
1104                 else {
1105                         printf("(");
1106                         utf_display_printable_ascii(m->clazz->sourcefile);
1107                         printf(":%d)\n", linenumber);
1108                 }
1109         }
1110
1111         fflush(stdout);
1112 }
1113
1114
1115 /* stacktrace_print ************************************************************
1116
1117    Print the given stacktrace with CACAO intern methods only (no Java
1118    code required).
1119
1120    This method is used by stacktrace_dump_trace and
1121    builtin_trace_exception.
1122
1123    IN:
1124        st ... stacktrace to print
1125
1126 *******************************************************************************/
1127
1128 void stacktrace_print(stacktrace_t *st)
1129 {
1130         stacktrace_entry_t *ste;
1131         methodinfo         *m;
1132         int32_t             linenumber;
1133         int                 i;
1134
1135         ste = &(st->entries[0]);
1136
1137         for (i = 0; i < st->length; i++, ste++) {
1138                 m = ste->code->m;
1139
1140                 /* Get the line number. */
1141
1142                 linenumber = linenumbertable_linenumber_for_pc(&m, ste->code, ste->pc);
1143
1144                 stacktrace_print_entry(m, linenumber);
1145         }
1146 }
1147
1148
1149 /* stacktrace_print_current ****************************************************
1150
1151    Print the current stacktrace of the current thread.
1152
1153    NOTE: This function prints all frames of the stacktrace and does
1154    not skip frames like stacktrace_get.
1155
1156 *******************************************************************************/
1157
1158 void stacktrace_print_current(void)
1159 {
1160         stackframeinfo_t *sfi;
1161         stackframeinfo_t  tmpsfi;
1162         codeinfo         *code;
1163         methodinfo       *m;
1164         int32_t           linenumber;
1165
1166         sfi = threads_get_current_stackframeinfo();
1167
1168         if (sfi == NULL) {
1169                 puts("\t<<No stacktrace available>>");
1170                 fflush(stdout);
1171                 return;
1172         }
1173
1174         for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1175                  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1176                  stacktrace_stackframeinfo_next(&tmpsfi)) {
1177                 /* Get the methodinfo. */
1178
1179                 code = tmpsfi.code;
1180                 m    = code->m;
1181
1182                 /* Get the line number. */
1183
1184                 linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
1185
1186                 stacktrace_print_entry(m, linenumber);
1187         }
1188 }
1189
1190
1191 /* stacktrace_print_of_thread **************************************************
1192
1193    Print the current stacktrace of the given thread.
1194
1195    ARGUMENTS:
1196        t ... thread
1197
1198 *******************************************************************************/
1199
1200 #if defined(ENABLE_THREADS)
1201 void stacktrace_print_of_thread(threadobject *t)
1202 {
1203         stackframeinfo_t *sfi;
1204         stackframeinfo_t  tmpsfi;
1205         codeinfo         *code;
1206         methodinfo       *m;
1207         int32_t           linenumber;
1208
1209         /* Build a stacktrace for the passed thread. */
1210
1211         sfi = t->_stackframeinfo;
1212         
1213         if (sfi == NULL) {
1214                 puts("\t<<No stacktrace available>>");
1215                 fflush(stdout);
1216                 return;
1217         }
1218
1219         for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1220                  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1221                  stacktrace_stackframeinfo_next(&tmpsfi)) {
1222                 /* Get the methodinfo. */
1223
1224                 code = tmpsfi.code;
1225                 m    = code->m;
1226
1227                 /* Get the line number. */
1228
1229                 linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
1230
1231                 stacktrace_print_entry(m, linenumber);
1232         }
1233 }
1234 #endif
1235
1236
1237 /* stacktrace_print_exception **************************************************
1238
1239    Print the stacktrace of a given exception (more or less a wrapper
1240    to stacktrace_print).
1241
1242    IN:
1243        h ... handle of exception to print
1244
1245 *******************************************************************************/
1246
1247 void stacktrace_print_exception(java_handle_t *h)
1248 {
1249         if (h == NULL)
1250                 return;
1251
1252         java_lang_Throwable t(h);
1253
1254         /* now print the stacktrace */
1255
1256 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1257
1258         java_lang_VMThrowable vmt(t.get_vmState());
1259         java_handle_bytearray_t* backtrace = vmt.get_vmdata();
1260
1261 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
1262
1263         java_handle_bytearray_t* backtrace = t.get_backtrace();
1264
1265 #else
1266 # error unknown classpath configuration
1267 #endif
1268
1269         // Sanity check.
1270
1271         assert(backtrace != NULL);
1272
1273         /* We need a critical section here as we use the byte-array data
1274            pointer directly. */
1275
1276         LLNI_CRITICAL_START;
1277         
1278         stacktrace_t* st = (stacktrace_t*) LLNI_array_data(backtrace);
1279
1280         stacktrace_print(st);
1281
1282         LLNI_CRITICAL_END;
1283 }
1284
1285
1286 #if defined(ENABLE_CYCLES_STATS)
1287 void stacktrace_print_cycles_stats(FILE *file)
1288 {
1289         CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead, file);
1290         CYCLES_STATS_PRINT(stacktrace_get,               file);
1291         CYCLES_STATS_PRINT(stacktrace_getClassContext ,  file);
1292         CYCLES_STATS_PRINT(stacktrace_getCurrentClass ,  file);
1293         CYCLES_STATS_PRINT(stacktrace_get_stack,         file);
1294 }
1295 #endif
1296
1297 } // extern "C"
1298
1299
1300 /*
1301  * These are local overrides for various environment variables in Emacs.
1302  * Please do not remove this and leave it at the end of the file, where
1303  * Emacs will automagically detect them.
1304  * ---------------------------------------------------------------------
1305  * Local variables:
1306  * mode: c++
1307  * indent-tabs-mode: t
1308  * c-basic-offset: 4
1309  * tab-width: 4
1310  * End:
1311  * vim:noexpandtab:sw=4:ts=4:
1312  */