зеркало из https://github.com/mozilla/gecko-dev.git
Bug 650161 - Add an assertion that something is only ever called from a GC callback r=terrence
This commit is contained in:
Родитель
98811767d8
Коммит
1ae2e41b28
|
@ -393,10 +393,32 @@ class JS_PUBLIC_API(AutoAssertOnGC)
|
|||
};
|
||||
|
||||
/*
|
||||
* Disable the static rooting hazard analysis in the live region, but assert if
|
||||
* any GC occurs while this guard object is live. This is most useful to help
|
||||
* the exact rooting hazard analysis in complex regions, since it cannot
|
||||
* understand dataflow.
|
||||
* Assert if an allocation of a GC thing occurs while this class is live. This
|
||||
* class does not disable the static rooting hazard analysis.
|
||||
*/
|
||||
class JS_PUBLIC_API(AutoAssertNoAlloc)
|
||||
{
|
||||
#ifdef JS_DEBUG
|
||||
js::gc::GCRuntime *gc;
|
||||
|
||||
public:
|
||||
AutoAssertNoAlloc() : gc(nullptr) {}
|
||||
explicit AutoAssertNoAlloc(JSRuntime *rt);
|
||||
void disallowAlloc(JSRuntime *rt);
|
||||
~AutoAssertNoAlloc();
|
||||
#else
|
||||
public:
|
||||
AutoAssertNoAlloc() {}
|
||||
explicit AutoAssertNoAlloc(JSRuntime *rt) {}
|
||||
void disallowAlloc(JSRuntime *rt) {}
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Disable the static rooting hazard analysis in the live region and assert if
|
||||
* any allocation that could potentially trigger a GC occurs while this guard
|
||||
* object is live. This is most useful to help the exact rooting hazard analysis
|
||||
* in complex regions, since it cannot understand dataflow.
|
||||
*
|
||||
* Note: GC behavior is unpredictable even when deterministice and is generally
|
||||
* non-deterministic in practice. The fact that this guard has not
|
||||
|
@ -406,11 +428,25 @@ class JS_PUBLIC_API(AutoAssertOnGC)
|
|||
* that the hazard analysis is correct for that code, rather than relying
|
||||
* on this class.
|
||||
*/
|
||||
class JS_PUBLIC_API(AutoSuppressGCAnalysis) : public AutoAssertOnGC
|
||||
class JS_PUBLIC_API(AutoSuppressGCAnalysis) : public AutoAssertNoAlloc
|
||||
{
|
||||
public:
|
||||
AutoSuppressGCAnalysis() : AutoAssertOnGC() {}
|
||||
explicit AutoSuppressGCAnalysis(JSRuntime *rt) : AutoAssertOnGC(rt) {}
|
||||
AutoSuppressGCAnalysis() : AutoAssertNoAlloc() {}
|
||||
explicit AutoSuppressGCAnalysis(JSRuntime *rt) : AutoAssertNoAlloc(rt) {}
|
||||
};
|
||||
|
||||
/*
|
||||
* Assert that code is only ever called from a GC callback, disable the static
|
||||
* rooting hazard analysis and assert if any allocation that could potentially
|
||||
* trigger a GC occurs while this guard object is live.
|
||||
*
|
||||
* This is useful to make the static analysis ignore code that runs in GC
|
||||
* callbacks.
|
||||
*/
|
||||
class JS_PUBLIC_API(AutoAssertGCCallback) : public AutoSuppressGCAnalysis
|
||||
{
|
||||
public:
|
||||
explicit AutoAssertGCCallback(JSObject *obj);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -222,6 +222,7 @@ function isRootedPointerTypeName(name)
|
|||
function isSuppressConstructor(name)
|
||||
{
|
||||
return name.indexOf("::AutoSuppressGC") != -1
|
||||
|| name.indexOf("::AutoAssertGCCallback") != -1
|
||||
|| name.indexOf("::AutoEnterAnalysis") != -1
|
||||
|| name.indexOf("::AutoSuppressGCAnalysis") != -1
|
||||
|| name.indexOf("::AutoIgnoreRootingHazards") != -1;
|
||||
|
|
|
@ -5642,12 +5642,12 @@ GCRuntime::collect(bool incremental, int64_t budget, JSGCInvocationKind gckind,
|
|||
JS::gcreason::Reason reason)
|
||||
{
|
||||
/* GC shouldn't be running in parallel execution mode */
|
||||
MOZ_ASSERT(!InParallelSection());
|
||||
MOZ_ALWAYS_TRUE(!InParallelSection());
|
||||
|
||||
JS_AbortIfWrongThread(rt);
|
||||
|
||||
/* If we attempt to invoke the GC while we are running in the GC, assert. */
|
||||
MOZ_ASSERT(!rt->isHeapBusy());
|
||||
MOZ_ALWAYS_TRUE(!rt->isHeapBusy());
|
||||
|
||||
/* The engine never locks across anything that could GC. */
|
||||
MOZ_ASSERT(!rt->currentThreadHasExclusiveAccess());
|
||||
|
@ -6359,8 +6359,33 @@ JS::AutoAssertOnGC::VerifyIsSafeToGC(JSRuntime *rt)
|
|||
if (rt->gc.isInsideUnsafeRegion())
|
||||
MOZ_CRASH("[AutoAssertOnGC] possible GC in GC-unsafe region");
|
||||
}
|
||||
|
||||
JS::AutoAssertNoAlloc::AutoAssertNoAlloc(JSRuntime *rt)
|
||||
: gc(nullptr)
|
||||
{
|
||||
disallowAlloc(rt);
|
||||
}
|
||||
|
||||
void JS::AutoAssertNoAlloc::disallowAlloc(JSRuntime *rt)
|
||||
{
|
||||
JS_ASSERT(!gc);
|
||||
gc = &rt->gc;
|
||||
gc->disallowAlloc();
|
||||
}
|
||||
|
||||
JS::AutoAssertNoAlloc::~AutoAssertNoAlloc()
|
||||
{
|
||||
if (gc)
|
||||
gc->allowAlloc();
|
||||
}
|
||||
#endif
|
||||
|
||||
JS::AutoAssertGCCallback::AutoAssertGCCallback(JSObject *obj)
|
||||
: AutoSuppressGCAnalysis()
|
||||
{
|
||||
MOZ_ASSERT(obj->runtimeFromMainThread()->isHeapMajorCollecting());
|
||||
}
|
||||
|
||||
#ifdef JSGC_HASH_TABLE_CHECKS
|
||||
void
|
||||
js::gc::CheckHashTablesAfterMovingGC(JSRuntime *rt)
|
||||
|
|
|
@ -325,37 +325,9 @@ class ZoneCellIterUnderGC : public ZoneCellIterImpl
|
|||
}
|
||||
};
|
||||
|
||||
/* In debug builds, assert that no allocation occurs. */
|
||||
class AutoAssertNoAlloc
|
||||
{
|
||||
#ifdef JS_DEBUG
|
||||
GCRuntime *gc;
|
||||
|
||||
public:
|
||||
AutoAssertNoAlloc() : gc(nullptr) {}
|
||||
explicit AutoAssertNoAlloc(JSRuntime *rt) : gc(nullptr) {
|
||||
disallowAlloc(rt);
|
||||
}
|
||||
void disallowAlloc(JSRuntime *rt) {
|
||||
JS_ASSERT(!gc);
|
||||
gc = &rt->gc;
|
||||
gc->disallowAlloc();
|
||||
}
|
||||
~AutoAssertNoAlloc() {
|
||||
if (gc)
|
||||
gc->allowAlloc();
|
||||
}
|
||||
#else
|
||||
public:
|
||||
AutoAssertNoAlloc() {}
|
||||
explicit AutoAssertNoAlloc(JSRuntime *) {}
|
||||
void disallowAlloc(JSRuntime *rt) {}
|
||||
#endif
|
||||
};
|
||||
|
||||
class ZoneCellIter : public ZoneCellIterImpl
|
||||
{
|
||||
AutoAssertNoAlloc noAlloc;
|
||||
JS::AutoAssertNoAlloc noAlloc;
|
||||
ArenaLists *lists;
|
||||
AllocKind kind;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче