* generateStackTraceArray: removed
[cacao.git] / src / native / vm / VMThrowable.c
1 /* src/native/vm/VMThrowable.c - java/lang/VMThrowable
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Joseph Wenninger
28
29    Changes: Christian Thalinger
30
31    $Id: VMThrowable.c 3077 2005-07-20 15:16:58Z twisti $
32
33 */
34
35
36 #include <assert.h>
37
38 #include "native/jni.h"
39 #include "native/native.h"
40 #include "native/include/java_lang_Class.h"
41 #include "native/include/java_lang_StackTraceElement.h"
42 #include "native/include/java_lang_Throwable.h"
43 #include "native/include/java_lang_VMClass.h"
44 #include "native/include/java_lang_VMThrowable.h"
45 #include "vm/builtin.h"
46 #include "vm/class.h"
47 #include "vm/loader.h"
48 #include "vm/stringlocal.h"
49 #include "vm/tables.h"
50 #include "vm/jit/asmpart.h"
51 #include "vm/jit/stacktrace.h"
52 #include "vm/exceptions.h"
53
54
55 /*
56  * Class:     java/lang/VMThrowable
57  * Method:    fillInStackTrace
58  * Signature: (Ljava/lang/Throwable;)Ljava/lang/VMThrowable;
59  */
60 JNIEXPORT java_lang_VMThrowable* JNICALL Java_java_lang_VMThrowable_fillInStackTrace(JNIEnv *env, jclass clazz, java_lang_Throwable *par1)
61 {
62         java_lang_VMThrowable *vmthrow;
63
64         if ((*dontfillinexceptionstacktrace) == true) {
65                 /*log_text("dontfillinexceptionstacktrace");*/
66                 return 0;
67         }
68
69         vmthrow = (java_lang_VMThrowable *)
70                 native_new_and_init(class_java_lang_VMThrowable);
71
72         if (!vmthrow) {
73                 log_text("Needed instance of class  java.lang.VMThrowable could not be created");
74                 assert(0);
75         }
76
77 #if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__X86_64__)
78         cacao_stacktrace_NormalTrace((void **) &(vmthrow->vmData));
79 #endif
80
81         return vmthrow;
82 }
83
84
85 /*
86  * Class:     java/lang/VMThrowable
87  * Method:    getStackTrace
88  * Signature: (Ljava/lang/Throwable;)[Ljava/lang/StackTraceElement;
89  */
90 JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMThrowable_getStackTrace(JNIEnv *env, java_lang_VMThrowable *this, java_lang_Throwable *t)
91 {
92 #if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__X86_64__)
93         stackTraceBuffer            *buf;
94         stacktraceelement           *elem;
95         stacktraceelement           *tmpelem;
96         s4                           size;
97         s4                           i;
98         classinfo                   *c;
99         bool                         inexceptionclass;
100         bool                         leftexceptionclass;
101
102         methodinfo                  *m;
103         java_objectarray            *oa;
104         s4                           oalength;
105         java_lang_StackTraceElement *ste;
106         java_lang_String            *filename;
107         s4                           linenumber;
108         java_lang_String            *declaringclass;
109
110         buf = (stackTraceBuffer *) this->vmData;
111         c = t->header.vftbl->class;
112
113         if (!buf) {
114                 log_text("Invalid java.lang.VMThrowable.vmData field in java.lang.VMThrowable.getStackTrace native code");
115                 assert(0);
116         }
117         
118         size = buf->full;
119
120         if (size < 2) {
121                 log_text("Invalid java.lang.VMThrowable.vmData field in java.lang.VMThrowable.getStackTrace native code (length<2)");
122                 assert(0);
123         }
124
125         /* skip first 2 elements in stacktrace buffer:                            */
126         /*   0: VMThrowable.fillInStackTrace                                      */
127         /*   1: Throwable.fillInStackTrace                                        */
128
129         elem = &(buf->start[2]);
130         size -= 2;
131
132         if (size && elem->method != 0) {
133                 /* not a builtin native wrapper*/
134
135                 if ((elem->method->class->name == utf_java_lang_Throwable) &&
136                         (elem->method->name == utf_init)) {
137                         /* We assume that we are within the initializer of the exception  */
138                         /* object, the exception object itself should not appear in the   */
139                         /* stack trace, so we skip till we reach the first function,      */
140                         /* which is not an init function.                                 */
141
142                         inexceptionclass = false;
143                         leftexceptionclass = false;
144
145                         while (size > 0) {
146                                 /* check if we are in the exception class */
147
148                                 if (elem->method->class == c)
149                                         inexceptionclass = true;
150
151                                 /* check if we left the exception class */
152
153                                 if (inexceptionclass && (elem->method->class != c))
154                                         leftexceptionclass = true;
155
156                                 /* found exception start point if we left the initalizers or  */
157                                 /* we left the exception class                                */
158
159                                 if ((elem->method->name != utf_init) || leftexceptionclass)
160                                         break;
161
162                                 elem++;
163                                 size--;
164                         }
165                 }
166         }
167
168
169         /* now fill the stacktrace into java objects */
170
171         m = class_findmethod(class_java_lang_StackTraceElement,
172                                                  utf_init,
173                                                  utf_new_char("(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Z)V"));
174
175         if (!m)
176                 return NULL;
177
178         /* count entries with a method name */
179
180         for (oalength = 0, i = size, tmpelem = elem; i > 0; i--, tmpelem++)
181                 if (tmpelem->method)
182                         oalength++;
183
184         /* create the stacktrace element array */
185
186         oa = builtin_anewarray(oalength, class_java_lang_StackTraceElement);
187
188         if (!oa)
189                 return NULL;
190
191         for (i = 0; size > 0; size--, elem++, i++) {
192                 if (elem->method == NULL) {
193                         i--;
194                         continue;
195                 }
196
197                 /* allocate a new stacktrace element */
198
199                 ste = (java_lang_StackTraceElement *)
200                         builtin_new(class_java_lang_StackTraceElement);
201
202                 if (!ste)
203                         return NULL;
204
205                 /* get filename */
206
207                 if (!(elem->method->flags & ACC_NATIVE)) {
208                         if (elem->method->class->sourcefile)
209                                 filename = javastring_new(elem->method->class->sourcefile);
210                         else
211                                 filename = NULL;
212
213                 } else {
214                         filename = NULL;
215                 }
216
217                 /* get line number */
218
219                 if (elem->method->flags & ACC_NATIVE)
220                         linenumber = -1;
221                 else
222                         linenumber = (elem->linenumber == 0) ? -1 : elem->linenumber;
223
224                 /* get declaring class name */
225
226                 declaringclass = Java_java_lang_VMClass_getName(env, NULL, (java_lang_Class *) elem->method->class);
227
228
229                 /* fill the stacktrace element */
230
231                 ste->fileName       = filename;
232                 ste->lineNumber     = linenumber;
233                 ste->declaringClass = declaringclass;
234                 ste->methodName     = javastring_new(elem->method->name);
235                 ste->isNative       = (elem->method->flags & ACC_NATIVE) ? 1 : 0;
236
237                 oa->data[i] = (java_objectheader *) ste;
238         }
239
240         return oa;
241 #else
242         return NULL;
243 #endif
244 }
245
246
247 /*
248  * These are local overrides for various environment variables in Emacs.
249  * Please do not remove this and leave it at the end of the file, where
250  * Emacs will automagically detect them.
251  * ---------------------------------------------------------------------
252  * Local variables:
253  * mode: c
254  * indent-tabs-mode: t
255  * c-basic-offset: 4
256  * tab-width: 4
257  * End:
258  */