Bug 1342345 part 2 - Use a Vector for AutoCycleDetector. r=jonco

This commit is contained in:
Jan de Mooij 2017-02-25 12:23:44 +01:00
parent ce45ed0a77
commit 9d0be99a0b
5 changed files with 34 additions and 38 deletions

View File

@ -74,6 +74,7 @@ class GCVector
MOZ_MUST_USE bool resize(size_t newLen) { return vector.resize(newLen); }
void clear() { return vector.clear(); }
void clearAndFree() { return vector.clearAndFree(); }
template<typename U> bool append(U&& item) { return vector.append(mozilla::Forward<U>(item)); }

View File

@ -172,7 +172,7 @@ JSString*
js::ObjectToSource(JSContext* cx, HandleObject obj)
{
/* 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);
if (!detector.init())

View File

@ -638,9 +638,6 @@ JS::InitSelfHostedCode(JSContext* cx)
if (!rt->initializeAtoms(cx))
return false;
if (!cx->cycleDetectorSet().init())
return false;
if (!rt->initSelfHosting(cx))
return false;

View File

@ -68,36 +68,36 @@ using mozilla::PointerRangeSize;
bool
js::AutoCycleDetector::init()
{
AutoCycleDetector::Set& set = cx->cycleDetectorSet();
hashsetAddPointer = set.lookupForAdd(obj);
if (!hashsetAddPointer) {
if (!set.add(hashsetAddPointer, obj)) {
ReportOutOfMemory(cx);
return false;
}
cyclic = false;
hashsetGenerationAtInit = set.generation();
MOZ_ASSERT(cyclic);
AutoCycleDetector::Vector& vector = cx->cycleDetectorVector();
for (JSObject* obj2 : vector) {
if (MOZ_UNLIKELY(obj == obj2))
return true;
}
if (!vector.append(obj))
return false;
cyclic = false;
return true;
}
js::AutoCycleDetector::~AutoCycleDetector()
{
if (!cyclic) {
if (hashsetGenerationAtInit == cx->cycleDetectorSet().generation())
cx->cycleDetectorSet().remove(hashsetAddPointer);
else
cx->cycleDetectorSet().remove(obj);
if (MOZ_LIKELY(!cyclic)) {
AutoCycleDetector::Vector& vec = cx->cycleDetectorVector();
MOZ_ASSERT(vec.back() == obj);
if (vec.length() > 1) {
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
JSContext::init(ContextKind kind)
{
@ -1197,6 +1197,7 @@ JSContext::JSContext(JSRuntime* runtime, const JS::ContextOptions& options)
enteredPolicy(nullptr),
#endif
generatingError(false),
cycleDetectorVector_(this),
data(nullptr),
outstandingRequests(0),
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
* added later.
*/
return cycleDetectorSet().sizeOfExcludingThis(mallocSizeOf);
return cycleDetectorVector().sizeOfExcludingThis(mallocSizeOf);
}
void
JSContext::trace(JSTracer* trc)
{
if (cycleDetectorSet().initialized())
TraceCycleDetectionSet(trc, cycleDetectorSet());
cycleDetectorVector().trace(trc);
if (trc->isMarkingTracer() && compartment_)
compartment_->mark();

View File

@ -41,7 +41,7 @@ typedef HashSet<Shape*> ShapeSet;
class MOZ_RAII AutoCycleDetector
{
public:
using Set = HashSet<JSObject*, MovableCellHasher<JSObject*>, SystemAllocPolicy>;
using Vector = GCVector<JSObject*, 8>;
AutoCycleDetector(JSContext* cx, HandleObject objArg
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
@ -57,18 +57,12 @@ class MOZ_RAII AutoCycleDetector
bool foundCycle() { return cyclic; }
private:
Generation hashsetGenerationAtInit;
JSContext* cx;
RootedObject obj;
Set::AddPtr hashsetAddPointer;
bool cyclic;
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;
namespace frontend { class CompileError; }
@ -640,11 +634,15 @@ struct JSContext : public JS::RootingContext,
private:
/* State for object and array toSource conversion. */
js::ThreadLocalData<js::AutoCycleDetector::Set> cycleDetectorSet_;
js::ThreadLocalData<js::AutoCycleDetector::Vector> cycleDetectorVector_;
public:
js::AutoCycleDetector::Set& cycleDetectorSet() { return cycleDetectorSet_.ref(); }
const js::AutoCycleDetector::Set& cycleDetectorSet() const { return cycleDetectorSet_.ref(); }
js::AutoCycleDetector::Vector& cycleDetectorVector() {
return cycleDetectorVector_.ref();
}
const js::AutoCycleDetector::Vector& cycleDetectorVector() const {
return cycleDetectorVector_.ref();
}
/* Client opaque pointer. */
js::UnprotectedData<void*> data;