// Copyright 2020 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/allocator/partition_alloc_features.h" #include "base/base_export.h" #include "base/feature_list.h" #include "base/features.h" #include "build/build_config.h" #include "build/chromecast_buildflags.h" #include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_constants.h" #include "partition_alloc/partition_root.h" #include "partition_alloc/shim/allocator_shim_dispatch_to_noop_on_free.h" namespace base::features { namespace { static constexpr char kPAFeatureEnabledProcessesStr[] = "enabled-processes"; static constexpr char kBrowserOnlyStr[] = "browser-only"; static constexpr char kBrowserAndRendererStr[] = "browser-and-renderer"; static constexpr char kNonRendererStr[] = "non-renderer"; #if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) static constexpr char kGPUOnlyStr[] = "gpu-only"; static constexpr char kBrowserAndGPUStr[] = "browser-and-gpu"; #endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) static constexpr char kAllProcessesStr[] = "all-processes"; } // namespace BASE_FEATURE(kPartitionAllocUnretainedDanglingPtr, FEATURE_ENABLED_BY_DEFAULT); constexpr FeatureParam::Option kUnretainedDanglingPtrModeOption[] = { {UnretainedDanglingPtrMode::kCrash, "crash"}, {UnretainedDanglingPtrMode::kDumpWithoutCrashing, "dump_without_crashing"}, }; // Note: Do not use the prepared macro as of no need for a local cache. constinit const FeatureParam kUnretainedDanglingPtrModeParam = { &kPartitionAllocUnretainedDanglingPtr, "mode", UnretainedDanglingPtrMode::kCrash, &kUnretainedDanglingPtrModeOption, }; // Note: DPD conflicts with no-op `free()` (see // `base::allocator::MakeFreeNoOp()`). No-op `free()` stands down in the // presence of DPD, but hypothetically fully launching DPD should prompt // a rethink of no-op `free()`. BASE_FEATURE(kPartitionAllocDanglingPtr, #if PA_BUILDFLAG(ENABLE_DANGLING_RAW_PTR_FEATURE_FLAG) FEATURE_ENABLED_BY_DEFAULT #else FEATURE_DISABLED_BY_DEFAULT #endif ); constexpr FeatureParam::Option kDanglingPtrModeOption[] = { {DanglingPtrMode::kCrash, "crash"}, {DanglingPtrMode::kLogOnly, "log_only"}, }; // Note: Do not use the prepared macro as of no need for a local cache. constinit const FeatureParam kDanglingPtrModeParam{ &kPartitionAllocDanglingPtr, "mode", DanglingPtrMode::kCrash, &kDanglingPtrModeOption, }; constexpr FeatureParam::Option kDanglingPtrTypeOption[] = { {DanglingPtrType::kAll, "all"}, {DanglingPtrType::kCrossTask, "cross_task"}, }; // Note: Do not use the prepared macro as of no need for a local cache. constinit const FeatureParam kDanglingPtrTypeParam{ &kPartitionAllocDanglingPtr, "type", DanglingPtrType::kAll, &kDanglingPtrTypeOption, }; #if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) // Use a larger maximum thread cache cacheable bucket size. BASE_FEATURE(kPartitionAllocLargeThreadCacheSize, FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kPartitionAllocLargeEmptySlotSpanRing, #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) FEATURE_ENABLED_BY_DEFAULT); #else FEATURE_DISABLED_BY_DEFAULT); #endif BASE_FEATURE_PARAM(int, kPartitionAllocLargeEmptySlotSpanRingSize, &kPartitionAllocLargeEmptySlotSpanRing, "ring-size", partition_alloc::internal::SlotSpanRingMaxSize::kMedium); BASE_FEATURE(kPartitionAllocWithAdvancedChecks, FEATURE_DISABLED_BY_DEFAULT); constexpr FeatureParam::Option kPartitionAllocWithAdvancedChecksEnabledProcessesOptions[] = { {PartitionAllocWithAdvancedChecksEnabledProcesses::kBrowserOnly, kBrowserOnlyStr}, {PartitionAllocWithAdvancedChecksEnabledProcesses::kBrowserAndRenderer, kBrowserAndRendererStr}, {PartitionAllocWithAdvancedChecksEnabledProcesses::kNonRenderer, kNonRendererStr}, {PartitionAllocWithAdvancedChecksEnabledProcesses::kGPUOnly, kGPUOnlyStr}, {PartitionAllocWithAdvancedChecksEnabledProcesses::kBrowserAndGPU, kBrowserAndGPUStr}, {PartitionAllocWithAdvancedChecksEnabledProcesses::kAllProcesses, kAllProcessesStr}}; // Note: Do not use the prepared macro as of no need for a local cache. constinit const FeatureParam kPartitionAllocWithAdvancedChecksEnabledProcessesParam{ &kPartitionAllocWithAdvancedChecks, kPAFeatureEnabledProcessesStr, PartitionAllocWithAdvancedChecksEnabledProcesses::kBrowserOnly, &kPartitionAllocWithAdvancedChecksEnabledProcessesOptions}; BASE_FEATURE(kPartitionAllocSchedulerLoopQuarantine, FEATURE_DISABLED_BY_DEFAULT); // Scheduler Loop Quarantine's config. // Note: Do not use the prepared macro as of no need for a local cache. constinit const FeatureParam kPartitionAllocSchedulerLoopQuarantineConfig{ &kPartitionAllocSchedulerLoopQuarantine, "PartitionAllocSchedulerLoopQuarantineConfig", "{}"}; BASE_FEATURE(kPartitionAllocSchedulerLoopQuarantineTaskControlledPurge, FEATURE_DISABLED_BY_DEFAULT); constexpr FeatureParam< PartitionAllocSchedulerLoopQuarantineTaskControlledPurgeEnabledProcesses>::Option kPartitionAllocSchedulerLoopQuarantineTaskControlledPurgeEnabledProcessesOptions[] = { {PartitionAllocSchedulerLoopQuarantineTaskControlledPurgeEnabledProcesses:: kBrowserOnly, kBrowserOnlyStr}, {PartitionAllocSchedulerLoopQuarantineTaskControlledPurgeEnabledProcesses:: kBrowserAndRenderer, kBrowserAndRendererStr}, {PartitionAllocSchedulerLoopQuarantineTaskControlledPurgeEnabledProcesses:: kNonRenderer, kNonRendererStr}, {PartitionAllocSchedulerLoopQuarantineTaskControlledPurgeEnabledProcesses:: kGPUOnly, kGPUOnlyStr}, {PartitionAllocSchedulerLoopQuarantineTaskControlledPurgeEnabledProcesses:: kBrowserAndGPU, kBrowserAndGPUStr}, {PartitionAllocSchedulerLoopQuarantineTaskControlledPurgeEnabledProcesses:: kAllProcesses, kAllProcessesStr}}; // Note: Do not use the prepared macro as of no need for a local cache. constinit const FeatureParam< PartitionAllocSchedulerLoopQuarantineTaskControlledPurgeEnabledProcesses> kPartitionAllocSchedulerLoopQuarantineTaskControlledPurgeEnabledProcessesParam{ &kPartitionAllocSchedulerLoopQuarantineTaskControlledPurge, "PartitionAllocSchedulerLoopQuarantineTaskControlledPurgeEnabledProcess" "es", PartitionAllocSchedulerLoopQuarantineTaskControlledPurgeEnabledProcesses:: kBrowserOnly, &kPartitionAllocSchedulerLoopQuarantineTaskControlledPurgeEnabledProcessesOptions}; BASE_FEATURE(kPartitionAllocEventuallyZeroFreedMemory, FEATURE_DISABLED_BY_DEFAULT); #endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) BASE_FEATURE(kPartitionAllocBackupRefPtr, #if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_FEATURE_FLAG) FEATURE_ENABLED_BY_DEFAULT #else FEATURE_DISABLED_BY_DEFAULT #endif ); constexpr FeatureParam::Option kBackupRefPtrEnabledProcessesOptions[] = { {BackupRefPtrEnabledProcesses::kBrowserOnly, kBrowserOnlyStr}, {BackupRefPtrEnabledProcesses::kBrowserAndRenderer, kBrowserAndRendererStr}, {BackupRefPtrEnabledProcesses::kNonRenderer, kNonRendererStr}, {BackupRefPtrEnabledProcesses::kAllProcesses, kAllProcessesStr}}; BASE_FEATURE_ENUM_PARAM(BackupRefPtrEnabledProcesses, kBackupRefPtrEnabledProcessesParam, &kPartitionAllocBackupRefPtr, kPAFeatureEnabledProcessesStr, #if PA_BUILDFLAG(IS_ANDROID) BackupRefPtrEnabledProcesses::kNonRenderer, #else BackupRefPtrEnabledProcesses::kAllProcesses, #endif &kBackupRefPtrEnabledProcessesOptions); constexpr FeatureParam::Option kBackupRefPtrModeOptions[] = { {BackupRefPtrMode::kDisabled, "disabled"}, {BackupRefPtrMode::kEnabled, "enabled"}, }; BASE_FEATURE_ENUM_PARAM(BackupRefPtrMode, kBackupRefPtrModeParam, &kPartitionAllocBackupRefPtr, "brp-mode", BackupRefPtrMode::kEnabled, &kBackupRefPtrModeOptions); // Note: Do not use the prepared macro as of no need for a local cache. constinit const FeatureParam kBackupRefPtrExtraExtrasSizeParam{ &kPartitionAllocBackupRefPtr, "brp-extra-extras-size", 0}; constinit const FeatureParam kBackupRefPtrSuppressDoubleFreeDetectedCrash{ &kPartitionAllocBackupRefPtr, "brp-suppress-double-free-detected-crash", false}; constinit const FeatureParam kBackupRefPtrSuppressCorruptionDetectedCrash{ &kPartitionAllocBackupRefPtr, "brp-suppress-corruption-detected-crash", #if PA_BUILDFLAG(IS_IOS) // TODO(crbug.com/41497028): Continue investigation and remove once // addressed. true}; #else false}; #endif BASE_FEATURE(kPartitionAllocMemoryTagging, #if PA_BUILDFLAG(USE_FULL_MTE) || BUILDFLAG(IS_ANDROID) FEATURE_ENABLED_BY_DEFAULT #else FEATURE_DISABLED_BY_DEFAULT #endif ); constexpr FeatureParam::Option kMemtagModeOptions[] = { {MemtagMode::kSync, "sync"}, {MemtagMode::kAsync, "async"}}; // Note: Do not use the prepared muacro as of no need for a local cache. constinit const FeatureParam kMemtagModeParam{ &kPartitionAllocMemoryTagging, "memtag-mode", #if PA_BUILDFLAG(USE_FULL_MTE) MemtagMode::kSync, #else MemtagMode::kAsync, #endif &kMemtagModeOptions}; constexpr FeatureParam::Option kRetagModeOptions[] = { {RetagMode::kIncrement, "increment"}, {RetagMode::kRandom, "random"}, }; // Note: Do not use the prepared macro as of no need for a local cache. constinit const FeatureParam kRetagModeParam{ &kPartitionAllocMemoryTagging, "retag-mode", RetagMode::kIncrement, &kRetagModeOptions}; constexpr FeatureParam::Option kMemoryTaggingEnabledProcessesOptions[] = { {MemoryTaggingEnabledProcesses::kBrowserOnly, kBrowserOnlyStr}, {MemoryTaggingEnabledProcesses::kNonRenderer, kNonRendererStr}, {MemoryTaggingEnabledProcesses::kAllProcesses, kAllProcessesStr}}; // Note: Do not use the prepared macro as of no need for a local cache. constinit const FeatureParam kMemoryTaggingEnabledProcessesParam{ &kPartitionAllocMemoryTagging, kPAFeatureEnabledProcessesStr, #if PA_BUILDFLAG(USE_FULL_MTE) MemoryTaggingEnabledProcesses::kAllProcesses, #else MemoryTaggingEnabledProcesses::kNonRenderer, #endif &kMemoryTaggingEnabledProcessesOptions}; BASE_FEATURE(kKillPartitionAllocMemoryTagging, FEATURE_DISABLED_BY_DEFAULT); BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocPermissiveMte); BASE_FEATURE(kPartitionAllocPermissiveMte, #if PA_BUILDFLAG(USE_FULL_MTE) // We want to actually crash if USE_FULL_MTE is enabled. FEATURE_DISABLED_BY_DEFAULT #else FEATURE_ENABLED_BY_DEFAULT #endif ); BASE_FEATURE(kAsanBrpDereferenceCheck, FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kAsanBrpExtractionCheck, // Not much noise at the moment to FEATURE_DISABLED_BY_DEFAULT); // enable by default. BASE_FEATURE(kAsanBrpInstantiationCheck, FEATURE_ENABLED_BY_DEFAULT); // If enabled, switches the bucket distribution to a denser one. // // We enable this by default everywhere except for 32-bit Android, since we saw // regressions there. BASE_FEATURE(kPartitionAllocUseDenserDistribution, #if BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_32_BITS) FEATURE_DISABLED_BY_DEFAULT #else FEATURE_ENABLED_BY_DEFAULT #endif // BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_32_BITS) ); const FeatureParam::Option kPartitionAllocBucketDistributionOption[] = { {BucketDistributionMode::kDefault, "default"}, {BucketDistributionMode::kDenser, "denser"}, }; // Note: Do not use the prepared macro as of no need for a local cache. constinit const FeatureParam kPartitionAllocBucketDistributionParam{ &kPartitionAllocUseDenserDistribution, "mode", #if BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_32_BITS) BucketDistributionMode::kDefault, #else BucketDistributionMode::kDenser, #endif // BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_32_BITS) &kPartitionAllocBucketDistributionOption}; BASE_FEATURE(kPartitionAllocMemoryReclaimer, FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE_PARAM(TimeDelta, kPartitionAllocMemoryReclaimerInterval, &kPartitionAllocMemoryReclaimer, "interval", TimeDelta() // Defaults to zero. ); // Configures whether we set a lower limit for renderers that do not have a main // frame, similar to the limit that is already done for backgrounded renderers. BASE_FEATURE(kLowerPAMemoryLimitForNonMainRenderers, FEATURE_DISABLED_BY_DEFAULT); // Whether to straighten free lists for larger slot spans in PurgeMemory() -> // ... -> PartitionPurgeSlotSpan(). BASE_FEATURE(kPartitionAllocStraightenLargerSlotSpanFreeLists, FEATURE_ENABLED_BY_DEFAULT); const FeatureParam:: Option kPartitionAllocStraightenLargerSlotSpanFreeListsModeOption[] = { {partition_alloc::StraightenLargerSlotSpanFreeListsMode:: kOnlyWhenUnprovisioning, "only-when-unprovisioning"}, {partition_alloc::StraightenLargerSlotSpanFreeListsMode::kAlways, "always"}, }; // Note: Do not use the prepared macro as of no need for a local cache. constinit const FeatureParam< partition_alloc::StraightenLargerSlotSpanFreeListsMode> kPartitionAllocStraightenLargerSlotSpanFreeListsMode = { &kPartitionAllocStraightenLargerSlotSpanFreeLists, "mode", partition_alloc::StraightenLargerSlotSpanFreeListsMode:: kOnlyWhenUnprovisioning, &kPartitionAllocStraightenLargerSlotSpanFreeListsModeOption, }; // Whether to sort free lists for smaller slot spans in PurgeMemory(). BASE_FEATURE(kPartitionAllocSortSmallerSlotSpanFreeLists, FEATURE_ENABLED_BY_DEFAULT); // Whether to sort the active slot spans in PurgeMemory(). BASE_FEATURE(kPartitionAllocSortActiveSlotSpans, FEATURE_DISABLED_BY_DEFAULT); #if BUILDFLAG(IS_WIN) // Whether to retry allocations when commit fails. BASE_FEATURE(kPageAllocatorRetryOnCommitFailure, FEATURE_ENABLED_BY_DEFAULT); #endif #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) // A parameter to exclude or not exclude PartitionAllocSupport from // PartialLowModeOnMidRangeDevices. This is used to see how it affects // renderer performances, e.g. blink_perf.parser benchmark. // The feature: kPartialLowEndModeOnMidRangeDevices is defined in // //base/features.cc. Since the following feature param is related to // PartitionAlloc, define the param here. BASE_FEATURE_PARAM(bool, kPartialLowEndModeExcludePartitionAllocSupport, &kPartialLowEndModeOnMidRangeDevices, "exclude-partition-alloc-support", false); #endif constexpr partition_alloc::internal::base::TimeDelta ToPartitionAllocTimeDelta( TimeDelta time_delta) { return partition_alloc::internal::base::Microseconds( time_delta.InMicroseconds()); } constexpr TimeDelta FromPartitionAllocTimeDelta( partition_alloc::internal::base::TimeDelta time_delta) { return Microseconds(time_delta.InMicroseconds()); } BASE_FEATURE(kPartitionAllocAdjustSizeWhenInForeground, #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) FEATURE_ENABLED_BY_DEFAULT); #else FEATURE_DISABLED_BY_DEFAULT); #endif BASE_FEATURE_PARAM( int, kPartitionAllocForegroundEmptySlotSpanRingSize, &kPartitionAllocAdjustSizeWhenInForeground, "foreground-ring-size", static_cast(partition_alloc::internal::kMaxEmptySlotSpanRingSize)); BASE_FEATURE_PARAM(int, kPartitionAllocBackgroundEmptySlotSpanRingSize, &kPartitionAllocAdjustSizeWhenInForeground, "background-ring-size", partition_alloc::internal::SlotSpanRingMaxSize::kMedium); #if PA_BUILDFLAG(ENABLE_PARTITION_LOCK_PRIORITY_INHERITANCE) BASE_FEATURE(kPartitionAllocUsePriorityInheritanceLocks, FEATURE_DISABLED_BY_DEFAULT); #endif // PA_BUILDFLAG(ENABLE_PARTITION_LOCK_PRIORITY_INHERITANCE) BASE_FEATURE(kPartitionAllocFreeWithSize, FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE_PARAM(bool, kPartitionAllocStrictFreeSizeCheck, &kPartitionAllocFreeWithSize, "strict-free-size-check", true); #if BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_ARM64) BASE_FEATURE(kPartitionAllocLockTuneSpin, FEATURE_DISABLED_BY_DEFAULT); // On ARM64, 2048 cycles results in spinning for 500-1500 nanoseconds on most // Android devices which overlaps with the time spent on a futex syscall. BASE_FEATURE_PARAM(int, kPartitionAllocLockSpinCount, &kPartitionAllocLockTuneSpin, "spin_count", 2048); #endif // BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_ARM64) } // namespace base::features