Empty merge ab/12770256 into aosp-main-future

Merged-In: Id8e38b36dd587f2a2a4176f1aea0259b6d02b3f0
Change-Id: I78201b5264fb756e762f21829530f5f5d4554752
diff --git a/OWNERS b/OWNERS
index 4f31bde..0d1ae30 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,3 +1,4 @@
 cferris@google.com
 enh@google.com
 chiahungduan@google.com
+include platform/system/core:/janitors/OWNERS #{LAST_RESORT_SUGGESTION}
diff --git a/standalone/allocator_config_wrapper.h b/standalone/allocator_config_wrapper.h
index 5477236..ea12a5b 100644
--- a/standalone/allocator_config_wrapper.h
+++ b/standalone/allocator_config_wrapper.h
@@ -12,35 +12,7 @@
 #include "condition_variable.h"
 #include "internal_defs.h"
 #include "secondary.h"
-
-namespace {
-
-template <typename T> struct removeConst {
-  using type = T;
-};
-template <typename T> struct removeConst<const T> {
-  using type = T;
-};
-
-// This is only used for SFINAE when detecting if a type is defined.
-template <typename T> struct voidAdaptor {
-  using type = void;
-};
-
-// This is used for detecting the case that defines the flag with wrong type and
-// it'll be viewed as undefined optional flag.
-template <typename L, typename R> struct assertSameType {
-  template <typename, typename> struct isSame {
-    static constexpr bool value = false;
-  };
-  template <typename T> struct isSame<T, T> {
-    static constexpr bool value = true;
-  };
-  static_assert(isSame<L, R>::value, "Flag type mismatches");
-  using type = R;
-};
-
-} // namespace
+#include "type_traits.h"
 
 namespace scudo {
 
diff --git a/standalone/list.h b/standalone/list.h
index c6bd32a..e0b8278 100644
--- a/standalone/list.h
+++ b/standalone/list.h
@@ -10,17 +10,7 @@
 #define SCUDO_LIST_H_
 
 #include "internal_defs.h"
-
-// TODO: Move the helpers to a header.
-namespace {
-template <typename T> struct isPointer {
-  static constexpr bool value = false;
-};
-
-template <typename T> struct isPointer<T *> {
-  static constexpr bool value = true;
-};
-} // namespace
+#include "type_traits.h"
 
 namespace scudo {
 
@@ -58,10 +48,11 @@
 
 template <class T> class LinkOp<T, /*LinkWithPtr=*/false> {
 public:
-  using LinkTy = decltype(T::Next);
+  using LinkTy = typename assertSameType<
+      typename removeConst<decltype(T::Next)>::type,
+      typename removeConst<decltype(T::EndOfListVal)>::type>::type;
 
   LinkOp() = default;
-  // TODO: Check if the `BaseSize` can fit in `Size`.
   LinkOp(T *BaseT, uptr BaseSize)
       : Base(BaseT), Size(static_cast<LinkTy>(BaseSize)) {}
   void init(T *LinkBase, uptr BaseSize) {
@@ -80,11 +71,12 @@
   }
   // Set `X->Next` to `Next`.
   void setNext(T *X, T *Next) const {
-    // TODO: Check if the offset fits in the size of `LinkTy`.
-    if (Next == nullptr)
+    if (Next == nullptr) {
       X->Next = getEndOfListVal();
-    else
+    } else {
+      assertElementInRange(Next);
       X->Next = static_cast<LinkTy>(Next - Base);
+    }
   }
 
   T *getPrev(T *X) const {
@@ -96,17 +88,22 @@
   }
   // Set `X->Prev` to `Prev`.
   void setPrev(T *X, T *Prev) const {
-    DCHECK_LT(reinterpret_cast<uptr>(Prev),
-              reinterpret_cast<uptr>(Base + Size));
-    if (Prev == nullptr)
+    if (Prev == nullptr) {
       X->Prev = getEndOfListVal();
-    else
+    } else {
+      assertElementInRange(Prev);
       X->Prev = static_cast<LinkTy>(Prev - Base);
+    }
   }
 
-  // TODO: `LinkTy` should be the same as decltype(T::EndOfListVal).
   LinkTy getEndOfListVal() const { return T::EndOfListVal; }
 
+private:
+  void assertElementInRange(T *X) const {
+    DCHECK_GE(reinterpret_cast<uptr>(X), reinterpret_cast<uptr>(Base));
+    DCHECK_LE(static_cast<LinkTy>(X - Base), Size);
+  }
+
 protected:
   T *Base = nullptr;
   LinkTy Size = 0;
diff --git a/standalone/primary32.h b/standalone/primary32.h
index 654b129..596c48f 100644
--- a/standalone/primary32.h
+++ b/standalone/primary32.h
@@ -387,7 +387,7 @@
 
   struct ReleaseToOsInfo {
     uptr BytesInFreeListAtLastCheckpoint;
-    uptr RangesReleased;
+    uptr NumReleasesAttempted;
     uptr LastReleasedBytes;
     u64 LastReleaseAtNs;
   };
@@ -880,14 +880,14 @@
           BytesInFreeList - Sci->ReleaseInfo.BytesInFreeListAtLastCheckpoint;
     }
     const uptr AvailableChunks = Sci->AllocatedUser / BlockSize;
-    Str->append("  %02zu (%6zu): mapped: %6zuK popped: %7zu pushed: %7zu "
-                "inuse: %6zu avail: %6zu releases: %6zu last released: %6zuK "
-                "latest pushed bytes: %6zuK\n",
-                ClassId, getSizeByClassId(ClassId), Sci->AllocatedUser >> 10,
-                Sci->FreeListInfo.PoppedBlocks, Sci->FreeListInfo.PushedBlocks,
-                InUse, AvailableChunks, Sci->ReleaseInfo.RangesReleased,
-                Sci->ReleaseInfo.LastReleasedBytes >> 10,
-                PushedBytesDelta >> 10);
+    Str->append(
+        "  %02zu (%6zu): mapped: %6zuK popped: %7zu pushed: %7zu "
+        "inuse: %6zu avail: %6zu releases attempted: %6zu last released: %6zuK "
+        "latest pushed bytes: %6zuK\n",
+        ClassId, getSizeByClassId(ClassId), Sci->AllocatedUser >> 10,
+        Sci->FreeListInfo.PoppedBlocks, Sci->FreeListInfo.PushedBlocks, InUse,
+        AvailableChunks, Sci->ReleaseInfo.NumReleasesAttempted,
+        Sci->ReleaseInfo.LastReleasedBytes >> 10, PushedBytesDelta >> 10);
   }
 
   void getSizeClassFragmentationInfo(SizeClassInfo *Sci, uptr ClassId,
@@ -972,6 +972,10 @@
     const uptr Base = First * RegionSize;
     const uptr NumberOfRegions = Last - First + 1U;
 
+    // The following steps contribute to the majority time spent in page
+    // releasing thus we increment the counter here.
+    ++Sci->ReleaseInfo.NumReleasesAttempted;
+
     // ==================================================================== //
     // 2. Mark the free blocks and we can tell which pages are in-use by
     //    querying `PageReleaseContext`.
@@ -991,9 +995,8 @@
     };
     releaseFreeMemoryToOS(Context, Recorder, SkipRegion);
 
-    if (Recorder.getReleasedRangesCount() > 0) {
+    if (Recorder.getReleasedBytes() > 0) {
       Sci->ReleaseInfo.BytesInFreeListAtLastCheckpoint = BytesInFreeList;
-      Sci->ReleaseInfo.RangesReleased += Recorder.getReleasedRangesCount();
       Sci->ReleaseInfo.LastReleasedBytes = Recorder.getReleasedBytes();
       TotalReleasedBytes += Sci->ReleaseInfo.LastReleasedBytes;
     }
diff --git a/standalone/primary64.h b/standalone/primary64.h
index e382e01..2b520ce 100644
--- a/standalone/primary64.h
+++ b/standalone/primary64.h
@@ -530,7 +530,7 @@
 
   struct ReleaseToOsInfo {
     uptr BytesInFreeListAtLastCheckpoint;
-    uptr RangesReleased;
+    uptr NumReleasesAttempted;
     uptr LastReleasedBytes;
     // The minimum size of pushed blocks to trigger page release.
     uptr TryReleaseThreshold;
@@ -1144,11 +1144,12 @@
     Str->append(
         "%s %02zu (%6zu): mapped: %6zuK popped: %7zu pushed: %7zu "
         "inuse: %6zu total: %6zu releases: %6zu last "
-        "released: %6zuK latest pushed bytes: %6zuK region: 0x%zx (0x%zx)\n",
+        "releases attempted: %6zuK latest pushed bytes: %6zuK region: 0x%zx "
+        "(0x%zx)\n",
         Region->Exhausted ? "E" : " ", ClassId, getSizeByClassId(ClassId),
         Region->MemMapInfo.MappedUser >> 10, Region->FreeListInfo.PoppedBlocks,
         Region->FreeListInfo.PushedBlocks, InUseBlocks, TotalChunks,
-        Region->ReleaseInfo.RangesReleased,
+        Region->ReleaseInfo.NumReleasesAttempted,
         Region->ReleaseInfo.LastReleasedBytes >> 10,
         RegionPushedBytesDelta >> 10, Region->RegionBeg,
         getRegionBaseByClassId(ClassId));
@@ -1322,7 +1323,7 @@
                                             Context.getReleaseOffset());
     auto SkipRegion = [](UNUSED uptr RegionIndex) { return false; };
     releaseFreeMemoryToOS(Context, Recorder, SkipRegion);
-    if (Recorder.getReleasedRangesCount() > 0) {
+    if (Recorder.getReleasedBytes() > 0) {
       // This is the case that we didn't hit the release threshold but it has
       // been past a certain period of time. Thus we try to release some pages
       // and if it does release some additional pages, it's hint that we are
@@ -1342,7 +1343,6 @@
       }
 
       Region->ReleaseInfo.BytesInFreeListAtLastCheckpoint = BytesInFreeList;
-      Region->ReleaseInfo.RangesReleased += Recorder.getReleasedRangesCount();
       Region->ReleaseInfo.LastReleasedBytes = Recorder.getReleasedBytes();
     }
     Region->ReleaseInfo.LastReleaseAtNs = getMonotonicTimeFast();
diff --git a/standalone/release.h b/standalone/release.h
index 6353daf..7a4912e 100644
--- a/standalone/release.h
+++ b/standalone/release.h
@@ -22,8 +22,6 @@
   RegionReleaseRecorder(MemMapT *RegionMemMap, uptr Base, uptr Offset = 0)
       : RegionMemMap(RegionMemMap), Base(Base), Offset(Offset) {}
 
-  uptr getReleasedRangesCount() const { return ReleasedRangesCount; }
-
   uptr getReleasedBytes() const { return ReleasedBytes; }
 
   uptr getBase() const { return Base; }
@@ -33,12 +31,10 @@
   void releasePageRangeToOS(uptr From, uptr To) {
     const uptr Size = To - From;
     RegionMemMap->releasePagesToOS(getBase() + Offset + From, Size);
-    ReleasedRangesCount++;
     ReleasedBytes += Size;
   }
 
 private:
-  uptr ReleasedRangesCount = 0;
   uptr ReleasedBytes = 0;
   MemMapT *RegionMemMap = nullptr;
   uptr Base = 0;
@@ -52,8 +48,6 @@
   ReleaseRecorder(uptr Base, uptr Offset = 0, MapPlatformData *Data = nullptr)
       : Base(Base), Offset(Offset), Data(Data) {}
 
-  uptr getReleasedRangesCount() const { return ReleasedRangesCount; }
-
   uptr getReleasedBytes() const { return ReleasedBytes; }
 
   uptr getBase() const { return Base; }
@@ -62,12 +56,10 @@
   void releasePageRangeToOS(uptr From, uptr To) {
     const uptr Size = To - From;
     releasePagesToOS(Base, From + Offset, Size, Data);
-    ReleasedRangesCount++;
     ReleasedBytes += Size;
   }
 
 private:
-  uptr ReleasedRangesCount = 0;
   uptr ReleasedBytes = 0;
   // The starting address to release. Note that we may want to combine (Base +
   // Offset) as a new Base. However, the Base is retrieved from
diff --git a/standalone/type_traits.h b/standalone/type_traits.h
new file mode 100644
index 0000000..16ed5a0
--- /dev/null
+++ b/standalone/type_traits.h
@@ -0,0 +1,47 @@
+//===-- type_traits.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_TYPE_TRAITS_H_
+#define SCUDO_TYPE_TRAITS_H_
+
+namespace scudo {
+
+template <typename T> struct removeConst {
+  using type = T;
+};
+template <typename T> struct removeConst<const T> {
+  using type = T;
+};
+
+// This is only used for SFINAE when detecting if a type is defined.
+template <typename T> struct voidAdaptor {
+  using type = void;
+};
+
+template <typename L, typename R> struct assertSameType {
+  template <typename, typename> struct isSame {
+    static constexpr bool value = false;
+  };
+  template <typename T> struct isSame<T, T> {
+    static constexpr bool value = true;
+  };
+  static_assert(isSame<L, R>::value, "Type mismatches");
+  using type = R;
+};
+
+template <typename T> struct isPointer {
+  static constexpr bool value = false;
+};
+
+template <typename T> struct isPointer<T *> {
+  static constexpr bool value = true;
+};
+
+} // namespace scudo
+
+#endif // SCUDO_TYPE_TRAITS_H_