Bug 1135001 - Get rid of slow GetTopJitJSScript calls in Ion ICs. r=bhackett

This commit is contained in:
Jan de Mooij 2015-02-22 23:37:58 +01:00
parent 1a54d7d54d
commit cb29c8e019
6 changed files with 90 additions and 72 deletions

View File

@ -7806,7 +7806,7 @@ CodeGenerator::visitGetNameCache(LGetNameCache *ins)
addCache(ins, allocateCache(cache));
}
typedef bool (*NameICFn)(JSContext *, size_t, HandleObject, MutableHandleValue);
typedef bool (*NameICFn)(JSContext *, HandleScript, size_t, HandleObject, MutableHandleValue);
const VMFunction NameIC::UpdateInfo = FunctionInfo<NameICFn>(NameIC::update);
void
@ -7817,6 +7817,7 @@ CodeGenerator::visitNameIC(OutOfLineUpdateCache *ool, DataPtr<NameIC> &ic)
pushArg(ic->scopeChainReg());
pushArg(Imm32(ool->getCacheIndex()));
pushArg(ImmGCPtr(gen->info().script()));
callVM(NameIC::UpdateInfo, lir);
StoreValueTo(ic->outputReg()).generate(this);
restoreLiveIgnore(lir, StoreValueTo(ic->outputReg()).clobbered());
@ -7883,9 +7884,9 @@ CodeGenerator::visitGetPropertyCacheT(LGetPropertyCacheT *ins)
ins->mir()->profilerLeavePc());
}
typedef bool (*GetPropertyICFn)(JSContext *, size_t, HandleObject, MutableHandleValue);
const VMFunction GetPropertyIC::UpdateInfo =
FunctionInfo<GetPropertyICFn>(GetPropertyIC::update);
typedef bool (*GetPropertyICFn)(JSContext *, HandleScript, size_t, HandleObject,
MutableHandleValue);
const VMFunction GetPropertyIC::UpdateInfo = FunctionInfo<GetPropertyICFn>(GetPropertyIC::update);
void
CodeGenerator::visitGetPropertyIC(OutOfLineUpdateCache *ool, DataPtr<GetPropertyIC> &ic)
@ -7903,6 +7904,7 @@ CodeGenerator::visitGetPropertyIC(OutOfLineUpdateCache *ool, DataPtr<GetProperty
pushArg(ic->object());
pushArg(Imm32(ool->getCacheIndex()));
pushArg(ImmGCPtr(gen->info().script()));
callVM(GetPropertyIC::UpdateInfo, lir);
StoreValueTo(ic->output()).generate(this);
restoreLiveIgnore(lir, StoreValueTo(ic->output()).clobbered());
@ -7945,9 +7947,9 @@ CodeGenerator::visitGetElementCacheT(LGetElementCacheT *ins)
mir->allowDoubleResult(), mir->profilerLeavePc());
}
typedef bool (*GetElementICFn)(JSContext *, size_t, HandleObject, HandleValue, MutableHandleValue);
const VMFunction GetElementIC::UpdateInfo =
FunctionInfo<GetElementICFn>(GetElementIC::update);
typedef bool (*GetElementICFn)(JSContext *, HandleScript, size_t, HandleObject, HandleValue,
MutableHandleValue);
const VMFunction GetElementIC::UpdateInfo = FunctionInfo<GetElementICFn>(GetElementIC::update);
void
CodeGenerator::visitGetElementIC(OutOfLineUpdateCache *ool, DataPtr<GetElementIC> &ic)
@ -7958,6 +7960,7 @@ CodeGenerator::visitGetElementIC(OutOfLineUpdateCache *ool, DataPtr<GetElementIC
pushArg(ic->index());
pushArg(ic->object());
pushArg(Imm32(ool->getCacheIndex()));
pushArg(ImmGCPtr(gen->info().script()));
callVM(GetElementIC::UpdateInfo, lir);
StoreValueTo(ic->output()).generate(this);
restoreLiveIgnore(lir, StoreValueTo(ic->output()).clobbered());
@ -8002,9 +8005,9 @@ CodeGenerator::visitSetElementCacheT(LSetElementCacheT *ins)
ins->mir()->profilerLeavePc());
}
typedef bool (*SetElementICFn)(JSContext *, size_t, HandleObject, HandleValue, HandleValue);
const VMFunction SetElementIC::UpdateInfo =
FunctionInfo<SetElementICFn>(SetElementIC::update);
typedef bool (*SetElementICFn)(JSContext *, HandleScript, size_t, HandleObject, HandleValue,
HandleValue);
const VMFunction SetElementIC::UpdateInfo = FunctionInfo<SetElementICFn>(SetElementIC::update);
void
CodeGenerator::visitSetElementIC(OutOfLineUpdateCache *ool, DataPtr<SetElementIC> &ic)
@ -8016,6 +8019,7 @@ CodeGenerator::visitSetElementIC(OutOfLineUpdateCache *ool, DataPtr<SetElementIC
pushArg(ic->index());
pushArg(ic->object());
pushArg(Imm32(ool->getCacheIndex()));
pushArg(ImmGCPtr(gen->info().script()));
callVM(SetElementIC::UpdateInfo, lir);
restoreLive(lir);
@ -8033,9 +8037,8 @@ CodeGenerator::visitBindNameCache(LBindNameCache *ins)
addCache(ins, allocateCache(cache));
}
typedef JSObject *(*BindNameICFn)(JSContext *, size_t, HandleObject);
const VMFunction BindNameIC::UpdateInfo =
FunctionInfo<BindNameICFn>(BindNameIC::update);
typedef JSObject *(*BindNameICFn)(JSContext *, HandleScript, size_t, HandleObject);
const VMFunction BindNameIC::UpdateInfo = FunctionInfo<BindNameICFn>(BindNameIC::update);
void
CodeGenerator::visitBindNameIC(OutOfLineUpdateCache *ool, DataPtr<BindNameIC> &ic)
@ -8045,6 +8048,7 @@ CodeGenerator::visitBindNameIC(OutOfLineUpdateCache *ool, DataPtr<BindNameIC> &i
pushArg(ic->scopeChainReg());
pushArg(Imm32(ool->getCacheIndex()));
pushArg(ImmGCPtr(gen->info().script()));
callVM(BindNameIC::UpdateInfo, lir);
StoreRegisterTo(ic->outputReg()).generate(this);
restoreLiveIgnore(lir, StoreRegisterTo(ic->outputReg()).clobbered());
@ -8138,9 +8142,8 @@ CodeGenerator::visitSetPropertyCacheT(LSetPropertyCacheT *ins)
ins->mir()->profilerLeavePc());
}
typedef bool (*SetPropertyICFn)(JSContext *, size_t, HandleObject, HandleValue);
const VMFunction SetPropertyIC::UpdateInfo =
FunctionInfo<SetPropertyICFn>(SetPropertyIC::update);
typedef bool (*SetPropertyICFn)(JSContext *, HandleScript, size_t, HandleObject, HandleValue);
const VMFunction SetPropertyIC::UpdateInfo = FunctionInfo<SetPropertyICFn>(SetPropertyIC::update);
void
CodeGenerator::visitSetPropertyIC(OutOfLineUpdateCache *ool, DataPtr<SetPropertyIC> &ic)
@ -8151,6 +8154,7 @@ CodeGenerator::visitSetPropertyIC(OutOfLineUpdateCache *ool, DataPtr<SetProperty
pushArg(ic->value());
pushArg(ic->object());
pushArg(Imm32(ool->getCacheIndex()));
pushArg(ImmGCPtr(gen->info().script()));
callVM(SetPropertyIC::UpdateInfo, lir);
restoreLive(lir);

View File

@ -471,6 +471,20 @@ IonCache::initializeAddCacheState(LInstruction *ins, AddCacheState *addState)
{
}
static void *
GetReturnAddressToIonCode(JSContext *cx)
{
JitFrameIterator iter(cx);
MOZ_ASSERT(iter.type() == JitFrame_Exit);
void *returnAddr = iter.returnAddress();
#ifdef DEBUG
++iter;
MOZ_ASSERT(iter.isIonJS());
#endif
return returnAddr;
}
static void
GeneratePrototypeGuards(JSContext *cx, IonScript *ion, MacroAssembler &masm, JSObject *obj,
JSObject *holder, Register objectReg, Register scratchReg,
@ -1243,7 +1257,7 @@ IsCacheableArrayLength(JSContext *cx, HandleObject obj, HandlePropertyName name,
template <class GetPropCache>
static GetPropertyIC::NativeGetPropCacheability
CanAttachNativeGetProp(typename GetPropCache::Context cx, const GetPropCache &cache,
CanAttachNativeGetProp(JSContext *cx, const GetPropCache &cache,
HandleObject obj, HandlePropertyName name,
MutableHandleNativeObject holder, MutableHandleShape shape,
bool skipArrayLen = false)
@ -1311,7 +1325,7 @@ CanAttachNativeGetProp(typename GetPropCache::Context cx, const GetPropCache &ca
}
bool
GetPropertyIC::allowArrayLength(Context cx, HandleObject obj) const
GetPropertyIC::allowArrayLength(JSContext *cx, HandleObject obj) const
{
if (!idempotent())
return true;
@ -1814,8 +1828,7 @@ GetPropertyIC::tryAttachArgumentsLength(JSContext *cx, HandleScript outerScript,
bool
GetPropertyIC::tryAttachStub(JSContext *cx, HandleScript outerScript, IonScript *ion,
HandleObject obj, HandlePropertyName name,
void *returnAddr, bool *emitted)
HandleObject obj, HandlePropertyName name, bool *emitted)
{
MOZ_ASSERT(!*emitted);
@ -1825,6 +1838,8 @@ GetPropertyIC::tryAttachStub(JSContext *cx, HandleScript outerScript, IonScript
if (!*emitted && !tryAttachArgumentsLength(cx, outerScript, ion, obj, name, emitted))
return false;
void *returnAddr = GetReturnAddressToIonCode(cx);
if (!*emitted && !tryAttachProxy(cx, outerScript, ion, obj, name, returnAddr, emitted))
return false;
@ -1844,11 +1859,9 @@ GetPropertyIC::tryAttachStub(JSContext *cx, HandleScript outerScript, IonScript
}
/* static */ bool
GetPropertyIC::update(JSContext *cx, size_t cacheIndex,
GetPropertyIC::update(JSContext *cx, HandleScript outerScript, size_t cacheIndex,
HandleObject obj, MutableHandleValue vp)
{
void *returnAddr;
RootedScript outerScript(cx, GetTopJitJSScript(cx, &returnAddr));
IonScript *ion = outerScript->ionScript();
GetPropertyIC &cache = ion->getCache(cacheIndex).toGetProperty();
@ -1865,7 +1878,7 @@ GetPropertyIC::update(JSContext *cx, size_t cacheIndex,
// limit. Once we can make calls from within generated stubs, a new call
// stub will be generated instead and the previous stubs unlinked.
bool emitted = false;
if (!cache.tryAttachStub(cx, outerScript, ion, obj, name, returnAddr, &emitted))
if (!cache.tryAttachStub(cx, outerScript, ion, obj, name, &emitted))
return false;
if (cache.idempotent() && !emitted) {
@ -2933,12 +2946,10 @@ CanAttachSetUnboxed(JSContext *cx, HandleObject obj, HandleId id, ConstantOrRegi
}
bool
SetPropertyIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
SetPropertyIC::update(JSContext *cx, HandleScript outerScript, size_t cacheIndex, HandleObject obj,
HandleValue value)
{
void *returnAddr;
RootedScript script(cx, GetTopJitJSScript(cx, &returnAddr));
IonScript *ion = script->ionScript();
IonScript *ion = outerScript->ionScript();
SetPropertyIC &cache = ion->getCache(cacheIndex).toSetProperty();
RootedPropertyName name(cx, cache.name());
RootedId id(cx, AtomToId(name));
@ -2953,26 +2964,27 @@ SetPropertyIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
bool addedSetterStub = false;
if (cache.canAttachStub() && !obj->watched()) {
if (!addedSetterStub && obj->is<ProxyObject>()) {
void *returnAddr = GetReturnAddressToIonCode(cx);
if (IsCacheableDOMProxy(obj)) {
DOMProxyShadowsResult shadows = GetDOMProxyShadowsCheck()(cx, obj, id);
if (shadows == ShadowCheckFailed)
return false;
if (shadows == Shadows) {
if (!cache.attachDOMProxyShadowed(cx, script, ion, obj, returnAddr))
if (!cache.attachDOMProxyShadowed(cx, outerScript, ion, obj, returnAddr))
return false;
addedSetterStub = true;
} else {
MOZ_ASSERT(shadows == DoesntShadow || shadows == DoesntShadowUnique);
if (shadows == DoesntShadowUnique)
cache.reset();
if (!cache.attachDOMProxyUnshadowed(cx, script, ion, obj, returnAddr))
if (!cache.attachDOMProxyUnshadowed(cx, outerScript, ion, obj, returnAddr))
return false;
addedSetterStub = true;
}
}
if (!addedSetterStub && !cache.hasGenericProxyStub()) {
if (!cache.attachGenericProxy(cx, script, ion, returnAddr))
if (!cache.attachGenericProxy(cx, outerScript, ion, returnAddr))
return false;
addedSetterStub = true;
}
@ -2986,13 +2998,14 @@ SetPropertyIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
if (!addedSetterStub && canCache == CanAttachSetSlot) {
RootedNativeObject nobj(cx, &obj->as<NativeObject>());
if (!cache.attachSetSlot(cx, script, ion, nobj, shape, checkTypeset))
if (!cache.attachSetSlot(cx, outerScript, ion, nobj, shape, checkTypeset))
return false;
addedSetterStub = true;
}
if (!addedSetterStub && canCache == CanAttachCallSetter) {
if (!cache.attachCallSetter(cx, script, ion, obj, holder, shape, returnAddr))
void *returnAddr = GetReturnAddressToIonCode(cx);
if (!cache.attachCallSetter(cx, outerScript, ion, obj, holder, shape, returnAddr))
return false;
addedSetterStub = true;
}
@ -3004,7 +3017,7 @@ SetPropertyIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
cache.needsTypeBarrier(),
&checkTypeset, &unboxedOffset, &unboxedType))
{
if (!cache.attachSetUnboxed(cx, script, ion, obj, id, unboxedOffset, unboxedType,
if (!cache.attachSetUnboxed(cx, outerScript, ion, obj, id, unboxedOffset, unboxedType,
checkTypeset))
{
return false;
@ -3028,7 +3041,7 @@ SetPropertyIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
&checkTypeset))
{
RootedNativeObject nobj(cx, &obj->as<NativeObject>());
if (!cache.attachAddSlot(cx, script, ion, nobj, oldShape, oldGroup, checkTypeset))
if (!cache.attachAddSlot(cx, outerScript, ion, nobj, oldShape, oldGroup, checkTypeset))
return false;
addedSetterStub = true;
}
@ -3074,8 +3087,7 @@ EqualStringsHelper(JSString *str1, JSString *str2)
bool
GetElementIC::attachGetProp(JSContext *cx, HandleScript outerScript, IonScript *ion,
HandleObject obj, const Value &idval, HandlePropertyName name,
void *returnAddr)
HandleObject obj, const Value &idval, HandlePropertyName name)
{
MOZ_ASSERT(index().reg().hasValue());
@ -3155,7 +3167,9 @@ GetElementIC::attachGetProp(JSContext *cx, HandleScript outerScript, IonScript *
&failures);
} else {
MOZ_ASSERT(canCache == GetPropertyIC::CanAttachCallGetter);
// Set the frame for bailout safety of the OOL call.
void *returnAddr = GetReturnAddressToIonCode(cx);
if (!GenerateCallGetter(cx, ion, masm, attacher, obj, name, holder, shape, liveRegs_,
object(), output(), returnAddr, &failures))
{
@ -3506,11 +3520,9 @@ GetElementIC::attachArgumentsElement(JSContext *cx, HandleScript outerScript, Io
}
bool
GetElementIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
GetElementIC::update(JSContext *cx, HandleScript outerScript, size_t cacheIndex, HandleObject obj,
HandleValue idval, MutableHandleValue res)
{
void *returnAddr;
RootedScript outerScript(cx, GetTopJitJSScript(cx, &returnAddr));
IonScript *ion = outerScript->ionScript();
GetElementIC &cache = ion->getCache(cacheIndex).toGetElement();
RootedScript script(cx);
@ -3547,7 +3559,7 @@ GetElementIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
}
if (!attachedStub && cache.monitoredResult() && canAttachGetProp(obj, idval, id)) {
RootedPropertyName name(cx, JSID_TO_ATOM(id)->asPropertyName());
if (!cache.attachGetProp(cx, outerScript, ion, obj, idval, name, returnAddr))
if (!cache.attachGetProp(cx, outerScript, ion, obj, idval, name))
return false;
attachedStub = true;
}
@ -3897,10 +3909,9 @@ SetElementIC::attachTypedArrayElement(JSContext *cx, HandleScript outerScript, I
}
bool
SetElementIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
SetElementIC::update(JSContext *cx, HandleScript outerScript, size_t cacheIndex, HandleObject obj,
HandleValue idval, HandleValue value)
{
RootedScript outerScript(cx, GetTopJitJSScript(cx));
IonScript *ion = outerScript->ionScript();
SetElementIC &cache = ion->getCache(cacheIndex).toSetElement();
@ -4066,9 +4077,9 @@ IsCacheableNonGlobalScopeChain(JSObject *scopeChain, JSObject *holder)
}
JSObject *
BindNameIC::update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain)
BindNameIC::update(JSContext *cx, HandleScript outerScript, size_t cacheIndex,
HandleObject scopeChain)
{
RootedScript outerScript(cx, GetTopJitJSScript(cx));
IonScript *ion = outerScript->ionScript();
BindNameIC &cache = ion->getCache(cacheIndex).toBindName();
HandlePropertyName name = cache.name();
@ -4216,11 +4227,9 @@ IsCacheableNameCallGetter(HandleObject scopeChain, HandleObject obj, HandleObjec
}
bool
NameIC::update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain,
NameIC::update(JSContext *cx, HandleScript outerScript, size_t cacheIndex, HandleObject scopeChain,
MutableHandleValue vp)
{
void *returnAddr;
RootedScript outerScript(cx, GetTopJitJSScript(cx, &returnAddr));
IonScript *ion = outerScript->ionScript();
NameIC &cache = ion->getCache(cacheIndex).toName();
@ -4253,8 +4262,12 @@ NameIC::update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain,
return false;
}
} else if (IsCacheableNameCallGetter(scopeChain, obj, holder, shape)) {
if (!cache.attachCallGetter(cx, outerScript, ion, scopeChain, obj, holder, shape, returnAddr))
void *returnAddr = GetReturnAddressToIonCode(cx);
if (!cache.attachCallGetter(cx, outerScript, ion, scopeChain, obj, holder, shape,
returnAddr))
{
return false;
}
}
}

View File

@ -638,16 +638,14 @@ class GetPropertyIC : public RepatchIonCache
};
// Helpers for CanAttachNativeGetProp
typedef JSContext * Context;
bool allowArrayLength(Context cx, HandleObject obj) const;
bool allowArrayLength(JSContext *cx, HandleObject obj) const;
bool allowGetters() const {
return monitoredResult() && !idempotent();
}
// Attach the proper stub, if possible
bool tryAttachStub(JSContext *cx, HandleScript outerScript, IonScript *ion,
HandleObject obj, HandlePropertyName name,
void *returnAddr, bool *emitted);
HandleObject obj, HandlePropertyName name, bool *emitted);
bool tryAttachProxy(JSContext *cx, HandleScript outerScript, IonScript *ion,
HandleObject obj, HandlePropertyName name,
@ -678,7 +676,8 @@ class GetPropertyIC : public RepatchIonCache
bool tryAttachArgumentsLength(JSContext *cx, HandleScript outerScript, IonScript *ion,
HandleObject obj, HandlePropertyName name, bool *emitted);
static bool update(JSContext *cx, size_t cacheIndex, HandleObject obj, MutableHandleValue vp);
static bool update(JSContext *cx, HandleScript outerScript, size_t cacheIndex,
HandleObject obj, MutableHandleValue vp);
};
class SetPropertyIC : public RepatchIonCache
@ -764,7 +763,8 @@ class SetPropertyIC : public RepatchIonCache
bool attachDOMProxyUnshadowed(JSContext *cx, HandleScript outerScript, IonScript *ion,
HandleObject obj, void *returnAddr);
static bool update(JSContext *cx, size_t cacheIndex, HandleObject obj, HandleValue value);
static bool update(JSContext *cx, HandleScript outerScript, size_t cacheIndex,
HandleObject obj, HandleValue value);
};
class GetElementIC : public RepatchIonCache
@ -846,8 +846,7 @@ class GetElementIC : public RepatchIonCache
TypedOrValueRegister output);
bool attachGetProp(JSContext *cx, HandleScript outerScript, IonScript *ion,
HandleObject obj, const Value &idval, HandlePropertyName name,
void *returnAddr);
HandleObject obj, const Value &idval, HandlePropertyName name);
bool attachDenseElement(JSContext *cx, HandleScript outerScript, IonScript *ion,
HandleObject obj, const Value &idval);
@ -859,8 +858,8 @@ class GetElementIC : public RepatchIonCache
HandleObject obj);
static bool
update(JSContext *cx, size_t cacheIndex, HandleObject obj, HandleValue idval,
MutableHandleValue vp);
update(JSContext *cx, HandleScript outerScript, size_t cacheIndex, HandleObject obj,
HandleValue idval, MutableHandleValue vp);
void incFailedUpdates() {
failedUpdates_++;
@ -954,8 +953,8 @@ class SetElementIC : public RepatchIonCache
HandleObject tarr);
static bool
update(JSContext *cx, size_t cacheIndex, HandleObject obj, HandleValue idval,
HandleValue value);
update(JSContext *cx, HandleScript outerScript, size_t cacheIndex, HandleObject obj,
HandleValue idval, HandleValue value);
};
class BindNameIC : public RepatchIonCache
@ -992,7 +991,7 @@ class BindNameIC : public RepatchIonCache
HandleObject scopeChain, HandleObject holder);
static JSObject *
update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain);
update(JSContext *cx, HandleScript outerScript, size_t cacheIndex, HandleObject scopeChain);
};
class NameIC : public RepatchIonCache
@ -1043,7 +1042,8 @@ class NameIC : public RepatchIonCache
HandleShape shape, void *returnAddr);
static bool
update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain, MutableHandleValue vp);
update(JSContext *cx, HandleScript outerScript, size_t cacheIndex, HandleObject scopeChain,
MutableHandleValue vp);
};
#undef CACHE_HEADER

