From cef23f69148b4c84c6b85584c11b1372461d2664 Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Mon, 16 Apr 2018 13:26:00 -0400 Subject: [PATCH 01/52] Bug 1454310 - Only call AccessibilityNodeInfo.getExtras on API >= 19. r=jchen --- .../mozilla/geckoview/SessionAccessibility.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionAccessibility.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionAccessibility.java index 7582dd8fbe7c..8a19c08d2f74 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionAccessibility.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionAccessibility.java @@ -107,10 +107,16 @@ public class SessionAccessibility { // can get to by traversing down. onInitializeAccessibilityNodeInfo(mView, info); info.setClassName("android.webkit.WebView"); // TODO: WTF - Bundle bundle = info.getExtras(); - bundle.putCharSequence( - "ACTION_ARGUMENT_HTML_ELEMENT_STRING_VALUES", - "ARTICLE,BUTTON,CHECKBOX,COMBOBOX,CONTROL,FOCUSABLE,FRAME,GRAPHIC,H1,H2,H3,H4,H5,H6,HEADING,LANDMARK,LINK,LIST,LIST_ITEM,MAIN,MEDIA,RADIO,SECTION,TABLE,TEXT_FIELD,UNVISITED_LINK,VISITED_LINK"); + if (Build.VERSION.SDK_INT >= 19) { + Bundle bundle = info.getExtras(); + bundle.putCharSequence( + "ACTION_ARGUMENT_HTML_ELEMENT_STRING_VALUES", + "ARTICLE,BUTTON,CHECKBOX,COMBOBOX,CONTROL," + + "FOCUSABLE,FRAME,GRAPHIC,H1,H2,H3,H4,H5,H6," + + "HEADING,LANDMARK,LINK,LIST,LIST_ITEM,MAIN," + + "MEDIA,RADIO,SECTION,TABLE,TEXT_FIELD," + + "UNVISITED_LINK,VISITED_LINK"); + } info.addAction(AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT); info.addChild(hostView, VIRTUAL_CONTENT_ID); break; From e4878be59c8cdbf42990d393ae152bf99d9efff2 Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Mon, 16 Apr 2018 13:26:00 -0400 Subject: [PATCH 02/52] Bug 1454484 - Rename GeckoViewAccessibility.init to onInit. r=jchen --- mobile/android/modules/geckoview/GeckoViewAccessibility.jsm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/android/modules/geckoview/GeckoViewAccessibility.jsm b/mobile/android/modules/geckoview/GeckoViewAccessibility.jsm index 11d5872059ba..cfdfbecfc0ad 100644 --- a/mobile/android/modules/geckoview/GeckoViewAccessibility.jsm +++ b/mobile/android/modules/geckoview/GeckoViewAccessibility.jsm @@ -19,7 +19,7 @@ XPCOMUtils.defineLazyGetter(this, "dump", () => {}).AndroidLog.d.bind(null, "GeckoAccessibility")); class GeckoViewAccessibility extends GeckoViewModule { - init() { + onInit() { EventDispatcher.instance.dispatch("GeckoView:AccessibilityReady"); EventDispatcher.instance.registerListener((aEvent, aData, aCallback) => { if (aData.enabled) { From aa51622886e5c5fe17540ab36888b976964dd6f6 Mon Sep 17 00:00:00 2001 From: Daniel Zielas Date: Sat, 14 Apr 2018 09:42:45 +0200 Subject: [PATCH 03/52] Bug 1453469 - Remove nsDisplayOwnLayer::mScrollTarget. r=botond MozReview-Commit-ID: 1LAWH96mm5m --HG-- extra : rebase_source : fe2bf1d16dc1921057f718cd5f7dd00b11e566c5 extra : amend_source : 53a8a2c0cd03b94002ba0600859e6c18d3a466b6 --- gfx/layers/LayerAttributes.h | 18 +++------------ gfx/layers/Layers.h | 17 +++------------ layout/generic/nsFrame.cpp | 1 - layout/generic/nsGfxScrollFrame.cpp | 6 ++--- layout/painting/nsDisplayList.cpp | 34 ++++++++++++++--------------- layout/painting/nsDisplayList.h | 23 ++++++++++--------- layout/xul/nsBoxFrame.cpp | 1 - layout/xul/nsSliderFrame.cpp | 5 +++-- 8 files changed, 42 insertions(+), 63 deletions(-) diff --git a/gfx/layers/LayerAttributes.h b/gfx/layers/LayerAttributes.h index 13e9b76c8644..03f0f206d34f 100644 --- a/gfx/layers/LayerAttributes.h +++ b/gfx/layers/LayerAttributes.h @@ -33,7 +33,8 @@ struct ScrollbarData { CSSCoord aThumbLength, bool aThumbIsAsyncDraggable, CSSCoord aScrollTrackStart, - CSSCoord aScrollTrackLength) + CSSCoord aScrollTrackLength, + uint64_t aTargetViewId) : mDirection(Some(aDirection)) , mScrollbarLayerType(aScrollbarLayerType) , mThumbRatio(aThumbRatio) @@ -42,6 +43,7 @@ struct ScrollbarData { , mThumbIsAsyncDraggable(aThumbIsAsyncDraggable) , mScrollTrackStart(aScrollTrackStart) , mScrollTrackLength(aScrollTrackLength) + , mTargetViewId(aTargetViewId) {} /** @@ -158,20 +160,6 @@ public: return true; } - bool SetScrollbarContainer(FrameMetrics::ViewID aTargetViewId, - ScrollDirection aDirection) { - if (mScrollbarData.mScrollbarLayerType == ScrollbarLayerType::Container && - mScrollbarData.mDirection && - *mScrollbarData.mDirection == aDirection && - mScrollbarData.mTargetViewId == aTargetViewId) { - return false; - } - mScrollbarData.mDirection = Some(aDirection); - mScrollbarData.mTargetViewId = aTargetViewId; - mScrollbarData.mScrollbarLayerType = ScrollbarLayerType::Container; - return true; - } - bool SetMixBlendMode(gfx::CompositionOp aMixBlendMode) { if (mMixBlendMode == aMixBlendMode) { return false; diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 9155098ff9cd..ef73c4b27b33 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -1259,9 +1259,9 @@ public: /** * CONSTRUCTION PHASE ONLY - * If a layer is a scroll thumb container layer, set the scroll identifier - * of the scroll frame scrolled by the thumb, and other data related to the - * thumb. + * If a layer is a scroll thumb container layer or a scrollbar container + * layer, set the scroll identifier of the scroll frame scrolled by + * the scrollbar, and other data related to the scrollbar. */ void SetScrollbarData(const ScrollbarData& aThumbData) { @@ -1271,17 +1271,6 @@ public: } } - // Set during construction for the container layer of scrollbar components. - // |aScrollId| holds the scroll identifier of the scrollable content that - // the scrollbar is for. - void SetScrollbarContainer(FrameMetrics::ViewID aScrollId, - ScrollDirection aDirection) - { - if (mSimpleAttrs.SetScrollbarContainer(aScrollId, aDirection)) { - MutatedSimple(); - } - } - // Used when forwarding transactions. Do not use at any other time. void SetSimpleAttributes(const SimpleLayerAttributes& aAttrs) { mSimpleAttrs = aAttrs; diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 0d1299018504..e027a9632903 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -3382,7 +3382,6 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, MakeDisplayItem(aBuilder, this, &resultList, aBuilder->CurrentActiveScrolledRoot(), nsDisplayOwnLayerFlags::eNone, - mozilla::layers::FrameMetrics::NULL_SCROLL_ID, ScrollbarData{}, /* aForceActive = */ false)); if (aCreatedContainerItem) { *aCreatedContainerItem = true; diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 662c5d6dd6c4..917d339c08dd 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -3042,21 +3042,21 @@ AppendToTop(nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists, nsDisplayWrapList* newItem; const ActiveScrolledRoot* asr = aBuilder->CurrentActiveScrolledRoot(); if (aFlags & APPEND_OWN_LAYER) { - FrameMetrics::ViewID scrollTarget = FrameMetrics::NULL_SCROLL_ID; nsDisplayOwnLayerFlags flags = aBuilder->GetCurrentScrollbarFlags(); // The flags here should be at most one scrollbar direction and nothing else MOZ_ASSERT(flags == nsDisplayOwnLayerFlags::eNone || flags == nsDisplayOwnLayerFlags::eVerticalScrollbar || flags == nsDisplayOwnLayerFlags::eHorizontalScrollbar); + ScrollbarData scrollbarData; if (aFlags & APPEND_SCROLLBAR_CONTAINER) { - scrollTarget = aBuilder->GetCurrentScrollbarTarget(); + scrollbarData.mTargetViewId = aBuilder->GetCurrentScrollbarTarget(); // The flags here should be exactly one scrollbar direction MOZ_ASSERT(flags != nsDisplayOwnLayerFlags::eNone); flags |= nsDisplayOwnLayerFlags::eScrollbarContainer; } - newItem = MakeDisplayItem(aBuilder, aSourceFrame, aSource, asr, flags, scrollTarget); + newItem = MakeDisplayItem(aBuilder, aSourceFrame, aSource, asr, flags, scrollbarData); } else { newItem = MakeDisplayItem(aBuilder, aSourceFrame, aSource, asr); } diff --git a/layout/painting/nsDisplayList.cpp b/layout/painting/nsDisplayList.cpp index 54e91dabd539..9263273fb32f 100644 --- a/layout/painting/nsDisplayList.cpp +++ b/layout/painting/nsDisplayList.cpp @@ -6922,14 +6922,13 @@ nsDisplayTableBlendContainer::CreateForBackgroundBlendMode(nsDisplayListBuilder* nsDisplayOwnLayer::nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsDisplayList* aList, const ActiveScrolledRoot* aActiveScrolledRoot, - nsDisplayOwnLayerFlags aFlags, ViewID aScrollTarget, - const ScrollbarData& aThumbData, + nsDisplayOwnLayerFlags aFlags, + const ScrollbarData& aScrollbarData, bool aForceActive, bool aClearClipChain) : nsDisplayWrapList(aBuilder, aFrame, aList, aActiveScrolledRoot, aClearClipChain) , mFlags(aFlags) - , mScrollTarget(aScrollTarget) - , mThumbData(aThumbData) + , mScrollbarData(aScrollbarData) , mForceActive(aForceActive) , mWrAnimationId(0) { @@ -6965,7 +6964,7 @@ nsDisplayOwnLayer::GetLayerState(nsDisplayListBuilder* aBuilder, bool nsDisplayOwnLayer::IsScrollThumbLayer() const { - return mThumbData.mScrollbarLayerType == layers::ScrollbarLayerType::Thumb; + return mScrollbarData.mScrollbarLayerType == layers::ScrollbarLayerType::Thumb; } bool @@ -6986,15 +6985,16 @@ nsDisplayOwnLayer::BuildLayer(nsDisplayListBuilder* aBuilder, BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList, aContainerParameters, nullptr, FrameLayerBuilder::CONTAINER_ALLOW_PULL_BACKGROUND_COLOR); + if (IsScrollThumbLayer()) { - mThumbData.mTargetViewId = mScrollTarget; - layer->SetScrollbarData(mThumbData); - } - if (mFlags & nsDisplayOwnLayerFlags::eScrollbarContainer) { - ScrollDirection dir = (mFlags & nsDisplayOwnLayerFlags::eVerticalScrollbar) - ? ScrollDirection::eVertical - : ScrollDirection::eHorizontal; - layer->SetScrollbarContainer(mScrollTarget, dir); + layer->SetScrollbarData(mScrollbarData); + } else if (mFlags & nsDisplayOwnLayerFlags::eScrollbarContainer) { + mScrollbarData.mScrollbarLayerType = ScrollbarLayerType::Container; + mScrollbarData.mDirection = (mFlags & nsDisplayOwnLayerFlags::eVerticalScrollbar) + ? Some(ScrollDirection::eVertical) + : Some(ScrollDirection::eHorizontal); + + layer->SetScrollbarData(mScrollbarData); } if (mFlags & nsDisplayOwnLayerFlags::eGenerateSubdocInvalidations) { @@ -7044,9 +7044,9 @@ nsDisplayOwnLayer::UpdateScrollData(mozilla::layers::WebRenderScrollData* aData, if (IsScrollThumbLayer()) { ret = true; if (aLayerData) { - aLayerData->SetScrollbarData(mThumbData); + aLayerData->SetScrollbarData(mScrollbarData); aLayerData->SetScrollbarAnimationId(mWrAnimationId); - aLayerData->SetScrollbarTargetContainerId(mScrollTarget); + aLayerData->SetScrollbarTargetContainerId(mScrollbarData.mTargetViewId); } } if (mFlags & nsDisplayOwnLayerFlags::eScrollbarContainer) { @@ -7056,7 +7056,7 @@ nsDisplayOwnLayer::UpdateScrollData(mozilla::layers::WebRenderScrollData* aData, ? ScrollDirection::eVertical : ScrollDirection::eHorizontal; aLayerData->SetScrollbarContainerDirection(dir); - aLayerData->SetScrollbarTargetContainerId(mScrollTarget); + aLayerData->SetScrollbarTargetContainerId(mScrollbarData.mTargetViewId); } } return ret; @@ -7065,7 +7065,7 @@ nsDisplayOwnLayer::UpdateScrollData(mozilla::layers::WebRenderScrollData* aData, void nsDisplayOwnLayer::WriteDebugInfo(std::stringstream& aStream) { - aStream << nsPrintfCString(" (flags 0x%x) (scrolltarget %" PRIu64 ")", (int)mFlags, mScrollTarget).get(); + aStream << nsPrintfCString(" (flags 0x%x) (scrolltarget %" PRIu64 ")", (int)mFlags, mScrollbarData.mTargetViewId).get(); } nsDisplaySubDocument::nsDisplaySubDocument(nsDisplayListBuilder* aBuilder, diff --git a/layout/painting/nsDisplayList.h b/layout/painting/nsDisplayList.h index bf42fd81192f..58ab8c7fb3c8 100644 --- a/layout/painting/nsDisplayList.h +++ b/layout/painting/nsDisplayList.h @@ -5600,18 +5600,18 @@ public: nsDisplayList* aList, const ActiveScrolledRoot* aActiveScrolledRoot, nsDisplayOwnLayerFlags aFlags = nsDisplayOwnLayerFlags::eNone, - ViewID aScrollTarget = mozilla::layers::FrameMetrics::NULL_SCROLL_ID, - const ScrollbarData& aThumbData = ScrollbarData{}, + const ScrollbarData& aScrollbarData = ScrollbarData{}, bool aForceActive = true, bool aClearClipChain = false); + #ifdef NS_BUILD_REFCNT_LOGGING virtual ~nsDisplayOwnLayer(); #endif + nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder, const nsDisplayOwnLayer& aOther) : nsDisplayWrapList(aBuilder, aOther) , mFlags(aOther.mFlags) - , mScrollTarget(aOther.mScrollTarget) - , mThumbData(aOther.mThumbData) + , mScrollbarData(aOther.mScrollbarData) , mForceActive(aOther.mForceActive) , mWrAnimationId(aOther.mWrAnimationId) { @@ -5651,12 +5651,15 @@ public: NS_DISPLAY_DECL_NAME("OwnLayer", TYPE_OWN_LAYER) protected: nsDisplayOwnLayerFlags mFlags; - ViewID mScrollTarget; - // If this nsDisplayOwnLayer represents a scroll thumb layer, mThumbData - // stores information about the scroll thumb. Otherwise, mThumbData will be - // default-constructed (in particular with mDirection == Nothing()) - // and can be ignored. - ScrollbarData mThumbData; + + /** + * If this nsDisplayOwnLayer represents a scroll thumb layer or a + * scrollbar container layer, mScrollbarData stores information + * about the scrollbar. Otherwise, mScrollbarData will be + * default-constructed (in particular with mDirection == Nothing()) + * and can be ignored. + */ + ScrollbarData mScrollbarData; bool mForceActive; uint64_t mWrAnimationId; }; diff --git a/layout/xul/nsBoxFrame.cpp b/layout/xul/nsBoxFrame.cpp index f76ed2c062b8..620d54504547 100644 --- a/layout/xul/nsBoxFrame.cpp +++ b/layout/xul/nsBoxFrame.cpp @@ -1390,7 +1390,6 @@ nsBoxFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, aLists.Content()->AppendToTop( MakeDisplayItem(aBuilder, this, &masterList, ownLayerASR, nsDisplayOwnLayerFlags::eNone, - mozilla::layers::FrameMetrics::NULL_SCROLL_ID, mozilla::layers::ScrollbarData{}, true, true)); } } diff --git a/layout/xul/nsSliderFrame.cpp b/layout/xul/nsSliderFrame.cpp index 8bfe0e136474..693650cb28c8 100644 --- a/layout/xul/nsSliderFrame.cpp +++ b/layout/xul/nsSliderFrame.cpp @@ -459,7 +459,7 @@ nsSliderFrame::BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder, const ActiveScrolledRoot* ownLayerASR = contASRTracker.GetContainerASR(); aLists.Content()->AppendToTop( MakeDisplayItem(aBuilder, this, &masterList, ownLayerASR, - flags, scrollTargetId, + flags, ScrollbarData{scrollDirection, layers::ScrollbarLayerType::Thumb, GetThumbRatio(), @@ -467,7 +467,8 @@ nsSliderFrame::BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder, thumbLength, isAsyncDraggable, sliderTrackStart, - sliderTrackLength})); + sliderTrackLength, + scrollTargetId})); return; } From 88c37965dd9af569ed201d162aa3730b289cbdd5 Mon Sep 17 00:00:00 2001 From: Simon Fraser Date: Tue, 17 Apr 2018 07:42:23 +0100 Subject: [PATCH 04/52] Bug 1454343 Update taskcluster cron documentation r=dustin Reviewers: dustin Reviewed By: dustin Bug #: 1454343 Differential Revision: https://phabricator.services.mozilla.com/D950 --HG-- extra : rebase_source : 50cce8d7c47dfaca18358d1c590eadd7417bd93c --- taskcluster/docs/cron.rst | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/taskcluster/docs/cron.rst b/taskcluster/docs/cron.rst index faecbd04e673..5a0c4ebc5cda 100644 --- a/taskcluster/docs/cron.rst +++ b/taskcluster/docs/cron.rst @@ -30,6 +30,45 @@ minutes) and creates tasks for any cron jobs scheduled at that time. Each cron job in ``.cron.yml`` specifies a ``job.type``, corresponding to a function responsible for creating TaskCluster tasks when the job runs. +Describing Time +--------------- + +This cron implementation understands the following directives when +describing when to run: + +* ``minute``: The minute in which to run, must be in 15 minute increments (see above) +* ``hour``: The hour of the day in which to run, in 24 hour time. +* ``day``: The day of the month as an integer, such as `1`, `16`. Be cautious above `28`, remember February. +* ``weekday``: The day of the week, `Monday`, `Tuesday`, etc. Full length ISO compliant words. + +Setting both 'day' and 'weekday' will result in a cron job that won't run very often, +and so is undesirable. + +*Examples* + +.. code-block:: yaml + + # Never + when: [] + + # 4 AM and 4 PM, on the hour, every day. + when: + - {hour: 16, minute: 0} + - {hour: 4, minute: 0} + + # The same as above, on a single line + when: [{hour: 16, minute: 0}, {hour: 4, minute: 0}] + + # 4 AM on the second day of every month. + when: + - {day: 2, hour: 4, minute: 0} + + # Mondays and Thursdays at 10 AM + when: + - {weekday: 'Monday', hour: 10, minute: 0} + - {weekday: 'Thursday', hour: 10, minute: 0} + + Decision Tasks .............. From 5bae58b0828581ba72091a81d11356f3986d034d Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Tue, 17 Apr 2018 08:44:55 +0200 Subject: [PATCH 05/52] Bug 1453028 - Refactor the way we parse zeal mode strings r=sfink --- js/src/gc/GC.cpp | 143 +++++++++++++++++++++++++++--------------- js/src/gc/GCEnum.h | 3 +- js/src/gc/GCRuntime.h | 2 + js/src/shell/js.cpp | 9 ++- 4 files changed, 101 insertions(+), 56 deletions(-) diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp index 799b4a907ce1..86763ec1227a 100644 --- a/js/src/gc/GC.cpp +++ b/js/src/gc/GC.cpp @@ -192,6 +192,7 @@ #include "mozilla/MacroForEach.h" #include "mozilla/MemoryReporting.h" #include "mozilla/Move.h" +#include "mozilla/Range.h" #include "mozilla/ScopeExit.h" #include "mozilla/TimeStamp.h" #include "mozilla/TypeTraits.h" @@ -1089,66 +1090,108 @@ GCRuntime::setNextScheduled(uint32_t count) nextScheduled = count; } +using CharRange = mozilla::Range; +using CharRangeVector = Vector; + +static bool +ParseZealModeName(CharRange text, uint32_t* modeOut) +{ + struct ModeInfo + { + const char* name; + size_t length; + uint32_t value; + }; + + static const ModeInfo zealModes[] = { + {"None", 0}, +#define ZEAL_MODE(name, value) {#name, strlen(#name), value}, + JS_FOR_EACH_ZEAL_MODE(ZEAL_MODE) +#undef ZEAL_MODE + }; + + for (auto mode : zealModes) { + if (text.length() == mode.length && + memcmp(text.begin().get(), mode.name, mode.length) == 0) + { + *modeOut = mode.value; + return true; + } + } + + return false; +} + +static bool +ParseZealModeNumericParam(CharRange text, uint32_t* paramOut) +{ + if (text.length() == 0) + return false; + + for (auto c : text) { + if (!isdigit(c)) + return false; + } + + *paramOut = atoi(text.begin().get()); + return true; +} + +static bool +SplitStringBy(CharRange text, char delimiter, CharRangeVector* result) +{ + auto start = text.begin(); + for (auto ptr = start; ptr != text.end(); ptr++) { + if (*ptr == delimiter) { + if (!result->emplaceBack(start, ptr)) + return false; + start = ptr + 1; + } + } + + return result->emplaceBack(start, text.end()); +} + +static bool +PrintZealHelpAndFail() +{ + fprintf(stderr, "Format: JS_GC_ZEAL=level(;level)*[,N]\n"); + fputs(ZealModeHelpText, stderr); + return false; +} + bool GCRuntime::parseAndSetZeal(const char* str) { - int frequency = -1; - bool foundFrequency = false; - mozilla::Vector zeals; + // Set the zeal mode from a string consisting of one or more mode specifiers + // separated by ';', optionally followed by a ',' and the trigger frequency. + // The mode specifiers can by a mode name or its number. - static const struct { - const char* const zealMode; - size_t length; - uint32_t zeal; - } zealModes[] = { -#define ZEAL_MODE(name, value) {#name, sizeof(#name) - 1, value}, - JS_FOR_EACH_ZEAL_MODE(ZEAL_MODE) -#undef ZEAL_MODE - {"None", 4, 0} - }; + auto text = CharRange(str, strlen(str)); - do { - int zeal = -1; + CharRangeVector parts; + if (!SplitStringBy(text, ',', &parts)) + return false; - const char* p = nullptr; - if (isdigit(str[0])) { - zeal = atoi(str); + if (parts.length() == 0 || parts.length() > 2) + return PrintZealHelpAndFail(); - size_t offset = strspn(str, "0123456789"); - p = str + offset; - } else { - for (auto z : zealModes) { - if (!strncmp(str, z.zealMode, z.length)) { - zeal = z.zeal; - p = str + z.length; - break; - } - } - } - if (p) { - if (!*p || *p == ';') { - frequency = JS_DEFAULT_ZEAL_FREQ; - } else if (*p == ',') { - frequency = atoi(p + 1); - foundFrequency = true; - } - } + uint32_t frequency = JS_DEFAULT_ZEAL_FREQ; + if (parts.length() == 2 && !ParseZealModeNumericParam(parts[1], &frequency)) + return PrintZealHelpAndFail(); - if (zeal < 0 || zeal > int(ZealMode::Limit) || frequency <= 0) { - fprintf(stderr, "Format: JS_GC_ZEAL=level(;level)*[,N]\n"); - fputs(ZealModeHelpText, stderr); - return false; - } + CharRangeVector modes; + if (!SplitStringBy(parts[0], ';', &modes)) + return false; - if (!zeals.emplaceBack(zeal)) { - return false; - } - } while (!foundFrequency && - (str = strchr(str, ';')) != nullptr && - str++); + for (const auto& descr : modes) { + uint32_t mode; + if (!ParseZealModeName(descr, &mode) && !ParseZealModeNumericParam(descr, &mode)) + return PrintZealHelpAndFail(); + + setZeal(mode, frequency); + } - for (auto z : zeals) - setZeal(z, frequency); return true; } diff --git a/js/src/gc/GCEnum.h b/js/src/gc/GCEnum.h index 2da3e400ae31..80fd9cd8a0b9 100644 --- a/js/src/gc/GCEnum.h +++ b/js/src/gc/GCEnum.h @@ -78,7 +78,8 @@ enum class ZealMode { #define ZEAL_MODE(name, value) name = value, JS_FOR_EACH_ZEAL_MODE(ZEAL_MODE) #undef ZEAL_MODE - Limit = 18 + Count, + Limit = Count - 1 }; } /* namespace gc */ diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index 25936bd9f7e5..0baf2a95e668 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -894,6 +894,8 @@ class GCRuntime * zeal_ value 14 performs periodic shrinking collections. */ #ifdef JS_GC_ZEAL + static_assert(size_t(ZealMode::Count) <= 32, + "Too many zeal modes to store in a uint32_t"); ActiveThreadData zealModeBits; ActiveThreadData zealFrequency; ActiveThreadData nextScheduled; diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index b3009462868c..c8f0571c7744 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -8627,11 +8627,10 @@ SetWorkerContextOptions(JSContext* cx) #ifdef JS_GC_ZEAL if (gZealBits && gZealFrequency) { -#define ZEAL_MODE(_, value) \ - if (gZealBits & (1 << value)) \ - cx->runtime()->gc.setZeal(value, gZealFrequency); - JS_FOR_EACH_ZEAL_MODE(ZEAL_MODE) -#undef ZEAL_MODE + for (size_t i = 0; i < size_t(gc::ZealMode::Count); i++) { + if (gZealBits & (1 << i)) + cx->runtime()->gc.setZeal(i, gZealFrequency); + } } #endif From f69380bdd209776441bce476b63538585f8e1e08 Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Tue, 17 Apr 2018 08:44:56 +0200 Subject: [PATCH 06/52] Bug 1453028 - Rename GC zeal modes that run in two slices and refactor r=sfink --- js/src/gc/GC.cpp | 119 ++++++++++++++++++++---------------------- js/src/gc/GCEnum.h | 6 +-- js/src/gc/GCRuntime.h | 16 ++++-- 3 files changed, 73 insertions(+), 68 deletions(-) diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp index 86763ec1227a..309843a45dd3 100644 --- a/js/src/gc/GC.cpp +++ b/js/src/gc/GC.cpp @@ -1020,30 +1020,34 @@ const char* gc::ZealModeHelpText = " both modes 2 and 4. Modes can be specified by name or number.\n" " \n" " Values:\n" - " 0: (None) Normal amount of collection (resets all modes)\n" - " 1: (RootsChange) Collect when roots are added or removed\n" - " 2: (Alloc) Collect when every N allocations (default: 100)\n" - " 4: (VerifierPre) Verify pre write barriers between instructions\n" - " 7: (GenerationalGC) Collect the nursery every N nursery allocations\n" - " 8: (IncrementalRootsThenFinish) Incremental GC in two slices: 1) mark roots 2) finish collection\n" - " 9: (IncrementalMarkAllThenFinish) Incremental GC in two slices: 1) mark all 2) new marking and finish\n" - " 10: (IncrementalMultipleSlices) Incremental GC in multiple slices\n" - " 11: (IncrementalMarkingValidator) Verify incremental marking\n" - " 12: (ElementsBarrier) Always use the individual element post-write barrier, regardless of elements size\n" - " 13: (CheckHashTablesOnMinorGC) Check internal hashtables on minor GC\n" - " 14: (Compact) Perform a shrinking collection every N allocations\n" - " 15: (CheckHeapAfterGC) Walk the heap to check its integrity after every GC\n" - " 16: (CheckNursery) Check nursery integrity on minor GC\n" - " 17: (IncrementalSweepThenFinish) Incremental GC in two slices: 1) start sweeping 2) finish collection\n" - " 18: (CheckGrayMarking) Check gray marking invariants after every GC\n"; + " 0: (None) Normal amount of collection (resets all modes)\n" + " 1: (RootsChange) Collect when roots are added or removed\n" + " 2: (Alloc) Collect when every N allocations (default: 100)\n" + " 4: (VerifierPre) Verify pre write barriers between instructions\n" + " 7: (GenerationalGC) Collect the nursery every N nursery allocations\n" + " 8: (YieldBeforeMarking) Incremental GC in two slices that yields between\n" + " the root marking and marking phases\n" + " 9: (YieldBeforeSweeping) Incremental GC in two slices that yields between\n" + " the marking and sweeping phases\n" + " 10: (IncrementalMultipleSlices) Incremental GC in many slices\n" + " 11: (IncrementalMarkingValidator) Verify incremental marking\n" + " 12: (ElementsBarrier) Use the individual element post-write barrier\n" + " regardless of elements size\n" + " 13: (CheckHashTablesOnMinorGC) Check internal hashtables on minor GC\n" + " 14: (Compact) Perform a shrinking collection every N allocations\n" + " 15: (CheckHeapAfterGC) Walk the heap to check its integrity after every GC\n" + " 16: (CheckNursery) Check nursery integrity on minor GC\n" + " 17: (YieldBeforeSweepingAtoms) Incremental GC in two slices that yields\n" + " before sweeping the atoms table\n" + " 18: (CheckGrayMarking) Check gray marking invariants after every GC\n"; // The set of zeal modes that control incremental slices. These modes are // mutually exclusive. static const mozilla::EnumSet IncrementalSliceZealModes = { - ZealMode::IncrementalRootsThenFinish, - ZealMode::IncrementalMarkAllThenFinish, + ZealMode::YieldBeforeMarking, + ZealMode::YieldBeforeSweeping, ZealMode::IncrementalMultipleSlices, - ZealMode::IncrementalSweepThenFinish + ZealMode::YieldBeforeSweepingAtoms }; void @@ -4987,9 +4991,9 @@ GCRuntime::groupZonesForSweeping(JS::gcreason::Reason reason) finder.useOneComponent(); #ifdef JS_GC_ZEAL - // Use one component for IncrementalSweepThenFinish zeal mode. + // Use one component for YieldBeforeSweepingAtoms zeal mode. if (isIncremental && reason == JS::gcreason::DEBUG_GC && - hasZealMode(ZealMode::IncrementalSweepThenFinish)) + hasZealMode(ZealMode::YieldBeforeSweepingAtoms)) { finder.useOneComponent(); } @@ -5741,7 +5745,7 @@ GCRuntime::maybeYieldForSweepingZeal(FreeOp* fop, SliceBudget& budget) */ if (isIncremental && useZeal && initialState != State::Sweep && (hasZealMode(ZealMode::IncrementalMultipleSlices) || - hasZealMode(ZealMode::IncrementalSweepThenFinish))) + hasZealMode(ZealMode::YieldBeforeSweepingAtoms))) { return NotFinished; } @@ -6987,10 +6991,7 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea isIncremental = !budget.isUnlimited(); - if (useZeal && (hasZealMode(ZealMode::IncrementalRootsThenFinish) || - hasZealMode(ZealMode::IncrementalMarkAllThenFinish) || - hasZealMode(ZealMode::IncrementalSweepThenFinish))) - { + if (useZeal && hasIncrementalTwoSliceZealMode()) { /* * Yields between slices occurs at predetermined points in these modes; * the budget is not used. @@ -7021,7 +7022,7 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea incrementalState = State::Mark; - if (isIncremental && useZeal && hasZealMode(ZealMode::IncrementalRootsThenFinish)) + if (isIncremental && useZeal && hasZealMode(ZealMode::YieldBeforeMarking)) break; MOZ_FALLTHROUGH; @@ -7047,16 +7048,16 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea * the next slice, since the first slice of sweeping can be expensive. * * This is modified by the various zeal modes. We don't yield in - * IncrementalRootsThenFinish mode and we always yield in - * IncrementalMarkAllThenFinish mode. + * YieldBeforeMarking mode and we always yield in YieldBeforeSweeping + * mode. * * We will need to mark anything new on the stack when we resume, so * we stay in Mark state. */ if (!lastMarkSlice && isIncremental && ((initialState == State::Mark && - !(useZeal && hasZealMode(ZealMode::IncrementalRootsThenFinish))) || - (useZeal && hasZealMode(ZealMode::IncrementalMarkAllThenFinish)))) + !(useZeal && hasZealMode(ZealMode::YieldBeforeMarking))) || + (useZeal && hasZealMode(ZealMode::YieldBeforeSweeping)))) { lastMarkSlice = true; break; @@ -8067,43 +8068,37 @@ GCRuntime::runDebugGC() PrepareForDebugGC(rt); auto budget = SliceBudget::unlimited(); - if (hasZealMode(ZealMode::IncrementalRootsThenFinish) || - hasZealMode(ZealMode::IncrementalMarkAllThenFinish) || - hasZealMode(ZealMode::IncrementalMultipleSlices) || - hasZealMode(ZealMode::IncrementalSweepThenFinish)) - { - js::gc::State initialState = incrementalState; - if (hasZealMode(ZealMode::IncrementalMultipleSlices)) { - /* - * Start with a small slice limit and double it every slice. This - * ensure that we get multiple slices, and collection runs to - * completion. - */ - if (!isIncrementalGCInProgress()) - incrementalLimit = zealFrequency / 2; - else - incrementalLimit *= 2; - budget = SliceBudget(WorkBudget(incrementalLimit)); - } else { - // This triggers incremental GC but is actually ignored by IncrementalMarkSlice. - budget = SliceBudget(WorkBudget(1)); - } + if (hasZealMode(ZealMode::IncrementalMultipleSlices)) { + /* + * Start with a small slice limit and double it every slice. This + * ensure that we get multiple slices, and collection runs to + * completion. + */ + if (!isIncrementalGCInProgress()) + incrementalLimit = zealFrequency / 2; + else + incrementalLimit *= 2; + budget = SliceBudget(WorkBudget(incrementalLimit)); + js::gc::State initialState = incrementalState; if (!isIncrementalGCInProgress()) invocationKind = GC_SHRINK; collect(false, budget, JS::gcreason::DEBUG_GC); - /* - * For multi-slice zeal, reset the slice size when we get to the sweep - * or compact phases. - */ - if (hasZealMode(ZealMode::IncrementalMultipleSlices)) { - if ((initialState == State::Mark && incrementalState == State::Sweep) || - (initialState == State::Sweep && incrementalState == State::Compact)) - { - incrementalLimit = zealFrequency / 2; - } + /* Reset the slice size when we get to the sweep or compact phases. */ + if ((initialState == State::Mark && incrementalState == State::Sweep) || + (initialState == State::Sweep && incrementalState == State::Compact)) + { + incrementalLimit = zealFrequency / 2; } + } else if (hasIncrementalTwoSliceZealMode()) { + // These modes trigger incremental GC that happens in two slices and the + // supplied budget is ignored by incrementalCollectSlice. + budget = SliceBudget(WorkBudget(1)); + + if (!isIncrementalGCInProgress()) + invocationKind = GC_NORMAL; + collect(false, budget, JS::gcreason::DEBUG_GC); } else if (hasZealMode(ZealMode::Compact)) { gc(GC_SHRINK, JS::gcreason::DEBUG_GC); } else { diff --git a/js/src/gc/GCEnum.h b/js/src/gc/GCEnum.h index 80fd9cd8a0b9..6829e4d710f8 100644 --- a/js/src/gc/GCEnum.h +++ b/js/src/gc/GCEnum.h @@ -62,8 +62,8 @@ enum class AbortReason { D(Alloc, 2) \ D(VerifierPre, 4) \ D(GenerationalGC, 7) \ - D(IncrementalRootsThenFinish, 8) \ - D(IncrementalMarkAllThenFinish, 9) \ + D(YieldBeforeMarking, 8) \ + D(YieldBeforeSweeping, 9) \ D(IncrementalMultipleSlices, 10) \ D(IncrementalMarkingValidator, 11) \ D(ElementsBarrier, 12) \ @@ -71,7 +71,7 @@ enum class AbortReason { D(Compact, 14) \ D(CheckHeapAfterGC, 15) \ D(CheckNursery, 16) \ - D(IncrementalSweepThenFinish, 17) \ + D(YieldBeforeSweepingAtoms, 17) \ D(CheckGrayMarking, 18) enum class ZealMode { diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index 0baf2a95e668..be26bc1dfb0e 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -230,6 +230,7 @@ class GCRuntime inline void clearZealMode(ZealMode mode); inline bool upcomingZealousGC(); inline bool needZealousGC(); + inline bool hasIncrementalTwoSliceZealMode(); MOZ_MUST_USE bool addRoot(Value* vp, const char* name); void removeRoot(Value* vp); @@ -1026,11 +1027,11 @@ GCRuntime::needZealousGC() { if (nextScheduled > 0 && --nextScheduled == 0) { if (hasZealMode(ZealMode::Alloc) || hasZealMode(ZealMode::GenerationalGC) || - hasZealMode(ZealMode::IncrementalRootsThenFinish) || - hasZealMode(ZealMode::IncrementalMarkAllThenFinish) || + hasZealMode(ZealMode::YieldBeforeMarking) || + hasZealMode(ZealMode::YieldBeforeSweeping) || hasZealMode(ZealMode::IncrementalMultipleSlices) || hasZealMode(ZealMode::Compact) || - hasZealMode(ZealMode::IncrementalSweepThenFinish)) + hasZealMode(ZealMode::YieldBeforeSweepingAtoms)) { nextScheduled = zealFrequency; } @@ -1038,11 +1039,20 @@ GCRuntime::needZealousGC() { } return false; } + +inline bool +GCRuntime::hasIncrementalTwoSliceZealMode() { + return hasZealMode(ZealMode::YieldBeforeMarking) || + hasZealMode(ZealMode::YieldBeforeSweeping) || + hasZealMode(ZealMode::YieldBeforeSweepingAtoms); +} + #else inline bool GCRuntime::hasZealMode(ZealMode mode) { return false; } inline void GCRuntime::clearZealMode(ZealMode mode) { } inline bool GCRuntime::upcomingZealousGC() { return false; } inline bool GCRuntime::needZealousGC() { return false; } +inline bool GCRuntime::hasIncrementalTwoSliceZealMode() { return false; } #endif } /* namespace gc */ From 9c2e6f6917e5715819fd986e5695ad9cc28f7bcc Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Tue, 17 Apr 2018 08:44:56 +0200 Subject: [PATCH 07/52] Bug 1453028 - Add a new sweep action to yield in a specified zeal mode r=sfink --- js/src/gc/GC.cpp | 62 ++++++++++++++++++++++++++++++++++++++----- js/src/gc/GCRuntime.h | 1 + 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp index 309843a45dd3..a9eee360d651 100644 --- a/js/src/gc/GC.cpp +++ b/js/src/gc/GC.cpp @@ -5735,6 +5735,14 @@ GCRuntime::beginSweepingSweepGroup(FreeOp* fop, SliceBudget& budget) } #ifdef JS_GC_ZEAL + +bool +GCRuntime::shouldYieldForZeal(ZealMode mode) +{ + MOZ_ASSERT_IF(useZeal, isIncremental); + return useZeal && hasZealMode(mode); +} + IncrementalProgress GCRuntime::maybeYieldForSweepingZeal(FreeOp* fop, SliceBudget& budget) { @@ -5743,15 +5751,12 @@ GCRuntime::maybeYieldForSweepingZeal(FreeOp* fop, SliceBudget& budget) * in incremental multi-slice zeal mode so RunDebugGC can reset the slice * budget. */ - if (isIncremental && useZeal && initialState != State::Sweep && - (hasZealMode(ZealMode::IncrementalMultipleSlices) || - hasZealMode(ZealMode::YieldBeforeSweepingAtoms))) - { + if (initialState != State::Sweep && shouldYieldForZeal(ZealMode::IncrementalMultipleSlices)) return NotFinished; - } return Finished; } + #endif IncrementalProgress @@ -6282,6 +6287,38 @@ class SweepActionCall final : public SweepAction void assertFinished() const override { } }; +#ifdef JS_GC_ZEAL +// Implementation of the SweepAction interface that yields in a specified zeal +// mode and then calls another action. +template +class SweepActionMaybeYield final : public SweepAction +{ + using Action = SweepAction; + + ZealMode mode; + UniquePtr action; + bool triggered; + + public: + SweepActionMaybeYield(UniquePtr action, ZealMode mode) + : mode(mode), action(Move(action)), triggered(false) {} + + IncrementalProgress run(GCRuntime* gc, Args... args) override { + if (!triggered && gc->shouldYieldForZeal(mode)) { + triggered = true; + return NotFinished; + } + + triggered = false; + return action->run(gc, args...); + } + + void assertFinished() const override { + MOZ_ASSERT(!triggered); + } +}; +#endif + // Implementation of the SweepAction interface that calls a list of actions in // sequence. template @@ -6418,7 +6455,17 @@ class RemoveLastTemplateParameter> template static UniquePtr> Call(IncrementalProgress (GCRuntime::*method)(Args...)) { - return MakeUnique>(method); + return MakeUnique>(method); +} + +template +static UniquePtr> +MaybeYield(ZealMode zealMode, UniquePtr> action) { +#ifdef JS_GC_ZEAL + return js::MakeUnique>(Move(action), zealMode); +#else + return action; +#endif } template @@ -6484,7 +6531,8 @@ GCRuntime::initSweepActions() #ifdef JS_GC_ZEAL Call(&GCRuntime::maybeYieldForSweepingZeal), #endif - Call(&GCRuntime::sweepAtomsTable), + MaybeYield(ZealMode::YieldBeforeSweepingAtoms, + Call(&GCRuntime::sweepAtomsTable)), Call(&GCRuntime::sweepWeakCaches), ForEachZoneInSweepGroup(rt, Sequence( diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index be26bc1dfb0e..21c3c411ab5d 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -447,6 +447,7 @@ class GCRuntime void endVerifyPreBarriers(); void finishVerifier(); bool isVerifyPreBarriersEnabled() const { return !!verifyPreData; } + bool shouldYieldForZeal(ZealMode mode); #else bool isVerifyPreBarriersEnabled() const { return false; } #endif From 275c02545495af2fd56b4eddfcd684079feda223 Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Tue, 17 Apr 2018 08:44:56 +0200 Subject: [PATCH 08/52] Bug 1453028 - Add new zeal modes to test the different parts of incremental sweeping r=sfink --- js/src/gc/GC.cpp | 46 +++++++++++++------ js/src/gc/GCEnum.h | 37 ++++++++------- js/src/gc/GCRuntime.h | 11 +++-- js/src/jit-test/tests/gc/incremental-state.js | 28 +++++++---- js/src/jsapi-tests/testGCFinalizeCallback.cpp | 2 +- 5 files changed, 81 insertions(+), 43 deletions(-) diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp index a9eee360d651..28d6f69c5e3e 100644 --- a/js/src/gc/GC.cpp +++ b/js/src/gc/GC.cpp @@ -1039,7 +1039,17 @@ const char* gc::ZealModeHelpText = " 16: (CheckNursery) Check nursery integrity on minor GC\n" " 17: (YieldBeforeSweepingAtoms) Incremental GC in two slices that yields\n" " before sweeping the atoms table\n" - " 18: (CheckGrayMarking) Check gray marking invariants after every GC\n"; + " 18: (CheckGrayMarking) Check gray marking invariants after every GC\n" + " 19: (YieldBeforeSweepingCaches) Incremental GC in two slices that yields\n" + " before sweeping weak caches\n" + " 20: (YieldBeforeSweepingTypes) Incremental GC in two slices that yields\n" + " before sweeping type information\n" + " 21: (YieldBeforeSweepingObjects) Incremental GC in two slices that yields\n" + " before sweeping foreground finalized objects\n" + " 22: (YieldBeforeSweepingNonObjects) Incremental GC in two slices that yields\n" + " before sweeping non-object GC things\n" + " 23: (YieldBeforeSweepingShapeTrees) Incremental GC in two slices that yields\n" + " before sweeping shape trees\n"; // The set of zeal modes that control incremental slices. These modes are // mutually exclusive. @@ -1047,7 +1057,12 @@ static const mozilla::EnumSet IncrementalSliceZealModes = { ZealMode::YieldBeforeMarking, ZealMode::YieldBeforeSweeping, ZealMode::IncrementalMultipleSlices, - ZealMode::YieldBeforeSweepingAtoms + ZealMode::YieldBeforeSweepingAtoms, + ZealMode::YieldBeforeSweepingCaches, + ZealMode::YieldBeforeSweepingTypes, + ZealMode::YieldBeforeSweepingObjects, + ZealMode::YieldBeforeSweepingNonObjects, + ZealMode::YieldBeforeSweepingShapeTrees }; void @@ -4991,12 +5006,10 @@ GCRuntime::groupZonesForSweeping(JS::gcreason::Reason reason) finder.useOneComponent(); #ifdef JS_GC_ZEAL - // Use one component for YieldBeforeSweepingAtoms zeal mode. - if (isIncremental && reason == JS::gcreason::DEBUG_GC && - hasZealMode(ZealMode::YieldBeforeSweepingAtoms)) - { + // Use one component for two-slice zeal modes. + MOZ_ASSERT_IF(useZeal, isIncremental); + if (useZeal && hasIncrementalTwoSliceZealMode()) finder.useOneComponent(); - } #endif for (GCZonesIter zone(rt); !zone.done(); zone.next()) { @@ -6533,15 +6546,20 @@ GCRuntime::initSweepActions() #endif MaybeYield(ZealMode::YieldBeforeSweepingAtoms, Call(&GCRuntime::sweepAtomsTable)), - Call(&GCRuntime::sweepWeakCaches), + MaybeYield(ZealMode::YieldBeforeSweepingCaches, + Call(&GCRuntime::sweepWeakCaches)), ForEachZoneInSweepGroup(rt, Sequence( - Call(&GCRuntime::sweepTypeInformation), - ForEachAllocKind(ForegroundObjectFinalizePhase.kinds, - Call(&GCRuntime::finalizeAllocKind)), - ForEachAllocKind(ForegroundNonObjectFinalizePhase.kinds, - Call(&GCRuntime::finalizeAllocKind)), - Call(&GCRuntime::sweepShapeTree), + MaybeYield(ZealMode::YieldBeforeSweepingTypes, + Call(&GCRuntime::sweepTypeInformation)), + MaybeYield(ZealMode::YieldBeforeSweepingObjects, + ForEachAllocKind(ForegroundObjectFinalizePhase.kinds, + Call(&GCRuntime::finalizeAllocKind))), + MaybeYield(ZealMode::YieldBeforeSweepingNonObjects, + ForEachAllocKind(ForegroundNonObjectFinalizePhase.kinds, + Call(&GCRuntime::finalizeAllocKind))), + MaybeYield(ZealMode::YieldBeforeSweepingShapeTrees, + Call(&GCRuntime::sweepShapeTree)), Call(&GCRuntime::releaseSweptEmptyArenas))), Call(&GCRuntime::endSweepingSweepGroup))); diff --git a/js/src/gc/GCEnum.h b/js/src/gc/GCEnum.h index 6829e4d710f8..83cc9d24a042 100644 --- a/js/src/gc/GCEnum.h +++ b/js/src/gc/GCEnum.h @@ -57,22 +57,27 @@ enum class AbortReason { #undef MAKE_REASON }; -#define JS_FOR_EACH_ZEAL_MODE(D) \ - D(RootsChange, 1) \ - D(Alloc, 2) \ - D(VerifierPre, 4) \ - D(GenerationalGC, 7) \ - D(YieldBeforeMarking, 8) \ - D(YieldBeforeSweeping, 9) \ - D(IncrementalMultipleSlices, 10) \ - D(IncrementalMarkingValidator, 11) \ - D(ElementsBarrier, 12) \ - D(CheckHashTablesOnMinorGC, 13) \ - D(Compact, 14) \ - D(CheckHeapAfterGC, 15) \ - D(CheckNursery, 16) \ - D(YieldBeforeSweepingAtoms, 17) \ - D(CheckGrayMarking, 18) +#define JS_FOR_EACH_ZEAL_MODE(D) \ + D(RootsChange, 1) \ + D(Alloc, 2) \ + D(VerifierPre, 4) \ + D(GenerationalGC, 7) \ + D(YieldBeforeMarking, 8) \ + D(YieldBeforeSweeping, 9) \ + D(IncrementalMultipleSlices, 10) \ + D(IncrementalMarkingValidator, 11) \ + D(ElementsBarrier, 12) \ + D(CheckHashTablesOnMinorGC, 13) \ + D(Compact, 14) \ + D(CheckHeapAfterGC, 15) \ + D(CheckNursery, 16) \ + D(YieldBeforeSweepingAtoms, 17) \ + D(CheckGrayMarking, 18) \ + D(YieldBeforeSweepingCaches, 19) \ + D(YieldBeforeSweepingTypes, 20) \ + D(YieldBeforeSweepingObjects, 21) \ + D(YieldBeforeSweepingNonObjects, 22) \ + D(YieldBeforeSweepingShapeTrees, 23) enum class ZealMode { #define ZEAL_MODE(name, value) name = value, diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index 21c3c411ab5d..2390d31391d7 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -1028,11 +1028,9 @@ GCRuntime::needZealousGC() { if (nextScheduled > 0 && --nextScheduled == 0) { if (hasZealMode(ZealMode::Alloc) || hasZealMode(ZealMode::GenerationalGC) || - hasZealMode(ZealMode::YieldBeforeMarking) || - hasZealMode(ZealMode::YieldBeforeSweeping) || hasZealMode(ZealMode::IncrementalMultipleSlices) || hasZealMode(ZealMode::Compact) || - hasZealMode(ZealMode::YieldBeforeSweepingAtoms)) + hasIncrementalTwoSliceZealMode()) { nextScheduled = zealFrequency; } @@ -1045,7 +1043,12 @@ inline bool GCRuntime::hasIncrementalTwoSliceZealMode() { return hasZealMode(ZealMode::YieldBeforeMarking) || hasZealMode(ZealMode::YieldBeforeSweeping) || - hasZealMode(ZealMode::YieldBeforeSweepingAtoms); + hasZealMode(ZealMode::YieldBeforeSweepingAtoms) || + hasZealMode(ZealMode::YieldBeforeSweepingCaches) || + hasZealMode(ZealMode::YieldBeforeSweepingTypes) || + hasZealMode(ZealMode::YieldBeforeSweepingObjects) || + hasZealMode(ZealMode::YieldBeforeSweepingNonObjects) || + hasZealMode(ZealMode::YieldBeforeSweepingShapeTrees); } #else diff --git a/js/src/jit-test/tests/gc/incremental-state.js b/js/src/jit-test/tests/gc/incremental-state.js index 6a3a887affcd..22af2ecda153 100644 --- a/js/src/jit-test/tests/gc/incremental-state.js +++ b/js/src/jit-test/tests/gc/incremental-state.js @@ -56,11 +56,23 @@ while (gcstate() == "Finalize") { gcslice(1); } while (gcstate() == "Decommit") { gcslice(1); } assertEq(gcstate(), "NotActive"); -// Zeal mode 17: Incremental GC in two slices: -// 1) mark everything and start sweeping -// 2) finish sweeping -gczeal(17, 0); -gcslice(1); -assertEq(gcstate(), "Sweep"); -gcslice(1); -assertEq(gcstate(), "NotActive"); +// Two-slice zeal modes that yield once during sweeping. +for (let mode of [ 17, 19 ]) { + print(mode); + gczeal(mode, 0); + gcslice(1); + assertEq(gcstate(), "Sweep"); + gcslice(1); + assertEq(gcstate(), "NotActive"); +} + +// Two-slice zeal modes that yield per-zone during sweeping. +const sweepingZealModes = [ 20, 21, 22, 23 ]; +for (let mode of sweepingZealModes) { + print(mode); + gczeal(mode, 0); + gcslice(1); + while (gcstate() === "Sweep") + gcslice(1); + assertEq(gcstate(), "NotActive"); +} diff --git a/js/src/jsapi-tests/testGCFinalizeCallback.cpp b/js/src/jsapi-tests/testGCFinalizeCallback.cpp index 669080b2ee3e..8136e02ec702 100644 --- a/js/src/jsapi-tests/testGCFinalizeCallback.cpp +++ b/js/src/jsapi-tests/testGCFinalizeCallback.cpp @@ -111,7 +111,7 @@ BEGIN_TEST(testGCFinalizeCallback) while (cx->runtime()->gc.isIncrementalGCInProgress()) cx->runtime()->gc.debugGCSlice(budget); CHECK(!cx->runtime()->gc.isIncrementalGCInProgress()); - CHECK(checkMultipleGroups()); + CHECK(checkSingleGroup()); CHECK(checkFinalizeStatus()); JS_SetGCZeal(cx, 0, 0); From 957369ecbec66c19d15773b8ad42a38c90f64d72 Mon Sep 17 00:00:00 2001 From: Simon Fraser Date: Tue, 17 Apr 2018 08:03:54 +0100 Subject: [PATCH 09/52] Bug 1454411 Update stat calls in funsize r=catlee Reviewers: catlee Reviewed By: catlee Bug #: 1454411 Differential Revision: https://phabricator.services.mozilla.com/D952 --HG-- extra : rebase_source : 3cd2e0499436eb72be3427881627142e606e8edd --- .../docker/funsize-update-generator/scripts/mbsdiff_hook.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/taskcluster/docker/funsize-update-generator/scripts/mbsdiff_hook.sh b/taskcluster/docker/funsize-update-generator/scripts/mbsdiff_hook.sh index da7f3364a6da..3ffcbb5798f7 100755 --- a/taskcluster/docker/funsize-update-generator/scripts/mbsdiff_hook.sh +++ b/taskcluster/docker/funsize-update-generator/scripts/mbsdiff_hook.sh @@ -62,7 +62,7 @@ print_usage(){ } upload_patch(){ - if [ "$(stat -f "%z" "$2")" -lt ${CACHE_THRESHOLD} ] + if [ "$(stat -c "%s" "$2")" -lt ${CACHE_THRESHOLD} ] then return 0 fi @@ -94,7 +94,7 @@ upload_patch(){ get_patch(){ # $1 and $2 are the /path/to/filename - if [ "$(stat -f "%z" "$2")" -lt ${CACHE_THRESHOLD} ] + if [ "$(stat -c "%s" "$2")" -lt ${CACHE_THRESHOLD} ] then return 1 fi From fd7a2a8cc5de84dd5545c92a8596ab23b92b0705 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Mon, 16 Apr 2018 10:13:57 +0200 Subject: [PATCH 10/52] Bug 1454161: Make --wasm-gc a no-op in non-Nightly builds; r=lth MozReview-Commit-ID: AynuyMIj9Rz --HG-- extra : rebase_source : 8f6992520635ad558095ad01fca72d5f6ff39413 extra : amend_source : ff1dba5e050dd9f453a81bab40a9eea2d14b5497 --- js/src/shell/js.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index c8f0571c7744..351f1db37fe3 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -8862,6 +8862,8 @@ main(int argc, char** argv, char** envp) "instantiation on completion of tier2") #ifdef ENABLE_WASM_GC || !op.addBoolOption('\0', "wasm-gc", "Enable wasm GC features") +#else + || !op.addBoolOption('\0', "wasm-gc", "No-op") #endif || !op.addBoolOption('\0', "no-native-regexp", "Disable native regexp compilation") || !op.addBoolOption('\0', "no-unboxed-objects", "Disable creating unboxed plain objects") From 050bda2db54c14f41e7024d064aa804a555fd29c Mon Sep 17 00:00:00 2001 From: Jan de Mooij Date: Tue, 17 Apr 2018 10:47:33 +0200 Subject: [PATCH 11/52] Bug 1452982 part 11 - Rename ActiveThread to MainThread. r=jonco --- js/src/gc/ArenaList.h | 2 +- js/src/gc/GCHelperState.h | 2 +- js/src/gc/GCMarker.h | 22 +++--- js/src/gc/GCParallelTask.h | 2 +- js/src/gc/GCRuntime.h | 120 ++++++++++++++--------------- js/src/gc/Scheduling.h | 24 +++--- js/src/gc/Zone.h | 10 +-- js/src/jit/JitCompartment.h | 10 +-- js/src/threading/ProtectedData.cpp | 8 +- js/src/threading/ProtectedData.h | 21 +++-- js/src/vm/Runtime.h | 70 ++++++++--------- 11 files changed, 145 insertions(+), 146 deletions(-) diff --git a/js/src/gc/ArenaList.h b/js/src/gc/ArenaList.h index 1fb151add161..8ad5ad6678a8 100644 --- a/js/src/gc/ArenaList.h +++ b/js/src/gc/ArenaList.h @@ -251,7 +251,7 @@ class ArenaLists const BackgroundFinalizeState& backgroundFinalizeState(AllocKind i) const { return backgroundFinalizeState_.ref()[i]; } /* For each arena kind, a list of arenas remaining to be swept. */ - ActiveThreadOrGCTaskData> arenaListsToSweep_; + MainThreadOrGCTaskData> arenaListsToSweep_; Arena*& arenaListsToSweep(AllocKind i) { return arenaListsToSweep_.ref()[i]; } Arena* arenaListsToSweep(AllocKind i) const { return arenaListsToSweep_.ref()[i]; } diff --git a/js/src/gc/GCHelperState.h b/js/src/gc/GCHelperState.h index 7bf031ca6478..d41b9a16ad77 100644 --- a/js/src/gc/GCHelperState.h +++ b/js/src/gc/GCHelperState.h @@ -42,7 +42,7 @@ class GCHelperState ConditionVariable done; // Activity for the helper to do, protected by the GC lock. - ActiveThreadOrGCTaskData state_; + MainThreadOrGCTaskData state_; // Whether work is being performed on some thread. GCLockData hasThread; diff --git a/js/src/gc/GCMarker.h b/js/src/gc/GCMarker.h index a84a02916cb4..30e7b64f5acd 100644 --- a/js/src/gc/GCMarker.h +++ b/js/src/gc/GCMarker.h @@ -174,13 +174,13 @@ class MarkStack const TaggedPtr& peekPtr() const; MOZ_MUST_USE bool pushTaggedPtr(Tag tag, Cell* ptr); - ActiveThreadData stack_; - ActiveThreadData tos_; - ActiveThreadData end_; + MainThreadData stack_; + MainThreadData tos_; + MainThreadData end_; // The capacity we start with and reset() to. - ActiveThreadData baseCapacity_; - ActiveThreadData maxCapacity_; + MainThreadData baseCapacity_; + MainThreadData maxCapacity_; #ifdef DEBUG mutable size_t iteratorCount_; @@ -349,29 +349,29 @@ class GCMarker : public JSTracer gc::MarkStack stack; /* The color is only applied to objects and functions. */ - ActiveThreadData color; + MainThreadData color; /* Pointer to the top of the stack of arenas we are delaying marking on. */ - ActiveThreadData unmarkedArenaStackTop; + MainThreadData unmarkedArenaStackTop; /* * If the weakKeys table OOMs, disable the linear algorithm and fall back * to iterating until the next GC. */ - ActiveThreadData linearWeakMarkingDisabled_; + MainThreadData linearWeakMarkingDisabled_; #ifdef DEBUG /* Count of arenas that are currently in the stack. */ - ActiveThreadData markLaterArenas; + MainThreadData markLaterArenas; /* Assert that start and stop are called with correct ordering. */ - ActiveThreadData started; + MainThreadData started; /* * If this is true, all marked objects must belong to a compartment being * GCed. This is used to look for compartment bugs. */ - ActiveThreadData strictCompartmentChecking; + MainThreadData strictCompartmentChecking; #endif // DEBUG }; diff --git a/js/src/gc/GCParallelTask.h b/js/src/gc/GCParallelTask.h index 229a23c3def1..4cded1d6a1b2 100644 --- a/js/src/gc/GCParallelTask.h +++ b/js/src/gc/GCParallelTask.h @@ -28,7 +28,7 @@ class GCParallelTask UnprotectedData state; // Amount of time this task took to execute. - ActiveThreadOrGCTaskData duration_; + MainThreadOrGCTaskData duration_; explicit GCParallelTask(const GCParallelTask&) = delete; diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index 2390d31391d7..61592b0f0090 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -134,13 +134,13 @@ class BackgroundDecommitTask : public GCParallelTask void run() override; private: - ActiveThreadOrGCTaskData toDecommit; + MainThreadOrGCTaskData toDecommit; }; template struct Callback { - ActiveThreadOrGCTaskData op; - ActiveThreadOrGCTaskData data; + MainThreadOrGCTaskData op; + MainThreadOrGCTaskData data; Callback() : op(nullptr), data(nullptr) @@ -151,7 +151,7 @@ struct Callback { }; template -using CallbackVector = ActiveThreadData, 4, SystemAllocPolicy>>; +using CallbackVector = MainThreadData, 4, SystemAllocPolicy>>; template class ChainedIter @@ -645,7 +645,7 @@ class GCRuntime // All zones in the runtime, except the atoms zone. private: - ActiveThreadOrGCTaskData zones_; + MainThreadOrGCTaskData zones_; public: ZoneVector& zones() { return zones_.ref(); } @@ -692,7 +692,7 @@ class GCRuntime // so as to reduce the cost of operations on the available lists. GCLockData fullChunks_; - ActiveThreadData rootsHash; + MainThreadData rootsHash; // An incrementing id used to assign unique ids to cells that require one. mozilla::Atomic nextCellUniqueId_; @@ -701,23 +701,23 @@ class GCRuntime * Number of the committed arenas in all GC chunks including empty chunks. */ mozilla::Atomic numArenasFreeCommitted; - ActiveThreadData verifyPreData; + MainThreadData verifyPreData; private: UnprotectedData chunkAllocationSinceLastGC; - ActiveThreadData lastGCTime; + MainThreadData lastGCTime; /* * JSGC_MODE * prefs: javascript.options.mem.gc_per_zone and * javascript.options.mem.gc_incremental. */ - ActiveThreadData mode; + MainThreadData mode; mozilla::Atomic numActiveZoneIters; /* During shutdown, the GC needs to clean up every possible object. */ - ActiveThreadData cleanUpEverything; + MainThreadData cleanUpEverything; // Gray marking must be done after all black marking is complete. However, // we do not have write barriers on XPConnect roots. Therefore, XPConnect @@ -730,7 +730,7 @@ class GCRuntime Okay, Failed }; - ActiveThreadOrGCTaskData grayBufferState; + MainThreadOrGCTaskData grayBufferState; bool hasValidGrayRootsBuffer() const { return grayBufferState == GrayBufferState::Okay; } // Clear each zone's gray buffers, but do not change the current state. @@ -752,85 +752,85 @@ class GCRuntime private: /* Perform full GC if rt->keepAtoms() becomes false. */ - ActiveThreadData fullGCForAtomsRequested_; + MainThreadData fullGCForAtomsRequested_; /* Incremented at the start of every minor GC. */ - ActiveThreadData minorGCNumber; + MainThreadData minorGCNumber; /* Incremented at the start of every major GC. */ - ActiveThreadData majorGCNumber; + MainThreadData majorGCNumber; /* The major GC number at which to release observed type information. */ - ActiveThreadData jitReleaseNumber; + MainThreadData jitReleaseNumber; /* Incremented on every GC slice. */ - ActiveThreadData number; + MainThreadData number; /* Whether the currently running GC can finish in multiple slices. */ - ActiveThreadData isIncremental; + MainThreadData isIncremental; /* Whether all zones are being collected in first GC slice. */ - ActiveThreadData isFull; + MainThreadData isFull; /* Whether the heap will be compacted at the end of GC. */ - ActiveThreadData isCompacting; + MainThreadData isCompacting; /* The invocation kind of the current GC, taken from the first slice. */ - ActiveThreadData invocationKind; + MainThreadData invocationKind; /* The initial GC reason, taken from the first slice. */ - ActiveThreadData initialReason; + MainThreadData initialReason; /* * The current incremental GC phase. This is also used internally in * non-incremental GC. */ - ActiveThreadOrGCTaskData incrementalState; + MainThreadOrGCTaskData incrementalState; /* The incremental state at the start of this slice. */ - ActiveThreadData initialState; + MainThreadData initialState; #ifdef JS_GC_ZEAL /* Whether to pay attention the zeal settings in this incremental slice. */ - ActiveThreadData useZeal; + MainThreadData useZeal; #endif /* Indicates that the last incremental slice exhausted the mark stack. */ - ActiveThreadData lastMarkSlice; + MainThreadData lastMarkSlice; /* Whether it's currently safe to yield to the mutator in an incremental GC. */ - ActiveThreadData safeToYield; + MainThreadData safeToYield; /* Whether any sweeping will take place in the separate GC helper thread. */ - ActiveThreadData sweepOnBackgroundThread; + MainThreadData sweepOnBackgroundThread; /* Whether observed type information is being released in the current GC. */ - ActiveThreadData releaseObservedTypes; + MainThreadData releaseObservedTypes; /* Singly linked list of zones to be swept in the background. */ - ActiveThreadOrGCTaskData backgroundSweepZones; + MainThreadOrGCTaskData backgroundSweepZones; /* * Free LIFO blocks are transferred to this allocator before being freed on * the background GC thread after sweeping. */ - ActiveThreadOrGCTaskData blocksToFreeAfterSweeping; + MainThreadOrGCTaskData blocksToFreeAfterSweeping; private: /* Index of current sweep group (for stats). */ - ActiveThreadData sweepGroupIndex; + MainThreadData sweepGroupIndex; /* * Incremental sweep state. */ - ActiveThreadData sweepGroups; - ActiveThreadOrGCTaskData currentSweepGroup; - ActiveThreadData>> sweepActions; - ActiveThreadOrGCTaskData sweepZone; - ActiveThreadData> maybeAtomsToSweep; - ActiveThreadOrGCTaskData sweepCache; - ActiveThreadData abortSweepAfterCurrentGroup; + MainThreadData sweepGroups; + MainThreadOrGCTaskData currentSweepGroup; + MainThreadData>> sweepActions; + MainThreadOrGCTaskData sweepZone; + MainThreadData> maybeAtomsToSweep; + MainThreadOrGCTaskData sweepCache; + MainThreadData abortSweepAfterCurrentGroup; friend class SweepGroupsIter; friend class WeakCacheSweepIterator; @@ -838,12 +838,12 @@ class GCRuntime /* * Incremental compacting state. */ - ActiveThreadData startedCompacting; - ActiveThreadData zonesToMaybeCompact; - ActiveThreadData relocatedArenasToRelease; + MainThreadData startedCompacting; + MainThreadData zonesToMaybeCompact; + MainThreadData relocatedArenasToRelease; #ifdef JS_GC_ZEAL - ActiveThreadData markingValidator; + MainThreadData markingValidator; #endif /* @@ -852,13 +852,13 @@ class GCRuntime * JSGC_SLICE_TIME_BUDGET * pref: javascript.options.mem.gc_incremental_slice_ms, */ - ActiveThreadData defaultTimeBudget_; + MainThreadData defaultTimeBudget_; /* * We disable incremental GC if we encounter a Class with a trace hook * that does not implement write barriers. */ - ActiveThreadData incrementalAllowed; + MainThreadData incrementalAllowed; /* * Whether compacting GC can is enabled globally. @@ -866,9 +866,9 @@ class GCRuntime * JSGC_COMPACTING_ENABLED * pref: javascript.options.mem.gc_compacting */ - ActiveThreadData compactingEnabled; + MainThreadData compactingEnabled; - ActiveThreadData rootsRemoved; + MainThreadData rootsRemoved; /* * These options control the zealousness of the GC. At every allocation, @@ -898,18 +898,18 @@ class GCRuntime #ifdef JS_GC_ZEAL static_assert(size_t(ZealMode::Count) <= 32, "Too many zeal modes to store in a uint32_t"); - ActiveThreadData zealModeBits; - ActiveThreadData zealFrequency; - ActiveThreadData nextScheduled; - ActiveThreadData deterministicOnly; - ActiveThreadData incrementalLimit; + MainThreadData zealModeBits; + MainThreadData zealFrequency; + MainThreadData nextScheduled; + MainThreadData deterministicOnly; + MainThreadData incrementalLimit; - ActiveThreadData> selectedForMarking; + MainThreadData> selectedForMarking; #endif - ActiveThreadData fullCompartmentChecks; + MainThreadData fullCompartmentChecks; - ActiveThreadData gcCallbackDepth; + MainThreadData gcCallbackDepth; Callback gcCallback; Callback gcDoCycleCollectionCallback; @@ -930,10 +930,10 @@ class GCRuntime Callback grayRootTracer; /* Always preserve JIT code during GCs, for testing. */ - ActiveThreadData alwaysPreserveCode; + MainThreadData alwaysPreserveCode; #ifdef DEBUG - ActiveThreadData arenasEmptyAtShutdown; + MainThreadData arenasEmptyAtShutdown; #endif /* Synchronize GC heap access among GC helper threads and active threads. */ @@ -950,18 +950,18 @@ class GCRuntime * During incremental sweeping, this field temporarily holds the arenas of * the current AllocKind being swept in order of increasing free space. */ - ActiveThreadData incrementalSweepList; + MainThreadData incrementalSweepList; private: - ActiveThreadData nursery_; - ActiveThreadData storeBuffer_; + MainThreadData nursery_; + MainThreadData storeBuffer_; public: Nursery& nursery() { return nursery_.ref(); } gc::StoreBuffer& storeBuffer() { return storeBuffer_.ref(); } // Free LIFO blocks are transferred to this allocator before being freed // after minor GC. - ActiveThreadData blocksToFreeAfterMinorGC; + MainThreadData blocksToFreeAfterMinorGC; const void* addressOfNurseryPosition() { return nursery_.refNoCheck().addressOfPosition(); diff --git a/js/src/gc/Scheduling.h b/js/src/gc/Scheduling.h index 9511a335a384..06bbe7a89c9e 100644 --- a/js/src/gc/Scheduling.h +++ b/js/src/gc/Scheduling.h @@ -342,7 +342,7 @@ class GCSchedulingTunables * * Maximum nursery size for each runtime. */ - ActiveThreadData gcMaxNurseryBytes_; + MainThreadData gcMaxNurseryBytes_; /* * JSGC_ALLOCATION_THRESHOLD @@ -351,7 +351,7 @@ class GCSchedulingTunables * usage.gcBytes() surpasses threshold.gcTriggerBytes() for a zone, the * zone may be scheduled for a GC, depending on the exact circumstances. */ - ActiveThreadOrGCTaskData gcZoneAllocThresholdBase_; + MainThreadOrGCTaskData gcZoneAllocThresholdBase_; /* * JSGC_ALLOCATION_THRESHOLD_FACTOR @@ -381,7 +381,7 @@ class GCSchedulingTunables * Totally disables |highFrequencyGC|, the HeapGrowthFactor, and other * tunables that make GC non-deterministic. */ - ActiveThreadData dynamicHeapGrowthEnabled_; + MainThreadData dynamicHeapGrowthEnabled_; /* * JSGC_HIGH_FREQUENCY_TIME_LIMIT @@ -389,7 +389,7 @@ class GCSchedulingTunables * We enter high-frequency mode if we GC a twice within this many * microseconds. This value is stored directly in microseconds. */ - ActiveThreadData highFrequencyThresholdUsec_; + MainThreadData highFrequencyThresholdUsec_; /* * JSGC_HIGH_FREQUENCY_LOW_LIMIT @@ -400,10 +400,10 @@ class GCSchedulingTunables * When in the |highFrequencyGC| mode, these parameterize the per-zone * "HeapGrowthFactor" computation. */ - ActiveThreadData highFrequencyLowLimitBytes_; - ActiveThreadData highFrequencyHighLimitBytes_; - ActiveThreadData highFrequencyHeapGrowthMax_; - ActiveThreadData highFrequencyHeapGrowthMin_; + MainThreadData highFrequencyLowLimitBytes_; + MainThreadData highFrequencyHighLimitBytes_; + MainThreadData highFrequencyHeapGrowthMax_; + MainThreadData highFrequencyHeapGrowthMin_; /* * JSGC_LOW_FREQUENCY_HEAP_GROWTH @@ -411,14 +411,14 @@ class GCSchedulingTunables * When not in |highFrequencyGC| mode, this is the global (stored per-zone) * "HeapGrowthFactor". */ - ActiveThreadData lowFrequencyHeapGrowth_; + MainThreadData lowFrequencyHeapGrowth_; /* * JSGC_DYNAMIC_MARK_SLICE * * Doubles the length of IGC slices when in the |highFrequencyGC| mode. */ - ActiveThreadData dynamicMarkSliceEnabled_; + MainThreadData dynamicMarkSliceEnabled_; /* * JSGC_MIN_EMPTY_CHUNK_COUNT @@ -473,7 +473,7 @@ class GCSchedulingState * growth factor is a measure of how large (as a percentage of the last GC) * the heap is allowed to grow before we try to schedule another GC. */ - ActiveThreadData inHighFrequencyGCMode_; + MainThreadData inHighFrequencyGCMode_; public: GCSchedulingState() @@ -500,7 +500,7 @@ class MemoryCounter size_t maxBytes_; // The counter value at the start of a GC. - ActiveThreadData bytesAtStartOfGC_; + MainThreadData bytesAtStartOfGC_; // Which kind of GC has been triggered if any. mozilla::Atomic triggered_; diff --git a/js/src/gc/Zone.h b/js/src/gc/Zone.h index 612b0283adb0..bfbab9b05319 100644 --- a/js/src/gc/Zone.h +++ b/js/src/gc/Zone.h @@ -307,7 +307,7 @@ struct Zone : public JS::shadow::Zone, private: // The set of compartments in this zone. - js::ActiveThreadOrGCTaskData compartments_; + js::MainThreadOrGCTaskData compartments_; public: CompartmentVector& compartments() { return compartments_.ref(); } @@ -349,7 +349,7 @@ struct Zone : public JS::shadow::Zone, // // This is used during GC while calculating sweep groups to record edges // that can't be determined by examining this zone by itself. - js::ActiveThreadData gcSweepGroupEdges_; + js::MainThreadData gcSweepGroupEdges_; public: ZoneSet& gcSweepGroupEdges() { return gcSweepGroupEdges_.ref(); } @@ -705,15 +705,15 @@ struct Zone : public JS::shadow::Zone, private: js::ZoneData jitZone_; - js::ActiveThreadData gcScheduled_; - js::ActiveThreadData gcScheduledSaved_; + js::MainThreadData gcScheduled_; + js::MainThreadData gcScheduledSaved_; js::ZoneData gcPreserveCode_; js::ZoneData keepShapeTables_; // Allow zones to be linked into a list friend class js::gc::ZoneList; static Zone * const NotOnList; - js::ActiveThreadOrGCTaskData listNext_; + js::MainThreadOrGCTaskData listNext_; bool isOnList() const; Zone* nextZone() const; diff --git a/js/src/jit/JitCompartment.h b/js/src/jit/JitCompartment.h index 3094ef5e681f..7d895b1ea132 100644 --- a/js/src/jit/JitCompartment.h +++ b/js/src/jit/JitCompartment.h @@ -62,9 +62,9 @@ class JitRuntime friend class JitCompartment; // Executable allocator for all code except wasm code. - ActiveThreadData execAlloc_; + MainThreadData execAlloc_; - ActiveThreadData nextCompilationId_; + MainThreadData nextCompilationId_; // Shared exception-handler tail. ExclusiveAccessLockWriteOnceData exceptionTailOffset_; @@ -138,7 +138,7 @@ class JitRuntime #ifdef DEBUG // The number of possible bailing places encounters before forcefully bailing // in that place. Zero means inactive. - ActiveThreadData ionBailAfter_; + MainThreadData ionBailAfter_; #endif // Number of Ion compilations which were finished off thread and are @@ -148,8 +148,8 @@ class JitRuntime // List of Ion compilation waiting to get linked. using IonBuilderList = mozilla::LinkedList; - ActiveThreadData ionLazyLinkList_; - ActiveThreadData ionLazyLinkListSize_; + MainThreadData ionLazyLinkList_; + MainThreadData ionLazyLinkListSize_; private: void generateLazyLinkStub(MacroAssembler& masm); diff --git a/js/src/threading/ProtectedData.cpp b/js/src/threading/ProtectedData.cpp index 1347c9166366..69ed663b609e 100644 --- a/js/src/threading/ProtectedData.cpp +++ b/js/src/threading/ProtectedData.cpp @@ -50,7 +50,7 @@ CheckThreadLocal::check() const template void -CheckActiveThread::check() const +CheckMainThread::check() const { if (OnHelperThread()) return; @@ -59,9 +59,9 @@ CheckActiveThread::check() const MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime())); } -template class CheckActiveThread; -template class CheckActiveThread; -template class CheckActiveThread; +template class CheckMainThread; +template class CheckMainThread; +template class CheckMainThread; template void diff --git a/js/src/threading/ProtectedData.h b/js/src/threading/ProtectedData.h index 27704eba332f..7dfbc17e07ce 100644 --- a/js/src/threading/ProtectedData.h +++ b/js/src/threading/ProtectedData.h @@ -202,26 +202,25 @@ enum class AllowedHelperThread }; template -class CheckActiveThread +class CheckMainThread { public: void check() const; }; -// Data which may only be accessed by the runtime's cooperatively scheduled -// active thread. +// Data which may only be accessed by the runtime's main thread. template -using ActiveThreadData = - ProtectedDataNoCheckArgs, T>; +using MainThreadData = + ProtectedDataNoCheckArgs, T>; -// Data which may only be accessed by the runtime's cooperatively scheduled -// active thread, or by various helper thread tasks. +// Data which may only be accessed by the runtime's main thread or by various +// helper thread tasks. template -using ActiveThreadOrGCTaskData = - ProtectedDataNoCheckArgs, T>; +using MainThreadOrGCTaskData = + ProtectedDataNoCheckArgs, T>; template -using ActiveThreadOrIonCompileData = - ProtectedDataNoCheckArgs, T>; +using MainThreadOrIonCompileData = + ProtectedDataNoCheckArgs, T>; template class CheckZone diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h index 5f457d32950a..c08811bc60f5 100644 --- a/js/src/vm/Runtime.h +++ b/js/src/vm/Runtime.h @@ -301,10 +301,10 @@ struct JSRuntime : public js::MallocProvider } /* Call this to accumulate telemetry data. */ - js::ActiveThreadData telemetryCallback; + js::MainThreadData telemetryCallback; /* Call this to accumulate use counter data. */ - js::ActiveThreadData useCounterCallback; + js::MainThreadData useCounterCallback; public: // Accumulates data for Firefox telemetry. |id| is the ID of a JS_TELEMETRY_* @@ -345,35 +345,35 @@ struct JSRuntime : public js::MallocProvider * Allow relazifying functions in compartments that are active. This is * only used by the relazifyFunctions() testing function. */ - js::ActiveThreadData allowRelazificationForTesting; + js::MainThreadData allowRelazificationForTesting; /* Compartment destroy callback. */ - js::ActiveThreadData destroyCompartmentCallback; + js::MainThreadData destroyCompartmentCallback; /* Compartment memory reporting callback. */ - js::ActiveThreadData sizeOfIncludingThisCompartmentCallback; + js::MainThreadData sizeOfIncludingThisCompartmentCallback; /* Call this to get the name of a compartment. */ - js::ActiveThreadData compartmentNameCallback; + js::MainThreadData compartmentNameCallback; /* Realm destroy callback. */ - js::ActiveThreadData destroyRealmCallback; + js::MainThreadData destroyRealmCallback; /* Call this to get the name of a realm. */ - js::ActiveThreadData realmNameCallback; + js::MainThreadData realmNameCallback; /* Callback for doing memory reporting on external strings. */ - js::ActiveThreadData externalStringSizeofCallback; + js::MainThreadData externalStringSizeofCallback; - js::ActiveThreadData> sourceHook; + js::MainThreadData> sourceHook; - js::ActiveThreadData securityCallbacks; - js::ActiveThreadData DOMcallbacks; - js::ActiveThreadData destroyPrincipals; - js::ActiveThreadData readPrincipals; + js::MainThreadData securityCallbacks; + js::MainThreadData DOMcallbacks; + js::MainThreadData destroyPrincipals; + js::MainThreadData readPrincipals; /* Optional warning reporter. */ - js::ActiveThreadData warningReporter; + js::MainThreadData warningReporter; private: /* Gecko profiling metadata */ @@ -382,7 +382,7 @@ struct JSRuntime : public js::MallocProvider js::GeckoProfilerRuntime& geckoProfiler() { return geckoProfiler_.ref(); } // Heap GC roots for PersistentRooted pointers. - js::ActiveThreadData>>> heapRoots; void tracePersistentRoots(JSTracer* trc); @@ -402,12 +402,12 @@ struct JSRuntime : public js::MallocProvider void setTrustedPrincipals(const JSPrincipals* p) { trustedPrincipals_ = p; } const JSPrincipals* trustedPrincipals() const { return trustedPrincipals_; } - js::ActiveThreadData wrapObjectCallbacks; - js::ActiveThreadData preserveWrapperCallback; + js::MainThreadData wrapObjectCallbacks; + js::MainThreadData preserveWrapperCallback; - js::ActiveThreadData scriptEnvironmentPreparer; + js::MainThreadData scriptEnvironmentPreparer; - js::ActiveThreadData ctypesActivityCallback; + js::MainThreadData ctypesActivityCallback; private: js::WriteOnceData windowProxyClass_; @@ -422,7 +422,7 @@ struct JSRuntime : public js::MallocProvider private: // List of non-ephemeron weak containers to sweep during beginSweepingSweepGroup. - js::ActiveThreadData> weakCaches_; + js::MainThreadData> weakCaches_; public: mozilla::LinkedList& weakCaches() { return weakCaches_.ref(); } void registerWeakCache(JS::detail::WeakCacheBase* cachep) { @@ -444,14 +444,14 @@ struct JSRuntime : public js::MallocProvider * List of all enabled Debuggers that have onNewGlobalObject handler * methods established. */ - js::ActiveThreadData onNewGlobalObjectWatchers_; + js::MainThreadData onNewGlobalObjectWatchers_; public: WatchersList& onNewGlobalObjectWatchers() { return onNewGlobalObjectWatchers_.ref(); } private: /* Linked list of all Debugger objects in the runtime. */ - js::ActiveThreadData> debuggerList_; + js::MainThreadData> debuggerList_; public: mozilla::LinkedList& debuggerList() { return debuggerList_.ref(); } @@ -516,19 +516,19 @@ struct JSRuntime : public js::MallocProvider // How many compartments there are across all zones. This number includes // off thread context compartments, so it isn't necessarily equal to the // number of compartments visited by CompartmentsIter. - js::ActiveThreadData numCompartments; + js::MainThreadData numCompartments; /* Locale-specific callbacks for string conversion. */ - js::ActiveThreadData localeCallbacks; + js::MainThreadData localeCallbacks; /* Default locale for Internationalization API */ - js::ActiveThreadData defaultLocale; + js::MainThreadData defaultLocale; /* If true, new scripts must be created with PC counter information. */ - js::ActiveThreadOrIonCompileData profilingScripts; + js::MainThreadOrIonCompileData profilingScripts; /* Strong references on scripts held for PCCount profiling API. */ - js::ActiveThreadData*> scriptAndCountsVector; + js::MainThreadData*> scriptAndCountsVector; private: /* Code coverage output. */ @@ -789,7 +789,7 @@ struct JSRuntime : public js::MallocProvider js::WriteOnceData wellKnownSymbols; /* Shared Intl data for this runtime. */ - js::ActiveThreadData sharedIntlData; + js::MainThreadData sharedIntlData; void traceSharedIntlData(JSTracer* trc); @@ -862,7 +862,7 @@ struct JSRuntime : public js::MallocProvider mozilla::Atomic offthreadIonCompilationEnabled_; mozilla::Atomic parallelParsingEnabled_; - js::ActiveThreadData autoWritableJitCodeActive_; + js::MainThreadData autoWritableJitCodeActive_; public: @@ -887,20 +887,20 @@ struct JSRuntime : public js::MallocProvider } /* See comment for JS::SetOutOfMemoryCallback in jsapi.h. */ - js::ActiveThreadData oomCallback; - js::ActiveThreadData oomCallbackData; + js::MainThreadData oomCallback; + js::MainThreadData oomCallbackData; /* * Debugger.Memory functions like takeCensus use this embedding-provided * function to assess the size of malloc'd blocks of memory. */ - js::ActiveThreadData debuggerMallocSizeOf; + js::MainThreadData debuggerMallocSizeOf; /* Last time at which an animation was played for this runtime. */ mozilla::Atomic lastAnimationTime; private: - js::ActiveThreadData performanceMonitoring_; + js::MainThreadData performanceMonitoring_; public: js::PerformanceMonitoring& performanceMonitoring() { return performanceMonitoring_.ref(); } @@ -930,7 +930,7 @@ struct JSRuntime : public js::MallocProvider friend class JS::AutoEnterCycleCollection; private: - js::ActiveThreadData caches_; + js::MainThreadData caches_; public: js::RuntimeCaches& caches() { return caches_.ref(); } From 3635c4e66f4b09bfd5d6210542e714af0afe84b2 Mon Sep 17 00:00:00 2001 From: Jan de Mooij Date: Tue, 17 Apr 2018 10:48:10 +0200 Subject: [PATCH 12/52] Bug 1452982 part 12 - Clean up ContextKind and CheckThreadLocal. r=jonco --- js/src/jsapi.cpp | 2 +- js/src/threading/ProtectedData.cpp | 11 +++-------- js/src/vm/HelperThreads.cpp | 2 +- js/src/vm/JSContext.cpp | 8 ++++---- js/src/vm/JSContext.h | 9 ++++++--- 5 files changed, 15 insertions(+), 17 deletions(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 79d58d2f5ee8..ff1461c73795 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1640,7 +1640,7 @@ JS_SetNativeStackQuota(JSContext* cx, size_t systemCodeStackSize, size_t trusted SetNativeStackQuotaAndLimit(cx, JS::StackForTrustedScript, trustedScriptStackSize); SetNativeStackQuotaAndLimit(cx, JS::StackForUntrustedScript, untrustedScriptStackSize); - if (cx->isCooperativelyScheduled()) + if (cx->isMainThreadContext()) cx->initJitStackLimit(); } diff --git a/js/src/threading/ProtectedData.cpp b/js/src/threading/ProtectedData.cpp index 69ed663b609e..b5baf9347379 100644 --- a/js/src/threading/ProtectedData.cpp +++ b/js/src/threading/ProtectedData.cpp @@ -38,14 +38,9 @@ CheckThreadLocal::check() const { JSContext* cx = TlsContext.get(); MOZ_ASSERT(cx); - - // As for CheckZone, in a cooperatively scheduled runtime the active - // thread is permitted access to thread local state for other suspended - // threads in the same runtime. - if (cx->isCooperativelyScheduled()) - MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime())); - else - MOZ_ASSERT(id == ThisThread::GetId()); + MOZ_ASSERT_IF(cx->isMainThreadContext(), + CurrentThreadCanAccessRuntime(cx->runtime())); + MOZ_ASSERT(id == ThisThread::GetId()); } template diff --git a/js/src/vm/HelperThreads.cpp b/js/src/vm/HelperThreads.cpp index 01fed75af133..b9dfdc8ef727 100644 --- a/js/src/vm/HelperThreads.cpp +++ b/js/src/vm/HelperThreads.cpp @@ -2224,7 +2224,7 @@ HelperThread::threadLoop() JSContext cx(nullptr, JS::ContextOptions()); { AutoEnterOOMUnsafeRegion oomUnsafe; - if (!cx.init(ContextKind::Background)) + if (!cx.init(ContextKind::HelperThread)) oomUnsafe.crash("HelperThread cx.init()"); } cx.setHelperThread(this); diff --git a/js/src/vm/JSContext.cpp b/js/src/vm/JSContext.cpp index 6e3f88dfaf29..1d9b1160db8c 100644 --- a/js/src/vm/JSContext.cpp +++ b/js/src/vm/JSContext.cpp @@ -100,7 +100,7 @@ bool JSContext::init(ContextKind kind) { // Skip most of the initialization if this thread will not be running JS. - if (kind == ContextKind::Cooperative) { + if (kind == ContextKind::MainThread) { if (!regexpStack.ref().init()) return false; @@ -153,7 +153,7 @@ js::NewContext(uint32_t maxBytes, uint32_t maxNurseryBytes, JSRuntime* parentRun return nullptr; } - if (!cx->init(ContextKind::Cooperative)) { + if (!cx->init(ContextKind::MainThread)) { runtime->destroyRuntime(); js_delete(cx); js_delete(runtime); @@ -1220,7 +1220,7 @@ JSContext::alreadyReportedError() JSContext::JSContext(JSRuntime* runtime, const JS::ContextOptions& options) : runtime_(runtime), - kind_(ContextKind::Background), + kind_(ContextKind::HelperThread), helperThread_(nullptr), options_(options), arenas_(nullptr), @@ -1318,7 +1318,7 @@ JSContext::~JSContext() { // Clear the ContextKind first, so that ProtectedData checks will allow us to // destroy this context even if the runtime is already gone. - kind_ = ContextKind::Background; + kind_ = ContextKind::HelperThread; /* Free the stuff hanging off of cx. */ MOZ_ASSERT(!resolvingList); diff --git a/js/src/vm/JSContext.h b/js/src/vm/JSContext.h index da50d3af015a..2b6870959c12 100644 --- a/js/src/vm/JSContext.h +++ b/js/src/vm/JSContext.h @@ -80,8 +80,11 @@ extern MOZ_THREAD_LOCAL(JSContext*) TlsContext; enum class ContextKind { - Cooperative, - Background + // Context for the main thread of a JSRuntime. + MainThread, + + // Context for a helper thread. + HelperThread }; #ifdef DEBUG @@ -122,7 +125,7 @@ struct JSContext : public JS::RootingContext, // currently operating on. void setRuntime(JSRuntime* rt); - bool isCooperativelyScheduled() const { return kind_ == js::ContextKind::Cooperative; } + bool isMainThreadContext() const { return kind_ == js::ContextKind::MainThread; } inline js::gc::ArenaLists* arenas() const { return arenas_; } From 8fc8563d65ddeb5b7a9efbf092266ccf28bd42af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 12 Apr 2018 11:59:09 +0200 Subject: [PATCH 13/52] Bug 1452143: Expose and honor a cssErrorReportingEnabled in the docshell. r=bholley The idea would be for parallel CSS parsing to check the static methods in ErrorReporter before loading the sheet. MozReview-Commit-ID: D7cedJQpz9K --- docshell/base/nsDocShell.cpp | 16 +++++++++ docshell/base/nsDocShell.h | 6 ++++ docshell/base/nsIDocShell.idl | 9 +++-- layout/style/ErrorReporter.cpp | 64 ++++++++++++++++++++++++++++++---- layout/style/ErrorReporter.h | 18 +++++----- 5 files changed, 95 insertions(+), 18 deletions(-) diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 7126171f0545..3a7852653ea6 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -362,6 +362,7 @@ nsDocShell::nsDocShell() , mAllowContentRetargetingOnChildren(true) , mUseErrorPages(false) , mObserveErrorPages(true) + , mCSSErrorReportingEnabled(false) , mAllowAuth(true) , mAllowKeywordFixup(false) , mIsOffScreenBrowser(false) @@ -1686,6 +1687,21 @@ nsDocShell::GetAllowJavascript(bool* aAllowJavascript) return NS_OK; } +NS_IMETHODIMP +nsDocShell::GetCssErrorReportingEnabled(bool* aEnabled) +{ + MOZ_ASSERT(aEnabled); + *aEnabled = mCSSErrorReportingEnabled; + return NS_OK; +} + +NS_IMETHODIMP +nsDocShell::SetCssErrorReportingEnabled(bool aEnabled) +{ + mCSSErrorReportingEnabled = aEnabled; + return NS_OK; +} + NS_IMETHODIMP nsDocShell::SetAllowJavascript(bool aAllowJavascript) { diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index e3be7360dd4b..2fe4a69441ba 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -890,6 +890,11 @@ private: // member functions return (mObserveErrorPages ? sUseErrorPages : mUseErrorPages); } + bool CSSErrorReportingEnabled() const + { + return mCSSErrorReportingEnabled; + } + private: // data members static nsIURIFixup* sURIFixup; @@ -1108,6 +1113,7 @@ private: // data members bool mAllowContentRetargetingOnChildren : 1; bool mUseErrorPages : 1; bool mObserveErrorPages : 1; + bool mCSSErrorReportingEnabled : 1; bool mAllowAuth : 1; bool mAllowKeywordFixup : 1; bool mIsOffScreenBrowser : 1; diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl index 520e339666e9..bc18c1286273 100644 --- a/docshell/base/nsIDocShell.idl +++ b/docshell/base/nsIDocShell.idl @@ -289,10 +289,15 @@ interface nsIDocShell : nsIDocShellTreeItem attribute nsIDOMEventTarget chromeEventHandler; /** - * This allows chrome to set a custom User agent on a specific docshell - */ + * This allows chrome to set a custom User agent on a specific docshell + */ attribute DOMString customUserAgent; + /** + * Whether CSS error reporting is enabled. + */ + attribute boolean cssErrorReportingEnabled; + /** * Whether to allow plugin execution */ diff --git a/layout/style/ErrorReporter.cpp b/layout/style/ErrorReporter.cpp index 21f6bafcae4b..defbbdc8abd6 100644 --- a/layout/style/ErrorReporter.cpp +++ b/layout/style/ErrorReporter.cpp @@ -16,7 +16,9 @@ #include "nsCSSScanner.h" #include "nsIConsoleService.h" #include "nsIDocument.h" +#include "nsIDocShell.h" #include "nsIFactory.h" +#include "nsINode.h" #include "nsIScriptError.h" #include "nsISensitiveInfoHiddenURI.h" #include "nsIStringBundle.h" @@ -134,9 +136,11 @@ ErrorReporter::ErrorReporter(const StyleSheet* aSheet, nsIURI* aURI) : mSheet(aSheet) , mLoader(aLoader) - , mURI(aURI), - mInnerWindowID(0), mErrorLineNumber(0), mPrevErrorLineNumber(0), - mErrorColNumber(0) + , mURI(aURI) + , mInnerWindowID(0) + , mErrorLineNumber(0) + , mPrevErrorLineNumber(0) + , mErrorColNumber(0) { } @@ -158,6 +162,54 @@ ErrorReporter::~ErrorReporter() } } +bool +ErrorReporter::ShouldReportErrors(const nsIDocument& aDoc) +{ + MOZ_ASSERT(NS_IsMainThread()); + nsIDocShell* shell = aDoc.GetDocShell(); + if (!shell) { + return false; + } + + bool report = false; + shell->GetCssErrorReportingEnabled(&report); + return report; +} + +bool +ErrorReporter::ShouldReportErrors() +{ + MOZ_ASSERT(NS_IsMainThread()); + + EnsureGlobalsInitialized(); + if (!sReportErrors) { + return false; + } + + if (mInnerWindowID) { + // We already reported an error, and that has cleared mSheet and mLoader, so + // we'd get the bogus value otherwise. + return true; + } + + if (mSheet) { + nsINode* owner = mSheet->GetOwnerNode() + ? mSheet->GetOwnerNode() + : mSheet->GetAssociatedDocument(); + + if (owner && ShouldReportErrors(*owner->OwnerDoc())) { + return true; + } + } + + if (mLoader && mLoader->GetDocument() && + ShouldReportErrors(*mLoader->GetDocument())) { + return true; + } + + return false; +} + void ErrorReporter::OutputError() { @@ -258,7 +310,7 @@ ErrorReporter::ClearError() void ErrorReporter::AddToError(const nsString &aErrorText) { - if (!ShouldReportErrors()) return; + MOZ_ASSERT(ShouldReportErrors()); if (mError.IsEmpty()) { mError = aErrorText; @@ -271,7 +323,7 @@ ErrorReporter::AddToError(const nsString &aErrorText) void ErrorReporter::ReportUnexpected(const char *aMessage) { - if (!ShouldReportErrors()) return; + MOZ_ASSERT(ShouldReportErrors()); nsAutoString str; sStringBundle->GetStringFromName(aMessage, str); @@ -282,7 +334,7 @@ void ErrorReporter::ReportUnexpectedUnescaped(const char *aMessage, const nsAutoString& aParam) { - if (!ShouldReportErrors()) return; + MOZ_ASSERT(ShouldReportErrors()); const char16_t *params[1] = { aParam.get() }; diff --git a/layout/style/ErrorReporter.h b/layout/style/ErrorReporter.h index 4e8de01f91a1..503a6b4c834a 100644 --- a/layout/style/ErrorReporter.h +++ b/layout/style/ErrorReporter.h @@ -9,13 +9,13 @@ #ifndef mozilla_css_ErrorReporter_h_ #define mozilla_css_ErrorReporter_h_ -#include "nsString.h" +#include "nsStringFwd.h" struct nsCSSToken; +class nsIDocument; class nsIURI; namespace mozilla { -class ServoStyleSheet; class StyleSheet; namespace css { @@ -37,11 +37,9 @@ public: } } - bool ShouldReportErrors() const - { - EnsureGlobalsInitialized(); - return sReportErrors; - } + static bool ShouldReportErrors(const nsIDocument&); + + bool ShouldReportErrors(); void OutputError(uint32_t aLineNumber, uint32_t aLineOffset, @@ -55,7 +53,7 @@ public: // no parameters void ReportUnexpected(const char *aMessage); // one parameter which has already been escaped appropriately - void ReportUnexpectedUnescaped(const char *aMessage, + void ReportUnexpectedUnescaped(const char* aMessage, const nsAutoString& aParam); private: @@ -69,8 +67,8 @@ private: nsAutoString mError; nsString mErrorLine; nsString mFileName; - const StyleSheet *mSheet; - const Loader *mLoader; + const StyleSheet* mSheet; + const Loader* mLoader; nsIURI *mURI; uint64_t mInnerWindowID; uint32_t mErrorLineNumber; From ec2824c99ffd29a388cb39d63e33872d9d6b2193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 16 Apr 2018 19:10:57 +0200 Subject: [PATCH 14/52] Bug 1452143: Make InspectorUtils.getAllStyleSheets handle Shadow DOM, and also optionally not return UA / User sheets. r=bholley We don't want to reparse over and over shared sheets, and that confused code pretty heavily. MozReview-Commit-ID: 7qkXoCoPNFW --- dom/chrome-webidl/InspectorUtils.webidl | 3 ++- layout/inspector/InspectorUtils.cpp | 34 ++++++++++++------------- layout/inspector/InspectorUtils.h | 1 + layout/style/ErrorReporter.cpp | 1 + layout/style/ServoStyleSet.cpp | 7 ++++- layout/style/ServoStyleSet.h | 2 +- 6 files changed, 27 insertions(+), 21 deletions(-) diff --git a/dom/chrome-webidl/InspectorUtils.webidl b/dom/chrome-webidl/InspectorUtils.webidl index 8ae374e2efd7..c1a96f6a9ff0 100644 --- a/dom/chrome-webidl/InspectorUtils.webidl +++ b/dom/chrome-webidl/InspectorUtils.webidl @@ -11,7 +11,8 @@ */ [ChromeOnly] namespace InspectorUtils { - sequence getAllStyleSheets(Document document); + // documentOnly tells whether user and UA sheets should get included. + sequence getAllStyleSheets(Document document, optional boolean documentOnly = false); sequence getCSSStyleRules( Element element, [TreatNullAs=EmptyString] optional DOMString pseudo = ""); diff --git a/layout/inspector/InspectorUtils.cpp b/layout/inspector/InspectorUtils.cpp index e94530e8e8de..3c23e19ca369 100644 --- a/layout/inspector/InspectorUtils.cpp +++ b/layout/inspector/InspectorUtils.cpp @@ -61,6 +61,7 @@ namespace dom { /* static */ void InspectorUtils::GetAllStyleSheets(GlobalObject& aGlobalObject, nsIDocument& aDocument, + bool aDocumentOnly, nsTArray>& aResult) { // Get the agent, then user and finally xbl sheets in the style set. @@ -68,19 +69,24 @@ InspectorUtils::GetAllStyleSheets(GlobalObject& aGlobalObject, if (presShell) { ServoStyleSet* styleSet = presShell->StyleSet(); - SheetType sheetType = SheetType::Agent; - for (int32_t i = 0; i < styleSet->SheetCount(sheetType); i++) { - aResult.AppendElement(styleSet->StyleSheetAt(sheetType, i)); - } - sheetType = SheetType::User; - for (int32_t i = 0; i < styleSet->SheetCount(sheetType); i++) { - aResult.AppendElement(styleSet->StyleSheetAt(sheetType, i)); + + if (!aDocumentOnly) { + SheetType sheetType = SheetType::Agent; + for (int32_t i = 0; i < styleSet->SheetCount(sheetType); i++) { + aResult.AppendElement(styleSet->StyleSheetAt(sheetType, i)); + } + sheetType = SheetType::User; + for (int32_t i = 0; i < styleSet->SheetCount(sheetType); i++) { + aResult.AppendElement(styleSet->StyleSheetAt(sheetType, i)); + } } AutoTArray xblSheetArray; - styleSet->AppendAllXBLStyleSheets(xblSheetArray); + styleSet->AppendAllNonDocumentAuthorSheets(xblSheetArray); // The XBL stylesheet array will quite often be full of duplicates. Cope: + // + // FIXME(emilio, bug 1454467): I think this is not true since bug 1452525. nsTHashtable> sheetSet; for (StyleSheet* sheet : xblSheetArray) { if (!sheetSet.Contains(sheet)) { @@ -1048,16 +1054,8 @@ InspectorUtils::ParseStyleSheet(GlobalObject& aGlobalObject, ErrorResult& aRv) { - RefPtr servoSheet = do_QueryObject(&aSheet); - if (servoSheet) { - nsresult rv = servoSheet->ReparseSheet(aInput); - if (NS_FAILED(rv)) { - aRv.Throw(rv); - } - return; - } - - aRv.Throw(NS_ERROR_INVALID_POINTER); + RefPtr servoSheet = aSheet.AsServo(); + aRv = servoSheet->ReparseSheet(aInput); } void diff --git a/layout/inspector/InspectorUtils.h b/layout/inspector/InspectorUtils.h index d4968cec6141..8efa267b8f42 100644 --- a/layout/inspector/InspectorUtils.h +++ b/layout/inspector/InspectorUtils.h @@ -37,6 +37,7 @@ class InspectorUtils public: static void GetAllStyleSheets(GlobalObject& aGlobal, nsIDocument& aDocument, + bool aDocumentOnly, nsTArray>& aResult); static void GetCSSStyleRules(GlobalObject& aGlobal, Element& aElement, diff --git a/layout/style/ErrorReporter.cpp b/layout/style/ErrorReporter.cpp index defbbdc8abd6..a3ae41a24fc1 100644 --- a/layout/style/ErrorReporter.cpp +++ b/layout/style/ErrorReporter.cpp @@ -146,6 +146,7 @@ ErrorReporter::ErrorReporter(const StyleSheet* aSheet, ErrorReporter::~ErrorReporter() { + MOZ_ASSERT(NS_IsMainThread()); // Schedule deferred cleanup for cached data. We want to strike a // balance between performance and memory usage, so we only allow // short-term caching. diff --git a/layout/style/ServoStyleSet.cpp b/layout/style/ServoStyleSet.cpp index 76951ae58dc2..c52f2e7054e9 100644 --- a/layout/style/ServoStyleSet.cpp +++ b/layout/style/ServoStyleSet.cpp @@ -869,10 +869,15 @@ ServoStyleSet::StyleSheetAt(SheetType aType, int32_t aIndex) const } void -ServoStyleSet::AppendAllXBLStyleSheets(nsTArray& aArray) const +ServoStyleSet::AppendAllNonDocumentAuthorSheets(nsTArray& aArray) const { if (mDocument) { mDocument->BindingManager()->AppendAllSheets(aArray); + EnumerateShadowRoots(*mDocument, [&](ShadowRoot& aShadowRoot) { + for (auto index : IntegerRange(aShadowRoot.SheetCount())) { + aArray.AppendElement(aShadowRoot.SheetAt(index)); + } + }); } } diff --git a/layout/style/ServoStyleSet.h b/layout/style/ServoStyleSet.h index 178e70f6f4dc..94ae168c5115 100644 --- a/layout/style/ServoStyleSet.h +++ b/layout/style/ServoStyleSet.h @@ -244,7 +244,7 @@ public: int32_t SheetCount(SheetType aType) const; ServoStyleSheet* StyleSheetAt(SheetType aType, int32_t aIndex) const; - void AppendAllXBLStyleSheets(nsTArray& aArray) const; + void AppendAllNonDocumentAuthorSheets(nsTArray& aArray) const; template void EnumerateStyleSheetArrays(Func aCallback) const { From df09059366267c4c02fab3be52e07d4ab31c76eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 12 Apr 2018 17:38:29 +0200 Subject: [PATCH 15/52] Bug 1452143: Hook the filters and enable error reporting on demand. r=nchevobbe MozReview-Commit-ID: BDFmxWjbDgj --- devtools/client/webconsole/store.js | 31 ++++++++++++++++++++++++++++ devtools/server/actors/tab.js | 14 +++++++++++++ devtools/shared/client/tab-client.js | 7 +++++++ 3 files changed, 52 insertions(+) diff --git a/devtools/client/webconsole/store.js b/devtools/client/webconsole/store.js index 8b2d8229fb5d..f8fae02bb01c 100644 --- a/devtools/client/webconsole/store.js +++ b/devtools/client/webconsole/store.js @@ -22,6 +22,8 @@ const { REMOVED_ACTORS_CLEAR, NETWORK_MESSAGE_UPDATE, PREFS, + INITIALIZE, + FILTER_TOGGLE, } = require("devtools/client/webconsole/constants"); const { reducers } = require("./reducers/index"); const { @@ -77,6 +79,7 @@ function configureStore(hud, options = {}) { enableBatching(), enableNetProvider(hud), enableMessagesCacheClearing(hud), + ensureCSSErrorReportingEnabled(hud), ) ); } @@ -165,6 +168,34 @@ function enableActorReleaser(hud) { }; } +/** + * This is responsible for ensuring that error reporting is enabled if the CSS + * filter is toggled on. + */ +function ensureCSSErrorReportingEnabled(hud) { + return next => (reducer, initialState, enhancer) => { + function ensureErrorReportingEnhancer(state, action) { + let proxy = hud ? hud.proxy : null; + if (!proxy) { + return reducer(state, action); + } + + state = reducer(state, action); + if (!state.filters.css) { + return state; + } + + let cssFilterToggled = + action.type == FILTER_TOGGLE && action.filter == "css"; + if (cssFilterToggled || action.type == INITIALIZE) { + proxy.target.activeTab.ensureCSSErrorReportingEnabled(); + } + return state; + } + return next(ensureErrorReportingEnhancer, initialState, enhancer); + }; +} + /** * This enhancer is responsible for fetching HTTP details data * collected by the backend. The fetch happens on-demand diff --git a/devtools/server/actors/tab.js b/devtools/server/actors/tab.js index 2d400813ae73..37008508ddfe 100644 --- a/devtools/server/actors/tab.js +++ b/devtools/server/actors/tab.js @@ -1007,6 +1007,19 @@ TabActor.prototype = { return {}; }, + /** + * Ensure that CSS error reporting is enabled. + */ + ensureCSSErrorReportingEnabled(request) { + if (!this.docShell || this.docShell.cssErrorReportingEnabled) { + return {}; + } + + this.docShell.cssErrorReportingEnabled = true; + // FIXME(emilio): Reparse sheets. + return {}; + }, + /** * Handle logic to enable/disable JS/cache/Service Worker testing. */ @@ -1430,6 +1443,7 @@ TabActor.prototype.requestTypes = { "reload": TabActor.prototype.onReload, "navigateTo": TabActor.prototype.onNavigateTo, "reconfigure": TabActor.prototype.onReconfigure, + "ensureCSSErrorReportingEnabled": TabActor.prototype.ensureCSSErrorReportingEnabled, "switchToFrame": TabActor.prototype.onSwitchToFrame, "listFrames": TabActor.prototype.onListFrames, "listWorkers": TabActor.prototype.onListWorkers, diff --git a/devtools/shared/client/tab-client.js b/devtools/shared/client/tab-client.js index c1a78880a567..57640d6818aa 100644 --- a/devtools/shared/client/tab-client.js +++ b/devtools/shared/client/tab-client.js @@ -102,6 +102,13 @@ TabClient.prototype = { type: "focus" }, {}), + /** + * Ensure relevant pages have error reporting enabled. + */ + ensureCSSErrorReportingEnabled: DebuggerClient.requester({ + type: "ensureCSSErrorReportingEnabled", + }, {}), + /** * Reload the page in this tab. * From 3f89f10942af65926207f4a3b31606835c6353fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 12 Apr 2018 23:58:12 +0200 Subject: [PATCH 16/52] Bug 1452143: Reparse doc sheets after enabling error reporting on a docshell. r=jryans While at it, remove useless charset rule lookups, since charset rules aren't part of the OM, and have no effect at all anymore. MozReview-Commit-ID: EefGrOZvmm7 --- devtools/server/actors/stylesheets.js | 286 ++++++++++++-------------- devtools/server/actors/tab.js | 35 +++- 2 files changed, 167 insertions(+), 154 deletions(-) diff --git a/devtools/server/actors/stylesheets.js b/devtools/server/actors/stylesheets.js index 552d96bd6969..427c536b18b3 100644 --- a/devtools/server/actors/stylesheets.js +++ b/devtools/server/actors/stylesheets.js @@ -125,6 +125,137 @@ var MediaRuleActor = protocol.ActorClassWithSpec(mediaRuleSpec, { } }); +function getSheetText(sheet, consoleActor) { + let cssText = modifiedStyleSheets.get(sheet); + if (cssText !== undefined) { + return Promise.resolve(cssText); + } + + if (!sheet.href) { + // this is an inline