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
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];
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 /* trace_java_call_enter ******************************************************
253 Traces an entry into a java method.
255 arg_regs: Array of size ARG_CNT containing all argument registers in
256 the same format as in asm_vm_call_method. The array is usually allocated
257 on the stack and used for restoring the argument registers later.
259 stack: Pointer to first on stack argument in the same format passed to
262 *******************************************************************************/
264 void trace_java_call_enter(methodinfo *m, uint64_t *arg_regs, uint64_t *stack) {
275 #if defined(ENABLE_DEBUG_FILTER)
276 if (! show_filters_test_verbosecall_enter(m)) return;
279 #if defined(ENABLE_VMLOG)
280 vmlog_cacao_enter_method(m);
286 /* calculate message length */
289 strlen("4294967295 ") +
290 strlen("-2147483647-") + /* INT_MAX should be sufficient */
291 TRACEJAVACALLINDENT +
293 utf_bytes(m->class->name) +
296 utf_bytes(m->descriptor);
298 /* Actually it's not possible to have all flags printed, but:
304 strlen(" PROTECTED") +
307 strlen(" SYNCHRONIZED") +
308 strlen(" VOLATILE") +
309 strlen(" TRANSIENT") +
311 strlen(" INTERFACE") +
314 /* add maximal argument length */
318 strlen("-9223372036854775808 (0x123456789abcdef0), ") * md->paramcount +
322 /* allocate memory */
324 dumpsize = dump_size();
326 logtext = DMNEW(char, logtextlen);
328 TRACEJAVACALLCOUNT++;
330 sprintf(logtext, "%10d ", TRACEJAVACALLCOUNT);
331 sprintf(logtext + strlen(logtext), "-%d-", TRACEJAVACALLINDENT);
333 pos = strlen(logtext);
335 for (i = 0; i < TRACEJAVACALLINDENT; i++)
336 logtext[pos++] = '\t';
338 strcpy(logtext + pos, "called: ");
340 utf_cat_classname(logtext, m->class->name);
341 strcat(logtext, ".");
342 utf_cat(logtext, m->name);
343 utf_cat(logtext, m->descriptor);
345 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
346 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
347 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
348 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
349 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
350 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
351 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
352 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
353 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
354 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
355 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
357 strcat(logtext, "(");
359 for (i = 0; i < md->paramcount; ++i) {
361 td = &md->paramtypes[i];
362 arg = _array_load_param(pd, td, arg_regs, stack);
363 logtext = trace_java_call_print_argument(
364 logtext, &logtextlen, td, arg
366 if (i != (md->paramcount - 1)) {
367 strcat(logtext, ", ");
371 strcat(logtext, ")");
377 dump_release(dumpsize);
379 TRACEJAVACALLINDENT++;
383 /* trace_java_call_exit ********************************************************
385 Traces an exit form a java method.
387 return_regs: Array of size 3 containing return registers:
389 [1] : REG_RESULT2 (if available on architecture)
391 The array is usually allocated on the stack and used for restoring the
392 registers later. The format of the array is the same as the format of
393 register arguments passed to asm_vm_call_method.
395 *******************************************************************************/
397 void trace_java_call_exit(methodinfo *m, uint64_t *return_regs)
407 #if defined(ENABLE_DEBUG_FILTER)
408 if (! show_filters_test_verbosecall_exit(m)) return;
411 #if defined(ENABLE_VMLOG)
412 vmlog_cacao_leave_method(m);
418 /* calculate message length */
421 strlen("4294967295 ") +
422 strlen("-2147483647-") + /* INT_MAX should be sufficient */
423 TRACEJAVACALLINDENT +
424 strlen("finished: ") +
425 utf_bytes(m->class->name) +
428 utf_bytes(m->descriptor) +
429 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
431 /* add maximal argument length */
433 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
435 /* allocate memory */
437 dumpsize = dump_size();
439 logtext = DMNEW(char, logtextlen);
441 /* outdent the log message */
443 if (TRACEJAVACALLINDENT)
444 TRACEJAVACALLINDENT--;
446 log_text("WARNING: unmatched TRACEJAVACALLINDENT--");
448 /* generate the message */
450 sprintf(logtext, " ");
451 sprintf(logtext + strlen(logtext), "-%d-", TRACEJAVACALLINDENT);
453 pos = strlen(logtext);
455 for (i = 0; i < TRACEJAVACALLINDENT; i++)
456 logtext[pos++] = '\t';
458 strcpy(logtext + pos, "finished: ");
459 utf_cat_classname(logtext, m->class->name);
460 strcat(logtext, ".");
461 utf_cat(logtext, m->name);
462 utf_cat(logtext, m->descriptor);
464 if (!IS_VOID_TYPE(md->returntype.type)) {
465 strcat(logtext, "->");
466 val = _array_load_return_value(&md->returntype, return_regs);
469 trace_java_call_print_argument(logtext, &logtextlen, &md->returntype, val);
476 dump_release(dumpsize);
480 #endif /* !defined(NDEBUG) */
483 * These are local overrides for various environment variables in Emacs.
484 * Please do not remove this and leave it at the end of the file, where
485 * Emacs will automagically detect them.
486 * ---------------------------------------------------------------------
489 * indent-tabs-mode: t
493 * vim:noexpandtab:sw=4:ts=4: