Bug 833817 part 3 - Replace JSStackFrame with JSAbstractFramePtr. r=luke

This commit is contained in:
Jan de Mooij 2013-01-25 09:49:29 +01:00
Родитель 9bf0337f71
Коммит 7799c058c4
15 изменённых файлов: 441 добавлений и 385 удалений

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

@ -210,7 +210,8 @@ struct JSDStackFrameInfo
JSDThreadState* jsdthreadstate;
JSDScript* jsdscript;
uintptr_t pc;
JSStackFrame* fp;
bool isConstructing;
JSAbstractFramePtr frame;
};
#define GOT_PROTO ((short) (1 << 0))
@ -347,7 +348,7 @@ extern JSDScript*
jsd_FindOrCreateJSDScript(JSDContext *jsdc,
JSContext *cx,
JSScript *script,
JSStackFrame *fp);
JSAbstractFramePtr frame);
extern JSDProfileData*
jsd_GetScriptProfileData(JSDContext* jsdc, JSDScript *script);
@ -978,12 +979,12 @@ jsd_GetPropertyFlags(JSDContext* jsdc, JSDProperty* jsdprop);
/* Stepping Functions */
extern void *
jsd_FunctionCallHook(JSContext *cx, JSStackFrame *fp, JSBool before,
JSBool *ok, void *closure);
jsd_FunctionCallHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing,
JSBool before, JSBool *ok, void *closure);
extern void *
jsd_TopLevelCallHook(JSContext *cx, JSStackFrame *fp, JSBool before,
JSBool *ok, void *closure);
jsd_TopLevelCallHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing,
JSBool before, JSBool *ok, void *closure);
/**************************************************/
/* Object Functions */
@ -999,7 +1000,7 @@ jsd_DestroyObjects(JSDContext* jsdc);
extern void
jsd_Constructing(JSDContext* jsdc, JSContext *cx, JSObject *obj,
JSStackFrame *fp);
JSAbstractFramePtr frame);
extern JSDObject*
jsd_IterateObjects(JSDContext* jsdc, JSDObject** iterp);

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

@ -34,7 +34,7 @@ jsd_InterruptHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rva
return JSTRAP_CONTINUE;
JSD_LOCK_SCRIPTS(jsdc);
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, NULL);
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, JSNullFramePtr());
JSD_UNLOCK_SCRIPTS(jsdc);
if( ! jsdscript )
return JSTRAP_CONTINUE;
@ -72,7 +72,7 @@ jsd_DebuggerHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
return JSTRAP_CONTINUE;
JSD_LOCK_SCRIPTS(jsdc);
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, NULL);
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, JSNullFramePtr());
JSD_UNLOCK_SCRIPTS(jsdc);
if( ! jsdscript )
return JSTRAP_CONTINUE;
@ -106,7 +106,7 @@ jsd_ThrowHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
return JSTRAP_CONTINUE;
JSD_LOCK_SCRIPTS(jsdc);
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, NULL);
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, JSNullFramePtr());
JSD_UNLOCK_SCRIPTS(jsdc);
if( ! jsdscript )
return JSTRAP_CONTINUE;

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

