Bug 768446 - Remove StackIter::sp_ (r=dvander)

--HG--
extra : rebase_source : 4a2e40e8cc8d8bddcefd2a2687354b5dacd3f248
This commit is contained in:
Luke Wagner 2012-06-29 10:34:09 -07:00
parent 1437538c15
commit 18656f0a0a
16 changed files with 131 additions and 233 deletions

View File

@ -12,6 +12,6 @@ try {
new x;
}
catch (e) {
assertEq(e.message, 'new x is not a constructor');
assertEq(String(e.message).indexOf('is not a constructor') === -1, false);
}
throw "ExitCleanly"

View File

@ -258,7 +258,6 @@ JS_ConvertArgumentsVA(JSContext *cx, unsigned argc, jsval *argv, const char *for
jsval *sp;
JSBool required;
char c;
JSFunction *fun;
double d;
JSString *str;
JSObject *obj;
@ -277,8 +276,7 @@ JS_ConvertArgumentsVA(JSContext *cx, unsigned argc, jsval *argv, const char *for
}
if (sp == argv + argc) {
if (required) {
fun = js_ValueToFunction(cx, &argv[-2], 0);
if (fun) {
if (JSFunction *fun = ReportIfNotFunction(cx, argv[-2])) {
char numBuf[12];
JS_snprintf(numBuf, sizeof numBuf, "%u", argc);
JSAutoByteString funNameBytes;
@ -342,7 +340,7 @@ JS_ConvertArgumentsVA(JSContext *cx, unsigned argc, jsval *argv, const char *for
*va_arg(ap, JSObject **) = obj;
break;
case 'f':
obj = js_ValueToFunction(cx, sp, 0);
obj = ReportIfNotFunction(cx, *sp);
if (!obj)
return JS_FALSE;
*sp = OBJECT_TO_JSVAL(obj);
@ -436,7 +434,7 @@ JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp)
break;
case JSTYPE_FUNCTION:
*vp = v;
obj = js_ValueToFunction(cx, vp, JSV2F_SEARCH_STACK);
obj = ReportIfNotFunction(cx, *vp);
ok = (obj != NULL);
break;
case JSTYPE_STRING:
@ -479,7 +477,7 @@ JS_ValueToFunction(JSContext *cx, jsval v)
AssertNoGC(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, v);
return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK);
return ReportIfNotFunction(cx, v);
}
JS_PUBLIC_API(JSFunction *)
@ -488,7 +486,7 @@ JS_ValueToConstructor(JSContext *cx, jsval v)
AssertNoGC(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, v);
return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK);
return ReportIfNotFunction(cx, v);
}
JS_PUBLIC_API(JSString *)
@ -4612,12 +4610,7 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent_)
}
if (!funobj->isFunction()) {
/*
* We cannot clone this object, so fail (we used to return funobj, bad
* idea, but we changed incompatibly to teach any abusers a lesson!).
*/
Value v = ObjectValue(*funobj);
js_ReportIsNotFunction(cx, &v, 0);
ReportIsNotFunction(cx, ObjectValue(*funobj));
return NULL;
}

View File

@ -3209,7 +3209,7 @@ array_readonlyCommon(JSContext *cx, CallArgs &args)
js_ReportMissingArg(cx, args.calleev(), 0);
return false;
}
RootedObject callable(cx, js_ValueToCallableObject(cx, &args[0], JSV2F_SEARCH_STACK));
RootedObject callable(cx, ValueToCallable(cx, &args[0]));
if (!callable)
return false;
@ -3301,7 +3301,7 @@ array_map(JSContext *cx, unsigned argc, Value *vp)
js_ReportMissingArg(cx, args.calleev(), 0);
return false;
}
RootedObject callable(cx, js_ValueToCallableObject(cx, &args[0], JSV2F_SEARCH_STACK));
RootedObject callable(cx, ValueToCallable(cx, &args[0]));
if (!callable)
return false;
@ -3377,7 +3377,7 @@ array_filter(JSContext *cx, unsigned argc, Value *vp)
js_ReportMissingArg(cx, args.calleev(), 0);
return false;
}
RootedObject callable(cx, js_ValueToCallableObject(cx, &args[0], JSV2F_SEARCH_STACK));
RootedObject callable(cx, ValueToCallable(cx, &args[0]));
if (!callable)
return false;
@ -3485,7 +3485,7 @@ array_reduceCommon(JSContext *cx, CallArgs &args)
js_ReportMissingArg(cx, args.calleev(), 0);
return false;
}
JSObject *callable = js_ValueToCallableObject(cx, &args[0], JSV2F_SEARCH_STACK);
JSObject *callable = ValueToCallable(cx, &args[0]);
if (!callable)
return false;

