summaryrefslogtreecommitdiffstats
path: root/chromium/base/allocator/partition_allocator/partition_page.h
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/base/allocator/partition_allocator/partition_page.h')
-rw-r--r--chromium/base/allocator/partition_allocator/partition_page.h35
1 files changed, 30 insertions, 5 deletions
diff --git a/chromium/base/allocator/partition_allocator/partition_page.h b/chromium/base/allocator/partition_allocator/partition_page.h
index 5a0e70f9711..d2e580bdda8 100644
--- a/chromium/base/allocator/partition_allocator/partition_page.h
+++ b/chromium/base/allocator/partition_allocator/partition_page.h
@@ -11,8 +11,27 @@
#include "base/allocator/partition_allocator/partition_bucket.h"
#include "base/allocator/partition_allocator/partition_cookie.h"
#include "base/allocator/partition_allocator/partition_freelist_entry.h"
+#include "base/allocator/partition_allocator/random.h"
#include "base/logging.h"
+namespace {
+
+// Returns true if we've hit the end of a random-length period. We don't want to
+// invoke `RandomValue` too often, because we call this function in a hot spot
+// (`Free`), and `RandomValue` incurs the cost of atomics.
+#if !DCHECK_IS_ON()
+bool RandomPeriod() {
+ static thread_local uint8_t counter = 0;
+ if (UNLIKELY(counter == 0)) {
+ counter = base::RandomValue();
+ }
+ counter--;
+ return counter == 0;
+}
+#endif
+
+} // namespace
+
namespace base {
namespace internal {
@@ -201,29 +220,35 @@ ALWAYS_INLINE size_t PartitionPage::get_raw_size() const {
}
ALWAYS_INLINE void PartitionPage::Free(void* ptr) {
-#if DCHECK_IS_ON()
size_t slot_size = this->bucket->slot_size;
const size_t raw_size = get_raw_size();
if (raw_size) {
slot_size = raw_size;
}
+#if DCHECK_IS_ON()
// If these asserts fire, you probably corrupted memory.
PartitionCookieCheckValue(ptr);
PartitionCookieCheckValue(reinterpret_cast<char*>(ptr) + slot_size -
kCookieSize);
memset(ptr, kFreedByte, slot_size);
+#else
+ // `memset` only once in a while.
+ if (UNLIKELY(RandomPeriod())) {
+ memset(ptr, kFreedByte, slot_size);
+ }
#endif
DCHECK(this->num_allocated_slots);
- CHECK(ptr != freelist_head); // Catches an immediate double free.
+ // Catches an immediate double free.
+ CHECK(ptr != freelist_head);
// Look for double free one level deeper in debug.
- DCHECK(!freelist_head || ptr != internal::PartitionFreelistEntry::Transform(
- freelist_head->next));
+ DCHECK(!freelist_head ||
+ ptr != EncodedPartitionFreelistEntry::Decode(freelist_head->next));
internal::PartitionFreelistEntry* entry =
static_cast<internal::PartitionFreelistEntry*>(ptr);
- entry->next = internal::PartitionFreelistEntry::Transform(freelist_head);
+ entry->next = internal::PartitionFreelistEntry::Encode(freelist_head);
freelist_head = entry;
--this->num_allocated_slots;
if (UNLIKELY(this->num_allocated_slots <= 0)) {