From 8c1a2345bc89029c16f3335796f68628b4055ca8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 31 Jul 2018 10:19:51 +1000 Subject: [PATCH 01/11] Bug 1479631 - Fix media.memory_caches_combined_limit_kb value on Android. r=drno It was accidentally changed from 524288 to 32768 on Android by bug 1448222. This commit changes it back. --HG-- extra : rebase_source : 9181928dccf0cfcd0f70c1c3840d43c378f38ca4 --- modules/libpref/init/StaticPrefList.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/modules/libpref/init/StaticPrefList.h b/modules/libpref/init/StaticPrefList.h index 87c6b9606319..d0948b94892e 100644 --- a/modules/libpref/init/StaticPrefList.h +++ b/modules/libpref/init/StaticPrefList.h @@ -486,17 +486,11 @@ VARCACHE_PREF( // Don't create more memory-backed MediaCaches if their combined size would go // above this absolute size limit. -#ifdef ANDROID -# define PREF_VALUE 32768 // Measured in KiB -#else -# define PREF_VALUE 524288 // Measured in KiB -#endif VARCACHE_PREF( "media.memory_caches_combined_limit_kb", MediaMemoryCachesCombinedLimitKb, - uint32_t, PREF_VALUE + uint32_t, 524288 ) -#undef PREF_VALUE // Don't create more memory-backed MediaCaches if their combined size would go // above this relative size limit (a percentage of physical memory). From e0ec59962ba2413709f86ce400c460466cbc7beb Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Tue, 31 Jul 2018 09:50:08 +0100 Subject: [PATCH 02/11] Bug 1479388 - Move most WeakMap inline method definitions into a separate header r=sfink --- js/src/builtin/WeakMapObject-inl.h | 2 + js/src/builtin/WeakMapObject.h | 2 +- js/src/frontend/SharedContext.h | 1 + js/src/gc/WeakMap.cpp | 2 +- js/src/gc/WeakMap.h | 226 ++++------------------------- js/src/gc/WeakMapPtr.cpp | 2 +- js/src/vm/Debugger-inl.h | 1 + js/src/vm/Debugger.h | 2 + js/src/vm/GlobalObject.h | 1 + 9 files changed, 37 insertions(+), 202 deletions(-) diff --git a/js/src/builtin/WeakMapObject-inl.h b/js/src/builtin/WeakMapObject-inl.h index f249a6bd14e0..be63310c78a2 100644 --- a/js/src/builtin/WeakMapObject-inl.h +++ b/js/src/builtin/WeakMapObject-inl.h @@ -11,6 +11,8 @@ #include "vm/ProxyObject.h" +#include "gc/WeakMap-inl.h" + namespace js { static bool diff --git a/js/src/builtin/WeakMapObject.h b/js/src/builtin/WeakMapObject.h index a3f365f057d3..2a1511926ec1 100644 --- a/js/src/builtin/WeakMapObject.h +++ b/js/src/builtin/WeakMapObject.h @@ -8,7 +8,7 @@ #define builtin_WeakMapObject_h #include "gc/WeakMap.h" -#include "vm/JSObject.h" +#include "vm/NativeObject.h" namespace js { diff --git a/js/src/frontend/SharedContext.h b/js/src/frontend/SharedContext.h index 636ebfd366e7..41f442d1f1e5 100644 --- a/js/src/frontend/SharedContext.h +++ b/js/src/frontend/SharedContext.h @@ -14,6 +14,7 @@ #include "ds/InlineTable.h" #include "frontend/ParseNode.h" #include "frontend/TokenStream.h" +#include "gc/Zone.h" #include "vm/BytecodeUtil.h" #include "vm/EnvironmentObject.h" #include "vm/JSAtom.h" diff --git a/js/src/gc/WeakMap.cpp b/js/src/gc/WeakMap.cpp index 22060f65be78..79e9b426014e 100644 --- a/js/src/gc/WeakMap.cpp +++ b/js/src/gc/WeakMap.cpp @@ -4,7 +4,7 @@ * 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 "gc/WeakMap.h" +#include "gc/WeakMap-inl.h" #include diff --git a/js/src/gc/WeakMap.h b/js/src/gc/WeakMap.h index 15991d968476..1ec7c145c4e0 100644 --- a/js/src/gc/WeakMap.h +++ b/js/src/gc/WeakMap.h @@ -8,20 +8,24 @@ #define gc_WeakMap_h #include "mozilla/LinkedList.h" -#include "mozilla/Move.h" - -#include "jsfriendapi.h" +#include "gc/Barrier.h" #include "gc/DeletePolicy.h" -#include "gc/StoreBuffer.h" #include "js/HashTable.h" -#include "vm/JSObject.h" -#include "vm/Realm.h" + +namespace JS { +class Zone; +} // namespace JS namespace js { class GCMarker; class WeakMapBase; +struct WeakMapTracer; + +namespace gc { +struct WeakMarkable; +} // namespace gc // A subclass template of js::HashMap whose keys and values may be garbage-collected. When // a key is collected, the table entry disappears, dropping its reference to the value. @@ -49,7 +53,7 @@ class WeakMapBase : public mozilla::LinkedListElement WeakMapBase(JSObject* memOf, JS::Zone* zone); virtual ~WeakMapBase(); - Zone* zone() const { return zone_; } + JS::Zone* zone() const { return zone_; } // Garbage collector entry points. @@ -107,17 +111,6 @@ class WeakMapBase : public mozilla::LinkedListElement bool marked; }; -template -static T extractUnbarriered(const WriteBarrieredBase& v) -{ - return v.get(); -} -template -static T* extractUnbarriered(T* v) -{ - return v; -} - template > class WeakMap : public HashMap, @@ -132,16 +125,9 @@ class WeakMap : public HashMap, typedef typename Base::Ptr Ptr; typedef typename Base::AddPtr AddPtr; - explicit WeakMap(JSContext* cx, JSObject* memOf = nullptr) - : Base(cx->zone()), WeakMapBase(memOf, cx->zone()) { } + explicit WeakMap(JSContext* cx, JSObject* memOf = nullptr); - bool init(uint32_t len = 16) { - if (!Base::init(len)) - return false; - zone()->gcWeakMapList().insertFront(this); - marked = JS::IsIncrementalGCInProgress(TlsContext.get()); - return true; - } + bool init(uint32_t len = 16); // Overwritten to add a read barrier to prevent an incorrectly gray value // from escaping the weak map. See the UnmarkGrayTracer::onChild comment in @@ -170,204 +156,46 @@ class WeakMap : public HashMap, // Resolve ambiguity with LinkedListElement<>::remove. using Base::remove; - // Trace a WeakMap entry based on 'markedCell' getting marked, where - // 'origKey' is the key in the weakmap. These will probably be the same, - // but can be different eg when markedCell is a delegate for origKey. - // - // This implementation does not use 'markedCell'; it looks up origKey and - // checks the mark bits on everything it cares about, one of which will be - // markedCell. But a subclass might use it to optimize the liveness check. - void markEntry(GCMarker* marker, gc::Cell* markedCell, JS::GCCellPtr origKey) override - { - MOZ_ASSERT(marked); + void markEntry(GCMarker* marker, gc::Cell* markedCell, JS::GCCellPtr origKey) override; - // If this cast fails, then you're instantiating the WeakMap with a - // Lookup that can't be constructed from a Cell*. The WeakKeyTable - // mechanism is indexed with a GCCellPtr, so that won't work. - Ptr p = Base::lookup(static_cast(origKey.asCell())); - MOZ_ASSERT(p.found()); - - Key key(p->key()); - MOZ_ASSERT((markedCell == extractUnbarriered(key)) || (markedCell == getDelegate(key))); - if (gc::IsMarked(marker->runtime(), &key)) { - TraceEdge(marker, &p->value(), "ephemeron value"); - } else if (keyNeedsMark(key)) { - TraceEdge(marker, &p->value(), "WeakMap ephemeron value"); - TraceEdge(marker, &key, "proxy-preserved WeakMap ephemeron key"); - MOZ_ASSERT(key == p->key()); // No moving - } - key.unsafeSet(nullptr); // Prevent destructor from running barriers. - } - - void trace(JSTracer* trc) override { - MOZ_ASSERT_IF(JS::RuntimeHeapIsBusy(), isInList()); - - TraceNullableEdge(trc, &memberOf, "WeakMap owner"); - - if (!Base::initialized()) - return; - - if (trc->isMarkingTracer()) { - MOZ_ASSERT(trc->weakMapAction() == ExpandWeakMaps); - marked = true; - (void) markIteratively(GCMarker::fromTracer(trc)); - return; - } - - if (trc->weakMapAction() == DoNotTraceWeakMaps) - return; - - // Trace keys only if weakMapAction() says to. - if (trc->weakMapAction() == TraceWeakMapKeysValues) { - for (Enum e(*this); !e.empty(); e.popFront()) - TraceEdge(trc, &e.front().mutableKey(), "WeakMap entry key"); - } - - // Always trace all values (unless weakMapAction() is - // DoNotTraceWeakMaps). - for (Range r = Base::all(); !r.empty(); r.popFront()) - TraceEdge(trc, &r.front().value(), "WeakMap entry value"); - } + void trace(JSTracer* trc) override; protected: - static void addWeakEntry(GCMarker* marker, JS::GCCellPtr key, gc::WeakMarkable markable) - { - Zone* zone = key.asCell()->asTenured().zone(); + static void addWeakEntry(GCMarker* marker, JS::GCCellPtr key, + const gc::WeakMarkable& markable); - auto p = zone->gcWeakKeys().get(key); - if (p) { - gc::WeakEntryVector& weakEntries = p->value; - if (!weakEntries.append(std::move(markable))) - marker->abortLinearWeakMarking(); - } else { - gc::WeakEntryVector weakEntries; - MOZ_ALWAYS_TRUE(weakEntries.append(std::move(markable))); - if (!zone->gcWeakKeys().put(JS::GCCellPtr(key), std::move(weakEntries))) - marker->abortLinearWeakMarking(); - } - } + bool markIteratively(GCMarker* marker) override; - bool markIteratively(GCMarker* marker) override { - MOZ_ASSERT(marked); - - bool markedAny = false; - - for (Enum e(*this); !e.empty(); e.popFront()) { - // If the entry is live, ensure its key and value are marked. - bool keyIsMarked = gc::IsMarked(marker->runtime(), &e.front().mutableKey()); - if (!keyIsMarked && keyNeedsMark(e.front().key())) { - TraceEdge(marker, &e.front().mutableKey(), "proxy-preserved WeakMap entry key"); - keyIsMarked = true; - markedAny = true; - } - - if (keyIsMarked) { - if (!gc::IsMarked(marker->runtime(), &e.front().value())) { - TraceEdge(marker, &e.front().value(), "WeakMap entry value"); - markedAny = true; - } - } else if (marker->isWeakMarkingTracer()) { - // Entry is not yet known to be live. Record this weakmap and - // the lookup key in the list of weak keys. Also record the - // delegate, if any, because marking the delegate also marks - // the entry. - JS::GCCellPtr weakKey(extractUnbarriered(e.front().key())); - gc::WeakMarkable markable(this, weakKey); - addWeakEntry(marker, weakKey, markable); - if (JSObject* delegate = getDelegate(e.front().key())) - addWeakEntry(marker, JS::GCCellPtr(delegate), markable); - } - } - - return markedAny; - } - - JSObject* getDelegate(JSObject* key) const { - JSWeakmapKeyDelegateOp op = key->getClass()->extWeakmapKeyDelegateOp(); - if (!op) - return nullptr; - - JSObject* obj = op(key); - if (!obj) - return nullptr; - - MOZ_ASSERT(obj->runtimeFromMainThread() == zone()->runtimeFromMainThread()); - return obj; - } - - JSObject* getDelegate(JSScript* script) const { - return nullptr; - } - JSObject* getDelegate(LazyScript* script) const { - return nullptr; - } + JSObject* getDelegate(JSObject* key) const; + JSObject* getDelegate(JSScript* script) const; + JSObject* getDelegate(LazyScript* script) const; private: void exposeGCThingToActiveJS(const JS::Value& v) const { JS::ExposeValueToActiveJS(v); } void exposeGCThingToActiveJS(JSObject* obj) const { JS::ExposeObjectToActiveJS(obj); } - bool keyNeedsMark(JSObject* key) const { - JSObject* delegate = getDelegate(key); - /* - * Check if the delegate is marked with any color to properly handle - * gray marking when the key's delegate is black and the map is gray. - */ - return delegate && gc::IsMarkedUnbarriered(zone()->runtimeFromMainThread(), &delegate); - } - - bool keyNeedsMark(JSScript* script) const { - return false; - } - bool keyNeedsMark(LazyScript* script) const { - return false; - } + bool keyNeedsMark(JSObject* key) const; + bool keyNeedsMark(JSScript* script) const; + bool keyNeedsMark(LazyScript* script) const; bool findZoneEdges() override { // This is overridden by ObjectValueMap. return true; } - void sweep() override { - /* Remove all entries whose keys remain unmarked. */ - for (Enum e(*this); !e.empty(); e.popFront()) { - if (gc::IsAboutToBeFinalized(&e.front().mutableKey())) - e.removeFront(); - } - /* - * Once we've swept, all remaining edges should stay within the - * known-live part of the graph. - */ - assertEntriesNotAboutToBeFinalized(); - } + void sweep() override; void finish() override { Base::finish(); } /* memberOf can be nullptr, which means that the map is not part of a JSObject. */ - void traceMappings(WeakMapTracer* tracer) override { - for (Range r = Base::all(); !r.empty(); r.popFront()) { - gc::Cell* key = gc::ToMarkable(r.front().key()); - gc::Cell* value = gc::ToMarkable(r.front().value()); - if (key && value) { - tracer->trace(memberOf, - JS::GCCellPtr(r.front().key().get()), - JS::GCCellPtr(r.front().value().get())); - } - } - } + void traceMappings(WeakMapTracer* tracer) override; protected: - void assertEntriesNotAboutToBeFinalized() { #if DEBUG - for (Range r = Base::all(); !r.empty(); r.popFront()) { - Key k(r.front().key()); - MOZ_ASSERT(!gc::IsAboutToBeFinalized(&k)); - MOZ_ASSERT(!gc::IsAboutToBeFinalized(&r.front().value())); - MOZ_ASSERT(k == r.front().key()); - } + void assertEntriesNotAboutToBeFinalized(); #endif - } }; diff --git a/js/src/gc/WeakMapPtr.cpp b/js/src/gc/WeakMapPtr.cpp index 8e7fa22a1abf..5421a66d22e4 100644 --- a/js/src/gc/WeakMapPtr.cpp +++ b/js/src/gc/WeakMapPtr.cpp @@ -6,7 +6,7 @@ #include "js/WeakMapPtr.h" -#include "gc/WeakMap.h" +#include "gc/WeakMap-inl.h" // // Machinery for the externally-linkable JS::WeakMapPtr, which wraps js::WeakMap diff --git a/js/src/vm/Debugger-inl.h b/js/src/vm/Debugger-inl.h index 7b57908b229b..bc4a338cb3c7 100644 --- a/js/src/vm/Debugger-inl.h +++ b/js/src/vm/Debugger-inl.h @@ -9,6 +9,7 @@ #include "vm/Debugger.h" +#include "gc/WeakMap-inl.h" #include "vm/Stack-inl.h" /* static */ inline bool diff --git a/js/src/vm/Debugger.h b/js/src/vm/Debugger.h index 6eb92f066111..3ecd5ee7b342 100644 --- a/js/src/vm/Debugger.h +++ b/js/src/vm/Debugger.h @@ -219,7 +219,9 @@ class DebuggerWeakMap : private WeakMap, HeapPtr Date: Tue, 31 Jul 2018 09:49:53 +0100 Subject: [PATCH 03/11] Bug 1479215 - Back out spurious files from changeset 162e063abd54. a=backout --HG-- extra : rebase_source : 137b47f944935184bf4c26ba9b6e7f8616a72c42 --- browser/themes/osx/browser.css | 8 ++++++++ browser/themes/shared/toolbarbuttons.inc.css | 6 ++++++ toolkit/themes/osx/global/findBar.css | 6 +++--- toolkit/themes/shared/findBar.inc.css | 6 ------ 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/browser/themes/osx/browser.css b/browser/themes/osx/browser.css index 11330205d607..0135be311a88 100644 --- a/browser/themes/osx/browser.css +++ b/browser/themes/osx/browser.css @@ -213,6 +213,14 @@ %include ../shared/toolbarbutton-icons.inc.css %include ../shared/menupanel.inc.css +/* Override OSX-specific toolkit findbar button styles */ +.findbar-button { + background: none; + box-shadow: none; + border: none; + color: inherit; +} + /* On Mac, native buttons keep their full opacity when they become disabled * and only the glyph or text on top of them becomes less opaque. */ :root:not([customizing]) #back-button[disabled="true"] { diff --git a/browser/themes/shared/toolbarbuttons.inc.css b/browser/themes/shared/toolbarbuttons.inc.css index ccf5e5d871e9..70d590f174b3 100644 --- a/browser/themes/shared/toolbarbuttons.inc.css +++ b/browser/themes/shared/toolbarbuttons.inc.css @@ -91,6 +91,12 @@ toolbar[brighttext] { background-color: Highlight; } +.findbar-button { + -moz-appearance: none; + padding: 0; + color: inherit; +} + toolbar .toolbarbutton-1 { -moz-appearance: none; margin: 0; diff --git a/toolkit/themes/osx/global/findBar.css b/toolkit/themes/osx/global/findBar.css index e63b116f78e7..098c6939d264 100644 --- a/toolkit/themes/osx/global/findBar.css +++ b/toolkit/themes/osx/global/findBar.css @@ -45,10 +45,10 @@ label.findbar-find-fast:-moz-lwtheme { .findbar-button { -moz-appearance: none; + border-width: @roundButtonBorderWidth@; margin-inline-end: 5px; - padding: 0; - color: inherit; - background: none; + padding: 2px 9px; + border-radius: 10000px; } .findbar-find-next:-moz-lwtheme, diff --git a/toolkit/themes/shared/findBar.inc.css b/toolkit/themes/shared/findBar.inc.css index feb512ed9882..c8379560c832 100644 --- a/toolkit/themes/shared/findBar.inc.css +++ b/toolkit/themes/shared/findBar.inc.css @@ -42,12 +42,6 @@ findbar[noanim] { padding: 0 8px; } -.findbar-button { - -moz-appearance: none; - padding: 0; - color: inherit; -} - /* Search field */ .findbar-textbox { From bd8a5ade23425be1dccf7089eb44c23912be508b Mon Sep 17 00:00:00 2001 From: shindli Date: Tue, 31 Jul 2018 11:56:47 +0300 Subject: [PATCH 04/11] Backed out changeset e988c40d5519 (bug 1479388) for spidermonkey bustages in /builds/worker/workspace/build/src/js/src/vm/Debugger-inl on a CLOSED TREE --- js/src/builtin/WeakMapObject-inl.h | 2 - js/src/builtin/WeakMapObject.h | 2 +- js/src/frontend/SharedContext.h | 1 - js/src/gc/WeakMap.cpp | 2 +- js/src/gc/WeakMap.h | 226 +++++++++++++++++++++++++---- js/src/gc/WeakMapPtr.cpp | 2 +- js/src/vm/Debugger-inl.h | 1 - js/src/vm/Debugger.h | 2 - js/src/vm/GlobalObject.h | 1 - 9 files changed, 202 insertions(+), 37 deletions(-) diff --git a/js/src/builtin/WeakMapObject-inl.h b/js/src/builtin/WeakMapObject-inl.h index be63310c78a2..f249a6bd14e0 100644 --- a/js/src/builtin/WeakMapObject-inl.h +++ b/js/src/builtin/WeakMapObject-inl.h @@ -11,8 +11,6 @@ #include "vm/ProxyObject.h" -#include "gc/WeakMap-inl.h" - namespace js { static bool diff --git a/js/src/builtin/WeakMapObject.h b/js/src/builtin/WeakMapObject.h index 2a1511926ec1..a3f365f057d3 100644 --- a/js/src/builtin/WeakMapObject.h +++ b/js/src/builtin/WeakMapObject.h @@ -8,7 +8,7 @@ #define builtin_WeakMapObject_h #include "gc/WeakMap.h" -#include "vm/NativeObject.h" +#include "vm/JSObject.h" namespace js { diff --git a/js/src/frontend/SharedContext.h b/js/src/frontend/SharedContext.h index 41f442d1f1e5..636ebfd366e7 100644 --- a/js/src/frontend/SharedContext.h +++ b/js/src/frontend/SharedContext.h @@ -14,7 +14,6 @@ #include "ds/InlineTable.h" #include "frontend/ParseNode.h" #include "frontend/TokenStream.h" -#include "gc/Zone.h" #include "vm/BytecodeUtil.h" #include "vm/EnvironmentObject.h" #include "vm/JSAtom.h" diff --git a/js/src/gc/WeakMap.cpp b/js/src/gc/WeakMap.cpp index 79e9b426014e..22060f65be78 100644 --- a/js/src/gc/WeakMap.cpp +++ b/js/src/gc/WeakMap.cpp @@ -4,7 +4,7 @@ * 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 "gc/WeakMap-inl.h" +#include "gc/WeakMap.h" #include diff --git a/js/src/gc/WeakMap.h b/js/src/gc/WeakMap.h index 1ec7c145c4e0..15991d968476 100644 --- a/js/src/gc/WeakMap.h +++ b/js/src/gc/WeakMap.h @@ -8,24 +8,20 @@ #define gc_WeakMap_h #include "mozilla/LinkedList.h" +#include "mozilla/Move.h" + +#include "jsfriendapi.h" -#include "gc/Barrier.h" #include "gc/DeletePolicy.h" +#include "gc/StoreBuffer.h" #include "js/HashTable.h" - -namespace JS { -class Zone; -} // namespace JS +#include "vm/JSObject.h" +#include "vm/Realm.h" namespace js { class GCMarker; class WeakMapBase; -struct WeakMapTracer; - -namespace gc { -struct WeakMarkable; -} // namespace gc // A subclass template of js::HashMap whose keys and values may be garbage-collected. When // a key is collected, the table entry disappears, dropping its reference to the value. @@ -53,7 +49,7 @@ class WeakMapBase : public mozilla::LinkedListElement WeakMapBase(JSObject* memOf, JS::Zone* zone); virtual ~WeakMapBase(); - JS::Zone* zone() const { return zone_; } + Zone* zone() const { return zone_; } // Garbage collector entry points. @@ -111,6 +107,17 @@ class WeakMapBase : public mozilla::LinkedListElement bool marked; }; +template +static T extractUnbarriered(const WriteBarrieredBase& v) +{ + return v.get(); +} +template +static T* extractUnbarriered(T* v) +{ + return v; +} + template > class WeakMap : public HashMap, @@ -125,9 +132,16 @@ class WeakMap : public HashMap, typedef typename Base::Ptr Ptr; typedef typename Base::AddPtr AddPtr; - explicit WeakMap(JSContext* cx, JSObject* memOf = nullptr); + explicit WeakMap(JSContext* cx, JSObject* memOf = nullptr) + : Base(cx->zone()), WeakMapBase(memOf, cx->zone()) { } - bool init(uint32_t len = 16); + bool init(uint32_t len = 16) { + if (!Base::init(len)) + return false; + zone()->gcWeakMapList().insertFront(this); + marked = JS::IsIncrementalGCInProgress(TlsContext.get()); + return true; + } // Overwritten to add a read barrier to prevent an incorrectly gray value // from escaping the weak map. See the UnmarkGrayTracer::onChild comment in @@ -156,46 +170,204 @@ class WeakMap : public HashMap, // Resolve ambiguity with LinkedListElement<>::remove. using Base::remove; - void markEntry(GCMarker* marker, gc::Cell* markedCell, JS::GCCellPtr origKey) override; + // Trace a WeakMap entry based on 'markedCell' getting marked, where + // 'origKey' is the key in the weakmap. These will probably be the same, + // but can be different eg when markedCell is a delegate for origKey. + // + // This implementation does not use 'markedCell'; it looks up origKey and + // checks the mark bits on everything it cares about, one of which will be + // markedCell. But a subclass might use it to optimize the liveness check. + void markEntry(GCMarker* marker, gc::Cell* markedCell, JS::GCCellPtr origKey) override + { + MOZ_ASSERT(marked); - void trace(JSTracer* trc) override; + // If this cast fails, then you're instantiating the WeakMap with a + // Lookup that can't be constructed from a Cell*. The WeakKeyTable + // mechanism is indexed with a GCCellPtr, so that won't work. + Ptr p = Base::lookup(static_cast(origKey.asCell())); + MOZ_ASSERT(p.found()); + + Key key(p->key()); + MOZ_ASSERT((markedCell == extractUnbarriered(key)) || (markedCell == getDelegate(key))); + if (gc::IsMarked(marker->runtime(), &key)) { + TraceEdge(marker, &p->value(), "ephemeron value"); + } else if (keyNeedsMark(key)) { + TraceEdge(marker, &p->value(), "WeakMap ephemeron value"); + TraceEdge(marker, &key, "proxy-preserved WeakMap ephemeron key"); + MOZ_ASSERT(key == p->key()); // No moving + } + key.unsafeSet(nullptr); // Prevent destructor from running barriers. + } + + void trace(JSTracer* trc) override { + MOZ_ASSERT_IF(JS::RuntimeHeapIsBusy(), isInList()); + + TraceNullableEdge(trc, &memberOf, "WeakMap owner"); + + if (!Base::initialized()) + return; + + if (trc->isMarkingTracer()) { + MOZ_ASSERT(trc->weakMapAction() == ExpandWeakMaps); + marked = true; + (void) markIteratively(GCMarker::fromTracer(trc)); + return; + } + + if (trc->weakMapAction() == DoNotTraceWeakMaps) + return; + + // Trace keys only if weakMapAction() says to. + if (trc->weakMapAction() == TraceWeakMapKeysValues) { + for (Enum e(*this); !e.empty(); e.popFront()) + TraceEdge(trc, &e.front().mutableKey(), "WeakMap entry key"); + } + + // Always trace all values (unless weakMapAction() is + // DoNotTraceWeakMaps). + for (Range r = Base::all(); !r.empty(); r.popFront()) + TraceEdge(trc, &r.front().value(), "WeakMap entry value"); + } protected: - static void addWeakEntry(GCMarker* marker, JS::GCCellPtr key, - const gc::WeakMarkable& markable); + static void addWeakEntry(GCMarker* marker, JS::GCCellPtr key, gc::WeakMarkable markable) + { + Zone* zone = key.asCell()->asTenured().zone(); - bool markIteratively(GCMarker* marker) override; + auto p = zone->gcWeakKeys().get(key); + if (p) { + gc::WeakEntryVector& weakEntries = p->value; + if (!weakEntries.append(std::move(markable))) + marker->abortLinearWeakMarking(); + } else { + gc::WeakEntryVector weakEntries; + MOZ_ALWAYS_TRUE(weakEntries.append(std::move(markable))); + if (!zone->gcWeakKeys().put(JS::GCCellPtr(key), std::move(weakEntries))) + marker->abortLinearWeakMarking(); + } + } - JSObject* getDelegate(JSObject* key) const; - JSObject* getDelegate(JSScript* script) const; - JSObject* getDelegate(LazyScript* script) const; + bool markIteratively(GCMarker* marker) override { + MOZ_ASSERT(marked); + + bool markedAny = false; + + for (Enum e(*this); !e.empty(); e.popFront()) { + // If the entry is live, ensure its key and value are marked. + bool keyIsMarked = gc::IsMarked(marker->runtime(), &e.front().mutableKey()); + if (!keyIsMarked && keyNeedsMark(e.front().key())) { + TraceEdge(marker, &e.front().mutableKey(), "proxy-preserved WeakMap entry key"); + keyIsMarked = true; + markedAny = true; + } + + if (keyIsMarked) { + if (!gc::IsMarked(marker->runtime(), &e.front().value())) { + TraceEdge(marker, &e.front().value(), "WeakMap entry value"); + markedAny = true; + } + } else if (marker->isWeakMarkingTracer()) { + // Entry is not yet known to be live. Record this weakmap and + // the lookup key in the list of weak keys. Also record the + // delegate, if any, because marking the delegate also marks + // the entry. + JS::GCCellPtr weakKey(extractUnbarriered(e.front().key())); + gc::WeakMarkable markable(this, weakKey); + addWeakEntry(marker, weakKey, markable); + if (JSObject* delegate = getDelegate(e.front().key())) + addWeakEntry(marker, JS::GCCellPtr(delegate), markable); + } + } + + return markedAny; + } + + JSObject* getDelegate(JSObject* key) const { + JSWeakmapKeyDelegateOp op = key->getClass()->extWeakmapKeyDelegateOp(); + if (!op) + return nullptr; + + JSObject* obj = op(key); + if (!obj) + return nullptr; + + MOZ_ASSERT(obj->runtimeFromMainThread() == zone()->runtimeFromMainThread()); + return obj; + } + + JSObject* getDelegate(JSScript* script) const { + return nullptr; + } + JSObject* getDelegate(LazyScript* script) const { + return nullptr; + } private: void exposeGCThingToActiveJS(const JS::Value& v) const { JS::ExposeValueToActiveJS(v); } void exposeGCThingToActiveJS(JSObject* obj) const { JS::ExposeObjectToActiveJS(obj); } - bool keyNeedsMark(JSObject* key) const; - bool keyNeedsMark(JSScript* script) const; - bool keyNeedsMark(LazyScript* script) const; + bool keyNeedsMark(JSObject* key) const { + JSObject* delegate = getDelegate(key); + /* + * Check if the delegate is marked with any color to properly handle + * gray marking when the key's delegate is black and the map is gray. + */ + return delegate && gc::IsMarkedUnbarriered(zone()->runtimeFromMainThread(), &delegate); + } + + bool keyNeedsMark(JSScript* script) const { + return false; + } + bool keyNeedsMark(LazyScript* script) const { + return false; + } bool findZoneEdges() override { // This is overridden by ObjectValueMap. return true; } - void sweep() override; + void sweep() override { + /* Remove all entries whose keys remain unmarked. */ + for (Enum e(*this); !e.empty(); e.popFront()) { + if (gc::IsAboutToBeFinalized(&e.front().mutableKey())) + e.removeFront(); + } + /* + * Once we've swept, all remaining edges should stay within the + * known-live part of the graph. + */ + assertEntriesNotAboutToBeFinalized(); + } void finish() override { Base::finish(); } /* memberOf can be nullptr, which means that the map is not part of a JSObject. */ - void traceMappings(WeakMapTracer* tracer) override; + void traceMappings(WeakMapTracer* tracer) override { + for (Range r = Base::all(); !r.empty(); r.popFront()) { + gc::Cell* key = gc::ToMarkable(r.front().key()); + gc::Cell* value = gc::ToMarkable(r.front().value()); + if (key && value) { + tracer->trace(memberOf, + JS::GCCellPtr(r.front().key().get()), + JS::GCCellPtr(r.front().value().get())); + } + } + } protected: + void assertEntriesNotAboutToBeFinalized() { #if DEBUG - void assertEntriesNotAboutToBeFinalized(); + for (Range r = Base::all(); !r.empty(); r.popFront()) { + Key k(r.front().key()); + MOZ_ASSERT(!gc::IsAboutToBeFinalized(&k)); + MOZ_ASSERT(!gc::IsAboutToBeFinalized(&r.front().value())); + MOZ_ASSERT(k == r.front().key()); + } #endif + } }; diff --git a/js/src/gc/WeakMapPtr.cpp b/js/src/gc/WeakMapPtr.cpp index 5421a66d22e4..8e7fa22a1abf 100644 --- a/js/src/gc/WeakMapPtr.cpp +++ b/js/src/gc/WeakMapPtr.cpp @@ -6,7 +6,7 @@ #include "js/WeakMapPtr.h" -#include "gc/WeakMap-inl.h" +#include "gc/WeakMap.h" // // Machinery for the externally-linkable JS::WeakMapPtr, which wraps js::WeakMap diff --git a/js/src/vm/Debugger-inl.h b/js/src/vm/Debugger-inl.h index bc4a338cb3c7..7b57908b229b 100644 --- a/js/src/vm/Debugger-inl.h +++ b/js/src/vm/Debugger-inl.h @@ -9,7 +9,6 @@ #include "vm/Debugger.h" -#include "gc/WeakMap-inl.h" #include "vm/Stack-inl.h" /* static */ inline bool diff --git a/js/src/vm/Debugger.h b/js/src/vm/Debugger.h index 3ecd5ee7b342..6eb92f066111 100644 --- a/js/src/vm/Debugger.h +++ b/js/src/vm/Debugger.h @@ -219,9 +219,7 @@ class DebuggerWeakMap : private WeakMap, HeapPtr Date: Tue, 31 Jul 2018 10:06:06 +0100 Subject: [PATCH 05/11] Bug 1479388 - Move most WeakMap inline method definitions into a separate header r=sfink --- js/src/builtin/WeakMapObject-inl.h | 2 + js/src/builtin/WeakMapObject.h | 2 +- js/src/frontend/SharedContext.h | 1 + js/src/gc/WeakMap-inl.h | 272 +++++++++++++++++++++++++++++ js/src/gc/WeakMap.cpp | 2 +- js/src/gc/WeakMap.h | 226 +++--------------------- js/src/gc/WeakMapPtr.cpp | 2 +- js/src/vm/Debugger-inl.h | 1 + js/src/vm/Debugger.h | 2 + js/src/vm/GlobalObject.h | 1 + 10 files changed, 309 insertions(+), 202 deletions(-) create mode 100644 js/src/gc/WeakMap-inl.h diff --git a/js/src/builtin/WeakMapObject-inl.h b/js/src/builtin/WeakMapObject-inl.h index f249a6bd14e0..be63310c78a2 100644 --- a/js/src/builtin/WeakMapObject-inl.h +++ b/js/src/builtin/WeakMapObject-inl.h @@ -11,6 +11,8 @@ #include "vm/ProxyObject.h" +#include "gc/WeakMap-inl.h" + namespace js { static bool diff --git a/js/src/builtin/WeakMapObject.h b/js/src/builtin/WeakMapObject.h index a3f365f057d3..2a1511926ec1 100644 --- a/js/src/builtin/WeakMapObject.h +++ b/js/src/builtin/WeakMapObject.h @@ -8,7 +8,7 @@ #define builtin_WeakMapObject_h #include "gc/WeakMap.h" -#include "vm/JSObject.h" +#include "vm/NativeObject.h" namespace js { diff --git a/js/src/frontend/SharedContext.h b/js/src/frontend/SharedContext.h index 636ebfd366e7..41f442d1f1e5 100644 --- a/js/src/frontend/SharedContext.h +++ b/js/src/frontend/SharedContext.h @@ -14,6 +14,7 @@ #include "ds/InlineTable.h" #include "frontend/ParseNode.h" #include "frontend/TokenStream.h" +#include "gc/Zone.h" #include "vm/BytecodeUtil.h" #include "vm/EnvironmentObject.h" #include "vm/JSAtom.h" diff --git a/js/src/gc/WeakMap-inl.h b/js/src/gc/WeakMap-inl.h new file mode 100644 index 000000000000..d7b1ffa11d4b --- /dev/null +++ b/js/src/gc/WeakMap-inl.h @@ -0,0 +1,272 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * 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/. */ + +#ifndef gc_WeakMap_inl_h +#define gc_WeakMap_inl_h + +#include "gc/WeakMap.h" + +#include "gc/Zone.h" +#include "vm/JSContext.h" + +namespace js { + +template +static T extractUnbarriered(const WriteBarrieredBase& v) +{ + return v.get(); +} +template +static T* extractUnbarriered(T* v) +{ + return v; +} + +template +WeakMap::WeakMap(JSContext* cx, JSObject* memOf) + : Base(cx->zone()), WeakMapBase(memOf, cx->zone()) +{} + +template +bool +WeakMap::init(uint32_t len) +{ + if (!Base::init(len)) + return false; + zone()->gcWeakMapList().insertFront(this); + marked = JS::IsIncrementalGCInProgress(TlsContext.get()); + return true; +} + +// Trace a WeakMap entry based on 'markedCell' getting marked, where 'origKey' +// is the key in the weakmap. These will probably be the same, but can be +// different eg when markedCell is a delegate for origKey. +// +// This implementation does not use 'markedCell'; it looks up origKey and checks +// the mark bits on everything it cares about, one of which will be +// markedCell. But a subclass might use it to optimize the liveness check. +template +void +WeakMap::markEntry(GCMarker* marker, gc::Cell* markedCell, JS::GCCellPtr origKey) +{ + MOZ_ASSERT(marked); + + // If this cast fails, then you're instantiating the WeakMap with a + // Lookup that can't be constructed from a Cell*. The WeakKeyTable + // mechanism is indexed with a GCCellPtr, so that won't work. + Ptr p = Base::lookup(static_cast(origKey.asCell())); + MOZ_ASSERT(p.found()); + + K key(p->key()); + MOZ_ASSERT((markedCell == extractUnbarriered(key)) || (markedCell == getDelegate(key))); + if (gc::IsMarked(marker->runtime(), &key)) { + TraceEdge(marker, &p->value(), "ephemeron value"); + } else if (keyNeedsMark(key)) { + TraceEdge(marker, &p->value(), "WeakMap ephemeron value"); + TraceEdge(marker, &key, "proxy-preserved WeakMap ephemeron key"); + MOZ_ASSERT(key == p->key()); // No moving + } + key.unsafeSet(nullptr); // Prevent destructor from running barriers. +} + +template +void +WeakMap::trace(JSTracer* trc) +{ + MOZ_ASSERT_IF(JS::RuntimeHeapIsBusy(), isInList()); + + TraceNullableEdge(trc, &memberOf, "WeakMap owner"); + + if (!Base::initialized()) + return; + + if (trc->isMarkingTracer()) { + MOZ_ASSERT(trc->weakMapAction() == ExpandWeakMaps); + marked = true; + (void) markIteratively(GCMarker::fromTracer(trc)); + return; + } + + if (trc->weakMapAction() == DoNotTraceWeakMaps) + return; + + // Trace keys only if weakMapAction() says to. + if (trc->weakMapAction() == TraceWeakMapKeysValues) { + for (Enum e(*this); !e.empty(); e.popFront()) + TraceEdge(trc, &e.front().mutableKey(), "WeakMap entry key"); + } + + // Always trace all values (unless weakMapAction() is + // DoNotTraceWeakMaps). + for (Range r = Base::all(); !r.empty(); r.popFront()) + TraceEdge(trc, &r.front().value(), "WeakMap entry value"); +} + +template +/* static */ void +WeakMap::addWeakEntry(GCMarker* marker, JS::GCCellPtr key, + const gc::WeakMarkable& markable) +{ + Zone* zone = key.asCell()->asTenured().zone(); + + auto p = zone->gcWeakKeys().get(key); + if (p) { + gc::WeakEntryVector& weakEntries = p->value; + if (!weakEntries.append(markable)) + marker->abortLinearWeakMarking(); + } else { + gc::WeakEntryVector weakEntries; + MOZ_ALWAYS_TRUE(weakEntries.append(markable)); + if (!zone->gcWeakKeys().put(JS::GCCellPtr(key), std::move(weakEntries))) + marker->abortLinearWeakMarking(); + } +} + +template +bool +WeakMap::markIteratively(GCMarker* marker) +{ + MOZ_ASSERT(marked); + + bool markedAny = false; + + for (Enum e(*this); !e.empty(); e.popFront()) { + // If the entry is live, ensure its key and value are marked. + bool keyIsMarked = gc::IsMarked(marker->runtime(), &e.front().mutableKey()); + if (!keyIsMarked && keyNeedsMark(e.front().key())) { + TraceEdge(marker, &e.front().mutableKey(), "proxy-preserved WeakMap entry key"); + keyIsMarked = true; + markedAny = true; + } + + if (keyIsMarked) { + if (!gc::IsMarked(marker->runtime(), &e.front().value())) { + TraceEdge(marker, &e.front().value(), "WeakMap entry value"); + markedAny = true; + } + } else if (marker->isWeakMarkingTracer()) { + // Entry is not yet known to be live. Record this weakmap and + // the lookup key in the list of weak keys. Also record the + // delegate, if any, because marking the delegate also marks + // the entry. + JS::GCCellPtr weakKey(extractUnbarriered(e.front().key())); + gc::WeakMarkable markable(this, weakKey); + addWeakEntry(marker, weakKey, markable); + if (JSObject* delegate = getDelegate(e.front().key())) + addWeakEntry(marker, JS::GCCellPtr(delegate), markable); + } + } + + return markedAny; +} + +template +inline JSObject* +WeakMap::getDelegate(JSObject* key) const +{ + JSWeakmapKeyDelegateOp op = key->getClass()->extWeakmapKeyDelegateOp(); + if (!op) + return nullptr; + + JSObject* obj = op(key); + if (!obj) + return nullptr; + + MOZ_ASSERT(obj->runtimeFromMainThread() == zone()->runtimeFromMainThread()); + return obj; +} + +template +inline JSObject* +WeakMap::getDelegate(JSScript* script) const +{ + return nullptr; +} + +template +inline JSObject* +WeakMap::getDelegate(LazyScript* script) const +{ + return nullptr; +} + +template +inline bool +WeakMap::keyNeedsMark(JSObject* key) const +{ + JSObject* delegate = getDelegate(key); + /* + * Check if the delegate is marked with any color to properly handle + * gray marking when the key's delegate is black and the map is gray. + */ + return delegate && gc::IsMarkedUnbarriered(zone()->runtimeFromMainThread(), &delegate); +} + +template +inline bool +WeakMap::keyNeedsMark(JSScript* script) const +{ + return false; +} + +template +inline bool +WeakMap::keyNeedsMark(LazyScript* script) const +{ + return false; +} + + +template +void +WeakMap::sweep() +{ + /* Remove all entries whose keys remain unmarked. */ + for (Enum e(*this); !e.empty(); e.popFront()) { + if (gc::IsAboutToBeFinalized(&e.front().mutableKey())) + e.removeFront(); + } + +#if DEBUG + // Once we've swept, all remaining edges should stay within the known-live + // part of the graph. + assertEntriesNotAboutToBeFinalized(); +#endif +} + +/* memberOf can be nullptr, which means that the map is not part of a JSObject. */ +template +void +WeakMap::traceMappings(WeakMapTracer* tracer) +{ + for (Range r = Base::all(); !r.empty(); r.popFront()) { + gc::Cell* key = gc::ToMarkable(r.front().key()); + gc::Cell* value = gc::ToMarkable(r.front().value()); + if (key && value) { + tracer->trace(memberOf, + JS::GCCellPtr(r.front().key().get()), + JS::GCCellPtr(r.front().value().get())); + } + } +} + +#if DEBUG +template +void +WeakMap::assertEntriesNotAboutToBeFinalized() +{ + for (Range r = Base::all(); !r.empty(); r.popFront()) { + K k(r.front().key()); + MOZ_ASSERT(!gc::IsAboutToBeFinalized(&k)); + MOZ_ASSERT(!gc::IsAboutToBeFinalized(&r.front().value())); + MOZ_ASSERT(k == r.front().key()); + } +} +#endif + +} /* namespace js */ + +#endif /* gc_WeakMap_inl_h */ diff --git a/js/src/gc/WeakMap.cpp b/js/src/gc/WeakMap.cpp index 22060f65be78..79e9b426014e 100644 --- a/js/src/gc/WeakMap.cpp +++ b/js/src/gc/WeakMap.cpp @@ -4,7 +4,7 @@ * 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 "gc/WeakMap.h" +#include "gc/WeakMap-inl.h" #include diff --git a/js/src/gc/WeakMap.h b/js/src/gc/WeakMap.h index 15991d968476..1ec7c145c4e0 100644 --- a/js/src/gc/WeakMap.h +++ b/js/src/gc/WeakMap.h @@ -8,20 +8,24 @@ #define gc_WeakMap_h #include "mozilla/LinkedList.h" -#include "mozilla/Move.h" - -#include "jsfriendapi.h" +#include "gc/Barrier.h" #include "gc/DeletePolicy.h" -#include "gc/StoreBuffer.h" #include "js/HashTable.h" -#include "vm/JSObject.h" -#include "vm/Realm.h" + +namespace JS { +class Zone; +} // namespace JS namespace js { class GCMarker; class WeakMapBase; +struct WeakMapTracer; + +namespace gc { +struct WeakMarkable; +} // namespace gc // A subclass template of js::HashMap whose keys and values may be garbage-collected. When // a key is collected, the table entry disappears, dropping its reference to the value. @@ -49,7 +53,7 @@ class WeakMapBase : public mozilla::LinkedListElement WeakMapBase(JSObject* memOf, JS::Zone* zone); virtual ~WeakMapBase(); - Zone* zone() const { return zone_; } + JS::Zone* zone() const { return zone_; } // Garbage collector entry points. @@ -107,17 +111,6 @@ class WeakMapBase : public mozilla::LinkedListElement bool marked; }; -template -static T extractUnbarriered(const WriteBarrieredBase& v) -{ - return v.get(); -} -template -static T* extractUnbarriered(T* v) -{ - return v; -} - template > class WeakMap : public HashMap, @@ -132,16 +125,9 @@ class WeakMap : public HashMap, typedef typename Base::Ptr Ptr; typedef typename Base::AddPtr AddPtr; - explicit WeakMap(JSContext* cx, JSObject* memOf = nullptr) - : Base(cx->zone()), WeakMapBase(memOf, cx->zone()) { } + explicit WeakMap(JSContext* cx, JSObject* memOf = nullptr); - bool init(uint32_t len = 16) { - if (!Base::init(len)) - return false; - zone()->gcWeakMapList().insertFront(this); - marked = JS::IsIncrementalGCInProgress(TlsContext.get()); - return true; - } + bool init(uint32_t len = 16); // Overwritten to add a read barrier to prevent an incorrectly gray value // from escaping the weak map. See the UnmarkGrayTracer::onChild comment in @@ -170,204 +156,46 @@ class WeakMap : public HashMap, // Resolve ambiguity with LinkedListElement<>::remove. using Base::remove; - // Trace a WeakMap entry based on 'markedCell' getting marked, where - // 'origKey' is the key in the weakmap. These will probably be the same, - // but can be different eg when markedCell is a delegate for origKey. - // - // This implementation does not use 'markedCell'; it looks up origKey and - // checks the mark bits on everything it cares about, one of which will be - // markedCell. But a subclass might use it to optimize the liveness check. - void markEntry(GCMarker* marker, gc::Cell* markedCell, JS::GCCellPtr origKey) override - { - MOZ_ASSERT(marked); + void markEntry(GCMarker* marker, gc::Cell* markedCell, JS::GCCellPtr origKey) override; - // If this cast fails, then you're instantiating the WeakMap with a - // Lookup that can't be constructed from a Cell*. The WeakKeyTable - // mechanism is indexed with a GCCellPtr, so that won't work. - Ptr p = Base::lookup(static_cast(origKey.asCell())); - MOZ_ASSERT(p.found()); - - Key key(p->key()); - MOZ_ASSERT((markedCell == extractUnbarriered(key)) || (markedCell == getDelegate(key))); - if (gc::IsMarked(marker->runtime(), &key)) { - TraceEdge(marker, &p->value(), "ephemeron value"); - } else if (keyNeedsMark(key)) { - TraceEdge(marker, &p->value(), "WeakMap ephemeron value"); - TraceEdge(marker, &key, "proxy-preserved WeakMap ephemeron key"); - MOZ_ASSERT(key == p->key()); // No moving - } - key.unsafeSet(nullptr); // Prevent destructor from running barriers. - } - - void trace(JSTracer* trc) override { - MOZ_ASSERT_IF(JS::RuntimeHeapIsBusy(), isInList()); - - TraceNullableEdge(trc, &memberOf, "WeakMap owner"); - - if (!Base::initialized()) - return; - - if (trc->isMarkingTracer()) { - MOZ_ASSERT(trc->weakMapAction() == ExpandWeakMaps); - marked = true; - (void) markIteratively(GCMarker::fromTracer(trc)); - return; - } - - if (trc->weakMapAction() == DoNotTraceWeakMaps) - return; - - // Trace keys only if weakMapAction() says to. - if (trc->weakMapAction() == TraceWeakMapKeysValues) { - for (Enum e(*this); !e.empty(); e.popFront()) - TraceEdge(trc, &e.front().mutableKey(), "WeakMap entry key"); - } - - // Always trace all values (unless weakMapAction() is - // DoNotTraceWeakMaps). - for (Range r = Base::all(); !r.empty(); r.popFront()) - TraceEdge(trc, &r.front().value(), "WeakMap entry value"); - } + void trace(JSTracer* trc) override; protected: - static void addWeakEntry(GCMarker* marker, JS::GCCellPtr key, gc::WeakMarkable markable) - { - Zone* zone = key.asCell()->asTenured().zone(); + static void addWeakEntry(GCMarker* marker, JS::GCCellPtr key, + const gc::WeakMarkable& markable); - auto p = zone->gcWeakKeys().get(key); - if (p) { - gc::WeakEntryVector& weakEntries = p->value; - if (!weakEntries.append(std::move(markable))) - marker->abortLinearWeakMarking(); - } else { - gc::WeakEntryVector weakEntries; - MOZ_ALWAYS_TRUE(weakEntries.append(std::move(markable))); - if (!zone->gcWeakKeys().put(JS::GCCellPtr(key), std::move(weakEntries))) - marker->abortLinearWeakMarking(); - } - } + bool markIteratively(GCMarker* marker) override; - bool markIteratively(GCMarker* marker) override { - MOZ_ASSERT(marked); - - bool markedAny = false; - - for (Enum e(*this); !e.empty(); e.popFront()) { - // If the entry is live, ensure its key and value are marked. - bool keyIsMarked = gc::IsMarked(marker->runtime(), &e.front().mutableKey()); - if (!keyIsMarked && keyNeedsMark(e.front().key())) { - TraceEdge(marker, &e.front().mutableKey(), "proxy-preserved WeakMap entry key"); - keyIsMarked = true; - markedAny = true; - } - - if (keyIsMarked) { - if (!gc::IsMarked(marker->runtime(), &e.front().value())) { - TraceEdge(marker, &e.front().value(), "WeakMap entry value"); - markedAny = true; - } - } else if (marker->isWeakMarkingTracer()) { - // Entry is not yet known to be live. Record this weakmap and - // the lookup key in the list of weak keys. Also record the - // delegate, if any, because marking the delegate also marks - // the entry. - JS::GCCellPtr weakKey(extractUnbarriered(e.front().key())); - gc::WeakMarkable markable(this, weakKey); - addWeakEntry(marker, weakKey, markable); - if (JSObject* delegate = getDelegate(e.front().key())) - addWeakEntry(marker, JS::GCCellPtr(delegate), markable); - } - } - - return markedAny; - } - - JSObject* getDelegate(JSObject* key) const { - JSWeakmapKeyDelegateOp op = key->getClass()->extWeakmapKeyDelegateOp(); - if (!op) - return nullptr; - - JSObject* obj = op(key); - if (!obj) - return nullptr; - - MOZ_ASSERT(obj->runtimeFromMainThread() == zone()->runtimeFromMainThread()); - return obj; - } - - JSObject* getDelegate(JSScript* script) const { - return nullptr; - } - JSObject* getDelegate(LazyScript* script) const { - return nullptr; - } + JSObject* getDelegate(JSObject* key) const; + JSObject* getDelegate(JSScript* script) const; + JSObject* getDelegate(LazyScript* script) const; private: void exposeGCThingToActiveJS(const JS::Value& v) const { JS::ExposeValueToActiveJS(v); } void exposeGCThingToActiveJS(JSObject* obj) const { JS::ExposeObjectToActiveJS(obj); } - bool keyNeedsMark(JSObject* key) const { - JSObject* delegate = getDelegate(key); - /* - * Check if the delegate is marked with any color to properly handle - * gray marking when the key's delegate is black and the map is gray. - */ - return delegate && gc::IsMarkedUnbarriered(zone()->runtimeFromMainThread(), &delegate); - } - - bool keyNeedsMark(JSScript* script) const { - return false; - } - bool keyNeedsMark(LazyScript* script) const { - return false; - } + bool keyNeedsMark(JSObject* key) const; + bool keyNeedsMark(JSScript* script) const; + bool keyNeedsMark(LazyScript* script) const; bool findZoneEdges() override { // This is overridden by ObjectValueMap. return true; } - void sweep() override { - /* Remove all entries whose keys remain unmarked. */ - for (Enum e(*this); !e.empty(); e.popFront()) { - if (gc::IsAboutToBeFinalized(&e.front().mutableKey())) - e.removeFront(); - } - /* - * Once we've swept, all remaining edges should stay within the - * known-live part of the graph. - */ - assertEntriesNotAboutToBeFinalized(); - } + void sweep() override; void finish() override { Base::finish(); } /* memberOf can be nullptr, which means that the map is not part of a JSObject. */ - void traceMappings(WeakMapTracer* tracer) override { - for (Range r = Base::all(); !r.empty(); r.popFront()) { - gc::Cell* key = gc::ToMarkable(r.front().key()); - gc::Cell* value = gc::ToMarkable(r.front().value()); - if (key && value) { - tracer->trace(memberOf, - JS::GCCellPtr(r.front().key().get()), - JS::GCCellPtr(r.front().value().get())); - } - } - } + void traceMappings(WeakMapTracer* tracer) override; protected: - void assertEntriesNotAboutToBeFinalized() { #if DEBUG - for (Range r = Base::all(); !r.empty(); r.popFront()) { - Key k(r.front().key()); - MOZ_ASSERT(!gc::IsAboutToBeFinalized(&k)); - MOZ_ASSERT(!gc::IsAboutToBeFinalized(&r.front().value())); - MOZ_ASSERT(k == r.front().key()); - } + void assertEntriesNotAboutToBeFinalized(); #endif - } }; diff --git a/js/src/gc/WeakMapPtr.cpp b/js/src/gc/WeakMapPtr.cpp index 8e7fa22a1abf..5421a66d22e4 100644 --- a/js/src/gc/WeakMapPtr.cpp +++ b/js/src/gc/WeakMapPtr.cpp @@ -6,7 +6,7 @@ #include "js/WeakMapPtr.h" -#include "gc/WeakMap.h" +#include "gc/WeakMap-inl.h" // // Machinery for the externally-linkable JS::WeakMapPtr, which wraps js::WeakMap diff --git a/js/src/vm/Debugger-inl.h b/js/src/vm/Debugger-inl.h index 7b57908b229b..bc4a338cb3c7 100644 --- a/js/src/vm/Debugger-inl.h +++ b/js/src/vm/Debugger-inl.h @@ -9,6 +9,7 @@ #include "vm/Debugger.h" +#include "gc/WeakMap-inl.h" #include "vm/Stack-inl.h" /* static */ inline bool diff --git a/js/src/vm/Debugger.h b/js/src/vm/Debugger.h index 6eb92f066111..3ecd5ee7b342 100644 --- a/js/src/vm/Debugger.h +++ b/js/src/vm/Debugger.h @@ -219,7 +219,9 @@ class DebuggerWeakMap : private WeakMap, HeapPtr Date: Tue, 31 Jul 2018 11:32:53 +0200 Subject: [PATCH 06/11] Bug 1479681: Fix the loop in nsTransitionManager dealing with stopping `all` transitions. r=hiro The loop was mutating the nsCSSPropertyID used to guard the exit, which is obviously wrong. This branch is pretty rarely taken, since people don't usually specify `all` as a transition property other than the first, for which case we take the fast path with `checkProperties = false`. Our test-suite failed to catch this. Added a crashtest that hangs without this patch. The reason bug 1478990 regressed this is because it changed the order of nsCSSPropertyID so that `p` actually went backwards causing the infinite loop, but the bug was introduced (by me, whoops) in bug 1309752. Differential Revision: https://phabricator.services.mozilla.com/D2552 MozReview-Commit-ID: Ii3D1FaZ31R --- layout/style/crashtests/1479681.html | 14 ++++++++++++++ layout/style/crashtests/crashtests.list | 1 + layout/style/nsTransitionManager.cpp | 3 +-- 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 layout/style/crashtests/1479681.html diff --git a/layout/style/crashtests/1479681.html b/layout/style/crashtests/1479681.html new file mode 100644 index 000000000000..1d4c6c612dab --- /dev/null +++ b/layout/style/crashtests/1479681.html @@ -0,0 +1,14 @@ + + +
Should turn Green
+ diff --git a/layout/style/crashtests/crashtests.list b/layout/style/crashtests/crashtests.list index 2542e0f6ac34..ef4e51d4474c 100644 --- a/layout/style/crashtests/crashtests.list +++ b/layout/style/crashtests/crashtests.list @@ -291,3 +291,4 @@ load 1457985.html pref(dom.webcomponents.shadowdom.enabled,true) load 1468640.html load 1469076.html load 1475003.html +load 1479681.html diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp index 1d06ddd4073c..43f280701aa6 100755 --- a/layout/style/nsTransitionManager.cpp +++ b/layout/style/nsTransitionManager.cpp @@ -544,8 +544,7 @@ nsTransitionManager::DoUpdateTransitions( for (nsCSSPropertyID p = nsCSSPropertyID(0); p < eCSSProperty_COUNT_no_shorthands; p = nsCSSPropertyID(p + 1)) { - p = nsCSSProps::Physicalize(p, aNewStyle); - allTransitionProperties.AddProperty(p); + allTransitionProperties.AddProperty(nsCSSProps::Physicalize(p, aNewStyle)); } } else if (nsCSSProps::IsShorthand(property)) { CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES( From 29968139639f1444e320496a0245c3881a8bbae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 30 Jul 2018 17:32:17 +0200 Subject: [PATCH 07/11] Bug 1479450: Implement nsCSSProps::LookupProperty using Rust. r=xidorn Always assume allowed-for-all-content. There are a couple callers which weren't doing that: * A unit test -> removed. * ComputeAnimationDistance: Used for testing (in transitions_per_property), and for the animation inspector. The animation inspector shouldn't show non-enabled properties. The transitions_per_property test already relies on getComputedStyle stuff which only uses eForAllContent. * GetCSSImageURLs: I added this API for the context menu page and such. It doesn't rely on non-enabled-everywhere properties, it was only using eInChrome because it was a ChromeOnly API, but it doesn't really need this. Differential Revision: https://phabricator.services.mozilla.com/D2514 MozReview-Commit-ID: 4VOi5Su3Bos --- dom/base/nsDOMWindowUtils.cpp | 9 +-- dom/smil/nsSMILCompositor.cpp | 3 +- dom/svg/nsSVGElement.cpp | 3 +- editor/libeditor/CSSEditUtils.cpp | 3 +- layout/inspector/InspectorUtils.cpp | 3 +- layout/style/ServoBindingList.h | 3 + layout/style/nsCSSProps.cpp | 34 ---------- layout/style/nsCSSProps.h | 19 +++++- layout/style/nsComputedDOMStyle.cpp | 8 +-- layout/style/nsDOMCSSDeclaration.cpp | 3 +- layout/style/test/TestCSSPropertyLookup.cpp | 65 ------------------- .../style/properties/properties.mako.rs | 12 ++++ servo/ports/geckolib/glue.rs | 11 ++++ 13 files changed, 53 insertions(+), 123 deletions(-) diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index 025fb0378027..5facf2945154 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -2707,10 +2707,8 @@ nsDOMWindowUtils::ComputeAnimationDistance(Element* aElement, { NS_ENSURE_ARG_POINTER(aElement); - nsCSSPropertyID property = - nsCSSProps::LookupProperty(aProperty, CSSEnabledState::eIgnoreEnabledState); - if (property == eCSSProperty_UNKNOWN || - nsCSSProps::IsShorthand(property)) { + nsCSSPropertyID property = nsCSSProps::LookupProperty(aProperty); + if (property == eCSSProperty_UNKNOWN || nsCSSProps::IsShorthand(property)) { return NS_ERROR_ILLEGAL_VALUE; } @@ -2737,8 +2735,7 @@ nsDOMWindowUtils::GetUnanimatedComputedStyle(Element* aElement, return NS_ERROR_INVALID_ARG; } - nsCSSPropertyID propertyID = - nsCSSProps::LookupProperty(aProperty, CSSEnabledState::eForAllContent); + nsCSSPropertyID propertyID = nsCSSProps::LookupProperty(aProperty); if (propertyID == eCSSProperty_UNKNOWN || nsCSSProps::IsShorthand(propertyID)) { return NS_ERROR_INVALID_ARG; diff --git a/dom/smil/nsSMILCompositor.cpp b/dom/smil/nsSMILCompositor.cpp index 72943800028f..67fa6cd1fba1 100644 --- a/dom/smil/nsSMILCompositor.cpp +++ b/dom/smil/nsSMILCompositor.cpp @@ -155,8 +155,7 @@ nsSMILCompositor::GetCSSPropertyToAnimate() const } nsCSSPropertyID propID = - nsCSSProps::LookupProperty(nsDependentAtomString(mKey.mAttributeName), - CSSEnabledState::eForAllContent); + nsCSSProps::LookupProperty(nsDependentAtomString(mKey.mAttributeName)); if (!nsSMILCSSProperty::IsPropertyAnimatable(propID)) { return eCSSProperty_UNKNOWN; diff --git a/dom/svg/nsSVGElement.cpp b/dom/svg/nsSVGElement.cpp index 330f512ab568..7d91f77b5e78 100644 --- a/dom/svg/nsSVGElement.cpp +++ b/dom/svg/nsSVGElement.cpp @@ -1192,8 +1192,7 @@ MappedAttrParser::ParseMappedAttrValue(nsAtom* aMappedAttrName, // Get the nsCSSPropertyID ID for our mapped attribute. nsCSSPropertyID propertyID = - nsCSSProps::LookupProperty(nsDependentAtomString(aMappedAttrName), - CSSEnabledState::eForAllContent); + nsCSSProps::LookupProperty(nsDependentAtomString(aMappedAttrName)); if (propertyID != eCSSProperty_UNKNOWN) { bool changed = false; // outparam for ParseProperty. NS_ConvertUTF16toUTF8 value(aMappedAttrValue); diff --git a/editor/libeditor/CSSEditUtils.cpp b/editor/libeditor/CSSEditUtils.cpp index 5b23a8a443e7..844f3ebd7869 100644 --- a/editor/libeditor/CSSEditUtils.cpp +++ b/editor/libeditor/CSSEditUtils.cpp @@ -538,8 +538,7 @@ CSSEditUtils::GetCSSInlinePropertyBase(nsINode* aNode, } nsCSSPropertyID prop = - nsCSSProps::LookupProperty(nsDependentAtomString(aProperty), - CSSEnabledState::eForAllContent); + nsCSSProps::LookupProperty(nsDependentAtomString(aProperty)); MOZ_ASSERT(prop != eCSSProperty_UNKNOWN); decl->GetPropertyValueByID(prop, aValue); diff --git a/layout/inspector/InspectorUtils.cpp b/layout/inspector/InspectorUtils.cpp index d96ad24ffe1b..589b5c8e1263 100644 --- a/layout/inspector/InspectorUtils.cpp +++ b/layout/inspector/InspectorUtils.cpp @@ -418,8 +418,7 @@ InspectorUtils::GetSubpropertiesForCSSProperty(GlobalObject& aGlobal, nsTArray& aResult, ErrorResult& aRv) { - nsCSSPropertyID propertyID = - nsCSSProps::LookupProperty(aProperty, CSSEnabledState::eForAllContent); + nsCSSPropertyID propertyID = nsCSSProps::LookupProperty(aProperty); if (propertyID == eCSSProperty_UNKNOWN) { aRv.Throw(NS_ERROR_FAILURE); diff --git a/layout/style/ServoBindingList.h b/layout/style/ServoBindingList.h index 0d65bab3f431..ade64734b71e 100644 --- a/layout/style/ServoBindingList.h +++ b/layout/style/ServoBindingList.h @@ -889,6 +889,9 @@ SERVO_BINDING_FUNC(Servo_ResolveLogicalProperty, nsCSSPropertyID, nsCSSPropertyID, ComputedStyleBorrowed); +SERVO_BINDING_FUNC(Servo_Property_LookupEnabledForAllContent, + nsCSSPropertyID, + const nsACString* name); SERVO_BINDING_FUNC(Servo_Property_IsShorthand, bool, const nsACString* name, bool* found); SERVO_BINDING_FUNC(Servo_Property_IsInherited, bool, diff --git a/layout/style/nsCSSProps.cpp b/layout/style/nsCSSProps.cpp index b0b0ba078075..553bde3ec32b 100644 --- a/layout/style/nsCSSProps.cpp +++ b/layout/style/nsCSSProps.cpp @@ -162,40 +162,6 @@ nsCSSProps::IsCustomPropertyName(const nsAString& aProperty) StringBeginsWith(aProperty, NS_LITERAL_STRING("--")); } -nsCSSPropertyID -nsCSSProps::LookupProperty(const nsAString& aProperty, EnabledState aEnabled) -{ - if (IsCustomPropertyName(aProperty)) { - return eCSSPropertyExtra_variable; - } - - // This is faster than converting and calling - // LookupProperty(nsACString&). The table will do its own - // converting and avoid a PromiseFlatCString() call. - MOZ_ASSERT(gPropertyTable, "no lookup table, needs addref"); - nsCSSPropertyID res = nsCSSPropertyID(gPropertyTable->Lookup(aProperty)); - if (MOZ_LIKELY(res < eCSSProperty_COUNT)) { - if (res != eCSSProperty_UNKNOWN && !IsEnabled(res, aEnabled)) { - res = eCSSProperty_UNKNOWN; - } - return res; - } - MOZ_ASSERT(eCSSAliasCount != 0, - "'res' must be an alias at this point so we better have some!"); - // We intentionally don't support CSSEnabledState::eInUASheets or - // CSSEnabledState::eInChrome for aliases yet because it's unlikely - // there will be a need for it. - if (IsEnabled(res) || aEnabled == CSSEnabledState::eIgnoreEnabledState) { - res = gAliases[res - eCSSProperty_COUNT]; - MOZ_ASSERT(0 <= res && res < eCSSProperty_COUNT, - "aliases must not point to other aliases"); - if (IsEnabled(res) || aEnabled == CSSEnabledState::eIgnoreEnabledState) { - return res; - } - } - return eCSSProperty_UNKNOWN; -} - nsCSSPropertyID nsCSSProps::LookupPropertyByIDLName(const nsACString& aPropertyIDLName, EnabledState aEnabled) diff --git a/layout/style/nsCSSProps.h b/layout/style/nsCSSProps.h index cb6d8ed2fb15..c9cb40176885 100644 --- a/layout/style/nsCSSProps.h +++ b/layout/style/nsCSSProps.h @@ -14,7 +14,7 @@ #include #include -#include "nsStringFwd.h" +#include "nsString.h" #include "nsCSSPropertyID.h" #include "nsStyleStructFwd.h" #include "nsCSSKeywords.h" @@ -36,6 +36,7 @@ class ComputedStyle; extern "C" { nsCSSPropertyID Servo_ResolveLogicalProperty(nsCSSPropertyID, const mozilla::ComputedStyle*); + nsCSSPropertyID Servo_Property_LookupEnabledForAllContent(const nsACString*); } struct nsCSSKTableEntry @@ -80,8 +81,20 @@ public: // Looks up the property with name aProperty and returns its corresponding // nsCSSPropertyID value. If aProperty is the name of a custom property, // then eCSSPropertyExtra_variable will be returned. - static nsCSSPropertyID LookupProperty(const nsAString& aProperty, - EnabledState aEnabled); + // + // This only returns properties enabled for all content, and resolves aliases + // to return the aliased property. + static nsCSSPropertyID LookupProperty(const nsACString& aProperty) + { + return Servo_Property_LookupEnabledForAllContent(&aProperty); + } + + static nsCSSPropertyID LookupProperty(const nsAString& aProperty) + { + NS_ConvertUTF16toUTF8 utf8(aProperty); + return LookupProperty(utf8); + } + // As above, but looked up using a property's IDL name. // eCSSPropertyExtra_variable won't be returned from these methods. static nsCSSPropertyID LookupPropertyByIDLName( diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index 06f18752b396..1a454afe9bd7 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -437,8 +437,7 @@ nsComputedDOMStyle::GetPropertyValue(const nsAString& aPropertyName, { aReturn.Truncate(); - nsCSSPropertyID prop = - nsCSSProps::LookupProperty(aPropertyName, CSSEnabledState::eForAllContent); + nsCSSPropertyID prop = nsCSSProps::LookupProperty(aPropertyName); const ComputedStyleMap::Entry* entry = nullptr; if (prop != eCSSPropertyExtra_variable) { @@ -719,7 +718,7 @@ CollectImageURLsForProperty(nsCSSPropertyID aProp, nsTArray& aURLs) { if (nsCSSProps::IsShorthand(aProp)) { - CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aProp, CSSEnabledState::eInChrome) { + CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aProp, CSSEnabledState::eForAllContent) { CollectImageURLsForProperty(*p, aStyle, aURLs); } return; @@ -761,8 +760,7 @@ nsComputedDOMStyle::GetCSSImageURLs(const nsAString& aPropertyName, nsTArray& aImageURLs, mozilla::ErrorResult& aRv) { - nsCSSPropertyID prop = - nsCSSProps::LookupProperty(aPropertyName, CSSEnabledState::eInChrome); + nsCSSPropertyID prop = nsCSSProps::LookupProperty(aPropertyName); if (prop == eCSSProperty_UNKNOWN) { aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR); return; diff --git a/layout/style/nsDOMCSSDeclaration.cpp b/layout/style/nsDOMCSSDeclaration.cpp index 5460ddd093a6..6d9a771be25d 100644 --- a/layout/style/nsDOMCSSDeclaration.cpp +++ b/layout/style/nsDOMCSSDeclaration.cpp @@ -209,8 +209,7 @@ nsDOMCSSDeclaration::SetProperty(const nsAString& aPropertyName, } // In the common (and fast) cases we can use the property id - nsCSSPropertyID propID = - nsCSSProps::LookupProperty(aPropertyName, CSSEnabledState::eForAllContent); + nsCSSPropertyID propID = nsCSSProps::LookupProperty(aPropertyName); if (propID == eCSSProperty_UNKNOWN) { return NS_OK; } diff --git a/layout/style/test/TestCSSPropertyLookup.cpp b/layout/style/test/TestCSSPropertyLookup.cpp index 01afa78cbdd4..2fdfc2524f3d 100644 --- a/layout/style/test/TestCSSPropertyLookup.cpp +++ b/layout/style/test/TestCSSPropertyLookup.cpp @@ -21,71 +21,6 @@ static const char* const kJunkNames[] = { "#@$&@#*@*$@$#" }; -static bool -TestProps() -{ - bool success = true; - nsCSSPropertyID id; - nsCSSPropertyID index; - - // Everything appears to assert if we don't do this first... - nsCSSProps::AddRefTable(); - - // First make sure we can find all of the tags that are supposed to - // be in the table. Futz with the case to make sure any case will - // work - extern const char* const kCSSRawProperties[]; - const char*const* et = &kCSSRawProperties[0]; - const char*const* end = &kCSSRawProperties[eCSSProperty_COUNT]; - index = eCSSProperty_UNKNOWN; - while (et < end) { - char tagName[100]; - PL_strcpy(tagName, *et); - index = nsCSSPropertyID(int32_t(index) + 1); - - id = nsCSSProps::LookupProperty(nsCString(tagName), - CSSEnabledState::eIgnoreEnabledState); - if (id == eCSSProperty_UNKNOWN) { - printf("bug: can't find '%s'\n", tagName); - success = false; - } - if (id != index) { - printf("bug: name='%s' id=%d index=%d\n", tagName, id, index); - success = false; - } - - // fiddle with the case to make sure we can still find it - if (('a' <= tagName[0]) && (tagName[0] <= 'z')) { - tagName[0] = tagName[0] - 32; - } - id = nsCSSProps::LookupProperty(NS_ConvertASCIItoUTF16(tagName), - CSSEnabledState::eIgnoreEnabledState); - if (id < 0) { - printf("bug: can't find '%s'\n", tagName); - success = false; - } - if (index != id) { - printf("bug: name='%s' id=%d index=%d\n", tagName, id, index); - success = false; - } - et++; - } - - // Now make sure we don't find some garbage - for (int i = 0; i < (int) (sizeof(kJunkNames) / sizeof(const char*)); i++) { - const char* const tag = kJunkNames[i]; - id = nsCSSProps::LookupProperty(nsAutoCString(tag), - CSSEnabledState::eIgnoreEnabledState); - if (id >= 0) { - printf("bug: found '%s'\n", tag ? tag : "(null)"); - success = false; - } - } - - nsCSSProps::ReleaseTable(); - return success; -} - bool TestKeywords() { diff --git a/servo/components/style/properties/properties.mako.rs b/servo/components/style/properties/properties.mako.rs index 5e341e82d6da..27458cf67c4f 100644 --- a/servo/components/style/properties/properties.mako.rs +++ b/servo/components/style/properties/properties.mako.rs @@ -1870,6 +1870,18 @@ impl PropertyId { id.enabled_for_all_content() } + /// Converts this PropertyId in nsCSSPropertyID, resolving aliases to the + /// resolved property, and returning eCSSPropertyExtra_variable for custom + /// properties. + #[cfg(feature = "gecko")] + #[inline] + pub fn to_nscsspropertyid_resolving_aliases(&self) -> nsCSSPropertyID { + match self.non_custom_non_alias_id() { + Some(id) => id.to_nscsspropertyid(), + None => nsCSSPropertyID::eCSSPropertyExtra_variable, + } + } + fn allowed_in(&self, context: &ParserContext) -> bool { let id = match self.non_custom_id() { // Custom properties are allowed everywhere diff --git a/servo/ports/geckolib/glue.rs b/servo/ports/geckolib/glue.rs index 6f4915b52d9a..2d6256dc6583 100644 --- a/servo/ports/geckolib/glue.rs +++ b/servo/ports/geckolib/glue.rs @@ -925,6 +925,17 @@ pub extern "C" fn Servo_ResolveLogicalProperty( longhand.to_physical(style.writing_mode).to_nscsspropertyid() } + +#[no_mangle] +pub unsafe extern "C" fn Servo_Property_LookupEnabledForAllContent( + prop: *const nsACString, +) -> nsCSSPropertyID { + match PropertyId::parse_enabled_for_all_content((*prop).as_str_unchecked()) { + Ok(p) => p.to_nscsspropertyid_resolving_aliases(), + Err(..) => nsCSSPropertyID::eCSSProperty_UNKNOWN, + } +} + macro_rules! parse_enabled_property_name { ($prop_name:ident, $found:ident, $default:expr) => {{ let prop_name = $prop_name.as_ref().unwrap().as_str_unchecked(); From 6c81e2e79ce6c0a66cb552e7517f2941732b1c37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 30 Jul 2018 18:04:05 +0200 Subject: [PATCH 08/11] Bug 1479450: Convert GetStringValue to use Servo. r=xidorn And remove gPropertyTable / kCSSRawProperties while at it. Differential Revision: https://phabricator.services.mozilla.com/D2516 MozReview-Commit-ID: 8U87BcBkrJF --- dom/animation/KeyframeEffect.cpp | 2 +- layout/inspector/InspectorUtils.cpp | 9 ++-- layout/style/ServoBindingList.h | 4 ++ layout/style/nsCSSProps.cpp | 47 ------------------- layout/style/nsCSSProps.h | 11 ++++- .../style/properties/properties.mako.rs | 5 +- servo/ports/geckolib/glue.rs | 20 +++++++- 7 files changed, 40 insertions(+), 58 deletions(-) diff --git a/dom/animation/KeyframeEffect.cpp b/dom/animation/KeyframeEffect.cpp index 5baa942657fd..68be46b833f1 100644 --- a/dom/animation/KeyframeEffect.cpp +++ b/dom/animation/KeyframeEffect.cpp @@ -818,7 +818,7 @@ void DumpAnimationProperties(nsTArray& aAnimationProperties) { for (auto& p : aAnimationProperties) { - printf("%s\n", nsCSSProps::GetStringValue(p.mProperty).get()); + printf("%s\n", nsCString(nsCSSProps::GetStringValue(p.mProperty)).get()); for (auto& s : p.mSegments) { nsString fromValue, toValue; s.mFromValue.SerializeSpecifiedValue(p.mProperty, fromValue); diff --git a/layout/inspector/InspectorUtils.cpp b/layout/inspector/InspectorUtils.cpp index 589b5c8e1263..428cd02c1e72 100644 --- a/layout/inspector/InspectorUtils.cpp +++ b/layout/inspector/InspectorUtils.cpp @@ -49,8 +49,6 @@ using namespace mozilla; using namespace mozilla::css; using namespace mozilla::dom; -extern const char* const kCSSRawProperties[]; - namespace mozilla { namespace dom { @@ -373,8 +371,8 @@ InspectorUtils::GetCSSPropertyNames(GlobalObject& aGlobalObject, auto appendProperty = [enabledState, &aResult](uint32_t prop) { nsCSSPropertyID cssProp = nsCSSPropertyID(prop); if (nsCSSProps::IsEnabled(cssProp, enabledState)) { - nsDependentCString name(kCSSRawProperties[prop]); - aResult.AppendElement(NS_ConvertASCIItoUTF16(name)); + aResult.AppendElement(NS_ConvertASCIItoUTF16( + nsCSSProps::GetStringValue(cssProp))); } }; @@ -406,8 +404,7 @@ InspectorUtils::GetCSSPropertyPrefs(GlobalObject& aGlobalObject, for (const auto* src = nsCSSProps::kPropertyPrefTable; src->mPropID != eCSSProperty_UNKNOWN; src++) { PropertyPref& dest = *aResult.AppendElement(); - const nsCString& name = nsCSSProps::GetStringValue(src->mPropID); - dest.mName.Assign(NS_ConvertASCIItoUTF16(name)); + dest.mName.Assign(NS_ConvertASCIItoUTF16(nsCSSProps::GetStringValue(src->mPropID))); dest.mPref.AssignASCII(src->mPref); } } diff --git a/layout/style/ServoBindingList.h b/layout/style/ServoBindingList.h index ade64734b71e..645572bce144 100644 --- a/layout/style/ServoBindingList.h +++ b/layout/style/ServoBindingList.h @@ -892,6 +892,10 @@ SERVO_BINDING_FUNC(Servo_ResolveLogicalProperty, SERVO_BINDING_FUNC(Servo_Property_LookupEnabledForAllContent, nsCSSPropertyID, const nsACString* name); +SERVO_BINDING_FUNC(Servo_Property_GetName, + const uint8_t*, + nsCSSPropertyID, + uint32_t* out_length); SERVO_BINDING_FUNC(Servo_Property_IsShorthand, bool, const nsACString* name, bool* found); SERVO_BINDING_FUNC(Servo_Property_IsInherited, bool, diff --git a/layout/style/nsCSSProps.cpp b/layout/style/nsCSSProps.cpp index 553bde3ec32b..73a5962c6c53 100644 --- a/layout/style/nsCSSProps.cpp +++ b/layout/style/nsCSSProps.cpp @@ -34,24 +34,9 @@ using namespace mozilla; typedef nsCSSProps::KTableEntry KTableEntry; -// required to make the symbol external, so that TestCSSPropertyLookup.cpp can link with it -extern const char* const kCSSRawProperties[]; - -// define an array of all CSS properties -const char* const kCSSRawProperties[eCSSProperty_COUNT_with_aliases] = { -#define CSS_PROP_LONGHAND(name_, ...) #name_, -#define CSS_PROP_SHORTHAND(name_, ...) #name_, -#define CSS_PROP_ALIAS(name_, ...) #name_, -#include "mozilla/ServoCSSPropList.h" -#undef CSS_PROP_ALIAS -#undef CSS_PROP_SHORTHAND -#undef CSS_PROP_LONGHAND -}; - using namespace mozilla; static int32_t gPropertyTableRefCount; -static nsStaticCaseInsensitiveNameTable* gPropertyTable; static nsStaticCaseInsensitiveNameTable* gFontDescTable; static nsStaticCaseInsensitiveNameTable* gCounterDescTable; static nsDataHashtable* gPropertyIDLNameTable; @@ -68,20 +53,6 @@ static const char* const kCSSRawCounterDescs[] = { #undef CSS_COUNTER_DESC }; -// We need eCSSAliasCount so we can make gAliases nonzero size when there -// are no aliases. -enum { - eCSSAliasCount = eCSSProperty_COUNT_with_aliases - eCSSProperty_COUNT -}; - -// The names are in kCSSRawProperties. -static nsCSSPropertyID gAliases[eCSSAliasCount != 0 ? eCSSAliasCount : 1] = { -#define CSS_PROP_ALIAS(aliasname_, aliasid_, propid_, aliasmethod_, pref_) \ - eCSSProperty_##propid_ , -#include "mozilla/ServoCSSPropList.h" -#undef CSS_PROP_ALIAS -}; - static nsStaticCaseInsensitiveNameTable* CreateStaticTable(const char* const aRawTable[], int32_t aLength) { @@ -101,13 +72,10 @@ void nsCSSProps::AddRefTable(void) { if (0 == gPropertyTableRefCount++) { - MOZ_ASSERT(!gPropertyTable, "pre existing array!"); MOZ_ASSERT(!gFontDescTable, "pre existing array!"); MOZ_ASSERT(!gCounterDescTable, "pre existing array!"); MOZ_ASSERT(!gPropertyIDLNameTable, "pre existing array!"); - gPropertyTable = CreateStaticTable( - kCSSRawProperties, eCSSProperty_COUNT_with_aliases); gFontDescTable = CreateStaticTable(kCSSRawFontDescs, eCSSFontDesc_COUNT); gCounterDescTable = CreateStaticTable( kCSSRawCounterDescs, eCSSCounterDesc_COUNT); @@ -141,9 +109,6 @@ void nsCSSProps::ReleaseTable(void) { if (0 == --gPropertyTableRefCount) { - delete gPropertyTable; - gPropertyTable = nullptr; - delete gFontDescTable; gFontDescTable = nullptr; @@ -199,18 +164,6 @@ nsCSSProps::LookupFontDesc(const nsAString& aFontDesc) return which; } -const nsCString& -nsCSSProps::GetStringValue(nsCSSPropertyID aProperty) -{ - MOZ_ASSERT(gPropertyTable, "no lookup table, needs addref"); - if (gPropertyTable) { - return gPropertyTable->GetStringValue(int32_t(aProperty)); - } else { - static nsDependentCString sNullStr(""); - return sNullStr; - } -} - const nsCString& nsCSSProps::GetStringValue(nsCSSFontDesc aFontDescID) { diff --git a/layout/style/nsCSSProps.h b/layout/style/nsCSSProps.h index c9cb40176885..29b23473536c 100644 --- a/layout/style/nsCSSProps.h +++ b/layout/style/nsCSSProps.h @@ -37,6 +37,7 @@ extern "C" { nsCSSPropertyID Servo_ResolveLogicalProperty(nsCSSPropertyID, const mozilla::ComputedStyle*); nsCSSPropertyID Servo_Property_LookupEnabledForAllContent(const nsACString*); + const uint8_t* Servo_Property_GetName(nsCSSPropertyID, uint32_t* aLength); } struct nsCSSKTableEntry @@ -119,7 +120,15 @@ public: static nsCSSFontDesc LookupFontDesc(const nsAString& aProperty); // Given a property enum, get the string value - static const nsCString& GetStringValue(nsCSSPropertyID aProperty); + // + // This string is static. + static const nsDependentCSubstring GetStringValue(nsCSSPropertyID aProperty) + { + uint32_t len; + const uint8_t* chars = Servo_Property_GetName(aProperty, &len); + return nsDependentCSubstring(reinterpret_cast(chars), len); + } + static const nsCString& GetStringValue(nsCSSFontDesc aFontDesc); static const nsCString& GetStringValue(nsCSSCounterDesc aCounterDesc); diff --git a/servo/components/style/properties/properties.mako.rs b/servo/components/style/properties/properties.mako.rs index 27458cf67c4f..809820eae074 100644 --- a/servo/components/style/properties/properties.mako.rs +++ b/servo/components/style/properties/properties.mako.rs @@ -427,9 +427,10 @@ impl NonCustomPropertyId { unsafe { ::std::mem::transmute(self.0 as i32) } } + /// Convert an `nsCSSPropertyID` into a `NonCustomPropertyId`. #[cfg(feature = "gecko")] #[inline] - fn from_nscsspropertyid(prop: nsCSSPropertyID) -> Result { + pub fn from_nscsspropertyid(prop: nsCSSPropertyID) -> Result { let prop = prop as i32; if prop < 0 { return Err(()); @@ -443,7 +444,7 @@ impl NonCustomPropertyId { /// Get the property name. #[inline] - fn name(self) -> &'static str { + pub fn name(self) -> &'static str { static MAP: [&'static str; ${len(data.longhands) + len(data.shorthands) + len(data.all_aliases())}] = [ % for property in data.longhands + data.shorthands + data.all_aliases(): "${property.name}", diff --git a/servo/ports/geckolib/glue.rs b/servo/ports/geckolib/glue.rs index 2d6256dc6583..8cf221dd990f 100644 --- a/servo/ports/geckolib/glue.rs +++ b/servo/ports/geckolib/glue.rs @@ -925,7 +925,6 @@ pub extern "C" fn Servo_ResolveLogicalProperty( longhand.to_physical(style.writing_mode).to_nscsspropertyid() } - #[no_mangle] pub unsafe extern "C" fn Servo_Property_LookupEnabledForAllContent( prop: *const nsACString, @@ -936,6 +935,25 @@ pub unsafe extern "C" fn Servo_Property_LookupEnabledForAllContent( } } +#[no_mangle] +pub unsafe extern "C" fn Servo_Property_GetName( + prop: nsCSSPropertyID, + out_length: *mut u32, +) -> *const u8 { + use style::properties::NonCustomPropertyId; + + let (ptr, len) = match NonCustomPropertyId::from_nscsspropertyid(prop) { + Ok(p) => { + let name = p.name(); + (name.as_bytes().as_ptr(), name.len()) + } + Err(..) => (ptr::null(), 0), + }; + + *out_length = len as u32; + ptr +} + macro_rules! parse_enabled_property_name { ($prop_name:ident, $found:ident, $default:expr) => {{ let prop_name = $prop_name.as_ref().unwrap().as_str_unchecked(); From 27932e0385f39b69e62fd4a1ab81162725059644 Mon Sep 17 00:00:00 2001 From: Jan Varga Date: Tue, 31 Jul 2018 12:27:17 +0200 Subject: [PATCH 09/11] Bug 1478573; r=asuth --- dom/indexedDB/IDBObjectStore.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp index ea17b6bacd66..80ff62056c89 100644 --- a/dom/indexedDB/IDBObjectStore.cpp +++ b/dom/indexedDB/IDBObjectStore.cpp @@ -1941,10 +1941,16 @@ IDBObjectStore::GetAddInfo(JSContext* aCx, // Figure out indexes and the index values to update here. const nsTArray& indexes = mSpec->indexes(); - const uint32_t idxCount = indexes.Length(); + uint32_t idxCount = indexes.Length(); - if (idxCount && !aValueWrapper.Clone(aCx)) { - return NS_ERROR_DOM_DATA_CLONE_ERR; + if (idxCount) { + if (!aValueWrapper.Clone(aCx)) { + return NS_ERROR_DOM_DATA_CLONE_ERR; + } + + // Update idxCount, the structured clone process may trigger content code + // via getters/other which can potentially call CreateIndex/DeleteIndex. + idxCount = indexes.Length(); } aUpdateInfoArray.SetCapacity(idxCount); // Pretty good estimate From 27250792bc87fd3c6c7bb06e22c5d4f95003070e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 29 Jul 2018 04:03:03 +0200 Subject: [PATCH 10/11] Bug 1479240: Make system metric queries always return false instead of not matching for fingerprinting-resistance. r=heycam Looks like these used this mechanism for no great reason, and actually doing this exposes trivially whether fingerprinting-resistance is enabled, which looks like an anti-goal (if a media query parses correctly, and doesn't match either 1 or 0, then fingerprinting-resistance is enabled). Differential Revision: https://phabricator.services.mozilla.com/D2493 MozReview-Commit-ID: 76tIIkwlpeP --- layout/style/nsMediaFeatures.cpp | 23 ++++++++++------------- layout/style/test/chrome/bug418986-2.js | 7 +++++-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/layout/style/nsMediaFeatures.cpp b/layout/style/nsMediaFeatures.cpp index cc41c9252447..5eef14006ea4 100644 --- a/layout/style/nsMediaFeatures.cpp +++ b/layout/style/nsMediaFeatures.cpp @@ -393,8 +393,15 @@ GetTransform3d(nsIDocument* aDocument, const nsMediaFeature*, } static bool -HasSystemMetric(nsAtom* aMetric) +HasSystemMetric(nsIDocument* aDocument, + nsAtom* aMetric, + bool aIsAccessibleFromContent) { + if (aIsAccessibleFromContent && + nsContentUtils::ShouldResistFingerprinting(aDocument)) { + return false; + } + nsMediaFeatures::InitSystemMetrics(); return sSystemMetrics->IndexOf(aMetric) != sSystemMetrics->NoIndex; } @@ -403,27 +410,17 @@ static void GetSystemMetric(nsIDocument* aDocument, const nsMediaFeature* aFeature, nsCSSValue& aResult) { - aResult.Reset(); - const bool isAccessibleFromContentPages = !(aFeature->mReqFlags & nsMediaFeature::eUserAgentAndChromeOnly); MOZ_ASSERT(!isAccessibleFromContentPages || *aFeature->mName == nsGkAtoms::_moz_touch_enabled); - - if (isAccessibleFromContentPages && - nsContentUtils::ShouldResistFingerprinting(aDocument)) { - // If "privacy.resistFingerprinting" is enabled, then we simply don't - // return any system-backed media feature values. (No spoofed values - // returned.) - return; - } - MOZ_ASSERT(aFeature->mValueType == nsMediaFeature::eBoolInteger, "unexpected type"); nsAtom* metricAtom = *aFeature->mData.mMetric; - bool hasMetric = HasSystemMetric(metricAtom); + bool hasMetric = + HasSystemMetric(aDocument, metricAtom, isAccessibleFromContentPages); aResult.SetIntValue(hasMetric ? 1 : 0, eCSSUnit_Integer); } diff --git a/layout/style/test/chrome/bug418986-2.js b/layout/style/test/chrome/bug418986-2.js index 26e58bbeef8d..532a84823804 100644 --- a/layout/style/test/chrome/bug418986-2.js +++ b/layout/style/test/chrome/bug418986-2.js @@ -104,10 +104,13 @@ var testToggles = function (resisting) { suppressed_toggles.forEach( function (key) { var exists = keyValMatches(key, 0) || keyValMatches(key, 1); - if (resisting || (!toggles_enabled_in_content.includes(key) && !is_chrome_window)) { + if (!toggles_enabled_in_content.includes(key) && !is_chrome_window) { ok(!exists, key + " should not exist."); } else { ok(exists, key + " should exist."); + if (resisting) { + ok(keyValMatches(key, 0) && !keyValMatches(key, 1), "Should always match as false"); + } } }); }; @@ -214,7 +217,7 @@ var generateCSSLines = function (resisting) { if (!toggles_enabled_in_content.includes(key) && !resisting && !is_chrome_window) { lines += "#" + key + " { background-color: green; }\n"; } else { - lines += suppressedMediaQueryCSSLine(key, resisting ? "red" : "green"); + lines += suppressedMediaQueryCSSLine(key, "green"); } }); if (OS === "WINNT") { From ae8a6c6dcc10fac6dadec1fd7dd554deeb682918 Mon Sep 17 00:00:00 2001 From: Devika Sugathan Date: Tue, 31 Jul 2018 00:35:36 +0530 Subject: [PATCH 11/11] Bug 1472121 - Remove unused patches from build/build-clang/. r=marco --- build/build-clang/clang-win64-st-an.json | 1 - .../hide-gcda-profiling-symbols.patch | 108 ------------------ .../return-empty-string-non-mangled.patch | 19 --- 3 files changed, 128 deletions(-) delete mode 100644 build/build-clang/hide-gcda-profiling-symbols.patch delete mode 100644 build/build-clang/return-empty-string-non-mangled.patch diff --git a/build/build-clang/clang-win64-st-an.json b/build/build-clang/clang-win64-st-an.json index 6f272320bab7..b4065b9d61d0 100644 --- a/build/build-clang/clang-win64-st-an.json +++ b/build/build-clang/clang-win64-st-an.json @@ -17,7 +17,6 @@ "r318309.patch", "r320462.patch", "loosen-msvc-detection.patch", - "hide-gcda-profiling-symbols.patch", "fflush-before-unlocking.patch" ] } diff --git a/build/build-clang/hide-gcda-profiling-symbols.patch b/build/build-clang/hide-gcda-profiling-symbols.patch deleted file mode 100644 index 02c9298621b2..000000000000 --- a/build/build-clang/hide-gcda-profiling-symbols.patch +++ /dev/null @@ -1,108 +0,0 @@ -diff --git a/compiler-rt/lib/profile/GCDAProfiling.c b/compiler-rt/lib/profile/GCDAProfiling.c -index 138af6ec4..f0c05075a 100644 ---- a/compiler-rt/lib/profile/GCDAProfiling.c -+++ b/compiler-rt/lib/profile/GCDAProfiling.c -@@ -231,6 +231,7 @@ static void unmap_file() { - * profiling enabled will emit to a different file. Only one file may be - * started at a time. - */ -+COMPILER_RT_VISIBILITY - void llvm_gcda_start_file(const char *orig_filename, const char version[4], - uint32_t checksum) { - const char *mode = "r+b"; -@@ -298,6 +299,7 @@ void llvm_gcda_start_file(const char *orig_filename, const char version[4], - /* Given an array of pointers to counters (counters), increment the n-th one, - * where we're also given a pointer to n (predecessor). - */ -+COMPILER_RT_VISIBILITY - void llvm_gcda_increment_indirect_counter(uint32_t *predecessor, - uint64_t **counters) { - uint64_t *counter; -@@ -320,6 +322,7 @@ void llvm_gcda_increment_indirect_counter(uint32_t *predecessor, - #endif - } - -+COMPILER_RT_VISIBILITY - void llvm_gcda_emit_function(uint32_t ident, const char *function_name, - uint32_t func_checksum, uint8_t use_extra_checksum, - uint32_t cfg_checksum) { -@@ -346,6 +349,7 @@ void llvm_gcda_emit_function(uint32_t ident, const char *function_name, - write_string(function_name); - } - -+COMPILER_RT_VISIBILITY - void llvm_gcda_emit_arcs(uint32_t num_counters, uint64_t *counters) { - uint32_t i; - uint64_t *old_ctrs = NULL; -@@ -397,6 +401,7 @@ void llvm_gcda_emit_arcs(uint32_t num_counters, uint64_t *counters) { - #endif - } - -+COMPILER_RT_VISIBILITY - void llvm_gcda_summary_info() { - const uint32_t obj_summary_len = 9; /* Length for gcov compatibility. */ - uint32_t i; -@@ -450,6 +455,7 @@ void llvm_gcda_summary_info() { - #endif - } - -+COMPILER_RT_VISIBILITY - void llvm_gcda_end_file() { - /* Write out EOF record. */ - if (output_file) { -@@ -474,6 +480,7 @@ void llvm_gcda_end_file() { - #endif - } - -+COMPILER_RT_VISIBILITY - void llvm_register_writeout_function(writeout_fn fn) { - struct writeout_fn_node *new_node = malloc(sizeof(struct writeout_fn_node)); - new_node->fn = fn; -@@ -487,6 +494,7 @@ void llvm_register_writeout_function(writeout_fn fn) { - } - } - -+COMPILER_RT_VISIBILITY - void llvm_writeout_files(void) { - struct writeout_fn_node *curr = writeout_fn_head; - -@@ -496,6 +504,7 @@ void llvm_writeout_files(void) { - } - } - -+COMPILER_RT_VISIBILITY - void llvm_delete_writeout_function_list(void) { - while (writeout_fn_head) { - struct writeout_fn_node *node = writeout_fn_head; -@@ -506,6 +515,7 @@ void llvm_delete_writeout_function_list(void) { - writeout_fn_head = writeout_fn_tail = NULL; - } - -+COMPILER_RT_VISIBILITY - void llvm_register_flush_function(flush_fn fn) { - struct flush_fn_node *new_node = malloc(sizeof(struct flush_fn_node)); - new_node->fn = fn; -@@ -519,6 +529,7 @@ void llvm_register_flush_function(flush_fn fn) { - } - } - -+COMPILER_RT_VISIBILITY - void __gcov_flush() { - struct flush_fn_node *curr = flush_fn_head; - -@@ -528,6 +539,7 @@ void __gcov_flush() { - } - } - -+COMPILER_RT_VISIBILITY - void llvm_delete_flush_function_list(void) { - while (flush_fn_head) { - struct flush_fn_node *node = flush_fn_head; -@@ -538,6 +550,7 @@ void llvm_delete_flush_function_list(void) { - flush_fn_head = flush_fn_tail = NULL; - } - -+COMPILER_RT_VISIBILITY - void llvm_gcov_init(writeout_fn wfn, flush_fn ffn) { - static int atexit_ran = 0; - diff --git a/build/build-clang/return-empty-string-non-mangled.patch b/build/build-clang/return-empty-string-non-mangled.patch deleted file mode 100644 index 33a39170399d..000000000000 --- a/build/build-clang/return-empty-string-non-mangled.patch +++ /dev/null @@ -1,19 +0,0 @@ -Author: Michael Wu -Date: Thu Sep 24 11:36:08 2015 -0400 - - Return an empty string when a symbol isn't mangled - -diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp ---- a/clang/tools/libclang/CIndex.cpp -+++ b/clang/tools/libclang/CIndex.cpp -@@ -3990,6 +3990,10 @@ - ASTContext &Ctx = ND->getASTContext(); - std::unique_ptr MC(Ctx.createMangleContext()); - -+ // Don't mangle if we don't need to. -+ if (!MC->shouldMangleCXXName(ND)) -+ return cxstring::createEmpty(); -+ - std::string FrontendBuf; - llvm::raw_string_ostream FrontendBufOS(FrontendBuf); - if (MC->shouldMangleDeclName(ND)) {