From 10e9f4f6b858148a32998791d1d631438d9bba2c Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Tue, 22 Sep 2009 15:02:50 -0700 Subject: [PATCH] Bug 517633: printf that can be called from trace, r=lw --HG-- extra : rebase_source : 7bf61fae910feab40ef706717420e883ccafc4da --- js/src/jsbuiltins.h | 1 + js/src/jstracer.cpp | 170 +++++++++++++++++++++++++++++++++++++++++++- js/src/jstracer.h | 14 ++++ 3 files changed, 184 insertions(+), 1 deletion(-) diff --git a/js/src/jsbuiltins.h b/js/src/jsbuiltins.h index 91614dac649..649280ef0c7 100644 --- a/js/src/jsbuiltins.h +++ b/js/src/jsbuiltins.h @@ -224,6 +224,7 @@ class ClosureVarInfo; #define _JS_CTYPE_FRAGMENT _JS_CTYPE(nanojit::Fragment *, _JS_PTR, --, --, INFALLIBLE) #define _JS_CTYPE_CLASS _JS_CTYPE(JSClass *, _JS_PTR, --, --, INFALLIBLE) #define _JS_CTYPE_DOUBLEPTR _JS_CTYPE(double *, _JS_PTR, --, --, INFALLIBLE) +#define _JS_CTYPE_CHARPTR _JS_CTYPE(char *, _JS_PTR, --, --, INFALLIBLE) #define _JS_CTYPE_APNPTR _JS_CTYPE(js_ArgsPrivateNative *, _JS_PTR, --, --, INFALLIBLE) #define _JS_CTYPE_CVIPTR _JS_CTYPE(const ClosureVarInfo *, _JS_PTR, --, --, INFALLIBLE) diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 0bec9c9b917..4709020d848 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -641,7 +641,7 @@ js_FragProfiling_showResults(JSTraceMonitor* tm) /* ----------------------------------------------------------------- */ -#if defined DEBUG +#ifdef DEBUG static const char* getExitName(ExitType type) { @@ -657,6 +657,174 @@ getExitName(ExitType type) return exitNames[type]; } + +static JSBool FASTCALL +PrintOnTrace(char* format, uint32 argc, double *argv) +{ + union { + struct { + uint32 lo; + uint32 hi; + } i; + double d; + char *cstr; + JSObject *o; + JSString *s; + } u; + +#define GET_ARG() JS_BEGIN_MACRO \ + if (argi >= argc) { \ + fprintf(out, "[too few args for format]"); \ + break; \ +} \ + u.d = argv[argi++]; \ + JS_END_MACRO + + FILE *out = stderr; + + uint32 argi = 0; + for (char *p = format; *p; ++p) { + if (*p != '%') { + putc(*p, out); + continue; + } + char ch = *++p; + if (!ch) { + fprintf(out, "[trailing %%]"); + continue; + } + + switch (ch) { + case 'a': + GET_ARG(); + fprintf(out, "[%u:%u 0x%x:0x%x %lf]", u.i.lo, u.i.hi, u.i.lo, u.i.hi, u.d); + break; + case 'd': + GET_ARG(); + fprintf(out, "%d", u.i.lo); + break; + case 'u': + GET_ARG(); + fprintf(out, "%u", u.i.lo); + break; + case 'x': + GET_ARG(); + fprintf(out, "%x", u.i.lo); + break; + case 'f': + GET_ARG(); + fprintf(out, "%lf", u.d); + break; + case 'o': + GET_ARG(); + js_DumpObject(u.o); + break; + case 's': + GET_ARG(); + { + size_t length = u.s->length(); + // protect against massive spew if u.s is a bad pointer. + if (length > 1 << 16) + length = 1 << 16; + jschar *chars = u.s->chars(); + for (unsigned i = 0; i < length; ++i) { + jschar co = chars[i]; + if (co < 128) + putc(co, out); + else if (co < 256) + fprintf(out, "\\u%02x", co); + else + fprintf(out, "\\u%04x", co); + } + } + break; + case 'S': + GET_ARG(); + fprintf(out, "%s", u.cstr); + break; + default: + fprintf(out, "[invalid %%%c]", *p); + } + } + +#undef GET_ARG + + return JS_TRUE; +} + +JS_DEFINE_CALLINFO_3(extern, BOOL, PrintOnTrace, CHARPTR, UINT32, DOUBLEPTR, 0, 0); + +// This version is not intended to be called directly: usually it is easier to +// use one of the other overloads. +void +TraceRecorder::tprint(const char *format, int count, nanojit::LIns *insa[]) +{ + size_t size = strlen(format) + 1; + char *data = (char*) lir->insSkip(size)->payload(); + memcpy(data, format, size); + + double *args = (double*) lir->insSkip(count * sizeof(double))->payload(); + for (int i = 0; i < count; ++i) { + JS_ASSERT(insa[i]); + lir->insStorei(insa[i], INS_CONSTPTR(args), sizeof(double) * i); + } + + LIns* args_ins[] = { INS_CONSTPTR(args), INS_CONST(count), INS_CONSTPTR(data) }; + LIns* call_ins = lir->insCall(&PrintOnTrace_ci, args_ins); + guard(false, lir->ins_eq0(call_ins), MISMATCH_EXIT); +} + +// Generate a 'printf'-type call from trace for debugging. +void +TraceRecorder::tprint(const char *format) +{ + LIns* insa[] = { NULL }; + tprint(format, 0, insa); +} + +void +TraceRecorder::tprint(const char *format, LIns *ins) +{ + LIns* insa[] = { ins }; + tprint(format, 1, insa); +} + +void +TraceRecorder::tprint(const char *format, LIns *ins1, LIns *ins2) +{ + LIns* insa[] = { ins1, ins2 }; + tprint(format, 2, insa); +} + +void +TraceRecorder::tprint(const char *format, LIns *ins1, LIns *ins2, LIns *ins3) +{ + LIns* insa[] = { ins1, ins2, ins3 }; + tprint(format, 3, insa); +} + +void +TraceRecorder::tprint(const char *format, LIns *ins1, LIns *ins2, LIns *ins3, LIns *ins4) +{ + LIns* insa[] = { ins1, ins2, ins3, ins4 }; + tprint(format, 4, insa); +} + +void +TraceRecorder::tprint(const char *format, LIns *ins1, LIns *ins2, LIns *ins3, LIns *ins4, + LIns *ins5) +{ + LIns* insa[] = { ins1, ins2, ins3, ins4, ins5 }; + tprint(format, 5, insa); +} + +void +TraceRecorder::tprint(const char *format, LIns *ins1, LIns *ins2, LIns *ins3, LIns *ins4, + LIns *ins5, LIns *ins6) +{ + LIns* insa[] = { ins1, ins2, ins3, ins4, ins5, ins6 }; + tprint(format, 6, insa); +} #endif /* diff --git a/js/src/jstracer.h b/js/src/jstracer.h index e0ba5fc4f6b..2173ae0aa92 100755 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -1053,6 +1053,20 @@ public: bool wasDeepAborted() { return deepAborted; } TreeInfo* getTreeInfo() { return treeInfo; } +#ifdef DEBUG + void tprint(const char *format, int count, nanojit::LIns *insa[]); + void tprint(const char *format); + void tprint(const char *format, nanojit::LIns *ins); + void tprint(const char *format, nanojit::LIns *ins1, nanojit::LIns *ins2); + void tprint(const char *format, nanojit::LIns *ins1, nanojit::LIns *ins2, nanojit::LIns *ins3); + void tprint(const char *format, nanojit::LIns *ins1, nanojit::LIns *ins2, nanojit::LIns *ins3, + nanojit::LIns *ins4); + void tprint(const char *format, nanojit::LIns *ins1, nanojit::LIns *ins2, nanojit::LIns *ins3, + nanojit::LIns *ins4, nanojit::LIns *ins5); + void tprint(const char *format, nanojit::LIns *ins1, nanojit::LIns *ins2, nanojit::LIns *ins3, + nanojit::LIns *ins4, nanojit::LIns *ins5, nanojit::LIns *ins6); +#endif + #define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ JS_REQUIRES_STACK JSRecordingStatus record_##op(); # include "jsopcode.tbl"