View File

@ -1350,63 +1350,3 @@ js_DefineFunction(JSContext *cx, HandleObject obj, HandleId id, Native native,
return fun;
}
JS_STATIC_ASSERT((JSV2F_CONSTRUCT & JSV2F_SEARCH_STACK) == 0);
JSFunction *
js_ValueToFunction(JSContext *cx, const Value *vp, unsigned flags)
{
JSFunction *fun;
if (!IsFunctionObject(*vp, &fun)) {
js_ReportIsNotFunction(cx, vp, flags);
return NULL;
}
return fun;
}
JSObject *
js_ValueToCallableObject(JSContext *cx, Value *vp, unsigned flags)
{
if (vp->isObject()) {
JSObject *callable = &vp->toObject();
if (callable->isCallable())
return callable;
}
js_ReportIsNotFunction(cx, vp, flags);
return NULL;
}
void
js_ReportIsNotFunction(JSContext *cx, const Value *vp, unsigned flags)
{
const char *name = NULL, *source = NULL;
unsigned error = (flags & JSV2F_CONSTRUCT) ? JSMSG_NOT_CONSTRUCTOR : JSMSG_NOT_FUNCTION;
/*
* We try to the print the code that produced vp if vp is a value in the
* most recent interpreted stack frame. Note that additional values, not
* directly produced by the script, may have been pushed onto the frame's
* expression stack (e.g. by pushInvokeArgs) thereby incrementing sp past
* the depth simulated by ReconstructPCStack.
*
* Conversely, values may have been popped from the stack in preparation
* for a call (e.g., by SplatApplyArgs). Since we must pass an offset from
* the top of the simulated stack to js_ReportValueError3, we do bounds
* checking using the minimum of both the simulated and actual stack depth.
*/
ptrdiff_t spindex = 0;
ScriptFrameIter i(cx);
if (!i.done()) {
unsigned depth = js_ReconstructStackDepth(cx, i.script(), i.pc());
Value *simsp = i.fp()->base() + depth;
if (i.fp()->base() <= vp && vp < Min(simsp, i.spFuzzy()))
spindex = vp - simsp;
}
if (!spindex)
spindex = ((flags & JSV2F_SEARCH_STACK) ? JSDVG_SEARCH_STACK : JSDVG_IGNORE_STACK);
js_ReportValueError3(cx, error, spindex, *vp, NULL, name, source);
}

View File

