Bug 602003: add jsd API to query valid script begin and end PCs, r=sayrer,jjb

This commit is contained in:
David Mandelin 2010-10-06 11:23:14 -07:00
parent 22817a28df
commit 544d2fb3f2
10 changed files with 75 additions and 15 deletions

View File

@ -1001,6 +1001,17 @@ interface jsdIScript : jsdIEphemeral
* The |pcmap| argument specifies which pc to source line map to use.
*/
boolean isLineExecutable (in unsigned long line, in unsigned long pcmap);
/**
* Get the first valid PC in the script. This will be either
* (a) the first bytecode in the script, or (b) the next bytecode
* in the script, iff the first bytecode is a JSOP_BEGIN.
*/
unsigned long getFirstValidPC ();
/**
* Return the last valid PC in the script (i.e., the PC just after
* the last bytecode).
*/
unsigned long getEndValidPC ();
/**
* Set a breakpoint at a PC in this script.
*/

View File

@ -478,6 +478,9 @@ jsd_GetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc* hook, void** callerdata)
extern jsuword
jsd_GetClosestPC(JSDContext* jsdc, JSDScript* jsdscript, uintN line);
extern jsuword
jsd_GetEndPC(JSDContext* jsdc, JSDScript* jsdscript);
extern uintN
jsd_GetClosestLine(JSDContext* jsdc, JSDScript* jsdscript, jsuword pc);

View File

@ -500,20 +500,16 @@ jsd_GetScriptLineExtent(JSDContext* jsdc, JSDScript *jsdscript)
jsuword
jsd_GetClosestPC(JSDContext* jsdc, JSDScript* jsdscript, uintN line)
{
#ifdef LIVEWIRE
if( jsdscript && jsdscript->lwscript )
{
uintN newline;
jsdlw_RawToProcessedLineNumber(jsdc, jsdscript, line, &newline);
if( line != newline )
line = newline;
}
#endif
return (jsuword) JS_LineNumberToPC(jsdc->dumbContext,
jsdscript->script, line );
}
jsuword
jsd_GetEndPC(JSDContext* jsdc, JSDScript* jsdscript)
{
return (jsuword) JS_EndPC(jsdc->dumbContext, jsdscript->script );
}
uintN
jsd_GetClosestLine(JSDContext* jsdc, JSDScript* jsdscript, jsuword pc)
{

View File

@ -958,7 +958,8 @@ jsdScript::jsdScript (JSDContext *aCx, JSDScript *aScript) : mValid(PR_FALSE),
mBaseLineNumber(0),
mLineExtent(0),
mPPLineMap(0),
mFirstPC(0)
mFirstPC(0),
mEndPC(0)
{
DEBUG_CREATE ("jsdScript", gScriptCount);
@ -972,6 +973,7 @@ jsdScript::jsdScript (JSDContext *aCx, JSDScript *aScript) : mValid(PR_FALSE),
mBaseLineNumber = JSD_GetScriptBaseLineNumber(mCx, mScript);
mLineExtent = JSD_GetScriptLineExtent(mCx, mScript);
mFirstPC = JSD_GetClosestPC(mCx, mScript, 0);
mEndPC = JSD_GetEndPC(mCx, mScript);
JSD_UnlockScriptSubsystem(mCx);
mValid = PR_TRUE;
@ -1475,6 +1477,25 @@ jsdScript::IsLineExecutable(PRUint32 aLine, PRUint32 aPcmap, PRBool *_rval)
return NS_OK;
}
NS_IMETHODIMP
jsdScript::GetFirstValidPC(PRUint32 *_rval)
{
ASSERT_VALID_EPHEMERAL;
jsbytecode *pc = (jsbytecode *) mFirstPC;
if (*pc == JSOP_BEGIN)
++pc;
*_rval = PRUint32(pc);
return NS_OK;
}
NS_IMETHODIMP
jsdScript::GetEndValidPC(PRUint32 *_rval)
{
ASSERT_VALID_EPHEMERAL;
*_rval = PRUint32(mEndPC);
return NS_OK;
}
NS_IMETHODIMP
jsdScript::SetBreakpoint(PRUint32 aPC)
{

View File

@ -183,6 +183,7 @@ class jsdScript : public jsdIScript
PCMapEntry *mPPLineMap;
PRUint32 mPCMapSize;
jsuword mFirstPC;
jsuword mEndPC;
};
PRUint32 jsdScript::LastTag = 0;

View File

@ -348,6 +348,14 @@ JSD_GetClosestPC(JSDContext* jsdc, JSDScript* jsdscript, uintN line)
return jsd_GetClosestPC(jsdc, jsdscript, line);
}
JSD_PUBLIC_API(jsuword)
JSD_GetEndPC(JSDContext* jsdc, JSDScript* jsdscript)
{
JSD_ASSERT_VALID_CONTEXT(jsdc);
JSD_ASSERT_VALID_SCRIPT(jsdscript);
return jsd_GetEndPC(jsdc, jsdscript);
}
JSD_PUBLIC_API(uintN)
JSD_GetClosestLine(JSDContext* jsdc, JSDScript* jsdscript, jsuword pc)
{

View File

@ -486,6 +486,13 @@ JSD_GetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc* hook, void** callerdata)
extern JSD_PUBLIC_API(jsuword)
JSD_GetClosestPC(JSDContext* jsdc, JSDScript* jsdscript, uintN line);
/*
* Get the 'Program Counter' value just after the last byte of the script.
* 0 is returned for invalid scripts.
*/
extern JSD_PUBLIC_API(jsuword)
JSD_GetEndPC(JSDContext* jsdc, JSDScript* jsdscript);
/*
* Get the source line number for a given 'Program Counter' location.
* Returns 0 if no source line information is appropriate (or available) for

View File

@ -475,7 +475,9 @@ AllFramesIter::operator++()
{
JS_ASSERT(!done());
if (curfp == curcs->getInitialFrame()) {
curcs = curcs->getPreviousInMemory();
do {
curcs = curcs->getPreviousInMemory();
} while (curcs && !curcs->inContext());
curfp = curcs ? curcs->getCurrentFrame() : NULL;
} else {
curfp = curfp->prev();

View File

@ -235,9 +235,11 @@ JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
return JS_FALSE;
}
// Do not trap BEGIN, it's a special prologue opcode.
if (JSOp(*pc) == JSOP_BEGIN)
pc += JSOP_BEGIN_LENGTH;
if (JSOp(*pc) == JSOP_BEGIN) {
JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage,
NULL, JSMSG_READ_ONLY, "trap invalid on BEGIN opcode");
return JS_FALSE;
}
JS_ASSERT((JSOp) *pc != JSOP_TRAP);
junk = NULL;
@ -1019,6 +1021,12 @@ JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno)
return js_LineNumberToPC(script, lineno);
}
JS_PUBLIC_API(jsbytecode *)
JS_EndPC(JSContext *cx, JSScript *script)
{
return script->code + script->length;
}
JS_PUBLIC_API(uintN)
JS_GetFunctionArgumentCount(JSContext *cx, JSFunction *fun)
{

View File

@ -159,6 +159,9 @@ JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc);
extern JS_PUBLIC_API(jsbytecode *)
JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno);
extern JS_PUBLIC_API(jsbytecode *)
JS_EndPC(JSContext *cx, JSScript *script);
extern JS_PUBLIC_API(uintN)
JS_GetFunctionArgumentCount(JSContext *cx, JSFunction *fun);