part of bug 109652, "Venkman needs to profile" r=peterv,r=a=shaver

add profiling support.
This commit is contained in:
rginda%netscape.com 2002-02-27 09:24:14 +00:00
Родитель 56974c5103
Коммит 615e1e1682
10 изменённых файлов: 671 добавлений и 104 удалений

Просмотреть файл

@ -80,7 +80,6 @@ interface jsdIDebuggerService : nsISupports
/** Internal use only. */
[noscript] readonly attribute JSDContext JSDContext;
/**
* Called when an error or warning occurs.
*/
@ -118,10 +117,49 @@ interface jsdIDebuggerService : nsISupports
*/
attribute jsdICallHook functionHook;
/**
* VERSION_* values must be kept in sync with the JSVersion enumeration in
* jspubtd.h.
*/
/**
* Possible values for jsdIScript::version and jsdIContext::version.
*/
const long VERSION_1_0 = 100;
const long VERSION_1_1 = 110;
const long VERSION_1_2 = 120;
const long VERSION_1_3 = 130;
const long VERSION_1_4 = 140;
const long VERSION_1_5 = 150;
const long VERSION_DEFAULT = 0;
const long VERSION_UNKNOWN = -1;
/**
* These flags need to be kept in sync with the context flags defined in
* jsdebug.h
*/
/**
* Link native frames in call stacks.
*/
const unsigned long ENABLE_NATIVE_FRAMES = 0x01;
const unsigned long ENABLE_NATIVE_FRAMES = 0x01;
/**
* Normally, if a script has a 0 in JSD_SCRIPT_PROFILE_BIT it is included in
* profile data, otherwise it is not profiled. Setting the
* PROFILE_WHEN_SET flag reverses this convention.
*/
const unsigned long PROFILE_WHEN_SET = 0x02;
/**
* Normally, when the script in the top frame of a thread state has a 1 in
* JSD_SCRIPT_DEBUG_BIT, the execution hook is ignored. Setting the
* DEBUG_WHEN_SET flag reverses this convention.
*/
const unsigned long DEBUG_WHEN_SET = 0x04;
/**
* When this flag is set the internal call hook will collect profile data.
*/
const unsigned long COLLECT_PROFILE_DATA = 0x08;
/**
* Debugger service flags.
@ -189,7 +227,12 @@ interface jsdIDebuggerService : nsISupports
* Force the engine to perform garbage collection.
*/
void GC();
/**
* Clear profile data for all scripts.
*/
void clearProfileData();
/**
* Adds an execution hook filter. These filters are consulted each time one
* of the jsdIExecutionHooks is about to be called. Filters are matched in
@ -620,29 +663,6 @@ interface jsdIContext : jsdIEphemeral
/* Internal use only. */
[noscript] readonly attribute JSContext JSContext;
/**
* VERSION_* values must be kept in sync with the JSVersion enumeration in
* jspubtd.h.
*/
/**
* Possible values for |version|.
*/
const long VERSION_1_0 = 100;
const long VERSION_1_1 = 110;
const long VERSION_1_2 = 120;
const long VERSION_1_3 = 130;
const long VERSION_1_4 = 140;
const long VERSION_1_5 = 150;
const long VERSION_DEFAULT = 0;
const long VERSION_UNKNOWN = -1;
/**
* Last version set on this context.
* Scripts typically select this with the "language" attribute.
*/
attribute long version;
/**
* OPT_* values must be kept in sync with JSOPTION_* #defines in jsapi.h.
*/
@ -669,7 +689,14 @@ interface jsdIContext : jsdIEphemeral
* OPT_* values above, OR'd together.
*/
attribute unsigned long options;
/**
* Last version set on this context.
* Scripts typically select this with the "language" attribute.
* See the VERSION_* consts on jsdIDebuggerService.
*/
attribute long version;
/**
* Unique tag among all valid jsdIContext objects, useful as a hash key.
*/
@ -790,13 +817,41 @@ interface jsdIScript : jsdIEphemeral
[noscript] readonly attribute JSDContext JSDContext;
/** Internal use only. */
[noscript] readonly attribute JSDScript JSDScript;
/**
* Last version set on this context.
* Scripts typically select this with the "language" attribute.
* See the VERSION_* consts on jsdIDebuggerService.
*/
readonly attribute long version;
/**
* Tag value guaranteed unique among jsdIScript objects. Useful as a
* hash key in script.
*/
readonly attribute unsigned long tag;
/**
* FLAG_* values need to be kept in sync with JSD_SCRIPT_* #defines in
* jsdebug.h.
*/
/**
* Determines whether or not to collect profile information for this
* script. The context flag FLAG_PROFILE_WHEN_SET decides the logic.
*/
const unsigned long FLAG_PROFILE = 0x01;
/**
* Determines whether or not to ignore breakpoints, etc. in this script.
* The context flag JSD_DEBUG_WHEN_SET decides the logic.
*/
const unsigned long FLAG_DEBUG = 0x02;
/**
* FLAG_* attributes from above, OR'd together.
*/
attribute unsigned long flags;
/**
* Filename given for this script when it was compiled.
* This data is copied from the underlying structure when the jsdIScript
@ -831,6 +886,32 @@ interface jsdIScript : jsdIEphemeral
*/
readonly attribute unsigned long lineExtent;
/**
* Number of times this script has been called.
*/
readonly attribute unsigned long callCount;
/**
* Number of times this script called itself, directly or indirectly.
*/
readonly attribute unsigned long maxRecurseDepth;
/**
* Shortest execution time recorded, in milliseconds.
*/
readonly attribute double minExecutionTime;
/**
* Longest execution time recorded, in milliseconds.
*/
readonly attribute double maxExecutionTime;
/**
* Total time spent in this function, in milliseconds.
*/
readonly attribute double totalExecutionTime;
/**
* Clear profile data for this script.
*/
void clearProfileData();
const unsigned long PCMAP_SOURCETEXT = 1; /* map to actual source text */
const unsigned long PCMAP_PRETTYPRINT = 2; /* map to pretty printed source */

