Bug 497999: collect context-specific TraceVis data in JS objects, r=jorendorff
This commit is contained in:
Родитель
af688b6d08
Коммит
571bfdff48
|
@ -112,6 +112,7 @@ MOZ_JPROF = @MOZ_JPROF@
|
||||||
MOZ_SHARK = @MOZ_SHARK@
|
MOZ_SHARK = @MOZ_SHARK@
|
||||||
MOZ_CALLGRIND = @MOZ_CALLGRIND@
|
MOZ_CALLGRIND = @MOZ_CALLGRIND@
|
||||||
MOZ_VTUNE = @MOZ_VTUNE@
|
MOZ_VTUNE = @MOZ_VTUNE@
|
||||||
|
MOZ_TRACEVIS = @MOZ_TRACEVIS@
|
||||||
DEHYDRA_PATH = @DEHYDRA_PATH@
|
DEHYDRA_PATH = @DEHYDRA_PATH@
|
||||||
|
|
||||||
MOZ_XPCTOOLS = @MOZ_XPCTOOLS@
|
MOZ_XPCTOOLS = @MOZ_XPCTOOLS@
|
||||||
|
|
11
configure.in
11
configure.in
|
@ -6697,6 +6697,17 @@ MOZ_ARG_WITH_STRING(wrap-malloc,
|
||||||
[ --with-wrap-malloc=DIR Location of malloc wrapper library],
|
[ --with-wrap-malloc=DIR Location of malloc wrapper library],
|
||||||
WRAP_MALLOC_LIB=$withval)
|
WRAP_MALLOC_LIB=$withval)
|
||||||
|
|
||||||
|
dnl ========================================================
|
||||||
|
dnl = Use TraceVis
|
||||||
|
dnl ========================================================
|
||||||
|
MOZ_ARG_ENABLE_BOOL(tracevis,
|
||||||
|
[ --enable-tracevis Enable TraceVis tracing tool (default=no)],
|
||||||
|
MOZ_TRACEVIS=1,
|
||||||
|
MOZ_TRACEVIS= )
|
||||||
|
if test -n "$MOZ_TRACEVIS"; then
|
||||||
|
AC_DEFINE(MOZ_TRACEVIS)
|
||||||
|
fi
|
||||||
|
|
||||||
dnl ========================================================
|
dnl ========================================================
|
||||||
dnl = Use Valgrind
|
dnl = Use Valgrind
|
||||||
dnl ========================================================
|
dnl ========================================================
|
||||||
|
|
|
@ -3269,6 +3269,14 @@ static JSFunctionSpec VtuneFunctions[] = {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MOZ_TRACEVIS
|
||||||
|
static JSFunctionSpec EthogramFunctions[] = {
|
||||||
|
{"initEthogram", js_InitEthogram, 0, 0, 0},
|
||||||
|
{"shutdownEthogram", js_ShutdownEthogram, 0, 0, 0},
|
||||||
|
{nsnull, nsnull, 0, 0, 0}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsJSContext::InitClasses(void *aGlobalObj)
|
nsJSContext::InitClasses(void *aGlobalObj)
|
||||||
{
|
{
|
||||||
|
@ -3316,6 +3324,11 @@ nsJSContext::InitClasses(void *aGlobalObj)
|
||||||
::JS_DefineFunctions(mContext, globalObj, VtuneFunctions);
|
::JS_DefineFunctions(mContext, globalObj, VtuneFunctions);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MOZ_TRACEVIS
|
||||||
|
// Attempt to initialize Ethogram functions
|
||||||
|
::JS_DefineFunctions(mContext, globalObj, EthogramFunctions);
|
||||||
|
#endif
|
||||||
|
|
||||||
JSOptionChangedCallback(js_options_dot_str, this);
|
JSOptionChangedCallback(js_options_dot_str, this);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
|
|
@ -2012,3 +2012,435 @@ js_ResumeVtune(JSContext *cx, JSObject *obj,
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* MOZ_VTUNE */
|
#endif /* MOZ_VTUNE */
|
||||||
|
|
||||||
|
#ifdef MOZ_TRACEVIS
|
||||||
|
/*
|
||||||
|
* Ethogram - Javascript wrapper for TraceVis state
|
||||||
|
*
|
||||||
|
* ethology: The scientific study of animal behavior,
|
||||||
|
* especially as it occurs in a natural environment.
|
||||||
|
* ethogram: A pictorial catalog of the behavioral patterns of
|
||||||
|
* an organism or a species.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#if defined(XP_WIN)
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
#include "jstracer.h"
|
||||||
|
|
||||||
|
#define ETHOGRAM_BUF_SIZE 65536
|
||||||
|
|
||||||
|
static JSBool
|
||||||
|
ethogram_construct(JSContext *cx, JSObject *obj,
|
||||||
|
uintN argc, jsval *argv, jsval *rval);
|
||||||
|
static void
|
||||||
|
ethogram_finalize(JSContext *cx, JSObject *obj);
|
||||||
|
|
||||||
|
static JSClass ethogram_class = {
|
||||||
|
"Ethogram",
|
||||||
|
JSCLASS_HAS_PRIVATE,
|
||||||
|
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||||
|
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, ethogram_finalize,
|
||||||
|
JSCLASS_NO_OPTIONAL_MEMBERS
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EthogramEvent {
|
||||||
|
TraceVisState s;
|
||||||
|
TraceVisExitReason r;
|
||||||
|
int ts;
|
||||||
|
int tus;
|
||||||
|
JSString *filename;
|
||||||
|
int lineno;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
compare_strings(const void *k1, const void *k2)
|
||||||
|
{
|
||||||
|
return strcmp((const char *) k1, (const char *) k2) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
class EthogramEventBuffer {
|
||||||
|
private:
|
||||||
|
EthogramEvent mBuf[ETHOGRAM_BUF_SIZE];
|
||||||
|
int mReadPos;
|
||||||
|
int mWritePos;
|
||||||
|
JSObject *mFilenames;
|
||||||
|
int mStartSecond;
|
||||||
|
|
||||||
|
struct EthogramScriptEntry {
|
||||||
|
char *filename;
|
||||||
|
JSString *jsfilename;
|
||||||
|
|
||||||
|
EthogramScriptEntry *next;
|
||||||
|
};
|
||||||
|
EthogramScriptEntry *mScripts;
|
||||||
|
|
||||||
|
public:
|
||||||
|
friend JSBool
|
||||||
|
ethogram_construct(JSContext *cx, JSObject *obj,
|
||||||
|
uintN argc, jsval *argv, jsval *rval);
|
||||||
|
|
||||||
|
inline void push(TraceVisState s, TraceVisExitReason r, char *filename, int lineno) {
|
||||||
|
mBuf[mWritePos].s = s;
|
||||||
|
mBuf[mWritePos].r = r;
|
||||||
|
#if defined(XP_WIN)
|
||||||
|
FILETIME now;
|
||||||
|
GetSystemTimeAsFileTime(&now);
|
||||||
|
unsigned long long raw_us = 0.1 *
|
||||||
|
(((unsigned long long) now.dwHighDateTime << 32ULL) |
|
||||||
|
(unsigned long long) now.dwLowDateTime);
|
||||||
|
unsigned int sec = raw_us / 1000000L;
|
||||||
|
unsigned int usec = raw_us % 1000000L;
|
||||||
|
mBuf[mWritePos].ts = sec - mStartSecond;
|
||||||
|
mBuf[mWritePos].tus = usec;
|
||||||
|
#else
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
mBuf[mWritePos].ts = tv.tv_sec - mStartSecond;
|
||||||
|
mBuf[mWritePos].tus = tv.tv_usec;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
JSString *jsfilename = findScript(filename);
|
||||||
|
mBuf[mWritePos].filename = jsfilename;
|
||||||
|
mBuf[mWritePos].lineno = lineno;
|
||||||
|
|
||||||
|
mWritePos = (mWritePos + 1) % ETHOGRAM_BUF_SIZE;
|
||||||
|
if (mWritePos == mReadPos) {
|
||||||
|
mReadPos = (mWritePos + 1) % ETHOGRAM_BUF_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline EthogramEvent *pop() {
|
||||||
|
EthogramEvent *e = &mBuf[mReadPos];
|
||||||
|
mReadPos = (mReadPos + 1) % ETHOGRAM_BUF_SIZE;
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEmpty() {
|
||||||
|
return (mReadPos == mWritePos);
|
||||||
|
}
|
||||||
|
|
||||||
|
EthogramScriptEntry *addScript(JSContext *cx, JSObject *obj, char *filename, JSString *jsfilename) {
|
||||||
|
JSHashNumber hash = JS_HashString(filename);
|
||||||
|
JSHashEntry **hep = JS_HashTableRawLookup(traceVisScriptTable, hash, filename);
|
||||||
|
if (*hep != NULL)
|
||||||
|
return JS_FALSE;
|
||||||
|
|
||||||
|
JS_HashTableRawAdd(traceVisScriptTable, hep, hash, filename, this);
|
||||||
|
|
||||||
|
EthogramScriptEntry * entry = (EthogramScriptEntry *) JS_malloc(cx, sizeof(EthogramScriptEntry));
|
||||||
|
if (entry == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
entry->next = mScripts;
|
||||||
|
mScripts = entry;
|
||||||
|
entry->filename = filename;
|
||||||
|
entry->jsfilename = jsfilename;
|
||||||
|
|
||||||
|
return mScripts;
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeScripts(JSContext *cx) {
|
||||||
|
EthogramScriptEntry *se = mScripts;
|
||||||
|
while (se != NULL) {
|
||||||
|
char *filename = se->filename;
|
||||||
|
|
||||||
|
JSHashNumber hash = JS_HashString(filename);
|
||||||
|
JSHashEntry **hep = JS_HashTableRawLookup(traceVisScriptTable, hash, filename);
|
||||||
|
JSHashEntry *he = *hep;
|
||||||
|
if (he) {
|
||||||
|
/* we hardly knew he */
|
||||||
|
JS_HashTableRawRemove(traceVisScriptTable, hep, he);
|
||||||
|
}
|
||||||
|
|
||||||
|
EthogramScriptEntry *se_head = se;
|
||||||
|
se = se->next;
|
||||||
|
JS_free(cx, se_head);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JSString *findScript(char *filename) {
|
||||||
|
EthogramScriptEntry *se = mScripts;
|
||||||
|
while (se != NULL) {
|
||||||
|
if (compare_strings(se->filename, filename))
|
||||||
|
return (se->jsfilename);
|
||||||
|
se = se->next;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject *filenames() {
|
||||||
|
return mFilenames;
|
||||||
|
}
|
||||||
|
|
||||||
|
int length() {
|
||||||
|
if (mWritePos < mReadPos)
|
||||||
|
return (mWritePos + ETHOGRAM_BUF_SIZE) - mReadPos;
|
||||||
|
else
|
||||||
|
return mWritePos - mReadPos;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static char jstv_empty[] = "<null>";
|
||||||
|
|
||||||
|
inline char *
|
||||||
|
jstv_Filename(JSStackFrame *fp)
|
||||||
|
{
|
||||||
|
while (fp && fp->script == NULL)
|
||||||
|
fp = fp->down;
|
||||||
|
return (fp && fp->script && fp->script->filename)
|
||||||
|
? (char *)fp->script->filename
|
||||||
|
: jstv_empty;
|
||||||
|
}
|
||||||
|
inline uintN
|
||||||
|
jstv_Lineno(JSContext *cx, JSStackFrame *fp)
|
||||||
|
{
|
||||||
|
while (fp && fp->regs == NULL)
|
||||||
|
fp = fp->down;
|
||||||
|
return (fp && fp->regs) ? js_FramePCToLineNumber(cx, fp) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Collect states here and distribute to a matching buffer, if any */
|
||||||
|
JS_FRIEND_API(void)
|
||||||
|
js_StoreTraceVisState(JSContext *cx, TraceVisState s, TraceVisExitReason r)
|
||||||
|
{
|
||||||
|
JSStackFrame *fp = cx->fp;
|
||||||
|
|
||||||
|
char *script_file = jstv_Filename(fp);
|
||||||
|
JSHashNumber hash = JS_HashString(script_file);
|
||||||
|
|
||||||
|
JSHashEntry **hep = JS_HashTableRawLookup(traceVisScriptTable, hash, script_file);
|
||||||
|
/* update event buffer, flag if overflowed */
|
||||||
|
JSHashEntry *he = *hep;
|
||||||
|
if (he) {
|
||||||
|
EthogramEventBuffer *p;
|
||||||
|
p = (EthogramEventBuffer *) he->value;
|
||||||
|
|
||||||
|
p->push(s, r, script_file, jstv_Lineno(cx, fp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSBool
|
||||||
|
ethogram_construct(JSContext *cx, JSObject *obj,
|
||||||
|
uintN argc, jsval *argv, jsval *rval)
|
||||||
|
{
|
||||||
|
EthogramEventBuffer *p;
|
||||||
|
|
||||||
|
p = (EthogramEventBuffer *) JS_malloc(cx, sizeof(EthogramEventBuffer));
|
||||||
|
|
||||||
|
p->mReadPos = p->mWritePos = 0;
|
||||||
|
p->mScripts = NULL;
|
||||||
|
p->mFilenames = JS_NewArrayObject(cx, 0, NULL);
|
||||||
|
|
||||||
|
#if defined(XP_WIN)
|
||||||
|
FILETIME now;
|
||||||
|
GetSystemTimeAsFileTime(&now);
|
||||||
|
unsigned long long raw_us = 0.1 *
|
||||||
|
(((unsigned long long) now.dwHighDateTime << 32ULL) |
|
||||||
|
(unsigned long long) now.dwLowDateTime);
|
||||||
|
unsigned int s = raw_us / 1000000L;
|
||||||
|
p->mStartSecond = s;
|
||||||
|
#else
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
p->mStartSecond = tv.tv_sec;
|
||||||
|
#endif
|
||||||
|
jsval filenames = OBJECT_TO_JSVAL(p->filenames());
|
||||||
|
if (!JS_DefineProperty(cx, obj, "filenames", filenames,
|
||||||
|
NULL, NULL, JSPROP_READONLY|JSPROP_PERMANENT))
|
||||||
|
return JS_FALSE;
|
||||||
|
|
||||||
|
if (!JS_IsConstructing(cx)) {
|
||||||
|
obj = JS_NewObject(cx, ðogram_class, NULL, NULL);
|
||||||
|
if (!obj)
|
||||||
|
return JS_FALSE;
|
||||||
|
*rval = OBJECT_TO_JSVAL(obj);
|
||||||
|
}
|
||||||
|
JS_SetPrivate(cx, obj, p);
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ethogram_finalize(JSContext *cx, JSObject *obj)
|
||||||
|
{
|
||||||
|
EthogramEventBuffer *p;
|
||||||
|
p = (EthogramEventBuffer *) JS_GetInstancePrivate(cx, obj, ðogram_class, NULL);
|
||||||
|
if (!p)
|
||||||
|
return;
|
||||||
|
|
||||||
|
p->removeScripts(cx);
|
||||||
|
|
||||||
|
JS_free(cx, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSBool
|
||||||
|
ethogram_addScript(JSContext *cx, JSObject *obj,
|
||||||
|
uintN argc, jsval *argv, jsval *rval)
|
||||||
|
{
|
||||||
|
JSString *str;
|
||||||
|
char *filename = NULL;
|
||||||
|
if (argc > 0 && JSVAL_IS_STRING(argv[0])) {
|
||||||
|
str = JSVAL_TO_STRING(argv[0]);
|
||||||
|
filename = js_DeflateString(cx,
|
||||||
|
str->chars(),
|
||||||
|
str->length());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* silently ignore no args */
|
||||||
|
if (!filename)
|
||||||
|
return JS_TRUE;
|
||||||
|
|
||||||
|
EthogramEventBuffer *p = (EthogramEventBuffer *) JS_GetInstancePrivate(cx, obj, ðogram_class, argv);
|
||||||
|
|
||||||
|
p->addScript(cx, obj, filename, str);
|
||||||
|
JS_CallFunctionName(cx, p->filenames(), "push", 1, argv, rval);
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSBool
|
||||||
|
ethogram_getAllEvents(JSContext *cx, JSObject *obj,
|
||||||
|
uintN argc, jsval *argv, jsval *rval)
|
||||||
|
{
|
||||||
|
EthogramEventBuffer *p;
|
||||||
|
|
||||||
|
p = (EthogramEventBuffer *) JS_GetInstancePrivate(cx, obj, ðogram_class, argv);
|
||||||
|
if (!p)
|
||||||
|
return JS_FALSE;
|
||||||
|
|
||||||
|
if (p->isEmpty()) {
|
||||||
|
*rval = JSVAL_NULL;
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject *rarray = JS_NewArrayObject(cx, 0, NULL);
|
||||||
|
if (rarray == NULL) {
|
||||||
|
*rval = JSVAL_NULL;
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*rval = OBJECT_TO_JSVAL(rarray);
|
||||||
|
|
||||||
|
for (int i = 0; !p->isEmpty(); i++) {
|
||||||
|
|
||||||
|
JSObject *x = JS_NewObject(cx, NULL, NULL, NULL);
|
||||||
|
if (x == NULL)
|
||||||
|
return JS_FALSE;
|
||||||
|
|
||||||
|
EthogramEvent *e = p->pop();
|
||||||
|
|
||||||
|
jsval state = INT_TO_JSVAL(e->s);
|
||||||
|
jsval reason = INT_TO_JSVAL(e->r);
|
||||||
|
jsval ts = INT_TO_JSVAL(e->ts);
|
||||||
|
jsval tus = INT_TO_JSVAL(e->tus);
|
||||||
|
|
||||||
|
jsval filename = STRING_TO_JSVAL(e->filename);
|
||||||
|
jsval lineno = INT_TO_JSVAL(e->lineno);
|
||||||
|
|
||||||
|
if (!JS_SetProperty(cx, x, "state", &state))
|
||||||
|
return JS_FALSE;
|
||||||
|
if (!JS_SetProperty(cx, x, "reason", &reason))
|
||||||
|
return JS_FALSE;
|
||||||
|
if (!JS_SetProperty(cx, x, "ts", &ts))
|
||||||
|
return JS_FALSE;
|
||||||
|
if (!JS_SetProperty(cx, x, "tus", &tus))
|
||||||
|
return JS_FALSE;
|
||||||
|
|
||||||
|
if (!JS_SetProperty(cx, x, "filename", &filename))
|
||||||
|
return JS_FALSE;
|
||||||
|
if (!JS_SetProperty(cx, x, "lineno", &lineno))
|
||||||
|
return JS_FALSE;
|
||||||
|
|
||||||
|
jsval element = OBJECT_TO_JSVAL(x);
|
||||||
|
JS_SetElement(cx, rarray, i, &element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSBool
|
||||||
|
ethogram_getNextEvent(JSContext *cx, JSObject *obj,
|
||||||
|
uintN argc, jsval *argv, jsval *rval)
|
||||||
|
{
|
||||||
|
EthogramEventBuffer *p;
|
||||||
|
|
||||||
|
p = (EthogramEventBuffer *) JS_GetInstancePrivate(cx, obj, ðogram_class, argv);
|
||||||
|
if (!p)
|
||||||
|
return JS_FALSE;
|
||||||
|
|
||||||
|
JSObject *x = JS_NewObject(cx, NULL, NULL, NULL);
|
||||||
|
if (x == NULL)
|
||||||
|
return JS_FALSE;
|
||||||
|
|
||||||
|
if (p->isEmpty()) {
|
||||||
|
*rval = JSVAL_NULL;
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
EthogramEvent *e = p->pop();
|
||||||
|
jsval state = INT_TO_JSVAL(e->s);
|
||||||
|
jsval reason = INT_TO_JSVAL(e->r);
|
||||||
|
jsval ts = INT_TO_JSVAL(e->ts);
|
||||||
|
jsval tus = INT_TO_JSVAL(e->tus);
|
||||||
|
|
||||||
|
jsval filename = STRING_TO_JSVAL(e->filename);
|
||||||
|
jsval lineno = INT_TO_JSVAL(e->lineno);
|
||||||
|
|
||||||
|
if (!JS_SetProperty(cx, x, "state", &state))
|
||||||
|
return JS_FALSE;
|
||||||
|
if (!JS_SetProperty(cx, x, "reason", &reason))
|
||||||
|
return JS_FALSE;
|
||||||
|
if (!JS_SetProperty(cx, x, "ts", &ts))
|
||||||
|
return JS_FALSE;
|
||||||
|
if (!JS_SetProperty(cx, x, "tus", &tus))
|
||||||
|
return JS_FALSE;
|
||||||
|
if (!JS_SetProperty(cx, x, "filename", &filename))
|
||||||
|
return JS_FALSE;
|
||||||
|
|
||||||
|
if (!JS_SetProperty(cx, x, "lineno", &lineno))
|
||||||
|
return JS_FALSE;
|
||||||
|
|
||||||
|
*rval = OBJECT_TO_JSVAL(x);
|
||||||
|
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSFunctionSpec ethogram_methods[] = {
|
||||||
|
{"addScript", ethogram_addScript, 1},
|
||||||
|
{"getAllEvents", ethogram_getAllEvents, 0},
|
||||||
|
{"getNextEvent", ethogram_getNextEvent, 0},
|
||||||
|
{0}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An |Ethogram| organizes the output of a collection of files that should be
|
||||||
|
* monitored together. A single object gets events for the group.
|
||||||
|
*/
|
||||||
|
JS_FRIEND_API(JSBool)
|
||||||
|
js_InitEthogram(JSContext *cx, JSObject *obj,
|
||||||
|
uintN argc, jsval *argv, jsval *rval)
|
||||||
|
{
|
||||||
|
if (!traceVisScriptTable) {
|
||||||
|
traceVisScriptTable = JS_NewHashTable(8, JS_HashString, compare_strings,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_InitClass(cx, JS_GetGlobalObject(cx), NULL, ðogram_class,
|
||||||
|
ethogram_construct, 0, NULL, ethogram_methods,
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_FRIEND_API(JSBool)
|
||||||
|
js_ShutdownEthogram(JSContext *cx, JSObject *obj,
|
||||||
|
uintN argc, jsval *argv, jsval *rval)
|
||||||
|
{
|
||||||
|
if (traceVisScriptTable)
|
||||||
|
JS_HashTableDestroy(traceVisScriptTable);
|
||||||
|
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* MOZ_TRACEVIS */
|
||||||
|
|
|
@ -495,6 +495,15 @@ js_ResumeVtune(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||||
|
|
||||||
#endif /* MOZ_VTUNE */
|
#endif /* MOZ_VTUNE */
|
||||||
|
|
||||||
|
#ifdef MOZ_TRACEVIS
|
||||||
|
extern JS_FRIEND_API(JSBool)
|
||||||
|
js_InitEthogram(JSContext *cx, JSObject *obj,
|
||||||
|
uintN argc, jsval *argv, jsval *rval);
|
||||||
|
extern JS_FRIEND_API(JSBool)
|
||||||
|
js_ShutdownEthogram(JSContext *cx, JSObject *obj,
|
||||||
|
uintN argc, jsval *argv, jsval *rval);
|
||||||
|
#endif /* MOZ_TRACEVIS */
|
||||||
|
|
||||||
JS_END_EXTERN_C
|
JS_END_EXTERN_C
|
||||||
|
|
||||||
#endif /* jsdbgapi_h___ */
|
#endif /* jsdbgapi_h___ */
|
||||||
|
|
|
@ -2664,7 +2664,7 @@ JS_REQUIRES_STACK JSBool
|
||||||
js_Interpret(JSContext *cx)
|
js_Interpret(JSContext *cx)
|
||||||
{
|
{
|
||||||
#ifdef MOZ_TRACEVIS
|
#ifdef MOZ_TRACEVIS
|
||||||
TraceVisStateObj tvso(S_INTERP);
|
TraceVisStateObj tvso(cx, S_INTERP);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
JSRuntime *rt;
|
JSRuntime *rt;
|
||||||
|
@ -2880,11 +2880,18 @@ js_Interpret(JSContext *cx)
|
||||||
#ifdef JS_TRACER
|
#ifdef JS_TRACER
|
||||||
|
|
||||||
#ifdef MOZ_TRACEVIS
|
#ifdef MOZ_TRACEVIS
|
||||||
|
#if JS_THREADED_INTERP
|
||||||
#define MONITOR_BRANCH_TRACEVIS \
|
#define MONITOR_BRANCH_TRACEVIS \
|
||||||
JS_BEGIN_MACRO \
|
JS_BEGIN_MACRO \
|
||||||
if (jumpTable != interruptJumpTable) \
|
if (jumpTable != interruptJumpTable) \
|
||||||
js_EnterTraceVisState(S_RECORD, R_NONE); \
|
js_EnterTraceVisState(cx, S_RECORD, R_NONE); \
|
||||||
JS_END_MACRO
|
JS_END_MACRO
|
||||||
|
#else /* !JS_THREADED_INTERP */
|
||||||
|
#define MONITOR_BRANCH_TRACEVIS \
|
||||||
|
JS_BEGIN_MACRO \
|
||||||
|
js_EnterTraceVisState(cx, S_RECORD, R_NONE); \
|
||||||
|
JS_END_MACRO
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#define MONITOR_BRANCH_TRACEVIS
|
#define MONITOR_BRANCH_TRACEVIS
|
||||||
#endif
|
#endif
|
||||||
|
@ -3115,7 +3122,7 @@ js_Interpret(JSContext *cx)
|
||||||
#if JS_THREADED_INTERP
|
#if JS_THREADED_INTERP
|
||||||
#ifdef MOZ_TRACEVIS
|
#ifdef MOZ_TRACEVIS
|
||||||
if (!moreInterrupts)
|
if (!moreInterrupts)
|
||||||
js_ExitTraceVisState(R_ABORT);
|
js_ExitTraceVisState(cx, R_ABORT);
|
||||||
#endif
|
#endif
|
||||||
jumpTable = moreInterrupts ? interruptJumpTable : normalJumpTable;
|
jumpTable = moreInterrupts ? interruptJumpTable : normalJumpTable;
|
||||||
JS_EXTENSION_(goto *normalJumpTable[op]);
|
JS_EXTENSION_(goto *normalJumpTable[op]);
|
||||||
|
|
|
@ -3729,7 +3729,7 @@ JS_REQUIRES_STACK void
|
||||||
TraceRecorder::compile(JSTraceMonitor* tm)
|
TraceRecorder::compile(JSTraceMonitor* tm)
|
||||||
{
|
{
|
||||||
#ifdef MOZ_TRACEVIS
|
#ifdef MOZ_TRACEVIS
|
||||||
TraceVisStateObj tvso(S_COMPILE);
|
TraceVisStateObj tvso(cx, S_COMPILE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (tm->needFlush) {
|
if (tm->needFlush) {
|
||||||
|
@ -5427,7 +5427,7 @@ ExecuteTree(JSContext* cx, Fragment* f, uintN& inlineCallCount,
|
||||||
VMSideExit** innermostNestedGuardp)
|
VMSideExit** innermostNestedGuardp)
|
||||||
{
|
{
|
||||||
#ifdef MOZ_TRACEVIS
|
#ifdef MOZ_TRACEVIS
|
||||||
TraceVisStateObj tvso(S_EXECUTE);
|
TraceVisStateObj tvso(cx, S_EXECUTE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
JS_ASSERT(f->root == f && f->code() && f->vmprivate);
|
JS_ASSERT(f->root == f && f->code() && f->vmprivate);
|
||||||
|
@ -5525,7 +5525,7 @@ ExecuteTree(JSContext* cx, Fragment* f, uintN& inlineCallCount,
|
||||||
// TraceVisStateObj constructors and destructors must run at the right times.
|
// TraceVisStateObj constructors and destructors must run at the right times.
|
||||||
{
|
{
|
||||||
#ifdef MOZ_TRACEVIS
|
#ifdef MOZ_TRACEVIS
|
||||||
TraceVisStateObj tvso_n(S_NATIVE);
|
TraceVisStateObj tvso_n(cx, S_NATIVE);
|
||||||
#endif
|
#endif
|
||||||
#if defined(JS_NO_FASTCALL) && defined(NANOJIT_IA32)
|
#if defined(JS_NO_FASTCALL) && defined(NANOJIT_IA32)
|
||||||
SIMULATE_FASTCALL(rec, state, NULL, u.func);
|
SIMULATE_FASTCALL(rec, state, NULL, u.func);
|
||||||
|
@ -5837,7 +5837,7 @@ JS_REQUIRES_STACK bool
|
||||||
js_MonitorLoopEdge(JSContext* cx, uintN& inlineCallCount)
|
js_MonitorLoopEdge(JSContext* cx, uintN& inlineCallCount)
|
||||||
{
|
{
|
||||||
#ifdef MOZ_TRACEVIS
|
#ifdef MOZ_TRACEVIS
|
||||||
TraceVisStateObj tvso(S_MONITOR);
|
TraceVisStateObj tvso(cx, S_MONITOR);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
|
JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
|
||||||
|
@ -12732,6 +12732,7 @@ DumpPeerStability(JSTraceMonitor* tm, const void* ip, JSObject* globalObj, uint3
|
||||||
#ifdef MOZ_TRACEVIS
|
#ifdef MOZ_TRACEVIS
|
||||||
|
|
||||||
FILE* traceVisLogFile = NULL;
|
FILE* traceVisLogFile = NULL;
|
||||||
|
JSHashTable *traceVisScriptTable = NULL;
|
||||||
|
|
||||||
JS_FRIEND_API(bool)
|
JS_FRIEND_API(bool)
|
||||||
JS_StartTraceVis(const char* filename = "tracevis.dat")
|
JS_StartTraceVis(const char* filename = "tracevis.dat")
|
||||||
|
|
|
@ -1005,14 +1005,18 @@ enum TraceVisExitReason {
|
||||||
R_OTHER_EXIT
|
R_OTHER_EXIT
|
||||||
};
|
};
|
||||||
|
|
||||||
const unsigned long long MS64_MASK = 0xfllu << 60;
|
const unsigned long long MS64_MASK = 0xfull << 60;
|
||||||
const unsigned long long MR64_MASK = 0x1fllu << 55;
|
const unsigned long long MR64_MASK = 0x1full << 55;
|
||||||
const unsigned long long MT64_MASK = ~(MS64_MASK | MR64_MASK);
|
const unsigned long long MT64_MASK = ~(MS64_MASK | MR64_MASK);
|
||||||
|
|
||||||
extern FILE* traceVisLogFile;
|
extern FILE* traceVisLogFile;
|
||||||
|
extern JSHashTable *traceVisScriptTable;
|
||||||
|
|
||||||
|
extern JS_FRIEND_API(void)
|
||||||
|
js_StoreTraceVisState(JSContext *cx, TraceVisState s, TraceVisExitReason r);
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
js_LogTraceVisState(TraceVisState s, TraceVisExitReason r)
|
js_LogTraceVisState(JSContext *cx, TraceVisState s, TraceVisExitReason r)
|
||||||
{
|
{
|
||||||
if (traceVisLogFile) {
|
if (traceVisLogFile) {
|
||||||
unsigned long long sllu = s;
|
unsigned long long sllu = s;
|
||||||
|
@ -1020,30 +1024,35 @@ js_LogTraceVisState(TraceVisState s, TraceVisExitReason r)
|
||||||
unsigned long long d = (sllu << 60) | (rllu << 55) | (rdtsc() & MT64_MASK);
|
unsigned long long d = (sllu << 60) | (rllu << 55) | (rdtsc() & MT64_MASK);
|
||||||
fwrite(&d, sizeof(d), 1, traceVisLogFile);
|
fwrite(&d, sizeof(d), 1, traceVisLogFile);
|
||||||
}
|
}
|
||||||
|
if (traceVisScriptTable) {
|
||||||
|
js_StoreTraceVisState(cx, s, r);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
js_EnterTraceVisState(TraceVisState s, TraceVisExitReason r)
|
js_EnterTraceVisState(JSContext *cx, TraceVisState s, TraceVisExitReason r)
|
||||||
{
|
{
|
||||||
js_LogTraceVisState(s, r);
|
js_LogTraceVisState(cx, s, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
js_ExitTraceVisState(TraceVisExitReason r)
|
js_ExitTraceVisState(JSContext *cx, TraceVisExitReason r)
|
||||||
{
|
{
|
||||||
js_LogTraceVisState(S_EXITLAST, r);
|
js_LogTraceVisState(cx, S_EXITLAST, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TraceVisStateObj {
|
struct TraceVisStateObj {
|
||||||
TraceVisExitReason r;
|
TraceVisExitReason r;
|
||||||
|
JSContext *mCx;
|
||||||
|
|
||||||
inline TraceVisStateObj(TraceVisState s) : r(R_NONE)
|
inline TraceVisStateObj(JSContext *cx, TraceVisState s) : r(R_NONE)
|
||||||
{
|
{
|
||||||
js_EnterTraceVisState(s, R_NONE);
|
js_EnterTraceVisState(cx, s, R_NONE);
|
||||||
|
mCx = cx;
|
||||||
}
|
}
|
||||||
inline ~TraceVisStateObj()
|
inline ~TraceVisStateObj()
|
||||||
{
|
{
|
||||||
js_ExitTraceVisState(r);
|
js_ExitTraceVisState(mCx, r);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@
|
||||||
#include "prmem.h"
|
#include "prmem.h"
|
||||||
#include "plbase64.h"
|
#include "plbase64.h"
|
||||||
|
|
||||||
#if defined(MOZ_SHARK) || defined(MOZ_CALLGRIND) || defined(MOZ_VTUNE)
|
#if defined(MOZ_SHARK) || defined(MOZ_CALLGRIND) || defined(MOZ_VTUNE) || defined(MOZ_TRACEVIS)
|
||||||
#include "jsdbgapi.h"
|
#include "jsdbgapi.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -291,6 +291,10 @@ static JSFunctionSpec gGlobalFun[] = {
|
||||||
{"stopVtune", js_StopVtune, 0,0,0},
|
{"stopVtune", js_StopVtune, 0,0,0},
|
||||||
{"pauseVtune", js_PauseVtune, 0,0,0},
|
{"pauseVtune", js_PauseVtune, 0,0,0},
|
||||||
{"resumeVtune", js_ResumeVtune, 0,0,0},
|
{"resumeVtune", js_ResumeVtune, 0,0,0},
|
||||||
|
#endif
|
||||||
|
#ifdef MOZ_TRACEVIS
|
||||||
|
{"initEthogram", js_InitEthogram, 0,0,0},
|
||||||
|
{"shutdownEthogram", js_ShutdownEthogram, 0,0,0},
|
||||||
#endif
|
#endif
|
||||||
{nsnull,nsnull,0,0,0}
|
{nsnull,nsnull,0,0,0}
|
||||||
};
|
};
|
||||||
|
|
Загрузка…
Ссылка в новой задаче