Make PartitionAlloc more like Chromium's.

- Add pdfium::base::bits::IsPowerOfTwo(), merge https://crrev.com/614040
- Add a cheap knockoff of CHECK_EQ(). Change some CHECK(x == y) calls
  back to using CHECK_EQ().

Change-Id: I34918e5dd17175d1f9d660b0b57a7a736f30a37a
Reviewed-on: https://pdfium-review.googlesource.com/c/51170
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Chris Palmer <palmer@chromium.org>
diff --git a/third_party/base/allocator/partition_allocator/page_allocator.cc b/third_party/base/allocator/partition_allocator/page_allocator.cc
index 76f584b..683632d 100644
--- a/third_party/base/allocator/partition_allocator/page_allocator.cc
+++ b/third_party/base/allocator/partition_allocator/page_allocator.cc
@@ -12,6 +12,7 @@
 #include "third_party/base/allocator/partition_allocator/address_space_randomization.h"
 #include "third_party/base/allocator/partition_allocator/page_allocator_internal.h"
 #include "third_party/base/allocator/partition_allocator/spin_lock.h"
+#include "third_party/base/bits.h"
 #include "third_party/base/logging.h"
 #include "third_party/base/numerics/safe_math.h"
 
@@ -109,7 +110,7 @@
   DCHECK(!(length & kPageAllocationGranularityOffsetMask));
   DCHECK(align >= kPageAllocationGranularity);
   // Alignment must be power of 2 for masking math to work.
-  DCHECK_EQ(align & (align - 1), 0UL);
+  DCHECK(pdfium::base::bits::IsPowerOfTwo(align));
   DCHECK(!(reinterpret_cast<uintptr_t>(address) &
            kPageAllocationGranularityOffsetMask));
   uintptr_t align_offset_mask = align - 1;
@@ -120,7 +121,7 @@
   // On 64 bit Linux, we may need to adjust the address space limit for
   // guarded allocations.
   if (length >= kMinimumGuardedMemorySize) {
-    CHECK(PageInaccessible == accessibility);
+    CHECK_EQ(PageInaccessible, accessibility);
     CHECK(!commit);
     if (!AdjustAddressSpaceLimit(base::checked_cast<int64_t>(length))) {
       // Fall through. Try the allocation, since we may have a reserve.
diff --git a/third_party/base/allocator/partition_allocator/page_allocator_internals_posix.h b/third_party/base/allocator/partition_allocator/page_allocator_internals_posix.h
index 4aba30c..026d10d 100644
--- a/third_party/base/allocator/partition_allocator/page_allocator_internals_posix.h
+++ b/third_party/base/allocator/partition_allocator/page_allocator_internals_posix.h
@@ -128,7 +128,7 @@
     void* address,
     size_t length,
     PageAccessibilityConfiguration accessibility) {
-  CHECK(0 == mprotect(address, length, GetAccessFlags(accessibility)));
+  CHECK_EQ(0, mprotect(address, length, GetAccessFlags(accessibility)));
 }
 
 void FreePagesInternal(void* address, size_t length) {
diff --git a/third_party/base/allocator/partition_allocator/page_allocator_internals_win.h b/third_party/base/allocator/partition_allocator/page_allocator_internals_win.h
index 65e953a..2ba0a25 100644
--- a/third_party/base/allocator/partition_allocator/page_allocator_internals_win.h
+++ b/third_party/base/allocator/partition_allocator/page_allocator_internals_win.h
@@ -84,7 +84,7 @@
     if (!VirtualFree(address, length, MEM_DECOMMIT)) {
       // We check `GetLastError` for `ERROR_SUCCESS` here so that in a crash
       // report we get the error number.
-      CHECK(static_cast<uint32_t>(ERROR_SUCCESS) == GetLastError());
+      CHECK_EQ(static_cast<uint32_t>(ERROR_SUCCESS), GetLastError());
     }
   } else {
     if (!VirtualAlloc(address, length, MEM_COMMIT,
@@ -94,7 +94,7 @@
         OOM_CRASH();
       // We check `GetLastError` for `ERROR_SUCCESS` here so that in a crash
       // report we get the error number.
-      CHECK(ERROR_SUCCESS == error);
+      CHECK_EQ(ERROR_SUCCESS, error);
     }
   }
 }
diff --git a/third_party/base/bits.h b/third_party/base/bits.h
index 3a92b4c..1253683 100644
--- a/third_party/base/bits.h
+++ b/third_party/base/bits.h
@@ -23,9 +23,22 @@
 namespace base {
 namespace bits {
 
+// Returns true iff |value| is a power of 2.
+template <typename T,
+          typename = typename std::enable_if<std::is_integral<T>::value>>
+constexpr inline bool IsPowerOfTwo(T value) {
+  // From "Hacker's Delight": Section 2.1 Manipulating Rightmost Bits.
+  //
+  // Only positive integers with a single bit set are powers of two. If only one
+  // bit is set in x (e.g. 0b00000100000000) then |x-1| will have that bit set
+  // to zero and all bits to its right set to 1 (e.g. 0b00000011111111). Hence
+  // |x & (x-1)| is 0 iff x is a power of two.
+  return value > 0 && (value & (value - 1)) == 0;
+}
+
 // Round up |size| to a multiple of alignment, which must be a power of two.
 inline size_t Align(size_t size, size_t alignment) {
-  DCHECK_EQ(alignment & (alignment - 1), 0u);
+  DCHECK(IsPowerOfTwo(alignment));
   return (size + alignment - 1) & ~(alignment - 1);
 }
 
diff --git a/third_party/base/logging.h b/third_party/base/logging.h
index dc42016..0081a44 100644
--- a/third_party/base/logging.h
+++ b/third_party/base/logging.h
@@ -116,6 +116,7 @@
 #define DCHECK assert
 #endif
 
+#define CHECK_EQ(x, y) CHECK((x) == (y))
 #define DCHECK_EQ(x, y) DCHECK((x) == (y))
 #define NOTREACHED() DCHECK(false)