mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-23 10:15:41 +00:00
Bug 772820 - Disallow GCs during script analysis or compilation, r=billm.
This commit is contained in:
parent
7563370004
commit
bfc1e7cc66
@ -1145,7 +1145,7 @@ ParallelArrayObject::create(JSContext *cx, HandleObject buffer, uint32_t offset,
|
||||
|
||||
// Propagate element types.
|
||||
if (cx->typeInferenceEnabled()) {
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
TypeObject *bufferType = buffer->getType(cx);
|
||||
TypeObject *resultType = result->getType(cx);
|
||||
if (!bufferType->unknownProperties() && !resultType->unknownProperties()) {
|
||||
|
@ -668,6 +668,8 @@ js::gc::MarkRuntime(JSTracer *trc, bool useSavedRoots)
|
||||
JSRuntime *rt = trc->runtime;
|
||||
JS_ASSERT(trc->callback != GCMarker::GrayCallback);
|
||||
|
||||
JS_ASSERT(!rt->mainThread.suppressGC);
|
||||
|
||||
if (IS_GC_MARKING_TRACER(trc)) {
|
||||
for (CompartmentsIter c(rt); !c.done(); c.next()) {
|
||||
if (!c->isCollecting())
|
||||
@ -730,7 +732,7 @@ js::gc::MarkRuntime(JSTracer *trc, bool useSavedRoots)
|
||||
if (IS_GC_MARKING_TRACER(trc) && !c->isCollecting())
|
||||
continue;
|
||||
|
||||
if (IS_GC_MARKING_TRACER(trc) && (c->activeAnalysis || c->isPreservingCode())) {
|
||||
if (IS_GC_MARKING_TRACER(trc) && c->isPreservingCode()) {
|
||||
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_MARK_TYPES);
|
||||
c->markTypes(trc);
|
||||
}
|
||||
|
@ -806,6 +806,9 @@ MaybeVerifyPreBarriers(JSRuntime *rt, bool always)
|
||||
if (rt->gcZeal() != ZealVerifierPreValue)
|
||||
return;
|
||||
|
||||
if (rt->mainThread.suppressGC)
|
||||
return;
|
||||
|
||||
if (VerifyPreTracer *trc = (VerifyPreTracer *)rt->gcVerifyPreData) {
|
||||
if (++trc->count < rt->gcZealFrequency && !always)
|
||||
return;
|
||||
@ -821,6 +824,9 @@ MaybeVerifyPostBarriers(JSRuntime *rt, bool always)
|
||||
if (rt->gcZeal() != ZealVerifierPostValue)
|
||||
return;
|
||||
|
||||
if (rt->mainThread.suppressGC)
|
||||
return;
|
||||
|
||||
if (VerifyPostTracer *trc = (VerifyPostTracer *)rt->gcVerifyPostData) {
|
||||
if (++trc->count < rt->gcZealFrequency && !always)
|
||||
return;
|
||||
|
@ -456,7 +456,7 @@ ReflowArgTypes(JSContext *cx)
|
||||
unsigned nargs = fp->fun()->nargs;
|
||||
RootedScript script(cx, fp->script());
|
||||
|
||||
types::AutoEnterTypeInference enter(cx);
|
||||
types::AutoEnterAnalysis enter(cx);
|
||||
|
||||
if (!fp->isConstructing())
|
||||
types::TypeScript::SetThis(cx, script, fp->thisValue());
|
||||
@ -486,7 +486,7 @@ ion::ReflowTypeInfo(uint32_t bailoutResult)
|
||||
IonSpew(IonSpew_Bailouts, "reflowing type info at %s:%d pcoff %d", script->filename,
|
||||
script->lineno, pc - script->code);
|
||||
|
||||
types::AutoEnterTypeInference enter(cx);
|
||||
types::AutoEnterAnalysis enter(cx);
|
||||
if (bailoutResult == BAILOUT_RETURN_TYPE_BARRIER)
|
||||
script->analysis()->breakTypeBarriers(cx, pc - script->code, false);
|
||||
else
|
||||
|
@ -1080,7 +1080,7 @@ AttachFinishedCompilations(JSContext *cx)
|
||||
// previously, though any GC activity would discard the builder.
|
||||
codegen->masm.constructRoot(cx);
|
||||
|
||||
types::AutoEnterTypeInference enterTypes(cx);
|
||||
types::AutoEnterAnalysis enterTypes(cx);
|
||||
|
||||
ExecutionMode executionMode = builder->info().executionMode();
|
||||
types::AutoEnterCompilation enterCompiler(cx, CompilerOutputKind(executionMode));
|
||||
@ -1149,7 +1149,7 @@ IonCompile(JSContext *cx, HandleScript script, HandleFunction fun, jsbytecode *o
|
||||
if (!info)
|
||||
return AbortReason_Alloc;
|
||||
|
||||
types::AutoEnterTypeInference enter(cx, true);
|
||||
types::AutoEnterAnalysis enter(cx);
|
||||
TypeInferenceOracle oracle;
|
||||
|
||||
if (!oracle.init(cx, script))
|
||||
|
@ -2015,7 +2015,7 @@ CrossScriptSSA::foldValue(const CrossSSAValue &cv)
|
||||
void
|
||||
ScriptAnalysis::printSSA(JSContext *cx)
|
||||
{
|
||||
AutoEnterAnalysis enter(cx);
|
||||
types::AutoEnterAnalysis enter(cx);
|
||||
|
||||
printf("\n");
|
||||
|
||||
|
@ -1204,39 +1204,6 @@ class ScriptAnalysis
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Protect analysis structures from GC while they are being used. */
|
||||
class AutoEnterAnalysis
|
||||
{
|
||||
JSCompartment *compartment;
|
||||
bool oldActiveAnalysis;
|
||||
bool left;
|
||||
|
||||
void construct(JSCompartment *compartment)
|
||||
{
|
||||
this->compartment = compartment;
|
||||
oldActiveAnalysis = compartment->activeAnalysis;
|
||||
compartment->activeAnalysis = true;
|
||||
left = false;
|
||||
}
|
||||
|
||||
public:
|
||||
AutoEnterAnalysis(JSContext *cx) { construct(cx->compartment); }
|
||||
AutoEnterAnalysis(JSCompartment *compartment) { construct(compartment); }
|
||||
|
||||
void leave()
|
||||
{
|
||||
if (!left) {
|
||||
left = true;
|
||||
compartment->activeAnalysis = oldActiveAnalysis;
|
||||
}
|
||||
}
|
||||
|
||||
~AutoEnterAnalysis()
|
||||
{
|
||||
leave();
|
||||
}
|
||||
};
|
||||
|
||||
/* SSA value as used by CrossScriptSSA, identifies the frame it came from. */
|
||||
struct CrossSSAValue
|
||||
{
|
||||
|
@ -875,7 +875,7 @@ static inline bool
|
||||
InitArrayTypes(JSContext *cx, TypeObject *type, const Value *vector, unsigned count)
|
||||
{
|
||||
if (cx->typeInferenceEnabled() && !type->unknownProperties()) {
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
TypeSet *types = type->getProperty(cx, JSID_VOID, true);
|
||||
if (!types)
|
||||
|
@ -121,7 +121,7 @@ JSCompartment::init(JSContext *cx)
|
||||
if (cx)
|
||||
cx->runtime->dateTimeInfo.updateTimeZoneAdjustment();
|
||||
|
||||
activeAnalysis = activeInference = false;
|
||||
activeAnalysis = false;
|
||||
types.init(cx);
|
||||
|
||||
if (!crossCompartmentWrappers.init())
|
||||
@ -564,7 +564,8 @@ JSCompartment::markTypes(JSTracer *trc)
|
||||
* compartment. These can be referred to directly by type sets, which we
|
||||
* cannot modify while code which depends on these type sets is active.
|
||||
*/
|
||||
JS_ASSERT(activeAnalysis || isPreservingCode());
|
||||
JS_ASSERT(!activeAnalysis);
|
||||
JS_ASSERT(isPreservingCode());
|
||||
|
||||
for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
@ -640,9 +641,11 @@ JSCompartment::isDiscardingJitCode(JSTracer *trc)
|
||||
void
|
||||
JSCompartment::sweep(FreeOp *fop, bool releaseTypes)
|
||||
{
|
||||
JS_ASSERT(!activeAnalysis);
|
||||
|
||||
{
|
||||
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_DISCARD_CODE);
|
||||
discardJitCode(fop, !activeAnalysis && !gcPreserveCode);
|
||||
discardJitCode(fop, !gcPreserveCode);
|
||||
}
|
||||
|
||||
/* This function includes itself in PHASE_SWEEP_TABLES. */
|
||||
@ -682,7 +685,7 @@ JSCompartment::sweep(FreeOp *fop, bool releaseTypes)
|
||||
WeakMapBase::sweepCompartment(this);
|
||||
}
|
||||
|
||||
if (!activeAnalysis && !gcPreserveCode) {
|
||||
if (!gcPreserveCode) {
|
||||
JS_ASSERT(!types.constrainedOutputs);
|
||||
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_DISCARD_ANALYSIS);
|
||||
|
||||
|
@ -293,7 +293,6 @@ struct JSCompartment : private JS::shadow::Compartment, public js::gc::GraphNode
|
||||
js::LifoAlloc typeLifoAlloc;
|
||||
|
||||
bool activeAnalysis;
|
||||
bool activeInference;
|
||||
|
||||
/* Type information about the scripts and objects in this compartment. */
|
||||
js::types::TypeCompartment types;
|
||||
|
@ -4151,14 +4151,11 @@ IncrementalCollectSlice(JSRuntime *rt,
|
||||
IncrementalSafety
|
||||
gc::IsIncrementalGCSafe(JSRuntime *rt)
|
||||
{
|
||||
JS_ASSERT(!rt->mainThread.suppressGC);
|
||||
|
||||
if (rt->gcKeepAtoms)
|
||||
return IncrementalSafety::Unsafe("gcKeepAtoms set");
|
||||
|
||||
for (CompartmentsIter c(rt); !c.done(); c.next()) {
|
||||
if (c->activeAnalysis)
|
||||
return IncrementalSafety::Unsafe("activeAnalysis set");
|
||||
}
|
||||
|
||||
if (!rt->gcIncrementalEnabled)
|
||||
return IncrementalSafety::Unsafe("incremental permanently disabled");
|
||||
|
||||
@ -4520,6 +4517,10 @@ gc::RunDebugGC(JSContext *cx)
|
||||
{
|
||||
#ifdef JS_GC_ZEAL
|
||||
JSRuntime *rt = cx->runtime;
|
||||
|
||||
if (rt->mainThread.suppressGC)
|
||||
return;
|
||||
|
||||
PrepareForDebugGC(cx->runtime);
|
||||
|
||||
int type = rt->gcZeal();
|
||||
@ -4557,8 +4558,7 @@ gc::RunDebugGC(JSContext *cx)
|
||||
rt->gcIncrementalLimit = rt->gcZealFrequency / 2;
|
||||
}
|
||||
} else if (type == ZealPurgeAnalysisValue) {
|
||||
if (!cx->compartment->activeAnalysis)
|
||||
cx->compartment->types.maybePurgeAnalysis(cx, /* force = */ true);
|
||||
cx->compartment->types.maybePurgeAnalysis(cx, /* force = */ true);
|
||||
} else {
|
||||
Collect(rt, false, SliceBudget::Unlimited, GC_NORMAL, gcreason::DEBUG_GC);
|
||||
}
|
||||
@ -4592,17 +4592,6 @@ void PreventGCDuringInteractiveDebug()
|
||||
|
||||
#endif
|
||||
|
||||
gc::AutoSuppressGC::AutoSuppressGC(JSContext *cx)
|
||||
: suppressGC_(cx->runtime->mainThread.suppressGC)
|
||||
{
|
||||
suppressGC_++;
|
||||
}
|
||||
|
||||
gc::AutoSuppressGC::~AutoSuppressGC()
|
||||
{
|
||||
suppressGC_--;
|
||||
}
|
||||
|
||||
void
|
||||
js::ReleaseAllJITCode(FreeOp *fop)
|
||||
{
|
||||
|
@ -1199,21 +1199,6 @@ MaybeVerifyBarriers(JSContext *cx, bool always = false)
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Instances of this class set the |JSRuntime::suppressGC| flag for the duration
|
||||
* that they are live. Use of this class is highly discouraged. Please carefully
|
||||
* read the comment in jscntxt.h above |suppressGC| and take all appropriate
|
||||
* precautions before instantiating this class.
|
||||
*/
|
||||
class AutoSuppressGC
|
||||
{
|
||||
int32_t &suppressGC_;
|
||||
|
||||
public:
|
||||
AutoSuppressGC(JSContext *cx);
|
||||
~AutoSuppressGC();
|
||||
};
|
||||
|
||||
} /* namespace gc */
|
||||
|
||||
void
|
||||
|
@ -546,6 +546,35 @@ TryNewGCThing(JSContext *cx, js::gc::AllocKind kind, size_t thingSize)
|
||||
return t;
|
||||
}
|
||||
|
||||
/*
|
||||
* Instances of this class set the |JSRuntime::suppressGC| flag for the duration
|
||||
* that they are live. Use of this class is highly discouraged. Please carefully
|
||||
* read the comment in jscntxt.h above |suppressGC| and take all appropriate
|
||||
* precautions before instantiating this class.
|
||||
*/
|
||||
class AutoSuppressGC
|
||||
{
|
||||
int32_t &suppressGC_;
|
||||
|
||||
public:
|
||||
AutoSuppressGC(JSContext *cx)
|
||||
: suppressGC_(cx->runtime->mainThread.suppressGC)
|
||||
{
|
||||
suppressGC_++;
|
||||
}
|
||||
|
||||
AutoSuppressGC(JSCompartment *comp)
|
||||
: suppressGC_(comp->rt->mainThread.suppressGC)
|
||||
{
|
||||
suppressGC_++;
|
||||
}
|
||||
|
||||
~AutoSuppressGC()
|
||||
{
|
||||
suppressGC_--;
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace gc */
|
||||
} /* namespace js */
|
||||
|
||||
|
@ -269,7 +269,7 @@ types::TypeHasProperty(JSContext *cx, TypeObject *obj, jsid id, const Value &val
|
||||
|
||||
Type type = GetValueType(cx, value);
|
||||
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
/*
|
||||
* We don't track types for properties inherited from prototypes which
|
||||
@ -375,7 +375,7 @@ TypeSet::add(JSContext *cx, TypeConstraint *constraint, bool callExisting)
|
||||
return;
|
||||
}
|
||||
|
||||
JS_ASSERT(cx->compartment->activeInference);
|
||||
JS_ASSERT(cx->compartment->activeAnalysis);
|
||||
|
||||
InferSpew(ISpewOps, "addConstraint: %sT%p%s %sC%p%s %s",
|
||||
InferSpewColor(this), this, InferSpewColorReset(),
|
||||
@ -442,7 +442,7 @@ TypeSet::print()
|
||||
StackTypeSet *
|
||||
StackTypeSet::make(JSContext *cx, const char *name)
|
||||
{
|
||||
JS_ASSERT(cx->compartment->activeInference);
|
||||
JS_ASSERT(cx->compartment->activeAnalysis);
|
||||
|
||||
StackTypeSet *res = cx->analysisLifoAlloc().new_<StackTypeSet>();
|
||||
if (!res) {
|
||||
@ -2348,7 +2348,7 @@ FindPreviousInnerInitializer(HandleScript script, jsbytecode *initpc)
|
||||
TypeObject *
|
||||
TypeCompartment::addAllocationSiteTypeObject(JSContext *cx, AllocationSiteKey key)
|
||||
{
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
if (!allocationSiteTable) {
|
||||
allocationSiteTable = cx->new_<AllocationSiteTable>();
|
||||
@ -2473,7 +2473,7 @@ types::UseNewTypeForInitializer(JSContext *cx, HandleScript script, jsbytecode *
|
||||
if (key != JSProto_Object && !(key >= JSProto_Int8Array && key <= JSProto_Uint8ClampedArray))
|
||||
return false;
|
||||
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
if (!JSScript::ensureRanAnalysis(cx, script))
|
||||
return false;
|
||||
@ -2572,7 +2572,7 @@ TypeCompartment::setPendingNukeTypes(JSContext *cx)
|
||||
void
|
||||
TypeCompartment::setPendingNukeTypesNoReport()
|
||||
{
|
||||
JS_ASSERT(compartment()->activeInference);
|
||||
JS_ASSERT(compartment()->activeAnalysis);
|
||||
if (!pendingNukeTypes)
|
||||
pendingNukeTypes = true;
|
||||
}
|
||||
@ -2764,7 +2764,7 @@ TypeCompartment::markSetsUnknown(JSContext *cx, TypeObject *target)
|
||||
JS_ASSERT(target->unknownProperties());
|
||||
target->flags |= OBJECT_FLAG_SETS_MARKED_UNKNOWN;
|
||||
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
/*
|
||||
* Mark both persistent and transient type sets which contain obj as having
|
||||
@ -2928,7 +2928,7 @@ TypeCompartment::print(JSContext *cx, bool force)
|
||||
gc::AutoSuppressGC suppressGC(cx);
|
||||
|
||||
JSCompartment *compartment = this->compartment();
|
||||
AutoEnterAnalysis enter(compartment);
|
||||
AutoEnterAnalysis enter(NULL, compartment);
|
||||
|
||||
if (!force && !InferSpewActive(ISpewResult))
|
||||
return;
|
||||
@ -3016,7 +3016,7 @@ struct types::ArrayTableKey
|
||||
void
|
||||
TypeCompartment::fixArrayType(JSContext *cx, HandleObject obj)
|
||||
{
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
if (!arrayTypeTable) {
|
||||
arrayTypeTable = cx->new_<ArrayTypeTable>();
|
||||
@ -3136,7 +3136,7 @@ struct types::ObjectTableEntry
|
||||
void
|
||||
TypeCompartment::fixObjectType(JSContext *cx, HandleObject obj)
|
||||
{
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
if (!objectTypeTable) {
|
||||
objectTypeTable = cx->new_<ObjectTypeTable>();
|
||||
@ -3369,7 +3369,7 @@ TypeObject::addDefiniteProperties(JSContext *cx, HandleObject obj)
|
||||
return true;
|
||||
|
||||
/* Mark all properties of obj as definite properties of this type. */
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
RootedShape shape(cx, obj->lastProperty());
|
||||
while (!shape->isEmptyShape()) {
|
||||
@ -3421,7 +3421,7 @@ InlineAddTypeProperty(JSContext *cx, TypeObject *obj, jsid id, Type type)
|
||||
AssertCanGC();
|
||||
JS_ASSERT(id == MakeTypeId(cx, id));
|
||||
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
TypeSet *types = obj->getProperty(cx, id, true);
|
||||
if (!types || types->hasType(type))
|
||||
@ -3452,7 +3452,7 @@ TypeObject::addPropertyType(JSContext *cx, const char *name, Type type)
|
||||
if (name) {
|
||||
JSAtom *atom = Atomize(cx, name, strlen(name));
|
||||
if (!atom) {
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
cx->compartment->types.setPendingNukeTypes(cx);
|
||||
return;
|
||||
}
|
||||
@ -3470,7 +3470,7 @@ TypeObject::addPropertyType(JSContext *cx, const char *name, const Value &value)
|
||||
void
|
||||
TypeObject::markPropertyConfigured(JSContext *cx, jsid id)
|
||||
{
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
id = MakeTypeId(cx, id);
|
||||
|
||||
@ -3487,7 +3487,7 @@ TypeObject::markStateChange(JSContext *cx)
|
||||
if (unknownProperties())
|
||||
return;
|
||||
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
TypeSet *types = maybeGetProperty(cx, JSID_EMPTY);
|
||||
if (types) {
|
||||
TypeConstraint *constraint = types->constraintList;
|
||||
@ -3504,7 +3504,7 @@ TypeObject::setFlags(JSContext *cx, TypeObjectFlags flags)
|
||||
if ((this->flags & flags) == flags)
|
||||
return;
|
||||
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
if (singleton) {
|
||||
/* Make sure flags are consistent with persistent object state. */
|
||||
@ -3524,9 +3524,9 @@ TypeObject::setFlags(JSContext *cx, TypeObjectFlags flags)
|
||||
void
|
||||
TypeObject::markUnknown(JSContext *cx)
|
||||
{
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
JS_ASSERT(cx->compartment->activeInference);
|
||||
JS_ASSERT(cx->compartment->activeAnalysis);
|
||||
JS_ASSERT(!unknownProperties());
|
||||
|
||||
if (!(flags & OBJECT_FLAG_NEW_SCRIPT_CLEARED))
|
||||
@ -3572,7 +3572,7 @@ TypeObject::clearNewScript(JSContext *cx)
|
||||
if (!newScript)
|
||||
return;
|
||||
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
/*
|
||||
* Any definite properties we added due to analysis of the new script when
|
||||
@ -5144,7 +5144,7 @@ CheckNewScriptProperties(JSContext *cx, HandleTypeObject type, JSFunction *fun)
|
||||
void
|
||||
ScriptAnalysis::printTypes(JSContext *cx)
|
||||
{
|
||||
AutoEnterAnalysis enter(script_->compartment());
|
||||
AutoEnterAnalysis enter(NULL, script_->compartment());
|
||||
TypeCompartment *compartment = &script_->compartment()->types;
|
||||
|
||||
/*
|
||||
@ -5292,7 +5292,7 @@ types::MarkIteratorUnknownSlow(JSContext *cx)
|
||||
if (JSOp(*pc) != JSOP_ITER)
|
||||
return;
|
||||
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
/*
|
||||
* This script is iterating over an actual Iterator or Generator object, or
|
||||
@ -5377,7 +5377,7 @@ void
|
||||
types::TypeDynamicResult(JSContext *cx, HandleScript script, jsbytecode *pc, Type type)
|
||||
{
|
||||
JS_ASSERT(cx->typeInferenceEnabled());
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
/* Directly update associated type sets for applicable bytecodes. */
|
||||
if (js_CodeSpec[*pc].format & JOF_TYPESET) {
|
||||
@ -5482,7 +5482,7 @@ types::TypeMonitorResult(JSContext *cx, HandleScript script, jsbytecode *pc, con
|
||||
if (!(js_CodeSpec[*pc].format & JOF_TYPESET))
|
||||
return;
|
||||
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
if (!JSScript::ensureRanAnalysis(cx, script)) {
|
||||
cx->compartment->types.setPendingNukeTypes(cx);
|
||||
@ -5593,7 +5593,7 @@ JSScript::makeTypes(JSContext *cx)
|
||||
return true;
|
||||
}
|
||||
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
unsigned count = TypeScript::NumTypeSets(this);
|
||||
|
||||
@ -5703,7 +5703,7 @@ JSFunction::setTypeForScriptedFunction(JSContext *cx, HandleFunction fun, bool s
|
||||
/* static */ void
|
||||
TypeScript::CheckBytecode(JSContext *cx, HandleScript script, jsbytecode *pc, const js::Value *sp)
|
||||
{
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
if (js_CodeSpec[*pc].format & JOF_DECOMPOSE)
|
||||
return;
|
||||
@ -5798,7 +5798,7 @@ JSObject::splicePrototype(JSContext *cx, Handle<TaggedProto> proto)
|
||||
|
||||
type->proto = proto.raw();
|
||||
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
if (protoType && protoType->unknownProperties() && !type->unknownProperties()) {
|
||||
type->markUnknown(cx);
|
||||
@ -5847,7 +5847,7 @@ JSObject::makeLazyType(JSContext *cx)
|
||||
return type;
|
||||
}
|
||||
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
/* Fill in the type according to the state of this object. */
|
||||
|
||||
@ -5997,7 +5997,7 @@ JSCompartment::getNewType(JSContext *cx, TaggedProto proto_, JSFunction *fun_, b
|
||||
if (!cx->typeInferenceEnabled())
|
||||
return type;
|
||||
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
/*
|
||||
* Set the special equality flag for types whose prototype also has the
|
||||
@ -6570,7 +6570,7 @@ TypeCompartment::maybePurgeAnalysis(JSContext *cx, bool force)
|
||||
return;
|
||||
}
|
||||
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
/* Reset the analysis pool, making its memory available for reuse. */
|
||||
cx->compartment->analysisLifoAlloc.releaseAll();
|
||||
|
@ -347,28 +347,30 @@ IsInlinableCall(jsbytecode *pc)
|
||||
* and JSScripts won't be collected during GC. Does additional sanity checking
|
||||
* that inference is not reentrant and that recompilations occur properly.
|
||||
*/
|
||||
struct AutoEnterTypeInference
|
||||
struct AutoEnterAnalysis
|
||||
{
|
||||
/* Prevent GC activity in the middle of analysis. */
|
||||
gc::AutoSuppressGC suppressGC;
|
||||
|
||||
FreeOp *freeOp;
|
||||
JSCompartment *compartment;
|
||||
bool oldActiveAnalysis;
|
||||
bool oldActiveInference;
|
||||
|
||||
AutoEnterTypeInference(JSContext *cx, bool compiling = false)
|
||||
AutoEnterAnalysis(JSContext *cx)
|
||||
: suppressGC(cx)
|
||||
{
|
||||
JS_ASSERT_IF(!compiling, cx->compartment->types.inferenceEnabled);
|
||||
init(cx->runtime->defaultFreeOp(), cx->compartment);
|
||||
}
|
||||
|
||||
AutoEnterTypeInference(FreeOp *fop, JSCompartment *comp)
|
||||
AutoEnterAnalysis(FreeOp *fop, JSCompartment *comp)
|
||||
: suppressGC(comp)
|
||||
{
|
||||
init(fop, comp);
|
||||
}
|
||||
|
||||
~AutoEnterTypeInference()
|
||||
~AutoEnterAnalysis()
|
||||
{
|
||||
compartment->activeAnalysis = oldActiveAnalysis;
|
||||
compartment->activeInference = oldActiveInference;
|
||||
|
||||
/*
|
||||
* If there are no more type inference activations on the stack,
|
||||
@ -376,7 +378,7 @@ struct AutoEnterTypeInference
|
||||
* invoking any scripted code while type inference is running.
|
||||
* :TODO: assert this.
|
||||
*/
|
||||
if (!compartment->activeInference) {
|
||||
if (!compartment->activeAnalysis) {
|
||||
TypeCompartment *types = &compartment->types;
|
||||
if (types->pendingNukeTypes)
|
||||
types->nukeTypes(freeOp);
|
||||
@ -390,9 +392,7 @@ struct AutoEnterTypeInference
|
||||
freeOp = fop;
|
||||
compartment = comp;
|
||||
oldActiveAnalysis = compartment->activeAnalysis;
|
||||
oldActiveInference = compartment->activeInference;
|
||||
compartment->activeAnalysis = true;
|
||||
compartment->activeInference = true;
|
||||
}
|
||||
};
|
||||
|
||||
@ -995,7 +995,7 @@ TypeScript::SetThis(JSContext *cx, HandleScript script, Type type)
|
||||
bool analyze = cx->hasRunOption(JSOPTION_METHODJIT_ALWAYS);
|
||||
|
||||
if (!ThisTypes(script)->hasType(type) || analyze) {
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
InferSpew(ISpewOps, "externalType: setThis #%u: %s",
|
||||
script->id(), TypeString(type));
|
||||
@ -1021,7 +1021,7 @@ TypeScript::SetLocal(JSContext *cx, HandleScript script, unsigned local, Type ty
|
||||
JS_ASSERT(script->types);
|
||||
|
||||
if (!LocalTypes(script, local)->hasType(type)) {
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
InferSpew(ISpewOps, "externalType: setLocal #%u %u: %s",
|
||||
script->id(), local, TypeString(type));
|
||||
@ -1046,7 +1046,7 @@ TypeScript::SetArgument(JSContext *cx, HandleScript script, unsigned arg, Type t
|
||||
JS_ASSERT(script->types);
|
||||
|
||||
if (!ArgTypes(script, arg)->hasType(type)) {
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
InferSpew(ISpewOps, "externalType: setArg #%u %u: %s",
|
||||
script->id(), arg, TypeString(type));
|
||||
@ -1350,7 +1350,7 @@ TypeSet::clearObjects()
|
||||
inline void
|
||||
TypeSet::addType(JSContext *cx, Type type)
|
||||
{
|
||||
JS_ASSERT(cx->compartment->activeInference);
|
||||
JS_ASSERT(cx->compartment->activeAnalysis);
|
||||
|
||||
if (unknown())
|
||||
return;
|
||||
@ -1537,7 +1537,7 @@ TypeObject::setBasePropertyCount(uint32_t count)
|
||||
inline HeapTypeSet *
|
||||
TypeObject::getProperty(JSContext *cx, jsid id, bool own)
|
||||
{
|
||||
JS_ASSERT(cx->compartment->activeInference);
|
||||
JS_ASSERT(cx->compartment->activeAnalysis);
|
||||
JS_ASSERT(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id));
|
||||
JS_ASSERT_IF(!JSID_IS_EMPTY(id), id == MakeTypeId(cx, id));
|
||||
JS_ASSERT(!unknownProperties());
|
||||
@ -1730,8 +1730,7 @@ JSScript::ensureHasTypes(JSContext *cx)
|
||||
/* static */ inline bool
|
||||
JSScript::ensureRanAnalysis(JSContext *cx, JS::HandleScript script)
|
||||
{
|
||||
AssertCanGC();
|
||||
js::analyze::AutoEnterAnalysis aea(cx->compartment);
|
||||
js::types::AutoEnterAnalysis aea(cx);
|
||||
|
||||
if (!script->ensureHasTypes(cx))
|
||||
return false;
|
||||
@ -1744,11 +1743,10 @@ JSScript::ensureRanAnalysis(JSContext *cx, JS::HandleScript script)
|
||||
/* static */ inline bool
|
||||
JSScript::ensureRanInference(JSContext *cx, JS::HandleScript script)
|
||||
{
|
||||
AssertCanGC();
|
||||
if (!script->ensureRanAnalysis(cx, script))
|
||||
return false;
|
||||
if (!script->analysis()->ranInference()) {
|
||||
js::types::AutoEnterTypeInference enter(cx);
|
||||
js::types::AutoEnterAnalysis enter(cx);
|
||||
script->analysis()->analyzeTypes(cx);
|
||||
}
|
||||
return !script->analysis()->OOM() &&
|
||||
|
@ -2349,7 +2349,7 @@ JSObject::growSlots(JSContext *cx, HandleObject obj, uint32_t oldCount, uint32_t
|
||||
gc::AllocKind kind = obj->type()->newScript->allocKind;
|
||||
unsigned newScriptSlots = gc::GetGCKindSlots(kind);
|
||||
if (newScriptSlots == obj->numFixedSlots() && gc::TryIncrementAllocKind(&kind)) {
|
||||
AutoEnterTypeInference enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
Rooted<TypeObject*> typeObj(cx, obj->type());
|
||||
RootedShape shape(cx, typeObj->newScript->shape);
|
||||
|
@ -2745,7 +2745,7 @@ JSScript::argumentsOptimizationFailed(JSContext *cx, HandleScript script)
|
||||
#endif
|
||||
|
||||
if (script->hasAnalysis() && script->analysis()->ranInference()) {
|
||||
types::AutoEnterTypeInference enter(cx);
|
||||
types::AutoEnterAnalysis enter(cx);
|
||||
types::TypeScript::MonitorUnknown(cx, script, script->argumentsBytecode());
|
||||
}
|
||||
|
||||
|
@ -539,7 +539,7 @@ mjit::Compiler::performCompilation()
|
||||
outerScript->debugMode = debugMode();
|
||||
#endif
|
||||
|
||||
JS_ASSERT(cx->compartment->activeInference);
|
||||
JS_ASSERT(cx->compartment->activeAnalysis);
|
||||
|
||||
{
|
||||
types::AutoEnterCompilation enter(cx, types::CompilerOutput::MethodJIT);
|
||||
@ -1091,7 +1091,7 @@ mjit::CanMethodJIT(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
|
||||
CompileStatus status;
|
||||
{
|
||||
types::AutoEnterTypeInference enter(cx, true);
|
||||
types::AutoEnterAnalysis enter(cx);
|
||||
|
||||
Compiler cc(cx, script, chunkIndex, construct);
|
||||
status = cc.compile();
|
||||
|
@ -652,7 +652,7 @@ js_InternalThrow(VMFrame &f)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
analyze::AutoEnterAnalysis enter(cx);
|
||||
types::AutoEnterAnalysis enter(cx);
|
||||
|
||||
/*
|
||||
* Interpret the ENTERBLOCK and EXCEPTION opcodes, so that we don't go
|
||||
@ -797,7 +797,9 @@ js_InternalInterpret(void *returnData, void *returnType, void *returnReg, js::VM
|
||||
return js_InternalThrow(f);
|
||||
}
|
||||
|
||||
analyze::AutoEnterAnalysis enter(cx);
|
||||
mozilla::Maybe<types::AutoEnterAnalysis> enter;
|
||||
enter.construct(cx);
|
||||
|
||||
analyze::ScriptAnalysis *analysis = script->analysis();
|
||||
|
||||
/*
|
||||
@ -1023,7 +1025,7 @@ js_InternalInterpret(void *returnData, void *returnType, void *returnReg, js::VM
|
||||
case REJOIN_CALL_SPLAT: {
|
||||
/* Leave analysis early and do the Invoke which SplatApplyArgs prepared. */
|
||||
nextDepth = analysis->getCode(nextpc).stackDepth;
|
||||
enter.leave();
|
||||
enter.destroy();
|
||||
f.regs.sp = nextsp + 2 + f.u.call.dynamicArgc;
|
||||
if (!InvokeKernel(cx, CallArgsFromSp(f.u.call.dynamicArgc, f.regs.sp)))
|
||||
return js_InternalThrow(f);
|
||||
|
@ -415,7 +415,7 @@ class SetPropCompiler : public PICStubCompiler
|
||||
return false;
|
||||
|
||||
if (!type->unknownProperties()) {
|
||||
types::AutoEnterTypeInference enter(cx);
|
||||
types::AutoEnterAnalysis enter(cx);
|
||||
types::TypeSet *types = type->getProperty(cx, types::MakeTypeId(cx, id), true);
|
||||
if (!types)
|
||||
return false;
|
||||
|
@ -411,7 +411,7 @@ Recompiler::clearStackReferences(FreeOp *fop, JSScript *script)
|
||||
script->filename, script->lineno, script->length, (int) script->getUseCount());
|
||||
|
||||
JSCompartment *comp = script->compartment();
|
||||
types::AutoEnterTypeInference enter(fop, comp);
|
||||
types::AutoEnterAnalysis enter(fop, comp);
|
||||
|
||||
/*
|
||||
* The strategy for this goes as follows:
|
||||
|
@ -1516,7 +1516,7 @@ stubs::TypeBarrierHelper(VMFrame &f, uint32_t which)
|
||||
*/
|
||||
RootedScript fscript(f.cx, f.script());
|
||||
if (fscript->hasAnalysis() && fscript->analysis()->ranInference()) {
|
||||
AutoEnterTypeInference enter(f.cx);
|
||||
AutoEnterAnalysis enter(f.cx);
|
||||
fscript->analysis()->breakTypeBarriers(f.cx, f.pc() - fscript->code, false);
|
||||
}
|
||||
|
||||
@ -1530,7 +1530,7 @@ stubs::StubTypeHelper(VMFrame &f, int32_t which)
|
||||
|
||||
RootedScript fscript(f.cx, f.script());
|
||||
if (fscript->hasAnalysis() && fscript->analysis()->ranInference()) {
|
||||
AutoEnterTypeInference enter(f.cx);
|
||||
AutoEnterAnalysis enter(f.cx);
|
||||
fscript->analysis()->breakTypeBarriers(f.cx, f.pc() - fscript->code, false);
|
||||
}
|
||||
|
||||
@ -1566,7 +1566,7 @@ stubs::CheckArgumentTypes(VMFrame &f)
|
||||
|
||||
{
|
||||
/* Postpone recompilations until all args have been updated. */
|
||||
types::AutoEnterTypeInference enter(f.cx);
|
||||
types::AutoEnterAnalysis enter(f.cx);
|
||||
|
||||
if (!f.fp()->isConstructing())
|
||||
TypeScript::SetThis(f.cx, fscript, fp->thisValue());
|
||||
|
Loading…
Reference in New Issue
Block a user