@ -219,21 +219,6 @@ js_DefineFunction(JSContext *cx, js::HandleObject obj, js::HandleId id, JSNative
unsigned nargs, unsigned flags,
js::gc::AllocKind kind = JSFunction::FinalizeKind);
/*
* Flags for js_ValueToFunction and js_ReportIsNotFunction.
*/
#define JSV2F_CONSTRUCT INITIAL_CONSTRUCT
#define JSV2F_SEARCH_STACK 0x10000
extern JSFunction *
js_ValueToFunction(JSContext *cx, const js::Value *vp, unsigned flags);
extern JSObject *
js_ValueToCallableObject(JSContext *cx, js::Value *vp, unsigned flags);
extern void
js_ReportIsNotFunction(JSContext *cx, const js::Value *vp, unsigned flags);
namespace js {
/*

View File

@ -216,6 +216,36 @@ NoSuchMethod(JSContext *cx, unsigned argc, Value *vp)
#endif /* JS_HAS_NO_SUCH_METHOD */
bool
js::ReportIsNotFunction(JSContext *cx, const Value &v, MaybeConstruct construct)
{
unsigned error = construct ? JSMSG_NOT_CONSTRUCTOR : JSMSG_NOT_FUNCTION;
js_ReportValueError3(cx, error, JSDVG_SEARCH_STACK, v, NULL, NULL, NULL);
return false;
}
bool
js::ReportIsNotFunction(JSContext *cx, const Value *vp, MaybeConstruct construct)
{
ptrdiff_t spIndex = cx->stack.spIndexOf(vp);
unsigned error = construct ? JSMSG_NOT_CONSTRUCTOR : JSMSG_NOT_FUNCTION;
js_ReportValueError3(cx, error, spIndex, *vp, NULL, NULL, NULL);
return false;
}
JSObject *
js::ValueToCallable(JSContext *cx, const Value *vp, MaybeConstruct construct)
{
if (vp->isObject()) {
JSObject *callable = &vp->toObject();
if (callable->isCallable())
return callable;
}
ReportIsNotFunction(cx, vp, construct);
return NULL;
}
bool
js::RunScript(JSContext *cx, JSScript *script, StackFrame *fp)
{
@ -282,10 +312,8 @@ js::InvokeKernel(JSContext *cx, CallArgs args, MaybeConstruct construct)
/* MaybeConstruct is a subset of InitialFrameFlags */
InitialFrameFlags initial = (InitialFrameFlags) construct;
if (args.calleev().isPrimitive()) {
js_ReportIsNotFunction(cx, &args.calleev(), ToReportFlags(initial));
return false;
}
if (args.calleev().isPrimitive())
return ReportIsNotFunction(cx, &args.calleev(), construct);
JSObject &callee = args.callee();
Class *clasp = callee.getClass();
@ -297,10 +325,8 @@ js::InvokeKernel(JSContext *cx, CallArgs args, MaybeConstruct construct)
return NoSuchMethod(cx, args.length(), args.base());
#endif
JS_ASSERT_IF(construct, !clasp->construct);
if (!clasp->call) {
js_ReportIsNotFunction(cx, &args.calleev(), ToReportFlags(initial));
return false;
}
if (!clasp->call)
return ReportIsNotFunction(cx, &args.calleev(), construct);
return CallJSNative(cx, clasp->call, args);
}
@ -359,42 +385,41 @@ js::Invoke(JSContext *cx, const Value &thisv, const Value &fval, unsigned argc,
}
bool
js::InvokeConstructorKernel(JSContext *cx, const CallArgs &argsRef)
js::InvokeConstructorKernel(JSContext *cx, CallArgs args)
{
JS_ASSERT(!FunctionClass.construct);
CallArgs args = argsRef;
args.thisv().setMagic(JS_IS_CONSTRUCTING);
if (args.calleev().isObject()) {
JSObject *callee = &args.callee();
Class *clasp = callee->getClass();
if (clasp == &FunctionClass) {
JSFunction *fun = callee->toFunction();
if (!args.calleev().isObject())
return ReportIsNotFunction(cx, &args.calleev(), CONSTRUCT);
if (fun->isNativeConstructor()) {
Probes::calloutBegin(cx, fun);
bool ok = CallJSNativeConstructor(cx, fun->native(), args);
Probes::calloutEnd(cx, fun);
return ok;
}
JSObject &callee = args.callee();
if (callee.isFunction()) {
JSFunction *fun = callee.toFunction();
if (!fun->isInterpretedConstructor())
goto error;
if (!InvokeKernel(cx, args, CONSTRUCT))
return false;
JS_ASSERT(args.rval().isObject());
return true;
if (fun->isNativeConstructor()) {
Probes::calloutBegin(cx, fun);
bool ok = CallJSNativeConstructor(cx, fun->native(), args);
Probes::calloutEnd(cx, fun);
return ok;
}
if (clasp->construct)
return CallJSNativeConstructor(cx, clasp->construct, args);
if (!fun->isInterpretedConstructor())
return ReportIsNotFunction(cx, &args.calleev(), CONSTRUCT);
if (!InvokeKernel(cx, args, CONSTRUCT))
return false;
JS_ASSERT(args.rval().isObject());
return true;
}
error:
js_ReportIsNotFunction(cx, &args.calleev(), JSV2F_CONSTRUCT);
return false;
Class *clasp = callee.getClass();
if (!clasp->construct)
return ReportIsNotFunction(cx, &args.calleev(), CONSTRUCT);
return CallJSNativeConstructor(cx, clasp->construct, args);
}
bool
@ -3226,7 +3251,7 @@ BEGIN_CASE(JSOP_SPREAD)
regs.sp--;
}
END_CASE(JSOP_SPREAD)
{
BEGIN_CASE(JSOP_GOSUB)
PUSH_BOOLEAN(false);

View File

@ -81,6 +81,25 @@ enum MaybeConstruct {
CONSTRUCT = INITIAL_CONSTRUCT
};
extern bool
ReportIsNotFunction(JSContext *cx, const Value &v, MaybeConstruct construct = NO_CONSTRUCT);
extern bool
ReportIsNotFunction(JSContext *cx, const Value *vp, MaybeConstruct construct = NO_CONSTRUCT);
extern JSObject *
ValueToCallable(JSContext *cx, const Value *vp, MaybeConstruct construct = NO_CONSTRUCT);
inline JSFunction *
ReportIfNotFunction(JSContext *cx, const Value &v, MaybeConstruct construct = NO_CONSTRUCT)
{
if (v.isObject() && v.toObject().isFunction())
return v.toObject().toFunction();
ReportIsNotFunction(cx, v, construct);
return NULL;
}
/*
* InvokeKernel assumes that the given args have been pushed on the top of the
* VM stack. Additionally, if 'args' is contained in a CallArgsList, that they
@ -124,7 +143,7 @@ InvokeGetterOrSetter(JSContext *cx, JSObject *obj, const Value &fval, unsigned a
* (e.g. 'new') handling the the creation of the new 'this' object.
*/
extern bool
InvokeConstructorKernel(JSContext *cx, const CallArgs &args);
InvokeConstructorKernel(JSContext *cx, CallArgs args);
/* See the InvokeArgsGuard overload of Invoke. */
inline bool

View File

@ -1190,7 +1190,7 @@ obj_watch(JSContext *cx, unsigned argc, Value *vp)
return false;
}
RootedObject callable(cx, js_ValueToCallableObject(cx, &vp[3], 0));
RootedObject callable(cx, ValueToCallable(cx, &vp[3]));
if (!callable)
return false;
@ -6324,20 +6324,6 @@ js_DumpStackFrame(JSContext *cx, StackFrame *start)
fprintf(stderr, " pc = %p\n", pc);
fprintf(stderr, " current op: %s\n", js_CodeName[*pc]);
}
Value *sp = i.spFuzzy();
fprintf(stderr, " slots: %p\n", (void *) fp->slots());
fprintf(stderr, " sp: %p = slots + %u\n", (void *) sp, (unsigned) (sp - fp->slots()));
if (sp - fp->slots() < 10000) { // sanity
for (Value *p = fp->slots(); p < sp; p++) {
fprintf(stderr, " %p: ", (void *) p);
dumpValue(*p);
fputc('\n', stderr);
}
}
if (fp->hasArgs()) {
fprintf(stderr, " actuals: %p (%u) ", (void *) fp->actuals(), (unsigned) fp->numActualArgs());
fprintf(stderr, " formals: %p (%u)\n", (void *) fp->formals(), (unsigned) fp->numFormalArgs());
}
MaybeDumpObject("blockChain", fp->maybeBlockChain());
if (!fp->isDummyFrame()) {
MaybeDumpValue("this", fp->thisValue());

View File

@ -264,18 +264,14 @@ bool
BaseProxyHandler::call(JSContext *cx, JSObject *proxy, unsigned argc,
Value *vp)
{
Value v = UndefinedValue();
js_ReportIsNotFunction(cx, &v, 0);
return false;
return ReportIsNotFunction(cx, UndefinedValue());
}
bool
BaseProxyHandler::construct(JSContext *cx, JSObject *proxy, unsigned argc,
Value *argv, Value *rval)
{
Value v = UndefinedValue();
js_ReportIsNotFunction(cx, &v, JSV2F_CONSTRUCT);
return false;
return ReportIsNotFunction(cx, UndefinedValue(), CONSTRUCT);
}
JSString *
@ -1819,12 +1815,12 @@ proxy_createFunction(JSContext *cx, unsigned argc, Value *vp)
return false;
parent = proto->getParent();
JSObject *call = js_ValueToCallableObject(cx, &vp[3], JSV2F_SEARCH_STACK);
JSObject *call = ValueToCallable(cx, &vp[3]);
if (!call)
return false;
JSObject *construct = NULL;
if (argc > 2) {
construct = js_ValueToCallableObject(cx, &vp[4], JSV2F_SEARCH_STACK);
construct = ValueToCallable(cx, &vp[4]);
if (!construct)
return false;
}

View File

@ -351,8 +351,7 @@ DirectWrapper::fun_toString(JSContext *cx, JSObject *wrapper, unsigned indent)
// Perform some default behavior that doesn't leak any information.
if (wrapper->isCallable())
return JS_NewStringCopyZ(cx, "function () {\n [native code]\n}");
js::Value v = ObjectValue(*wrapper);
js_ReportIsNotFunction(cx, &v, 0);
ReportIsNotFunction(cx, ObjectValue(*wrapper));
return NULL;
}
return NULL;

View File

@ -9,9 +9,9 @@ function checkConstruct(thing, buggy) {
assertEq(0, 1, "not reached " + thing);
} catch (e) {
if (buggy)
assertEq(e.message, "new thing is not a constructor");
assertEq(String(e.message).indexOf("is not a constructor") === -1, false);
else
assertEq(e.message, "thing is not a constructor");
assertEq(String(e.message).indexOf("thing is not a constructor") === -1, false);
}
}

