DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (d38398e5144e)

VCS Links

DocumentEntry

Entry

ExpirationTracker

HasSheet_ThenRemoveRuleProcessors

RuleProcessorCache

Macros

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*
 * cache of re-usable nsCSSRuleProcessors for given sets of style sheets
 */

#ifndef mozilla_RuleProcessorCache_h
#define mozilla_RuleProcessorCache_h

#include "mozilla/MemoryReporting.h"
#include "mozilla/StaticPtr.h"
#include "nsCSSRuleProcessor.h"
#include "nsExpirationTracker.h"
#include "nsMediaList.h"
#include "nsIMemoryReporter.h"
#include "nsTArray.h"

class nsCSSRuleProcessor;
namespace mozilla {
class CSSStyleSheet;
namespace css {
class DocumentRule;
} // namespace css
} // namespace mozilla

namespace mozilla {

/**
 * The RuleProcessorCache is a singleton object that caches
 * nsCSSRuleProcessors keyed off a list of style sheets and the result of
 * evaluating all @-moz-documents in the style sheets.  nsStyleSet gets and
 * puts nsCSSRuleProcessors from/to the RuleProcessorCache.
 *
 * State bits on CSSStyleSheet and nsCSSRuleProcessor track whether they are in
 * the RuleProcessorCache.  This lets us remove them from the RuleProcessorCache
 * when they're going away.
 */
class RuleProcessorCache final : public nsIMemoryReporter
{
  NS_DECL_ISUPPORTS
  NS_DECL_NSIMEMORYREPORTER

public:
  static nsCSSRuleProcessor* GetRuleProcessor(
      const nsTArray<CSSStyleSheet*>& aSheets,
      nsPresContext* aPresContext);
  static void PutRuleProcessor(
      const nsTArray<CSSStyleSheet*>& aSheets,
      nsTArray<css::DocumentRule*>&& aDocumentRulesInSheets,
      const nsDocumentRuleResultCacheKey& aCacheKey,
      nsCSSRuleProcessor* aRuleProcessor);
  static void StartTracking(nsCSSRuleProcessor* aRuleProcessor);
  static void StopTracking(nsCSSRuleProcessor* aRuleProcessor);

#ifdef DEBUG
  static bool HasRuleProcessor(nsCSSRuleProcessor* aRuleProcessor);
#endif
  static void RemoveRuleProcessor(nsCSSRuleProcessor* aRuleProcessor);
  static void RemoveSheet(CSSStyleSheet* aSheet);

  static void Shutdown() { gShutdown = true; gRuleProcessorCache = nullptr; }

  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);

private:
  class ExpirationTracker : public nsExpirationTracker<nsCSSRuleProcessor,3>
  {
  public:
    explicit ExpirationTracker(RuleProcessorCache* aCache)
      : nsExpirationTracker<nsCSSRuleProcessor,3>(
          10000, "RuleProcessorCache::ExpirationTracker")
      , mCache(aCache) {}

    void RemoveObjectIfTracked(nsCSSRuleProcessor* aRuleProcessor);

    virtual void NotifyExpired(nsCSSRuleProcessor* aRuleProcessor) override {
      mCache->RemoveRuleProcessor(aRuleProcessor);
    }

  private:
    RuleProcessorCache* mCache;
  };

  RuleProcessorCache() : mExpirationTracker(this) {}
  ~RuleProcessorCache();

  void InitMemoryReporter();

  static bool EnsureGlobal();
  static StaticRefPtr<RuleProcessorCache> gRuleProcessorCache;
  static bool gShutdown;

  void DoRemoveSheet(CSSStyleSheet* aSheet);
  nsCSSRuleProcessor* DoGetRuleProcessor(
      const nsTArray<CSSStyleSheet*>& aSheets,
      nsPresContext* aPresContext);
  void DoPutRuleProcessor(const nsTArray<CSSStyleSheet*>& aSheets,
                          nsTArray<css::DocumentRule*>&& aDocumentRulesInSheets,
                          const nsDocumentRuleResultCacheKey& aCacheKey,
                          nsCSSRuleProcessor* aRuleProcessor);
#ifdef DEBUG
  bool DoHasRuleProcessor(nsCSSRuleProcessor* aRuleProcessor);
#endif
  void DoRemoveRuleProcessor(nsCSSRuleProcessor* aRuleProcessor);
  void DoStartTracking(nsCSSRuleProcessor* aRuleProcessor);
  void DoStopTracking(nsCSSRuleProcessor* aRuleProcessor);

  struct DocumentEntry {
    nsDocumentRuleResultCacheKey mCacheKey;
    RefPtr<nsCSSRuleProcessor> mRuleProcessor;
  };

  struct Entry {
    nsTArray<CSSStyleSheet*>     mSheets;
    nsTArray<css::DocumentRule*> mDocumentRulesInSheets;
    nsTArray<DocumentEntry>      mDocumentEntries;
  };

  // Function object to test whether an Entry object has a given sheet
  // in its mSheets array.  If it does, removes all of its rule processors
  // before returning true.
  struct HasSheet_ThenRemoveRuleProcessors {
    HasSheet_ThenRemoveRuleProcessors(RuleProcessorCache* aCache,
                                      CSSStyleSheet* aSheet)
      : mCache(aCache), mSheet(aSheet) {}
    bool operator()(Entry& aEntry) {
      if (aEntry.mSheets.Contains(mSheet)) {
        for (DocumentEntry& de : aEntry.mDocumentEntries) {
          de.mRuleProcessor->SetInRuleProcessorCache(false);
          mCache->mExpirationTracker.RemoveObjectIfTracked(de.mRuleProcessor);
        }
        return true;
      }
      return false;
    }
    RuleProcessorCache* mCache;
    CSSStyleSheet* mSheet;
  };

  ExpirationTracker mExpirationTracker;
  nsTArray<Entry> mEntries;
};

} // namespace mozilla

#endif // mozilla_RuleProcessorCache_h