Backed out 5 changesets (bug 1212624) for breaking stuff.

Backed out changeset cf5ffa45a4a2
Backed out changeset 0d7a968d2d64 (bug 1212624)
Backed out changeset 379edefa8e47 (bug 1212624)
Backed out changeset f73fca35daad (bug 1212624)
Backed out changeset 4f499d30a0e0 (bug 1212624)
This commit is contained in:
Steve Fink 2015-10-14 16:49:12 -07:00
parent e975f4d60e
commit 70a6b1e10f
13 changed files with 86 additions and 209 deletions

View File

@ -1775,7 +1775,7 @@ GCMarker::enterWeakMarkingMode()
tag_ = TracerKindTag::WeakMarking;
for (GCZoneGroupIter zone(runtime()); !zone.done(); zone.next()) {
for (WeakMapBase* m : zone->gcWeakMapList) {
for (WeakMapBase* m = zone->gcWeakMapList; m; m = m->next) {
if (m->marked)
m->markEphemeronEntries(this);
}

View File

@ -220,7 +220,7 @@ struct PersistentRootedMarker
static void
markChain(JSTracer* trc, List& list, const char* name)
{
for (Element* r : list)
for (Element* r = list.getFirst(); r; r = r->getNext())
TraceFn(trc, r->address(), name);
}
};

View File

@ -27,6 +27,7 @@ JS::Zone::Zone(JSRuntime* rt)
debuggers(nullptr),
arenas(rt),
types(this),
gcWeakMapList(nullptr),
compartments(),
gcGrayRoots(),
gcMallocBytes(0),

View File

@ -283,8 +283,8 @@ struct Zone : public JS::shadow::Zone,
js::TypeZone types;
/* Live weakmaps in this zone. */
mozilla::LinkedList<js::WeakMapBase> gcWeakMapList;
/* Linked list of live weakmaps in this zone. */
js::WeakMapBase* gcWeakMapList;
// The set of compartments in this zone.
typedef js::Vector<JSCompartment*, 1, js::SystemAllocPolicy> CompartmentVector;

View File

@ -25,6 +25,7 @@ using namespace js::gc;
WeakMapBase::WeakMapBase(JSObject* memOf, Zone* zone)
: memberOf(memOf),
zone(zone),
next(WeakMapNotInList),
marked(false)
{
MOZ_ASSERT_IF(memberOf, memberOf->compartment()->zone() == zone);
@ -33,6 +34,9 @@ WeakMapBase::WeakMapBase(JSObject* memOf, Zone* zone)
WeakMapBase::~WeakMapBase()
{
MOZ_ASSERT(CurrentThreadIsGCSweeping() || CurrentThreadIsHandlingInitFailure());
MOZ_ASSERT_IF(CurrentThreadIsGCSweeping(), !isInList());
if (isInList())
removeWeakMapFromList(this);
}
void
@ -67,7 +71,7 @@ WeakMapBase::trace(JSTracer* tracer)
void
WeakMapBase::unmarkZone(JS::Zone* zone)
{
for (WeakMapBase* m : zone->gcWeakMapList)
for (WeakMapBase* m = zone->gcWeakMapList; m; m = m->next)
m->marked = false;
}
@ -75,7 +79,7 @@ void
WeakMapBase::markAll(JS::Zone* zone, JSTracer* tracer)
{
MOZ_ASSERT(tracer->weakMapAction() != DoNotTraceWeakMaps);
for (WeakMapBase* m : zone->gcWeakMapList) {
for (WeakMapBase* m = zone->gcWeakMapList; m; m = m->next) {
m->trace(tracer);
if (m->memberOf)
TraceEdge(tracer, &m->memberOf, "memberOf");
@ -86,7 +90,7 @@ bool
WeakMapBase::markZoneIteratively(JS::Zone* zone, JSTracer* tracer)
{
bool markedAny = false;
for (WeakMapBase* m : zone->gcWeakMapList) {
for (WeakMapBase* m = zone->gcWeakMapList; m; m = m->next) {
if (m->marked && m->markIteratively(tracer))
markedAny = true;
}
@ -96,7 +100,7 @@ WeakMapBase::markZoneIteratively(JS::Zone* zone, JSTracer* tracer)
bool
WeakMapBase::findInterZoneEdges(JS::Zone* zone)
{
for (WeakMapBase* m : zone->gcWeakMapList) {
for (WeakMapBase* m = zone->gcWeakMapList; m; m = m->next) {
if (!m->findZoneEdges())
return false;
}
@ -106,20 +110,24 @@ WeakMapBase::findInterZoneEdges(JS::Zone* zone)
void
WeakMapBase::sweepZone(JS::Zone* zone)
{
for (WeakMapBase* m = zone->gcWeakMapList.getFirst(); m; ) {
WeakMapBase* next = m->getNext();
WeakMapBase** tailPtr = &zone->gcWeakMapList;
for (WeakMapBase* m = zone->gcWeakMapList; m; ) {
WeakMapBase* next = m->next;
if (m->marked) {
m->sweep();
*tailPtr = m;
tailPtr = &m->next;
} else {
/* Destroy the hash map now to catch any use after this point. */
m->finish();
m->removeFrom(zone->gcWeakMapList);
m->next = WeakMapNotInList;
}
m = next;
}
*tailPtr = nullptr;
#ifdef DEBUG
for (WeakMapBase* m : zone->gcWeakMapList)
for (WeakMapBase* m = zone->gcWeakMapList; m; m = m->next)
MOZ_ASSERT(m->isInList() && m->marked);
#endif
}
@ -129,7 +137,7 @@ WeakMapBase::traceAllMappings(WeakMapTracer* tracer)
{
JSRuntime* rt = tracer->runtime;
for (ZonesIter zone(rt, SkipAtoms); !zone.done(); zone.next()) {
for (WeakMapBase* m : zone->gcWeakMapList) {
for (WeakMapBase* m = zone->gcWeakMapList; m; m = m->next) {
// The WeakMapTracer callback is not allowed to GC.
JS::AutoSuppressGCAnalysis nogc;
m->traceMappings(tracer);
@ -140,7 +148,7 @@ WeakMapBase::traceAllMappings(WeakMapTracer* tracer)
bool
WeakMapBase::saveZoneMarkedWeakMaps(JS::Zone* zone, WeakMapSet& markedWeakMaps)
{
for (WeakMapBase* m : zone->gcWeakMapList) {
for (WeakMapBase* m = zone->gcWeakMapList; m; m = m->next) {
if (m->marked && !markedWeakMaps.put(m))
return false;
}
@ -158,6 +166,19 @@ WeakMapBase::restoreMarkedWeakMaps(WeakMapSet& markedWeakMaps)
}
}
void
WeakMapBase::removeWeakMapFromList(WeakMapBase* weakmap)
{
JS::Zone* zone = weakmap->zone;
for (WeakMapBase** p = &zone->gcWeakMapList; *p; p = &(*p)->next) {
if (*p == weakmap) {
*p = (*p)->next;
weakmap->next = WeakMapNotInList;
break;
}
}
}
bool
ObjectValueMap::findZoneEdges()
{
@ -196,6 +217,11 @@ ObjectWeakMap::init()
return map.init();
}
ObjectWeakMap::~ObjectWeakMap()
{
WeakMapBase::removeWeakMapFromList(&map);
}
JSObject*
ObjectWeakMap::lookup(const JSObject* obj)
{

View File

@ -7,7 +7,6 @@
#ifndef jsweakmap_h
#define jsweakmap_h
#include "mozilla/LinkedList.h"
#include "mozilla/Move.h"
#include "jscompartment.h"
@ -36,12 +35,14 @@ class WeakMapBase;
// implementation takes care of the iterative marking needed for weak tables and removing
// table entries when collection is complete.
// The value for the next pointer for maps not in the map list.
static WeakMapBase * const WeakMapNotInList = reinterpret_cast<WeakMapBase*>(1);
typedef HashSet<WeakMapBase*, DefaultHasher<WeakMapBase*>, SystemAllocPolicy> WeakMapSet;
// Common base class for all WeakMap specializations. The collector uses this to call
// their markIteratively and sweep methods.
class WeakMapBase : public mozilla::LinkedListElement<WeakMapBase>
{
class WeakMapBase {
friend void js::GCMarker::enterWeakMarkingMode();
public:
@ -74,12 +75,17 @@ class WeakMapBase : public mozilla::LinkedListElement<WeakMapBase>
// Trace all delayed weak map bindings. Used by the cycle collector.
static void traceAllMappings(WeakMapTracer* tracer);
bool isInList() { return next != WeakMapNotInList; }
// Save information about which weak maps are marked for a zone.
static bool saveZoneMarkedWeakMaps(JS::Zone* zone, WeakMapSet& markedWeakMaps);
// Restore information about which weak maps are marked for many zones.
static void restoreMarkedWeakMaps(WeakMapSet& markedWeakMaps);
// Remove a weakmap from its zone's weakmaps list.
static void removeWeakMapFromList(WeakMapBase* weakmap);
// Any weakmap key types that want to participate in the non-iterative
// ephemeron marking must override this method.
virtual void maybeMarkEntry(JSTracer* trc, gc::Cell* markedCell, JS::GCCellPtr l) = 0;
@ -103,6 +109,11 @@ class WeakMapBase : public mozilla::LinkedListElement<WeakMapBase>
// Zone containing this weak map.
JS::Zone* zone;
// Link in a list of all WeakMaps in a Zone, headed by
// JS::Zone::gcWeakMapList. The last element of the list has nullptr as its
// next. Maps not in the list have WeakMapNotInList as their next.
WeakMapBase* next;
// Whether this object has been traced during garbage collection.
bool marked;
};
@ -136,7 +147,8 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, RuntimeAllocPolicy>, publ
bool init(uint32_t len = 16) {
if (!Base::init(len))
return false;
zone->gcWeakMapList.insertFront(this);
next = zone->gcWeakMapList;
zone->gcWeakMapList = this;
marked = JS::IsIncrementalGCInProgress(zone->runtimeFromMainThread());
return true;
}
@ -165,9 +177,6 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, RuntimeAllocPolicy>, publ
return p;
}
// Resolve ambiguity with LinkedListElement<>::remove.
using Base::remove;
// The WeakMap and some part of the key are marked. If the entry is marked
// according to the exact semantics of this WeakMap, then mark the value.
// (For a standard WeakMap, the entry is marked if either the key its
@ -409,6 +418,7 @@ class ObjectWeakMap
public:
explicit ObjectWeakMap(JSContext* cx);
bool init();
~ObjectWeakMap();
JSObject* lookup(const JSObject* obj);
bool add(JSContext* cx, JSObject* obj, JSObject* target);

View File

@ -2439,7 +2439,7 @@ Debugger::markIncomingCrossCompartmentEdges(JSTracer* trc)
gc::State state = rt->gc.state();
MOZ_ASSERT(state == gc::MARK_ROOTS || state == gc::COMPACT);
for (Debugger* dbg : rt->debuggerList) {
for (Debugger* dbg = rt->debuggerList.getFirst(); dbg; dbg = dbg->getNext()) {
Zone* zone = dbg->object->zone();
if ((state == gc::MARK_ROOTS && !zone->isCollecting()) ||
(state == gc::COMPACT && !zone->isGCCompacting()))
@ -2535,7 +2535,7 @@ Debugger::markAllIteratively(GCMarker* trc)
Debugger::markAll(JSTracer* trc)
{
JSRuntime* rt = trc->runtime();
for (Debugger* dbg : rt->debuggerList) {
for (Debugger* dbg = rt->debuggerList.getFirst(); dbg; dbg = dbg->getNext()) {
WeakGlobalObjectSet& debuggees = dbg->debuggees;
for (WeakGlobalObjectSet::Enum e(debuggees); !e.empty(); e.popFront()) {
GlobalObject* global = e.front();
@ -2607,7 +2607,7 @@ Debugger::sweepAll(FreeOp* fop)
{
JSRuntime* rt = fop->runtime();
for (Debugger* dbg : rt->debuggerList) {
for (Debugger* dbg = rt->debuggerList.getFirst(); dbg; dbg = dbg->getNext()) {
if (IsAboutToBeFinalized(&dbg->object)) {
/*
* dbg is being GC'd. Detach it from its debuggees. The debuggee
@ -2638,7 +2638,10 @@ Debugger::findZoneEdges(Zone* zone, js::gc::ComponentFinder<Zone>& finder)
* This ensure that debuggers and their debuggees are finalized in the same
* group.
*/
for (Debugger* dbg : zone->runtimeFromMainThread()->debuggerList) {
for (Debugger* dbg = zone->runtimeFromMainThread()->debuggerList.getFirst();
dbg;
dbg = dbg->getNext())
{
Zone* w = dbg->object->zone();
if (w == zone || !w->isGCMarking())
continue;
@ -8476,7 +8479,7 @@ FireOnGarbageCollectionHook(JSContext* cx, JS::dbg::GarbageCollectionEvent::Ptr&
// participated in this GC.
AutoCheckCannotGC noGC;
for (Debugger* dbg : cx->runtime()->debuggerList) {
for (Debugger* dbg = cx->runtime()->debuggerList.getFirst(); dbg; dbg = dbg->getNext()) {
if (dbg->enabled &&
dbg->observedGC(data->majorGCNumber()) &&
dbg->getHook(Debugger::OnGarbageCollection))

View File

@ -93,6 +93,16 @@ class DebuggerWeakMap : private WeakMap<PreBarriered<UnbarrieredKey>, Relocatabl
compartment(cx->compartment())
{ }
~DebuggerWeakMap() {
// If our owning Debugger fails construction after already initializing
// this DebuggerWeakMap, we need to make sure that we aren't in the
// compartment's weak map list anymore. Normally, when we are destroyed
// because the GC finds us unreachable, the GC takes care of removing us
// from this list.
if (WeakMapBase::isInList())
WeakMapBase::removeWeakMapFromList(this);
}
public:
/* Expose those parts of HashMap public interface that are used by Debugger methods. */
@ -200,7 +210,6 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
friend class DebuggerMemory;
friend class SavedStacks;
friend class mozilla::LinkedListElement<Debugger>;
friend class mozilla::LinkedList<Debugger>;
friend bool (::JS_DefineDebuggerObject)(JSContext* cx, JS::HandleObject obj);
friend bool (::JS::dbg::IsDebugger)(JSObject&);
friend bool (::JS::dbg::GetDebuggeeGlobals)(JSContext*, JSObject&, AutoObjectVector&);

View File

@ -1780,7 +1780,10 @@ ComputePlainObjectLayout(ExclusiveContext* cx, Shape* templateShape,
// properties, which will allow us to generate better code if the objects
// have a subtype/supertype relation and are accessed at common sites.
UnboxedLayout* bestExisting = nullptr;
for (UnboxedLayout* existing : cx->compartment()->unboxedLayouts) {
for (UnboxedLayout* existing = cx->compartment()->unboxedLayouts.getFirst();
existing;
existing = existing->getNext())
{
if (PropertiesAreSuperset(properties, existing)) {
if (!bestExisting ||
existing->properties().length() > bestExisting->properties().length())

View File

@ -53,7 +53,12 @@ void
JS::WeakMapPtr<K, V>::destroy()
{
MOZ_ASSERT(initialized());
js_delete(Utils<K, V>::cast(ptr));
auto map = Utils<K, V>::cast(ptr);
// If this destruction happens mid-GC, we might be in the compartment's list
// of known live weakmaps. If we are, remove ourselves before deleting.
if (map->isInList())
WeakMapBase::removeWeakMapFromList(map);
js_delete(map);
ptr = nullptr;
}

View File

@ -299,26 +299,6 @@ private:
LinkedListElement<T> sentinel;
public:
class Iterator {
T* mCurrent;
public:
explicit Iterator(T* aCurrent) : mCurrent(aCurrent) {}
T* operator *() const {
return mCurrent;
}
const Iterator& operator++() {
mCurrent = mCurrent->getNext();
return *this;
}
bool operator!=(Iterator& aOther) const {
return mCurrent != aOther.mCurrent;
}
};
LinkedList() : sentinel(LinkedListElement<T>::NODE_KIND_SENTINEL) { }
LinkedList(LinkedList<T>&& aOther)
@ -403,18 +383,6 @@ public:
}
}
/*
* Allow range-based iteration:
*
* for (MyElementType* elt : myList) { ... }
*/
Iterator begin() {
return Iterator(getFirst());
}
Iterator end() {
return Iterator(nullptr);
}
/*
* Measures the memory consumption of the list excluding |this|. Note that
* it only measures the list elements themselves. If the list elements

View File

@ -1,147 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/Assertions.h"
#include "mozilla/LinkedList.h"
using mozilla::LinkedList;
using mozilla::LinkedListElement;
struct SomeClass : public LinkedListElement<SomeClass> {
unsigned int mValue;
explicit SomeClass(int aValue) : mValue(aValue) {}
void incr() { ++mValue; }
};
struct PrivateClass : private LinkedListElement<PrivateClass> {
friend class LinkedList<PrivateClass>;
friend class LinkedListElement<PrivateClass>;
};
template <size_t N>
static void
CheckListValues(LinkedList<SomeClass>& list, unsigned int (&values)[N])
{
size_t count = 0;
for (SomeClass* x : list) {
MOZ_RELEASE_ASSERT(x->mValue == values[count]);
++count;
}
MOZ_RELEASE_ASSERT(count == N);
}
static void
TestList()
{
LinkedList<SomeClass> list;
SomeClass one(1), two(2), three(3);
MOZ_RELEASE_ASSERT(list.isEmpty());
MOZ_RELEASE_ASSERT(!list.getFirst());
MOZ_RELEASE_ASSERT(!list.getLast());
MOZ_RELEASE_ASSERT(!list.popFirst());
MOZ_RELEASE_ASSERT(!list.popLast());
for (SomeClass* x : list) {
MOZ_RELEASE_ASSERT(x);
MOZ_RELEASE_ASSERT(false);
}
list.insertFront(&one);
{ unsigned int check[] { 1 }; CheckListValues(list, check); }
MOZ_RELEASE_ASSERT(one.isInList());
MOZ_RELEASE_ASSERT(!two.isInList());
MOZ_RELEASE_ASSERT(!three.isInList());
MOZ_RELEASE_ASSERT(!list.isEmpty());
MOZ_RELEASE_ASSERT(list.getFirst()->mValue == 1);
MOZ_RELEASE_ASSERT(list.getLast()->mValue == 1);
list.insertFront(&two);
{ unsigned int check[] { 2, 1 }; CheckListValues(list, check); }
MOZ_RELEASE_ASSERT(list.getFirst()->mValue == 2);
MOZ_RELEASE_ASSERT(list.getLast()->mValue == 1);
list.insertBack(&three);
{ unsigned int check[] { 2, 1, 3 }; CheckListValues(list, check); }
MOZ_RELEASE_ASSERT(list.getFirst()->mValue == 2);
MOZ_RELEASE_ASSERT(list.getLast()->mValue == 3);
one.removeFrom(list);
{ unsigned int check[] { 2, 3 }; CheckListValues(list, check); }
three.setPrevious(&one);
{ unsigned int check[] { 2, 1, 3 }; CheckListValues(list, check); }
three.removeFrom(list);
{ unsigned int check[] { 2, 1 }; CheckListValues(list, check); }
two.setPrevious(&three);
{ unsigned int check[] { 3, 2, 1 }; CheckListValues(list, check); }
three.removeFrom(list);
{ unsigned int check[] { 2, 1 }; CheckListValues(list, check); }
two.setNext(&three);
{ unsigned int check[] { 2, 3, 1 }; CheckListValues(list, check); }
one.remove();
{ unsigned int check[] { 2, 3 }; CheckListValues(list, check); }
two.remove();
{ unsigned int check[] { 3 }; CheckListValues(list, check); }
three.setPrevious(&two);
{ unsigned int check[] { 2, 3 }; CheckListValues(list, check); }
three.remove();
{ unsigned int check[] { 2 }; CheckListValues(list, check); }
two.remove();
list.insertBack(&three);
{ unsigned int check[] { 3 }; CheckListValues(list, check); }
list.insertFront(&two);
{ unsigned int check[] { 2, 3 }; CheckListValues(list, check); }
for (SomeClass* x : list) {
x->incr();
}
MOZ_RELEASE_ASSERT(list.getFirst() == &two);
MOZ_RELEASE_ASSERT(list.getLast() == &three);
MOZ_RELEASE_ASSERT(list.getFirst()->mValue == 3);
MOZ_RELEASE_ASSERT(list.getLast()->mValue == 4);
}
static void
TestPrivate()
{
LinkedList<PrivateClass> list;
PrivateClass one, two;
list.insertBack(&one);
list.insertBack(&two);
size_t count = 0;
for (PrivateClass* p : list) {
MOZ_RELEASE_ASSERT(p, "cannot have null elements in list");
count++;
}
MOZ_RELEASE_ASSERT(count == 2);
}
int
main()
{
TestList();
TestPrivate();
return 0;
}

View File

@ -22,7 +22,6 @@ CppUnitTests([
'TestIntegerPrintfMacros',
'TestIntegerRange',
'TestJSONWriter',
'TestLinkedList',
'TestMacroArgs',
'TestMacroForEach',
'TestMathAlgorithms',