1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/allocator/partition_alloc_features.h"
6
7 #include "base/allocator/miracle_parameter.h"
8 #include "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time.h"
9 #include "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_buildflags.h"
10 #include "base/allocator/partition_allocator/src/partition_alloc/partition_root.h"
11 #include "base/allocator/partition_allocator/src/partition_alloc/thread_cache.h"
12 #include "base/base_export.h"
13 #include "base/feature_list.h"
14 #include "base/features.h"
15 #include "base/metrics/field_trial_params.h"
16 #include "base/time/time.h"
17 #include "build/build_config.h"
18 #include "build/chromecast_buildflags.h"
19 #include "build/chromeos_buildflags.h"
20
21 namespace base {
22 namespace features {
23
24 BASE_FEATURE(kPartitionAllocUnretainedDanglingPtr,
25 "PartitionAllocUnretainedDanglingPtr",
26 FEATURE_ENABLED_BY_DEFAULT);
27
28 constexpr FeatureParam<UnretainedDanglingPtrMode>::Option
29 kUnretainedDanglingPtrModeOption[] = {
30 {UnretainedDanglingPtrMode::kCrash, "crash"},
31 {UnretainedDanglingPtrMode::kDumpWithoutCrashing,
32 "dump_without_crashing"},
33 };
34 const base::FeatureParam<UnretainedDanglingPtrMode>
35 kUnretainedDanglingPtrModeParam = {
36 &kPartitionAllocUnretainedDanglingPtr,
37 "mode",
38 UnretainedDanglingPtrMode::kDumpWithoutCrashing,
39 &kUnretainedDanglingPtrModeOption,
40 };
41
42 BASE_FEATURE(kPartitionAllocDanglingPtr,
43 "PartitionAllocDanglingPtr",
44 #if BUILDFLAG(ENABLE_DANGLING_RAW_PTR_FEATURE_FLAG) || \
45 (BUILDFLAG(ENABLE_DANGLING_RAW_PTR_CHECKS) && BUILDFLAG(IS_LINUX) && \
46 !defined(OFFICIAL_BUILD) && (!defined(NDEBUG) || DCHECK_IS_ON()))
47 FEATURE_ENABLED_BY_DEFAULT
48 #else
49 FEATURE_DISABLED_BY_DEFAULT
50 #endif
51 );
52
53 constexpr FeatureParam<DanglingPtrMode>::Option kDanglingPtrModeOption[] = {
54 {DanglingPtrMode::kCrash, "crash"},
55 {DanglingPtrMode::kLogOnly, "log_only"},
56 };
57 const base::FeatureParam<DanglingPtrMode> kDanglingPtrModeParam{
58 &kPartitionAllocDanglingPtr,
59 "mode",
60 DanglingPtrMode::kCrash,
61 &kDanglingPtrModeOption,
62 };
63 constexpr FeatureParam<DanglingPtrType>::Option kDanglingPtrTypeOption[] = {
64 {DanglingPtrType::kAll, "all"},
65 {DanglingPtrType::kCrossTask, "cross_task"},
66 };
67 const base::FeatureParam<DanglingPtrType> kDanglingPtrTypeParam{
68 &kPartitionAllocDanglingPtr,
69 "type",
70 DanglingPtrType::kAll,
71 &kDanglingPtrTypeOption,
72 };
73
74 #if BUILDFLAG(USE_STARSCAN)
75 // If enabled, PCScan is turned on by default for all partitions that don't
76 // disable it explicitly.
77 BASE_FEATURE(kPartitionAllocPCScan,
78 "PartitionAllocPCScan",
79 FEATURE_DISABLED_BY_DEFAULT);
80 #endif // BUILDFLAG(USE_STARSCAN)
81
82 #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
83 // If enabled, PCScan is turned on only for the browser's malloc partition.
84 BASE_FEATURE(kPartitionAllocPCScanBrowserOnly,
85 "PartitionAllocPCScanBrowserOnly",
86 FEATURE_DISABLED_BY_DEFAULT);
87
88 // If enabled, PCScan is turned on only for the renderer's malloc partition.
89 BASE_FEATURE(kPartitionAllocPCScanRendererOnly,
90 "PartitionAllocPCScanRendererOnly",
91 FEATURE_DISABLED_BY_DEFAULT);
92
93 // Use a larger maximum thread cache cacheable bucket size.
94 BASE_FEATURE(kPartitionAllocLargeThreadCacheSize,
95 "PartitionAllocLargeThreadCacheSize",
96 FEATURE_ENABLED_BY_DEFAULT);
97
98 MIRACLE_PARAMETER_FOR_INT(
99 GetPartitionAllocLargeThreadCacheSizeValue,
100 kPartitionAllocLargeThreadCacheSize,
101 "PartitionAllocLargeThreadCacheSizeValue",
102 ::partition_alloc::ThreadCacheLimits::kLargeSizeThreshold)
103
104 MIRACLE_PARAMETER_FOR_INT(
105 GetPartitionAllocLargeThreadCacheSizeValueForLowRAMAndroid,
106 kPartitionAllocLargeThreadCacheSize,
107 "PartitionAllocLargeThreadCacheSizeValueForLowRAMAndroid",
108 ::partition_alloc::ThreadCacheLimits::kDefaultSizeThreshold)
109
110 BASE_FEATURE(kPartitionAllocLargeEmptySlotSpanRing,
111 "PartitionAllocLargeEmptySlotSpanRing",
112 FEATURE_DISABLED_BY_DEFAULT);
113
114 BASE_FEATURE(kPartitionAllocSchedulerLoopQuarantine,
115 "PartitionAllocSchedulerLoopQuarantine",
116 FEATURE_DISABLED_BY_DEFAULT);
117 // Scheduler Loop Quarantine's capacity in bytes.
118 const base::FeatureParam<int> kPartitionAllocSchedulerLoopQuarantineCapacity{
119 &kPartitionAllocSchedulerLoopQuarantine,
120 "PartitionAllocSchedulerLoopQuarantineCapacity", 0};
121
122 BASE_FEATURE(kPartitionAllocZappingByFreeFlags,
123 "PartitionAllocZappingByFreeFlags",
124 FEATURE_DISABLED_BY_DEFAULT);
125 #endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
126
127 BASE_FEATURE(kPartitionAllocBackupRefPtr,
128 "PartitionAllocBackupRefPtr",
129 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || \
130 BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS) || \
131 (BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CASTOS)) || \
132 BUILDFLAG(ENABLE_BACKUP_REF_PTR_FEATURE_FLAG)
133 FEATURE_ENABLED_BY_DEFAULT
134 #else
135 FEATURE_DISABLED_BY_DEFAULT
136 #endif
137 );
138
139 BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocBackupRefPtrForAsh);
140 BASE_FEATURE(kPartitionAllocBackupRefPtrForAsh,
141 "PartitionAllocBackupRefPtrForAsh",
142 FEATURE_ENABLED_BY_DEFAULT);
143
144 constexpr FeatureParam<BackupRefPtrEnabledProcesses>::Option
145 kBackupRefPtrEnabledProcessesOptions[] = {
146 {BackupRefPtrEnabledProcesses::kBrowserOnly, "browser-only"},
147 {BackupRefPtrEnabledProcesses::kBrowserAndRenderer,
148 "browser-and-renderer"},
149 {BackupRefPtrEnabledProcesses::kNonRenderer, "non-renderer"},
150 {BackupRefPtrEnabledProcesses::kAllProcesses, "all-processes"}};
151
152 const base::FeatureParam<BackupRefPtrEnabledProcesses>
153 kBackupRefPtrEnabledProcessesParam{
154 &kPartitionAllocBackupRefPtr, "enabled-processes",
155 BackupRefPtrEnabledProcesses::kNonRenderer,
156 &kBackupRefPtrEnabledProcessesOptions};
157
158 constexpr FeatureParam<BackupRefPtrRefCountSize>::Option
159 kBackupRefPtrRefCountSizeOptions[] = {
160 {BackupRefPtrRefCountSize::kNatural, "natural"},
161 {BackupRefPtrRefCountSize::k4B, "4B"},
162 {BackupRefPtrRefCountSize::k8B, "8B"},
163 {BackupRefPtrRefCountSize::k16B, "16B"}};
164
165 const base::FeatureParam<BackupRefPtrRefCountSize>
166 kBackupRefPtrRefCountSizeParam{
167 &kPartitionAllocBackupRefPtr, "ref-count-size",
168 BackupRefPtrRefCountSize::kNatural, &kBackupRefPtrRefCountSizeOptions};
169
170 // Map -with-memory-reclaimer modes onto their counterpars without the suffix.
171 // They are the same, as memory reclaimer is now controlled independently.
172 // However, we need to keep both option strings, as there is a long tail of
173 // clients that may have an old field trial config, which used these modes.
174 //
175 // DO NOT USE -with-memory-reclaimer modes in new configs!
176 constexpr FeatureParam<BackupRefPtrMode>::Option kBackupRefPtrModeOptions[] = {
177 {BackupRefPtrMode::kDisabled, "disabled"},
178 {BackupRefPtrMode::kEnabled, "enabled"},
179 {BackupRefPtrMode::kEnabled, "enabled-with-memory-reclaimer"},
180 {BackupRefPtrMode::kDisabledButSplitPartitions2Way,
181 "disabled-but-2-way-split"},
182 {BackupRefPtrMode::kDisabledButSplitPartitions2Way,
183 "disabled-but-2-way-split-with-memory-reclaimer"},
184 {BackupRefPtrMode::kDisabledButSplitPartitions3Way,
185 "disabled-but-3-way-split"},
186 };
187
188 const base::FeatureParam<BackupRefPtrMode> kBackupRefPtrModeParam{
189 &kPartitionAllocBackupRefPtr, "brp-mode", BackupRefPtrMode::kEnabled,
190 &kBackupRefPtrModeOptions};
191
192 BASE_FEATURE(kPartitionAllocMemoryTagging,
193 "PartitionAllocMemoryTagging",
194 FEATURE_DISABLED_BY_DEFAULT);
195
196 constexpr FeatureParam<MemtagMode>::Option kMemtagModeOptions[] = {
197 {MemtagMode::kSync, "sync"},
198 {MemtagMode::kAsync, "async"}};
199
200 const base::FeatureParam<MemtagMode> kMemtagModeParam{
201 &kPartitionAllocMemoryTagging, "memtag-mode", MemtagMode::kAsync,
202 &kMemtagModeOptions};
203
204 constexpr FeatureParam<MemoryTaggingEnabledProcesses>::Option
205 kMemoryTaggingEnabledProcessesOptions[] = {
206 {MemoryTaggingEnabledProcesses::kBrowserOnly, "browser-only"},
207 {MemoryTaggingEnabledProcesses::kNonRenderer, "non-renderer"},
208 {MemoryTaggingEnabledProcesses::kAllProcesses, "all-processes"}};
209
210 const base::FeatureParam<MemoryTaggingEnabledProcesses>
211 kMemoryTaggingEnabledProcessesParam{
212 &kPartitionAllocMemoryTagging, "enabled-processes",
213 MemoryTaggingEnabledProcesses::kBrowserOnly,
214 &kMemoryTaggingEnabledProcessesOptions};
215
216 BASE_FEATURE(kKillPartitionAllocMemoryTagging,
217 "KillPartitionAllocMemoryTagging",
218 FEATURE_DISABLED_BY_DEFAULT);
219
220 BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocPermissiveMte);
221 BASE_FEATURE(kPartitionAllocPermissiveMte,
222 "PartitionAllocPermissiveMte",
223 FEATURE_ENABLED_BY_DEFAULT);
224
225 const base::FeatureParam<bool> kBackupRefPtrAsanEnableDereferenceCheckParam{
226 &kPartitionAllocBackupRefPtr, "asan-enable-dereference-check", true};
227 const base::FeatureParam<bool> kBackupRefPtrAsanEnableExtractionCheckParam{
228 &kPartitionAllocBackupRefPtr, "asan-enable-extraction-check",
229 false}; // Not much noise at the moment to enable by default.
230 const base::FeatureParam<bool> kBackupRefPtrAsanEnableInstantiationCheckParam{
231 &kPartitionAllocBackupRefPtr, "asan-enable-instantiation-check", true};
232
233 // If enabled, switches the bucket distribution to a denser one.
234 //
235 // We enable this by default everywhere except for 32-bit Android, since we saw
236 // regressions there.
237 BASE_FEATURE(kPartitionAllocUseDenserDistribution,
238 "PartitionAllocUseDenserDistribution",
239 #if BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_32_BITS)
240 FEATURE_DISABLED_BY_DEFAULT
241 #else
242 FEATURE_ENABLED_BY_DEFAULT
243 #endif // BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_32_BITS)
244 );
245 const base::FeatureParam<BucketDistributionMode>::Option
246 kPartitionAllocBucketDistributionOption[] = {
247 {BucketDistributionMode::kDefault, "default"},
248 {BucketDistributionMode::kDenser, "denser"},
249 };
250 const base::FeatureParam<BucketDistributionMode>
251 kPartitionAllocBucketDistributionParam {
252 &kPartitionAllocUseDenserDistribution, "mode",
253 #if BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_32_BITS)
254 BucketDistributionMode::kDefault,
255 #else
256 BucketDistributionMode::kDenser,
257 #endif // BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_32_BITS)
258 &kPartitionAllocBucketDistributionOption
259 };
260
261 BASE_FEATURE(kPartitionAllocMemoryReclaimer,
262 "PartitionAllocMemoryReclaimer",
263 FEATURE_ENABLED_BY_DEFAULT);
264 const base::FeatureParam<TimeDelta> kPartitionAllocMemoryReclaimerInterval = {
265 &kPartitionAllocMemoryReclaimer, "interval",
266 TimeDelta(), // Defaults to zero.
267 };
268
269 // Configures whether we set a lower limit for renderers that do not have a main
270 // frame, similar to the limit that is already done for backgrounded renderers.
271 BASE_FEATURE(kLowerPAMemoryLimitForNonMainRenderers,
272 "LowerPAMemoryLimitForNonMainRenderers",
273 FEATURE_DISABLED_BY_DEFAULT);
274
275 // If enabled, switches PCScan scheduling to a mutator-aware scheduler. Does not
276 // affect whether PCScan is enabled itself.
277 BASE_FEATURE(kPartitionAllocPCScanMUAwareScheduler,
278 "PartitionAllocPCScanMUAwareScheduler",
279 FEATURE_ENABLED_BY_DEFAULT);
280
281 // If enabled, PCScan frees unconditionally all quarantined objects.
282 // This is a performance testing feature.
283 BASE_FEATURE(kPartitionAllocPCScanImmediateFreeing,
284 "PartitionAllocPCScanImmediateFreeing",
285 FEATURE_DISABLED_BY_DEFAULT);
286
287 // If enabled, PCScan clears eagerly (synchronously) on free().
288 BASE_FEATURE(kPartitionAllocPCScanEagerClearing,
289 "PartitionAllocPCScanEagerClearing",
290 FEATURE_DISABLED_BY_DEFAULT);
291
292 // In addition to heap, scan also the stack of the current mutator.
293 BASE_FEATURE(kPartitionAllocPCScanStackScanning,
294 "PartitionAllocPCScanStackScanning",
295 #if BUILDFLAG(PCSCAN_STACK_SUPPORTED)
296 FEATURE_ENABLED_BY_DEFAULT
297 #else
298 FEATURE_DISABLED_BY_DEFAULT
299 #endif // BUILDFLAG(PCSCAN_STACK_SUPPORTED)
300 );
301
302 BASE_FEATURE(kPartitionAllocDCScan,
303 "PartitionAllocDCScan",
304 FEATURE_DISABLED_BY_DEFAULT);
305
306 // Whether to straighten free lists for larger slot spans in PurgeMemory() ->
307 // ... -> PartitionPurgeSlotSpan().
308 BASE_FEATURE(kPartitionAllocStraightenLargerSlotSpanFreeLists,
309 "PartitionAllocStraightenLargerSlotSpanFreeLists",
310 FEATURE_ENABLED_BY_DEFAULT);
311 const base::FeatureParam<
312 partition_alloc::StraightenLargerSlotSpanFreeListsMode>::Option
313 kPartitionAllocStraightenLargerSlotSpanFreeListsModeOption[] = {
314 {partition_alloc::StraightenLargerSlotSpanFreeListsMode::
315 kOnlyWhenUnprovisioning,
316 "only-when-unprovisioning"},
317 {partition_alloc::StraightenLargerSlotSpanFreeListsMode::kAlways,
318 "always"},
319 };
320 const base::FeatureParam<partition_alloc::StraightenLargerSlotSpanFreeListsMode>
321 kPartitionAllocStraightenLargerSlotSpanFreeListsMode = {
322 &kPartitionAllocStraightenLargerSlotSpanFreeLists,
323 "mode",
324 partition_alloc::StraightenLargerSlotSpanFreeListsMode::
325 kOnlyWhenUnprovisioning,
326 &kPartitionAllocStraightenLargerSlotSpanFreeListsModeOption,
327 };
328
329 // Whether to sort free lists for smaller slot spans in PurgeMemory().
330 BASE_FEATURE(kPartitionAllocSortSmallerSlotSpanFreeLists,
331 "PartitionAllocSortSmallerSlotSpanFreeLists",
332 FEATURE_ENABLED_BY_DEFAULT);
333
334 // Whether to sort the active slot spans in PurgeMemory().
335 BASE_FEATURE(kPartitionAllocSortActiveSlotSpans,
336 "PartitionAllocSortActiveSlotSpans",
337 FEATURE_DISABLED_BY_DEFAULT);
338
339 #if BUILDFLAG(IS_WIN)
340 // Whether to retry allocations when commit fails.
341 BASE_FEATURE(kPageAllocatorRetryOnCommitFailure,
342 "PageAllocatorRetryOnCommitFailure",
343 FEATURE_DISABLED_BY_DEFAULT);
344 #endif
345
346 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS)
347 // A parameter to exclude or not exclude PartitionAllocSupport from
348 // PartialLowModeOnMidRangeDevices. This is used to see how it affects
349 // renderer performances, e.g. blink_perf.parser benchmark.
350 // The feature: kPartialLowEndModeOnMidRangeDevices is defined in
351 // //base/features.cc. Since the following feature param is related to
352 // PartitionAlloc, define the param here.
353 const FeatureParam<bool> kPartialLowEndModeExcludePartitionAllocSupport{
354 &kPartialLowEndModeOnMidRangeDevices, "exclude-partition-alloc-support",
355 false};
356 #endif
357
358 BASE_FEATURE(kEnableConfigurableThreadCacheMultiplier,
359 "EnableConfigurableThreadCacheMultiplier",
360 base::FEATURE_DISABLED_BY_DEFAULT);
361
362 MIRACLE_PARAMETER_FOR_DOUBLE(GetThreadCacheMultiplier,
363 kEnableConfigurableThreadCacheMultiplier,
364 "ThreadCacheMultiplier",
365 2.)
366
367 MIRACLE_PARAMETER_FOR_DOUBLE(GetThreadCacheMultiplierForAndroid,
368 kEnableConfigurableThreadCacheMultiplier,
369 "ThreadCacheMultiplierForAndroid",
370 1.)
371
ToPartitionAllocTimeDelta(base::TimeDelta time_delta)372 constexpr partition_alloc::internal::base::TimeDelta ToPartitionAllocTimeDelta(
373 base::TimeDelta time_delta) {
374 return partition_alloc::internal::base::Microseconds(
375 time_delta.InMicroseconds());
376 }
377
FromPartitionAllocTimeDelta(partition_alloc::internal::base::TimeDelta time_delta)378 constexpr base::TimeDelta FromPartitionAllocTimeDelta(
379 partition_alloc::internal::base::TimeDelta time_delta) {
380 return base::Microseconds(time_delta.InMicroseconds());
381 }
382
383 BASE_FEATURE(kEnableConfigurableThreadCachePurgeInterval,
384 "EnableConfigurableThreadCachePurgeInterval",
385 base::FEATURE_DISABLED_BY_DEFAULT);
386
387 MIRACLE_PARAMETER_FOR_TIME_DELTA(
388 GetThreadCacheMinPurgeIntervalValue,
389 kEnableConfigurableThreadCachePurgeInterval,
390 "ThreadCacheMinPurgeInterval",
391 FromPartitionAllocTimeDelta(partition_alloc::kMinPurgeInterval))
392
393 MIRACLE_PARAMETER_FOR_TIME_DELTA(
394 GetThreadCacheMaxPurgeIntervalValue,
395 kEnableConfigurableThreadCachePurgeInterval,
396 "ThreadCacheMaxPurgeInterval",
397 FromPartitionAllocTimeDelta(partition_alloc::kMaxPurgeInterval))
398
399 MIRACLE_PARAMETER_FOR_TIME_DELTA(
400 GetThreadCacheDefaultPurgeIntervalValue,
401 kEnableConfigurableThreadCachePurgeInterval,
402 "ThreadCacheDefaultPurgeInterval",
403 FromPartitionAllocTimeDelta(partition_alloc::kDefaultPurgeInterval))
404
405 const partition_alloc::internal::base::TimeDelta
GetThreadCacheMinPurgeInterval()406 GetThreadCacheMinPurgeInterval() {
407 return ToPartitionAllocTimeDelta(GetThreadCacheMinPurgeIntervalValue());
408 }
409
410 const partition_alloc::internal::base::TimeDelta
GetThreadCacheMaxPurgeInterval()411 GetThreadCacheMaxPurgeInterval() {
412 return ToPartitionAllocTimeDelta(GetThreadCacheMaxPurgeIntervalValue());
413 }
414
415 const partition_alloc::internal::base::TimeDelta
GetThreadCacheDefaultPurgeInterval()416 GetThreadCacheDefaultPurgeInterval() {
417 return ToPartitionAllocTimeDelta(GetThreadCacheDefaultPurgeIntervalValue());
418 }
419
420 BASE_FEATURE(kEnableConfigurableThreadCacheMinCachedMemoryForPurging,
421 "EnableConfigurableThreadCacheMinCachedMemoryForPurging",
422 base::FEATURE_DISABLED_BY_DEFAULT);
423
424 MIRACLE_PARAMETER_FOR_INT(
425 GetThreadCacheMinCachedMemoryForPurgingBytes,
426 kEnableConfigurableThreadCacheMinCachedMemoryForPurging,
427 "ThreadCacheMinCachedMemoryForPurgingBytes",
428 partition_alloc::kMinCachedMemoryForPurgingBytes)
429
430 // An apparent quarantine leak in the buffer partition unacceptably
431 // bloats memory when MiraclePtr is enabled in the renderer process.
432 // We believe we have found and patched the leak, but out of an
433 // abundance of caution, we provide this toggle that allows us to
434 // wholly disable MiraclePtr in the buffer partition, if necessary.
435 //
436 // TODO(crbug.com/1444624): this is unneeded once
437 // MiraclePtr-for-Renderer launches.
438 BASE_FEATURE(kPartitionAllocDisableBRPInBufferPartition,
439 "PartitionAllocDisableBRPInBufferPartition",
440 FEATURE_DISABLED_BY_DEFAULT);
441
442 #if BUILDFLAG(USE_FREELIST_POOL_OFFSETS)
443 BASE_FEATURE(kUsePoolOffsetFreelists,
444 "PartitionAllocUsePoolOffsetFreelists",
445 base::FEATURE_DISABLED_BY_DEFAULT);
446 #endif
447
448 } // namespace features
449 } // namespace base
450