зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1254376 - Add a read barrier to the global's debugger vector r=jimb
This commit is contained in:
Родитель
e8da73b559
Коммит
7ed132a5e3
|
@ -23,21 +23,6 @@ namespace js {
|
|||
|
||||
#ifdef DEBUG
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
BarrieredBase<T>::assertTypeConstraints() const
|
||||
{
|
||||
static_assert(mozilla::IsBaseOf<gc::Cell, typename mozilla::RemovePointer<T>::Type>::value ||
|
||||
mozilla::IsSame<JS::Value, T>::value ||
|
||||
mozilla::IsSame<jsid, T>::value ||
|
||||
mozilla::IsSame<TaggedProto, T>::value,
|
||||
"ensure only supported types are instantiated with barriers");
|
||||
}
|
||||
#define INSTANTIATE_ALL_VALID_TYPES(type) \
|
||||
template void BarrieredBase<type>::assertTypeConstraints() const;
|
||||
FOR_EACH_GC_POINTER_TYPE(INSTANTIATE_ALL_VALID_TYPES)
|
||||
#undef INSTANTIATE_ALL_VALID_TYPES
|
||||
|
||||
bool
|
||||
HeapSlot::preconditionForSet(NativeObject* owner, Kind kind, uint32_t slot)
|
||||
{
|
||||
|
|
|
@ -173,6 +173,11 @@
|
|||
* Barriers designed to be used externally are provided in js/RootingAPI.h.
|
||||
* These external barriers call into the same post-barrier implementations at
|
||||
* InternalBarrierMethods<T>::post via an indirect call to Heap(.+)Barrier.
|
||||
*
|
||||
* These clases are designed to be used to wrap GC thing pointers or values that
|
||||
* act like them (i.e. JS::Value and jsid). It is possible to use them for
|
||||
* other types by supplying the necessary barrier implementations but this
|
||||
* is not usually necessary and should be done with caution.
|
||||
*/
|
||||
|
||||
class JSAtom;
|
||||
|
@ -322,11 +327,7 @@ class BarrieredBase : public BarrieredBaseMixins<T>
|
|||
{
|
||||
protected:
|
||||
// BarrieredBase is not directly instantiable.
|
||||
explicit BarrieredBase(T v) : value(v) {
|
||||
#ifdef DEBUG
|
||||
assertTypeConstraints();
|
||||
#endif
|
||||
}
|
||||
explicit BarrieredBase(T v) : value(v) {}
|
||||
|
||||
// Storage for all barrier classes. |value| must be a GC thing reference
|
||||
// type: either a direct pointer to a GC thing or a supported tagged
|
||||
|
@ -339,13 +340,6 @@ class BarrieredBase : public BarrieredBaseMixins<T>
|
|||
// Friending to the generic template leads to a number of unintended consequences, including
|
||||
// template resolution ambiguity and a circular dependency with Tracing.h.
|
||||
T* unsafeUnbarrieredForTracing() { return &value; }
|
||||
|
||||
private:
|
||||
#ifdef DEBUG
|
||||
// Static type assertions about T must be moved out of line to avoid
|
||||
// circular dependencies between Barrier classes and GC memory definitions.
|
||||
void assertTypeConstraints() const;
|
||||
#endif
|
||||
};
|
||||
|
||||
// Base class for barriered pointer types that intercept only writes.
|
||||
|
|
|
@ -1015,7 +1015,7 @@ JSCompartment::updateDebuggerObservesFlag(unsigned flag)
|
|||
? unsafeUnbarrieredMaybeGlobal()
|
||||
: maybeGlobal();
|
||||
const GlobalObject::DebuggerVector* v = global->getDebuggers();
|
||||
for (Debugger * const* p = v->begin(); p != v->end(); p++) {
|
||||
for (auto p = v->begin(); p != v->end(); p++) {
|
||||
Debugger* dbg = *p;
|
||||
if (flag == DebuggerObservesAllExecution ? dbg->observesAllExecution() :
|
||||
flag == DebuggerObservesCoverage ? dbg->observesCoverage() :
|
||||
|
|
|
@ -646,7 +646,7 @@ Debugger::getScriptFrameWithIter(JSContext* cx, AbstractFramePtr frame,
|
|||
Debugger::hasLiveHook(GlobalObject* global, Hook which)
|
||||
{
|
||||
if (GlobalObject::DebuggerVector* debuggers = global->getDebuggers()) {
|
||||
for (Debugger** p = debuggers->begin(); p != debuggers->end(); p++) {
|
||||
for (auto p = debuggers->begin(); p != debuggers->end(); p++) {
|
||||
Debugger* dbg = *p;
|
||||
if (dbg->enabled && dbg->getHook(which))
|
||||
return true;
|
||||
|
@ -1572,7 +1572,7 @@ Debugger::dispatchHook(JSContext* cx, HookIsEnabledFun hookIsEnabled, FireHookFu
|
|||
AutoValueVector triggered(cx);
|
||||
Handle<GlobalObject*> global = cx->global();
|
||||
if (GlobalObject::DebuggerVector* debuggers = global->getDebuggers()) {
|
||||
for (Debugger** p = debuggers->begin(); p != debuggers->end(); p++) {
|
||||
for (auto p = debuggers->begin(); p != debuggers->end(); p++) {
|
||||
Debugger* dbg = *p;
|
||||
if (dbg->enabled && hookIsEnabled(dbg)) {
|
||||
if (!triggered.append(ObjectValue(*dbg->toJSObject())))
|
||||
|
@ -1753,7 +1753,7 @@ Debugger::onSingleStep(JSContext* cx, MutableHandleValue vp)
|
|||
JSScript* trappingScript = iter.script();
|
||||
GlobalObject* global = cx->global();
|
||||
if (GlobalObject::DebuggerVector* debuggers = global->getDebuggers()) {
|
||||
for (Debugger** p = debuggers->begin(); p != debuggers->end(); p++) {
|
||||
for (auto p = debuggers->begin(); p != debuggers->end(); p++) {
|
||||
Debugger* dbg = *p;
|
||||
for (FrameMap::Range r = dbg->frames.all(); !r.empty(); r.popFront()) {
|
||||
AbstractFramePtr frame = r.front().key();
|
||||
|
@ -1890,7 +1890,7 @@ Debugger::slowPathOnLogAllocationSite(JSContext* cx, HandleObject obj, HandleSav
|
|||
double when, GlobalObject::DebuggerVector& dbgs)
|
||||
{
|
||||
MOZ_ASSERT(!dbgs.empty());
|
||||
mozilla::DebugOnly<Debugger**> begin = dbgs.begin();
|
||||
mozilla::DebugOnly<ReadBarriered<Debugger*>*> begin = dbgs.begin();
|
||||
|
||||
// Root all the Debuggers while we're iterating over them;
|
||||
// appendAllocationSite calls JSCompartment::wrap, and thus can GC.
|
||||
|
@ -1900,17 +1900,12 @@ Debugger::slowPathOnLogAllocationSite(JSContext* cx, HandleObject obj, HandleSav
|
|||
// Handle), but in this case, we're iterating over a global's list of
|
||||
// Debuggers, and globals only hold their Debuggers weakly.
|
||||
Rooted<GCVector<JSObject*>> activeDebuggers(cx, GCVector<JSObject*>(cx));
|
||||
for (Debugger** dbgp = dbgs.begin(); dbgp < dbgs.end(); dbgp++) {
|
||||
// Since we're pulling these Debugger objects out of the GlobalObject's
|
||||
// debugger array, which holds them only weakly, we need to let the
|
||||
// incremental GC know that a possibly previously unreachable Debugger
|
||||
// object just became reachable.
|
||||
InternalBarrierMethods<JSObject*>::readBarrier((*dbgp)->object);
|
||||
for (auto dbgp = dbgs.begin(); dbgp < dbgs.end(); dbgp++) {
|
||||
if (!activeDebuggers.append((*dbgp)->object))
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Debugger** dbgp = dbgs.begin(); dbgp < dbgs.end(); dbgp++) {
|
||||
for (auto dbgp = dbgs.begin(); dbgp < dbgs.end(); dbgp++) {
|
||||
// The set of debuggers had better not change while we're iterating,
|
||||
// such that the vector gets reallocated.
|
||||
MOZ_ASSERT(dbgs.begin() == begin);
|
||||
|
@ -2517,8 +2512,7 @@ Debugger::cannotTrackAllocations(const GlobalObject& global)
|
|||
Debugger::isObservedByDebuggerTrackingAllocations(const GlobalObject& debuggee)
|
||||
{
|
||||
if (auto* v = debuggee.getDebuggers()) {
|
||||
Debugger** p;
|
||||
for (p = v->begin(); p != v->end(); p++) {
|
||||
for (auto p = v->begin(); p != v->end(); p++) {
|
||||
if ((*p)->trackingAllocationSites && (*p)->enabled) {
|
||||
return true;
|
||||
}
|
||||
|
@ -2686,7 +2680,7 @@ Debugger::markAllIteratively(GCMarker* trc)
|
|||
*/
|
||||
const GlobalObject::DebuggerVector* debuggers = global->getDebuggers();
|
||||
MOZ_ASSERT(debuggers);
|
||||
for (Debugger * const* p = debuggers->begin(); p != debuggers->end(); p++) {
|
||||
for (auto p = debuggers->begin(); p != debuggers->end(); p++) {
|
||||
Debugger* dbg = *p;
|
||||
|
||||
/*
|
||||
|
@ -3551,7 +3545,7 @@ Debugger::addDebuggeeGlobal(JSContext* cx, Handle<GlobalObject*> global)
|
|||
*/
|
||||
if (c->isDebuggee()) {
|
||||
GlobalObject::DebuggerVector* v = c->maybeGlobal()->getDebuggers();
|
||||
for (Debugger** p = v->begin(); p != v->end(); p++) {
|
||||
for (auto p = v->begin(); p != v->end(); p++) {
|
||||
JSCompartment* next = (*p)->object->compartment();
|
||||
if (Find(visited, next) == visited.end() && !visited.append(next))
|
||||
return false;
|
||||
|
@ -3659,11 +3653,11 @@ Debugger::recomputeDebuggeeZoneSet()
|
|||
}
|
||||
}
|
||||
|
||||
template<typename V>
|
||||
static Debugger**
|
||||
findDebuggerInVector(Debugger* dbg, V* vec)
|
||||
template <typename T>
|
||||
static T*
|
||||
findDebuggerInVector(Debugger* dbg, Vector<T, 0, js::SystemAllocPolicy>* vec)
|
||||
{
|
||||
Debugger** p;
|
||||
T* p;
|
||||
for (p = vec->begin(); p != vec->end(); p++) {
|
||||
if (*p == dbg)
|
||||
break;
|
||||
|
|
|
@ -345,6 +345,12 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
|
|||
}
|
||||
};
|
||||
|
||||
// Barrier methods so we can have ReadBarriered<Debugger*>.
|
||||
static void readBarrier(Debugger* dbg) {
|
||||
InternalBarrierMethods<JSObject*>::readBarrier(dbg->object);
|
||||
}
|
||||
static void writeBarrierPost(Debugger** vp, Debugger* prev, Debugger* next) {}
|
||||
|
||||
private:
|
||||
HeapPtrNativeObject object; /* The Debugger object. Strong reference. */
|
||||
WeakGlobalObjectSet debuggees; /* Debuggee globals. Cross-compartment weak references. */
|
||||
|
@ -353,7 +359,7 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
|
|||
bool enabled;
|
||||
bool allowUnobservedAsmJS;
|
||||
|
||||
// Wether to enable code coverage on the Debuggee.
|
||||
// Whether to enable code coverage on the Debuggee.
|
||||
bool collectCoverageInfo;
|
||||
|
||||
JSCList breakpoints; /* Circular list of all js::Breakpoints in this debugger */
|
||||
|
|
|
@ -745,7 +745,7 @@ class GlobalObject : public NativeObject
|
|||
static bool initSelfHostingBuiltins(JSContext* cx, Handle<GlobalObject*> global,
|
||||
const JSFunctionSpec* builtins);
|
||||
|
||||
typedef js::Vector<js::Debugger*, 0, js::SystemAllocPolicy> DebuggerVector;
|
||||
typedef js::Vector<js::ReadBarriered<js::Debugger*>, 0, js::SystemAllocPolicy> DebuggerVector;
|
||||
|
||||
/*
|
||||
* The collection of Debugger objects debugging this global. If this global
|
||||
|
|
|
@ -1385,11 +1385,11 @@ SavedStacks::chooseSamplingProbability(JSCompartment* compartment)
|
|||
if (!dbgs || dbgs->empty())
|
||||
return;
|
||||
|
||||
mozilla::DebugOnly<Debugger**> begin = dbgs->begin();
|
||||
mozilla::DebugOnly<ReadBarriered<Debugger*>*> begin = dbgs->begin();
|
||||
mozilla::DebugOnly<bool> foundAnyDebuggers = false;
|
||||
|
||||
double probability = 0;
|
||||
for (Debugger** dbgp = dbgs->begin(); dbgp < dbgs->end(); dbgp++) {
|
||||
for (auto dbgp = dbgs->begin(); dbgp < dbgs->end(); dbgp++) {
|
||||
// The set of debuggers had better not change while we're iterating,
|
||||
// such that the vector gets reallocated.
|
||||
MOZ_ASSERT(dbgs->begin() == begin);
|
||||
|
|
Загрузка…
Ссылка в новой задаче