CACAO
trace.cpp
Go to the documentation of this file.
1 /* src/vm/jit/trace.cpp - Functions for tracing from java code.
2 
3  Copyright (C) 1996-2013
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/jit/trace.hpp"
26 #include <cstdio>
27 #include "config.h" // for ENABLE_DEBUG_FILTER, etc
28 #include "md-abi.hpp"
29 #include "native/llni.hpp"
30 #include "threads/thread.hpp" // for threadobject
31 #include "toolbox/logging.hpp"
32 #include "toolbox/buffer.hpp" // for Buffer
33 #include "vm/array.hpp"
34 #include "vm/class.hpp" // for classinfo
35 #include "vm/descriptor.hpp" // for methoddesc, typedesc
36 #include "vm/global.hpp" // for imm_union, java_object_t, etc
37 #include "vm/globals.hpp" // for class_java_lang_Class, etc
38 #include "vm/hook.hpp" // for method_enter, method_exit
39 #include "vm/javaobjects.hpp" // for java_lang_Throwable, etc
40 #include "vm/jit/argument.hpp" // for argument_jitarray_load, etc
41 #include "vm/jit/code.hpp" // for codeinfo
43 #include "vm/jit/show.hpp"
44 #include "vm/method.hpp" // for methodinfo, etc
45 #include "vm/options.hpp" // for opt_TraceBuiltinCalls, etc
46 #include "vm/string.hpp" // for JavaString
47 #include "vm/types.hpp" // for s4
48 #include "vm/utf8.hpp" // for Utf8String
49 #include "vm/vftbl.hpp" // for vftbl_t
50 
51 #if !defined(NDEBUG)
52 
53 /* trace_java_call_print_argument **********************************************
54 
55  XXX: Document me!
56 
57 *******************************************************************************/
58 
59 static void trace_java_call_print_argument(Buffer<>& logtext, methodinfo *m, typedesc *paramtype, imm_union imu)
60 {
61  java_object_t *o;
62  classinfo *c;
63  Utf8String u;
64 
65  switch (paramtype->type) {
66  case TYPE_INT:
67  logtext.write_dec(imu.i).write(" (").write_hex(imu.i).write(')');
68  break;
69  case TYPE_LNG:
70  logtext.write_dec(imu.l).write(" (").write_hex(imu.l).write(')');
71  break;
72  case TYPE_FLT:
73  logtext.write_dec(imu.f).write(" (").write_hex(imu.f).write(')');
74  break;
75  case TYPE_DBL:
76  logtext.write_dec(imu.d).write(" (").write_hex(imu.d).write(')');
77  break;
78 
79  case TYPE_ADR:
80  logtext.write_ptr(imu.a);
81 
82  /* Workaround for sun.misc.Unsafe methods. In the future
83  (exact GC) we should check if the address is on the GC
84  heap. */
85 
86  if ((m->clazz != NULL) &&
87  (m->clazz->name == Utf8String::from_utf8("sun/misc/Unsafe")))
88  break;
89 
90  /* Cast to java.lang.Object. */
91 
92  o = (java_handle_t*) (uintptr_t) imu.l;
93 
94  /* Check return argument for java.lang.Class or
95  java.lang.String. */
96 
97  if (o != NULL) {
98  if (o->vftbl->clazz == class_java_lang_String) {
99  /* convert java.lang.String object to utf8 string and strcat it to the logtext */
100 
101  logtext.write(" (String = \"")
102  .write(o)
103  .write("\")");
104  }
105  else {
106  if (o->vftbl->clazz == class_java_lang_Class) {
107  /* if the object returned is a java.lang.Class
108  cast it to classinfo structure and get the name
109  of the class */
110 
111  c = (classinfo *) o;
112 
113  u = c->name;
114  }
115  else {
116  /* if the object returned is not a java.lang.String or
117  a java.lang.Class just print the name of the class */
118 
119  u = o->vftbl->clazz->name;
120  }
121 
122  /* strcat to the logtext */
123 
124  logtext.write(" (Class = \"")
126  .write("\")");
127  }
128  }
129  break;
130  default:
131  assert(false);
132  break;
133  }
134 }
135 
136 /* trace_java_call_enter ******************************************************
137 
138  Traces an entry into a java method.
139 
140  arg_regs: Array containing all argument registers as int64_t values in
141  the same order as listed in m->methoddesc. The array is usually allocated
142  on the stack and used for restoring the argument registers later.
143 
144  stack: Pointer to first on stack argument in the same format passed to
145  asm_vm_call_method.
146 
147 *******************************************************************************/
148 
149 void trace_java_call_enter(methodinfo *m, uint64_t *arg_regs, uint64_t *stack)
150 {
151  methoddesc *md;
152  imm_union arg;
153  s4 i;
154 
155  /* We can only trace "slow" builtin functions (those with a stub)
156  * here, because the argument passing of "fast" ones happens via
157  * the native ABI and does not fit these functions. */
158 
159  if (method_is_builtin(m)) {
161  return;
162  }
163  else {
164  if (!opt_TraceJavaCalls)
165  return;
166 #if defined(ENABLE_DEBUG_FILTER)
168  return;
169 #endif
170  }
171 
172  // Hook point on entry into Java method.
174 
175  md = m->parseddesc;
176 
177  // Create new dump memory area.
178 // DumpMemoryArea dma;
179 
180  Buffer<> logtext(128);
181 
183 
184  logtext.writef("%10d ", TRACEJAVACALLCOUNT);
185  logtext.writef("-%d-", TRACEJAVACALLINDENT);
186 
187  for (i = 0; i < TRACEJAVACALLINDENT; i++)
188  logtext.write("\t");
189 
190  logtext.write("called: ");
191 
192  if (m->clazz != NULL)
193  logtext.write_slash_to_dot(m->clazz->name);
194  else
195  logtext.write("NULL");
196  logtext.write(".");
197  logtext.write(m->name);
198  logtext.write(m->descriptor);
199 
200  if (m->flags & ACC_PUBLIC) logtext.write(" PUBLIC");
201  if (m->flags & ACC_PRIVATE) logtext.write(" PRIVATE");
202  if (m->flags & ACC_PROTECTED) logtext.write(" PROTECTED");
203  if (m->flags & ACC_STATIC) logtext.write(" STATIC");
204  if (m->flags & ACC_FINAL) logtext.write(" FINAL");
205  if (m->flags & ACC_SYNCHRONIZED) logtext.write(" SYNCHRONIZED");
206  if (m->flags & ACC_VOLATILE) logtext.write(" VOLATILE");
207  if (m->flags & ACC_TRANSIENT) logtext.write(" TRANSIENT");
208  if (m->flags & ACC_NATIVE) logtext.write(" NATIVE");
209  if (m->flags & ACC_INTERFACE) logtext.write(" INTERFACE");
210  if (m->flags & ACC_ABSTRACT) logtext.write(" ABSTRACT");
211 
212  logtext.write("(");
213 
214  for (i = 0; i < md->paramcount; ++i) {
215  arg = argument_jitarray_load(md, i, arg_regs, stack);
216  trace_java_call_print_argument(logtext, m, &md->paramtypes[i], arg);
217 
218  if (i != (md->paramcount - 1)) {
219  logtext.write(", ");
220  }
221  }
222 
223  logtext.write(")");
224 
225  log_text(logtext.c_str());
226 
227  TRACEJAVACALLINDENT++;
228 }
229 
230 /* trace_java_call_exit ********************************************************
231 
232  Traces an exit form a java method.
233 
234  return_regs: Array of size 1 containing return register.
235  The array is usually allocated on the stack and used for restoring the
236  registers later.
237 
238 *******************************************************************************/
239 
240 void trace_java_call_exit(methodinfo *m, uint64_t *return_regs)
241 {
242  methoddesc *md;
243  s4 i;
244  imm_union val;
245 
246  /* We can only trace "slow" builtin functions (those with a stub)
247  * here, because the argument passing of "fast" ones happens via
248  * the native ABI and does not fit these functions. */
249 
250  if (method_is_builtin(m)) {
252  return;
253  }
254  else {
255  if (!opt_TraceJavaCalls)
256  return;
257 #if defined(ENABLE_DEBUG_FILTER)
259  return;
260 #endif
261  }
262 
263  // Hook point upon exit from Java method.
265 
266  md = m->parseddesc;
267 
268  /* outdent the log message */
269 
272  else
273  log_text("trace_java_call_exit: WARNING: unmatched unindent");
274 
275  // Create new dump memory area.
276 // DumpMemoryArea dma;
277 
278  Buffer<> logtext(128);
279 
280  /* generate the message */
281 
282  logtext.write(" ");
283  logtext.writef("-%d-", TRACEJAVACALLINDENT);
284 
285  for (i = 0; i < TRACEJAVACALLINDENT; i++)
286  logtext.write("\t");
287 
288  logtext.write("finished: ");
289  if (m->clazz != NULL)
290  logtext.write_slash_to_dot(m->clazz->name);
291  else
292  logtext.write("NULL");
293  logtext.write(".");
294  logtext.write(m->name);
295  logtext.write(m->descriptor);
296 
297  if (!IS_VOID_TYPE(md->returntype.type)) {
298  logtext.write("->");
299  val = argument_jitreturn_load(md, return_regs);
300 
301  trace_java_call_print_argument(logtext, m, &md->returntype, val);
302  }
303 
304  log_text(logtext.c_str());
305 }
306 
307 
308 /* trace_exception *************************************************************
309 
310  Traces an exception which is handled by exceptions_handle_exception.
311 
312 *******************************************************************************/
313 
315 {
316  codeinfo *code;
317 
318  // Create new dump memory area.
319 // DumpMemoryArea dma;
320 
321  Buffer<> logtext(128);
322 
323  if (xptr) {
324  logtext.write("Exception ");
325  logtext.write_slash_to_dot(xptr->vftbl->clazz->name);
326 
327  } else {
328  logtext.write("Some Throwable");
329  }
330 
331  logtext.write(" thrown in ");
332 
333  if (m) {
334  logtext.write_slash_to_dot(m->clazz->name);
335  logtext.write(".");
336  logtext.write(m->name);
337  logtext.write(m->descriptor);
338 
339  if (m->flags & ACC_SYNCHRONIZED)
340  logtext.write("(SYNC");
341  else
342  logtext.write("(NOSYNC");
343 
344  if (m->flags & ACC_NATIVE) {
345  logtext.write(",NATIVE");
346 
347  code = m->code;
348 
349  logtext.write(")(").write_ptr(code->entrypoint)
350  .write(") at position ").write_ptr(pos);
351  } else {
352 
353  /* XXX preliminary: This should get the actual codeinfo */
354  /* in which the exception happened. */
355  code = m->code;
356 
357  logtext.write(")(").write_ptr(code->entrypoint)
358  .write(") at position ").write_ptr(pos);
359 
360  if (m->clazz->sourcefile == NULL)
361  logtext.write("<NO CLASSFILE INFORMATION>");
362  else
363  logtext.write(m->clazz->sourcefile);
364 
365  logtext.writef(":%d)", 0);
366  }
367 
368  } else
369  logtext.write("call_java_method");
370 
371  log_text(logtext.c_str());
372 }
373 
374 
375 /* trace_exception_builtin *****************************************************
376 
377  Traces an exception which is thrown by builtin_throw_exception.
378 
379 *******************************************************************************/
380 
382 {
383  java_lang_Throwable jlt(h);
384 
385  // Get detail message.
386  java_handle_t* s = NULL;
387 
388  if (jlt.get_handle() != NULL)
389  s = jlt.get_detailMessage();
390 
391  java_lang_String jls(s);
392 
393  // Create new dump memory area.
394 // DumpMemoryArea dma;
395 
396  Buffer<> logtext(128);
397 
398  logtext.write("Builtin exception thrown: ");
399 
400  if (jlt.get_handle()) {
401  logtext.write_slash_to_dot(jlt.get_vftbl()->clazz->name);
402 
403  if (s) {
404  logtext.write(": ");
405  logtext.write(JavaString(jls.get_handle()));
406  }
407 
408  } else {
409  logtext.write("(nil)");
410  }
411 
412  log_text(logtext.c_str());
413 }
414 
415 #endif /* !defined(NDEBUG) */
416 
417 
418 /*
419  * These are local overrides for various environment variables in Emacs.
420  * Please do not remove this and leave it at the end of the file, where
421  * Emacs will automagically detect them.
422  * ---------------------------------------------------------------------
423  * Local variables:
424  * mode: c++
425  * indent-tabs-mode: t
426  * c-basic-offset: 4
427  * tab-width: 4
428  * End:
429  * vim:noexpandtab:sw=4:ts=4:
430  */
void trace_exception_builtin(java_handle_t *h)
Definition: trace.cpp:381
Utf8String name
Definition: method.hpp:71
imm_union argument_jitreturn_load(methoddesc *md, uint64_t *return_regs)
Definition: argument.cpp:153
float f
Definition: global.hpp:56
virtual java_handle_t * get_handle() const
double d
Definition: global.hpp:57
imm_union argument_jitarray_load(methoddesc *md, int32_t index, uint64_t *arg_regs, uint64_t *stack)
Definition: argument.cpp:57
static bool method_is_builtin(methodinfo *m)
Definition: method.hpp:189
static void trace_java_call_print_argument(Buffer<> &logtext, methodinfo *m, typedesc *paramtype, imm_union imu)
Definition: trace.cpp:59
Buffer & write_ptr(void *)
write address of pointer as hex to buffer
Definition: buffer.hpp:361
void * a
Definition: global.hpp:58
vftbl_t * get_vftbl() const
#define IS_VOID_TYPE(a)
Definition: global.hpp:140
int opt_TraceJavaCalls
Definition: options.cpp:213
const char * c_str()
get contents of buffer as zero-terminated c-style-string This strings lifetime is tied to it&#39;s buffer...
Definition: buffer.hpp:489
#define TRACEJAVACALLCOUNT
Definition: thread.hpp:191
void trace_java_call_exit(methodinfo *m, uint64_t *return_regs)
Definition: trace.cpp:240
Buffer & write_hex(s4)
write number to buffer as hexadecimal
Definition: buffer.hpp:386
void method_exit(methodinfo *m)
Definition: hook.hpp:115
Buffer & write_slash_to_dot(const char *)
write to buffer, replacing &#39;/&#39; by &#39;.&#39;
Definition: buffer.hpp:297
typedesc paramtypes[1]
Definition: descriptor.hpp:167
int opt_TraceBuiltinCalls
Definition: options.cpp:206
void trace_java_call_enter(methodinfo *m, uint64_t *arg_regs, uint64_t *stack)
Definition: trace.cpp:149
Utf8String descriptor
Definition: method.hpp:72
JNIEnv void * arg
Definition: jvmti.h:405
int show_filters_test_verbosecall_exit(methodinfo *m)
Definition: show.cpp:1597
classinfo * clazz
Definition: method.hpp:80
alloc::list< PassInfo::IDTy >::type & stack
Utf8String name
Definition: class.hpp:91
classinfo * clazz
Definition: vftbl.hpp:100
classinfo * class_java_lang_Class
Definition: globals.cpp:35
static Utf8String from_utf8(const char *, size_t)
Definition: utf8.cpp:335
MIIterator i
typedesc returntype
Definition: descriptor.hpp:166
int32_t s4
Definition: types.hpp:45
MIIterator pos
GNU Classpath java/lang/Throwable.
Utf8String sourcefile
Definition: class.hpp:133
codeinfo * code
Definition: method.hpp:103
classinfo * class_java_lang_String
Definition: globals.cpp:39
methoddesc * parseddesc
Definition: method.hpp:78
GNU Classpath java/lang/String.
int show_filters_test_verbosecall_enter(methodinfo *m)
Definition: show.cpp:1572
Buffer & write(char)
Definition: buffer.hpp:280
#define TRACEJAVACALLINDENT
Definition: thread.hpp:190
java_handle_t * get_detailMessage() const
void method_enter(methodinfo *m)
Definition: hook.hpp:110
Buffer & write_dec(s4)
write number to buffer as decimal
Definition: buffer.hpp:366
Buffer & writef(const char *fmt,...)
Definition: buffer.hpp:426
s4 flags
Definition: method.hpp:70
vftbl_t * vftbl
Definition: global.hpp:264
#define log_text(s)
Definition: logging.hpp:170
void trace_exception(java_object_t *xptr, methodinfo *m, void *pos)
Definition: trace.cpp:314
u1 * entrypoint
Definition: code.hpp:84
#define xptr
Definition: md-asm.hpp:50