Просмотреть файл

@ -85,6 +85,7 @@ JS_BEGIN_EXTERN_C
#include "jsscope.h"
#include "jsdbgapi.h"
#include "jsd_lock.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -111,13 +112,21 @@ JS_BEGIN_EXTERN_C
#undef CLEAR_BIT_FLAG
#define CLEAR_BIT_FLAG(f,b) ((f)&=(~(b)))
#define JSD_IS_DEBUG_ENABLED(jsdc,jsdscript) \
(!(((jsdc->flags & JSD_DEBUG_WHEN_SET) ? 1 : 0) ^ \
((jsdscript->flags & JSD_SCRIPT_DEBUG_BIT) ? 1 : 0)))
#define JSD_IS_PROFILE_ENABLED(jsdc,jsdscript) \
((jsdc->flags & JSD_COLLECT_PROFILE_DATA) && \
(!(((jsdc->flags & JSD_PROFILE_WHEN_SET) ? 1 : 0) ^ \
((jsdscript->flags & JSD_SCRIPT_PROFILE_BIT) ? 1 : 0))))
/***************************************************************************/
/* These are not exposed in jsdebug.h - typedef here for consistency */
typedef struct JSDExecHook JSDExecHook;
typedef struct JSDAtom JSDAtom;
typedef struct JSDProfileData JSDProfileData;
/***************************************************************************/
/* Our structures */
@ -154,6 +163,7 @@ struct JSDContext
JSD_UserCallbacks userCallbacks;
void* user;
JSCList scripts;
JSHashTable* scriptsTable;
JSCList sources;
JSCList removedSources;
uintN sourceAlterCount;
@ -183,13 +193,28 @@ struct JSDScript
uintN lineExtent; /* we cache this */
JSCList hooks; /* JSCList of JSDExecHooks for this script */
char* url;
uint32 flags;
void* data;
JSDProfileData *profileData;
#ifdef LIVEWIRE
LWDBGApp* app;
LWDBGScript* lwscript;
#endif
};
struct JSDProfileData
{
int64 lastCallStart;
uintN callCount;
uintN recurseDepth;
uintN maxRecurseDepth;
jsdouble minExecutionTime;
jsdouble maxExecutionTime;
jsdouble totalExecutionTime;
};
struct JSDSourceText
{
JSCList links; /* we are part of a JSCList */
@ -327,6 +352,9 @@ jsd_SetContextPrivate(JSDContext* jsdc, void *data);
extern void*
jsd_GetContextPrivate(JSDContext* jsdc);
extern void
jsd_ClearAllProfileData(JSDContext* jsdc);
extern JSBool
jsd_SetErrorReporter(JSDContext* jsdc,
JSD_ErrorReporter reporter,
@ -344,13 +372,43 @@ jsd_DebugErrorHook(JSContext *cx, const char *message,
/***************************************************************************/
/* Script functions */
extern JSBool
jsd_InitScriptManager(JSDContext *jsdc);
extern void
jsd_DestroyAllJSDScripts(JSDContext* jsdc);
jsd_DestroyScriptManager(JSDContext* jsdc);
extern JSDScript*
jsd_FindJSDScript(JSDContext* jsdc,
JSScript *script);
extern JSDProfileData*
jsd_GetScriptProfileData(JSDContext* jsdc, JSDScript *script);
extern uint32
jsd_GetScriptFlags(JSDContext *jsdc, JSDScript *script);
extern void
jsd_SetScriptFlags(JSDContext *jsdc, JSDScript *script, uint32 flags);
extern uintN
jsd_GetScriptCallCount(JSDContext* jsdc, JSDScript *script);
extern uintN
jsd_GetScriptMaxRecurseDepth(JSDContext* jsdc, JSDScript *script);
extern jsdouble
jsd_GetScriptMinExecutionTime(JSDContext* jsdc, JSDScript *script);
extern jsdouble
jsd_GetScriptMaxExecutionTime(JSDContext* jsdc, JSDScript *script);
extern jsdouble
jsd_GetScriptTotalExecutionTime(JSDContext* jsdc, JSDScript *script);
extern void
jsd_ClearScriptProfileData(JSDContext* jsdc, JSDScript *script);
extern JSScript *
jsd_GetJSScript (JSDContext *jsdc, JSDScript *script);

Просмотреть файл

@ -117,7 +117,6 @@ _newJSDContext(JSRuntime* jsrt,
#endif
JS_INIT_CLIST(&jsdc->threadsStates);
JS_INIT_CLIST(&jsdc->scripts);
JS_INIT_CLIST(&jsdc->sources);
JS_INIT_CLIST(&jsdc->removedSources);
@ -129,6 +128,9 @@ _newJSDContext(JSRuntime* jsrt,
if( ! jsd_InitObjectManager(jsdc) )
goto label_newJSDContext_failure;
if( ! jsd_InitScriptManager(jsdc) )
goto label_newJSDContext_failure;
jsdc->dumbContext = JS_NewContext(jsdc->jsrt, 256);
if( ! jsdc->dumbContext )
goto label_newJSDContext_failure;
@ -237,7 +239,7 @@ jsd_DebuggerOff(JSDContext* jsdc)
/* clean up */
JSD_LockScriptSubsystem(jsdc);
jsd_DestroyAllJSDScripts(jsdc);
jsd_DestroyScriptManager(jsdc);
JSD_UnlockScriptSubsystem(jsdc);
jsd_DestroyAllSources(jsdc);
@ -277,6 +279,22 @@ jsd_GetContextPrivate(JSDContext* jsdc)
return jsdc->data;
}
void
jsd_ClearAllProfileData(JSDContext* jsdc)
{
JSDScript *current;
JSD_LOCK_SCRIPTS(jsdc);
current = (JSDScript *)jsdc->scripts.next;
while (current != (JSDScript *)&jsdc->scripts)
{
jsd_ClearScriptProfileData(jsdc, current);
current = (JSDScript *)current->links.next;
}
JSD_UNLOCK_SCRIPTS(jsdc);
}
JSDContext*
jsd_JSDContextForJSContext(JSContext* context)
{

Просмотреть файл

@ -109,7 +109,8 @@ _newJSDScript(JSDContext* jsdc,
return NULL;
raw_filename = JS_GetScriptFilename(cx,script);
JS_HashTableAdd(jsdc->scriptsTable, (void *)script, (void *)jsdscript);
JS_APPEND_LINK(&jsdscript->links, &jsdc->scripts);
jsdscript->jsdc = jsdc;
jsdscript->script = script;
@ -162,6 +163,9 @@ _destroyJSDScript(JSDContext* jsdc,
if(jsdscript->url)
free(jsdscript->url);
if (jsdscript->profileData)
free(jsdscript->profileData);
if(jsdscript)
free(jsdscript);
}
@ -213,41 +217,152 @@ _dumpJSDScriptList( JSDContext* jsdc )
#endif /* JSD_DUMP */
/***************************************************************************/
void
jsd_DestroyAllJSDScripts( JSDContext* jsdc )
JS_STATIC_DLL_CALLBACK(JSHashNumber)
jsd_hash_script(const void *key)
{
JSDScript *jsdscript;
JSDScript *next;
return ((JSHashNumber) key) >> 2; /* help lame MSVC1.5 on Win16 */
}
JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
JS_STATIC_DLL_CALLBACK(void *)
jsd_alloc_script_table(void *priv, size_t size)
{
return malloc(size);
}
for( jsdscript = (JSDScript*)jsdc->scripts.next;
jsdscript != (JSDScript*)&jsdc->scripts;
jsdscript = next )
JS_STATIC_DLL_CALLBACK(void)
jsd_free_script_table(void *priv, void *item)
{
free(item);
}
JS_STATIC_DLL_CALLBACK(JSHashEntry *)
jsd_alloc_script_entry(void *priv, const void *item)
{
return (JSHashEntry*) malloc(sizeof(JSHashEntry));
}
JS_STATIC_DLL_CALLBACK(void)
jsd_free_script_entry(void *priv, JSHashEntry *he, uintN flag)
{
if (flag == HT_FREE_ENTRY)
{
next = (JSDScript*)jsdscript->links.next;
_destroyJSDScript( jsdc, jsdscript );
_destroyJSDScript((JSDContext*) priv, (JSDScript*) he->value);
free(he);
}
}
static JSHashAllocOps script_alloc_ops = {
jsd_alloc_script_table, jsd_free_script_table,
jsd_alloc_script_entry, jsd_free_script_entry
};
#ifndef JSD_SCRIPT_HASH_SIZE
#define JSD_SCRIPT_HASH_SIZE 1024
#endif
JSBool
jsd_InitScriptManager(JSDContext* jsdc)
{
JS_INIT_CLIST(&jsdc->scripts);
jsdc->scriptsTable = JS_NewHashTable(JSD_SCRIPT_HASH_SIZE, jsd_hash_script,
JS_CompareValues, JS_CompareValues,
&script_alloc_ops, (void*) jsdc);
return (JSBool) jsdc->scriptsTable;
}
void
jsd_DestroyScriptManager(JSDContext* jsdc)
{
JSD_LOCK_SCRIPTS(jsdc);
if (jsdc->scriptsTable)
JS_HashTableDestroy(jsdc->scriptsTable);
JSD_UNLOCK_SCRIPTS(jsdc);
}
JSDScript*
jsd_FindJSDScript( JSDContext* jsdc,
JSScript *script )
{
JSDScript *jsdscript;
JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
for( jsdscript = (JSDScript *)jsdc->scripts.next;
jsdscript != (JSDScript *)&jsdc->scripts;
jsdscript = (JSDScript *)jsdscript->links.next )
{
if (jsdscript->script == script)
return jsdscript;
}
return NULL;
return (JSDScript*) JS_HashTableLookup(jsdc->scriptsTable, (void *)script);
}
JSDProfileData*
jsd_GetScriptProfileData(JSDContext* jsdc, JSDScript *script)
{
if (!script->profileData)
script->profileData = (JSDProfileData*)calloc(1, sizeof(JSDProfileData));
return script->profileData;
}
uint32
jsd_GetScriptFlags(JSDContext *jsdc, JSDScript *script)
{
return script->flags;
}
void
jsd_SetScriptFlags(JSDContext *jsdc, JSDScript *script, uint32 flags)
{
script->flags = flags;
}
uintN
jsd_GetScriptCallCount(JSDContext* jsdc, JSDScript *script)
{
if (script->profileData)
return script->profileData->callCount;
return 0;
}
uintN
jsd_GetScriptMaxRecurseDepth(JSDContext* jsdc, JSDScript *script)
{
if (script->profileData)
return script->profileData->maxRecurseDepth;
return 0;
}
jsdouble
jsd_GetScriptMinExecutionTime(JSDContext* jsdc, JSDScript *script)
{
if (script->profileData)
return script->profileData->minExecutionTime;
return 0.0;
}
jsdouble
jsd_GetScriptMaxExecutionTime(JSDContext* jsdc, JSDScript *script)
{
if (script->profileData)
return script->profileData->maxExecutionTime;
return 0.0;
}
jsdouble
jsd_GetScriptTotalExecutionTime(JSDContext* jsdc, JSDScript *script)
{
if (script->profileData)
return script->profileData->totalExecutionTime;
return 0.0;
}
void
jsd_ClearScriptProfileData(JSDContext* jsdc, JSDScript *script)
{
if (script->profileData)
{
free(script->profileData);
script->profileData = NULL;
}
}
JSScript *
jsd_GetJSScript (JSDContext *jsdc, JSDScript *script)
{
@ -486,7 +601,7 @@ jsd_DestroyScriptHookProc(
hook(jsdc, jsdscript, JS_FALSE, hookData);
JSD_LOCK_SCRIPTS(jsdc);
_destroyJSDScript(jsdc, jsdscript);
JS_HashTableRemove(jsdc->scriptsTable, (void *)script);
JSD_UNLOCK_SCRIPTS(jsdc);
#ifdef JSD_DUMP

Просмотреть файл

@ -70,7 +70,7 @@ _addNewFrame(JSDContext* jsdc,
JSD_LOCK_SCRIPTS(jsdc);
jsdscript = jsd_FindJSDScript(jsdc, script);
JSD_UNLOCK_SCRIPTS(jsdc);
if( ! jsdscript )
if (!jsdscript || !JSD_IS_DEBUG_ENABLED(jsdc, jsdscript))
return NULL;
}
@ -128,7 +128,16 @@ jsd_NewThreadState(JSDContext* jsdc, JSContext *cx )
((jsdc->flags & JSD_INCLUDE_NATIVE_FRAMES) ||
!JS_IsNativeFrame(cx, fp)))
{
_addNewFrame( jsdc, jsdthreadstate, script, pc, fp );
if (!_addNewFrame( jsdc, jsdthreadstate, script, pc, fp ) &&
jsdthreadstate->stackDepth == 0)
{
/*
* if we failed to create the first frame, fail the entire
* thread state.
*/
break;
}
}
}

Просмотреть файл

@ -122,23 +122,67 @@ _callHook(JSDContext *jsdc, JSContext *cx, JSStackFrame *fp, JSBool before,
if (before && JS_IsConstructorFrame(cx, fp))
jsd_Constructing(jsdc, cx, JS_GetFrameThis(cx, fp), fp);
if (hook)
jsscript = JS_GetFrameScript(cx, fp);
if (jsscript)
{
jsscript = JS_GetFrameScript(cx, fp);
if (jsscript) {
JSD_LOCK_SCRIPTS(jsdc);
jsdscript = jsd_FindJSDScript(jsdc, jsscript);
JSD_UNLOCK_SCRIPTS(jsdc);
if (jsdscript) {
hookresult = jsd_CallCallHook (jsdc, cx, type, hook, hookData);
JSD_LOCK_SCRIPTS(jsdc);
jsdscript = jsd_FindJSDScript(jsdc, jsscript);
JSD_UNLOCK_SCRIPTS(jsdc);
if (jsdscript)
{
if (JSD_IS_PROFILE_ENABLED(jsdc, jsdscript))
{
JSDProfileData *pdata;
pdata = jsd_GetScriptProfileData (jsdc, jsdscript);
if (pdata)
{
if (before)
{
if (JSLL_IS_ZERO(pdata->lastCallStart))
{
pdata->lastCallStart = JS_Now();
} else {
if (++pdata->recurseDepth > pdata->maxRecurseDepth)
pdata->maxRecurseDepth = pdata->recurseDepth;
}
/* make sure we're called for the return too. */
hookresult = JS_TRUE;
} else if (!pdata->recurseDepth &&
!JSLL_IS_ZERO(pdata->lastCallStart)) {
int64 now, ll_delta;
jsdouble delta;
now = JS_Now();
JSLL_SUB(ll_delta, now, pdata->lastCallStart);
JSLL_L2D(delta, ll_delta);
delta /= 1000.0;
pdata->totalExecutionTime += delta;
if (!pdata->minExecutionTime ||
delta < pdata->minExecutionTime)
{
pdata->minExecutionTime = delta;
}
if (delta > pdata->maxExecutionTime)
pdata->maxExecutionTime = delta;
pdata->lastCallStart = JSLL_ZERO;
++pdata->callCount;
} else if (pdata->recurseDepth) {
--pdata->recurseDepth;
++pdata->callCount;
}
}
if (hook)
jsd_CallCallHook (jsdc, cx, type, hook, hookData);
} else {
if (hook)
hookresult =
jsd_CallCallHook (jsdc, cx, type, hook, hookData);
else
hookresult = JS_TRUE;
}
}
}
else
{
hookresult = JS_TRUE;
}
#ifdef JSD_TRACE
_interpreterTrace(jsdc, cx, fp, before);
return JS_TRUE;

Просмотреть файл

@ -215,7 +215,7 @@ jsd_GetValueString(JSDContext* jsdc, JSDValue* jsdval)
JS_RestoreExceptionState(cx, exceptionState);
if(jsdval->string)
{
if(!JS_AddRoot(cx, &jsdval->string))
if(!JS_AddNamedRoot(cx, &jsdval->string, "ValueString"))
jsdval->string = NULL;
}
}
@ -255,7 +255,7 @@ jsd_NewValue(JSDContext* jsdc, jsval val)
if(JSVAL_IS_GCTHING(val))
{
if(!JS_AddRoot(jsdc->dumbContext, &jsdval->val))
if(!JS_AddNamedRoot(jsdc->dumbContext, &jsdval->val, "JSDValue"))
{
free(jsdval);
return NULL;

Просмотреть файл

@ -378,10 +378,6 @@ jsds_FilterHook (JSDContext *jsdc, JSDThreadState *state)
return PR_TRUE;
jsuint pc = JSD_GetPCForStackFrame (jsdc, state, frame);
if (!pc) {
NS_WARNING("No pc in threadstate");
return PR_TRUE;
}
const char *url = JSD_GetScriptFilename (jsdc, script);
if (!url) {
@ -795,9 +791,14 @@ jsdObject::GetJSDObject(JSDObject **_rval)
NS_IMETHODIMP
jsdObject::GetCreatorURL(char **_rval)
{
*_rval = ToNewCString(nsDependentCString(JSD_GetObjectNewURL(mCx, mObject)));
if (!*_rval)
return NS_ERROR_OUT_OF_MEMORY;
const char *url = JSD_GetObjectNewURL(mCx, mObject);
if (url) {
*_rval = PL_strdup(url);
if (!*_rval)
return NS_ERROR_OUT_OF_MEMORY;
} else {
*_rval = nsnull;
}
return NS_OK;
}
@ -811,9 +812,14 @@ jsdObject::GetCreatorLine(PRUint32 *_rval)
NS_IMETHODIMP
jsdObject::GetConstructorURL(char **_rval)
{
*_rval = ToNewCString(nsDependentCString(JSD_GetObjectConstructorURL(mCx, mObject)));
if (!*_rval)
return NS_ERROR_OUT_OF_MEMORY;
const char *url = JSD_GetObjectConstructorURL(mCx, mObject);
if (url) {
*_rval = PL_strdup(url);
if (!*_rval)
return NS_ERROR_OUT_OF_MEMORY;
} else {
*_rval = nsnull;
}
return NS_OK;
}
@ -1105,6 +1111,16 @@ jsdScript::GetJSDScript(JSDScript **_rval)
return NS_OK;
}
NS_IMETHODIMP
jsdScript::GetVersion (PRInt32 *_rval)
{
ASSERT_VALID_EPHEMERAL;
JSContext *cx = JSD_GetDefaultJSContext (mCx);
JSScript *script = JSD_GetJSScript(mCx, mScript);
*_rval = NS_STATIC_CAST (PRInt32, JS_GetScriptVersion(cx, script));
return NS_OK;
}
NS_IMETHODIMP
jsdScript::GetTag(PRUint32 *_rval)
{
@ -1154,7 +1170,23 @@ jsdScript::GetIsValid(PRBool *_rval)
*_rval = mValid;
return NS_OK;
}
NS_IMETHODIMP
jsdScript::SetFlags(PRUint32 flags)
{
ASSERT_VALID_EPHEMERAL;
JSD_SetScriptFlags(mCx, mScript, flags);
return NS_OK;
}
NS_IMETHODIMP
jsdScript::GetFlags(PRUint32 *_rval)
{
ASSERT_VALID_EPHEMERAL;
*_rval = JSD_GetScriptFlags(mCx, mScript);
return NS_OK;
}
NS_IMETHODIMP
jsdScript::GetFileName(char **_rval)
{
@ -1213,6 +1245,54 @@ jsdScript::GetLineExtent(PRUint32 *_rval)
return NS_OK;
}
NS_IMETHODIMP
jsdScript::GetCallCount(PRUint32 *_rval)
{
ASSERT_VALID_EPHEMERAL;
*_rval = JSD_GetScriptCallCount (mCx, mScript);
return NS_OK;
}
NS_IMETHODIMP
jsdScript::GetMaxRecurseDepth(PRUint32 *_rval)
{
ASSERT_VALID_EPHEMERAL;
*_rval = JSD_GetScriptMaxRecurseDepth (mCx, mScript);
return NS_OK;
}
NS_IMETHODIMP
jsdScript::GetMinExecutionTime(double *_rval)
{
ASSERT_VALID_EPHEMERAL;
*_rval = JSD_GetScriptMinExecutionTime (mCx, mScript);
return NS_OK;
}
NS_IMETHODIMP
jsdScript::GetMaxExecutionTime(double *_rval)
{
ASSERT_VALID_EPHEMERAL;
*_rval = JSD_GetScriptMaxExecutionTime (mCx, mScript);
return NS_OK;
}
NS_IMETHODIMP
jsdScript::GetTotalExecutionTime(double *_rval)
{
ASSERT_VALID_EPHEMERAL;
*_rval = JSD_GetScriptTotalExecutionTime (mCx, mScript);
return NS_OK;
}
NS_IMETHODIMP
jsdScript::ClearProfileData()
{
ASSERT_VALID_EPHEMERAL;
JSD_ClearScriptProfileData(mCx, mScript);
return NS_OK;
}
NS_IMETHODIMP
jsdScript::PcToLine(PRUint32 aPC, PRUint32 aPcmap, PRUint32 *_rval)
{
@ -1565,15 +1645,15 @@ jsdStackFrame::GetFunctionName(char **_rval)
ASSERT_VALID_EPHEMERAL;
const char *name = JSD_GetNameForStackFrame(mCx, mThreadState,
mStackFrameInfo);
if (!name)
{
if (name) {
*_rval = PL_strdup(name);
if (!*_rval)
return NS_ERROR_OUT_OF_MEMORY;
} else {
/* top level scripts have no function name */
*_rval = nsnull;
return NS_OK;
}
*_rval = ToNewCString(nsDependentCString(name));
if (!*_rval)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
@ -1622,7 +1702,10 @@ jsdStackFrame::GetPc(PRUint32 *_rval)
jsuword pcbase = JSD_GetClosestPC(mCx, script, 0);
jsuword pc = JSD_GetPCForStackFrame (mCx, mThreadState, mStackFrameInfo);
*_rval = pc - pcbase;
if (pc)
*_rval = pc - pcbase;
else
*_rval = pcbase;
return NS_OK;
}
@ -1876,9 +1959,15 @@ NS_IMETHODIMP
jsdValue::GetJsClassName(char **_rval)
{
ASSERT_VALID_EPHEMERAL;
*_rval = ToNewCString(nsDependentCString(JSD_GetValueClassName(mCx, mValue)));
if (!*_rval)
return NS_ERROR_OUT_OF_MEMORY;
const char *name = JSD_GetValueClassName(mCx, mValue);
if (name) {
*_rval = PL_strdup(name);
if (!*_rval)
return NS_ERROR_OUT_OF_MEMORY;
} else {
*_rval = nsnull;
}
return NS_OK;
}
@ -1896,16 +1985,16 @@ jsdValue::GetJsFunctionName(char **_rval)
{
ASSERT_VALID_EPHEMERAL;
const char *name = JSD_GetValueFunctionName(mCx, mValue);
if (!name)
{
if (name) {
*_rval = PL_strdup(name);
if (!*_rval)
return NS_ERROR_OUT_OF_MEMORY;
} else {
/* top level scripts have no function name */
*_rval = nsnull;
return NS_OK;
}
*_rval = ToNewCString(nsDependentCString(*_rval));
if (!*_rval)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
@ -1953,9 +2042,14 @@ jsdValue::GetStringValue(char **_rval)
{
ASSERT_VALID_EPHEMERAL;
JSString *jstr_val = JSD_GetValueString(mCx, mValue);
*_rval = ToNewCString(nsDependentCString(JS_GetStringBytes(jstr_val)));
if (!*_rval)
return NS_ERROR_OUT_OF_MEMORY;
char *bytes = JS_GetStringBytes(jstr_val);
if (bytes) {
*_rval = PL_strdup(bytes);
if (!*_rval)
return NS_ERROR_OUT_OF_MEMORY;
} else {
*_rval = nsnull;
}
return NS_OK;
}
@ -2430,7 +2524,6 @@ jsdService::EnumerateScripts (jsdIScriptEnumerator *enumerator)
return rv;
}
NS_IMETHODIMP
jsdService::GC (void)
{
@ -2439,6 +2532,14 @@ jsdService::GC (void)
JS_GC(cx);
return NS_OK;
}
NS_IMETHODIMP
jsdService::ClearProfileData ()
{
ASSERT_VALID_CONTEXT;
JSD_ClearAllProfileData (mCx);
return NS_OK;
}
NS_IMETHODIMP
jsdService::InsertFilter (jsdIFilter *filter, jsdIFilter *after)

Просмотреть файл

@ -112,6 +112,13 @@ JSD_GetContextPrivate(JSDContext *jsdc)
return jsd_GetContextPrivate (jsdc);
}
JSD_PUBLIC_API(void)
JSD_ClearAllProfileData(JSDContext *jsdc)
{
JSD_ASSERT_VALID_CONTEXT(jsdc);
jsd_ClearAllProfileData(jsdc);
}
JSD_PUBLIC_API(void)
JSD_SetContextFlags(JSDContext *jsdc, uint32 flags)
{
@ -156,6 +163,63 @@ JSD_IterateScripts(JSDContext* jsdc, JSDScript **iterp)
return jsd_IterateScripts(jsdc, iterp);
}
JSD_PUBLIC_API(uint32)
JSD_GetScriptFlags(JSDContext *jsdc, JSDScript *script)
{
JSD_ASSERT_VALID_CONTEXT(jsdc);
return jsd_GetScriptFlags(jsdc, script);
}
JSD_PUBLIC_API(void)
JSD_SetScriptFlags(JSDContext *jsdc, JSDScript *script, uint32 flags)
{
JSD_ASSERT_VALID_CONTEXT(jsdc);
jsd_SetScriptFlags(jsdc, script, flags);
}
JSD_PUBLIC_API(uintN)
JSD_GetScriptCallCount(JSDContext* jsdc, JSDScript *script)
{
JSD_ASSERT_VALID_CONTEXT(jsdc);
return jsd_GetScriptCallCount(jsdc, script);
}
JSD_PUBLIC_API(uintN)
JSD_GetScriptMaxRecurseDepth(JSDContext* jsdc, JSDScript *script)
{
JSD_ASSERT_VALID_CONTEXT(jsdc);
return jsd_GetScriptMaxRecurseDepth(jsdc, script);
}
JSD_PUBLIC_API(jsdouble)
JSD_GetScriptMinExecutionTime(JSDContext* jsdc, JSDScript *script)
{
JSD_ASSERT_VALID_CONTEXT(jsdc);
return jsd_GetScriptMinExecutionTime(jsdc, script);
}
JSD_PUBLIC_API(jsdouble)
JSD_GetScriptMaxExecutionTime(JSDContext* jsdc, JSDScript *script)
{
JSD_ASSERT_VALID_CONTEXT(jsdc);
return jsd_GetScriptMaxExecutionTime(jsdc, script);
}
JSD_PUBLIC_API(jsdouble)
JSD_GetScriptTotalExecutionTime(JSDContext* jsdc, JSDScript *script)
{
JSD_ASSERT_VALID_CONTEXT(jsdc);
return jsd_GetScriptTotalExecutionTime(jsdc, script);
}
JSD_PUBLIC_API(void)
JSD_ClearScriptProfileData(JSDContext* jsdc, JSDScript *script)
{
JSD_ASSERT_VALID_CONTEXT(jsdc);
jsd_ClearScriptProfileData(jsdc, script);
}
JSD_PUBLIC_API(JSScript*)
JSD_GetJSScript(JSDContext* jsdc, JSDScript *script)
{

Просмотреть файл

@ -179,10 +179,34 @@ JSD_SetContextPrivate(JSDContext *jsdc, void *data);
extern JSD_PUBLIC_API(void *)
JSD_GetContextPrivate(JSDContext *jsdc);
/*
* Clear profile data for all scripts
*/
extern JSD_PUBLIC_API(void)
JSD_ClearAllProfileData(JSDContext* jsdc);
/*
* Context flags.
*/
#define JSD_INCLUDE_NATIVE_FRAMES 0x1
/* Include native frames in JSDThreadStates. */
#define JSD_INCLUDE_NATIVE_FRAMES 0x01
/*
* Normally, if a script has a 0 in JSD_SCRIPT_PROFILE_BIT it is included in
* profile data, otherwise it is not profiled. Setting the JSD_PROFILE_WHEN_SET
* flag reverses this convention.
*/
#define JSD_PROFILE_WHEN_SET 0x02
/*
* Normally, when the script in the top frame of a thread state has a 1 in
* JSD_SCRIPT_DEBUG_BIT, the execution hook is ignored. Setting the
* JSD_DEBUG_WHEN_SET flag reverses this convention.
*/
#define JSD_DEBUG_WHEN_SET 0x04
/*
* When this flag is set the internal call hook will collect profile data.
*/
#define JSD_COLLECT_PROFILE_DATA 0x08
extern JSD_PUBLIC_API(void)
JSD_SetContextFlags (JSDContext* jsdc, uint32 flags);
@ -245,6 +269,42 @@ JSD_UnlockScriptSubsystem(JSDContext* jsdc);
extern JSD_PUBLIC_API(JSDScript*)
JSD_IterateScripts(JSDContext* jsdc, JSDScript **iterp);
/*
* Get the number of times this script has been called.
*/
extern JSD_PUBLIC_API(uintN)
JSD_GetScriptCallCount(JSDContext* jsdc, JSDScript *script);
/*
* Get the max number of times this script called itself, directly or indirectly.
*/
extern JSD_PUBLIC_API(uintN)
JSD_GetScriptMaxRecurseDepth(JSDContext* jsdc, JSDScript *script);
/*
* Get the shortest execution time recorded.
*/
extern JSD_PUBLIC_API(jsdouble)
JSD_GetScriptMinExecutionTime(JSDContext* jsdc, JSDScript *script);
/*
* Get the longest execution time recorded.
*/
extern JSD_PUBLIC_API(jsdouble)
JSD_GetScriptMaxExecutionTime(JSDContext* jsdc, JSDScript *script);
/*
* Get the total amount of time spent in this script.
*/
extern JSD_PUBLIC_API(jsdouble)
JSD_GetScriptTotalExecutionTime(JSDContext* jsdc, JSDScript *script);
/*
* Clear profile data for this script.
*/
extern JSD_PUBLIC_API(void)
JSD_ClearScriptProfileData(JSDContext* jsdc, JSDScript *script);
/*
* Get the JSScript for a JSDScript
*/
@ -256,18 +316,35 @@ JSD_GetJSScript(JSDContext* jsdc, JSDScript *script);
*/
extern JSD_PUBLIC_API(JSFunction*)
JSD_GetJSFunction(JSDContext* jsdc, JSDScript *script);
/*
* Determines whether or not to collect profile information for this
* script. The context flag JSD_PROFILE_WHEN_SET decides the logic.
*/
#define JSD_SCRIPT_PROFILE_BIT 0x01
/*
* Determines whether or not to ignore breakpoints, etc. in this script.
* The context flag JSD_DEBUG_WHEN_SET decides the logic.
*/
#define JSD_SCRIPT_DEBUG_BIT 0x02
extern JSD_PUBLIC_API(uint32)
JSD_GetScriptFlags(JSDContext *jsdc, JSDScript* jsdscript);
extern JSD_PUBLIC_API(void)
JSD_SetScriptFlags(JSDContext *jsdc, JSDScript* jsdscript, uint32 flags);
/*
* Set the private data for this script, returns previous value
*/
extern JSD_PUBLIC_API(void *)
JSD_SetScriptPrivate(JSDScript *jsdscript, void *data);
JSD_SetScriptPrivate(JSDScript* jsdscript, void *data);
/*
* Get the private data for this script
*/
extern JSD_PUBLIC_API(void *)
JSD_GetScriptPrivate(JSDScript *jsdscript);
JSD_GetScriptPrivate(JSDScript* jsdscript);
/*
* Determine if this script is still loaded in the interpreter