View File

@ -142,17 +142,17 @@ function test()
} catch (e) {
s = e + "";
}
expect("TypeError: o.hello() is not a function", s);
expect("TypeError: ({}) is not a function", s);
s = "no exception";
try {
eval("o.hello()");
} catch (e) {
s = e + "";
}
expect("TypeError: o.hello() is not a function", s);
expect("TypeError: ({}) is not a function", s);
s = "no exception";
try { [2, 3, 0].sort({}); } catch (e) { s = e + ""; }
expect("TypeError: [2, 3, 0].sort({}) is not a function", s);
expect("TypeError: ({}) is not a function", s);
/*
* Generator expressions.

View File

@ -1581,17 +1581,14 @@ Debugger::setHookImpl(JSContext *cx, unsigned argc, Value *vp, Hook which)
JS_ASSERT(which >= 0 && which < HookCount);
REQUIRE_ARGC("Debugger.setHook", 1);
THIS_DEBUGGER(cx, argc, vp, "setHook", args, dbg);
const Value &v = args[0];
if (v.isObject()) {
if (!v.toObject().isCallable()) {
js_ReportIsNotFunction(cx, vp, JSV2F_SEARCH_STACK);
return false;
}
} else if (!v.isUndefined()) {
if (args[0].isObject()) {
if (!args[0].toObject().isCallable())
return ReportIsNotFunction(cx, &args[0]);
} else if (!args[0].isUndefined()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_CALLABLE_OR_UNDEFINED);
return false;
}
dbg->object->setReservedSlot(JSSLOT_DEBUG_HOOK_START + which, v);
dbg->object->setReservedSlot(JSSLOT_DEBUG_HOOK_START + which, args[0]);
args.rval().setUndefined();
return true;
}

View File

@ -36,7 +36,7 @@ js::ReportIncompatibleMethod(JSContext *cx, CallReceiver call, Class *clasp)
}
#endif
if (JSFunction *fun = js_ValueToFunction(cx, &call.calleev(), 0)) {
if (JSFunction *fun = ReportIfNotFunction(cx, call.calleev())) {
JSAutoByteString funNameBytes;
if (const char *funName = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,

View File

@ -798,6 +798,20 @@ ContextStack::~ContextStack()
JS_ASSERT(!seg_);
}
ptrdiff_t
ContextStack::spIndexOf(const Value *vp)
{
if (!hasfp() || !fp()->isScriptFrame())
return JSDVG_SEARCH_STACK;
Value *base = fp()->base();
Value *sp = regs().sp;
if (vp < base || vp >= sp)
return JSDVG_SEARCH_STACK;
return vp - sp;
}
bool
ContextStack::onTop() const
{
@ -1154,7 +1168,6 @@ ContextStack::restoreFrameChain()
void
StackIter::poisonRegs()
{
sp_ = (Value *)0xbad;
pc_ = (jsbytecode *)0xbad;
script_ = (JSScript *)0xbad;
}
@ -1169,36 +1182,6 @@ StackIter::popFrame()
InlinedSite *inline_;
pc_ = oldfp->prevpc(&inline_);
JS_ASSERT(!inline_);
/*
* If there is a CallArgsList element between oldfp and fp_, then sp_
* is ignored, so we only consider the case where there is no
* intervening CallArgsList. The stack representation is not optimized
* for this operation so we need to do a full case analysis of how
* frames are pushed by considering each ContextStack::push*Frame.
*/
if (oldfp->isGeneratorFrame()) {
/* Generator's args do not overlap with the caller's expr stack. */
sp_ = oldfp->generatorArgsSnapshotBegin();
} else if (oldfp->isNonEvalFunctionFrame()) {
/*
* When Invoke is called from a native, there will be an enclosing
* pushInvokeArgs which pushes a CallArgsList element so we can
* ignore that case. The other two cases of function call frames are
* Invoke called directly from script and pushInlineFrmae. In both
* cases, the actual arguments of the callee should be included in
* the caller's expr stack.
*/
sp_ = oldfp->actuals() + oldfp->numActualArgs();
} else if (oldfp->isFramePushedByExecute()) {
/* pushExecuteFrame pushes exactly (callee, this) before frame. */
sp_ = (Value *)oldfp - 2;
} else {
/* pushDummyFrame pushes exactly 0 slots before frame. */
JS_ASSERT(oldfp->isDummyFrame());
sp_ = (Value *)oldfp;
}
script_ = fp_->maybeScript();
} else {
poisonRegs();
@ -1211,19 +1194,14 @@ StackIter::popCall()
CallArgsList *oldCall = calls_;
JS_ASSERT(seg_->contains(oldCall));
calls_ = calls_->prev();
if (seg_->contains(fp_)) {
/* pc_ keeps its same value. */
sp_ = oldCall->base();
} else {
if (!seg_->contains(fp_))
poisonRegs();
}
}
void
StackIter::settleOnNewSegment()
{
if (FrameRegs *regs = seg_->maybeRegs()) {
sp_ = regs->sp;
pc_ = regs->pc;
if (fp_)
script_ = fp_->maybeScript();
@ -1317,17 +1295,6 @@ StackIter::settleOnNewState()
state_ = SCRIPTED;
script_ = fp_->script();
/*
* Check sp and pc. JM's getter ICs may push 2 extra values on the
* stack; this is okay since the methodjit reserves some extra slots
* for loop temporaries.
*/
if (*pc_ == JSOP_GETPROP || *pc_ == JSOP_CALLPROP)
JS_ASSERT(sp_ >= fp_->base() && sp_ <= fp_->slots() + script_->nslots + 2);
else if (*pc_ != JSOP_FUNAPPLY)
JS_ASSERT(sp_ >= fp_->base() && sp_ <= fp_->slots() + script_->nslots);
JS_ASSERT(pc_ >= script_->code && pc_ < script_->code + script_->length);
return;
}

View File

@ -411,8 +411,6 @@ class StackFrame
friend class CallObject;
friend class ClonedBlockObject;
friend class ArgumentsObject;
friend void ::js_DumpStackFrame(JSContext *, StackFrame *);
friend void ::js_ReportIsNotFunction(JSContext *, const js::Value *, unsigned);
#ifdef JS_METHODJIT
friend class mjit::CallCompiler;
friend class mjit::GetPropCompiler;
@ -1140,12 +1138,6 @@ class StackFrame
static const size_t VALUES_PER_STACK_FRAME = sizeof(StackFrame) / sizeof(Value);
static inline unsigned
ToReportFlags(InitialFrameFlags initial)
{
return unsigned(initial & StackFrame::CONSTRUCTING);
}
static inline StackFrame::Flags
ToFrameFlags(InitialFrameFlags initial)
{
@ -1587,6 +1579,14 @@ class ContextStack
*/
inline bool hasfp() const { return seg_ && seg_->maybeRegs(); }
/*
* Return the spindex value for 'vp' which can be used to call
* DecompileValueGenerator. (The spindex is either the negative offset of
* 'vp' from 'sp', if 'vp' points to a value in the innermost scripted
* stack frame, otherwise it is JSDVG_SEARCH_STACK.)
*/
ptrdiff_t spIndexOf(const Value *vp);
/*
* Return the most recent script activation's registers with the same
* caveat as hasfp regarding JS_SaveFrameChain.
@ -1783,7 +1783,6 @@ class StackIter
CallArgsList *calls_;
StackSegment *seg_;
Value *sp_;
jsbytecode *pc_;
JSScript *script_;
CallArgs args_;
@ -1823,14 +1822,6 @@ class StackIter
Value calleev() const;
Value thisv() const;
/*
* 'spFuzzy' is a best-effort approximiation of the frame's sp. It is only
* guaranteed to point to a safe range above fp's base and below fp's next.
* Ideally, we'd remove this altogether... wait, I'll do that in the next
* patch.
*/
Value *spFuzzy() const { JS_ASSERT(isScript()); return sp_; }
CallArgs nativeArgs() const { JS_ASSERT(isNativeCall()); return args_; }
};