View File

@ -289,16 +289,12 @@ MakeFrameDescriptor(uint32_t frameSize, FrameType type)
// Returns the JSScript associated with the topmost JIT frame.
inline JSScript *
GetTopJitJSScript(JSContext *cx, void **returnAddrOut = nullptr)
GetTopJitJSScript(JSContext *cx)
{
JitFrameIterator iter(cx);
MOZ_ASSERT(iter.type() == JitFrame_Exit);
++iter;
MOZ_ASSERT(iter.returnAddressToFp() != nullptr);
if (returnAddrOut)
*returnAddrOut = (void *) iter.returnAddressToFp();
if (iter.isBaselineStub()) {
++iter;
MOZ_ASSERT(iter.isBaselineJS());

View File

@ -36,10 +36,9 @@ namespace jit {
// run before the constructors for static VMFunctions.
/* static */ VMFunction *VMFunction::functions;
AutoDetectInvalidation::AutoDetectInvalidation(JSContext *cx, MutableHandleValue rval,
IonScript *ionScript)
AutoDetectInvalidation::AutoDetectInvalidation(JSContext *cx, MutableHandleValue rval)
: cx_(cx),
ionScript_(ionScript ? ionScript : GetTopJitJSScript(cx)->ionScript()),
ionScript_(GetTopJitJSScript(cx)->ionScript()),
rval_(rval),
disabled_(false)
{ }

View File

@ -617,7 +617,13 @@ class AutoDetectInvalidation
void setReturnOverride();
public:
AutoDetectInvalidation(JSContext *cx, MutableHandleValue rval, IonScript *ionScript = nullptr);
AutoDetectInvalidation(JSContext *cx, MutableHandleValue rval, IonScript *ionScript)
: cx_(cx), ionScript_(ionScript), rval_(rval), disabled_(false)
{
MOZ_ASSERT(ionScript);
}
AutoDetectInvalidation(JSContext *cx, MutableHandleValue rval);
void disable() {
MOZ_ASSERT(!disabled_);