mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
[INFER] Always maintain a synced interpreter stack for method JIT stub calls, bug 685358.
This commit is contained in:
parent
ceb94a57c3
commit
d3435e89d8
@ -506,7 +506,7 @@ JSCompartment::markTypes(JSTracer *trc)
|
||||
}
|
||||
|
||||
void
|
||||
JSCompartment::sweep(JSContext *cx, uint32 releaseInterval)
|
||||
JSCompartment::sweep(JSContext *cx, bool releaseTypes)
|
||||
{
|
||||
/* Remove dead wrappers from the table. */
|
||||
for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) {
|
||||
@ -545,49 +545,8 @@ JSCompartment::sweep(JSContext *cx, uint32 releaseInterval)
|
||||
traceMonitor()->sweep(cx);
|
||||
#endif
|
||||
|
||||
# if defined JS_METHODJIT && defined JS_POLYIC
|
||||
/*
|
||||
* Purge all PICs in the compartment. These can reference type data and
|
||||
* need to know which types are pending collection.
|
||||
*/
|
||||
for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
if (script->hasJITCode())
|
||||
mjit::ic::PurgePICs(cx, script);
|
||||
}
|
||||
# endif
|
||||
|
||||
bool discardScripts = !active && (releaseInterval != 0 || hasDebugModeCodeToDrop);
|
||||
|
||||
#if defined JS_METHODJIT && defined JS_MONOIC
|
||||
|
||||
/*
|
||||
* The release interval is the frequency with which we should try to destroy
|
||||
* executable pools by releasing all JIT code in them, zero to never destroy pools.
|
||||
* Initialize counter so that the first pool will be destroyed, and eventually drive
|
||||
* the amount of JIT code in never-used compartments to zero. Don't discard anything
|
||||
* for compartments which currently have active stack frames.
|
||||
*/
|
||||
uint32 counter = 1;
|
||||
if (discardScripts)
|
||||
hasDebugModeCodeToDrop = false;
|
||||
|
||||
for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
if (script->hasJITCode()) {
|
||||
mjit::ic::SweepCallICs(cx, script, discardScripts);
|
||||
if (discardScripts) {
|
||||
ScriptTryDestroyCode(cx, script, true, releaseInterval, counter);
|
||||
ScriptTryDestroyCode(cx, script, false, releaseInterval, counter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
if (types.inferenceEnabled)
|
||||
mjit::ClearAllFrames(this);
|
||||
mjit::ClearAllFrames(this);
|
||||
#endif
|
||||
|
||||
if (activeAnalysis) {
|
||||
@ -597,11 +556,9 @@ JSCompartment::sweep(JSContext *cx, uint32 releaseInterval)
|
||||
* GC then shape numbers baked into the code may change.
|
||||
*/
|
||||
#ifdef JS_METHODJIT
|
||||
if (types.inferenceEnabled) {
|
||||
for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
mjit::ReleaseScriptCode(cx, script);
|
||||
}
|
||||
for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
mjit::ReleaseScriptCode(cx, script);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
@ -618,17 +575,19 @@ JSCompartment::sweep(JSContext *cx, uint32 releaseInterval)
|
||||
* enabled in the compartment.
|
||||
*/
|
||||
if (types.inferenceEnabled) {
|
||||
if (active)
|
||||
releaseTypes = false;
|
||||
for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
if (script->types) {
|
||||
types::TypeScript::Sweep(cx, script);
|
||||
|
||||
/*
|
||||
* On each 1/8 lifetime, release observed types for all scripts.
|
||||
* This is always safe to do when there are no frames for the
|
||||
* compartment on the stack.
|
||||
* Periodically release observed types for all scripts.
|
||||
* This is always safe to do when there are no frames for
|
||||
* the compartment on the stack.
|
||||
*/
|
||||
if (discardScripts) {
|
||||
if (releaseTypes) {
|
||||
script->types->destroy();
|
||||
script->types = NULL;
|
||||
script->typesPurged = true;
|
||||
@ -684,20 +643,6 @@ JSCompartment::purge(JSContext *cx)
|
||||
if (hasTraceMonitor())
|
||||
traceMonitor()->needFlush = JS_TRUE;
|
||||
#endif
|
||||
|
||||
#if defined JS_METHODJIT && defined JS_MONOIC
|
||||
/*
|
||||
* MICs do not refer to data which can be GC'ed and do not generate stubs
|
||||
* which might need to be discarded, but are sensitive to shape regeneration.
|
||||
*/
|
||||
if (cx->runtime->gcRegenShapes) {
|
||||
for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
if (script->hasJITCode())
|
||||
mjit::ic::PurgeMICs(cx, script);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
MathCache *
|
||||
|
@ -532,7 +532,7 @@ struct JS_FRIEND_API(JSCompartment) {
|
||||
bool wrap(JSContext *cx, js::AutoIdVector &props);
|
||||
|
||||
void markTypes(JSTracer *trc);
|
||||
void sweep(JSContext *cx, uint32 releaseInterval);
|
||||
void sweep(JSContext *cx, bool releaseTypes);
|
||||
void purge(JSContext *cx);
|
||||
|
||||
void setGCLastBytes(size_t lastBytes, JSGCInvocationKind gckind);
|
||||
|
@ -646,12 +646,8 @@ js_GCThingIsMarked(void *thing, uintN color = BLACK)
|
||||
return reinterpret_cast<Cell *>(thing)->isMarked(color);
|
||||
}
|
||||
|
||||
/*
|
||||
* 1/8 life for JIT code. After this number of microseconds have passed, 1/8 of all
|
||||
* JIT code is discarded in inactive compartments, regardless of how often that
|
||||
* code runs.
|
||||
*/
|
||||
static const int64 JIT_SCRIPT_EIGHTH_LIFETIME = 60 * 1000 * 1000;
|
||||
/* Lifetime for type sets attached to scripts containing observed types. */
|
||||
static const int64 JIT_SCRIPT_RELEASE_TYPES_INTERVAL = 60 * 1000 * 1000;
|
||||
|
||||
JSBool
|
||||
js_InitGC(JSRuntime *rt, uint32 maxbytes)
|
||||
@ -693,7 +689,7 @@ js_InitGC(JSRuntime *rt, uint32 maxbytes)
|
||||
*/
|
||||
rt->setGCLastBytes(8192, GC_NORMAL);
|
||||
|
||||
rt->gcJitReleaseTime = PRMJ_Now() + JIT_SCRIPT_EIGHTH_LIFETIME;
|
||||
rt->gcJitReleaseTime = PRMJ_Now() + JIT_SCRIPT_RELEASE_TYPES_INTERVAL;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2127,20 +2123,12 @@ static void
|
||||
SweepCrossCompartmentWrappers(JSContext *cx)
|
||||
{
|
||||
JSRuntime *rt = cx->runtime;
|
||||
/*
|
||||
* Figure out how much JIT code should be released from inactive compartments.
|
||||
* If multiple eighth-lives have passed, compound the release interval linearly;
|
||||
* if enough time has passed, all inactive JIT code will be released.
|
||||
*/
|
||||
uint32 releaseInterval = 0;
|
||||
|
||||
bool releaseTypes = false;
|
||||
int64 now = PRMJ_Now();
|
||||
if (now >= rt->gcJitReleaseTime) {
|
||||
releaseInterval = 8;
|
||||
while (now >= rt->gcJitReleaseTime) {
|
||||
if (--releaseInterval == 1)
|
||||
rt->gcJitReleaseTime = now;
|
||||
rt->gcJitReleaseTime += JIT_SCRIPT_EIGHTH_LIFETIME;
|
||||
}
|
||||
releaseTypes = true;
|
||||
rt->gcJitReleaseTime = now + JIT_SCRIPT_RELEASE_TYPES_INTERVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2151,7 +2139,7 @@ SweepCrossCompartmentWrappers(JSContext *cx)
|
||||
* (4) Sweep the method JIT ICs and release infrequently used JIT code.
|
||||
*/
|
||||
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c)
|
||||
(*c)->sweep(cx, releaseInterval);
|
||||
(*c)->sweep(cx, releaseTypes);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -859,13 +859,6 @@ MarkChildren(JSTracer *trc, JSScript *script)
|
||||
|
||||
if (script->types)
|
||||
script->types->trace(trc);
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
if (script->jitNormal)
|
||||
script->jitNormal->trace(trc);
|
||||
if (script->jitCtor)
|
||||
script->jitCtor->trace(trc);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -122,7 +122,6 @@ mjit::Compiler::Compiler(JSContext *cx, JSScript *outerScript, bool isConstructi
|
||||
jumpTables(CompilerAllocPolicy(cx, *thisFromCtor())),
|
||||
jumpTableOffsets(CompilerAllocPolicy(cx, *thisFromCtor())),
|
||||
loopEntries(CompilerAllocPolicy(cx, *thisFromCtor())),
|
||||
rootedObjects(CompilerAllocPolicy(cx, *thisFromCtor())),
|
||||
stubcc(cx, *thisFromCtor(), frame),
|
||||
debugMode_(cx->compartment->debugMode()),
|
||||
#if defined JS_TRACER
|
||||
@ -942,7 +941,6 @@ mjit::Compiler::finishThisUp(JITScript **jitp)
|
||||
sizeof(NativeMapEntry) * nNmapLive +
|
||||
sizeof(InlineFrame) * inlineFrames.length() +
|
||||
sizeof(CallSite) * callSites.length() +
|
||||
sizeof(JSObject *) * rootedObjects.length() +
|
||||
#if defined JS_MONOIC
|
||||
sizeof(ic::GetGlobalNameIC) * getGlobalNames.length() +
|
||||
sizeof(ic::SetGlobalNameIC) * setGlobalNames.length() +
|
||||
@ -1074,13 +1072,6 @@ mjit::Compiler::finishThisUp(JITScript **jitp)
|
||||
stubCode.patch(from.loopPatch.codePatch, result + codeOffset);
|
||||
}
|
||||
|
||||
/* Build the list of objects rooted by the script. */
|
||||
JSObject **jitRooted = (JSObject **)cursor;
|
||||
jit->nRootedObjects = rootedObjects.length();
|
||||
cursor += sizeof(JSObject *) * jit->nRootedObjects;
|
||||
for (size_t i = 0; i < jit->nRootedObjects; i++)
|
||||
jitRooted[i] = rootedObjects[i];
|
||||
|
||||
#if defined JS_MONOIC
|
||||
JS_INIT_CLIST(&jit->callers);
|
||||
|
||||
@ -4661,12 +4652,6 @@ mjit::Compiler::jsop_callprop_str(JSAtom *atom)
|
||||
if (!js_GetClassPrototype(cx, globalObj, JSProto_String, &obj))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Root the proto, since JS_ClearScope might overwrite the global object's
|
||||
* copy.
|
||||
*/
|
||||
rootedObjects.append(obj);
|
||||
|
||||
/* Force into a register because getprop won't expect a constant. */
|
||||
RegisterID reg = frame.allocReg();
|
||||
|
||||
|
@ -455,7 +455,6 @@ class Compiler : public BaseCompiler
|
||||
js::Vector<JumpTable, 16> jumpTables;
|
||||
js::Vector<uint32, 16> jumpTableOffsets;
|
||||
js::Vector<LoopEntry, 16> loopEntries;
|
||||
js::Vector<JSObject *, 0, CompilerAllocPolicy> rootedObjects;
|
||||
StubCompiler stubcc;
|
||||
Label invokeLabel;
|
||||
Label arityLabel;
|
||||
|
@ -1324,11 +1324,7 @@ FrameState::sync(Assembler &masm, Uses uses) const
|
||||
Registers avail(freeRegs.freeMask & Registers::AvailRegs);
|
||||
Registers temp(Registers::TempAnyRegs);
|
||||
|
||||
FrameEntry *bottom = (cx->typeInferenceEnabled() || cx->compartment->debugMode())
|
||||
? entries
|
||||
: a->sp - uses.nuses;
|
||||
|
||||
for (FrameEntry *fe = a->sp - 1; fe >= bottom; fe--) {
|
||||
for (FrameEntry *fe = a->sp - 1; fe >= entries; fe--) {
|
||||
if (!fe->isTracked())
|
||||
continue;
|
||||
|
||||
@ -1378,7 +1374,7 @@ FrameState::sync(Assembler &masm, Uses uses) const
|
||||
/* Fall back to a slower sync algorithm if load required. */
|
||||
if ((!fe->type.synced() && backing->type.inMemory()) ||
|
||||
(!fe->data.synced() && backing->data.inMemory())) {
|
||||
syncFancy(masm, avail, fe, bottom);
|
||||
syncFancy(masm, avail, fe, entries);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@ -1459,11 +1455,7 @@ FrameState::syncAndKill(Registers kill, Uses uses, Uses ignore)
|
||||
|
||||
uint32 maxvisits = tracker.nentries;
|
||||
|
||||
FrameEntry *bottom = (cx->typeInferenceEnabled() || cx->compartment->debugMode())
|
||||
? entries
|
||||
: a->sp - uses.nuses;
|
||||
|
||||
for (FrameEntry *fe = a->sp - 1; fe >= bottom && maxvisits; fe--) {
|
||||
for (FrameEntry *fe = a->sp - 1; fe >= entries && maxvisits; fe--) {
|
||||
if (!fe->isTracked())
|
||||
continue;
|
||||
|
||||
|
@ -990,16 +990,10 @@ JITScript::callSites() const
|
||||
return (js::mjit::CallSite *)&inlineFrames()[nInlineFrames];
|
||||
}
|
||||
|
||||
JSObject **
|
||||
JITScript::rootedObjects() const
|
||||
{
|
||||
return (JSObject **)&callSites()[nCallSites];
|
||||
}
|
||||
|
||||
char *
|
||||
JITScript::commonSectionLimit() const
|
||||
{
|
||||
return (char *)&rootedObjects()[nRootedObjects];
|
||||
return (char *)&callSites()[nCallSites];
|
||||
}
|
||||
|
||||
#ifdef JS_MONOIC
|
||||
@ -1164,7 +1158,6 @@ mjit::JITScript::scriptDataSize(JSUsableSizeFun usf)
|
||||
sizeof(NativeMapEntry) * nNmapPairs +
|
||||
sizeof(InlineFrame) * nInlineFrames +
|
||||
sizeof(CallSite) * nCallSites +
|
||||
sizeof(JSObject *) * nRootedObjects +
|
||||
#if defined JS_MONOIC
|
||||
sizeof(ic::GetGlobalNameIC) * nGetGlobalNames +
|
||||
sizeof(ic::SetGlobalNameIC) * nSetGlobalNames +
|
||||
@ -1304,20 +1297,4 @@ mjit::NativeToPC(JITScript *jit, void *ncode, mjit::CallSite **pinline)
|
||||
return jit->nativeToPC(ncode, pinline);
|
||||
}
|
||||
|
||||
void
|
||||
JITScript::trace(JSTracer *trc)
|
||||
{
|
||||
/*
|
||||
* MICs and PICs attached to the JITScript are weak references, and either
|
||||
* entirely purged or selectively purged on each GC. We do, however, need
|
||||
* to maintain references to any scripts whose code was inlined into this.
|
||||
*/
|
||||
InlineFrame *inlineFrames_ = inlineFrames();
|
||||
for (unsigned i = 0; i < nInlineFrames; i++)
|
||||
MarkObject(trc, *inlineFrames_[i].fun, "jitscript_fun");
|
||||
|
||||
for (uint32 i = 0; i < nRootedObjects; ++i)
|
||||
MarkObject(trc, *rootedObjects()[i], "mjit rooted object");
|
||||
}
|
||||
|
||||
/* static */ const double mjit::Assembler::oneDouble = 1.0;
|
||||
|
@ -605,7 +605,6 @@ struct JITScript {
|
||||
bool singleStepMode:1; /* compiled in "single step mode" */
|
||||
uint32 nInlineFrames;
|
||||
uint32 nCallSites;
|
||||
uint32 nRootedObjects;
|
||||
#ifdef JS_MONOIC
|
||||
uint32 nGetGlobalNames;
|
||||
uint32 nSetGlobalNames;
|
||||
@ -643,7 +642,6 @@ struct JITScript {
|
||||
NativeMapEntry *nmap() const;
|
||||
js::mjit::InlineFrame *inlineFrames() const;
|
||||
js::mjit::CallSite *callSites() const;
|
||||
JSObject **rootedObjects() const;
|
||||
#ifdef JS_MONOIC
|
||||
ic::GetGlobalNameIC *getGlobalNames() const;
|
||||
ic::SetGlobalNameIC *setGlobalNames() const;
|
||||
@ -666,11 +664,6 @@ struct JITScript {
|
||||
}
|
||||
|
||||
void nukeScriptDependentICs();
|
||||
void sweepCallICs(JSContext *cx, bool purgeAll);
|
||||
void purgeMICs();
|
||||
void purgePICs();
|
||||
|
||||
void trace(JSTracer *trc);
|
||||
|
||||
/* |usf| can be NULL here, in which case the fallback size computation will be used. */
|
||||
size_t scriptDataSize(JSUsableSizeFun usf);
|
||||
|
@ -1383,168 +1383,5 @@ JITScript::resetArgsCheck()
|
||||
repatch.relink(argsCheckJump, argsCheckStub);
|
||||
}
|
||||
|
||||
void
|
||||
JITScript::purgeMICs()
|
||||
{
|
||||
if (!nGetGlobalNames || !nSetGlobalNames)
|
||||
return;
|
||||
|
||||
Repatcher repatch(this);
|
||||
|
||||
ic::GetGlobalNameIC *getGlobalNames_ = getGlobalNames();
|
||||
for (uint32 i = 0; i < nGetGlobalNames; i++) {
|
||||
ic::GetGlobalNameIC &ic = getGlobalNames_[i];
|
||||
JSC::CodeLocationDataLabel32 label = ic.fastPathStart.dataLabel32AtOffset(ic.shapeOffset);
|
||||
repatch.repatch(label, int(INVALID_SHAPE));
|
||||
}
|
||||
|
||||
ic::SetGlobalNameIC *setGlobalNames_ = setGlobalNames();
|
||||
for (uint32 i = 0; i < nSetGlobalNames; i++) {
|
||||
ic::SetGlobalNameIC &ic = setGlobalNames_[i];
|
||||
ic.patchInlineShapeGuard(repatch, int32(INVALID_SHAPE));
|
||||
|
||||
if (ic.hasExtraStub) {
|
||||
Repatcher repatcher(ic.extraStub);
|
||||
ic.patchExtraShapeGuard(repatcher, int32(INVALID_SHAPE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ic::PurgeMICs(JSContext *cx, JSScript *script)
|
||||
{
|
||||
/* MICs are purged during GC to handle changing shapes. */
|
||||
JS_ASSERT(cx->runtime->gcRegenShapes);
|
||||
|
||||
if (script->jitNormal)
|
||||
script->jitNormal->purgeMICs();
|
||||
if (script->jitCtor)
|
||||
script->jitCtor->purgeMICs();
|
||||
}
|
||||
|
||||
void
|
||||
JITScript::nukeScriptDependentICs()
|
||||
{
|
||||
if (!nCallICs)
|
||||
return;
|
||||
|
||||
Repatcher repatcher(this);
|
||||
|
||||
ic::CallICInfo *callICs_ = callICs();
|
||||
for (uint32 i = 0; i < nCallICs; i++) {
|
||||
ic::CallICInfo &ic = callICs_[i];
|
||||
if (!ic.fastGuardedObject)
|
||||
continue;
|
||||
repatcher.repatch(ic.funGuard, NULL);
|
||||
repatcher.relink(ic.funJump, ic.slowPathStart);
|
||||
ic.releasePool(CallICInfo::Pool_ClosureStub);
|
||||
ic.fastGuardedObject = NULL;
|
||||
ic.hasJsFunCheck = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JITScript::sweepCallICs(JSContext *cx, bool purgeAll)
|
||||
{
|
||||
Repatcher repatcher(this);
|
||||
|
||||
/*
|
||||
* If purgeAll is set, purge stubs in the script except those covered by PurgePICs
|
||||
* (which is always called during GC). We want to remove references which can keep
|
||||
* alive pools that we are trying to destroy (see JSCompartment::sweep).
|
||||
*/
|
||||
|
||||
ic::CallICInfo *callICs_ = callICs();
|
||||
for (uint32 i = 0; i < nCallICs; i++) {
|
||||
ic::CallICInfo &ic = callICs_[i];
|
||||
|
||||
/*
|
||||
* If the object is unreachable, we're guaranteed not to be currently
|
||||
* executing a stub generated by a guard on that object. This lets us
|
||||
* precisely GC call ICs while keeping the identity guard safe.
|
||||
*/
|
||||
bool fastFunDead = ic.fastGuardedObject &&
|
||||
(purgeAll || IsAboutToBeFinalized(cx, ic.fastGuardedObject));
|
||||
bool nativeDead = ic.fastGuardedNative &&
|
||||
(purgeAll || IsAboutToBeFinalized(cx, ic.fastGuardedNative));
|
||||
|
||||
/*
|
||||
* There are three conditions where we need to relink:
|
||||
* (1) purgeAll is true.
|
||||
* (2) The native is dead, since it always has a stub.
|
||||
* (3) The fastFun is dead *and* there is a closure stub.
|
||||
*
|
||||
* Note although both objects can be non-NULL, there can only be one
|
||||
* of [closure, native] stub per call IC.
|
||||
*/
|
||||
if (purgeAll || nativeDead || (fastFunDead && ic.hasJsFunCheck)) {
|
||||
repatcher.relink(ic.funJump, ic.slowPathStart);
|
||||
ic.hit = false;
|
||||
}
|
||||
|
||||
if (fastFunDead) {
|
||||
repatcher.repatch(ic.funGuard, NULL);
|
||||
ic.purgeGuardedObject();
|
||||
}
|
||||
|
||||
if (nativeDead)
|
||||
ic.fastGuardedNative = NULL;
|
||||
|
||||
if (purgeAll) {
|
||||
ic.releasePool(CallICInfo::Pool_ScriptStub);
|
||||
JSC::CodeLocationJump oolJump = ic.slowPathStart.jumpAtOffset(ic.oolJumpOffset);
|
||||
JSC::CodeLocationLabel icCall = ic.slowPathStart.labelAtOffset(ic.icCallOffset);
|
||||
repatcher.relink(oolJump, icCall);
|
||||
}
|
||||
}
|
||||
|
||||
/* The arguments type check IC can refer to type objects which might be swept. */
|
||||
if (argsCheckPool)
|
||||
resetArgsCheck();
|
||||
|
||||
if (purgeAll) {
|
||||
/* Purge ICs generating stubs into execPools. */
|
||||
uint32 released = 0;
|
||||
|
||||
ic::EqualityICInfo *equalityICs_ = equalityICs();
|
||||
for (uint32 i = 0; i < nEqualityICs; i++) {
|
||||
ic::EqualityICInfo &ic = equalityICs_[i];
|
||||
if (!ic.generated)
|
||||
continue;
|
||||
|
||||
JSC::FunctionPtr fptr(JS_FUNC_TO_DATA_PTR(void *, ic::Equality));
|
||||
repatcher.relink(ic.stubCall, fptr);
|
||||
repatcher.relink(ic.jumpToStub, ic.stubEntry);
|
||||
|
||||
ic.generated = false;
|
||||
released++;
|
||||
}
|
||||
|
||||
ic::SetGlobalNameIC *setGlobalNames_ = setGlobalNames();
|
||||
for (uint32 i = 0; i < nSetGlobalNames; i ++) {
|
||||
ic::SetGlobalNameIC &ic = setGlobalNames_[i];
|
||||
if (!ic.hasExtraStub)
|
||||
continue;
|
||||
repatcher.relink(ic.fastPathStart.jumpAtOffset(ic.inlineShapeJump), ic.slowPathStart);
|
||||
ic.hasExtraStub = false;
|
||||
released++;
|
||||
}
|
||||
|
||||
JS_ASSERT(released == execPools.length());
|
||||
for (uint32 i = 0; i < released; i++)
|
||||
execPools[i]->release();
|
||||
execPools.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ic::SweepCallICs(JSContext *cx, JSScript *script, bool purgeAll)
|
||||
{
|
||||
if (script->jitNormal)
|
||||
script->jitNormal->sweepCallICs(cx, purgeAll);
|
||||
if (script->jitCtor)
|
||||
script->jitCtor->sweepCallICs(cx, purgeAll);
|
||||
}
|
||||
|
||||
#endif /* JS_MONOIC */
|
||||
|
||||
|
@ -301,9 +301,6 @@ JSBool JS_FASTCALL SplatApplyArgs(VMFrame &f);
|
||||
|
||||
void GenerateArgumentCheckStub(VMFrame &f);
|
||||
|
||||
void PurgeMICs(JSContext *cx, JSScript *script);
|
||||
void SweepCallICs(JSContext *cx, JSScript *script, bool purgeAll);
|
||||
|
||||
} /* namespace ic */
|
||||
} /* namespace mjit */
|
||||
} /* namespace js */
|
||||
|
@ -3261,57 +3261,5 @@ ic::SetElement(VMFrame &f, ic::SetElementIC *ic)
|
||||
template void JS_FASTCALL ic::SetElement<true>(VMFrame &f, SetElementIC *ic);
|
||||
template void JS_FASTCALL ic::SetElement<false>(VMFrame &f, SetElementIC *ic);
|
||||
|
||||
void
|
||||
JITScript::purgePICs()
|
||||
{
|
||||
if (!nPICs && !nGetElems && !nSetElems)
|
||||
return;
|
||||
|
||||
Repatcher repatcher(this);
|
||||
|
||||
ic::PICInfo *pics_ = pics();
|
||||
for (uint32 i = 0; i < nPICs; i++) {
|
||||
ic::PICInfo &pic = pics_[i];
|
||||
switch (pic.kind) {
|
||||
case ic::PICInfo::SET:
|
||||
case ic::PICInfo::SETMETHOD:
|
||||
SetPropCompiler::reset(repatcher, pic);
|
||||
break;
|
||||
case ic::PICInfo::NAME:
|
||||
case ic::PICInfo::XNAME:
|
||||
case ic::PICInfo::CALLNAME:
|
||||
ScopeNameCompiler::reset(repatcher, pic);
|
||||
break;
|
||||
case ic::PICInfo::BIND:
|
||||
BindNameCompiler::reset(repatcher, pic);
|
||||
break;
|
||||
case ic::PICInfo::CALL: /* fall-through */
|
||||
case ic::PICInfo::GET:
|
||||
GetPropCompiler::reset(repatcher, pic);
|
||||
break;
|
||||
default:
|
||||
JS_NOT_REACHED("Unhandled PIC kind");
|
||||
break;
|
||||
}
|
||||
pic.reset();
|
||||
}
|
||||
|
||||
ic::GetElementIC *getElems_ = getElems();
|
||||
ic::SetElementIC *setElems_ = setElems();
|
||||
for (uint32 i = 0; i < nGetElems; i++)
|
||||
getElems_[i].purge(repatcher);
|
||||
for (uint32 i = 0; i < nSetElems; i++)
|
||||
setElems_[i].purge(repatcher);
|
||||
}
|
||||
|
||||
void
|
||||
ic::PurgePICs(JSContext *cx, JSScript *script)
|
||||
{
|
||||
if (script->jitNormal)
|
||||
script->jitNormal->purgePICs();
|
||||
if (script->jitCtor)
|
||||
script->jitCtor->purgePICs();
|
||||
}
|
||||
|
||||
#endif /* JS_POLYIC */
|
||||
|
||||
|
@ -554,7 +554,6 @@ struct PICInfo : public BasePolyIC {
|
||||
};
|
||||
|
||||
#ifdef JS_POLYIC
|
||||
void PurgePICs(JSContext *cx, JSScript *script);
|
||||
void JS_FASTCALL GetProp(VMFrame &f, ic::PICInfo *);
|
||||
void JS_FASTCALL GetPropNoCache(VMFrame &f, ic::PICInfo *);
|
||||
void JS_FASTCALL SetProp(VMFrame &f, ic::PICInfo *);
|
||||
|
Loading…
Reference in New Issue
Block a user