GNU header update.
[cacao.git] / src / native / vm / VMThrowable.c
1 /* nat/VMThrowable.c - java/lang/Throwable
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    $Id: VMThrowable.c 1735 2004-12-07 14:33:27Z twisti $
30
31 */
32
33
34 #include "native/jni.h"
35 #include "native/native.h"
36 #include "native/include/java_lang_Class.h"
37 #include "native/include/java_lang_Throwable.h"
38 #include "native/include/java_lang_VMClass.h"
39 #include "native/include/java_lang_VMThrowable.h"
40 #include "vm/builtin.h"
41 #include "vm/loader.h"
42 #include "vm/tables.h"
43 #include "vm/jit/asmpart.h"
44 #include "vm/jit/stacktrace.h"
45
46
47 /*
48  * Class:     java/lang/VMThrowable
49  * Method:    fillInStackTrace
50  * Signature: (Ljava/lang/Throwable;)Ljava/lang/VMThrowable;
51  */
52 JNIEXPORT java_lang_VMThrowable* JNICALL Java_java_lang_VMThrowable_fillInStackTrace(JNIEnv *env, jclass clazz, java_lang_Throwable *par1)
53 {
54         classinfo *class_java_lang_VMThrowable = NULL;
55         java_lang_VMThrowable *vmthrow;
56
57         if (!class_java_lang_VMThrowable)
58                 class_java_lang_VMThrowable = class_new(utf_new_char("java/lang/VMThrowable"));
59
60         if (class_java_lang_VMThrowable == NULL)
61                 panic("Needed class java.lang.VMThrowable missing");
62
63         vmthrow = (java_lang_VMThrowable *) native_new_and_init(class_java_lang_VMThrowable);
64
65         if (vmthrow == NULL)
66                 panic("Needed instance of class  java.lang.VMThrowable could not be created");
67
68 #if defined(__I386__) || defined(__ALPHA__)
69         cacao_stacktrace_NormalTrace(&(vmthrow->vmData));
70 #endif
71         return vmthrow;
72 }
73
74
75 static
76 java_objectarray* generateStackTraceArray(JNIEnv *env,stacktraceelement *el,long size)
77 {
78         long resultPos;
79         methodinfo *m;
80         classinfo *c;
81         java_objectarray *oa;
82
83         c = class_new(utf_new_char("java/lang/StackTraceElement"));
84
85         if (!c->loaded)
86                 class_load(c);
87
88         if (!c->linked)
89                 class_link(c);
90
91         m = class_findmethod(c,
92                                                  utf_new_char("<init>"),
93                                                  utf_new_char("(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Z)V"));
94
95         if (!m)
96                 panic("java.lang.StackTraceElement misses needed constructor"); 
97
98         oa = builtin_anewarray(size, c);
99
100         if (!oa)
101                 return 0;
102
103 /*      printf("Should return an array with %ld element(s)\n",size);*/
104         /*pos--;*/
105         
106         for(resultPos=0;size>0;size--,el++,resultPos++) {
107                 java_objectheader *element;
108
109                 if (el->method==0) {
110                         resultPos--;
111                         continue;
112                 }
113
114                 element=builtin_new(c);
115                 if (!element) {
116                         panic("Memory for stack trace element could not be allocated");
117                 }
118 #ifdef __GNUC__
119 #warning call constructor once jni is fixed to allow more than three parameters
120 #endif
121 #if 0
122                 (*env)->CallVoidMethod(env,element,m,
123                         javastring_new(el->method->class->sourcefile),
124                         source[size].linenumber,
125                         javastring_new(el->method->class->name),
126                         javastring_new(el->method->name),
127                         el->method->flags & ACC_NATIVE);
128 #else
129                 if (!(el->method->flags & ACC_NATIVE))setfield_critical(c,element,"fileName",          
130                 "Ljava/lang/String;",  jobject, 
131                 (jobject) javastring_new(el->method->class->sourcefile));
132 /*              setfield_critical(c,element,"className",          "Ljava/lang/String;",  jobject,  */
133 /*              (jobject) javastring_new(el->method->class->name)); */
134                 setfield_critical(c,element,"declaringClass",          "Ljava/lang/String;",  jobject, 
135                 (jobject) Java_java_lang_VMClass_getName(env, NULL, (java_lang_Class *) el->method->class));
136                 setfield_critical(c,element,"methodName",          "Ljava/lang/String;",  jobject, 
137                 (jobject) javastring_new(el->method->name));
138                 setfield_critical(c,element,"lineNumber",          "I",  jint, 
139                 (jint) ((el->method->flags & ACC_NATIVE) ? -1:(el->linenumber)));
140                 setfield_critical(c,element,"isNative",          "Z",  jboolean, 
141                 (jboolean) ((el->method->flags & ACC_NATIVE) ? 1:0));
142
143
144 #endif                  
145
146                 oa->data[resultPos]=element;
147         }
148
149         return oa;
150
151 }
152
153
154 /*
155  * Class:     java/lang/VMThrowable
156  * Method:    getStackTrace
157  * Signature: (Ljava/lang/Throwable;)[Ljava/lang/StackTraceElement;
158  */
159 JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMThrowable_getStackTrace(JNIEnv *env, java_lang_VMThrowable *this, java_lang_Throwable *par1)
160 {
161 #if defined(__I386__) || defined(__ALPHA__)
162         stackTraceBuffer *buf=(stackTraceBuffer*)this->vmData;
163         u8 size;
164         stacktraceelement *el;
165         classinfo  *excClass=par1->header.vftbl->class;
166         utf*  init=utf_new_char("<init>");
167         utf*  throwable=utf_new_char("java/lang/Throwable");
168         long destElementCount;
169         stacktraceelement *tmpEl;
170
171         if (!buf) panic("Invalid java.lang.VMThrowable.vmData field in java.lang.VMThrowable.getStackTrace native code");
172         
173         size=buf->full;
174         if (size<=2) panic("Invalid java.lang.VMThrowable.vmData field in java.lang.VMThrowable.getStackTrace native code (length<=2)");
175         size -=2;
176         el=&(buf->start[2]); /* element 0==VMThrowable.fillInStackTrace native call, 1==Throwable.fillInStackTrace*/
177         if (el->method!=0) { /* => not a builtin native wrapper*/
178                 if ((el->method->class->name==throwable) && (el->method->name == init) ){
179                         /* We assume that we are within the initializer of the exception object, the exception object itself should not appear
180                                 in the stack trace, so we skip till we reach the first function, which is not an init function or till we reach the exception object class*/
181                         for (; (size>0) && (el->method->name==init) && (el->method->class!=excClass); el++, size--) {
182                                 /* just loop*/
183                         }
184                         size --;
185                         el++;
186                         if (size<1) {
187                                 log_text("Invalid stacktrace for VMThrowable.getStackTrace()");
188                         }
189                 }
190         }
191
192         
193         for (destElementCount = 0, tmpEl=el; size>0; size--,tmpEl++) {
194                 if (tmpEl->method!=0) destElementCount++;
195         }
196
197         return generateStackTraceArray(env,el,destElementCount);
198 #else
199         return 0;
200 #endif
201 }
202
203
204 /*
205  * These are local overrides for various environment variables in Emacs.
206  * Please do not remove this and leave it at the end of the file, where
207  * Emacs will automagically detect them.
208  * ---------------------------------------------------------------------
209  * Local variables:
210  * mode: c
211  * indent-tabs-mode: t
212  * c-basic-offset: 4
213  * tab-width: 4
214  * End:
215  */