Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/layout/generic/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 6 kB image not shown  

Quelle  IntrinsicISizesCache.h   Sprache: C

 
/* -*- 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/. */


#ifndef mozilla_IntrinsicISizesCache_h
#define mozilla_IntrinsicISizesCache_h

#include "nsIFrame.h"

namespace mozilla {

// Some frame classes keep a cache of intrinsic inline sizes. This class
// encapsulates the logic for caching them depending on the IntrinsicSizeInput.
//
// The cache is intended to take as little space as possible
// (max(sizeof(nscoord) * 2, sizeof(void*))), when there are no percentage-size
// dependencies.
struct IntrinsicISizesCache final {
  IntrinsicISizesCache() {
    new (&mInline) InlineCache();
    MOZ_ASSERT(IsInline());
  }

  ~IntrinsicISizesCache() { delete GetOutOfLine(); }

  template <typename Compute>
  nscoord GetOrSet(nsIFrame& aFrame, IntrinsicISizeType aType,
                   const IntrinsicSizeInput& aInput, Compute aCompute) {
    bool dependentOnPercentBSize = aFrame.HasAnyStateBits(
        NS_FRAME_DESCENDANT_INTRINSIC_ISIZE_DEPENDS_ON_BSIZE);
    nscoord value = Get(dependentOnPercentBSize, aType, aInput);
    if (value != kNotFound) {
      return value;
    }
    value = aCompute();
    // Inside of aCompute(), we might have newly discovered that we do have a
    // descendant whose intrinsic isize depends on our bsize; so we check that
    // state bit again before updating the cache.
    dependentOnPercentBSize = aFrame.HasAnyStateBits(
        NS_FRAME_DESCENDANT_INTRINSIC_ISIZE_DEPENDS_ON_BSIZE);
    Set(dependentOnPercentBSize, aType, aInput, value);
    return value;
  }

  void Clear() {
    if (auto* ool = GetOutOfLine()) {
      ool->mCacheWithPercentageBasis.Clear();
      ool->mCacheWithoutPercentageBasis.Clear();
      ool->mLastPercentageBasis.reset();
    } else {
      mInline.Clear();
    }
  }

 private:
  // We use nscoord_MAX rather than NS_INTRINSIC_ISIZE_UNKNOWN as our sentinel
  // value so that our high bit is always free.
  static constexpr nscoord kNotFound = nscoord_MAX;

  nscoord Get(bool aDependentOnPercentBSize, IntrinsicISizeType aType,
              const IntrinsicSizeInput& aInput) const {
    const bool usePercentageAwareCache =
        aDependentOnPercentBSize && aInput.HasSomePercentageBasisForChildren();
    if (!usePercentageAwareCache) {
      if (auto* ool = GetOutOfLine()) {
        return ool->mCacheWithoutPercentageBasis.Get(aType);
      }
      return mInline.Get(aType);
    }
    if (auto* ool = GetOutOfLine()) {
      if (ool->mLastPercentageBasis == aInput.mPercentageBasisForChildren) {
        return ool->mCacheWithPercentageBasis.Get(aType);
      }
    }
    return kNotFound;
  }

  void Set(bool aDependentOnPercentBSize, IntrinsicISizeType aType,
           const IntrinsicSizeInput& aInput, nscoord aValue) {
    // Intrinsic sizes should be nonnegative, so this std::max clamping should
    // rarely be necessary except in cases of integer overflow.  We have to be
    // strict about it, though, because of how we (ab)use the high bit
    // (see kHighBit)
    aValue = std::max(aValue, 0);
    const bool usePercentageAwareCache =
        aDependentOnPercentBSize && aInput.HasSomePercentageBasisForChildren();
    if (usePercentageAwareCache) {
      auto* ool = EnsureOutOfLine();
      if (ool->mLastPercentageBasis != aInput.mPercentageBasisForChildren) {
        ool->mLastPercentageBasis = aInput.mPercentageBasisForChildren;
        ool->mCacheWithPercentageBasis.Clear();
      }
      ool->mCacheWithPercentageBasis.Set(aType, aValue);
    } else if (auto* ool = GetOutOfLine()) {
      ool->mCacheWithoutPercentageBasis.Set(aType, aValue);
    } else {
      mInline.Set(aType, aValue);
      // No inline value should be able to cause us to misinterpret our
      // representation as out-of-line, because intrinsic isizes should always
      // be non-negative.
      MOZ_DIAGNOSTIC_ASSERT(IsInline());
    }
  }

  struct InlineCache {
    nscoord mCachedMinISize = kNotFound;
    nscoord mCachedPrefISize = kNotFound;

    nscoord Get(IntrinsicISizeType aType) const {
      return aType == IntrinsicISizeType::MinISize ? mCachedMinISize
                                                   : mCachedPrefISize;
    }
    void Set(IntrinsicISizeType aType, nscoord aValue) {
      MOZ_ASSERT(aValue >= 0);
      if (aType == IntrinsicISizeType::MinISize) {
        mCachedMinISize = aValue;
      } else {
        mCachedPrefISize = aValue;
      }
    }

    void Clear() { *this = {}; }
  };

  struct OutOfLineCache {
    InlineCache mCacheWithoutPercentageBasis;
    InlineCache mCacheWithPercentageBasis;
    Maybe<LogicalSize> mLastPercentageBasis;
  };

  // If the high bit of mOutOfLine is 1, then it points to an OutOfLineCache.
  union {
    InlineCache mInline;
    struct {
#ifndef HAVE_64BIT_BUILD
      uintptr_t mPadding = 0;
#endif
      uintptr_t mOutOfLine = 0;
    };
  };

  static constexpr uintptr_t kHighBit = uintptr_t(1)
                                        << (sizeof(void*) * CHAR_BIT - 1);

  bool IsOutOfLine() const {
#ifdef HAVE_64BIT_BUILD
    return mOutOfLine & kHighBit;
#else
    return mPadding & kHighBit;
#endif
  }
  bool IsInline() const { return !IsOutOfLine(); }
  OutOfLineCache* EnsureOutOfLine() {
    if (auto* ool = GetOutOfLine()) {
      return ool;
    }
    auto inlineCache = mInline;
    auto* ool = new OutOfLineCache();
    ool->mCacheWithoutPercentageBasis = inlineCache;
#ifdef HAVE_64BIT_BUILD
    MOZ_ASSERT((reinterpret_cast<uintptr_t>(ool) & kHighBit) == 0);
    mOutOfLine = reinterpret_cast<uintptr_t>(ool) | kHighBit;
#else
    mOutOfLine = reinterpret_cast<uintptr_t>(ool);
    mPadding = kHighBit;
#endif
    MOZ_ASSERT(IsOutOfLine());
    return ool;
  }

  OutOfLineCache* GetOutOfLine() const {
    if (!IsOutOfLine()) {
      return nullptr;
    }
#ifdef HAVE_64BIT_BUILD
    return reinterpret_cast<OutOfLineCache*>(mOutOfLine & ~kHighBit);
#else
    return reinterpret_cast<OutOfLineCache*>(mOutOfLine);
#endif
  }
};

static_assert(sizeof(IntrinsicISizesCache) == 8, "Unexpected cache size");

}  // namespace mozilla

#endif

Messung V0.5
C=89 H=96 G=92

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.