@ -80,7 +80,7 @@ _destroyJSDObject(JSDContext* jsdc, JSDObject* jsdobj)
void
jsd_Constructing(JSDContext* jsdc, JSContext *cx, JSObject *obj,
JSStackFrame *fp)
JSAbstractFramePtr frame)
{
JSDObject* jsdobj;
JSScript* script;
@ -93,7 +93,7 @@ jsd_Constructing(JSDContext* jsdc, JSContext *cx, JSObject *obj,
jsdobj = jsd_GetJSDObjectForJSObject(jsdc, obj);
if( jsdobj && !jsdobj->ctorURL )
{
script = JS_GetFrameScript(cx, fp);
script = frame.script();
if( script )
{
ctorURL = JS_GetScriptFilename(cx, script);
@ -101,7 +101,7 @@ jsd_Constructing(JSDContext* jsdc, JSContext *cx, JSObject *obj,
jsdobj->ctorURL = jsd_AddAtom(jsdc, ctorURL);
JSD_LOCK_SCRIPTS(jsdc);
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, fp);
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, frame);
JSD_UNLOCK_SCRIPTS(jsdc);
if( jsdscript && (ctorNameStr = jsd_GetScriptFunctionId(jsdc, jsdscript)) ) {
if( (ctorName = JS_EncodeString(cx, ctorNameStr)) ) {

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

@ -278,7 +278,7 @@ JSDScript *
jsd_FindOrCreateJSDScript(JSDContext *jsdc,
JSContext *cx,
JSScript *script,
JSStackFrame *fp)
JSAbstractFramePtr frame)
{
JSDScript *jsdscript;
JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
@ -288,9 +288,12 @@ jsd_FindOrCreateJSDScript(JSDContext *jsdc,
return jsdscript;
/* Fallback for unknown scripts: create a new script. */
if (!fp)
JS_BrokenFrameIterator(cx, &fp);
if (fp)
if (!frame) {
JSBrokenFrameIterator iter(cx);
if (!iter.done())
frame = iter.abstractFramePtr();
}
if (frame)
jsdscript = _newJSDScript(jsdc, cx, script);
return jsdscript;

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

@ -29,7 +29,8 @@ _addNewFrame(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSScript* script,
uintptr_t pc,
JSStackFrame* fp)
bool isConstructing,
JSAbstractFramePtr frame)
{
JSDStackFrameInfo* jsdframe;
JSDScript* jsdscript = NULL;
@ -52,8 +53,9 @@ _addNewFrame(JSDContext* jsdc,
jsdframe->jsdthreadstate = jsdthreadstate;
jsdframe->jsdscript = jsdscript;
jsdframe->isConstructing = isConstructing;
jsdframe->pc = pc;
jsdframe->fp = fp;
jsdframe->frame = frame;
JS_APPEND_LINK(&jsdframe->links, &jsdthreadstate->stack);
jsdthreadstate->stackDepth++;
@ -74,8 +76,6 @@ JSDThreadState*
jsd_NewThreadState(JSDContext* jsdc, JSContext *cx )
{
JSDThreadState* jsdthreadstate;
JSStackFrame * iter = NULL;
JSStackFrame * fp;
jsdthreadstate = (JSDThreadState*)calloc(1, sizeof(JSDThreadState));
if( ! jsdthreadstate )
@ -87,10 +87,13 @@ jsd_NewThreadState(JSDContext* jsdc, JSContext *cx )
jsdthreadstate->stackDepth = 0;
JS_BeginRequest(jsdthreadstate->context);
while( NULL != (fp = JS_BrokenFrameIterator(cx, &iter)) )
JSBrokenFrameIterator iter(cx);
while(!iter.done())
{
JSScript* script = JS_GetFrameScript(cx, fp);
uintptr_t pc = (uintptr_t) JS_GetFramePC(cx, fp);
JSAbstractFramePtr frame = iter.abstractFramePtr();
JSScript* script = frame.script();
uintptr_t pc = (uintptr_t)iter.pc();
jsval dummyThis;
/*
@ -98,15 +101,14 @@ jsd_NewThreadState(JSDContext* jsdc, JSContext *cx )
* |this| object, or native frames, if JSD_INCLUDE_NATIVE_FRAMES
* isn't set.
*/
if (JS_GetFrameThis(cx, fp, &dummyThis))
if (frame.getThisValue(cx, &dummyThis))
{
JSDStackFrameInfo *frame;
bool isConstructing = iter.isConstructing();
JSDStackFrameInfo *frameInfo = _addNewFrame( jsdc, jsdthreadstate, script, pc, isConstructing, frame );
frame = _addNewFrame( jsdc, jsdthreadstate, script, pc, fp );
if ((jsdthreadstate->stackDepth == 0 && !frame) ||
(jsdthreadstate->stackDepth == 1 && frame &&
frame->jsdscript && !JSD_IS_DEBUG_ENABLED(jsdc, frame->jsdscript)))
if ((jsdthreadstate->stackDepth == 0 && !frameInfo) ||
(jsdthreadstate->stackDepth == 1 && frameInfo &&
frameInfo->jsdscript && !JSD_IS_DEBUG_ENABLED(jsdc, frameInfo->jsdscript)))
{
/*
* if we failed to create the first frame, or the top frame
@ -118,6 +120,8 @@ jsd_NewThreadState(JSDContext* jsdc, JSContext *cx )
return NULL;
}
}
++iter;
}
JS_EndRequest(jsdthreadstate->context);
@ -262,7 +266,7 @@ jsd_GetCallObjectForStackFrame(JSDContext* jsdc,
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
{
obj = JS_GetFrameCallObject(jsdthreadstate->context, jsdframe->fp);
obj = jsdframe->frame.callObject(jsdthreadstate->context);
if(obj)
jsdval = JSD_NewValue(jsdc, OBJECT_TO_JSVAL(obj));
}
@ -285,10 +289,10 @@ jsd_GetScopeChainForStackFrame(JSDContext* jsdc,
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
{
JS_BeginRequest(jsdthreadstate->context);
obj = JS_GetFrameScopeChain(jsdthreadstate->context, jsdframe->fp);
obj = jsdframe->frame.scopeChain(jsdthreadstate->context);
JS_EndRequest(jsdthreadstate->context);
if(obj)
jsdval = JSD_NewValue(jsdc, OBJECT_TO_JSVAL(obj));
if(obj)
jsdval = JSD_NewValue(jsdc, OBJECT_TO_JSVAL(obj));
}
JSD_UNLOCK_THREADSTATES(jsdc);
@ -309,7 +313,7 @@ jsd_GetThisForStackFrame(JSDContext* jsdc,
JSBool ok;
jsval thisval;
JS_BeginRequest(jsdthreadstate->context);
ok = JS_GetFrameThis(jsdthreadstate->context, jsdframe->fp, &thisval);
ok = jsdframe->frame.getThisValue(jsdthreadstate->context, &thisval);
JS_EndRequest(jsdthreadstate->context);
if(ok)
jsdval = JSD_NewValue(jsdc, thisval);
@ -330,8 +334,7 @@ jsd_GetIdForStackFrame(JSDContext* jsdc,
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
{
JSFunction *fun = JS_GetFrameFunction (jsdthreadstate->context,
jsdframe->fp);
JSFunction *fun = jsdframe->frame.maybeFun();
if( fun )
{
rv = JS_GetFunctionId (fun);
@ -359,7 +362,7 @@ jsd_IsStackFrameDebugger(JSDContext* jsdc,
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
{
rv = JS_IsDebuggerFrame(jsdthreadstate->context, jsdframe->fp);
rv = jsdframe->frame.isDebuggerFrame();
}
JSD_UNLOCK_THREADSTATES(jsdc);
@ -376,7 +379,7 @@ jsd_IsStackFrameConstructing(JSDContext* jsdc,
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
{
rv = JS_IsConstructorFrame(jsdthreadstate->context, jsdframe->fp);
rv = jsdframe->isConstructing;
}
JSD_UNLOCK_THREADSTATES(jsdc);
@ -412,8 +415,8 @@ jsd_EvaluateUCScriptInStackFrame(JSDContext* jsdc,
exceptionState = JS_SaveExceptionState(cx);
JS_ClearPendingException(cx);
jsd_StartingEvalUsingFilename(jsdc, filename);
retval = JS_EvaluateUCInStackFrame(cx, jsdframe->fp, bytes, length,
filename, lineno, rval);
retval = jsdframe->frame.evaluateUCInStackFrame(cx, bytes, length, filename, lineno,
rval);
jsd_FinishedEvalUsingFilename(jsdc, filename);
if (eatExceptions)
JS_RestoreExceptionState(cx, exceptionState);
@ -450,8 +453,8 @@ jsd_EvaluateScriptInStackFrame(JSDContext* jsdc,
exceptionState = JS_SaveExceptionState(cx);
JS_ClearPendingException(cx);
jsd_StartingEvalUsingFilename(jsdc, filename);
retval = JS_EvaluateInStackFrame(cx, jsdframe->fp, bytes, length,
filename, lineno, rval);
retval = jsdframe->frame.evaluateInStackFrame(cx, bytes, length, filename, lineno,
rval);
jsd_FinishedEvalUsingFilename(jsdc, filename);
if (eatExceptions)
JS_RestoreExceptionState(cx, exceptionState);

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

@ -31,19 +31,19 @@ _indentSpaces(int i)
}
static void
_interpreterTrace(JSDContext* jsdc, JSContext *cx, JSStackFrame *fp,
JSBool before)
_interpreterTrace(JSDContext* jsdc, JSContext *cx, JSAbstractFramePtr frame,
bool isConstructing, JSBool before)
{
JSDScript* jsdscript = NULL;
JSScript * script;
static indent = 0;
JSString* funName = NULL;
script = JS_GetFrameScript(cx, fp);
script = frame.script();
if(script)
{
JSD_LOCK_SCRIPTS(jsdc);
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, fp);
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, frame);
JSD_UNLOCK_SCRIPTS(jsdc);
if(jsdscript)
funName = JSD_GetScriptFunctionId(jsdc, jsdscript);
@ -63,9 +63,9 @@ _interpreterTrace(JSDContext* jsdc, JSContext *cx, JSStackFrame *fp,
{
jsval thisVal;
printf("%s this: ", JS_IsConstructorFrame(cx, fp) ? "constructing":"");
printf("%s this: ", isConstructing ? "constructing":"");
if (JS_GetFrameThis(cx, fp, &thisVal))
if (JS_GetFrameThis(cx, frame, &thisVal))
printf("0x%0llx", (uintptr_t) thisVal);
else
puts("<unavailable>");
@ -76,8 +76,8 @@ _interpreterTrace(JSDContext* jsdc, JSContext *cx, JSStackFrame *fp,
#endif
JSBool
_callHook(JSDContext *jsdc, JSContext *cx, JSStackFrame *fp, JSBool before,
unsigned type, JSD_CallHookProc hook, void *hookData)
_callHook(JSDContext *jsdc, JSContext *cx, JSAbstractFramePtr frame, bool isConstructing,
JSBool before, unsigned type, JSD_CallHookProc hook, void *hookData)
{
JSDScript* jsdscript;
JSScript* jsscript;
@ -93,19 +93,19 @@ _callHook(JSDContext *jsdc, JSContext *cx, JSStackFrame *fp, JSBool before,
*/
return hookresult;
}
if (before && JS_IsConstructorFrame(cx, fp)) {
if (before && isConstructing) {
jsval newObj;
if (!JS_GetFrameThis(cx, fp, &newObj))
if (!frame.getThisValue(cx, &newObj))
return JS_FALSE;
jsd_Constructing(jsdc, cx, JSVAL_TO_OBJECT(newObj), fp);
jsd_Constructing(jsdc, cx, JSVAL_TO_OBJECT(newObj), frame);
}
jsscript = JS_GetFrameScript(cx, fp);
jsscript = frame.script();
if (jsscript)
{
JSD_LOCK_SCRIPTS(jsdc);
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, jsscript, fp);
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, jsscript, frame);
JSD_UNLOCK_SCRIPTS(jsdc);
if (jsdscript)
@ -223,7 +223,7 @@ _callHook(JSDContext *jsdc, JSContext *cx, JSStackFrame *fp, JSBool before,
}
#ifdef JSD_TRACE
_interpreterTrace(jsdc, cx, fp, before);
_interpreterTrace(jsdc, cx, frame, isConstructing, before);
return JS_TRUE;
#else
return hookresult;
@ -232,8 +232,8 @@ _callHook(JSDContext *jsdc, JSContext *cx, JSStackFrame *fp, JSBool before,
}
void *
jsd_FunctionCallHook(JSContext *cx, JSStackFrame *fp, JSBool before,
JSBool *ok, void *closure)
jsd_FunctionCallHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing,
JSBool before, JSBool *ok, void *closure)
{
JSDContext* jsdc;
JSD_CallHookProc hook;
@ -247,7 +247,7 @@ jsd_FunctionCallHook(JSContext *cx, JSStackFrame *fp, JSBool before,
hookData = jsdc->functionHookData;
JSD_UNLOCK();
if (_callHook (jsdc, cx, fp, before,
if (_callHook (jsdc, cx, frame, isConstructing, before,
(before) ? JSD_HOOK_FUNCTION_CALL : JSD_HOOK_FUNCTION_RETURN,
hook, hookData))
{
@ -258,8 +258,8 @@ jsd_FunctionCallHook(JSContext *cx, JSStackFrame *fp, JSBool before,
}
void *
jsd_TopLevelCallHook(JSContext *cx, JSStackFrame *fp, JSBool before,
JSBool *ok, void *closure)
jsd_TopLevelCallHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing,
JSBool before, JSBool *ok, void *closure)
{
JSDContext* jsdc;
JSD_CallHookProc hook;
@ -273,7 +273,7 @@ jsd_TopLevelCallHook(JSContext *cx, JSStackFrame *fp, JSBool before,
hookData = jsdc->toplevelHookData;
JSD_UNLOCK();
if (_callHook (jsdc, cx, fp, before,
if (_callHook (jsdc, cx, frame, isConstructing, before,
(before) ? JSD_HOOK_TOPLEVEL_START : JSD_HOOK_TOPLEVEL_END,
hook, hookData))
{

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

@ -13,12 +13,13 @@
static int callCount[2] = {0, 0};
static void *
callCountHook(JSContext *cx, JSStackFrame *fp, JSBool before, JSBool *ok, void *closure)
callCountHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing, JSBool before,
JSBool *ok, void *closure)
{
callCount[before]++;
jsval thisv;
JS_GetFrameThis(cx, fp, &thisv); // assert if fp is incomplete
frame.getThisValue(cx, &thisv); // assert if fp is incomplete
return cx; // any non-null value causes the hook to be called again after
}
@ -38,12 +39,13 @@ BEGIN_TEST(testDebugger_bug519719)
END_TEST(testDebugger_bug519719)
static void *
nonStrictThisHook(JSContext *cx, JSStackFrame *fp, JSBool before, JSBool *ok, void *closure)
nonStrictThisHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing, JSBool before,
JSBool *ok, void *closure)
{
if (before) {
bool *allWrapped = (bool *) closure;
js::RootedValue thisv(cx);
JS_GetFrameThis(cx, fp, thisv.address());
frame.getThisValue(cx, thisv.address());
*allWrapped = *allWrapped && !JSVAL_IS_PRIMITIVE(thisv);
}
return NULL;
@ -76,12 +78,13 @@ BEGIN_TEST(testDebugger_getThisNonStrict)
END_TEST(testDebugger_getThisNonStrict)
static void *
strictThisHook(JSContext *cx, JSStackFrame *fp, JSBool before, JSBool *ok, void *closure)
strictThisHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing, JSBool before,
JSBool *ok, void *closure)
{
if (before) {
bool *anyWrapped = (bool *) closure;
js::RootedValue thisv(cx);
JS_GetFrameThis(cx, fp, thisv.address());
frame.getThisValue(cx, thisv.address());
*anyWrapped = *anyWrapped || !JSVAL_IS_PRIMITIVE(thisv);
}
return NULL;

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

@ -71,6 +71,14 @@ JS_SetRuntimeDebugMode(JSRuntime *rt, JSBool debug)
rt->debugMode = !!debug;
}
static bool
IsTopFrameConstructing(JSContext *cx, AbstractFramePtr frame)
{
ScriptFrameIter iter(cx);
JS_ASSERT(iter.abstractFramePtr() == frame);
return iter.isConstructing();
}
JSTrapStatus
js::ScriptDebugPrologue(JSContext *cx, AbstractFramePtr frame)
{
@ -78,12 +86,12 @@ js::ScriptDebugPrologue(JSContext *cx, AbstractFramePtr frame)
if (frame.isFramePushedByExecute()) {
if (JSInterpreterHook hook = cx->runtime->debugHooks.executeHook)
frame.setHookData(hook(cx, Jsvalify(frame.asStackFrame()), true, 0,
cx->runtime->debugHooks.executeHookData));
frame.setHookData(hook(cx, Jsvalify(frame), IsTopFrameConstructing(cx, frame),
true, 0, cx->runtime->debugHooks.executeHookData));
} else {
if (JSInterpreterHook hook = cx->runtime->debugHooks.callHook)
frame.setHookData(hook(cx, Jsvalify(frame.asStackFrame()), true, 0,
cx->runtime->debugHooks.callHookData));
frame.setHookData(hook(cx, Jsvalify(frame), IsTopFrameConstructing(cx, frame),
true, 0, cx->runtime->debugHooks.callHookData));
}
RootedValue rval(cx);
@ -115,10 +123,10 @@ js::ScriptDebugEpilogue(JSContext *cx, AbstractFramePtr frame, bool okArg)
if (void *hookData = frame.maybeHookData()) {
if (frame.isFramePushedByExecute()) {
if (JSInterpreterHook hook = cx->runtime->debugHooks.executeHook)
hook(cx, Jsvalify(frame.asStackFrame()), false, &ok, hookData);
hook(cx, Jsvalify(frame), IsTopFrameConstructing(cx, frame), false, &ok, hookData);
} else {
if (JSInterpreterHook hook = cx->runtime->debugHooks.callHook)
hook(cx, Jsvalify(frame.asStackFrame()), false, &ok, hookData);
hook(cx, Jsvalify(frame), IsTopFrameConstructing(cx, frame), false, &ok, hookData);
}
}
@ -537,103 +545,6 @@ JS_GetScriptOriginPrincipals(JSScript *script)
/************************************************************************/
JS_PUBLIC_API(JSStackFrame *)
JS_BrokenFrameIterator(JSContext *cx, JSStackFrame **iteratorp)
{
StackFrame *fp = Valueify(*iteratorp);
if (!fp) {
#ifdef JS_METHODJIT
js::mjit::ExpandInlineFrames(cx->compartment);
#endif
fp = cx->maybefp();
} else {
fp = fp->prev();
}
// settle on the next non-ion frame as it is not considered safe to inspect
// Ion's activation StackFrame.
while (fp && fp->runningInIon())
fp = fp->prev();
*iteratorp = Jsvalify(fp);
return *iteratorp;
}
JS_PUBLIC_API(JSScript *)
JS_GetFrameScript(JSContext *cx, JSStackFrame *fpArg)
{
return Valueify(fpArg)->script();
}
JS_PUBLIC_API(jsbytecode *)
JS_GetFramePC(JSContext *cx, JSStackFrame *fpArg)
{
/*
* This API is used to compute the line number for jsd and XPConnect
* exception handling backtraces. Once the stack gets really deep, the
* overall cost can become quadratic. This can hang the browser (eventually
* terminated by a slow-script dialog) when content causes infinite
* recursion and a backtrace.
*/
return Valueify(fpArg)->pcQuadratic(cx->stack, 100);
}
JS_PUBLIC_API(JSObject *)
JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fpArg)
{
StackFrame *fp = Valueify(fpArg);
JS_ASSERT(cx->stack.space().containsSlow(fp));
AutoCompartment ac(cx, fp->scopeChain());
return GetDebugScopeForFrame(cx, fp);
}
JS_PUBLIC_API(JSObject *)
JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fpArg)
{
StackFrame *fp = Valueify(fpArg);
JS_ASSERT(cx->stack.space().containsSlow(fp));
if (!fp->isFunctionFrame())
return NULL;
JSObject *o = GetDebugScopeForFrame(cx, fp);
/*
* Given that fp is a function frame and GetDebugScopeForFrame always fills
* in missing scopes, we can expect to find fp's CallObject on 'o'. Note:
* - GetDebugScopeForFrame wraps every ScopeObject (missing or not) with
* a DebugScopeObject proxy.
* - If fp is an eval-in-function, then fp has no callobj of its own and
* JS_GetFrameCallObject will return the innermost function's callobj.
*/
while (o) {
ScopeObject &scope = o->asDebugScope().scope();
if (scope.isCall())
return o;
o = o->enclosingScope();
}
return NULL;
}
JS_PUBLIC_API(JSBool)
JS_GetFrameThis(JSContext *cx, JSStackFrame *fpArg, jsval *thisv)
{
StackFrame *fp = Valueify(fpArg);
js::AutoCompartment ac(cx, fp->scopeChain());
if (!ComputeThis(cx, fp))
return false;
*thisv = fp->thisValue();
return true;
}
JS_PUBLIC_API(JSFunction *)
JS_GetFrameFunction(JSContext *cx, JSStackFrame *fp)
{
return Valueify(fp)->maybeScriptFunction();
}
JS_PUBLIC_API(JSFunction *)
JS_GetScriptFunction(JSContext *cx, JSScript *script)
{
@ -646,12 +557,6 @@ JS_GetParentOrScopeChain(JSContext *cx, JSObject *obj)
return obj->enclosingScope();
}
JS_PUBLIC_API(JSBool)
JS_IsConstructorFrame(JSContext *cx, JSStackFrame *fp)
{
return Valueify(fp)->isConstructing();
}
JS_PUBLIC_API(const char *)
JS_GetDebugClassName(JSObject *obj)
{
@ -660,18 +565,6 @@ JS_GetDebugClassName(JSObject *obj)
return obj->getClass()->name;
}
JS_PUBLIC_API(JSBool)
JS_IsDebuggerFrame(JSContext *cx, JSStackFrame *fp)
{
return Valueify(fp)->isDebuggerFrame();
}
JS_PUBLIC_API(JSBool)
JS_IsGlobalFrame(JSContext *cx, JSStackFrame *fp)
{
return Valueify(fp)->isGlobalFrame();
}
/************************************************************************/
JS_PUBLIC_API(const char *)
@ -737,56 +630,6 @@ JS_SetDestroyScriptHook(JSRuntime *rt, JSDestroyScriptHook hook,
/***************************************************************************/
JS_PUBLIC_API(JSBool)
JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fpArg,
const jschar *chars, unsigned length,
const char *filename, unsigned lineno,
jsval *rval)
{
if (!CheckDebugMode(cx))
return false;
Rooted<Env*> env(cx, JS_GetFrameScopeChain(cx, fpArg));
if (!env)
return false;
StackFrame *fp = Valueify(fpArg);
if (!ComputeThis(cx, fp))
return false;
RootedValue thisv(cx, fp->thisValue());
js::AutoCompartment ac(cx, env);
return EvaluateInEnv(cx, env, thisv, fp, StableCharPtr(chars, length), length,
filename, lineno, rval);
}
JS_PUBLIC_API(JSBool)
JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp,
const char *bytes, unsigned length,
const char *filename, unsigned lineno,
jsval *rval)
{
jschar *chars;
JSBool ok;
size_t len = length;
if (!CheckDebugMode(cx))
return JS_FALSE;
chars = InflateString(cx, bytes, &len);
if (!chars)
return JS_FALSE;
length = (unsigned) len;
ok = JS_EvaluateUCInStackFrame(cx, fp, chars, length, filename, lineno,
rval);
js_free(chars);
return ok;
}
/************************************************************************/
/* This all should be reworked to avoid requiring JSScopeProperty types. */
static JSBool
@ -1293,7 +1136,8 @@ FormatFrame(JSContext *cx, const ScriptFrameIter &iter, char *buf, int num,
AutoPropertyDescArray callProps(cx);
if (!iter.isIon() && (showArgs || showLocals)) {
callObj = JS_GetFrameCallObject(cx, Jsvalify(iter.interpFrame()));
JSAbstractFramePtr frame(Jsvalify(iter.abstractFramePtr()));
callObj = frame.callObject(cx);
if (callObj)
callProps.fetch(callObj);
}
@ -1461,3 +1305,175 @@ JS::FormatStackDump(JSContext *cx, char *buf,
return buf;
}
JSAbstractFramePtr::JSAbstractFramePtr(void *raw)
: ptr_(uintptr_t(raw))
{ }
JSObject *
JSAbstractFramePtr::scopeChain(JSContext *cx)
{
AbstractFramePtr frame = Valueify(*this);
JS_ASSERT_IF(frame.isStackFrame(),
cx->stack.space().containsSlow(frame.asStackFrame()));
RootedObject scopeChain(cx, frame.scopeChain());
AutoCompartment ac(cx, scopeChain);
return GetDebugScopeForFrame(cx, frame);
}
JSObject *
JSAbstractFramePtr::callObject(JSContext *cx)
{
AbstractFramePtr frame = Valueify(*this);
JS_ASSERT_IF(frame.isStackFrame(),
cx->stack.space().containsSlow(frame.asStackFrame()));
if (!frame.isFunctionFrame())
return NULL;
JSObject *o = GetDebugScopeForFrame(cx, frame);
/*
* Given that fp is a function frame and GetDebugScopeForFrame always fills
* in missing scopes, we can expect to find fp's CallObject on 'o'. Note:
* - GetDebugScopeForFrame wraps every ScopeObject (missing or not) with
* a DebugScopeObject proxy.
* - If fp is an eval-in-function, then fp has no callobj of its own and
* JS_GetFrameCallObject will return the innermost function's callobj.
*/
while (o) {
ScopeObject &scope = o->asDebugScope().scope();
if (scope.isCall())
return o;
o = o->enclosingScope();
}
return NULL;
}
JSFunction *
JSAbstractFramePtr::maybeFun()
{
AbstractFramePtr frame = Valueify(*this);
return frame.maybeFun();
}
JSScript *
JSAbstractFramePtr::script()
{
AbstractFramePtr frame = Valueify(*this);
return frame.script();
}
bool
JSAbstractFramePtr::getThisValue(JSContext *cx, jsval *thisv)
{
AbstractFramePtr frame = Valueify(*this);
RootedObject scopeChain(cx, frame.scopeChain());
js::AutoCompartment ac(cx, scopeChain);
if (!ComputeThis(cx, frame))
return false;
*thisv = frame.thisValue();
return true;
}
bool
JSAbstractFramePtr::isDebuggerFrame()
{
AbstractFramePtr frame = Valueify(*this);
return frame.isDebuggerFrame();
}
bool
JSAbstractFramePtr::evaluateInStackFrame(JSContext *cx,
const char *bytes, unsigned length,
const char *filename, unsigned lineno,
jsval *rval)
{
if (!CheckDebugMode(cx))
return false;
size_t len = length;
jschar *chars = InflateString(cx, bytes, &len);
if (!chars)
return false;
length = (unsigned) len;
bool ok = evaluateUCInStackFrame(cx, chars, length, filename, lineno, rval);
js_free(chars);
return ok;
}
bool
JSAbstractFramePtr::evaluateUCInStackFrame(JSContext *cx,
const jschar *chars, unsigned length,
const char *filename, unsigned lineno,
jsval *rval)
{
if (!CheckDebugMode(cx))
return false;
RootedObject scope(cx, scopeChain(cx));
Rooted<Env*> env(cx, scope);
if (!env)
return false;
AbstractFramePtr frame = Valueify(*this);
if (!ComputeThis(cx, frame))
return false;
RootedValue thisv(cx, frame.thisValue());
js::AutoCompartment ac(cx, env);
return EvaluateInEnv(cx, env, thisv, frame, StableCharPtr(chars, length), length,
filename, lineno, rval);
}
JSBrokenFrameIterator::JSBrokenFrameIterator(JSContext *cx)
{
ScriptFrameIter iter(cx);
data_ = iter.copyData();
}
JSBrokenFrameIterator::~JSBrokenFrameIterator()
{
js_free((StackIter::Data *)data_);
}
bool
JSBrokenFrameIterator::done() const
{
ScriptFrameIter iter(*(StackIter::Data *)data_);
return iter.done();
}
JSBrokenFrameIterator &
JSBrokenFrameIterator::operator++()
{
StackIter::Data *data = (StackIter::Data *)data_;
ScriptFrameIter iter(*data);
++iter;
*data = iter.data_;
return *this;
}
JSAbstractFramePtr
JSBrokenFrameIterator::abstractFramePtr() const
{
ScriptFrameIter iter(*(StackIter::Data *)data_);
return Jsvalify(iter.abstractFramePtr());
}
jsbytecode *
JSBrokenFrameIterator::pc() const
{
ScriptFrameIter iter(*(StackIter::Data *)data_);
return iter.pc();
}
bool
JSBrokenFrameIterator::isConstructing() const
{
ScriptFrameIter iter(*(StackIter::Data *)data_);
return iter.isConstructing();
}

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

@ -191,53 +191,12 @@ JS_GetScriptPrincipals(JSScript *script);
extern JS_PUBLIC_API(JSPrincipals *)
JS_GetScriptOriginPrincipals(JSScript *script);
/*
* This function does not work when IonMonkey is active. It remains for legacy
* code: caps/principal clamping, which will be removed shortly after
* compartment-per-global, and jsd, which can only be used when IonMonkey is
* disabled.
*
* To find the calling script and line number, use JS_DescribeSciptedCaller.
* To summarize the call stack, use JS::DescribeStack.
*/
extern JS_PUBLIC_API(JSStackFrame *)
JS_BrokenFrameIterator(JSContext *cx, JSStackFrame **iteratorp);
extern JS_PUBLIC_API(JSScript *)
JS_GetFrameScript(JSContext *cx, JSStackFrame *fp);
extern JS_PUBLIC_API(jsbytecode *)
JS_GetFramePC(JSContext *cx, JSStackFrame *fp);
extern JS_PUBLIC_API(JSObject *)
JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp);
extern JS_PUBLIC_API(JSObject *)
JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fp);
extern JS_PUBLIC_API(JSBool)
JS_GetFrameThis(JSContext *cx, JSStackFrame *fp, jsval *thisv);
extern JS_PUBLIC_API(JSFunction *)
JS_GetFrameFunction(JSContext *cx, JSStackFrame *fp);
JS_PUBLIC_API(JSFunction *)
JS_GetScriptFunction(JSContext *cx, JSScript *script);
extern JS_PUBLIC_API(JSObject *)
JS_GetParentOrScopeChain(JSContext *cx, JSObject *obj);
/* XXXrginda Initially published with typo */
#define JS_IsContructorFrame JS_IsConstructorFrame
extern JS_PUBLIC_API(JSBool)
JS_IsConstructorFrame(JSContext *cx, JSStackFrame *fp);
extern JS_PUBLIC_API(JSBool)
JS_IsDebuggerFrame(JSContext *cx, JSStackFrame *fp);
extern JS_PUBLIC_API(JSBool)
JS_IsGlobalFrame(JSContext *cx, JSStackFrame *fp);
/************************************************************************/
/*
@ -291,20 +250,6 @@ JS_SetDestroyScriptHook(JSRuntime *rt, JSDestroyScriptHook hook,
/************************************************************************/
extern JS_PUBLIC_API(JSBool)
JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fp,
const jschar *chars, unsigned length,
const char *filename, unsigned lineno,
jsval *rval);
extern JS_PUBLIC_API(JSBool)
JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp,
const char *bytes, unsigned length,
const char *filename, unsigned lineno,
jsval *rval);
/************************************************************************/
typedef struct JSPropertyDesc {
jsval id; /* primary id, atomized string, or int */
jsval value; /* property value */
@ -337,6 +282,135 @@ JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda);
/************************************************************************/
/*
* JSAbstractFramePtr is the public version of AbstractFramePtr, a pointer to a
* StackFrame or baseline JIT frame.
*/
class JS_PUBLIC_API(JSAbstractFramePtr)
{
uintptr_t ptr_;
protected:
JSAbstractFramePtr()
: ptr_(0)
{ }
public:
explicit JSAbstractFramePtr(void *raw);
uintptr_t raw() const { return ptr_; }
operator bool() const { return !!ptr_; }
JSObject *scopeChain(JSContext *cx);
JSObject *callObject(JSContext *cx);
JSFunction *maybeFun();
JSScript *script();
bool getThisValue(JSContext *cx, jsval *thisv);
bool isDebuggerFrame();
bool evaluateInStackFrame(JSContext *cx,
const char *bytes, unsigned length,
const char *filename, unsigned lineno,
jsval *rval);
bool evaluateUCInStackFrame(JSContext *cx,
const jschar *chars, unsigned length,
const char *filename, unsigned lineno,
jsval *rval);
};
class JS_PUBLIC_API(JSNullFramePtr) : public JSAbstractFramePtr
{
public:
JSNullFramePtr()
: JSAbstractFramePtr()
{}
};
/*
* This class does not work when IonMonkey is active. It's only used by jsd,
* which can only be used when IonMonkey is disabled.
*
* To find the calling script and line number, use JS_DescribeSciptedCaller.
* To summarize the call stack, use JS::DescribeStack.
*/
class JS_PUBLIC_API(JSBrokenFrameIterator)
{
void *data_;
public:
JSBrokenFrameIterator(JSContext *cx);
~JSBrokenFrameIterator();
bool done() const;
JSBrokenFrameIterator& operator++();
JSAbstractFramePtr abstractFramePtr() const;
jsbytecode *pc() const;
bool isConstructing() const;
};
/*
* This hook captures high level script execution and function calls (JS or
* native). It is used by JS_SetExecuteHook to hook top level scripts and by
* JS_SetCallHook to hook function calls. It will get called twice per script
* or function call: just before execution begins and just after it finishes.
* In both cases the 'current' frame is that of the executing code.
*
* The 'before' param is JS_TRUE for the hook invocation before the execution
* and JS_FALSE for the invocation after the code has run.
*
* The 'ok' param is significant only on the post execution invocation to
* signify whether or not the code completed 'normally'.
*
* The 'closure' param is as passed to JS_SetExecuteHook or JS_SetCallHook
* for the 'before'invocation, but is whatever value is returned from that
* invocation for the 'after' invocation. Thus, the hook implementor *could*
* allocate a structure in the 'before' invocation and return a pointer to that
* structure. The pointer would then be handed to the hook for the 'after'
* invocation. Alternately, the 'before' could just return the same value as
* in 'closure' to cause the 'after' invocation to be called with the same
* 'closure' value as the 'before'.
*
* Returning NULL in the 'before' hook will cause the 'after' hook *not* to
* be called.
*/
typedef void *
(* JSInterpreterHook)(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing,
JSBool before, JSBool *ok, void *closure);
typedef JSBool
(* JSDebugErrorHook)(JSContext *cx, const char *message, JSErrorReport *report,
void *closure);
typedef struct JSDebugHooks {
JSInterruptHook interruptHook;
void *interruptHookData;
JSNewScriptHook newScriptHook;
void *newScriptHookData;
JSDestroyScriptHook destroyScriptHook;
void *destroyScriptHookData;
JSDebuggerHandler debuggerHandler;
void *debuggerHandlerData;
JSSourceHandler sourceHandler;
void *sourceHandlerData;
JSInterpreterHook executeHook;
void *executeHookData;
JSInterpreterHook callHook;
void *callHookData;
JSThrowHook throwHook;
void *throwHookData;
JSDebugErrorHook debugErrorHook;
void *debugErrorHookData;
} JSDebugHooks;
/************************************************************************/
extern JS_PUBLIC_API(JSBool)
JS_SetDebuggerHandler(JSRuntime *rt, JSDebuggerHandler hook, void *closure);

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

@ -283,60 +283,6 @@ typedef void
(* JSSourceHandler)(const char *filename, unsigned lineno, const jschar *str,
size_t length, void **listenerTSData, void *closure);
/*
* This hook captures high level script execution and function calls (JS or
* native). It is used by JS_SetExecuteHook to hook top level scripts and by
* JS_SetCallHook to hook function calls. It will get called twice per script
* or function call: just before execution begins and just after it finishes.
* In both cases the 'current' frame is that of the executing code.
*
* The 'before' param is JS_TRUE for the hook invocation before the execution
* and JS_FALSE for the invocation after the code has run.
*
* The 'ok' param is significant only on the post execution invocation to
* signify whether or not the code completed 'normally'.
*
* The 'closure' param is as passed to JS_SetExecuteHook or JS_SetCallHook
* for the 'before'invocation, but is whatever value is returned from that
* invocation for the 'after' invocation. Thus, the hook implementor *could*
* allocate a structure in the 'before' invocation and return a pointer to that
* structure. The pointer would then be handed to the hook for the 'after'
* invocation. Alternately, the 'before' could just return the same value as
* in 'closure' to cause the 'after' invocation to be called with the same
* 'closure' value as the 'before'.
*
* Returning NULL in the 'before' hook will cause the 'after' hook *not* to
* be called.
*/
typedef void *
(* JSInterpreterHook)(JSContext *cx, JSStackFrame *fp, JSBool before,
JSBool *ok, void *closure);
typedef JSBool
(* JSDebugErrorHook)(JSContext *cx, const char *message, JSErrorReport *report,
void *closure);
typedef struct JSDebugHooks {
JSInterruptHook interruptHook;
void *interruptHookData;
JSNewScriptHook newScriptHook;
void *newScriptHookData;
JSDestroyScriptHook destroyScriptHook;
void *destroyScriptHookData;
JSDebuggerHandler debuggerHandler;
void *debuggerHandlerData;
JSSourceHandler sourceHandler;
void *sourceHandlerData;
JSInterpreterHook executeHook;
void *executeHookData;
JSInterpreterHook callHook;
void *callHookData;
JSThrowHook throwHook;
void *throwHookData;
JSDebugErrorHook debugErrorHook;
void *debugErrorHookData;
} JSDebugHooks;
/* js::ObjectOps function pointer typedefs. */
/*

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

@ -181,7 +181,6 @@ typedef struct JSPropertyName JSPropertyName;
typedef struct JSPropertySpec JSPropertySpec;
typedef struct JSRuntime JSRuntime;
typedef struct JSSecurityCallbacks JSSecurityCallbacks;
typedef struct JSStackFrame JSStackFrame;
typedef struct JSStructuredCloneCallbacks JSStructuredCloneCallbacks;
typedef struct JSStructuredCloneReader JSStructuredCloneReader;
typedef struct JSStructuredCloneWriter JSStructuredCloneWriter;

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

@ -1539,7 +1539,7 @@ TrapHandler(JSContext *cx, RawScript, jsbytecode *pc, jsval *rval,
JS_ASSERT(!iter.done());
/* Debug-mode currently disables Ion compilation. */
JSStackFrame *caller = Jsvalify(iter.interpFrame());
JSAbstractFramePtr frame(Jsvalify(iter.abstractFramePtr()));
RootedScript script(cx, iter.script());
size_t length;
@ -1547,10 +1547,11 @@ TrapHandler(JSContext *cx, RawScript, jsbytecode *pc, jsval *rval,
if (!chars)
return JSTRAP_ERROR;
if (!JS_EvaluateUCInStackFrame(cx, caller, chars, length,
script->filename,
script->lineno,
rval)) {
if (!frame.evaluateUCInStackFrame(cx, chars, length,
script->filename,
script->lineno,
rval))
{
return JSTRAP_ERROR;
}
if (!JSVAL_IS_VOID(*rval))
@ -2635,13 +2636,13 @@ EvalInFrame(JSContext *cx, unsigned argc, jsval *vp)
if (!chars)
return false;
StackFrame *fp = fi.interpFrame();
RootedScript fpscript(cx, fp->script());
bool ok = !!JS_EvaluateUCInStackFrame(cx, Jsvalify(fp), chars, length,
fpscript->filename,
JS_PCToLineNumber(cx, fpscript,
fi.pc()),
vp);
JSAbstractFramePtr frame(Jsvalify(fi.abstractFramePtr()));
RootedScript fpscript(cx, frame.script());
bool ok = !!frame.evaluateUCInStackFrame(cx, chars, length,
fpscript->filename,
JS_PCToLineNumber(cx, fpscript,
fi.pc()),
vp);
if (saved)
JS_RestoreFrameChain(cx);

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

@ -795,6 +795,14 @@ AbstractFramePtr::fun() const
JS_NOT_REACHED("Invalid frame");
return NULL;
}
inline JSFunction *
AbstractFramePtr::maybeFun() const
{
if (isStackFrame())
return asStackFrame()->maybeFun();
JS_NOT_REACHED("Invalid frame");
return NULL;
}
inline JSFunction &
AbstractFramePtr::callee() const
{

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

@ -238,6 +238,11 @@ class AbstractFramePtr
JS_ASSERT((uintptr_t(fp) & 1) == 0);
}
explicit AbstractFramePtr(JSAbstractFramePtr frame)
: ptr_(uintptr_t(frame.raw()))
{
}
bool isStackFrame() const {
return ptr_ & 0x1;
}
@ -274,6 +279,7 @@ class AbstractFramePtr
inline UnrootedScript script() const;
inline JSFunction *fun() const;
inline JSFunction *maybeFun() const;
inline JSFunction &callee() const;
inline Value calleev() const;
inline Value &thisValue() const;
@ -761,7 +767,7 @@ class StackFrame
* All function frames have an associated interpreted JSFunction. The
* function returned by fun() and maybeFun() is not necessarily the
* original canonical function which the frame's script was compiled
* against. To get this function, use maybeScriptFunction().
* against.
*/
JSFunction* fun() const {
@ -773,15 +779,6 @@ class StackFrame
return isFunctionFrame() ? fun() : NULL;
}
JSFunction* maybeScriptFunction() const {
if (!isFunctionFrame())
return NULL;
const StackFrame *fp = this;
while (fp->isEvalFrame())
fp = fp->prev();
return fp->script()->function();
}
/*
* This value
*
@ -1222,8 +1219,8 @@ InitialFrameFlagsAreLowered(InitialFrameFlags initial)
return !!(initial & INITIAL_LOWERED);
}
inline StackFrame * Valueify(JSStackFrame *fp) { return (StackFrame *)fp; }
static inline JSStackFrame * Jsvalify(StackFrame *fp) { return (JSStackFrame *)fp; }
inline AbstractFramePtr Valueify(JSAbstractFramePtr frame) { return AbstractFramePtr(frame); }
static inline JSAbstractFramePtr Jsvalify(AbstractFramePtr frame) { return JSAbstractFramePtr(frame.raw()); }
/*****************************************************************************/
@ -1879,6 +1876,7 @@ class StackIter
};
friend class ContextStack;
friend class ::JSBrokenFrameIterator;
private:
Data data_;
#ifdef JS_ION

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

@ -71,10 +71,6 @@ xpcDumpEvalErrorReporter(JSContext *cx, const char *message,
JSBool
xpc_DumpEvalInJSStackFrame(JSContext* cx, uint32_t frameno, const char* text)
{
JSStackFrame* fp;
JSStackFrame* iter = nullptr;
uint32_t num = 0;
if (!cx || !text) {
DebugDump("%s", "invalid params passed to xpc_DumpEvalInJSStackFrame!\n");
return false;
@ -82,13 +78,21 @@ xpc_DumpEvalInJSStackFrame(JSContext* cx, uint32_t frameno, const char* text)
DebugDump("js[%d]> %s\n", frameno, text);
while (nullptr != (fp = JS_BrokenFrameIterator(cx, &iter))) {
if (num == frameno)
uint32_t num = 0;
JSAbstractFramePtr frame = JSNullFramePtr();
JSBrokenFrameIterator iter(cx);
while (!iter.done()) {
if (num == frameno) {
frame = iter.abstractFramePtr();
break;
}
++iter;
num++;
}
if (!fp) {
if (!frame) {
DebugDump("%s", "invalid frame number!\n");
return false;
}
@ -101,7 +105,7 @@ xpc_DumpEvalInJSStackFrame(JSContext* cx, uint32_t frameno, const char* text)
jsval rval;
JSString* str;
JSAutoByteString bytes;
if (JS_EvaluateInStackFrame(cx, fp, text, strlen(text), "eval", 1, &rval) &&
if (frame.evaluateInStackFrame(cx, text, strlen(text), "eval", 1, &rval) &&
nullptr != (str = JS_ValueToString(cx, rval)) &&
bytes.encode(cx, str)) {
DebugDump("%s\n", bytes.ptr());