1 /* src/vm/jit/trace.c - Functions for tracing from java code.
3 Copyright (C) 1996-2005, 2006, 2007 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
8 This file is part of CACAO.
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.
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.
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
25 $Id: trace.c 8348 2007-08-19 09:27:03Z pm $
34 #include "mm/memory.h"
36 #if defined(ENABLE_THREADS)
37 #include "threads/native/threads.h"
39 #include "threads/none/threads.h"
42 #include "toolbox/logging.h"
44 #include "vm/global.h"
45 #include "vm/stringlocal.h"
46 #include "vm/jit/codegen-common.h"
47 #include "vm/jit/trace.h"
48 #include "vm/jit/show.h"
50 #include "vmcore/utf8.h"
56 #if !defined(ENABLE_THREADS)
57 s4 _no_threads_tracejavacallindent = 0;
58 u4 _no_threads_tracejavacallcount= 0;
61 /* _array_load_param **********************************************************
63 Returns the argument specified by pd and td from one of the passed arrays
66 *******************************************************************************/
68 static imm_union _array_load_param(paramdesc *pd, typedesc *td, uint64_t *arg_regs, uint64_t *stack) {
75 #if (SIZEOF_VOID_P == 8)
76 ret.l = (int64_t)stack[pd->index];
78 ret.l = *(int32_t *)(stack + pd->index);
81 ret.l = arg_regs[pd->index];
86 ret.l = (int64_t)stack[pd->index];
88 #if (SIZEOF_VOID_P == 8)
89 ret.l = (int64_t)arg_regs[pd->index];
92 (arg_regs[GET_HIGH_REG(pd->index)] << 32) |
93 (arg_regs[GET_LOW_REG(pd->index)] & 0xFFFFFFFF)
100 ret.l = (int64_t)stack[pd->index];
102 ret.l = (int64_t)arg_regs[pd->index + INT_ARG_CNT];
107 ret.l = (int64_t)stack[pd->index];
109 ret.l = (int64_t)arg_regs[pd->index + INT_ARG_CNT];
117 /* _array_load_return_value ***************************************************
119 Loads the proper return value form the return registers array and returns it.
121 *******************************************************************************/
123 static imm_union _array_load_return_value(typedesc *td, uint64_t *return_regs) {
129 ret.l = return_regs[0];
132 #if (SIZEOF_VOID_P == 8)
133 ret.l = (int64_t)return_regs[0];
136 (return_regs[0] << 32) | (return_regs[1] & 0xFFFFFFFF)
141 ret.l = (int64_t)return_regs[2];
144 ret.l = (int64_t)return_regs[2];
151 static char *trace_java_call_print_argument(char *logtext, s4 *logtextlen,
152 typedesc *paramtype, imm_union imu)
159 switch (paramtype->type) {
161 sprintf(logtext + strlen(logtext), "%d (0x%08x)", (int32_t)imu.l, (int32_t)imu.l);
165 #if SIZEOF_VOID_P == 4
166 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
168 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
173 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
177 #if SIZEOF_VOID_P == 4
178 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
180 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
185 #if SIZEOF_VOID_P == 4
186 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) imu.l);
188 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) imu.l);
191 /* cast to java.lang.Object */
193 o = (java_handle_t *) (ptrint) imu.l;
195 /* check return argument for java.lang.Class or java.lang.String */
198 if (o->vftbl->class == class_java_lang_String) {
199 /* get java.lang.String object and the length of the
202 u = javastring_toutf(o, false);
204 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
206 /* realloc memory for string length */
208 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
211 /* convert to utf8 string and strcat it to the logtext */
213 strcat(logtext, " (String = \"");
215 strcat(logtext, "\")");
218 if (o->vftbl->class == class_java_lang_Class) {
219 /* if the object returned is a java.lang.Class
220 cast it to classinfo structure and get the name
228 /* if the object returned is not a java.lang.String or
229 a java.lang.Class just print the name of the class */
231 u = o->vftbl->class->name;
234 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
236 /* realloc memory for string length */
238 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
241 /* strcat to the logtext */
243 strcat(logtext, " (Class = \"");
244 utf_cat_classname(logtext, u);
245 strcat(logtext, "\")");
253 /* trace_java_call_enter ******************************************************
255 Traces an entry into a java method.
257 arg_regs: Array of size ARG_CNT containing all argument registers in
258 the same format as in asm_vm_call_method. The array is usually allocated
259 on the stack and used for restoring the argument registers later.
261 stack: Pointer to first on stack argument in the same format passed to
264 *******************************************************************************/
266 void trace_java_call_enter(methodinfo *m, uint64_t *arg_regs, uint64_t *stack) {
277 #if defined(ENABLE_DEBUG_FILTER)
278 if (! show_filters_test_verbosecall_enter(m)) return;
281 #if defined(ENABLE_VMLOG)
282 vmlog_cacao_enter_method(m);
288 /* calculate message length */
291 strlen("4294967295 ") +
292 strlen("-2147483647-") + /* INT_MAX should be sufficient */
293 TRACEJAVACALLINDENT +
295 utf_bytes(m->class->name) +
298 utf_bytes(m->descriptor);
300 /* Actually it's not possible to have all flags printed, but:
306 strlen(" PROTECTED") +
309 strlen(" SYNCHRONIZED") +
310 strlen(" VOLATILE") +
311 strlen(" TRANSIENT") +
313 strlen(" INTERFACE") +
316 /* add maximal argument length */
320 strlen("-9223372036854775808 (0x123456789abcdef0), ") * md->paramcount +
324 /* allocate memory */
326 dumpsize = dump_size();
328 logtext = DMNEW(char, logtextlen);
330 TRACEJAVACALLCOUNT++;
332 sprintf(logtext, "%10d ", TRACEJAVACALLCOUNT);
333 sprintf(logtext + strlen(logtext), "-%d-", TRACEJAVACALLINDENT);
335 pos = strlen(logtext);
337 for (i = 0; i < TRACEJAVACALLINDENT; i++)
338 logtext[pos++] = '\t';
340 strcpy(logtext + pos, "called: ");
342 utf_cat_classname(logtext, m->class->name);
343 strcat(logtext, ".");
344 utf_cat(logtext, m->name);
345 utf_cat(logtext, m->descriptor);
347 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
348 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
349 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
350 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
351 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
352 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
353 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
354 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
355 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
356 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
357 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
359 strcat(logtext, "(");
361 for (i = 0; i < md->paramcount; ++i) {
363 td = &md->paramtypes[i];
364 arg = _array_load_param(pd, td, arg_regs, stack);
365 logtext = trace_java_call_print_argument(
366 logtext, &logtextlen, td, arg
368 if (i != (md->paramcount - 1)) {
369 strcat(logtext, ", ");
373 strcat(logtext, ")");
379 dump_release(dumpsize);
381 TRACEJAVACALLINDENT++;
385 /* trace_java_call_exit ********************************************************
387 Traces an exit form a java method.
389 return_regs: Array of size 3 containing return registers:
391 [1] : REG_RESULT2 (if available on architecture)
393 The array is usually allocated on the stack and used for restoring the
394 registers later. The format of the array is the same as the format of
395 register arguments passed to asm_vm_call_method.
397 *******************************************************************************/
399 void trace_java_call_exit(methodinfo *m, uint64_t *return_regs)
409 #if defined(ENABLE_DEBUG_FILTER)
410 if (! show_filters_test_verbosecall_exit(m)) return;
413 #if defined(ENABLE_VMLOG)
414 vmlog_cacao_leave_method(m);
420 /* calculate message length */
423 strlen("4294967295 ") +
424 strlen("-2147483647-") + /* INT_MAX should be sufficient */
425 TRACEJAVACALLINDENT +
426 strlen("finished: ") +
427 utf_bytes(m->class->name) +
430 utf_bytes(m->descriptor) +
431 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
433 /* add maximal argument length */
435 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
437 /* allocate memory */
439 dumpsize = dump_size();
441 logtext = DMNEW(char, logtextlen);
443 /* outdent the log message */
445 if (TRACEJAVACALLINDENT)
446 TRACEJAVACALLINDENT--;
448 log_text("WARNING: unmatched TRACEJAVACALLINDENT--");
450 /* generate the message */
452 sprintf(logtext, " ");
453 sprintf(logtext + strlen(logtext), "-%d-", TRACEJAVACALLINDENT);
455 pos = strlen(logtext);
457 for (i = 0; i < TRACEJAVACALLINDENT; i++)
458 logtext[pos++] = '\t';
460 strcpy(logtext + pos, "finished: ");
461 utf_cat_classname(logtext, m->class->name);
462 strcat(logtext, ".");
463 utf_cat(logtext, m->name);
464 utf_cat(logtext, m->descriptor);
466 if (!IS_VOID_TYPE(md->returntype.type)) {
467 strcat(logtext, "->");
468 val = _array_load_return_value(&md->returntype, return_regs);
471 trace_java_call_print_argument(logtext, &logtextlen, &md->returntype, val);
478 dump_release(dumpsize);
482 #endif /* !defined(NDEBUG) */
485 * These are local overrides for various environment variables in Emacs.
486 * Please do not remove this and leave it at the end of the file, where
487 * Emacs will automagically detect them.
488 * ---------------------------------------------------------------------
491 * indent-tabs-mode: t
495 * vim:noexpandtab:sw=4:ts=4: