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 8304 2007-08-14 19:57:20Z pm $
32 #include "mm/memory.h"
34 #if defined(ENABLE_THREADS)
35 #include "threads/native/threads.h"
37 #include "threads/none/threads.h"
40 #include "toolbox/logging.h"
42 #include "vm/global.h"
43 #include "vm/stringlocal.h"
44 #include "vm/jit/codegen-common.h"
45 #include "vm/jit/trace.h"
46 #include "vm/jit/show.h"
48 #include "vmcore/utf8.h"
54 #if !defined(ENABLE_THREADS)
55 s4 _no_threads_tracejavacallindent = 0;
56 u4 _no_threads_tracejavacallcount= 0;
59 /* _array_load_param **********************************************************
61 Returns the argument specified by pd and td from one of the passed arrays
64 *******************************************************************************/
66 static imm_union _array_load_param(paramdesc *pd, typedesc *td, uint64_t *arg_regs, uint64_t *stack) {
73 #if (SIZEOF_VOID_P == 8)
74 ret.l = (int64_t)stack[pd->index + stack_offset];
76 ret.l = *(int32_t *)(stack + pd->index);
79 ret.l = arg_regs[pd->index];
84 ret.l = (int64_t)stack[pd->index];
86 #if (SIZEOF_VOID_P == 8)
87 ret.l = (int64_t)arg_regs[pd->index];
90 (arg_regs[GET_HIGH_REG(pd->index)] << 32) |
91 (arg_regs[GET_LOW_REG(pd->index)] & 0xFFFFFFFF)
98 ret.l = (int64_t)stack[pd->index];
100 ret.l = (int64_t)arg_regs[pd->index + INT_ARG_CNT];
105 ret.l = (int64_t)stack[pd->index];
107 ret.l = (int64_t)arg_regs[pd->index + INT_ARG_CNT];
115 /* _array_load_return_value ***************************************************
117 Loads the proper return value form the return registers array and returns it.
119 *******************************************************************************/
121 static imm_union _array_load_return_value(typedesc *td, uint64_t *return_regs) {
127 ret.l = return_regs[0];
130 #if (SIZEOF_VOID_P == 8)
131 ret.l = (int64_t)return_regs[0];
134 (return_regs[0] << 32) | (return_regs[1] & 0xFFFFFFFF)
139 ret.l = (int64_t)return_regs[2];
142 ret.l = (int64_t)return_regs[2];
149 static char *trace_java_call_print_argument(char *logtext, s4 *logtextlen,
150 typedesc *paramtype, imm_union imu)
157 switch (paramtype->type) {
159 sprintf(logtext + strlen(logtext), "%d (0x%08x)", (int32_t)imu.l, (int32_t)imu.l);
163 #if SIZEOF_VOID_P == 4
164 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
166 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
171 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
175 #if SIZEOF_VOID_P == 4
176 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
178 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
183 #if SIZEOF_VOID_P == 4
184 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) imu.l);
186 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) imu.l);
189 /* cast to java.lang.Object */
191 o = (java_handle_t *) (ptrint) imu.l;
193 /* check return argument for java.lang.Class or java.lang.String */
196 if (o->vftbl->class == class_java_lang_String) {
197 /* get java.lang.String object and the length of the
200 u = javastring_toutf(o, false);
202 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
204 /* realloc memory for string length */
206 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
209 /* convert to utf8 string and strcat it to the logtext */
211 strcat(logtext, " (String = \"");
213 strcat(logtext, "\")");
216 if (o->vftbl->class == class_java_lang_Class) {
217 /* if the object returned is a java.lang.Class
218 cast it to classinfo structure and get the name
226 /* if the object returned is not a java.lang.String or
227 a java.lang.Class just print the name of the class */
229 u = o->vftbl->class->name;
232 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
234 /* realloc memory for string length */
236 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
239 /* strcat to the logtext */
241 strcat(logtext, " (Class = \"");
242 utf_cat_classname(logtext, u);
243 strcat(logtext, "\")");
251 void trace_java_call_enter(methodinfo *m, uint64_t *arg_regs, uint64_t *stack) {
262 #if defined(ENABLE_DEBUG_FILTER)
263 if (! show_filters_test_verbosecall_enter(m)) return;
266 #if defined(ENABLE_VMLOG)
267 vmlog_cacao_enter_method(m);
273 /* calculate message length */
276 strlen("4294967295 ") +
277 strlen("-2147483647-") + /* INT_MAX should be sufficient */
278 TRACEJAVACALLINDENT +
280 utf_bytes(m->class->name) +
283 utf_bytes(m->descriptor);
285 /* Actually it's not possible to have all flags printed, but:
291 strlen(" PROTECTED") +
294 strlen(" SYNCHRONIZED") +
295 strlen(" VOLATILE") +
296 strlen(" TRANSIENT") +
298 strlen(" INTERFACE") +
301 /* add maximal argument length */
305 strlen("-9223372036854775808 (0x123456789abcdef0), ") * md->paramcount +
309 /* allocate memory */
311 dumpsize = dump_size();
313 logtext = DMNEW(char, logtextlen);
315 TRACEJAVACALLCOUNT++;
317 sprintf(logtext, "%10d ", TRACEJAVACALLCOUNT);
318 sprintf(logtext + strlen(logtext), "-%d-", TRACEJAVACALLINDENT);
320 pos = strlen(logtext);
322 for (i = 0; i < TRACEJAVACALLINDENT; i++)
323 logtext[pos++] = '\t';
325 strcpy(logtext + pos, "called: ");
327 utf_cat_classname(logtext, m->class->name);
328 strcat(logtext, ".");
329 utf_cat(logtext, m->name);
330 utf_cat(logtext, m->descriptor);
332 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
333 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
334 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
335 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
336 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
337 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
338 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
339 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
340 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
341 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
342 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
344 strcat(logtext, "(");
346 for (i = 0; i < md->paramcount; ++i) {
348 td = &md->paramtypes[i];
349 arg = _array_load_param(pd, td, arg_regs, stack);
350 logtext = trace_java_call_print_argument(
351 logtext, &logtextlen, td, arg
353 if (i != (md->paramcount - 1)) {
354 strcat(logtext, ", ");
358 strcat(logtext, ")");
364 dump_release(dumpsize);
366 TRACEJAVACALLINDENT++;
370 void trace_java_call_exit(methodinfo *m, uint64_t *return_regs)
380 #if defined(ENABLE_DEBUG_FILTER)
381 if (! show_filters_test_verbosecall_exit(m)) return;
384 #if defined(ENABLE_VMLOG)
385 vmlog_cacao_leave_method(m);
391 /* calculate message length */
394 strlen("4294967295 ") +
395 strlen("-2147483647-") + /* INT_MAX should be sufficient */
396 TRACEJAVACALLINDENT +
397 strlen("finished: ") +
398 utf_bytes(m->class->name) +
401 utf_bytes(m->descriptor) +
402 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
404 /* add maximal argument length */
406 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
408 /* allocate memory */
410 dumpsize = dump_size();
412 logtext = DMNEW(char, logtextlen);
414 /* outdent the log message */
416 if (TRACEJAVACALLINDENT)
417 TRACEJAVACALLINDENT--;
419 log_text("WARNING: unmatched TRACEJAVACALLINDENT--");
421 /* generate the message */
423 sprintf(logtext, " ");
424 sprintf(logtext + strlen(logtext), "-%d-", TRACEJAVACALLINDENT);
426 pos = strlen(logtext);
428 for (i = 0; i < TRACEJAVACALLINDENT; i++)
429 logtext[pos++] = '\t';
431 strcpy(logtext + pos, "finished: ");
432 utf_cat_classname(logtext, m->class->name);
433 strcat(logtext, ".");
434 utf_cat(logtext, m->name);
435 utf_cat(logtext, m->descriptor);
437 if (!IS_VOID_TYPE(md->returntype.type)) {
438 strcat(logtext, "->");
439 val = _array_load_return_value(&md->returntype, return_regs);
442 trace_java_call_print_argument(logtext, &logtextlen, &md->returntype, val);
449 dump_release(dumpsize);
453 #endif /* !defined(NDEBUG) */