1 /* src/vm/jit/trace.c - Functions for tracing from java code.
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
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.
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.
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
32 #include "mm/memory.h"
34 #include "native/jni.h"
35 #include "native/llni.h"
37 #include "native/include/java_lang_String.h"
38 #include "native/include/java_lang_Throwable.h"
40 #include "threads/threads-common.h"
42 #include "toolbox/logging.h"
44 #include "vm/global.h"
45 #include "vm/stringlocal.h"
46 #include "vm/jit/argument.h"
47 #include "vm/jit/codegen-common.h"
48 #include "vm/jit/trace.h"
49 #include "vm/jit/show.h"
51 #include "vmcore/options.h"
52 #include "vmcore/utf8.h"
58 /* global variables ***********************************************************/
60 #if !defined(ENABLE_THREADS)
61 s4 _no_threads_tracejavacallindent = 0;
62 u4 _no_threads_tracejavacallcount= 0;
66 /* trace_java_call_print_argument **********************************************
70 *******************************************************************************/
72 static char *trace_java_call_print_argument(char *logtext, s4 *logtextlen,
73 typedesc *paramtype, imm_union imu)
80 switch (paramtype->type) {
82 sprintf(logtext + strlen(logtext), "%d (0x%08x)", (int32_t)imu.l, (int32_t)imu.l);
86 #if SIZEOF_VOID_P == 4
87 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
89 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
94 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
98 #if SIZEOF_VOID_P == 4
99 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
101 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
106 #if SIZEOF_VOID_P == 4
107 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) imu.l);
109 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) imu.l);
112 /* cast to java.lang.Object */
114 o = (java_object_t *) (ptrint) imu.l;
116 /* check return argument for java.lang.Class or java.lang.String */
119 if (o->vftbl->class == class_java_lang_String) {
120 /* get java.lang.String object and the length of the
123 u = javastring_toutf(o, false);
125 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
127 /* realloc memory for string length */
129 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
132 /* convert to utf8 string and strcat it to the logtext */
134 strcat(logtext, " (String = \"");
136 strcat(logtext, "\")");
139 if (o->vftbl->class == class_java_lang_Class) {
140 /* if the object returned is a java.lang.Class
141 cast it to classinfo structure and get the name
149 /* if the object returned is not a java.lang.String or
150 a java.lang.Class just print the name of the class */
152 u = o->vftbl->class->name;
155 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
157 /* realloc memory for string length */
159 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
162 /* strcat to the logtext */
164 strcat(logtext, " (Class = \"");
165 utf_cat_classname(logtext, u);
166 strcat(logtext, "\")");
174 /* trace_java_call_enter ******************************************************
176 Traces an entry into a java method.
178 arg_regs: Array containing all argument registers as int64_t values in
179 the same order as listed in m->methoddesc. The array is usually allocated
180 on the stack and used for restoring the argument registers later.
182 stack: Pointer to first on stack argument in the same format passed to
185 *******************************************************************************/
187 void trace_java_call_enter(methodinfo *m, uint64_t *arg_regs, uint64_t *stack)
197 #if defined(ENABLE_DEBUG_FILTER)
198 if (!show_filters_test_verbosecall_enter(m))
202 #if defined(ENABLE_VMLOG)
203 vmlog_cacao_enter_method(m);
209 /* calculate message length */
212 strlen("4294967295 ") +
213 strlen("-2147483647-") + /* INT_MAX should be sufficient */
214 TRACEJAVACALLINDENT +
216 ((m->class == NULL) ? strlen("NULL") : utf_bytes(m->class->name)) +
219 utf_bytes(m->descriptor);
221 /* Actually it's not possible to have all flags printed, but:
227 strlen(" PROTECTED") +
230 strlen(" SYNCHRONIZED") +
231 strlen(" VOLATILE") +
232 strlen(" TRANSIENT") +
234 strlen(" INTERFACE") +
235 strlen(" ABSTRACT") +
236 strlen(" METHOD_BUILTIN");
238 /* add maximal argument length */
242 strlen("-9223372036854775808 (0x123456789abcdef0), ") * md->paramcount +
246 /* allocate memory */
250 logtext = DMNEW(char, logtextlen);
252 TRACEJAVACALLCOUNT++;
254 sprintf(logtext, "%10d ", TRACEJAVACALLCOUNT);
255 sprintf(logtext + strlen(logtext), "-%d-", TRACEJAVACALLINDENT);
257 pos = strlen(logtext);
259 for (i = 0; i < TRACEJAVACALLINDENT; i++)
260 logtext[pos++] = '\t';
262 strcpy(logtext + pos, "called: ");
264 if (m->class != NULL)
265 utf_cat_classname(logtext, m->class->name);
267 strcat(logtext, "NULL");
268 strcat(logtext, ".");
269 utf_cat(logtext, m->name);
270 utf_cat(logtext, m->descriptor);
272 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
273 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
274 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
275 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
276 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
277 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
278 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
279 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
280 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
281 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
282 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
283 if (m->flags & ACC_METHOD_BUILTIN) strcat(logtext, " METHOD_BUILTIN");
285 strcat(logtext, "(");
287 for (i = 0; i < md->paramcount; ++i) {
288 arg = argument_jitarray_load(md, i, arg_regs, stack);
289 logtext = trace_java_call_print_argument(
290 logtext, &logtextlen, &md->paramtypes[i], arg
292 if (i != (md->paramcount - 1)) {
293 strcat(logtext, ", ");
297 strcat(logtext, ")");
305 TRACEJAVACALLINDENT++;
309 /* trace_java_call_exit ********************************************************
311 Traces an exit form a java method.
313 return_regs: Array of size 1 containing return register.
314 The array is usually allocated on the stack and used for restoring the
317 *******************************************************************************/
319 void trace_java_call_exit(methodinfo *m, uint64_t *return_regs)
329 #if defined(ENABLE_DEBUG_FILTER)
330 if (!show_filters_test_verbosecall_exit(m))
334 #if defined(ENABLE_VMLOG)
335 vmlog_cacao_leave_method(m);
341 /* outdent the log message */
343 if (TRACEJAVACALLINDENT)
344 TRACEJAVACALLINDENT--;
346 log_text("trace_java_call_exit: WARNING: unmatched unindent");
348 /* calculate message length */
351 strlen("4294967295 ") +
352 strlen("-2147483647-") + /* INT_MAX should be sufficient */
353 TRACEJAVACALLINDENT +
354 strlen("finished: ") +
355 ((m->class == NULL) ? strlen("NULL") : utf_bytes(m->class->name)) +
358 utf_bytes(m->descriptor) +
359 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
361 /* add maximal argument length */
363 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
365 /* allocate memory */
369 logtext = DMNEW(char, logtextlen);
371 /* generate the message */
373 sprintf(logtext, " ");
374 sprintf(logtext + strlen(logtext), "-%d-", TRACEJAVACALLINDENT);
376 pos = strlen(logtext);
378 for (i = 0; i < TRACEJAVACALLINDENT; i++)
379 logtext[pos++] = '\t';
381 strcpy(logtext + pos, "finished: ");
382 if (m->class != NULL)
383 utf_cat_classname(logtext, m->class->name);
385 strcat(logtext, "NULL");
386 strcat(logtext, ".");
387 utf_cat(logtext, m->name);
388 utf_cat(logtext, m->descriptor);
390 if (!IS_VOID_TYPE(md->returntype.type)) {
391 strcat(logtext, "->");
392 val = argument_jitreturn_load(md, return_regs);
395 trace_java_call_print_argument(logtext, &logtextlen, &md->returntype, val);
406 /* trace_exception *************************************************************
408 Traces an exception which is handled by exceptions_handle_exception.
410 *******************************************************************************/
412 void trace_exception(java_object_t *xptr, methodinfo *m, void *pos)
419 /* calculate message length */
423 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
426 logtextlen = strlen("Some Throwable");
429 logtextlen += strlen(" thrown in ");
433 utf_bytes(m->class->name) +
436 utf_bytes(m->descriptor) +
437 strlen("(NOSYNC,NATIVE");
439 #if SIZEOF_VOID_P == 8
441 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
443 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
446 if (m->class->sourcefile == NULL)
447 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
449 logtextlen += utf_bytes(m->class->sourcefile);
451 logtextlen += strlen(":65536)");
455 logtextlen += strlen("call_java_method");
458 logtextlen += strlen("0");
460 /* allocate memory */
464 logtext = DMNEW(char, logtextlen);
467 strcpy(logtext, "Exception ");
468 utf_cat_classname(logtext, xptr->vftbl->class->name);
471 strcpy(logtext, "Some Throwable");
474 strcat(logtext, " thrown in ");
477 utf_cat_classname(logtext, m->class->name);
478 strcat(logtext, ".");
479 utf_cat(logtext, m->name);
480 utf_cat(logtext, m->descriptor);
482 if (m->flags & ACC_SYNCHRONIZED)
483 strcat(logtext, "(SYNC");
485 strcat(logtext, "(NOSYNC");
487 if (m->flags & ACC_NATIVE) {
488 strcat(logtext, ",NATIVE");
492 #if SIZEOF_VOID_P == 8
493 sprintf(logtext + strlen(logtext),
494 ")(0x%016lx) at position 0x%016lx",
495 (ptrint) code->entrypoint, (ptrint) pos);
497 sprintf(logtext + strlen(logtext),
498 ")(0x%08x) at position 0x%08x",
499 (ptrint) code->entrypoint, (ptrint) pos);
504 /* XXX preliminary: This should get the actual codeinfo */
505 /* in which the exception happened. */
508 #if SIZEOF_VOID_P == 8
509 sprintf(logtext + strlen(logtext),
510 ")(0x%016lx) at position 0x%016lx (",
511 (ptrint) code->entrypoint, (ptrint) pos);
513 sprintf(logtext + strlen(logtext),
514 ")(0x%08x) at position 0x%08x (",
515 (ptrint) code->entrypoint, (ptrint) pos);
518 if (m->class->sourcefile == NULL)
519 strcat(logtext, "<NO CLASSFILE INFORMATION>");
521 utf_cat(logtext, m->class->sourcefile);
523 sprintf(logtext + strlen(logtext), ":%d)", 0);
527 strcat(logtext, "call_java_method");
537 /* trace_exception_builtin *****************************************************
539 Traces an exception which is thrown by builtin_throw_exception.
541 *******************************************************************************/
543 void trace_exception_builtin(java_object_t *xptr)
545 java_lang_Throwable *t;
551 t = (java_lang_Throwable *) xptr;
553 /* get detail message */
555 LLNI_field_get_ref(t, detailMessage, s);
557 /* calculate message length */
559 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
563 utf_bytes(xptr->vftbl->class->name);
565 logtextlen += strlen(": ") +
566 u2_utflength(LLNI_field_direct(s, value)->data
567 + LLNI_field_direct(s, offset),
568 LLNI_field_direct(s,count));
572 logtextlen += strlen("(nil)");
575 /* allocate memory */
579 logtext = DMNEW(char, logtextlen);
581 strcpy(logtext, "Builtin exception thrown: ");
584 utf_cat_classname(logtext, xptr->vftbl->class->name);
589 buf = javastring_tochar((java_handle_t *) s);
590 strcat(logtext, ": ");
591 strcat(logtext, buf);
592 MFREE(buf, char, strlen(buf) + 1);
596 strcat(logtext, "(nil)");
607 #endif /* !defined(NDEBUG) */
611 * These are local overrides for various environment variables in Emacs.
612 * Please do not remove this and leave it at the end of the file, where
613 * Emacs will automagically detect them.
614 * ---------------------------------------------------------------------
617 * indent-tabs-mode: t
621 * vim:noexpandtab:sw=4:ts=4: