mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bug 1342345
part 2 - Use a Vector for AutoCycleDetector. r=jonco
This commit is contained in:
parent
ce45ed0a77
commit
9d0be99a0b
@ -74,6 +74,7 @@ class GCVector
|
|||||||
MOZ_MUST_USE bool resize(size_t newLen) { return vector.resize(newLen); }
|
MOZ_MUST_USE bool resize(size_t newLen) { return vector.resize(newLen); }
|
||||||
|
|
||||||
void clear() { return vector.clear(); }
|
void clear() { return vector.clear(); }
|
||||||
|
void clearAndFree() { return vector.clearAndFree(); }
|
||||||
|
|
||||||
template<typename U> bool append(U&& item) { return vector.append(mozilla::Forward<U>(item)); }
|
template<typename U> bool append(U&& item) { return vector.append(mozilla::Forward<U>(item)); }
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ JSString*
|
|||||||
js::ObjectToSource(JSContext* cx, HandleObject obj)
|
js::ObjectToSource(JSContext* cx, HandleObject obj)
|
||||||
{
|
{
|
||||||
/* If outermost, we need parentheses to be an expression, not a block. */
|
/* If outermost, we need parentheses to be an expression, not a block. */
|
||||||
bool outermost = (cx->cycleDetectorSet().count() == 0);
|
bool outermost = cx->cycleDetectorVector().empty();
|
||||||
|
|
||||||
AutoCycleDetector detector(cx, obj);
|
AutoCycleDetector detector(cx, obj);
|
||||||
if (!detector.init())
|
if (!detector.init())
|
||||||
|
@ -638,9 +638,6 @@ JS::InitSelfHostedCode(JSContext* cx)
|
|||||||
if (!rt->initializeAtoms(cx))
|
if (!rt->initializeAtoms(cx))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!cx->cycleDetectorSet().init())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!rt->initSelfHosting(cx))
|
if (!rt->initSelfHosting(cx))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -68,36 +68,36 @@ using mozilla::PointerRangeSize;
|
|||||||
bool
|
bool
|
||||||
js::AutoCycleDetector::init()
|
js::AutoCycleDetector::init()
|
||||||
{
|
{
|
||||||
AutoCycleDetector::Set& set = cx->cycleDetectorSet();
|
MOZ_ASSERT(cyclic);
|
||||||
hashsetAddPointer = set.lookupForAdd(obj);
|
|
||||||
if (!hashsetAddPointer) {
|
AutoCycleDetector::Vector& vector = cx->cycleDetectorVector();
|
||||||
if (!set.add(hashsetAddPointer, obj)) {
|
|
||||||
ReportOutOfMemory(cx);
|
for (JSObject* obj2 : vector) {
|
||||||
return false;
|
if (MOZ_UNLIKELY(obj == obj2))
|
||||||
}
|
return true;
|
||||||
cyclic = false;
|
|
||||||
hashsetGenerationAtInit = set.generation();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!vector.append(obj))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
cyclic = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
js::AutoCycleDetector::~AutoCycleDetector()
|
js::AutoCycleDetector::~AutoCycleDetector()
|
||||||
{
|
{
|
||||||
if (!cyclic) {
|
if (MOZ_LIKELY(!cyclic)) {
|
||||||
if (hashsetGenerationAtInit == cx->cycleDetectorSet().generation())
|
AutoCycleDetector::Vector& vec = cx->cycleDetectorVector();
|
||||||
cx->cycleDetectorSet().remove(hashsetAddPointer);
|
MOZ_ASSERT(vec.back() == obj);
|
||||||
else
|
if (vec.length() > 1) {
|
||||||
cx->cycleDetectorSet().remove(obj);
|
vec.popBack();
|
||||||
|
} else {
|
||||||
|
// Avoid holding on to unused heap allocations.
|
||||||
|
vec.clearAndFree();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
js::TraceCycleDetectionSet(JSTracer* trc, AutoCycleDetector::Set& set)
|
|
||||||
{
|
|
||||||
for (AutoCycleDetector::Set::Enum e(set); !e.empty(); e.popFront())
|
|
||||||
TraceRoot(trc, &e.mutableFront(), "cycle detector table entry");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
JSContext::init(ContextKind kind)
|
JSContext::init(ContextKind kind)
|
||||||
{
|
{
|
||||||
@ -1197,6 +1197,7 @@ JSContext::JSContext(JSRuntime* runtime, const JS::ContextOptions& options)
|
|||||||
enteredPolicy(nullptr),
|
enteredPolicy(nullptr),
|
||||||
#endif
|
#endif
|
||||||
generatingError(false),
|
generatingError(false),
|
||||||
|
cycleDetectorVector_(this),
|
||||||
data(nullptr),
|
data(nullptr),
|
||||||
outstandingRequests(0),
|
outstandingRequests(0),
|
||||||
jitIsBroken(false),
|
jitIsBroken(false),
|
||||||
@ -1391,14 +1392,13 @@ JSContext::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
|
|||||||
* ones have been found by DMD to be worth measuring. More stuff may be
|
* ones have been found by DMD to be worth measuring. More stuff may be
|
||||||
* added later.
|
* added later.
|
||||||
*/
|
*/
|
||||||
return cycleDetectorSet().sizeOfExcludingThis(mallocSizeOf);
|
return cycleDetectorVector().sizeOfExcludingThis(mallocSizeOf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
JSContext::trace(JSTracer* trc)
|
JSContext::trace(JSTracer* trc)
|
||||||
{
|
{
|
||||||
if (cycleDetectorSet().initialized())
|
cycleDetectorVector().trace(trc);
|
||||||
TraceCycleDetectionSet(trc, cycleDetectorSet());
|
|
||||||
|
|
||||||
if (trc->isMarkingTracer() && compartment_)
|
if (trc->isMarkingTracer() && compartment_)
|
||||||
compartment_->mark();
|
compartment_->mark();
|
||||||
|
@ -41,7 +41,7 @@ typedef HashSet<Shape*> ShapeSet;
|
|||||||
class MOZ_RAII AutoCycleDetector
|
class MOZ_RAII AutoCycleDetector
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using Set = HashSet<JSObject*, MovableCellHasher<JSObject*>, SystemAllocPolicy>;
|
using Vector = GCVector<JSObject*, 8>;
|
||||||
|
|
||||||
AutoCycleDetector(JSContext* cx, HandleObject objArg
|
AutoCycleDetector(JSContext* cx, HandleObject objArg
|
||||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||||
@ -57,18 +57,12 @@ class MOZ_RAII AutoCycleDetector
|
|||||||
bool foundCycle() { return cyclic; }
|
bool foundCycle() { return cyclic; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Generation hashsetGenerationAtInit;
|
|
||||||
JSContext* cx;
|
JSContext* cx;
|
||||||
RootedObject obj;
|
RootedObject obj;
|
||||||
Set::AddPtr hashsetAddPointer;
|
|
||||||
bool cyclic;
|
bool cyclic;
|
||||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Updates references in the cycle detection set if the GC moves them. */
|
|
||||||
extern void
|
|
||||||
TraceCycleDetectionSet(JSTracer* trc, AutoCycleDetector::Set& set);
|
|
||||||
|
|
||||||
struct AutoResolving;
|
struct AutoResolving;
|
||||||
|
|
||||||
namespace frontend { class CompileError; }
|
namespace frontend { class CompileError; }
|
||||||
@ -640,11 +634,15 @@ struct JSContext : public JS::RootingContext,
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
/* State for object and array toSource conversion. */
|
/* State for object and array toSource conversion. */
|
||||||
js::ThreadLocalData<js::AutoCycleDetector::Set> cycleDetectorSet_;
|
js::ThreadLocalData<js::AutoCycleDetector::Vector> cycleDetectorVector_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
js::AutoCycleDetector::Set& cycleDetectorSet() { return cycleDetectorSet_.ref(); }
|
js::AutoCycleDetector::Vector& cycleDetectorVector() {
|
||||||
const js::AutoCycleDetector::Set& cycleDetectorSet() const { return cycleDetectorSet_.ref(); }
|
return cycleDetectorVector_.ref();
|
||||||
|
}
|
||||||
|
const js::AutoCycleDetector::Vector& cycleDetectorVector() const {
|
||||||
|
return cycleDetectorVector_.ref();
|
||||||
|
}
|
||||||
|
|
||||||
/* Client opaque pointer. */
|
/* Client opaque pointer. */
|
||||||
js::UnprotectedData<void*> data;
|
js::UnprotectedData<void*> data;
|
||||||
|
Loading…
Reference in New Issue
Block a user