mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Bug 737365 - stop using the cx during finalization, part 3.
This part removes the usage of JSContext* during the finalization and when sweeping the compartments. That required to change quite a few methods in type inference, jit and debugger implementation to take a FreeOp rather than JSContext pointer. In turn that also often required to replace cx->compartment usage with extracting the compartment from the passed objects or pass the compartment explicitly. On the plus side it allowed to remove fallible compartment enter code in methods that could be called during finalization.
This commit is contained in:
parent
ac58c404f7
commit
18841022a6
@ -707,7 +707,7 @@ JSRuntime::JSRuntime()
|
||||
nativeStackQuota(0),
|
||||
interpreterFrames(NULL),
|
||||
cxCallback(NULL),
|
||||
compartmentCallback(NULL),
|
||||
destroyCompartmentCallback(NULL),
|
||||
activityCallback(NULL),
|
||||
activityCallbackArg(NULL),
|
||||
#ifdef JS_THREADSAFE
|
||||
@ -776,7 +776,7 @@ JSRuntime::JSRuntime()
|
||||
gcLock(NULL),
|
||||
gcHelperThread(thisFromCtor()),
|
||||
#endif
|
||||
defaultFreeOp_(thisFromCtor(), false, false, NULL),
|
||||
defaultFreeOp_(thisFromCtor(), false, false),
|
||||
debuggerMutations(0),
|
||||
securityCallbacks(const_cast<JSSecurityCallbacks *>(&NullSecurityCallbacks)),
|
||||
destroyPrincipals(NULL),
|
||||
@ -1325,12 +1325,10 @@ JS_GetImplementationVersion(void)
|
||||
return "JavaScript-C 1.8.5+ 2011-04-16";
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSCompartmentCallback)
|
||||
JS_SetCompartmentCallback(JSRuntime *rt, JSCompartmentCallback callback)
|
||||
JS_PUBLIC_API(void)
|
||||
JS_SetDestroyCompartmentCallback(JSRuntime *rt, JSDestroyCompartmentCallback callback)
|
||||
{
|
||||
JSCompartmentCallback old = rt->compartmentCallback;
|
||||
rt->compartmentCallback = callback;
|
||||
return old;
|
||||
rt->destroyCompartmentCallback = callback;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSWrapObjectCallback)
|
||||
@ -3052,7 +3050,7 @@ JS_IdArrayGet(JSContext *cx, JSIdArray *ida, int index)
|
||||
JS_PUBLIC_API(void)
|
||||
JS_DestroyIdArray(JSContext *cx, JSIdArray *ida)
|
||||
{
|
||||
cx->free_(ida);
|
||||
DestroyIdArray(cx->runtime->defaultFreeOp(), ida);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
@ -4276,7 +4274,7 @@ prop_iter_finalize(FreeOp *fop, JSObject *obj)
|
||||
if (obj->getSlot(JSSLOT_ITER_INDEX).toInt32() >= 0) {
|
||||
/* Non-native case: destroy the ida enumerated when obj was created. */
|
||||
JSIdArray *ida = (JSIdArray *) pdata;
|
||||
JS_DestroyIdArray(fop->context, ida);
|
||||
DestroyIdArray(fop, ida);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1597,12 +1597,8 @@ typedef JSObject *
|
||||
typedef JSObject *
|
||||
(* JSPreWrapCallback)(JSContext *cx, JSObject *scope, JSObject *obj, unsigned flags);
|
||||
|
||||
typedef enum {
|
||||
JSCOMPARTMENT_DESTROY
|
||||
} JSCompartmentOp;
|
||||
|
||||
typedef JSBool
|
||||
(* JSCompartmentCallback)(JSContext *cx, JSCompartment *compartment, unsigned compartmentOp);
|
||||
typedef void
|
||||
(* JSDestroyCompartmentCallback)(JSFreeOp *fop, JSCompartment *compartment);
|
||||
|
||||
/*
|
||||
* Read structured data from the reader r. This hook is used to read a value
|
||||
@ -2681,8 +2677,8 @@ JS_SetJitHardening(JSRuntime *rt, JSBool enabled);
|
||||
extern JS_PUBLIC_API(const char *)
|
||||
JS_GetImplementationVersion(void);
|
||||
|
||||
extern JS_PUBLIC_API(JSCompartmentCallback)
|
||||
JS_SetCompartmentCallback(JSRuntime *rt, JSCompartmentCallback callback);
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_SetDestroyCompartmentCallback(JSRuntime *rt, JSDestroyCompartmentCallback callback);
|
||||
|
||||
extern JS_PUBLIC_API(JSWrapObjectCallback)
|
||||
JS_SetWrapObjectCallbacks(JSRuntime *rt,
|
||||
|
@ -218,7 +218,7 @@ js_FinishAtomState(JSRuntime *rt)
|
||||
return;
|
||||
}
|
||||
|
||||
FreeOp fop(rt, false, false, NULL);
|
||||
FreeOp fop(rt, false, false);
|
||||
for (AtomSet::Range r = state->atoms.all(); !r.empty(); r.popFront())
|
||||
r.front().asPtr()->finalize(&fop);
|
||||
}
|
||||
|
@ -186,18 +186,16 @@ struct ConservativeGCData
|
||||
class FreeOp : public JSFreeOp {
|
||||
bool shouldFreeLater_;
|
||||
bool onBackgroundThread_;
|
||||
public:
|
||||
JSContext *context;
|
||||
|
||||
public:
|
||||
static FreeOp *get(JSFreeOp *fop) {
|
||||
return static_cast<FreeOp *>(fop);
|
||||
}
|
||||
|
||||
FreeOp(JSRuntime *rt, bool shouldFreeLater, bool onBackgroundThread, JSContext *cx)
|
||||
FreeOp(JSRuntime *rt, bool shouldFreeLater, bool onBackgroundThread)
|
||||
: JSFreeOp(rt),
|
||||
shouldFreeLater_(shouldFreeLater),
|
||||
onBackgroundThread_(onBackgroundThread),
|
||||
context(cx)
|
||||
onBackgroundThread_(onBackgroundThread)
|
||||
{
|
||||
}
|
||||
|
||||
@ -290,8 +288,8 @@ struct JSRuntime : js::RuntimeFriendFields
|
||||
/* Context create/destroy callback. */
|
||||
JSContextCallback cxCallback;
|
||||
|
||||
/* Compartment create/destroy callback. */
|
||||
JSCompartmentCallback compartmentCallback;
|
||||
/* Compartment destroy callback. */
|
||||
JSDestroyCompartmentCallback destroyCompartmentCallback;
|
||||
|
||||
js::ActivityCallback activityCallback;
|
||||
void *activityCallbackArg;
|
||||
|
@ -98,7 +98,7 @@ class AutoNamespaceArray : protected AutoGCRooter {
|
||||
}
|
||||
|
||||
~AutoNamespaceArray() {
|
||||
array.finish(context);
|
||||
array.finish(context->runtime->defaultFreeOp());
|
||||
}
|
||||
|
||||
uint32_t length() const { return array.length; }
|
||||
|
@ -466,7 +466,7 @@ JSCompartment::markTypes(JSTracer *trc)
|
||||
}
|
||||
|
||||
void
|
||||
JSCompartment::discardJitCode(JSContext *cx)
|
||||
JSCompartment::discardJitCode(FreeOp *fop)
|
||||
{
|
||||
/*
|
||||
* Kick all frames on the stack into the interpreter, and release all JIT
|
||||
@ -477,7 +477,7 @@ JSCompartment::discardJitCode(JSContext *cx)
|
||||
|
||||
for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
mjit::ReleaseScriptCode(cx, script);
|
||||
mjit::ReleaseScriptCode(fop, script);
|
||||
|
||||
/*
|
||||
* Use counts for scripts are reset on GC. After discarding code we
|
||||
@ -521,7 +521,7 @@ JSCompartment::sweep(FreeOp *fop, bool releaseTypes)
|
||||
|
||||
{
|
||||
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_DISCARD_CODE);
|
||||
discardJitCode(fop->context);
|
||||
discardJitCode(fop);
|
||||
}
|
||||
|
||||
if (!activeAnalysis) {
|
||||
@ -552,7 +552,7 @@ JSCompartment::sweep(FreeOp *fop, bool releaseTypes)
|
||||
for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
if (script->types) {
|
||||
types::TypeScript::Sweep(fop->context, script);
|
||||
types::TypeScript::Sweep(fop, script);
|
||||
|
||||
if (releaseTypes) {
|
||||
script->types->destroy();
|
||||
@ -565,7 +565,7 @@ JSCompartment::sweep(FreeOp *fop, bool releaseTypes)
|
||||
|
||||
{
|
||||
gcstats::AutoPhase ap2(rt->gcStats, gcstats::PHASE_SWEEP_TYPES);
|
||||
types.sweep(fop->context);
|
||||
types.sweep(fop);
|
||||
}
|
||||
|
||||
{
|
||||
@ -677,12 +677,12 @@ JSCompartment::setDebugModeFromC(JSContext *cx, bool b)
|
||||
debugModeBits = (debugModeBits & ~unsigned(DebugFromC)) | (b ? DebugFromC : 0);
|
||||
JS_ASSERT(debugMode() == enabledAfter);
|
||||
if (enabledBefore != enabledAfter)
|
||||
updateForDebugMode(cx);
|
||||
updateForDebugMode(cx->runtime->defaultFreeOp());
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
JSCompartment::updateForDebugMode(JSContext *cx)
|
||||
JSCompartment::updateForDebugMode(FreeOp *fop)
|
||||
{
|
||||
for (ContextIter acx(rt); !acx.done(); acx.next()) {
|
||||
if (acx->compartment == this)
|
||||
@ -704,7 +704,7 @@ JSCompartment::updateForDebugMode(JSContext *cx)
|
||||
for (gc::CellIter i(this, gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
if (script->debugMode != enabled) {
|
||||
mjit::ReleaseScriptCode(cx, script);
|
||||
mjit::ReleaseScriptCode(fop, script);
|
||||
script->clearAnalysis();
|
||||
script->debugMode = enabled;
|
||||
}
|
||||
@ -722,12 +722,12 @@ JSCompartment::addDebuggee(JSContext *cx, js::GlobalObject *global)
|
||||
}
|
||||
debugModeBits |= DebugFromJS;
|
||||
if (!wasEnabled)
|
||||
updateForDebugMode(cx);
|
||||
updateForDebugMode(cx->runtime->defaultFreeOp());
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
JSCompartment::removeDebuggee(JSContext *cx,
|
||||
JSCompartment::removeDebuggee(FreeOp *fop,
|
||||
js::GlobalObject *global,
|
||||
js::GlobalObjectSet::Enum *debuggeesEnum)
|
||||
{
|
||||
@ -741,7 +741,7 @@ JSCompartment::removeDebuggee(JSContext *cx,
|
||||
if (debuggees.empty()) {
|
||||
debugModeBits &= ~DebugFromJS;
|
||||
if (wasEnabled && !debugMode())
|
||||
updateForDebugMode(cx);
|
||||
updateForDebugMode(fop);
|
||||
}
|
||||
}
|
||||
|
||||
@ -761,7 +761,7 @@ JSCompartment::clearTraps(JSContext *cx)
|
||||
for (gc::CellIter i(this, gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
if (script->hasAnyBreakpointsOrStepMode())
|
||||
script->clearTraps(cx);
|
||||
script->clearTraps(cx->runtime->defaultFreeOp());
|
||||
}
|
||||
}
|
||||
|
||||
@ -786,7 +786,7 @@ JSCompartment::sweepBreakpoints(FreeOp *fop)
|
||||
for (Breakpoint *bp = site->firstBreakpoint(); bp; bp = nextbp) {
|
||||
nextbp = bp->nextInSite();
|
||||
if (scriptGone || IsAboutToBeFinalized(bp->debugger->toJSObject()))
|
||||
bp->destroy(fop->context);
|
||||
bp->destroy(fop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -383,7 +383,7 @@ struct JSCompartment
|
||||
bool wrap(JSContext *cx, js::AutoIdVector &props);
|
||||
|
||||
void markTypes(JSTracer *trc);
|
||||
void discardJitCode(JSContext *cx);
|
||||
void discardJitCode(js::FreeOp *fop);
|
||||
void sweep(js::FreeOp *fop, bool releaseTypes);
|
||||
void purge();
|
||||
|
||||
@ -446,12 +446,12 @@ struct JSCompartment
|
||||
|
||||
private:
|
||||
/* This is called only when debugMode() has just toggled. */
|
||||
void updateForDebugMode(JSContext *cx);
|
||||
void updateForDebugMode(js::FreeOp *fop);
|
||||
|
||||
public:
|
||||
js::GlobalObjectSet &getDebuggees() { return debuggees; }
|
||||
bool addDebuggee(JSContext *cx, js::GlobalObject *global);
|
||||
void removeDebuggee(JSContext *cx, js::GlobalObject *global,
|
||||
void removeDebuggee(js::FreeOp *fop, js::GlobalObject *global,
|
||||
js::GlobalObjectSet::Enum *debuggeesEnum = NULL);
|
||||
bool setDebugModeFromC(JSContext *cx, bool b);
|
||||
|
||||
|
@ -204,7 +204,7 @@ JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc, JSTrapHandler handle
|
||||
BreakpointSite *site = script->getOrCreateBreakpointSite(cx, pc, NULL);
|
||||
if (!site)
|
||||
return false;
|
||||
site->setTrap(cx, handler, closure);
|
||||
site->setTrap(cx->runtime->defaultFreeOp(), handler, closure);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -213,7 +213,7 @@ JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
JSTrapHandler *handlerp, jsval *closurep)
|
||||
{
|
||||
if (BreakpointSite *site = script->getBreakpointSite(pc)) {
|
||||
site->clearTrap(cx, handlerp, closurep);
|
||||
site->clearTrap(cx->runtime->defaultFreeOp(), handlerp, closurep);
|
||||
} else {
|
||||
if (handlerp)
|
||||
*handlerp = NULL;
|
||||
@ -225,7 +225,7 @@ JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
JS_PUBLIC_API(void)
|
||||
JS_ClearScriptTraps(JSContext *cx, JSScript *script)
|
||||
{
|
||||
script->clearTraps(cx);
|
||||
script->clearTraps(cx->runtime->defaultFreeOp());
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
|
@ -2765,7 +2765,7 @@ GCHelperThread::replenishAndFreeLater(void *ptr)
|
||||
void
|
||||
GCHelperThread::doSweep()
|
||||
{
|
||||
if (JSContext *cx = finalizationContext) {
|
||||
if (finalizationContext) {
|
||||
finalizationContext = NULL;
|
||||
AutoUnlockGC unlock(rt);
|
||||
|
||||
@ -2773,7 +2773,7 @@ GCHelperThread::doSweep()
|
||||
* We must finalize in the insert order, see comments in
|
||||
* finalizeObjects.
|
||||
*/
|
||||
FreeOp fop(rt, false, true, cx);
|
||||
FreeOp fop(rt, false, true);
|
||||
for (ArenaHeader **i = finalizeVector.begin(); i != finalizeVector.end(); ++i)
|
||||
ArenaLists::backgroundFinalize(&fop, *i);
|
||||
finalizeVector.resize(0);
|
||||
@ -2833,7 +2833,7 @@ static void
|
||||
SweepCompartments(FreeOp *fop, JSGCInvocationKind gckind)
|
||||
{
|
||||
JSRuntime *rt = fop->runtime();
|
||||
JSCompartmentCallback callback = rt->compartmentCallback;
|
||||
JSDestroyCompartmentCallback callback = rt->destroyCompartmentCallback;
|
||||
|
||||
/* Skip the atomsCompartment. */
|
||||
JSCompartment **read = rt->compartments.begin() + 1;
|
||||
@ -2850,7 +2850,7 @@ SweepCompartments(FreeOp *fop, JSGCInvocationKind gckind)
|
||||
{
|
||||
compartment->arenas.checkEmptyFreeLists();
|
||||
if (callback)
|
||||
JS_ALWAYS_TRUE(callback(fop->context, compartment, JSCOMPARTMENT_DESTROY));
|
||||
callback(fop, compartment);
|
||||
if (compartment->principals)
|
||||
JS_DropPrincipals(rt, compartment->principals);
|
||||
fop->delete_(compartment);
|
||||
@ -3115,7 +3115,7 @@ SweepPhase(JSContext *cx, JSGCInvocationKind gckind)
|
||||
for (GCCompartmentsIter c(rt); !c.done(); c.next())
|
||||
c->arenas.purge();
|
||||
|
||||
FreeOp fop(rt, !!cx->gcBackgroundFree, false, cx);
|
||||
FreeOp fop(rt, !!cx->gcBackgroundFree, false);
|
||||
{
|
||||
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_FINALIZE_START);
|
||||
if (rt->gcFinalizeCallback)
|
||||
@ -3416,7 +3416,7 @@ IncrementalGCSlice(JSContext *cx, int64_t budget, JSGCInvocationKind gckind)
|
||||
|
||||
for (GCCompartmentsIter c(rt); !c.done(); c.next()) {
|
||||
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_DISCARD_CODE);
|
||||
c->discardJitCode(cx);
|
||||
c->discardJitCode(rt->defaultFreeOp());
|
||||
}
|
||||
|
||||
BeginMarkPhase(rt);
|
||||
@ -4175,7 +4175,7 @@ StartVerifyBarriers(JSContext *cx)
|
||||
r.front()->bitmap.clear();
|
||||
|
||||
for (CompartmentsIter c(rt); !c.done(); c.next())
|
||||
c->discardJitCode(cx);
|
||||
c->discardJitCode(rt->defaultFreeOp());
|
||||
|
||||
VerifyTracer *trc = new (js_malloc(sizeof(VerifyTracer))) VerifyTracer;
|
||||
|
||||
@ -4329,7 +4329,7 @@ EndVerifyBarriers(JSContext *cx)
|
||||
c->needsBarrier_ = false;
|
||||
|
||||
for (CompartmentsIter c(rt); !c.done(); c.next())
|
||||
c->discardJitCode(cx);
|
||||
c->discardJitCode(rt->defaultFreeOp());
|
||||
|
||||
rt->gcVerifyData = NULL;
|
||||
rt->gcIncrementalState = NO_INCREMENTAL;
|
||||
@ -4423,7 +4423,7 @@ static void ReleaseAllJITCode(JSContext *cx)
|
||||
mjit::ClearAllFrames(c);
|
||||
for (CellIter i(c, FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
mjit::ReleaseScriptCode(cx, script);
|
||||
mjit::ReleaseScriptCode(cx->runtime->defaultFreeOp(), script);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -2082,7 +2082,7 @@ TypeCompartment::growPendingArray(JSContext *cx)
|
||||
}
|
||||
|
||||
void
|
||||
TypeCompartment::processPendingRecompiles(JSContext *cx)
|
||||
TypeCompartment::processPendingRecompiles(FreeOp *fop)
|
||||
{
|
||||
/* Steal the list of scripts to recompile, else we will try to recursively recompile them. */
|
||||
Vector<RecompileInfo> *pending = pendingRecompiles;
|
||||
@ -2092,18 +2092,18 @@ TypeCompartment::processPendingRecompiles(JSContext *cx)
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
|
||||
mjit::ExpandInlineFrames(cx->compartment);
|
||||
mjit::ExpandInlineFrames(compartment());
|
||||
|
||||
for (unsigned i = 0; i < pending->length(); i++) {
|
||||
const RecompileInfo &info = (*pending)[i];
|
||||
mjit::JITScript *jit = info.script->getJIT(info.constructing);
|
||||
if (jit && jit->chunkDescriptor(info.chunkIndex).chunk)
|
||||
mjit::Recompiler::clearStackReferencesAndChunk(cx, info.script, jit, info.chunkIndex);
|
||||
mjit::Recompiler::clearStackReferencesAndChunk(fop, info.script, jit, info.chunkIndex);
|
||||
}
|
||||
|
||||
#endif /* JS_METHODJIT */
|
||||
|
||||
cx->delete_(pending);
|
||||
fop->delete_(pending);
|
||||
}
|
||||
|
||||
void
|
||||
@ -2118,10 +2118,16 @@ TypeCompartment::setPendingNukeTypes(JSContext *cx)
|
||||
}
|
||||
|
||||
void
|
||||
TypeCompartment::nukeTypes(JSContext *cx)
|
||||
TypeCompartment::setPendingNukeTypesNoReport()
|
||||
{
|
||||
JS_ASSERT(this == &cx->compartment->types);
|
||||
JS_ASSERT(compartment()->activeInference);
|
||||
if (!pendingNukeTypes)
|
||||
pendingNukeTypes = true;
|
||||
}
|
||||
|
||||
void
|
||||
TypeCompartment::nukeTypes(FreeOp *fop)
|
||||
{
|
||||
/*
|
||||
* This is the usual response if we encounter an OOM while adding a type
|
||||
* or resolving type constraints. Reset the compartment to not use type
|
||||
@ -2135,28 +2141,28 @@ TypeCompartment::nukeTypes(JSContext *cx)
|
||||
*/
|
||||
JS_ASSERT(pendingNukeTypes);
|
||||
if (pendingRecompiles) {
|
||||
cx->free_(pendingRecompiles);
|
||||
fop->free_(pendingRecompiles);
|
||||
pendingRecompiles = NULL;
|
||||
}
|
||||
|
||||
inferenceEnabled = false;
|
||||
|
||||
/* Update the cached inferenceEnabled bit in all contexts. */
|
||||
for (ContextIter acx(cx->runtime); !acx.done(); acx.next())
|
||||
for (ContextIter acx(fop->runtime()); !acx.done(); acx.next())
|
||||
acx->setCompartment(acx->compartment);
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
|
||||
JSCompartment *compartment = cx->compartment;
|
||||
JSCompartment *compartment = this->compartment();
|
||||
mjit::ExpandInlineFrames(compartment);
|
||||
mjit::ClearAllFrames(compartment);
|
||||
|
||||
/* Throw away all JIT code in the compartment, but leave everything else alone. */
|
||||
|
||||
for (gc::CellIter i(cx->compartment, gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
for (gc::CellIter i(compartment, gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
if (script->hasJITCode())
|
||||
mjit::ReleaseScriptCode(cx, script);
|
||||
mjit::ReleaseScriptCode(fop, script);
|
||||
}
|
||||
#endif /* JS_METHODJIT */
|
||||
|
||||
@ -5730,7 +5736,7 @@ JSCompartment::getLazyType(JSContext *cx, JSObject *proto)
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
TypeSet::sweep(JSContext *cx, JSCompartment *compartment)
|
||||
TypeSet::sweep(JSCompartment *compartment)
|
||||
{
|
||||
/*
|
||||
* Purge references to type objects that are no longer live. Type sets hold
|
||||
@ -5754,7 +5760,7 @@ TypeSet::sweep(JSContext *cx, JSCompartment *compartment)
|
||||
if (pentry)
|
||||
*pentry = object;
|
||||
else
|
||||
compartment->types.setPendingNukeTypes(cx);
|
||||
compartment->types.setPendingNukeTypesNoReport();
|
||||
}
|
||||
}
|
||||
setBaseObjectCount(objectCount);
|
||||
@ -5789,7 +5795,7 @@ TypeObject::clearProperties()
|
||||
* so that type objects do not need later finalization.
|
||||
*/
|
||||
inline void
|
||||
TypeObject::sweep(JSContext *cx)
|
||||
TypeObject::sweep(FreeOp *fop)
|
||||
{
|
||||
/*
|
||||
* We may be regenerating existing type sets containing this object,
|
||||
@ -5811,7 +5817,7 @@ TypeObject::sweep(JSContext *cx)
|
||||
|
||||
if (!isMarked()) {
|
||||
if (newScript)
|
||||
Foreground::free_(newScript);
|
||||
fop->free_(newScript);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -5840,12 +5846,12 @@ TypeObject::sweep(JSContext *cx)
|
||||
(compartment, propertySet, propertyCount, prop->id);
|
||||
if (pentry) {
|
||||
*pentry = newProp;
|
||||
newProp->types.sweep(cx, compartment);
|
||||
newProp->types.sweep(compartment);
|
||||
} else {
|
||||
compartment->types.setPendingNukeTypes(cx);
|
||||
compartment->types.setPendingNukeTypesNoReport();
|
||||
}
|
||||
} else {
|
||||
compartment->types.setPendingNukeTypes(cx);
|
||||
compartment->types.setPendingNukeTypesNoReport();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5856,9 +5862,9 @@ TypeObject::sweep(JSContext *cx)
|
||||
Property *newProp = compartment->typeLifoAlloc.new_<Property>(*prop);
|
||||
if (newProp) {
|
||||
propertySet = (Property **) newProp;
|
||||
newProp->types.sweep(cx, compartment);
|
||||
newProp->types.sweep(compartment);
|
||||
} else {
|
||||
compartment->types.setPendingNukeTypes(cx);
|
||||
compartment->types.setPendingNukeTypesNoReport();
|
||||
}
|
||||
} else {
|
||||
propertySet = NULL;
|
||||
@ -5882,27 +5888,27 @@ TypeObject::sweep(JSContext *cx)
|
||||
|
||||
struct SweepTypeObjectOp
|
||||
{
|
||||
JSContext *cx;
|
||||
SweepTypeObjectOp(JSContext *cx) : cx(cx) {}
|
||||
FreeOp *fop;
|
||||
SweepTypeObjectOp(FreeOp *fop) : fop(fop) {}
|
||||
void operator()(gc::Cell *cell) {
|
||||
TypeObject *object = static_cast<TypeObject *>(cell);
|
||||
object->sweep(cx);
|
||||
object->sweep(fop);
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
SweepTypeObjects(JSContext *cx, JSCompartment *compartment)
|
||||
SweepTypeObjects(FreeOp *fop, JSCompartment *compartment)
|
||||
{
|
||||
SweepTypeObjectOp op(cx);
|
||||
SweepTypeObjectOp op(fop);
|
||||
gc::ForEachArenaAndCell(compartment, gc::FINALIZE_TYPE_OBJECT, gc::EmptyArenaOp, op);
|
||||
}
|
||||
|
||||
void
|
||||
TypeCompartment::sweep(JSContext *cx)
|
||||
TypeCompartment::sweep(FreeOp *fop)
|
||||
{
|
||||
JSCompartment *compartment = this->compartment();
|
||||
|
||||
SweepTypeObjects(cx, compartment);
|
||||
SweepTypeObjects(fop, compartment);
|
||||
|
||||
/*
|
||||
* Iterate through the array/object type tables and remove all entries
|
||||
@ -5970,7 +5976,7 @@ TypeCompartment::sweep(JSContext *cx)
|
||||
* to reallocate if the compartment becomes active again.
|
||||
*/
|
||||
if (pendingArray)
|
||||
cx->free_(pendingArray);
|
||||
fop->free_(pendingArray);
|
||||
|
||||
pendingArray = NULL;
|
||||
pendingCapacity = 0;
|
||||
@ -6004,7 +6010,7 @@ TypeCompartment::~TypeCompartment()
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
TypeScript::Sweep(JSContext *cx, JSScript *script)
|
||||
TypeScript::Sweep(FreeOp *fop, JSScript *script)
|
||||
{
|
||||
JSCompartment *compartment = script->compartment();
|
||||
JS_ASSERT(compartment->types.inferenceEnabled);
|
||||
@ -6014,7 +6020,7 @@ TypeScript::Sweep(JSContext *cx, JSScript *script)
|
||||
|
||||
/* Remove constraints and references to dead objects from the persistent type sets. */
|
||||
for (unsigned i = 0; i < num; i++)
|
||||
typeArray[i].sweep(cx, compartment);
|
||||
typeArray[i].sweep(compartment);
|
||||
|
||||
TypeResult **presult = &script->types->dynamicList;
|
||||
while (*presult) {
|
||||
@ -6024,7 +6030,7 @@ TypeScript::Sweep(JSContext *cx, JSScript *script)
|
||||
if (!type.isUnknown() && !type.isAnyObject() && type.isObject() &&
|
||||
IsAboutToBeFinalized(type.objectKey())) {
|
||||
*presult = result->next;
|
||||
cx->delete_(result);
|
||||
fop->delete_(result);
|
||||
} else {
|
||||
presult = &result->next;
|
||||
}
|
||||
|
@ -366,7 +366,7 @@ class TypeSet
|
||||
|
||||
void print(JSContext *cx);
|
||||
|
||||
inline void sweep(JSContext *cx, JSCompartment *compartment);
|
||||
inline void sweep(JSCompartment *compartment);
|
||||
inline size_t computedSizeOfExcludingThis();
|
||||
|
||||
/* Whether this set contains a specific type. */
|
||||
@ -864,7 +864,7 @@ struct TypeObject : gc::Cell
|
||||
void print(JSContext *cx);
|
||||
|
||||
inline void clearProperties();
|
||||
inline void sweep(JSContext *cx);
|
||||
inline void sweep(FreeOp *fop);
|
||||
|
||||
inline size_t computedSizeOfExcludingThis();
|
||||
|
||||
@ -1121,7 +1121,7 @@ class TypeScript
|
||||
static inline void SetArgument(JSContext *cx, JSScript *script, unsigned arg, Type type);
|
||||
static inline void SetArgument(JSContext *cx, JSScript *script, unsigned arg, const js::Value &value);
|
||||
|
||||
static void Sweep(JSContext *cx, JSScript *script);
|
||||
static void Sweep(FreeOp *fop, JSScript *script);
|
||||
inline void trace(JSTracer *trc);
|
||||
void destroy();
|
||||
};
|
||||
@ -1244,11 +1244,12 @@ struct TypeCompartment
|
||||
/* Make an object for an allocation site. */
|
||||
TypeObject *newAllocationSiteTypeObject(JSContext *cx, const AllocationSiteKey &key);
|
||||
|
||||
void nukeTypes(JSContext *cx);
|
||||
void processPendingRecompiles(JSContext *cx);
|
||||
void nukeTypes(FreeOp *fop);
|
||||
void processPendingRecompiles(FreeOp *fop);
|
||||
|
||||
/* Mark all types as needing destruction once inference has 'finished'. */
|
||||
void setPendingNukeTypes(JSContext *cx);
|
||||
void setPendingNukeTypesNoReport();
|
||||
|
||||
/* Mark a script as needing recompilation once inference has finished. */
|
||||
void addPendingRecompile(JSContext *cx, const RecompileInfo &info);
|
||||
@ -1261,7 +1262,7 @@ struct TypeCompartment
|
||||
/* Mark any type set containing obj as having a generic object type. */
|
||||
void markSetsUnknown(JSContext *cx, TypeObject *obj);
|
||||
|
||||
void sweep(JSContext *cx);
|
||||
void sweep(FreeOp *fop);
|
||||
void finalizeObjects();
|
||||
};
|
||||
|
||||
|
@ -202,23 +202,26 @@ TypeIdString(jsid id)
|
||||
*/
|
||||
struct AutoEnterTypeInference
|
||||
{
|
||||
JSContext *cx;
|
||||
FreeOp *freeOp;
|
||||
JSCompartment *compartment;
|
||||
bool oldActiveAnalysis;
|
||||
bool oldActiveInference;
|
||||
|
||||
AutoEnterTypeInference(JSContext *cx, bool compiling = false)
|
||||
: cx(cx), oldActiveAnalysis(cx->compartment->activeAnalysis),
|
||||
oldActiveInference(cx->compartment->activeInference)
|
||||
{
|
||||
JS_ASSERT_IF(!compiling, cx->compartment->types.inferenceEnabled);
|
||||
cx->compartment->activeAnalysis = true;
|
||||
cx->compartment->activeInference = true;
|
||||
init(cx->runtime->defaultFreeOp(), cx->compartment);
|
||||
}
|
||||
|
||||
AutoEnterTypeInference(FreeOp *fop, JSCompartment *comp)
|
||||
{
|
||||
init(fop, comp);
|
||||
}
|
||||
|
||||
~AutoEnterTypeInference()
|
||||
{
|
||||
cx->compartment->activeAnalysis = oldActiveAnalysis;
|
||||
cx->compartment->activeInference = oldActiveInference;
|
||||
compartment->activeAnalysis = oldActiveAnalysis;
|
||||
compartment->activeInference = oldActiveInference;
|
||||
|
||||
/*
|
||||
* If there are no more type inference activations on the stack,
|
||||
@ -226,14 +229,24 @@ struct AutoEnterTypeInference
|
||||
* invoking any scripted code while type inference is running.
|
||||
* :TODO: assert this.
|
||||
*/
|
||||
if (!cx->compartment->activeInference) {
|
||||
TypeCompartment *types = &cx->compartment->types;
|
||||
if (!compartment->activeInference) {
|
||||
TypeCompartment *types = &compartment->types;
|
||||
if (types->pendingNukeTypes)
|
||||
types->nukeTypes(cx);
|
||||
types->nukeTypes(freeOp);
|
||||
else if (types->pendingRecompiles)
|
||||
types->processPendingRecompiles(cx);
|
||||
types->processPendingRecompiles(freeOp);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void init(FreeOp *fop, JSCompartment *comp) {
|
||||
freeOp = fop;
|
||||
compartment = comp;
|
||||
oldActiveAnalysis = compartment->activeAnalysis;
|
||||
oldActiveInference = compartment->activeInference;
|
||||
compartment->activeAnalysis = true;
|
||||
compartment->activeInference = true;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -858,7 +858,7 @@ class EvalScriptGuard
|
||||
|
||||
~EvalScriptGuard() {
|
||||
if (script_) {
|
||||
js_CallDestroyScriptHook(cx_, script_);
|
||||
CallDestroyScriptHook(cx_->runtime->defaultFreeOp(), script_);
|
||||
script_->isActiveEval = false;
|
||||
script_->isCachedEval = true;
|
||||
script_->evalHashLink() = *bucket_;
|
||||
|
@ -1622,6 +1622,9 @@ NonNullObject(JSContext *cx, const Value &v);
|
||||
extern const char *
|
||||
InformalValueTypeName(const Value &v);
|
||||
|
||||
inline void
|
||||
DestroyIdArray(FreeOp *fop, JSIdArray *ida);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* jsobj_h___ */
|
||||
|
@ -1754,4 +1754,10 @@ js_PurgeScopeChain(JSContext *cx, JSObject *obj, jsid id)
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void
|
||||
js::DestroyIdArray(FreeOp *fop, JSIdArray *ida)
|
||||
{
|
||||
fop->free_(ida);
|
||||
}
|
||||
|
||||
#endif /* jsobjinlines_h___ */
|
||||
|
@ -231,10 +231,10 @@ Probes::registerMJITCode(JSContext *cx, js::mjit::JITScript *jscr,
|
||||
}
|
||||
|
||||
void
|
||||
Probes::discardMJITCode(JSContext *cx, mjit::JITScript *jscr, JSScript *script, void* address)
|
||||
Probes::discardMJITCode(FreeOp *fop, mjit::JITScript *jscr, JSScript *script, void* address)
|
||||
{
|
||||
for (JITWatcher **p = jitWatchers.begin(); p != jitWatchers.end(); ++p)
|
||||
(*p)->discardMJITCode(cx, jscr, script, address);
|
||||
(*p)->discardMJITCode(fop, jscr, script, address);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -264,7 +264,7 @@ public:
|
||||
void *mainCodeAddress, size_t mainCodeSize,
|
||||
void *stubCodeAddress, size_t stubCodeSize) = 0;
|
||||
|
||||
virtual void discardMJITCode(JSContext *cx, mjit::JITScript *jscr, JSScript *script,
|
||||
virtual void discardMJITCode(FreeOp *fop, mjit::JITScript *jscr, JSScript *script,
|
||||
void* address) = 0;
|
||||
|
||||
virtual void registerICCode(JSContext *cx,
|
||||
@ -316,7 +316,7 @@ registerMJITCode(JSContext *cx, js::mjit::JITScript *jscr,
|
||||
* Method JIT code is about to be discarded
|
||||
*/
|
||||
void
|
||||
discardMJITCode(JSContext *cx, mjit::JITScript *jscr, JSScript *script, void* address);
|
||||
discardMJITCode(FreeOp *fop, mjit::JITScript *jscr, JSScript *script, void* address);
|
||||
|
||||
/*
|
||||
* IC code has been allocated within the given JITScript
|
||||
|
@ -388,7 +388,7 @@ typedef void
|
||||
|
||||
/* called just before script destruction */
|
||||
typedef void
|
||||
(* JSDestroyScriptHook)(JSContext *cx,
|
||||
(* JSDestroyScriptHook)(JSFreeOp *fop,
|
||||
JSScript *script,
|
||||
void *callerdata);
|
||||
|
||||
|
@ -818,10 +818,10 @@ JSScript::initScriptCounts(JSContext *cx)
|
||||
}
|
||||
|
||||
void
|
||||
JSScript::destroyScriptCounts(JSContext *cx)
|
||||
JSScript::destroyScriptCounts(FreeOp *fop)
|
||||
{
|
||||
if (scriptCounts) {
|
||||
cx->free_(scriptCounts.pcCountsVector);
|
||||
fop->free_(scriptCounts.pcCountsVector);
|
||||
scriptCounts.pcCountsVector = NULL;
|
||||
}
|
||||
}
|
||||
@ -1380,21 +1380,21 @@ js_CallNewScriptHook(JSContext *cx, JSScript *script, JSFunction *fun)
|
||||
}
|
||||
|
||||
void
|
||||
js_CallDestroyScriptHook(JSContext *cx, JSScript *script)
|
||||
js::CallDestroyScriptHook(FreeOp *fop, JSScript *script)
|
||||
{
|
||||
if (!script->callDestroyHook)
|
||||
return;
|
||||
|
||||
if (JSDestroyScriptHook hook = cx->runtime->debugHooks.destroyScriptHook)
|
||||
hook(cx, script, cx->runtime->debugHooks.destroyScriptHookData);
|
||||
if (JSDestroyScriptHook hook = fop->runtime()->debugHooks.destroyScriptHook)
|
||||
hook(fop, script, fop->runtime()->debugHooks.destroyScriptHookData);
|
||||
script->callDestroyHook = false;
|
||||
JS_ClearScriptTraps(cx, script);
|
||||
script->clearTraps(fop);
|
||||
}
|
||||
|
||||
void
|
||||
JSScript::finalize(FreeOp *fop)
|
||||
{
|
||||
js_CallDestroyScriptHook(fop->context, this);
|
||||
CallDestroyScriptHook(fop, this);
|
||||
|
||||
JS_ASSERT_IF(principals, originPrincipals);
|
||||
if (principals)
|
||||
@ -1406,10 +1406,10 @@ JSScript::finalize(FreeOp *fop)
|
||||
types->destroy();
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
mjit::ReleaseScriptCode(fop->context, this);
|
||||
mjit::ReleaseScriptCode(fop, this);
|
||||
#endif
|
||||
|
||||
destroyScriptCounts(fop->context);
|
||||
destroyScriptCounts(fop);
|
||||
|
||||
if (sourceMap)
|
||||
fop->free_(sourceMap);
|
||||
@ -1420,7 +1420,7 @@ JSScript::finalize(FreeOp *fop)
|
||||
if (BreakpointSite *site = getBreakpointSite(pc)) {
|
||||
/* Breakpoints are swept before finalization. */
|
||||
JS_ASSERT(site->firstBreakpoint() == NULL);
|
||||
site->clearTrap(fop->context, NULL, NULL);
|
||||
site->clearTrap(fop, NULL, NULL);
|
||||
JS_ASSERT(getBreakpointSite(pc) == NULL);
|
||||
}
|
||||
}
|
||||
@ -1685,16 +1685,15 @@ JSScript::ensureHasDebug(JSContext *cx)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
JSScript::recompileForStepMode(JSContext *cx)
|
||||
void
|
||||
JSScript::recompileForStepMode(FreeOp *fop)
|
||||
{
|
||||
#ifdef JS_METHODJIT
|
||||
if (jitNormal || jitCtor) {
|
||||
mjit::Recompiler::clearStackReferences(cx, this);
|
||||
mjit::ReleaseScriptCode(cx, this);
|
||||
mjit::Recompiler::clearStackReferences(fop, this);
|
||||
mjit::ReleaseScriptCode(fop, this);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1707,10 +1706,7 @@ JSScript::tryNewStepMode(JSContext *cx, uint32_t newValue)
|
||||
|
||||
if (!prior != !newValue) {
|
||||
/* Step mode has been enabled or disabled. Alert the methodjit. */
|
||||
if (!recompileForStepMode(cx)) {
|
||||
debug->stepMode = prior;
|
||||
return false;
|
||||
}
|
||||
recompileForStepMode(cx->runtime->defaultFreeOp());
|
||||
|
||||
if (!stepModeEnabled() && !debug->numSites) {
|
||||
cx->free_(debug);
|
||||
@ -1775,18 +1771,18 @@ JSScript::getOrCreateBreakpointSite(JSContext *cx, jsbytecode *pc,
|
||||
}
|
||||
|
||||
void
|
||||
JSScript::destroyBreakpointSite(JSRuntime *rt, jsbytecode *pc)
|
||||
JSScript::destroyBreakpointSite(FreeOp *fop, jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(unsigned(pc - code) < length);
|
||||
|
||||
BreakpointSite *&site = debug->breakpoints[pc - code];
|
||||
JS_ASSERT(site);
|
||||
|
||||
rt->delete_(site);
|
||||
fop->delete_(site);
|
||||
site = NULL;
|
||||
|
||||
if (--debug->numSites == 0 && !stepModeEnabled()) {
|
||||
rt->free_(debug);
|
||||
fop->free_(debug);
|
||||
debug = NULL;
|
||||
}
|
||||
}
|
||||
@ -1805,14 +1801,14 @@ JSScript::clearBreakpointsIn(JSContext *cx, js::Debugger *dbg, JSObject *handler
|
||||
for (Breakpoint *bp = site->firstBreakpoint(); bp; bp = nextbp) {
|
||||
nextbp = bp->nextInSite();
|
||||
if ((!dbg || bp->debugger == dbg) && (!handler || bp->getHandler() == handler))
|
||||
bp->destroy(cx);
|
||||
bp->destroy(cx->runtime->defaultFreeOp());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JSScript::clearTraps(JSContext *cx)
|
||||
JSScript::clearTraps(FreeOp *fop)
|
||||
{
|
||||
if (!hasAnyBreakpointsOrStepMode())
|
||||
return;
|
||||
@ -1821,7 +1817,7 @@ JSScript::clearTraps(JSContext *cx)
|
||||
for (jsbytecode *pc = code; pc < end; pc++) {
|
||||
BreakpointSite *site = getBreakpointSite(pc);
|
||||
if (site)
|
||||
site->clearTrap(cx);
|
||||
site->clearTrap(fop);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1917,8 +1913,8 @@ JSScript::applySpeculationFailed(JSContext *cx)
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
if (hasJITCode()) {
|
||||
mjit::Recompiler::clearStackReferences(cx, this);
|
||||
mjit::ReleaseScriptCode(cx, this);
|
||||
mjit::Recompiler::clearStackReferences(cx->runtime->defaultFreeOp(), this);
|
||||
mjit::ReleaseScriptCode(cx->runtime->defaultFreeOp(), this);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -635,7 +635,7 @@ struct JSScript : public js::gc::Cell
|
||||
}
|
||||
|
||||
bool initScriptCounts(JSContext *cx);
|
||||
void destroyScriptCounts(JSContext *cx);
|
||||
void destroyScriptCounts(js::FreeOp *fop);
|
||||
|
||||
jsbytecode *main() {
|
||||
return code + mainOffset;
|
||||
@ -751,10 +751,10 @@ struct JSScript : public js::gc::Cell
|
||||
|
||||
private:
|
||||
/*
|
||||
* Attempt to recompile with or without single-stepping support, as directed
|
||||
* Recompile with or without single-stepping support, as directed
|
||||
* by stepModeEnabled().
|
||||
*/
|
||||
bool recompileForStepMode(JSContext *cx);
|
||||
void recompileForStepMode(js::FreeOp *fop);
|
||||
|
||||
/* Attempt to change this->stepMode to |newValue|. */
|
||||
bool tryNewStepMode(JSContext *cx, uint32_t newValue);
|
||||
@ -774,10 +774,10 @@ struct JSScript : public js::gc::Cell
|
||||
js::BreakpointSite *getOrCreateBreakpointSite(JSContext *cx, jsbytecode *pc,
|
||||
js::GlobalObject *scriptGlobal);
|
||||
|
||||
void destroyBreakpointSite(JSRuntime *rt, jsbytecode *pc);
|
||||
void destroyBreakpointSite(js::FreeOp *fop, jsbytecode *pc);
|
||||
|
||||
void clearBreakpointsIn(JSContext *cx, js::Debugger *dbg, JSObject *handler);
|
||||
void clearTraps(JSContext *cx);
|
||||
void clearTraps(js::FreeOp *fop);
|
||||
|
||||
void markTrapClosures(JSTracer *trc);
|
||||
|
||||
@ -836,11 +836,11 @@ StackDepth(JSScript *script)
|
||||
extern JS_FRIEND_API(void)
|
||||
js_CallNewScriptHook(JSContext *cx, JSScript *script, JSFunction *fun);
|
||||
|
||||
extern void
|
||||
js_CallDestroyScriptHook(JSContext *cx, JSScript *script);
|
||||
|
||||
namespace js {
|
||||
|
||||
extern void
|
||||
CallDestroyScriptHook(FreeOp *fop, JSScript *script);
|
||||
|
||||
extern const char *
|
||||
SaveScriptFilename(JSContext *cx, const char *filename);
|
||||
|
||||
|
@ -926,15 +926,15 @@ JSXMLArray<T>::trim()
|
||||
|
||||
template<class T>
|
||||
void
|
||||
JSXMLArray<T>::finish(JSContext *cx)
|
||||
JSXMLArray<T>::finish(FreeOp *fop)
|
||||
{
|
||||
if (!cx->runtime->gcRunning) {
|
||||
if (!fop->runtime()->gcRunning) {
|
||||
/* We need to clear these to trigger a write barrier. */
|
||||
for (uint32_t i = 0; i < length; i++)
|
||||
vector[i].~HeapPtr<T>();
|
||||
}
|
||||
|
||||
cx->free_(vector);
|
||||
fop->free_(vector);
|
||||
|
||||
while (JSXMLArrayCursor<T> *cursor = cursors)
|
||||
cursor->disconnect();
|
||||
@ -1178,10 +1178,10 @@ void
|
||||
JSXML::finalize(FreeOp *fop)
|
||||
{
|
||||
if (JSXML_HAS_KIDS(this)) {
|
||||
xml_kids.finish(fop->context);
|
||||
xml_kids.finish(fop);
|
||||
if (xml_class == JSXML_CLASS_ELEMENT) {
|
||||
xml_namespaces.finish(fop->context);
|
||||
xml_attrs.finish(fop->context);
|
||||
xml_namespaces.finish(fop);
|
||||
xml_attrs.finish(fop);
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_notme
|
||||
@ -4485,7 +4485,7 @@ PutProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
|
||||
cursor.index = matchIndex;
|
||||
kid = cursor.getCurrent();
|
||||
if (JSXML_HAS_KIDS(kid)) {
|
||||
kid->xml_kids.finish(cx);
|
||||
kid->xml_kids.finish(cx->runtime->defaultFreeOp());
|
||||
kid->xml_kids.init();
|
||||
ok = kid->xml_kids.setCapacity(cx, 1);
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ struct JSXMLArray
|
||||
cursors = NULL;
|
||||
}
|
||||
|
||||
void finish(JSContext *cx);
|
||||
void finish(js::FreeOp *fop);
|
||||
|
||||
bool setCapacity(JSContext *cx, uint32_t capacity);
|
||||
void trim();
|
||||
|
@ -1313,23 +1313,23 @@ JITChunk::~JITChunk()
|
||||
}
|
||||
|
||||
void
|
||||
JITScript::destroy(JSContext *cx)
|
||||
JITScript::destroy(FreeOp *fop)
|
||||
{
|
||||
for (unsigned i = 0; i < nchunks; i++)
|
||||
destroyChunk(cx, i);
|
||||
destroyChunk(fop, i);
|
||||
|
||||
if (shimPool)
|
||||
shimPool->release();
|
||||
}
|
||||
|
||||
void
|
||||
JITScript::destroyChunk(JSContext *cx, unsigned chunkIndex, bool resetUses)
|
||||
JITScript::destroyChunk(FreeOp *fop, unsigned chunkIndex, bool resetUses)
|
||||
{
|
||||
ChunkDescriptor &desc = chunkDescriptor(chunkIndex);
|
||||
|
||||
if (desc.chunk) {
|
||||
Probes::discardMJITCode(cx, this, script, desc.chunk->code.m_code.executableAddress());
|
||||
cx->delete_(desc.chunk);
|
||||
Probes::discardMJITCode(fop, this, script, desc.chunk->code.m_code.executableAddress());
|
||||
fop->delete_(desc.chunk);
|
||||
desc.chunk = NULL;
|
||||
|
||||
CrossChunkEdge *edges = this->edges();
|
||||
@ -1341,7 +1341,7 @@ JITScript::destroyChunk(JSContext *cx, unsigned chunkIndex, bool resetUses)
|
||||
edge.sourceTrampoline = NULL;
|
||||
#endif
|
||||
if (edge.jumpTableEntries) {
|
||||
cx->delete_(edge.jumpTableEntries);
|
||||
fop->delete_(edge.jumpTableEntries);
|
||||
edge.jumpTableEntries = NULL;
|
||||
}
|
||||
} else if (edge.target >= desc.begin && edge.target < desc.end) {
|
||||
@ -1438,7 +1438,7 @@ mjit::JITChunk::sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf)
|
||||
}
|
||||
|
||||
void
|
||||
mjit::ReleaseScriptCode(JSContext *cx, JSScript *script, bool construct)
|
||||
mjit::ReleaseScriptCode(FreeOp *fop, JSScript *script, bool construct)
|
||||
{
|
||||
// NB: The recompiler may call ReleaseScriptCode, in which case it
|
||||
// will get called again when the script is destroyed, so we
|
||||
@ -1448,8 +1448,8 @@ mjit::ReleaseScriptCode(JSContext *cx, JSScript *script, bool construct)
|
||||
void **parity = construct ? &script->jitArityCheckCtor : &script->jitArityCheckNormal;
|
||||
|
||||
if (*pjit) {
|
||||
(*pjit)->destroy(cx);
|
||||
cx->free_(*pjit);
|
||||
(*pjit)->destroy(fop);
|
||||
fop->free_(*pjit);
|
||||
*pjit = NULL;
|
||||
*parity = NULL;
|
||||
}
|
||||
|
@ -866,8 +866,8 @@ struct JITScript
|
||||
|
||||
size_t sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf);
|
||||
|
||||
void destroy(JSContext *cx);
|
||||
void destroyChunk(JSContext *cx, unsigned chunkIndex, bool resetUses = true);
|
||||
void destroy(FreeOp *fop);
|
||||
void destroyChunk(FreeOp *fop, unsigned chunkIndex, bool resetUses = true);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -907,15 +907,15 @@ CanMethodJIT(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
bool construct, CompileRequest request);
|
||||
|
||||
void
|
||||
ReleaseScriptCode(JSContext *cx, JSScript *script, bool construct);
|
||||
ReleaseScriptCode(FreeOp *fop, JSScript *script, bool construct);
|
||||
|
||||
inline void
|
||||
ReleaseScriptCode(JSContext *cx, JSScript *script)
|
||||
ReleaseScriptCode(FreeOp *fop, JSScript *script)
|
||||
{
|
||||
if (script->jitCtor)
|
||||
mjit::ReleaseScriptCode(cx, script, true);
|
||||
mjit::ReleaseScriptCode(fop, script, true);
|
||||
if (script->jitNormal)
|
||||
mjit::ReleaseScriptCode(cx, script, false);
|
||||
mjit::ReleaseScriptCode(fop, script, false);
|
||||
}
|
||||
|
||||
// Expand all stack frames inlined by the JIT within a compartment.
|
||||
|
@ -401,14 +401,15 @@ ClearAllFrames(JSCompartment *compartment)
|
||||
* redirect that entryncode to the interpoline.
|
||||
*/
|
||||
void
|
||||
Recompiler::clearStackReferences(JSContext *cx, JSScript *script)
|
||||
Recompiler::clearStackReferences(FreeOp *fop, JSScript *script)
|
||||
{
|
||||
JS_ASSERT(script->hasJITCode());
|
||||
|
||||
JaegerSpew(JSpew_Recompile, "recompiling script (file \"%s\") (line \"%d\") (length \"%d\")\n",
|
||||
script->filename, script->lineno, script->length);
|
||||
|
||||
types::AutoEnterTypeInference enter(cx, true);
|
||||
JSCompartment *comp = script->compartment();
|
||||
types::AutoEnterTypeInference enter(fop, comp);
|
||||
|
||||
/*
|
||||
* The strategy for this goes as follows:
|
||||
@ -422,7 +423,7 @@ Recompiler::clearStackReferences(JSContext *cx, JSScript *script)
|
||||
|
||||
// Find all JIT'd stack frames to account for return addresses that will
|
||||
// need to be patched after recompilation.
|
||||
for (VMFrame *f = script->compartment()->jaegerCompartment()->activeFrame();
|
||||
for (VMFrame *f = comp->jaegerCompartment()->activeFrame();
|
||||
f != NULL;
|
||||
f = f->previous) {
|
||||
|
||||
@ -450,18 +451,18 @@ Recompiler::clearStackReferences(JSContext *cx, JSScript *script)
|
||||
next = fp;
|
||||
}
|
||||
|
||||
patchFrame(cx->compartment, f, script);
|
||||
patchFrame(comp, f, script);
|
||||
}
|
||||
|
||||
cx->compartment->types.recompilations++;
|
||||
comp->types.recompilations++;
|
||||
}
|
||||
|
||||
void
|
||||
Recompiler::clearStackReferencesAndChunk(JSContext *cx, JSScript *script,
|
||||
Recompiler::clearStackReferencesAndChunk(FreeOp *fop, JSScript *script,
|
||||
JITScript *jit, size_t chunkIndex,
|
||||
bool resetUses)
|
||||
{
|
||||
Recompiler::clearStackReferences(cx, script);
|
||||
Recompiler::clearStackReferences(fop, script);
|
||||
|
||||
bool releaseChunk = true;
|
||||
if (jit->nchunks > 1) {
|
||||
@ -469,7 +470,7 @@ Recompiler::clearStackReferencesAndChunk(JSContext *cx, JSScript *script,
|
||||
// we need to make sure all JIT code for the script is purged, as
|
||||
// otherwise we will have orphaned the native stub but pointers to it
|
||||
// still exist in the containing chunk.
|
||||
for (VMFrame *f = cx->compartment->jaegerCompartment()->activeFrame();
|
||||
for (VMFrame *f = script->compartment()->jaegerCompartment()->activeFrame();
|
||||
f != NULL;
|
||||
f = f->previous) {
|
||||
if (f->fp()->script() == script) {
|
||||
@ -477,7 +478,7 @@ Recompiler::clearStackReferencesAndChunk(JSContext *cx, JSScript *script,
|
||||
f->stubRejoin != REJOIN_NATIVE_LOWERED &&
|
||||
f->stubRejoin != REJOIN_NATIVE_GETTER);
|
||||
if (f->stubRejoin == REJOIN_NATIVE_PATCHED) {
|
||||
mjit::ReleaseScriptCode(cx, script);
|
||||
mjit::ReleaseScriptCode(fop, script);
|
||||
releaseChunk = false;
|
||||
break;
|
||||
}
|
||||
@ -486,7 +487,7 @@ Recompiler::clearStackReferencesAndChunk(JSContext *cx, JSScript *script,
|
||||
}
|
||||
|
||||
if (releaseChunk)
|
||||
jit->destroyChunk(cx, chunkIndex, resetUses);
|
||||
jit->destroyChunk(fop, chunkIndex, resetUses);
|
||||
}
|
||||
|
||||
} /* namespace mjit */
|
||||
|
@ -68,12 +68,12 @@ public:
|
||||
// Clear all uses of compiled code for script on the stack. This must be
|
||||
// followed by destroying all JIT code for the script.
|
||||
static void
|
||||
clearStackReferences(JSContext *cx, JSScript *script);
|
||||
clearStackReferences(FreeOp *fop, JSScript *script);
|
||||
|
||||
// Clear all uses of compiled code for script on the stack, along with
|
||||
// the specified compiled chunk.
|
||||
static void
|
||||
clearStackReferencesAndChunk(JSContext *cx, JSScript *script,
|
||||
clearStackReferencesAndChunk(FreeOp *fop, JSScript *script,
|
||||
JITScript *jit, size_t chunkIndex,
|
||||
bool resetUses = true);
|
||||
|
||||
|
@ -818,8 +818,8 @@ void JS_FASTCALL
|
||||
stubs::RecompileForInline(VMFrame &f)
|
||||
{
|
||||
ExpandInlineFrames(f.cx->compartment);
|
||||
Recompiler::clearStackReferencesAndChunk(f.cx, f.script(), f.jit(), f.chunkIndex(),
|
||||
/* resetUses = */ false);
|
||||
Recompiler::clearStackReferencesAndChunk(f.cx->runtime->defaultFreeOp(), f.script(), f.jit(),
|
||||
f.chunkIndex(), /* resetUses = */ false);
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
@ -1670,8 +1670,8 @@ stubs::InvariantFailure(VMFrame &f, void *rval)
|
||||
|
||||
ExpandInlineFrames(f.cx->compartment);
|
||||
|
||||
mjit::Recompiler::clearStackReferences(f.cx, script);
|
||||
mjit::ReleaseScriptCode(f.cx, script);
|
||||
mjit::Recompiler::clearStackReferences(f.cx->runtime->defaultFreeOp(), script);
|
||||
mjit::ReleaseScriptCode(f.cx->runtime->defaultFreeOp(), script);
|
||||
|
||||
/* Return the same value (if any) as the call triggering the invariant failure. */
|
||||
return rval;
|
||||
|
@ -283,58 +283,45 @@ ScriptGlobal(JSContext *cx, JSScript *script, GlobalObject *scriptGlobal)
|
||||
JS_NOT_REACHED("ScriptGlobal: live non-held script not on stack");
|
||||
}
|
||||
|
||||
bool
|
||||
BreakpointSite::recompile(JSContext *cx, bool forTrap)
|
||||
void
|
||||
BreakpointSite::recompile(FreeOp *fop)
|
||||
{
|
||||
#ifdef JS_METHODJIT
|
||||
if (script->hasJITCode()) {
|
||||
Maybe<AutoCompartment> ac;
|
||||
if (!forTrap) {
|
||||
ac.construct(cx, ScriptGlobal(cx, script, scriptGlobal));
|
||||
if (!ac.ref().enter())
|
||||
return false;
|
||||
}
|
||||
mjit::Recompiler::clearStackReferences(cx, script);
|
||||
mjit::ReleaseScriptCode(cx, script);
|
||||
mjit::Recompiler::clearStackReferences(fop, script);
|
||||
mjit::ReleaseScriptCode(fop, script);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BreakpointSite::inc(JSContext *cx)
|
||||
{
|
||||
if (enabledCount == 0 && !trapHandler) {
|
||||
if (!recompile(cx, false))
|
||||
return false;
|
||||
}
|
||||
enabledCount++;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
BreakpointSite::dec(JSContext *cx)
|
||||
BreakpointSite::inc(FreeOp *fop)
|
||||
{
|
||||
if (enabledCount == 0 && !trapHandler)
|
||||
recompile(fop);
|
||||
enabledCount++;
|
||||
}
|
||||
|
||||
void
|
||||
BreakpointSite::dec(FreeOp *fop)
|
||||
{
|
||||
JS_ASSERT(enabledCount > 0);
|
||||
enabledCount--;
|
||||
if (enabledCount == 0 && !trapHandler)
|
||||
recompile(cx, false); /* ignore failure */
|
||||
}
|
||||
|
||||
bool
|
||||
BreakpointSite::setTrap(JSContext *cx, JSTrapHandler handler, const Value &closure)
|
||||
{
|
||||
if (enabledCount == 0) {
|
||||
if (!recompile(cx, true))
|
||||
return false;
|
||||
}
|
||||
trapHandler = handler;
|
||||
trapClosure = closure;
|
||||
return true;
|
||||
recompile(fop);
|
||||
}
|
||||
|
||||
void
|
||||
BreakpointSite::clearTrap(JSContext *cx, JSTrapHandler *handlerp, Value *closurep)
|
||||
BreakpointSite::setTrap(FreeOp *fop, JSTrapHandler handler, const Value &closure)
|
||||
{
|
||||
if (enabledCount == 0)
|
||||
recompile(fop);
|
||||
trapHandler = handler;
|
||||
trapClosure = closure;
|
||||
}
|
||||
|
||||
void
|
||||
BreakpointSite::clearTrap(FreeOp *fop, JSTrapHandler *handlerp, Value *closurep)
|
||||
{
|
||||
if (handlerp)
|
||||
*handlerp = trapHandler;
|
||||
@ -344,19 +331,19 @@ BreakpointSite::clearTrap(JSContext *cx, JSTrapHandler *handlerp, Value *closure
|
||||
trapHandler = NULL;
|
||||
trapClosure = UndefinedValue();
|
||||
if (enabledCount == 0) {
|
||||
if (!cx->runtime->gcRunning) {
|
||||
if (!fop->runtime()->gcRunning) {
|
||||
/* If the GC is running then the script is being destroyed. */
|
||||
recompile(cx, true); /* ignore failure */
|
||||
recompile(fop);
|
||||
}
|
||||
destroyIfEmpty(cx->runtime);
|
||||
destroyIfEmpty(fop);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BreakpointSite::destroyIfEmpty(JSRuntime *rt)
|
||||
BreakpointSite::destroyIfEmpty(FreeOp *fop)
|
||||
{
|
||||
if (JS_CLIST_IS_EMPTY(&breakpoints) && !trapHandler)
|
||||
script->destroyBreakpointSite(rt, pc);
|
||||
script->destroyBreakpointSite(fop, pc);
|
||||
}
|
||||
|
||||
Breakpoint *
|
||||
@ -396,15 +383,14 @@ Breakpoint::fromSiteLinks(JSCList *links)
|
||||
}
|
||||
|
||||
void
|
||||
Breakpoint::destroy(JSContext *cx)
|
||||
Breakpoint::destroy(FreeOp *fop)
|
||||
{
|
||||
if (debugger->enabled)
|
||||
site->dec(cx);
|
||||
site->dec(fop);
|
||||
JS_REMOVE_LINK(&debuggerLinks);
|
||||
JS_REMOVE_LINK(&siteLinks);
|
||||
JSRuntime *rt = cx->runtime;
|
||||
site->destroyIfEmpty(rt);
|
||||
rt->delete_(this);
|
||||
site->destroyIfEmpty(fop);
|
||||
fop->delete_(this);
|
||||
}
|
||||
|
||||
Breakpoint *
|
||||
@ -1476,7 +1462,7 @@ Debugger::sweepAll(FreeOp *fop)
|
||||
* objects, this must be done before finalize time.
|
||||
*/
|
||||
for (GlobalObjectSet::Enum e(dbg->debuggees); !e.empty(); e.popFront())
|
||||
dbg->removeDebuggeeGlobal(fop->context, e.front(), NULL, &e);
|
||||
dbg->removeDebuggeeGlobal(fop, e.front(), NULL, &e);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1487,19 +1473,19 @@ Debugger::sweepAll(FreeOp *fop)
|
||||
for (GlobalObjectSet::Enum e(debuggees); !e.empty(); e.popFront()) {
|
||||
GlobalObject *global = e.front();
|
||||
if (IsAboutToBeFinalized(global))
|
||||
detachAllDebuggersFromGlobal(fop->context, global, &e);
|
||||
detachAllDebuggersFromGlobal(fop, global, &e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Debugger::detachAllDebuggersFromGlobal(JSContext *cx, GlobalObject *global,
|
||||
Debugger::detachAllDebuggersFromGlobal(FreeOp *fop, GlobalObject *global,
|
||||
GlobalObjectSet::Enum *compartmentEnum)
|
||||
{
|
||||
const GlobalObject::DebuggerVector *debuggers = global->getDebuggers();
|
||||
JS_ASSERT(!debuggers->empty());
|
||||
while (!debuggers->empty())
|
||||
debuggers->back()->removeDebuggeeGlobal(cx, global, compartmentEnum, NULL);
|
||||
debuggers->back()->removeDebuggeeGlobal(fop, global, compartmentEnum, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1575,23 +1561,10 @@ Debugger::setEnabled(JSContext *cx, unsigned argc, Value *vp)
|
||||
|
||||
if (enabled != dbg->enabled) {
|
||||
for (Breakpoint *bp = dbg->firstBreakpoint(); bp; bp = bp->nextInDebugger()) {
|
||||
if (enabled) {
|
||||
if (!bp->site->inc(cx)) {
|
||||
/*
|
||||
* Roll back the changes on error to keep the
|
||||
* BreakpointSite::enabledCount counters correct.
|
||||
*/
|
||||
for (Breakpoint *bp2 = dbg->firstBreakpoint();
|
||||
bp2 != bp;
|
||||
bp2 = bp2->nextInDebugger())
|
||||
{
|
||||
bp->site->dec(cx);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
bp->site->dec(cx);
|
||||
}
|
||||
if (enabled)
|
||||
bp->site->inc(cx->runtime->defaultFreeOp());
|
||||
else
|
||||
bp->site->dec(cx->runtime->defaultFreeOp());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1756,7 +1729,7 @@ Debugger::removeDebuggee(JSContext *cx, unsigned argc, Value *vp)
|
||||
return false;
|
||||
GlobalObject *global = &referent->global();
|
||||
if (dbg->debuggees.has(global))
|
||||
dbg->removeDebuggeeGlobal(cx, global, NULL, NULL);
|
||||
dbg->removeDebuggeeGlobal(cx->runtime->defaultFreeOp(), global, NULL, NULL);
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
@ -1946,7 +1919,7 @@ Debugger::addDebuggeeGlobal(JSContext *cx, GlobalObject *global)
|
||||
}
|
||||
|
||||
void
|
||||
Debugger::removeDebuggeeGlobal(JSContext *cx, GlobalObject *global,
|
||||
Debugger::removeDebuggeeGlobal(FreeOp *fop, GlobalObject *global,
|
||||
GlobalObjectSet::Enum *compartmentEnum,
|
||||
GlobalObjectSet::Enum *debugEnum)
|
||||
{
|
||||
@ -1992,7 +1965,7 @@ Debugger::removeDebuggeeGlobal(JSContext *cx, GlobalObject *global,
|
||||
*/
|
||||
v->erase(p);
|
||||
if (v->empty())
|
||||
global->compartment()->removeDebuggee(cx, global, compartmentEnum);
|
||||
global->compartment()->removeDebuggee(fop, global, compartmentEnum);
|
||||
if (debugEnum)
|
||||
debugEnum->removeFront();
|
||||
else
|
||||
@ -2608,14 +2581,13 @@ DebuggerScript_setBreakpoint(JSContext *cx, unsigned argc, Value *vp)
|
||||
BreakpointSite *site = script->getOrCreateBreakpointSite(cx, pc, scriptGlobal);
|
||||
if (!site)
|
||||
return false;
|
||||
if (site->inc(cx)) {
|
||||
if (cx->runtime->new_<Breakpoint>(dbg, site, handler)) {
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
site->dec(cx);
|
||||
site->inc(cx->runtime->defaultFreeOp());
|
||||
if (cx->runtime->new_<Breakpoint>(dbg, site, handler)) {
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
site->destroyIfEmpty(cx->runtime);
|
||||
site->dec(cx->runtime->defaultFreeOp());
|
||||
site->destroyIfEmpty(cx->runtime->defaultFreeOp());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,7 @@ class Debugger {
|
||||
class FrameRange;
|
||||
|
||||
bool addDebuggeeGlobal(JSContext *cx, GlobalObject *obj);
|
||||
void removeDebuggeeGlobal(JSContext *cx, GlobalObject *global,
|
||||
void removeDebuggeeGlobal(FreeOp *fop, GlobalObject *global,
|
||||
GlobalObjectSet::Enum *compartmentEnum,
|
||||
GlobalObjectSet::Enum *debugEnum);
|
||||
|
||||
@ -264,7 +264,7 @@ class Debugger {
|
||||
static void markCrossCompartmentDebuggerObjectReferents(JSTracer *tracer);
|
||||
static bool markAllIteratively(GCMarker *trc);
|
||||
static void sweepAll(FreeOp *fop);
|
||||
static void detachAllDebuggersFromGlobal(JSContext *cx, GlobalObject *global,
|
||||
static void detachAllDebuggersFromGlobal(FreeOp *fop, GlobalObject *global,
|
||||
GlobalObjectSet::Enum *compartmentEnum);
|
||||
|
||||
static inline JSTrapStatus onEnterFrame(JSContext *cx, Value *vp);
|
||||
@ -399,7 +399,7 @@ class BreakpointSite {
|
||||
JSTrapHandler trapHandler; /* jsdbgapi trap state */
|
||||
HeapValue trapClosure;
|
||||
|
||||
bool recompile(JSContext *cx, bool forTrap);
|
||||
void recompile(FreeOp *fop);
|
||||
|
||||
public:
|
||||
BreakpointSite(JSScript *script, jsbytecode *pc);
|
||||
@ -408,11 +408,11 @@ class BreakpointSite {
|
||||
bool hasTrap() const { return !!trapHandler; }
|
||||
GlobalObject *getScriptGlobal() const { return scriptGlobal; }
|
||||
|
||||
bool inc(JSContext *cx);
|
||||
void dec(JSContext *cx);
|
||||
bool setTrap(JSContext *cx, JSTrapHandler handler, const Value &closure);
|
||||
void clearTrap(JSContext *cx, JSTrapHandler *handlerp = NULL, Value *closurep = NULL);
|
||||
void destroyIfEmpty(JSRuntime *rt);
|
||||
void inc(FreeOp *fop);
|
||||
void dec(FreeOp *fop);
|
||||
void setTrap(FreeOp *fop, JSTrapHandler handler, const Value &closure);
|
||||
void clearTrap(FreeOp *fop, JSTrapHandler *handlerp = NULL, Value *closurep = NULL);
|
||||
void destroyIfEmpty(FreeOp *fop);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -449,7 +449,7 @@ class Breakpoint {
|
||||
static Breakpoint *fromDebuggerLinks(JSCList *links);
|
||||
static Breakpoint *fromSiteLinks(JSCList *links);
|
||||
Breakpoint(Debugger *debugger, BreakpointSite *site, JSObject *handler);
|
||||
void destroy(JSContext *cx);
|
||||
void destroy(FreeOp *fop);
|
||||
Breakpoint *nextInDebugger();
|
||||
Breakpoint *nextInSite();
|
||||
const HeapPtrObject &getHandler() const { return handler; }
|
||||
|
@ -370,8 +370,8 @@ GlobalObject::clear(JSContext *cx)
|
||||
for (gc::CellIter i(cx->compartment, gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
if (script->compileAndGo && script->hasJITCode() && script->hasClearedGlobal()) {
|
||||
mjit::Recompiler::clearStackReferences(cx, script);
|
||||
mjit::ReleaseScriptCode(cx, script);
|
||||
mjit::Recompiler::clearStackReferences(cx->runtime->defaultFreeOp(), script);
|
||||
mjit::ReleaseScriptCode(cx->runtime->defaultFreeOp(), script);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -507,7 +507,7 @@ GlobalObject::addDebugger(JSContext *cx, Debugger *dbg)
|
||||
if (debuggers->empty() && !compartment()->addDebuggee(cx, this))
|
||||
return false;
|
||||
if (!debuggers->append(dbg)) {
|
||||
compartment()->removeDebuggee(cx, this);
|
||||
compartment()->removeDebuggee(cx->runtime->defaultFreeOp(), this);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -251,19 +251,17 @@ xpc::CompartmentPrivate::~CompartmentPrivate()
|
||||
MOZ_COUNT_DTOR(xpc::CompartmentPrivate);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
CompartmentCallback(JSContext *cx, JSCompartment *compartment, unsigned op)
|
||||
static void
|
||||
CompartmentDestroyedCallback(JSFreeOp *fop, JSCompartment *compartment)
|
||||
{
|
||||
JS_ASSERT(op == JSCOMPARTMENT_DESTROY);
|
||||
|
||||
XPCJSRuntime* self = nsXPConnect::GetRuntimeInstance();
|
||||
if (!self)
|
||||
return true;
|
||||
return;
|
||||
|
||||
nsAutoPtr<xpc::CompartmentPrivate>
|
||||
priv(static_cast<xpc::CompartmentPrivate*>(JS_GetCompartmentPrivate(compartment)));
|
||||
if (!priv)
|
||||
return true;
|
||||
return;
|
||||
|
||||
JS_SetCompartmentPrivate(compartment, nsnull);
|
||||
|
||||
@ -275,8 +273,6 @@ CompartmentCallback(JSContext *cx, JSCompartment *compartment, unsigned op)
|
||||
NS_ASSERTION(current == compartment, "compartment mismatch");
|
||||
#endif
|
||||
map.Remove(key);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct ObjectHolder : public JSDHashEntryHdr
|
||||
@ -2001,7 +1997,7 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
|
||||
JS_SetNativeStackQuota(mJSRuntime, 128 * sizeof(size_t) * 1024);
|
||||
#endif
|
||||
JS_SetContextCallback(mJSRuntime, ContextCallback);
|
||||
JS_SetCompartmentCallback(mJSRuntime, CompartmentCallback);
|
||||
JS_SetDestroyCompartmentCallback(mJSRuntime, CompartmentDestroyedCallback);
|
||||
JS_SetGCCallback(mJSRuntime, GCCallback);
|
||||
JS_SetFinalizeCallback(mJSRuntime, FinalizeCallback);
|
||||
JS_SetExtraGCRootsTracer(mJSRuntime, TraceBlackJS, this);
|
||||
|
Loading…
Reference in New Issue
Block a user