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