Compare commits

...

No commits in common. "v132.0.6834.79-1" and "master" have entirely different histories.

6432 changed files with 510072 additions and 246971 deletions

View file

@ -396,8 +396,8 @@ jobs:
openwrt: "target=sunxi subtarget=cortexa53"
target_cpu: arm64
extra: 'arm_cpu="cortex-a53" build_static=true use_allocator_shim=false use_partition_alloc=false'
openwrt_release: '23.05.0'
openwrt_gcc_ver: '12.3.0'
openwrt_release: '24.10.0'
openwrt_gcc_ver: '13.3.0'
- arch: aarch64_cortex-a72
openwrt: "target=mvebu subtarget=cortexa72"
target_cpu: arm64
@ -406,8 +406,14 @@ jobs:
openwrt: "target=mvebu subtarget=cortexa72"
target_cpu: arm64
extra: 'arm_cpu="cortex-a72" build_static=true use_allocator_shim=false use_partition_alloc=false'
openwrt_release: '23.05.0'
openwrt_gcc_ver: '12.3.0'
openwrt_release: '24.10.0'
openwrt_gcc_ver: '13.3.0'
- arch: aarch64_cortex-a76
openwrt: "target=bcm27xx subtarget=bcm2712"
target_cpu: arm64
extra: 'arm_cpu="cortex-a76"'
openwrt_release: '24.10.0'
openwrt_gcc_ver: '13.3.0'
- arch: aarch64_generic
openwrt: "target=layerscape subtarget=armv8_64b"
target_cpu: arm64
@ -415,8 +421,8 @@ jobs:
openwrt: "target=layerscape subtarget=armv8_64b"
target_cpu: arm64
extra: "build_static=true use_allocator_shim=false use_partition_alloc=false"
openwrt_release: '23.05.0'
openwrt_gcc_ver: '12.3.0'
openwrt_release: '24.10.0'
openwrt_gcc_ver: '13.3.0'
- arch: arm_arm1176jzf-s_vfp
openwrt: "target=brcm2708 subtarget=bcm2708"
target_cpu: arm
@ -447,8 +453,8 @@ jobs:
openwrt: "target=sunxi subtarget=cortexa7"
target_cpu: arm
extra: 'arm_version=0 arm_cpu="cortex-a7" arm_fpu="neon-vfpv4" arm_float_abi="hard" arm_use_neon=true build_static=true use_allocator_shim=false use_partition_alloc=false'
openwrt_release: '23.05.0'
openwrt_gcc_ver: '12.3.0'
openwrt_release: '24.10.0'
openwrt_gcc_ver: '13.3.0'
- arch: arm_cortex-a7_vfpv4
openwrt: "target=at91 subtarget=sama7"
target_cpu: arm
@ -467,8 +473,8 @@ jobs:
openwrt: "target=bcm53xx subtarget=generic"
target_cpu: arm
extra: 'arm_version=0 arm_cpu="cortex-a9" arm_float_abi="soft" arm_use_neon=false build_static=true use_allocator_shim=false use_partition_alloc=false'
openwrt_release: '23.05.0'
openwrt_gcc_ver: '12.3.0'
openwrt_release: '24.10.0'
openwrt_gcc_ver: '13.3.0'
- arch: arm_cortex-a9_neon
openwrt: "target=imx6 subtarget=generic"
target_cpu: arm
@ -493,8 +499,8 @@ jobs:
openwrt: "target=ramips subtarget=rt305x"
target_cpu: mipsel
extra: 'mips_arch_variant="r2" mips_float_abi="soft" build_static=true use_allocator_shim=false use_partition_alloc=false'
openwrt_release: '23.05.0'
openwrt_gcc_ver: '12.3.0'
openwrt_release: '24.10.0'
openwrt_gcc_ver: '13.3.0'
- arch: mipsel_mips32
openwrt: "target=brcm47xx subtarget=legacy"
target_cpu: mipsel

View file

@ -1 +1 @@
132.0.6834.79
134.0.6998.39

View file

@ -82,7 +82,6 @@ Or `quic://user:pass@example.com`, if it works better. See also [parameter usage
* [v2rayN](https://github.com/2dust/v2rayN), GUI client, Windows
* [NekoBox for Android](https://github.com/MatsuriDayo/NekoBoxForAndroid), Proxy toolchain, Android
* [NekoRay / NekoBox For PC](https://github.com/MatsuriDayo/nekoray), Qt based GUI, Windows, Linux
* [Yet Another Shadow Socket](https://github.com/Chilledheart/yass), NaïveProxy-compatible forward proxy, Android, iOS, Windows, macOS, Linux, FreeBSD
## Notes for downstream

View file

@ -90,7 +90,7 @@ no_check_targets = [
"//v8:v8_libplatform", # 2 errors
]
# These are the list of GN files that run exec_script. This whitelist exists
# These are the list of GN files that run exec_script. This allowlist exists
# to force additional review for new uses of exec_script, which is strongly
# discouraged.
#
@ -145,11 +145,11 @@ no_check_targets = [
# this situation much easier to create. if the build always lists the
# files and passes them to a script, it will always be correct.
exec_script_whitelist =
build_dotfile_settings.exec_script_whitelist +
exec_script_allowlist =
build_dotfile_settings.exec_script_allowlist +
angle_dotfile_settings.exec_script_whitelist +
[
# Whitelist entries for //build should go into
# Allowlist entries for //build should go into
# //build/dotfile_settings.gni instead, so that they can be shared
# with other repos. The entries in this list should be only for files
# in the Chromium repo outside of //build.

View file

@ -118,6 +118,7 @@ Andreas Papacharalampous <andreas@apap04.com>
Andrei Borza <andrei.borza@gmail.com>
Andrei Parvu <andrei.prv@gmail.com>
Andrei Parvu <parvu@adobe.com>
Andrei Volykhin <andrei.volykhin@gmail.com>
Andres Salomon <dilinger@queued.net>
Andreu Botella <andreu@andreubotella.com>
Andrew Boyarshin <andrew.boyarshin@gmail.com>
@ -312,6 +313,7 @@ Daniel Lockyer <thisisdaniellockyer@gmail.com>
Daniel Nishi <dhnishi@gmail.com>
Daniel Platz <daplatz@googlemail.com>
Daniel Playfair Cal <daniel.playfair.cal@gmail.com>
Daniel Richard G. <iskunk@gmail.com>
Daniel Shaulov <dshaulov@ptc.com>
Daniel Trebbien <dtrebbien@gmail.com>
Daniel Waxweiler <daniel.waxweiler@gmail.com>
@ -329,8 +331,10 @@ Darshini KN <kn.darshini@samsung.com>
Dave Vandyke <kzar@kzar.co.uk>
David Benjamin <davidben@mit.edu>
David Brown <develop.david.brown@gmail.com>
David Cernoch <dcernoch@uplandsoftware.com>
David Davidovic <david@davidovic.io>
David Erceg <erceg.david@gmail.com>
David Faden <dfaden@gmail.com>
David Fox <david@davidjfox.com>
David Futcher <david.mike.futcher@gmail.com>
David Jin <davidjin@amazon.com>
@ -366,6 +370,7 @@ Diana Suvorova <diana.suvorova@gmail.com>
Diego Fernández Santos <agujaydedal@gmail.com>
Diego Ferreiro Val <elfogris@gmail.com>
Dillon Sellars <dill.sellars@gmail.com>
Dingming Liu <liudingming@bytedance.com>
Divya Bansal <divya.bansal@samsung.com>
Dmitry Shachnev <mitya57@gmail.com>
Dmitry Sokolov <dimanne@gmail.com>
@ -502,6 +507,7 @@ Hansel Lee <mr.hansel.lee@gmail.com>
Hanwen Zheng <eserinc.z@gmail.com>
Hao Li <hao.x.li@intel.com>
Haojian Wu <hokein.wu@gmail.com>
Haoran Tang <haoran.tang.personal@gmail.com>
Haoxuan Zhang <zhanghaoxuan.59@bytedance.com>
Hari Singh <hari.singh1@samsung.com>
Harpreet Singh Khurana <harpreet.sk@samsung.com>
@ -623,8 +629,10 @@ Jared Wein <weinjared@gmail.com>
Jari Karppanen <jkarp@amazon.com>
Jason Gronn <jasontopia03@gmail.com>
Javayhu <javayhu@gmail.com>
Jay Kapadia <jaykapadia389@gmail.com>
Jay Oster <jay@kodewerx.org>
Jay Soffian <jaysoffian@gmail.com>
Jay Yang <sjyang1126@gmail.com>
Jeado Ko <haibane84@gmail.com>
Jeffrey C <jeffreyca16@gmail.com>
Jeffrey Yeung <jeffrey.yeung@poly.com>
@ -723,6 +731,7 @@ Joseph Lolak <joseph.lolak@samsung.com>
Josh Triplett <josh.triplett@intel.com>
Josh Triplett <josh@joshtriplett.org>
Joshua Lock <joshua.lock@intel.com>
Joshua Olaoye <joshuaolaoye46@gmail.com>
Joshua Roesslein <jroesslein@gmail.com>
Josué Ratelle <jorat1346@gmail.com>
Josyula Venkat Narasimham <venkat.nj@samsung.com>
@ -772,6 +781,7 @@ Kangyuan Shu <kangyuan.shu@intel.com>
Karan Thakkar <karanjthakkar@gmail.com>
Karel Král <kralkareliv@gmail.com>
Karl <karlpolicechromium@gmail.com>
Karl Piper <karl4piper@gmail.com>
Kartikey Bhatt <kartikey@amazon.com>
Kaspar Brand <googlecontrib@velox.ch>
Kaushalendra Mishra <k.mishra@samsung.com>
@ -931,6 +941,7 @@ Martin Persson <mnpn03@gmail.com>
Martin Rogalla <martin@martinrogalla.com>
Martina Kollarova <martina.kollarova@intel.com>
Martino Fontana <tinozzo123@gmail.com>
Marvin Giessing <marvin.giessing@gmail.com>
Masahiro Yado <yado.masa@gmail.com>
Masaru Nishida <msr.i386@gmail.com>
Masayuki Wakizaka <mwakizaka0108@gmail.com>
@ -941,6 +952,7 @@ Mathieu Meisser <mmeisser@logitech.com>
Matt Arpidone <mma.public@gmail.com>
Matt Fysh <mattfysh@gmail.com>
Matt Harding <majaharding@gmail.com>
Matt Jolly <kangie@gentoo.org>
Matt Strum <mstrum@amazon.com>
Matt Zeunert <matt@mostlystatic.com>
Matthew "strager" Glazar <strager.nds@gmail.com>
@ -964,10 +976,12 @@ Mc Zeng <zengmcong@gmail.com>
Md Abdullah Al Alamin <a.alamin.cse@gmail.com>
Md. Hasanur Rashid <hasanur.r@samsung.com>
Md Hasibul Hasan <hasibulhasan873@gmail.com>
Md Hasibul Hasan <hasibul.h@samsung.com>
Md Jobed Hossain <jobed.h@samsung.com>
Md Raiyan bin Sayeed <mrbsayee@uwaterloo.ca>
Md. Sadiqul Amin <sadiqul.amin@samsung.com>
Md Sami Uddin <md.sami@samsung.com>
Mego Tan <tannal2409@gmail.com>
Merajul Arefin <merajularefin@gmail.com>
Micha Hanselmann <micha.hanselmann@gmail.com>
Michael Cirone <mikecirone@gmail.com>
@ -995,6 +1009,7 @@ Milko Leporis <milko.leporis@imgtec.com>
Milton Chiang <milton.chiang@mediatek.com>
Milutin Smiljanic <msmiljanic.gm@gmail.com>
Minchul Kang <tegongkang@gmail.com>
Ming Lei <minggeorgelei@gmail.com>
Mingeun Park <mindal99546@gmail.com>
Minggang Wang <minggang.wang@intel.com>
Mingmin Xie <melvinxie@gmail.com>
@ -1452,6 +1467,7 @@ Tom Harwood <tfh@skip.org>
Tomas Popela <tomas.popela@gmail.com>
Tomasz Edward Posłuszny <tom@devpeer.net>
Tony Shen <legendmastertony@gmail.com>
Topi Lassila <tolassila@gmail.com>
Torsten Kurbad <google@tk-webart.de>
Toshihito Kikuchi <leamovret@gmail.com>
Toshiaki Tanaka <zokutyou2@gmail.com>
@ -1503,6 +1519,7 @@ Wojciech Bielawski <wojciech.bielawski@gmail.com>
Wang Chen <wangchen20@iscas.ac.cn>
Wang Chen <unicornxw@gmail.com>
Wang Weiwei <wangww@dingdao.com>
Wang Zirui <kingzirvi@gmail.com>
Wangyang Dai <jludwy@gmail.com>
Wanming Lin <wanming.lin@intel.com>
Wei Li <wei.c.li@intel.com>
@ -1611,6 +1628,7 @@ Zeqin Chen <talonchen@tencent.com>
Zhanbang He <hezhanbang@gmail.com>
Zhang Hao <zhanghao.m@bytedance.com>
Zhang Hao <15686357310a@gmail.com>
Zhao Qin <qzmiss@gmail.com>
Zhaoming Jiang <zhaoming.jiang@intel.com>
Zhaoze Zhou <zhaoze.zhou@partner.samsung.com>
Zheda Chen <zheda.chen@intel.com>
@ -1636,6 +1654,7 @@ Zsolt Borbely <zsborbely.u-szeged@partner.samsung.com>
迷渡 <justjavac@gmail.com>
郑苏波 (Super Zheng) <superzheng@tencent.com>
一丝 (Yisi) <yiorsi@gmail.com>
林训杰 (XunJie Lin) <wick.linxunjie@gmail.com>
# Please DO NOT APPEND here. See comments at the top of the file.
# END individuals section.
@ -1665,6 +1684,7 @@ EngFlow, Inc. <*@engflow.com>
Estimote, Inc. <*@estimote.com>
Google Inc. <*@google.com>
Grammarly, Inc. <*@grammarly.com>
Here Inc. <*@here.io>
Hewlett-Packard Development Company, L.P. <*@hp.com>
HyperConnect Inc. <*@hpcnt.com>
IBM Inc. <*@*.ibm.com>

View file

@ -12,7 +12,6 @@ import("//build/config/compiler/compiler.gni")
import("//build/config/cronet/config.gni")
import("//build/config/dcheck_always_on.gni")
import("//build/config/features.gni")
import("//build/config/ios/config.gni")
import("//build/config/rust.gni")
import("//build/config/sanitizers/sanitizers.gni")
import("//build/config/ui.gni")

1087
src/DEPS

File diff suppressed because it is too large Load diff

View file

@ -29,8 +29,6 @@ import("//build/config/chromeos/ui_mode.gni")
import("//build/config/compiler/compiler.gni")
import("//build/config/cronet/config.gni")
import("//build/config/dcheck_always_on.gni")
import("//build/config/features.gni")
import("//build/config/ios/config.gni")
import("//build/config/logging.gni")
import("//build/config/nacl/config.gni")
import("//build/config/profiling/profiling.gni")
@ -43,6 +41,9 @@ import("//build/util/process_version.gni")
import("//build_overrides/build.gni")
if (is_ios) {
# Used to access target_environment.
import("//build/config/apple/mobile_config.gni")
# Used to access ios_is_app_extension variable definition.
import("//build/config/ios/ios_sdk.gni")
}
@ -170,8 +171,6 @@ component("base") {
"allocator/dispatcher/internal/dispatch_data.h",
"allocator/dispatcher/internal/dispatcher_internal.h",
"allocator/dispatcher/internal/tools.h",
"allocator/dispatcher/memory_tagging.cc",
"allocator/dispatcher/memory_tagging.h",
"allocator/dispatcher/notification_data.h",
"allocator/dispatcher/reentry_guard.cc",
"allocator/dispatcher/reentry_guard.h",
@ -182,6 +181,7 @@ component("base") {
"at_exit.h",
"atomic_ref_count.h",
"atomic_sequence_num.h",
"atomicops.cc",
"atomicops.h",
"atomicops_internals_atomicword_compat.h",
"atomicops_internals_portable.h",
@ -213,6 +213,7 @@ component("base") {
"compiler_specific.h",
"component_export.h",
"containers/adapters.h",
"containers/adapters_internal.h",
"containers/buffer_iterator.h",
"containers/checked_iterators.h",
"containers/circular_deque.h",
@ -342,6 +343,7 @@ component("base") {
"macros/uniquify.h",
"memory/aligned_memory.cc",
"memory/aligned_memory.h",
"memory/asan_interface.h",
"memory/free_deleter.h",
"memory/memory_pressure_listener.cc",
"memory/memory_pressure_listener.h",
@ -367,7 +369,6 @@ component("base") {
"memory/raw_ptr_cast.h",
"memory/raw_ptr_exclusion.h",
"memory/raw_ref.h",
"memory/raw_scoped_refptr_mismatch_checker.h",
"memory/raw_span.h",
"memory/read_only_shared_memory_region.cc",
"memory/read_only_shared_memory_region.h",
@ -404,6 +405,8 @@ component("base") {
"memory/weak_ptr.h",
"memory/writable_shared_memory_region.cc",
"memory/writable_shared_memory_region.h",
"message_loop/io_watcher.cc",
"message_loop/io_watcher.h",
"message_loop/message_pump.cc",
"message_loop/message_pump.h",
"message_loop/message_pump_default.cc",
@ -457,6 +460,7 @@ component("base") {
"metrics/record_histogram_checker.h",
"metrics/sample_map.cc",
"metrics/sample_map.h",
"metrics/sample_map_iterator.h",
"metrics/sample_vector.cc",
"metrics/sample_vector.h",
"metrics/single_sample_metrics.cc",
@ -516,6 +520,7 @@ component("base") {
"process/process_info.h",
"process/set_process_title.cc",
"process/set_process_title.h",
"profiler/core_unwinders.h",
"profiler/frame.cc",
"profiler/frame.h",
"profiler/metadata_recorder.cc",
@ -526,6 +531,7 @@ component("base") {
"profiler/periodic_sampling_scheduler.h",
"profiler/profile_builder.h",
"profiler/register_context.h",
"profiler/register_context_registers.h",
"profiler/sample_metadata.cc",
"profiler/sample_metadata.h",
"profiler/sampling_profiler_thread_token.cc",
@ -544,15 +550,13 @@ component("base") {
"profiler/stack_unwind_data.h",
"profiler/suspendable_thread_delegate.h",
"profiler/thread_delegate.h",
"profiler/thread_group_profiler.cc",
"profiler/thread_group_profiler.h",
"profiler/thread_group_profiler_client.h",
"profiler/unwinder.cc",
"profiler/unwinder.h",
"rand_util.cc",
"rand_util.h",
"ranges/algorithm.h",
"ranges/from_range.h",
"ranges/functional.h",
"ranges/ranges.h",
"run_loop.cc",
"run_loop.h",
"sampling_heap_profiler/lock_free_address_hash_set.cc",
@ -591,12 +595,14 @@ component("base") {
"strings/pattern.h",
"strings/safe_sprintf.cc",
"strings/safe_sprintf.h",
"strings/span_printf.h",
"strings/strcat.cc",
"strings/strcat.h",
"strings/strcat_internal.h",
"strings/string_number_conversions.cc",
"strings/string_number_conversions.h",
"strings/string_number_conversions_internal.h",
"strings/string_slice.h",
"strings/string_split.cc",
"strings/string_split.h",
"strings/string_split_internal.h",
@ -627,6 +633,8 @@ component("base") {
"supports_user_data.h",
"synchronization/atomic_flag.cc",
"synchronization/atomic_flag.h",
"synchronization/cancelable_event.cc",
"synchronization/cancelable_event.h",
"synchronization/condition_variable.h",
"synchronization/lock.cc",
"synchronization/lock.h",
@ -682,7 +690,6 @@ component("base") {
"task/sequence_manager/enqueue_order_generator.h",
"task/sequence_manager/fence.cc",
"task/sequence_manager/fence.h",
"task/sequence_manager/lazily_deallocated_deque.h",
"task/sequence_manager/sequence_manager.cc",
"task/sequence_manager/sequence_manager.h",
"task/sequence_manager/sequence_manager_impl.cc",
@ -870,6 +877,7 @@ component("base") {
"traits_bag.h",
"tuple.h",
"types/always_false.h",
"types/cxx23_from_range.h",
"types/cxx23_is_scoped_enum.h",
"types/cxx23_to_underlying.h",
"types/expected.h",
@ -883,11 +891,13 @@ component("base") {
"types/optional_ref.h",
"types/optional_util.h",
"types/pass_key.h",
"types/same_as_any.h",
"types/strong_alias.h",
"types/supports_ostream_operator.h",
"types/to_address.h",
"types/token_type.h",
"types/variant_util.h",
"types/zip.h",
"unguessable_token.cc",
"unguessable_token.h",
"uuid.cc",
@ -1024,8 +1034,8 @@ component("base") {
# to provide the appropriate `#define` here.
defines += [ "IS_RAW_PTR_IMPL" ]
# native_unwinder_android is intended for use solely via a dynamic feature
# module, to avoid increasing Chrome's executable size.
# native_unwinder_android is split into a separate target to avoid pulling
# libunwindstack dependencies into cronet's base.
assert_no_deps = [ ":native_unwinder_android" ]
public_deps = [
@ -1100,7 +1110,8 @@ component("base") {
"android/scoped_hardware_buffer_fence_sync.h",
"android/scoped_hardware_buffer_handle.cc",
"android/scoped_hardware_buffer_handle.h",
"android/sys_utils.h",
"android/scoped_input_event.cc",
"android/scoped_input_event.h",
"debug/stack_trace_android.cc",
"files/file_util_android.cc",
"files/scoped_file_android.cc",
@ -1140,18 +1151,12 @@ component("base") {
# well when doing a component build.
public_configs = [ ":android_system_libs" ]
if (can_unwind_with_cfi_table) {
sources += [
"trace_event/cfi_backtrace_android.cc",
"trace_event/cfi_backtrace_android.h",
]
}
if (current_cpu == "arm") {
sources += [
"profiler/chrome_unwind_info_android.cc",
"profiler/chrome_unwind_info_android.h",
"profiler/chrome_unwinder_android.cc",
"profiler/chrome_unwinder_android.h",
"profiler/chrome_unwind_info_android_32.cc",
"profiler/chrome_unwind_info_android_32.h",
"profiler/chrome_unwinder_android_32.cc",
"profiler/chrome_unwinder_android_32.h",
]
}
@ -1194,6 +1199,8 @@ component("base") {
"android/jni_array.h",
"android/jni_bytebuffer.cc",
"android/jni_bytebuffer.h",
"android/jni_callback.cc",
"android/jni_callback.h",
"android/jni_registrar.cc",
"android/jni_registrar.h",
"android/jni_string.cc",
@ -1425,6 +1432,7 @@ component("base") {
"debug/crash_logging.h",
"debug/stack_trace.cc",
"debug/stack_trace.h",
"files/drive_info.cc",
"files/drive_info.h",
"files/file_enumerator.cc",
"files/file_enumerator.h",
@ -1552,6 +1560,13 @@ component("base") {
if (is_posix && !is_ios) {
sources += [ "process/process_posix.cc" ]
}
if (!is_win && !is_chromeos && !is_android && !is_linux) {
sources += [ "synchronization/cancelable_event_default.cc" ]
}
if (is_linux || is_chromeos || is_android) {
sources += [ "synchronization/cancelable_event_posix.cc" ]
}
if (use_blink) {
sources += [
@ -1586,8 +1601,12 @@ component("base") {
]
}
if (use_partition_alloc) {
# Add stuff that doesn't work in NaCl.
# Add stuff that doesn't work in NaCl or other environments that disable
# partition_alloc.
sources += [
"allocator/dispatcher/memory_tagging.cc",
"allocator/dispatcher/memory_tagging.h",
# PartitionAlloc uses SpinLock, which doesn't work in NaCl (see below).
"allocator/miracle_parameter.cc",
"allocator/miracle_parameter.h",
@ -1597,15 +1616,9 @@ component("base") {
"allocator/partition_alloc_support.h",
]
}
# Need this to pass gn check, because gn check doesn't see
# BUILDFLAG(USE_PARTITION_ALLOC). A linker will remove all
# partition_alloc code if use_partition_alloc = false because no code uses
# partition_alloc.
public_deps += [
"allocator/partition_allocator:partition_alloc",
"allocator/partition_allocator:raw_ptr",
]
if (use_allocator_shim) {
public_deps += [ "allocator/partition_allocator:allocator_shim" ]
}
}
# Windows.
@ -1652,6 +1665,7 @@ component("base") {
"process/process_iterator_win.cc",
"process/process_metrics_win.cc",
"process/process_win.cc",
"profiler/core_unwinders_win.cc",
"profiler/module_cache_win.cc",
"profiler/native_unwinder_win.cc",
"profiler/native_unwinder_win.h",
@ -1672,6 +1686,7 @@ component("base") {
"strings/string_util_win.h",
"strings/sys_string_conversions_win.cc",
"sync_socket_win.cc",
"synchronization/cancelable_event_win.cc",
"synchronization/condition_variable_win.cc",
"synchronization/lock_impl_win.cc",
"synchronization/waitable_event_watcher_win.cc",
@ -1714,6 +1729,8 @@ component("base") {
"win/event_trace_controller.h",
"win/event_trace_provider.cc",
"win/event_trace_provider.h",
"win/hardware_check.cc",
"win/hardware_check.h",
"win/hstring_reference.cc",
"win/hstring_reference.h",
"win/i18n.cc",
@ -1725,10 +1742,12 @@ component("base") {
"win/message_window.h",
"win/nt_status.cc",
"win/nt_status.h",
"win/ntsecapi_shim.h",
"win/object_watcher.cc",
"win/object_watcher.h",
"win/patch_util.cc",
"win/patch_util.h",
"win/pdh_shim.h",
"win/pe_image_reader.cc",
"win/pe_image_reader.h",
"win/post_async_results.h",
@ -1747,6 +1766,7 @@ component("base") {
"win/scoped_co_mem.h",
"win/scoped_com_initializer.cc",
"win/scoped_com_initializer.h",
"win/scoped_gdi_object.cc",
"win/scoped_gdi_object.h",
"win/scoped_handle.cc",
"win/scoped_handle.h",
@ -1786,10 +1806,13 @@ component("base") {
"win/variant_vector.h",
"win/vector.cc",
"win/vector.h",
"win/wbemidl_shim.h",
"win/win_handle_types.h",
"win/win_handle_types_list.inc",
"win/win_util.cc",
"win/win_util.h",
"win/winbase_shim.h",
"win/wincred_shim.h",
"win/wincrypt_shim.h",
"win/window_enumerator.cc",
"win/window_enumerator.h",
@ -1803,6 +1826,7 @@ component("base") {
"win/winrt_foundation_helpers.h",
"win/winrt_storage_util.cc",
"win/winrt_storage_util.h",
"win/wintrust_shim.h",
"win/wmi.cc",
"win/wmi.h",
"win/wrapped_window_proc.cc",
@ -1966,10 +1990,11 @@ component("base") {
"process/port_provider_mac.cc",
"process/port_provider_mac.h",
"process/process_handle_mac.cc",
"process/process_info_mac.cc",
"process/process_info_mac.mm",
"process/process_iterator_mac.cc",
"process/process_mac.cc",
"process/process_metrics_mac.cc",
"profiler/core_unwinders_mac.cc",
"profiler/frame_pointer_unwinder.cc",
"profiler/frame_pointer_unwinder.h",
"profiler/stack_sampler_mac.cc",
@ -2012,6 +2037,7 @@ component("base") {
"power_monitor/power_monitor_device_source_ios.mm",
"process/process_metrics_ios.cc",
"process/process_metrics_posix.cc",
"profiler/core_unwinders_ios.cc",
"profiler/stack_sampler_ios.cc",
"system/sys_info_ios.mm",
]
@ -2196,7 +2222,10 @@ component("base") {
}
if ((is_posix && !is_apple && !is_android) || is_fuchsia) {
sources += [ "profiler/stack_sampler_posix.cc" ]
sources += [
"profiler/core_unwinders_posix.cc",
"profiler/stack_sampler_posix.cc",
]
}
if ((is_posix && !is_apple && !is_android && !is_chromeos) || is_fuchsia) {
@ -2221,8 +2250,6 @@ component("base") {
"trace_event/auto_open_close_event.h",
"trace_event/builtin_categories.cc",
"trace_event/builtin_categories.h",
"trace_event/category_registry.cc",
"trace_event/category_registry.h",
"trace_event/heap_profiler.h",
"trace_event/interned_args_helper.cc",
"trace_event/interned_args_helper.h",
@ -2249,13 +2276,14 @@ component("base") {
"trace_event/memory_usage_estimator.cc",
"trace_event/memory_usage_estimator.h",
"trace_event/optional_trace_event.h",
"trace_event/perfetto_proto_appender.cc",
"trace_event/perfetto_proto_appender.h",
"trace_event/process_memory_dump.cc",
"trace_event/process_memory_dump.h",
"trace_event/trace_arguments.cc",
"trace_event/trace_arguments.h",
"trace_event/trace_buffer.cc",
"trace_event/trace_buffer.h",
"trace_event/trace_category.h",
"trace_event/trace_config.cc",
"trace_event/trace_config.h",
"trace_event/trace_config_category_filter.cc",
@ -2263,11 +2291,8 @@ component("base") {
"trace_event/trace_event.h",
"trace_event/trace_event_impl.cc",
"trace_event/trace_event_impl.h",
"trace_event/trace_event_memory_overhead.cc",
"trace_event/trace_event_memory_overhead.h",
"trace_event/trace_log.cc",
"trace_event/trace_log.h",
"trace_event/trace_log_constants.cc",
"trace_event/traced_value.cc",
"trace_event/traced_value.h",
"trace_event/traced_value_support.h",
@ -2275,8 +2300,6 @@ component("base") {
"trace_event/tracing_agent.h",
"trace_event/typed_macros.h",
"trace_event/typed_macros_embedder_support.h",
"trace_event/typed_macros_internal.cc",
"trace_event/typed_macros_internal.h",
"tracing/perfetto_platform.cc",
"tracing/perfetto_platform.h",
"tracing/perfetto_task_runner.cc",
@ -2303,8 +2326,6 @@ component("base") {
sources += [
"trace_event/etw_interceptor_win.cc",
"trace_event/etw_interceptor_win.h",
"trace_event/trace_event_etw_export_win.cc",
"trace_event/trace_event_etw_export_win.h",
"trace_event/trace_logging_minimal_win.cc",
"trace_event/trace_logging_minimal_win.h",
]

View file

@ -3,6 +3,7 @@ include_rules = [
"+third_party/apple_apsl",
"+third_party/boringssl/src/include",
"+third_party/ced",
"+third_party/fuzztest",
# We are moving the old jni_generator to jni_zero, some references will remain
# in //base.
"+third_party/jni_zero",

View file

@ -21,4 +21,4 @@ constexpr size_t kMaximumNumberOfObservers = 4;
} // namespace base::allocator::dispatcher::configuration
#endif // BASE_ALLOCATOR_DISPATCHER_CONFIGURATION_H_
#endif // BASE_ALLOCATOR_DISPATCHER_CONFIGURATION_H_

View file

@ -16,7 +16,7 @@
#endif
#if PA_BUILDFLAG(USE_PARTITION_ALLOC)
#include "partition_alloc/partition_alloc_hooks.h"
#include "partition_alloc/partition_alloc_hooks.h" // nogncheck
#endif
namespace base::allocator::dispatcher {

View file

@ -5,11 +5,11 @@
#ifndef BASE_ALLOCATOR_DISPATCHER_DISPATCHER_H_
#define BASE_ALLOCATOR_DISPATCHER_DISPATCHER_H_
#include <memory>
#include "base/allocator/dispatcher/internal/dispatcher_internal.h"
#include "base/base_export.h"
#include <memory>
namespace base::allocator::dispatcher {
namespace internal {

View file

@ -5,13 +5,13 @@
#ifndef BASE_ALLOCATOR_DISPATCHER_INITIALIZER_H_
#define BASE_ALLOCATOR_DISPATCHER_INITIALIZER_H_
#include <tuple>
#include <utility>
#include "base/allocator/dispatcher/configuration.h"
#include "base/allocator/dispatcher/dispatcher.h"
#include "base/allocator/dispatcher/internal/tools.h"
#include <tuple>
#include <utility>
namespace base::allocator::dispatcher {
namespace internal {

View file

@ -10,11 +10,11 @@
#include "partition_alloc/buildflags.h"
#if PA_BUILDFLAG(USE_PARTITION_ALLOC)
#include "partition_alloc/partition_alloc_hooks.h"
#include "partition_alloc/partition_alloc_hooks.h" // nogncheck
#endif
#if PA_BUILDFLAG(USE_ALLOCATOR_SHIM)
#include "partition_alloc/shim/allocator_shim.h"
#include "partition_alloc/shim/allocator_shim.h" // nogncheck
#endif
namespace base::allocator::dispatcher::internal {

View file

@ -16,7 +16,7 @@
#include "partition_alloc/buildflags.h"
#if PA_BUILDFLAG(USE_PARTITION_ALLOC)
#include "partition_alloc/partition_alloc_allocation_data.h"
#include "partition_alloc/partition_alloc_allocation_data.h" // nogncheck
#endif
#if PA_BUILDFLAG(USE_ALLOCATOR_SHIM)

View file

@ -24,4 +24,4 @@ enum class AllocationSubsystem {
};
} // namespace base::allocator::dispatcher
#endif // BASE_ALLOCATOR_DISPATCHER_SUBSYSTEM_H_
#endif // BASE_ALLOCATOR_DISPATCHER_SUBSYSTEM_H_

View file

@ -24,4 +24,4 @@ struct DispatcherTest : public ::testing::Test {
} // namespace base::allocator::dispatcher::testing
#endif // BASE_ALLOCATOR_DISPATCHER_TESTING_DISPATCHER_TEST_H_
#endif // BASE_ALLOCATOR_DISPATCHER_TESTING_DISPATCHER_TEST_H_

View file

@ -30,4 +30,4 @@ struct ObserverMock {
} // namespace testing
} // namespace base::allocator::dispatcher
#endif // BASE_ALLOCATOR_DISPATCHER_TESTING_OBSERVER_MOCK_H_
#endif // BASE_ALLOCATOR_DISPATCHER_TESTING_OBSERVER_MOCK_H_

View file

@ -8,14 +8,14 @@
#if USE_LOCAL_TLS_EMULATION()
#include <sys/mman.h>
#include "base/check.h"
#include "base/dcheck_is_on.h"
#include "base/debug/crash_logging.h"
#include "base/immediate_crash.h"
#include "build/build_config.h"
#include <sys/mman.h>
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX)
#include <sys/prctl.h>
#endif

View file

@ -17,17 +17,21 @@
#endif
#if USE_LOCAL_TLS_EMULATION()
#include <pthread.h>
#include <algorithm>
#include <atomic>
#include <functional>
#include <memory>
#include <mutex>
#include "base/base_export.h"
#include "base/check.h"
#include "base/compiler_specific.h"
#include "partition_alloc/partition_alloc_constants.h"
#include <pthread.h>
#if PA_BUILDFLAG(USE_PARTITION_ALLOC)
#include "partition_alloc/partition_alloc_constants.h" // nogncheck
#endif
#if HAS_FEATURE(thread_sanitizer)
#define DISABLE_TSAN_INSTRUMENTATION __attribute__((no_sanitize("thread")))

View file

@ -166,7 +166,7 @@ Enum GetMiracleParameterAsEnum(
default_value, type, options) \
type function_name() { \
static const type value = miracle_parameter::GetMiracleParameterAsEnum( \
feature, param_name, default_value, base::make_span(options)); \
feature, param_name, default_value, base::span(options)); \
return value; \
}

View file

@ -20,8 +20,7 @@
#include "partition_alloc/shim/allocator_shim_dispatch_to_noop_on_free.h"
#include "partition_alloc/thread_cache.h"
namespace base {
namespace features {
namespace base::features {
namespace {
@ -48,7 +47,8 @@ constexpr FeatureParam<UnretainedDanglingPtrMode>::Option
{UnretainedDanglingPtrMode::kDumpWithoutCrashing,
"dump_without_crashing"},
};
const base::FeatureParam<UnretainedDanglingPtrMode>
// Note: Do not use the prepared macro as of no need for a local cache.
constinit const FeatureParam<UnretainedDanglingPtrMode>
kUnretainedDanglingPtrModeParam = {
&kPartitionAllocUnretainedDanglingPtr,
"mode",
@ -73,7 +73,8 @@ constexpr FeatureParam<DanglingPtrMode>::Option kDanglingPtrModeOption[] = {
{DanglingPtrMode::kCrash, "crash"},
{DanglingPtrMode::kLogOnly, "log_only"},
};
const base::FeatureParam<DanglingPtrMode> kDanglingPtrModeParam{
// Note: Do not use the prepared macro as of no need for a local cache.
constinit const FeatureParam<DanglingPtrMode> kDanglingPtrModeParam{
&kPartitionAllocDanglingPtr,
"mode",
DanglingPtrMode::kCrash,
@ -83,7 +84,8 @@ constexpr FeatureParam<DanglingPtrType>::Option kDanglingPtrTypeOption[] = {
{DanglingPtrType::kAll, "all"},
{DanglingPtrType::kCrossTask, "cross_task"},
};
const base::FeatureParam<DanglingPtrType> kDanglingPtrTypeParam{
// Note: Do not use the prepared macro as of no need for a local cache.
constinit const FeatureParam<DanglingPtrType> kDanglingPtrTypeParam{
&kPartitionAllocDanglingPtr,
"type",
DanglingPtrType::kAll,
@ -109,7 +111,7 @@ MIRACLE_PARAMETER_FOR_INT(
BASE_FEATURE(kPartitionAllocLargeEmptySlotSpanRing,
"PartitionAllocLargeEmptySlotSpanRing",
#if BUILDFLAG(IS_MAC)
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
FEATURE_ENABLED_BY_DEFAULT);
#else
FEATURE_DISABLED_BY_DEFAULT);
@ -128,7 +130,8 @@ constexpr FeatureParam<PartitionAllocWithAdvancedChecksEnabledProcesses>::Option
kNonRendererStr},
{PartitionAllocWithAdvancedChecksEnabledProcesses::kAllProcesses,
kAllProcessesStr}};
const base::FeatureParam<PartitionAllocWithAdvancedChecksEnabledProcesses>
// Note: Do not use the prepared macro as of no need for a local cache.
constinit const FeatureParam<PartitionAllocWithAdvancedChecksEnabledProcesses>
kPartitionAllocWithAdvancedChecksEnabledProcessesParam{
&kPartitionAllocWithAdvancedChecks, kPAFeatureEnabledProcessesStr,
PartitionAllocWithAdvancedChecksEnabledProcesses::kBrowserOnly,
@ -138,10 +141,17 @@ BASE_FEATURE(kPartitionAllocSchedulerLoopQuarantine,
"PartitionAllocSchedulerLoopQuarantine",
FEATURE_DISABLED_BY_DEFAULT);
// Scheduler Loop Quarantine's per-branch capacity in bytes.
const base::FeatureParam<int>
// Note: Do not use the prepared macro as of no need for a local cache.
constinit const FeatureParam<int>
kPartitionAllocSchedulerLoopQuarantineBranchCapacity{
&kPartitionAllocSchedulerLoopQuarantine,
"PartitionAllocSchedulerLoopQuarantineBranchCapacity", 0};
// Scheduler Loop Quarantine's capacity for the UI thread in bytes.
BASE_FEATURE_PARAM(int,
kPartitionAllocSchedulerLoopQuarantineBrowserUICapacity,
&kPartitionAllocSchedulerLoopQuarantine,
"PartitionAllocSchedulerLoopQuarantineBrowserUICapacity",
0);
BASE_FEATURE(kPartitionAllocZappingByFreeFlags,
"PartitionAllocZappingByFreeFlags",
@ -150,6 +160,10 @@ BASE_FEATURE(kPartitionAllocZappingByFreeFlags,
BASE_FEATURE(kPartitionAllocEventuallyZeroFreedMemory,
"PartitionAllocEventuallyZeroFreedMemory",
FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kPartitionAllocFewerMemoryRegions,
"PartitionAllocFewerMemoryRegions",
FEATURE_DISABLED_BY_DEFAULT);
#endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
BASE_FEATURE(kPartitionAllocBackupRefPtr,
@ -169,24 +183,31 @@ constexpr FeatureParam<BackupRefPtrEnabledProcesses>::Option
{BackupRefPtrEnabledProcesses::kNonRenderer, kNonRendererStr},
{BackupRefPtrEnabledProcesses::kAllProcesses, kAllProcessesStr}};
const base::FeatureParam<BackupRefPtrEnabledProcesses>
kBackupRefPtrEnabledProcessesParam{
&kPartitionAllocBackupRefPtr, kPAFeatureEnabledProcessesStr,
BASE_FEATURE_ENUM_PARAM(BackupRefPtrEnabledProcesses,
kBackupRefPtrEnabledProcessesParam,
&kPartitionAllocBackupRefPtr,
kPAFeatureEnabledProcessesStr,
#if PA_BUILDFLAG(IS_MAC) && PA_BUILDFLAG(PA_ARCH_CPU_ARM64)
BackupRefPtrEnabledProcesses::kNonRenderer,
BackupRefPtrEnabledProcesses::kNonRenderer,
#else
BackupRefPtrEnabledProcesses::kAllProcesses,
BackupRefPtrEnabledProcesses::kAllProcesses,
#endif
&kBackupRefPtrEnabledProcessesOptions};
&kBackupRefPtrEnabledProcessesOptions);
constexpr FeatureParam<BackupRefPtrMode>::Option kBackupRefPtrModeOptions[] = {
{BackupRefPtrMode::kDisabled, "disabled"},
{BackupRefPtrMode::kEnabled, "enabled"},
};
const base::FeatureParam<BackupRefPtrMode> kBackupRefPtrModeParam{
&kPartitionAllocBackupRefPtr, "brp-mode", BackupRefPtrMode::kEnabled,
&kBackupRefPtrModeOptions};
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<int> kBackupRefPtrExtraExtrasSizeParam{
&kPartitionAllocBackupRefPtr, "brp-extra-extras-size", 0};
BASE_FEATURE(kPartitionAllocMemoryTagging,
"PartitionAllocMemoryTagging",
@ -201,7 +222,8 @@ constexpr FeatureParam<MemtagMode>::Option kMemtagModeOptions[] = {
{MemtagMode::kSync, "sync"},
{MemtagMode::kAsync, "async"}};
const base::FeatureParam<MemtagMode> kMemtagModeParam{
// Note: Do not use the prepared macro as of no need for a local cache.
constinit const FeatureParam<MemtagMode> kMemtagModeParam{
&kPartitionAllocMemoryTagging, "memtag-mode",
#if PA_BUILDFLAG(USE_FULL_MTE)
MemtagMode::kSync,
@ -215,7 +237,8 @@ constexpr FeatureParam<RetagMode>::Option kRetagModeOptions[] = {
{RetagMode::kRandom, "random"},
};
const base::FeatureParam<RetagMode> kRetagModeParam{
// Note: Do not use the prepared macro as of no need for a local cache.
constinit const FeatureParam<RetagMode> kRetagModeParam{
&kPartitionAllocMemoryTagging, "retag-mode", RetagMode::kIncrement,
&kRetagModeOptions};
@ -225,7 +248,8 @@ constexpr FeatureParam<MemoryTaggingEnabledProcesses>::Option
{MemoryTaggingEnabledProcesses::kNonRenderer, kNonRendererStr},
{MemoryTaggingEnabledProcesses::kAllProcesses, kAllProcessesStr}};
const base::FeatureParam<MemoryTaggingEnabledProcesses>
// Note: Do not use the prepared macro as of no need for a local cache.
constinit const FeatureParam<MemoryTaggingEnabledProcesses>
kMemoryTaggingEnabledProcessesParam{
&kPartitionAllocMemoryTagging, kPAFeatureEnabledProcessesStr,
#if PA_BUILDFLAG(USE_FULL_MTE)
@ -250,13 +274,16 @@ BASE_FEATURE(kPartitionAllocPermissiveMte,
#endif
);
const base::FeatureParam<bool> kBackupRefPtrAsanEnableDereferenceCheckParam{
// Note: Do not use the prepared macro to implement following FeatureParams
// as of no need for a local cache.
constinit const FeatureParam<bool> kBackupRefPtrAsanEnableDereferenceCheckParam{
&kPartitionAllocBackupRefPtr, "asan-enable-dereference-check", true};
const base::FeatureParam<bool> kBackupRefPtrAsanEnableExtractionCheckParam{
constinit const FeatureParam<bool> kBackupRefPtrAsanEnableExtractionCheckParam{
&kPartitionAllocBackupRefPtr, "asan-enable-extraction-check",
false}; // Not much noise at the moment to enable by default.
const base::FeatureParam<bool> kBackupRefPtrAsanEnableInstantiationCheckParam{
&kPartitionAllocBackupRefPtr, "asan-enable-instantiation-check", true};
constinit const FeatureParam<bool>
kBackupRefPtrAsanEnableInstantiationCheckParam{
&kPartitionAllocBackupRefPtr, "asan-enable-instantiation-check", true};
// If enabled, switches the bucket distribution to a denser one.
//
@ -270,29 +297,31 @@ BASE_FEATURE(kPartitionAllocUseDenserDistribution,
FEATURE_ENABLED_BY_DEFAULT
#endif // BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_32_BITS)
);
const base::FeatureParam<BucketDistributionMode>::Option
const FeatureParam<BucketDistributionMode>::Option
kPartitionAllocBucketDistributionOption[] = {
{BucketDistributionMode::kDefault, "default"},
{BucketDistributionMode::kDenser, "denser"},
};
const base::FeatureParam<BucketDistributionMode>
kPartitionAllocBucketDistributionParam {
&kPartitionAllocUseDenserDistribution, "mode",
// Note: Do not use the prepared macro as of no need for a local cache.
constinit const FeatureParam<BucketDistributionMode>
kPartitionAllocBucketDistributionParam{
&kPartitionAllocUseDenserDistribution, "mode",
#if BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_32_BITS)
BucketDistributionMode::kDefault,
BucketDistributionMode::kDefault,
#else
BucketDistributionMode::kDenser,
BucketDistributionMode::kDenser,
#endif // BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_32_BITS)
&kPartitionAllocBucketDistributionOption
};
&kPartitionAllocBucketDistributionOption};
BASE_FEATURE(kPartitionAllocMemoryReclaimer,
"PartitionAllocMemoryReclaimer",
FEATURE_ENABLED_BY_DEFAULT);
const base::FeatureParam<TimeDelta> kPartitionAllocMemoryReclaimerInterval = {
&kPartitionAllocMemoryReclaimer, "interval",
TimeDelta(), // Defaults to zero.
};
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.
@ -305,16 +334,17 @@ BASE_FEATURE(kLowerPAMemoryLimitForNonMainRenderers,
BASE_FEATURE(kPartitionAllocStraightenLargerSlotSpanFreeLists,
"PartitionAllocStraightenLargerSlotSpanFreeLists",
FEATURE_ENABLED_BY_DEFAULT);
const base::FeatureParam<
partition_alloc::StraightenLargerSlotSpanFreeListsMode>::Option
kPartitionAllocStraightenLargerSlotSpanFreeListsModeOption[] = {
const FeatureParam<partition_alloc::StraightenLargerSlotSpanFreeListsMode>::
Option kPartitionAllocStraightenLargerSlotSpanFreeListsModeOption[] = {
{partition_alloc::StraightenLargerSlotSpanFreeListsMode::
kOnlyWhenUnprovisioning,
"only-when-unprovisioning"},
{partition_alloc::StraightenLargerSlotSpanFreeListsMode::kAlways,
"always"},
};
const base::FeatureParam<partition_alloc::StraightenLargerSlotSpanFreeListsMode>
// Note: Do not use the prepared macro as of no need for a local cache.
constinit const FeatureParam<
partition_alloc::StraightenLargerSlotSpanFreeListsMode>
kPartitionAllocStraightenLargerSlotSpanFreeListsMode = {
&kPartitionAllocStraightenLargerSlotSpanFreeLists,
"mode",
@ -347,9 +377,11 @@ BASE_FEATURE(kPageAllocatorRetryOnCommitFailure,
// The feature: kPartialLowEndModeOnMidRangeDevices is defined in
// //base/features.cc. Since the following feature param is related to
// PartitionAlloc, define the param here.
const FeatureParam<bool> kPartialLowEndModeExcludePartitionAllocSupport{
&kPartialLowEndModeOnMidRangeDevices, "exclude-partition-alloc-support",
false};
BASE_FEATURE_PARAM(bool,
kPartialLowEndModeExcludePartitionAllocSupport,
&kPartialLowEndModeOnMidRangeDevices,
"exclude-partition-alloc-support",
false);
#endif
BASE_FEATURE(kEnableConfigurableThreadCacheMultiplier,
@ -367,19 +399,19 @@ MIRACLE_PARAMETER_FOR_DOUBLE(GetThreadCacheMultiplierForAndroid,
1.)
constexpr partition_alloc::internal::base::TimeDelta ToPartitionAllocTimeDelta(
base::TimeDelta time_delta) {
TimeDelta time_delta) {
return partition_alloc::internal::base::Microseconds(
time_delta.InMicroseconds());
}
constexpr base::TimeDelta FromPartitionAllocTimeDelta(
constexpr TimeDelta FromPartitionAllocTimeDelta(
partition_alloc::internal::base::TimeDelta time_delta) {
return base::Microseconds(time_delta.InMicroseconds());
return Microseconds(time_delta.InMicroseconds());
}
BASE_FEATURE(kEnableConfigurableThreadCachePurgeInterval,
"EnableConfigurableThreadCachePurgeInterval",
base::FEATURE_DISABLED_BY_DEFAULT);
FEATURE_DISABLED_BY_DEFAULT);
MIRACLE_PARAMETER_FOR_TIME_DELTA(
GetThreadCacheMinPurgeIntervalValue,
@ -416,7 +448,7 @@ GetThreadCacheDefaultPurgeInterval() {
BASE_FEATURE(kEnableConfigurableThreadCacheMinCachedMemoryForPurging,
"EnableConfigurableThreadCacheMinCachedMemoryForPurging",
base::FEATURE_DISABLED_BY_DEFAULT);
FEATURE_DISABLED_BY_DEFAULT);
MIRACLE_PARAMETER_FOR_INT(
GetThreadCacheMinCachedMemoryForPurgingBytes,
@ -439,12 +471,12 @@ BASE_FEATURE(kPartitionAllocDisableBRPInBufferPartition,
#if PA_BUILDFLAG(USE_FREELIST_DISPATCHER)
BASE_FEATURE(kUsePoolOffsetFreelists,
"PartitionAllocUsePoolOffsetFreelists",
base::FEATURE_DISABLED_BY_DEFAULT);
FEATURE_ENABLED_BY_DEFAULT);
#endif
BASE_FEATURE(kPartitionAllocAdjustSizeWhenInForeground,
"PartitionAllocAdjustSizeWhenInForeground",
#if BUILDFLAG(IS_MAC)
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
FEATURE_ENABLED_BY_DEFAULT);
#else
FEATURE_DISABLED_BY_DEFAULT);
@ -452,12 +484,12 @@ BASE_FEATURE(kPartitionAllocAdjustSizeWhenInForeground,
BASE_FEATURE(kPartitionAllocUseSmallSingleSlotSpans,
"PartitionAllocUseSmallSingleSlotSpans",
base::FEATURE_DISABLED_BY_DEFAULT);
FEATURE_ENABLED_BY_DEFAULT);
#if PA_CONFIG(ENABLE_SHADOW_METADATA)
BASE_FEATURE(kPartitionAllocShadowMetadata,
"PartitionAllocShadowMetadata",
base::FEATURE_DISABLED_BY_DEFAULT);
FEATURE_DISABLED_BY_DEFAULT);
constexpr FeatureParam<ShadowMetadataEnabledProcesses>::Option
kShadowMetadataEnabledProcessesOptions[] = {
@ -465,12 +497,12 @@ constexpr FeatureParam<ShadowMetadataEnabledProcesses>::Option
{ShadowMetadataEnabledProcesses::kAllChildProcesses,
kAllChildProcessesStr}};
const base::FeatureParam<ShadowMetadataEnabledProcesses>
// Note: Do not use the prepared macro as of no need for a local cache.
constinit const FeatureParam<ShadowMetadataEnabledProcesses>
kShadowMetadataEnabledProcessesParam{
&kPartitionAllocShadowMetadata, kPAFeatureEnabledProcessesStr,
ShadowMetadataEnabledProcesses::kRendererOnly,
&kShadowMetadataEnabledProcessesOptions};
#endif // PA_CONFIG(ENABLE_SHADOW_METADATA)
} // namespace features
} // namespace base
} // namespace base::features

View file

@ -15,8 +15,7 @@
#include "partition_alloc/partition_alloc_base/time/time.h"
#include "partition_alloc/partition_root.h"
namespace base {
namespace features {
namespace base::features {
namespace internal {
@ -37,13 +36,13 @@ enum class PAFeatureEnabledProcesses {
} // namespace internal
extern const BASE_EXPORT Feature kPartitionAllocUnretainedDanglingPtr;
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocUnretainedDanglingPtr);
enum class UnretainedDanglingPtrMode {
kCrash,
kDumpWithoutCrashing,
};
extern const BASE_EXPORT base::FeatureParam<UnretainedDanglingPtrMode>
kUnretainedDanglingPtrModeParam;
BASE_EXPORT BASE_DECLARE_FEATURE_PARAM(UnretainedDanglingPtrMode,
kUnretainedDanglingPtrModeParam);
// See /docs/dangling_ptr.md
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocDanglingPtr);
@ -62,8 +61,7 @@ enum class DanglingPtrMode {
// Note: This will be extended with a single shot DumpWithoutCrashing.
};
extern const BASE_EXPORT base::FeatureParam<DanglingPtrMode>
kDanglingPtrModeParam;
BASE_EXPORT BASE_DECLARE_FEATURE_PARAM(DanglingPtrMode, kDanglingPtrModeParam);
enum class DanglingPtrType {
// Act on any dangling raw_ptr released after being freed.
kAll, // (default)
@ -74,8 +72,7 @@ enum class DanglingPtrType {
// Note: This will be extended with LongLived
};
extern const BASE_EXPORT base::FeatureParam<DanglingPtrType>
kDanglingPtrTypeParam;
BASE_EXPORT BASE_DECLARE_FEATURE_PARAM(DanglingPtrType, kDanglingPtrTypeParam);
using PartitionAllocWithAdvancedChecksEnabledProcesses =
internal::PAFeatureEnabledProcesses;
@ -88,13 +85,19 @@ BASE_EXPORT int GetPartitionAllocLargeThreadCacheSizeValueForLowRAMAndroid();
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocLargeEmptySlotSpanRing);
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocWithAdvancedChecks);
extern const BASE_EXPORT
base::FeatureParam<PartitionAllocWithAdvancedChecksEnabledProcesses>
kPartitionAllocWithAdvancedChecksEnabledProcessesParam;
BASE_EXPORT BASE_DECLARE_FEATURE_PARAM(
PartitionAllocWithAdvancedChecksEnabledProcesses,
kPartitionAllocWithAdvancedChecksEnabledProcessesParam);
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocSchedulerLoopQuarantine);
// Scheduler Loop Quarantine's per-thread capacity in bytes.
extern const BASE_EXPORT base::FeatureParam<int>
kPartitionAllocSchedulerLoopQuarantineBranchCapacity;
BASE_EXPORT BASE_DECLARE_FEATURE_PARAM(
int,
kPartitionAllocSchedulerLoopQuarantineBranchCapacity);
// Scheduler Loop Quarantine's capacity for the UI thread in bytes.
// TODO(https://crbug.com/387470567): Support more thread types.
BASE_EXPORT BASE_DECLARE_FEATURE_PARAM(
int,
kPartitionAllocSchedulerLoopQuarantineBrowserUICapacity);
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocZappingByFreeFlags);
@ -102,6 +105,11 @@ BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocZappingByFreeFlags);
// security guarantee, but to increase the compression ratio of PartitionAlloc's
// fragmented super pages.
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocEventuallyZeroFreedMemory);
// Whether to make PartitionAlloc use fewer memory regions. This matters on
// Linux-based systems, where there is a per-process limit that we hit in some
// cases. See the comment in PartitionBucket::SlotSpanCOmmitedSize() for detail.
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocFewerMemoryRegions);
#endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
using BackupRefPtrEnabledProcesses = internal::PAFeatureEnabledProcesses;
@ -139,39 +147,44 @@ enum class BucketDistributionMode : uint8_t {
};
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocBackupRefPtr);
extern const BASE_EXPORT base::FeatureParam<BackupRefPtrEnabledProcesses>
kBackupRefPtrEnabledProcessesParam;
extern const BASE_EXPORT base::FeatureParam<BackupRefPtrMode>
kBackupRefPtrModeParam;
BASE_EXPORT BASE_DECLARE_FEATURE_PARAM(BackupRefPtrEnabledProcesses,
kBackupRefPtrEnabledProcessesParam);
BASE_EXPORT BASE_DECLARE_FEATURE_PARAM(BackupRefPtrMode,
kBackupRefPtrModeParam);
BASE_EXPORT BASE_DECLARE_FEATURE_PARAM(int,
kBackupRefPtrExtraExtrasSizeParam);
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocMemoryTagging);
extern const BASE_EXPORT base::FeatureParam<MemtagMode> kMemtagModeParam;
extern const BASE_EXPORT base::FeatureParam<RetagMode> kRetagModeParam;
extern const BASE_EXPORT base::FeatureParam<MemoryTaggingEnabledProcesses>
kMemoryTaggingEnabledProcessesParam;
BASE_EXPORT BASE_DECLARE_FEATURE_PARAM(MemtagMode, kMemtagModeParam);
BASE_EXPORT BASE_DECLARE_FEATURE_PARAM(RetagMode, kRetagModeParam);
BASE_EXPORT BASE_DECLARE_FEATURE_PARAM(MemoryTaggingEnabledProcesses,
kMemoryTaggingEnabledProcessesParam);
// Kill switch for memory tagging. Skips any code related to memory tagging when
// enabled.
BASE_EXPORT BASE_DECLARE_FEATURE(kKillPartitionAllocMemoryTagging);
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocPermissiveMte);
extern const BASE_EXPORT base::FeatureParam<bool>
kBackupRefPtrAsanEnableDereferenceCheckParam;
extern const BASE_EXPORT base::FeatureParam<bool>
kBackupRefPtrAsanEnableExtractionCheckParam;
extern const BASE_EXPORT base::FeatureParam<bool>
kBackupRefPtrAsanEnableInstantiationCheckParam;
extern const BASE_EXPORT base::FeatureParam<BucketDistributionMode>
kPartitionAllocBucketDistributionParam;
BASE_EXPORT BASE_DECLARE_FEATURE_PARAM(
bool,
kBackupRefPtrAsanEnableDereferenceCheckParam);
BASE_EXPORT BASE_DECLARE_FEATURE_PARAM(
bool,
kBackupRefPtrAsanEnableExtractionCheckParam);
BASE_EXPORT BASE_DECLARE_FEATURE_PARAM(
bool,
kBackupRefPtrAsanEnableInstantiationCheckParam);
BASE_EXPORT BASE_DECLARE_FEATURE_PARAM(BucketDistributionMode,
kPartitionAllocBucketDistributionParam);
BASE_EXPORT BASE_DECLARE_FEATURE(kLowerPAMemoryLimitForNonMainRenderers);
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocUseDenserDistribution);
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocMemoryReclaimer);
extern const BASE_EXPORT base::FeatureParam<TimeDelta>
kPartitionAllocMemoryReclaimerInterval;
BASE_EXPORT BASE_DECLARE_FEATURE_PARAM(TimeDelta,
kPartitionAllocMemoryReclaimerInterval);
BASE_EXPORT BASE_DECLARE_FEATURE(
kPartitionAllocStraightenLargerSlotSpanFreeLists);
extern const BASE_EXPORT
base::FeatureParam<partition_alloc::StraightenLargerSlotSpanFreeListsMode>
kPartitionAllocStraightenLargerSlotSpanFreeListsMode;
BASE_EXPORT BASE_DECLARE_FEATURE_PARAM(
partition_alloc::StraightenLargerSlotSpanFreeListsMode,
kPartitionAllocStraightenLargerSlotSpanFreeListsMode);
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocSortSmallerSlotSpanFreeLists);
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocSortActiveSlotSpans);
@ -180,8 +193,9 @@ BASE_EXPORT BASE_DECLARE_FEATURE(kPageAllocatorRetryOnCommitFailure);
#endif
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS)
extern const base::FeatureParam<bool>
kPartialLowEndModeExcludePartitionAllocSupport;
BASE_EXPORT BASE_DECLARE_FEATURE_PARAM(
bool,
kPartialLowEndModeExcludePartitionAllocSupport);
#endif
BASE_EXPORT BASE_DECLARE_FEATURE(kEnableConfigurableThreadCacheMultiplier);
@ -223,11 +237,10 @@ BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocUseSmallSingleSlotSpans);
using ShadowMetadataEnabledProcesses = internal::PAFeatureEnabledProcesses;
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocShadowMetadata);
extern const BASE_EXPORT base::FeatureParam<ShadowMetadataEnabledProcesses>
kShadowMetadataEnabledProcessesParam;
BASE_EXPORT BASE_DECLARE_FEATURE_PARAM(ShadowMetadataEnabledProcesses,
kShadowMetadataEnabledProcessesParam);
#endif // PA_CONFIG(ENABLE_SHADOW_METADATA)
} // namespace features
} // namespace base
} // namespace base::features
#endif // BASE_ALLOCATOR_PARTITION_ALLOC_FEATURES_H_

View file

@ -4,6 +4,7 @@
#include "base/allocator/partition_alloc_support.h"
#include <algorithm>
#include <array>
#include <cinttypes>
#include <cstdint>
@ -31,7 +32,6 @@
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/pending_task.h"
#include "base/ranges/algorithm.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
@ -48,6 +48,7 @@
#include "partition_alloc/memory_reclaimer.h"
#include "partition_alloc/page_allocator.h"
#include "partition_alloc/partition_alloc_base/debug/alias.h"
#include "partition_alloc/partition_alloc_base/immediate_crash.h"
#include "partition_alloc/partition_alloc_base/threading/platform_thread.h"
#include "partition_alloc/partition_alloc_check.h"
#include "partition_alloc/partition_alloc_config.h"
@ -464,7 +465,7 @@ std::string ExtractDanglingPtrSignature(std::string stacktrace) {
size_t caller_index = 0;
for (size_t i = 0; i < lines.size(); ++i) {
for (const auto& patterns : callee_patterns) {
if (ranges::all_of(patterns, [&](std::string_view pattern) {
if (std::ranges::all_of(patterns, [&](std::string_view pattern) {
return lines[i].find(pattern) != std::string_view::npos;
})) {
caller_index = i + 1;
@ -587,38 +588,55 @@ void DanglingRawPtrReleased(uintptr_t id) {
std::string dangling_signature = ExtractDanglingPtrSignature(
free_info, stack_trace_release, task_trace_release);
static const char dangling_ptr_footer[] =
"\n"
"\n"
"Please check for more information on:\n"
"https://chromium.googlesource.com/chromium/src/+/main/docs/"
"dangling_ptr_guide.md\n"
"\n"
"Googlers: Please give us your feedback about the dangling pointer\n"
" detector at:\n"
" http://go/dangling-ptr-cq-survey\n";
if (free_info) {
LOG(ERROR) << "Detected dangling raw_ptr with id="
<< StringPrintf("0x%016" PRIxPTR, id) << ":\n"
<< dangling_signature << "\n\n"
<< "The memory was freed at:\n"
<< free_info->stack_trace << "\n"
<< free_info->task_trace << "\n"
<< "The dangling raw_ptr was released at:\n"
<< stack_trace_release << "\n"
<< task_trace_release << dangling_ptr_footer;
} else {
LOG(ERROR) << "Detected dangling raw_ptr with id="
<< StringPrintf("0x%016" PRIxPTR, id) << ":\n\n"
<< dangling_signature << "\n\n"
<< "It was not recorded where the memory was freed.\n\n"
<< "The dangling raw_ptr was released at:\n"
<< stack_trace_release << "\n"
<< task_trace_release << dangling_ptr_footer;
{
// Log the full error in a single LogMessage. Printing StackTrace is
// expensive, so we want to avoid interleaving the output with other logs.
logging::LogMessage log_message(__FILE__, __LINE__, logging::LOGGING_ERROR);
std::ostream& error = log_message.stream();
// The dangling signature can be used by script to locate the origin of
// every dangling pointers.
error << "\n\n"
<< ExtractDanglingPtrSignature(free_info, stack_trace_release,
task_trace_release)
<< "\n\n";
error << "[DanglingPtr](1/3) A raw_ptr/raw_ref is dangling.\n\n";
auto print_traces = [](debug::StackTrace stack_trace,
debug::TaskTrace task_trace, std::ostream& error) {
error << "Stack trace:\n";
error << stack_trace << "\n";
// Printing "Task trace:" is implied by the TaskTrace itself.
if (!task_trace.empty()) {
error << task_trace << "\n";
}
};
error << "[DanglingPtr](2/3) ";
if (free_info) {
error << "First, the memory was freed at:\n\n";
print_traces(free_info->stack_trace, free_info->task_trace, error);
} else {
error << "It was not recorded where the memory was freed.\n";
}
error << "[DanglingPtr](3/3) Later, the dangling raw_ptr was released "
"at:\n\n";
print_traces(stack_trace_release, task_trace_release, error);
error << "Please check for more information on:\n";
error << "https://chromium.googlesource.com/chromium/src/+/main/docs/";
error << "dangling_ptr_guide.md\n";
error << "\n";
}
if constexpr (dangling_pointer_mode == features::DanglingPtrMode::kCrash) {
ImmediateCrash();
// We use `PA_IMMEDIATE_CRASH()` instead of base's ImmediateCrash() to avoid
// printing the raw_ptr release stack trace twice.
PA_IMMEDIATE_CRASH();
}
}
@ -649,16 +667,16 @@ void CheckDanglingRawPtrBufferEmpty() {
std::vector<std::array<const void*, 32>> stack_traces =
internal::InstanceTracer::GetStackTracesForDanglingRefs(entry->id);
for (const auto& raw_stack_trace : stack_traces) {
CHECK(ranges::is_partitioned(raw_stack_trace, is_frame_ptr_not_null))
CHECK(std::ranges::is_partitioned(raw_stack_trace, is_frame_ptr_not_null))
<< "`raw_stack_trace` is expected to be partitioned: non-null values "
"at the begining followed by `nullptr`s.";
LOG(ERROR) << "Dangling reference from:\n";
LOG(ERROR) << debug::StackTrace(
// This call truncates the `nullptr` tail of the stack
// trace (see the `is_partitioned` CHECK above).
make_span(raw_stack_trace.begin(),
ranges::partition_point(
raw_stack_trace, is_frame_ptr_not_null)))
span(raw_stack_trace.begin(),
std::ranges::partition_point(
raw_stack_trace, is_frame_ptr_not_null)))
<< "\n";
}
#else
@ -862,36 +880,28 @@ PartitionAllocSupport::GetBrpConfiguration(const std::string& process_type) {
// TODO(bartekn): Switch to DCHECK once confirmed there are no issues.
CHECK(base::FeatureList::GetInstance());
bool process_affected_by_brp_flag = false;
#if (PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \
PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) && \
!PA_BUILDFLAG(FORCE_DISABLE_BACKUP_REF_PTR_FEATURE)) || \
PA_BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
if (base::FeatureList::IsEnabled(
base::features::kPartitionAllocBackupRefPtr)) {
// No specified process type means this is the Browser process.
process_affected_by_brp_flag = ShouldEnableFeatureOnProcess(
base::features::kBackupRefPtrEnabledProcessesParam.Get(), process_type);
}
#endif // (PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) &&
// PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)&&
// !PA_BUILDFLAG(FORCE_DISABLE_BACKUP_REF_PTR_FEATURE)) ||
// PA_BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
const bool enable_brp =
#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \
PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
// kDisabled is equivalent to !IsEnabled(kPartitionAllocBackupRefPtr).
process_affected_by_brp_flag &&
PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) && \
!PA_BUILDFLAG(FORCE_DISABLE_BACKUP_REF_PTR_FEATURE)
if (base::FeatureList::IsEnabled(
base::features::kPartitionAllocBackupRefPtr) &&
base::features::kBackupRefPtrModeParam.Get() !=
base::features::BackupRefPtrMode::kDisabled;
#else
false;
base::features::BackupRefPtrMode::kDisabled &&
ShouldEnableFeatureOnProcess(
base::features::kBackupRefPtrEnabledProcessesParam.Get(),
process_type)) {
return {
.enable_brp = true,
.extra_extras_size = static_cast<size_t>(
base::features::kBackupRefPtrExtraExtrasSizeParam.Get()),
};
}
#endif
return {
enable_brp,
process_affected_by_brp_flag,
.enable_brp = false,
.extra_extras_size = 0,
};
}
@ -994,8 +1004,15 @@ void PartitionAllocSupport::ReconfigureAfterFeatureListInit(
[[maybe_unused]] BrpConfiguration brp_config =
GetBrpConfiguration(process_type);
#if PA_BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
if (brp_config.process_affected_by_brp_flag) {
// Configure ASAN hooks to report the `MiraclePtr status`. This is enabled
// only if BackupRefPtr is normally enabled in the current process for the
// current platform. Note that CastOS and iOS aren't protected by BackupRefPtr
// a the moment, so they are excluded.
#if PA_BUILDFLAG(USE_ASAN_BACKUP_REF_PTR) && !PA_BUILDFLAG(IS_CASTOS) && \
!PA_BUILDFLAG(IS_IOS)
if (ShouldEnableFeatureOnProcess(
base::features::kBackupRefPtrEnabledProcessesParam.Get(),
process_type)) {
base::RawPtrAsanService::GetInstance().Configure(
base::EnableDereferenceCheck(
base::features::kBackupRefPtrAsanEnableDereferenceCheckParam.Get()),
@ -1034,6 +1051,8 @@ void PartitionAllocSupport::ReconfigureAfterFeatureListInit(
base::features::kPartitionAllocZappingByFreeFlags);
const bool eventually_zero_freed_memory = base::FeatureList::IsEnabled(
base::features::kPartitionAllocEventuallyZeroFreedMemory);
const bool fewer_memory_regions = base::FeatureList::IsEnabled(
base::features::kPartitionAllocFewerMemoryRegions);
#if PA_BUILDFLAG(USE_FREELIST_DISPATCHER)
const bool use_pool_offset_freelists =
@ -1136,12 +1155,14 @@ void PartitionAllocSupport::ReconfigureAfterFeatureListInit(
allocator_shim::ConfigurePartitions(
allocator_shim::EnableBrp(brp_config.enable_brp),
brp_config.extra_extras_size,
allocator_shim::EnableMemoryTagging(enable_memory_tagging),
memory_tagging_reporting_mode, bucket_distribution,
allocator_shim::SchedulerLoopQuarantine(scheduler_loop_quarantine),
scheduler_loop_quarantine_branch_capacity_in_bytes,
allocator_shim::ZappingByFreeFlags(zapping_by_free_flags),
allocator_shim::EventuallyZeroFreedMemory(eventually_zero_freed_memory),
allocator_shim::FewerMemoryRegions(fewer_memory_regions),
allocator_shim::UsePoolOffsetFreelists(use_pool_offset_freelists),
use_small_single_slot_spans);
@ -1168,6 +1189,18 @@ void PartitionAllocSupport::ReconfigureAfterFeatureListInit(
->EnableLargeEmptySlotSpanRing();
}
if (process_type == "" &&
base::FeatureList::IsEnabled(
base::features::kPartitionAllocSchedulerLoopQuarantine)) {
// `ReconfigureAfterTaskRunnerInit()` is called on the UI thread.
const size_t capacity_in_bytes = static_cast<size_t>(
base::features::kPartitionAllocSchedulerLoopQuarantineBrowserUICapacity
.Get());
allocator_shim::internal::PartitionAllocMalloc::Allocator()
->SetSchedulerLoopQuarantineThreadLocalBranchCapacity(
capacity_in_bytes);
}
#if PA_BUILDFLAG( \
ENABLE_ALLOCATOR_SHIM_PARTITION_ALLOC_DISPATCH_WITH_ADVANCED_CHECKS_SUPPORT)
bool enable_pa_with_advanced_checks =
@ -1293,7 +1326,8 @@ void PartitionAllocSupport::ReconfigureAfterTaskRunnerInit(
if (ShouldEnableShadowMetadata(process_type)) {
partition_alloc::PartitionRoot::EnableShadowMetadata(
partition_alloc::internal::PoolHandleMask::kRegular |
partition_alloc::internal::PoolHandleMask::kBRP);
partition_alloc::internal::PoolHandleMask::kBRP |
partition_alloc::internal::PoolHandleMask::kConfigurable);
}
#endif // PA_CONFIG(ENABLE_SHADOW_METADATA)
}

View file

@ -49,7 +49,9 @@ class BASE_EXPORT PartitionAllocSupport {
public:
struct BrpConfiguration {
bool enable_brp = false;
bool process_affected_by_brp_flag = false;
// TODO(https://crbug.com/371135823): Remove after the investigation.
size_t extra_extras_size = 0;
};
// Reconfigure* functions re-configure PartitionAlloc. It is impossible to

View file

@ -11,8 +11,14 @@ group("buildflags") {
public_deps = [ "src/partition_alloc:buildflags" ]
}
if (is_clang_or_gcc) {
if (use_partition_alloc && is_clang_or_gcc) {
group("partition_alloc") {
public_deps = [ "src/partition_alloc:partition_alloc" ]
}
}
if (use_allocator_shim) {
group("allocator_shim") {
public_deps = [ "src/partition_alloc:allocator_shim" ]
}
}

View file

@ -230,3 +230,20 @@ def CheckCpp17CompatibleKeywords(input_api, output_api):
'%s:%d\nPartitionAlloc disallows C++20 keywords: %s'
% (f.LocalPath(), line_number + 1, keyword)))
return errors
# Check `NDEBUG` is not used inside partition_alloc. We prefer to use the
# buildflags `#if PA_BUILDFLAG(IS_DEBUG)` instead.
def CheckNoNDebug(input_api, output_api):
sources = lambda affected_file: input_api.FilterSourceFile(
affected_file,
files_to_skip=[],
files_to_check=[_SOURCE_FILE_PATTERN])
errors = []
for f in input_api.AffectedSourceFiles(sources):
for line_number, line in f.ChangedContents():
if 'NDEBUG' in line:
errors.append(output_api.PresubmitError('%s:%d\nPartitionAlloc'
% (f.LocalPath(), line_number + 1)
+ 'disallows NDEBUG, use PA_BUILDFLAG(IS_DEBUG) instead'))
return errors

View file

@ -4,6 +4,56 @@
import("//build_overrides/partition_alloc.gni")
# -----------------------------------------------------------------------------
# Note on the use of `xxx_default` variable in partition_alloc.
#
# GN provides default_args() instruction. It is meant to be used by embedders,
# to override the default args declared by the embeddees (e.g. partition_alloc).
# This is the intended way to use GN. It properly interacts with the args.gn
# user's file.
#
# Unfortunately, Chrome and others embedders aren't using it. Instead, they
# expect embeddees to import global '.gni' file from the embedder, e.g.
# `//build_overrides/partition_alloc.gni`. This file sets some `xxx_default`
# variable that will be transferred to the declared args. For instance
# a library would use:
# ```
# import("//build_overrides/library.gni")
# declare_args() {
# xxx = xxx_default
# }
# ```
#
# We don't really want to break embedders when introducing new args. Ideally,
# We would have liked to have defaults for default variables. That would be
# a recursive problem. To resolve it, we sometimes use the `defined(...)`
# instruction to check if the embedder has defined the `xxx_default` variable or
# not.
#
# In general, we should aim to support the embedders that are using GN normally,
# and avoid requiring them to define `xxx_default` in the `//build_overrides`
# -----------------------------------------------------------------------------
# Some embedders uses `is_debug`, it can be used to set the default value of
# `partition_alloc_is_debug_default`.
if (!defined(partition_alloc_is_debug_default)) {
if (defined(is_debug)) {
partition_alloc_is_debug_default = is_debug
} else {
partition_alloc_is_debug_default = false
}
}
# Some embedders uses `dcheck_always_on`, it can be used to set the default
# value of `partition_alloc_dcheck_always_on_default`.
if (!defined(partition_alloc_dcheck_always_on_default)) {
if (defined(dcheck_always_on)) {
partition_alloc_dcheck_always_on_default = dcheck_always_on
} else {
partition_alloc_dcheck_always_on_default = false
}
}
# PartitionAlloc have limited support for MSVC's cl.exe compiler. It can only
# access the generate "buildflags" and the "raw_ptr" definitions implemented
# with RawPtrNoOpImpl. Everything else is considered not supported.
@ -32,8 +82,9 @@ if (is_nacl) {
# foreground mode compared to background mode
# (see `PartitionRoot::AdjustFor(Background|Foreground)`).
#
# Foreground/background modes are used by default on macOS so this must be
# true on that platform. It's also true on other platforms to allow experiments.
# Foreground/background modes are used by default on macOS and Windows so this
# must be true on these platforms. It's also true on other platforms to allow
# experiments.
#
# TODO(crbug.com/329199197): Clean this up when experiments are complete.
use_large_empty_slot_span_ring = true
@ -47,6 +98,12 @@ has_memory_tagging =
current_cpu == "arm64" && is_clang && !is_asan && is_linux && current_os != "openwrt"
declare_args() {
# Debug configuration.
partition_alloc_is_debug = partition_alloc_is_debug_default
# Enable PA_DCHECKs in PartitionAlloc in release mode.
partition_alloc_dcheck_always_on = partition_alloc_dcheck_always_on_default
# Causes all the allocations to be routed via allocator_shim.cc. Usually,
# the allocator shim will, in turn, route them to PartitionAlloc, but
# other allocators are also supported by the allocator shim.
@ -134,8 +191,8 @@ if (use_allocator_shim && is_win) {
# If libcxx_is_shared=false, libc++ is a static library. All libc++ code
# will be run inside the client. The above issue will disappear.
assert(
!is_component_build || (!libcxx_is_shared && !is_debug),
"The allocator shim for the Windows component build needs !libcxx_is_shared && !is_debug.")
!is_component_build || (!libcxx_is_shared && !partition_alloc_is_debug),
"The allocator shim for the Windows component build needs !libcxx_is_shared && !partition_alloc_is_debug.")
}
declare_args() {
@ -171,7 +228,8 @@ declare_args() {
# later verify the pattern remain unchanged to ensure there is no OOB write.
# It comes with performance and memory cost, hence enabled only in debug.
use_partition_cookie =
is_debug || dcheck_always_on || enable_ios_corruption_hardening
partition_alloc_is_debug || partition_alloc_dcheck_always_on ||
enable_ios_corruption_hardening
# This will change partition cookie size to 4B or 8B, whichever equivalent to
# size of InSlotMetadata. This option is useful for InSlotMetadata corruption

View file

@ -35,7 +35,8 @@ enable_pointer_compression =
# Duplicates the setup Chromium uses to define `DCHECK_IS_ON()`, but avails it
# as a buildflag.
dchecks_are_on = is_debug || dcheck_always_on
partition_alloc_dchecks_are_on =
partition_alloc_is_debug || partition_alloc_dcheck_always_on
# Building PartitionAlloc for Windows component build.
# Currently use build_with_chromium not to affect any third_party code,
@ -151,7 +152,7 @@ pa_buildflag_header("buildflags") {
"IS_CASTOS=$is_castos",
"IS_CAST_ANDROID=$is_cast_android",
"IS_CHROMEOS=$is_chromeos",
"IS_DEBUG=$is_debug",
"IS_DEBUG=$partition_alloc_is_debug",
"RAW_PTR_ZERO_ON_CONSTRUCT=$raw_ptr_zero_on_construct",
"RAW_PTR_ZERO_ON_DESTRUCT=$raw_ptr_zero_on_destruct",
"RAW_PTR_ZERO_ON_MOVE=$raw_ptr_zero_on_move",
@ -171,7 +172,7 @@ pa_buildflag_header("buildflags") {
"USE_RAW_PTR_BACKUP_REF_IMPL=$use_raw_ptr_backup_ref_impl",
"USE_RAW_PTR_HOOKABLE_IMPL=$use_raw_ptr_hookable_impl",
"ENABLE_ALLOCATOR_SHIM_PARTITION_ALLOC_DISPATCH_WITH_ADVANCED_CHECKS_SUPPORT=$enable_allocator_shim_partition_alloc_dispatch_with_advanced_checks_support",
"DCHECKS_ARE_ON=$dchecks_are_on",
"DCHECKS_ARE_ON=$partition_alloc_dchecks_are_on",
"EXPENSIVE_DCHECKS_ARE_ON=$enable_expensive_dchecks",
"DCHECK_IS_CONFIGURABLE=$dcheck_is_configurable",
"CAN_UNWIND_WITH_FRAME_POINTERS=$can_unwind_with_frame_pointers",
@ -330,7 +331,7 @@ if (is_clang_or_gcc) {
}
}
if (enable_pkeys && is_debug) {
if (enable_pkeys && partition_alloc_is_debug) {
config("no_stack_protector") {
cflags = [ "-fno-stack-protector" ]
}
@ -442,6 +443,7 @@ if (is_clang_or_gcc) {
"partition_page_constants.h",
"partition_root.cc",
"partition_root.h",
"partition_shared_mutex.h",
"partition_stats.cc",
"partition_stats.h",
"partition_superpage_extent_entry.h",
@ -566,7 +568,7 @@ if (is_clang_or_gcc) {
# We want to be able to test pkey mode without access to the default pkey.
# This is incompatible with stack protectors since the TLS won't be pkey-tagged.
if (enable_pkeys && is_debug) {
if (enable_pkeys && partition_alloc_is_debug) {
configs += [ ":no_stack_protector" ]
}
}
@ -599,6 +601,7 @@ if (is_clang_or_gcc) {
"partition_alloc_base/debug/stack_trace.cc",
"partition_alloc_base/debug/stack_trace.h",
"partition_alloc_base/export_template.h",
"partition_alloc_base/files/platform_file.h",
"partition_alloc_base/immediate_crash.h",
"partition_alloc_base/log_message.cc",
"partition_alloc_base/log_message.h",
@ -644,6 +647,7 @@ if (is_clang_or_gcc) {
"partition_alloc_base/time/time.h",
"partition_alloc_base/time/time_override.cc",
"partition_alloc_base/time/time_override.h",
"partition_alloc_base/types/same_as_any.h",
"partition_alloc_base/types/strong_alias.h",
"partition_alloc_base/win/win_handle_types.h",
"partition_alloc_base/win/win_handle_types_list.inc",
@ -787,8 +791,6 @@ if (is_clang_or_gcc) {
}
component("allocator_shim") {
visibility = [ ":*" ]
sources = []
deps = []
all_dependent_configs = []
@ -1014,7 +1016,7 @@ if (build_with_chromium) {
]
}
if (enable_pkeys && is_debug && !is_component_build) {
if (enable_pkeys && partition_alloc_is_debug && !is_component_build) {
# This test requires RELRO, which is not enabled in component builds.
# Also, require a debug build, since we only disable stack protectors in
# debug builds in PartitionAlloc (see below why it's needed).

View file

@ -292,7 +292,7 @@ AslrMask(uintptr_t bits) {
#endif // PA_BUILDFLAG(PA_ARCH_CPU_32_BITS)
// clang-format on
// clang-format on
} // namespace internal

View file

@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "partition_alloc/allocation_guard.h"
#include "partition_alloc/partition_alloc_base/immediate_crash.h"
#include "partition_alloc/partition_alloc_config.h"

View file

@ -77,7 +77,17 @@ ThreadCacheProcessScopeForTesting::ThreadCacheProcessScopeForTesting(
// Replace ThreadCache's PartitionRoot.
ThreadCache::SwapForTesting(root_);
} else {
if (!regular_was_enabled_) {
bool regular_was_disabled = !regular_was_enabled_;
#if PA_BUILDFLAG(IS_WIN)
// ThreadCache may be tombstone because of the previous test. In the
// case, we have to remove tombstone and re-create ThreadCache for
// a new test.
if (ThreadCache::IsTombstone(ThreadCache::Get())) {
ThreadCache::RemoveTombstoneForTesting();
regular_was_disabled = true;
}
#endif
if (regular_was_disabled) {
EnablePartitionAllocThreadCacheForRootIfDisabled(root_);
ThreadCache::SwapForTesting(root_);
}
@ -89,6 +99,7 @@ ThreadCacheProcessScopeForTesting::ThreadCacheProcessScopeForTesting(
#endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
PA_CHECK(ThreadCache::Get());
PA_CHECK(!ThreadCache::IsTombstone(ThreadCache::Get()));
}
ThreadCacheProcessScopeForTesting::~ThreadCacheProcessScopeForTesting() {

View file

@ -37,8 +37,4 @@ void InternalPartitionAllocated::operator delete(void* ptr, std::align_val_t) {
InternalAllocatorRoot().Free<FreeFlags::kNoHooks>(ptr);
}
// A deleter for `std::unique_ptr<T>`.
void InternalPartitionDeleter::operator()(void* ptr) const {
InternalAllocatorRoot().Free<FreeFlags::kNoHooks>(ptr);
}
} // namespace partition_alloc::internal

View file

@ -48,8 +48,6 @@ T* ConstructAtInternalPartition(Args&&... args) {
}
// Destroy an object on heap in the internal partition.
// TODO(crbug.com/40274826) This is an unused function. Start using it in tests
// and/or in production code.
template <typename T>
void DestroyAtInternalPartition(T* ptr) {
// Destroying an array is not supported.

View file

@ -67,14 +67,13 @@ template <typename T, typename... Args>
T* ConstructAtInternalPartition(Args&&... args);
// Destroy an object on heap in the internal partition.
// TODO(crbug.com/40274826) This is an unused function. Start using it in tests
// and/or in production code.
template <typename T>
void DestroyAtInternalPartition(T* ptr);
// A deleter for `std::unique_ptr<T>`.
struct PA_COMPONENT_EXPORT(PARTITION_ALLOC) InternalPartitionDeleter final {
void operator()(void* ptr) const;
template <typename T>
struct InternalPartitionDeleter final {
void operator()(T* ptr) const { DestroyAtInternalPartition(ptr); }
};
} // namespace partition_alloc::internal

View file

@ -19,7 +19,10 @@ class PA_SCOPED_LOCKABLE
public:
PA_ALWAYS_INLINE explicit CompileTimeConditionalScopedGuard(Lock& lock)
PA_EXCLUSIVE_LOCK_FUNCTION(lock) {}
PA_ALWAYS_INLINE ~CompileTimeConditionalScopedGuard() PA_UNLOCK_FUNCTION() {}
// For some reason, defaulting this causes a thread safety annotation failure.
PA_ALWAYS_INLINE
~CompileTimeConditionalScopedGuard() // NOLINT(modernize-use-equals-default)
PA_UNLOCK_FUNCTION() {}
};
template <>
@ -71,7 +74,12 @@ LightweightQuarantineBranch::LightweightQuarantineBranch(
const LightweightQuarantineBranchConfig& config)
: root_(root),
lock_required_(config.lock_required),
branch_capacity_in_bytes_(config.branch_capacity_in_bytes) {}
branch_capacity_in_bytes_(config.branch_capacity_in_bytes) {
if (lock_required_) {
to_be_freed_working_memory_ =
ConstructAtInternalPartition<ToBeFreedArray>();
}
}
LightweightQuarantineBranch::LightweightQuarantineBranch(
LightweightQuarantineBranch&& b)
@ -82,10 +90,19 @@ LightweightQuarantineBranch::LightweightQuarantineBranch(
branch_capacity_in_bytes_(
b.branch_capacity_in_bytes_.load(std::memory_order_relaxed)) {
b.branch_size_in_bytes_ = 0;
if (lock_required_) {
to_be_freed_working_memory_.store(b.to_be_freed_working_memory_.exchange(
nullptr, std::memory_order_relaxed),
std::memory_order_relaxed);
}
}
LightweightQuarantineBranch::~LightweightQuarantineBranch() {
Purge();
if (lock_required_) {
DestroyAtInternalPartition(to_be_freed_working_memory_.exchange(
nullptr, std::memory_order_relaxed));
}
}
bool LightweightQuarantineBranch::IsQuarantinedForTesting(void* object) {
@ -151,16 +168,26 @@ bool LightweightQuarantineBranch::QuarantineInternal(
const size_t random_index = random_.RandUint32() % slots_.size();
std::swap(slots_[random_index], slots_.back());
} else {
ToBeFreedArray to_be_freed;
std::unique_ptr<ToBeFreedArray, InternalPartitionDeleter<ToBeFreedArray>>
to_be_freed;
size_t num_of_slots = 0;
{
CompileTimeConditionalScopedGuard<lock_required> guard(lock_);
// Borrow the reserved working memory from to_be_freed_working_memory_,
// and set nullptr to it indicating that it's in use.
to_be_freed.reset(to_be_freed_working_memory_.exchange(nullptr));
if (!to_be_freed) {
// When the reserved working memory has already been in use by another
// thread, fall back to allocate another chunk of working memory.
to_be_freed.reset(ConstructAtInternalPartition<ToBeFreedArray>());
}
// Dequarantine some entries as required. Save the objects to be
// deallocated into `to_be_freed`.
PurgeInternalWithDefferedFree(capacity_in_bytes - usable_size,
to_be_freed, num_of_slots);
*to_be_freed, num_of_slots);
// Put the entry onto the list.
branch_size_in_bytes_ += usable_size;
@ -173,7 +200,17 @@ bool LightweightQuarantineBranch::QuarantineInternal(
}
// Actually deallocate the dequarantined objects.
BatchFree(to_be_freed, num_of_slots);
BatchFree(*to_be_freed, num_of_slots);
// Return the possibly-borrowed working memory to
// to_be_freed_working_memory_. It doesn't matter much if it's really
// borrowed or locally-allocated. The important facts are 1) to_be_freed is
// non-null, and 2) to_be_freed_working_memory_ may likely be null (because
// this or another thread has already borrowed it). It's simply good to make
// to_be_freed_working_memory_ non-null whenever possible. Maybe yet another
// thread would be about to borrow the working memory.
to_be_freed.reset(
to_be_freed_working_memory_.exchange(to_be_freed.release()));
}
// Update stats (not locked).

View file

@ -217,6 +217,17 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) LightweightQuarantineBranch {
// Using `std::atomic` here so that other threads can update this value.
std::atomic_size_t branch_capacity_in_bytes_;
// This working memory is temporarily needed only while dequarantining
// objects in slots_ when lock_required_ is true. However, allocating this
// working memory on stack may cause stack overflow [1]. Plus, it's non-
// negligible perf penalty to allocate and deallocate this working memory on
// heap only while dequarantining. So, we reserve one chunk of working memory
// on heap during the entire lifetime of this branch object and try to reuse
// this working memory among threads. Only when thread contention occurs, we
// allocate and deallocate another chunk of working memory.
// [1] https://issues.chromium.org/issues/387508217
std::atomic<ToBeFreedArray*> to_be_freed_working_memory_ = nullptr;
friend class LightweightQuarantineRoot;
};

View file

@ -26,7 +26,7 @@
#define PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR __attribute__((const))
#elif (PA_BUILDFLAG(IS_ANDROID) && PA_BUILDFLAG(PA_ARCH_CPU_64_BITS)) || \
(PA_BUILDFLAG(IS_LINUX) && PA_BUILDFLAG(PA_ARCH_CPU_ARM64)) || \
(PA_BUILDFLAG(IS_LINUX) && PA_BUILDFLAG(PA_ARCH_CPU_ARM64)) || \
(PA_BUILDFLAG(IS_LINUX) && PA_BUILDFLAG(PA_ARCH_CPU_PPC64))
// This should work for all POSIX (if needed), but currently all other
// supported OS/architecture combinations use either hard-coded values
@ -39,6 +39,7 @@
#define PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR __attribute__((const))
#include <unistd.h>
#include <atomic>
namespace partition_alloc::internal {
@ -69,9 +70,30 @@ extern PageCharacteristics page_characteristics;
// Ability to name anonymous VMAs is available on some, but not all Linux-based
// systems.
#if PA_BUILDFLAG(IS_ANDROID) || PA_BUILDFLAG(IS_LINUX)
#if PA_BUILDFLAG(IS_ANDROID) || PA_BUILDFLAG(IS_LINUX) || \
PA_BUILDFLAG(IS_CHROMEOS)
#include <sys/prctl.h>
#if (PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS)) && \
!(defined(PR_SET_VMA) && defined(PR_SET_VMA_ANON_NAME))
// The PR_SET_VMA* symbols are originally from
// https://android.googlesource.com/platform/bionic/+/lollipop-release/libc/private/bionic_prctl.h
// and were subsequently added to mainline Linux in Jan 2022, see
// https://github.com/torvalds/linux/commit/9a10064f5625d5572c3626c1516e0bebc6c9fe9b.
//
// Define them to support compiling with older headers.
#if !defined(PR_SET_VMA)
#define PR_SET_VMA 0x53564d41
#endif
#if !defined(PR_SET_VMA_ANON_NAME)
#define PR_SET_VMA_ANON_NAME 0
#endif
#endif // (PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS)) &&
// !(defined(PR_SET_VMA) && defined(PR_SET_VMA_ANON_NAME))
#if defined(PR_SET_VMA) && defined(PR_SET_VMA_ANON_NAME)
#define LINUX_NAME_REGION 1
#endif

View file

@ -150,7 +150,7 @@ void NameRegion(void* start, size_t length, PageTag page_tag) {
PA_NOTREACHED();
}
// No error checking on purpose, testing only.
// No error checking on purpose, used for debugging only.
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, start, length, name);
}

View file

@ -19,6 +19,7 @@
#include "partition_alloc/partition_alloc_base/bits.h"
#include "partition_alloc/partition_alloc_base/compiler_specific.h"
#include "partition_alloc/partition_alloc_base/debug/alias.h"
#include "partition_alloc/partition_alloc_base/files/platform_file.h"
#include "partition_alloc/partition_alloc_check.h"
#include "partition_alloc/partition_alloc_config.h"
#include "partition_alloc/partition_alloc_constants.h"
@ -89,9 +90,12 @@ std::ptrdiff_t PartitionAddressSpace::brp_pool_shadow_offset_ = 0;
std::ptrdiff_t PartitionAddressSpace::configurable_pool_shadow_offset_ = 0;
// File descriptors for shared mappings.
int PartitionAddressSpace::regular_pool_fd_ = -1;
int PartitionAddressSpace::brp_pool_fd_ = -1;
int PartitionAddressSpace::configurable_pool_fd_ = -1;
base::PlatformFile PartitionAddressSpace::regular_pool_fd_ =
base::kInvalidPlatformFile;
base::PlatformFile PartitionAddressSpace::brp_pool_fd_ =
base::kInvalidPlatformFile;
base::PlatformFile PartitionAddressSpace::configurable_pool_fd_ =
base::kInvalidPlatformFile;
uintptr_t PartitionAddressSpace::pool_shadow_address_ =
PartitionAddressSpace::kUninitializedPoolBaseAddress;
@ -152,9 +156,6 @@ void PartitionAddressSpace::Init() {
const size_t core_pool_size = CorePoolSize();
// TODO(crbug.com/40238514): Support PA_ENABLE_SHADOW_METADATA.
int pools_fd = -1;
size_t glued_pool_sizes = core_pool_size * 2;
// Note, BRP pool requires to be preceded by a "forbidden zone", which is
// conveniently taken care of by the last guard page of the regular pool.
@ -162,7 +163,7 @@ void PartitionAddressSpace::Init() {
AllocPages(glued_pool_sizes, glued_pool_sizes,
PageAccessibilityConfiguration(
PageAccessibilityConfiguration::kInaccessible),
PageTag::kPartitionAlloc, pools_fd);
PageTag::kPartitionAlloc);
#if PA_BUILDFLAG(IS_ANDROID)
// On Android, Adreno-GSL library fails to mmap if we snatch address
// 0x400000000. Find a different address instead.
@ -171,7 +172,7 @@ void PartitionAddressSpace::Init() {
AllocPages(glued_pool_sizes, glued_pool_sizes,
PageAccessibilityConfiguration(
PageAccessibilityConfiguration::kInaccessible),
PageTag::kPartitionAlloc, pools_fd);
PageTag::kPartitionAlloc);
FreePages(setup_.regular_pool_base_address_, glued_pool_sizes);
setup_.regular_pool_base_address_ = new_base_address;
}
@ -356,9 +357,10 @@ void PartitionAddressSpace::UninitThreadIsolatedPoolForTesting() {
namespace {
int CreateAnonymousFileForMapping([[maybe_unused]] const char* name,
[[maybe_unused]] size_t size) {
int fd = -1;
base::PlatformFile CreateAnonymousFileForMapping(
[[maybe_unused]] const char* name,
[[maybe_unused]] size_t size) {
base::PlatformFile fd = base::kInvalidPlatformFile;
#if PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS)
// TODO(crbug.com/40238514): if memfd_secret() is available, try
// memfd_secret() first.
@ -396,7 +398,7 @@ void PartitionAddressSpace::InitShadowMetadata(PoolHandleMask mask) {
// Set up a memory file for the given pool, and init |offset|.
if (ContainsFlags(mask, PoolHandleMask::kConfigurable)) {
if (configurable_pool_fd_ == -1) {
if (configurable_pool_fd_ == base::kInvalidPlatformFile) {
PA_DCHECK(pool_shadow_address_);
PA_DCHECK(configurable_pool_shadow_offset_ == 0);
configurable_pool_fd_ = CreateAnonymousFileForMapping(
@ -407,7 +409,7 @@ void PartitionAddressSpace::InitShadowMetadata(PoolHandleMask mask) {
}
}
if (ContainsFlags(mask, PoolHandleMask::kBRP)) {
if (brp_pool_fd_ == -1) {
if (brp_pool_fd_ == base::kInvalidPlatformFile) {
PA_DCHECK(pool_shadow_address_);
PA_DCHECK(brp_pool_shadow_offset_ == 0);
brp_pool_fd_ = CreateAnonymousFileForMapping("brp_pool_shadow",
@ -418,7 +420,7 @@ void PartitionAddressSpace::InitShadowMetadata(PoolHandleMask mask) {
}
}
if (ContainsFlags(mask, PoolHandleMask::kRegular)) {
if (regular_pool_fd_ == -1) {
if (regular_pool_fd_ == base::kInvalidPlatformFile) {
PA_DCHECK(pool_shadow_address_);
PA_DCHECK(regular_pool_shadow_offset_ == 0);
regular_pool_fd_ = CreateAnonymousFileForMapping("regular_pool_shadow",
@ -437,7 +439,7 @@ void PartitionAddressSpace::MapMetadata(uintptr_t super_page,
PA_DCHECK(pool_shadow_address_);
PA_DCHECK(0u == (super_page & kSuperPageOffsetMask));
std::ptrdiff_t offset;
int pool_fd = -1;
base::PlatformFile pool_fd = base::kInvalidPlatformFile;
uintptr_t base_address;
if (IsInRegularPool(super_page)) {

View file

@ -15,6 +15,7 @@
#include "partition_alloc/partition_alloc_base/bits.h"
#include "partition_alloc/partition_alloc_base/compiler_specific.h"
#include "partition_alloc/partition_alloc_base/component_export.h"
#include "partition_alloc/partition_alloc_base/files/platform_file.h"
#include "partition_alloc/partition_alloc_base/notreached.h"
#include "partition_alloc/partition_alloc_check.h"
#include "partition_alloc/partition_alloc_config.h"
@ -221,15 +222,15 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionAddressSpace {
#if PA_CONFIG(ENABLE_SHADOW_METADATA)
PA_ALWAYS_INLINE static bool IsShadowMetadataEnabledOnRegularPool() {
return regular_pool_fd_ != -1;
return regular_pool_fd_ != base::kInvalidPlatformFile;
}
PA_ALWAYS_INLINE static bool IsShadowMetadataEnabledOnBRPPool() {
return brp_pool_fd_ != -1;
return brp_pool_fd_ != base::kInvalidPlatformFile;
}
PA_ALWAYS_INLINE static bool IsShadowMetadataEnabledOnConfigurablePool() {
return configurable_pool_fd_ != -1;
return configurable_pool_fd_ != base::kInvalidPlatformFile;
}
PA_ALWAYS_INLINE static bool IsShadowMetadataEnabled(pool_handle pool) {
@ -454,10 +455,9 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionAddressSpace {
static std::ptrdiff_t regular_pool_shadow_offset_;
static std::ptrdiff_t brp_pool_shadow_offset_;
static std::ptrdiff_t configurable_pool_shadow_offset_;
// TODO(crbug.com/40238514): Use platform file handles instead of |int|.
static int regular_pool_fd_;
static int brp_pool_fd_;
static int configurable_pool_fd_;
static base::PlatformFile regular_pool_fd_;
static base::PlatformFile brp_pool_fd_;
static base::PlatformFile configurable_pool_fd_;
static uintptr_t pool_shadow_address_;
#endif // PA_CONFIG(ENABLE_SHADOW_METADATA)

View file

@ -20,11 +20,12 @@
// This header defines the CHECK, DCHECK, and DPCHECK macros.
//
// CHECK dies with a fatal error if its condition is not true. It is not
// controlled by NDEBUG, so the check will be executed regardless of compilation
// mode.
// controlled by PA_BUILDFLAG(IS_DEBUG), so the check will be executed
// regardless of compilation mode.
//
// DCHECK, the "debug mode" check, is enabled depending on NDEBUG and
// DCHECK_ALWAYS_ON, and its severity depends on DCHECK_IS_CONFIGURABLE.
// DCHECK, the "debug mode" check, is enabled depending on
// PA_BUILDFLAG(IS_DEBUG) and PA_BUILDFLAG(DCHECK_ALWAYS_ON), and its severity
// depends on PA_BUILDFLAG(DCHECK_IS_CONFIGURABLE).
//
// (D)PCHECK is like (D)CHECK, but includes the system error code (c.f.
// perror(3)).
@ -141,9 +142,9 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) NotImplemented
} // namespace check_error
#if defined(OFFICIAL_BUILD) && !defined(NDEBUG)
#if defined(OFFICIAL_BUILD) && PA_BUILDFLAG(IS_DEBUG)
#error "Debug builds are not expected to be optimized as official builds."
#endif // defined(OFFICIAL_BUILD) && !defined(NDEBUG)
#endif // defined(OFFICIAL_BUILD) && BUILDFLAG(IS_DEBUG)
#if defined(OFFICIAL_BUILD) && !PA_BUILDFLAG(DCHECKS_ARE_ON)

View file

@ -6,6 +6,7 @@
#define PARTITION_ALLOC_PARTITION_ALLOC_BASE_COMPILER_SPECIFIC_H_
#include "partition_alloc/build_config.h"
#include "partition_alloc/buildflags.h"
// A wrapper around `__has_cpp_attribute()`, which is in C++20 and thus not yet
// available for all targets PA supports (since PA's minimum C++ version is 17).
@ -87,7 +88,7 @@
//
// Since `ALWAYS_INLINE` is performance-oriented but can hamper debugging,
// ignore it in debug mode.
#if defined(NDEBUG)
#if !PA_BUILDFLAG(IS_DEBUG)
#if PA_HAS_CPP_ATTRIBUTE(clang::always_inline)
#define PA_ALWAYS_INLINE [[clang::always_inline]] inline
#elif PA_HAS_CPP_ATTRIBUTE(gnu::always_inline)
@ -95,7 +96,7 @@
#elif defined(PA_COMPILER_MSVC)
#define PA_ALWAYS_INLINE __forceinline
#endif
#endif
#endif // !PA_BUILDFLAG(IS_DEBUG)
#if !defined(PA_ALWAYS_INLINE)
#define PA_ALWAYS_INLINE inline
#endif

View file

@ -97,7 +97,7 @@ uint64_t xgetbv(uint32_t xcr) {
void CPU::Initialize() {
#if PA_BUILDFLAG(PA_ARCH_CPU_X86_FAMILY)
int cpu_info[4] = {-1};
int cpu_info[4] = {-1, 0, 0, 0};
// __cpuid with an InfoType argument of 0 returns the number of
// valid Ids in CPUInfo[0] and the CPU identification string in
@ -112,7 +112,7 @@ void CPU::Initialize() {
// Interpret CPU feature information.
if (num_ids > 0) {
int cpu_info7[4] = {0};
int cpu_info7[4] = {};
__cpuid(cpu_info, 1);
if (num_ids >= 7) {
__cpuid(cpu_info7, 7);

View file

@ -35,7 +35,7 @@ namespace partition_alloc::internal::base::debug {
// strncpy(name_copy, p->name, sizeof(name_copy)-1);
// name_copy[sizeof(name_copy)-1] = '\0';;
// base::debug::alias(name_copy);
// CHECK(false);
// NOTREACHED();
//
// Case #2: Prevent a tail call into a function. This is useful to make sure the
// function containing the call to base::debug::Alias() will be present in the

View file

@ -0,0 +1,39 @@
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_FILES_PLATFORM_FILE_H_
#define PARTITION_ALLOC_PARTITION_ALLOC_BASE_FILES_PLATFORM_FILE_H_
#include "partition_alloc/build_config.h"
#if PA_BUILDFLAG(IS_WIN)
#include "partition_alloc/partition_alloc_base/win/windows_types.h"
#endif
// This file defines platform-independent types for dealing with
// platform-dependent files. If possible, use the higher-level base::File class
// rather than these primitives.
namespace partition_alloc::internal::base {
#if PA_BUILDFLAG(IS_WIN)
using PlatformFile = HANDLE;
// It would be nice to make this constexpr but INVALID_HANDLE_VALUE is a
// ((void*)(-1)) which Clang rejects since reinterpret_cast is technically
// disallowed in constexpr. Visual Studio accepts this, however.
const PlatformFile kInvalidPlatformFile = INVALID_HANDLE_VALUE;
#elif PA_BUILDFLAG(IS_POSIX) || PA_BUILDFLAG(IS_FUCHSIA)
using PlatformFile = int;
inline constexpr PlatformFile kInvalidPlatformFile = -1;
#endif
} // namespace partition_alloc::internal::base
#endif // PARTITION_ALLOC_PARTITION_ALLOC_BASE_FILES_PLATFORM_FILE_H_

View file

@ -9,6 +9,8 @@
#include <limits>
#include <type_traits>
#include "partition_alloc/buildflags.h"
namespace partition_alloc::internal::base::internal {
// The std library doesn't provide a binary max_exponent for integers, however
@ -83,13 +85,13 @@ constexpr typename std::make_unsigned<T>::type SafeUnsignedAbs(T value) {
// TODO(jschuh): Debug builds don't reliably propagate constants, so we restrict
// some accelerated runtime paths to release builds until this can be forced
// with consteval support in C++20 or C++23.
#if defined(NDEBUG)
constexpr bool kEnableAsmCode = true;
#if PA_BUILDFLAG(IS_DEBUG)
inline constexpr bool kEnableAsmCode = false;
#else
constexpr bool kEnableAsmCode = false;
inline constexpr bool kEnableAsmCode = true;
#endif
// Forces a crash, like a CHECK(false). Used for numeric boundary errors.
// Forces a crash, like a NOTREACHED(). Used for numeric boundary errors.
// Also used in a constexpr template to trigger a compilation failure on
// an error condition.
struct CheckOnFailure {

View file

@ -18,6 +18,7 @@
#define PARTITION_ALLOC_PARTITION_ALLOC_BASE_POSIX_EINTR_WRAPPER_H_
#include "partition_alloc/build_config.h"
#include "partition_alloc/buildflags.h"
#if PA_BUILDFLAG(IS_POSIX)
#include <cerrno>
@ -31,7 +32,7 @@ template <typename Fn>
inline auto WrapEINTR(Fn fn) {
return [fn](auto&&... args) {
int out = -1;
#if defined(NDEBUG)
#if !PA_BUILDFLAG(IS_DEBUG)
while (true)
#else
for (int retry_count = 0; retry_count < 100; ++retry_count)

View file

@ -10,8 +10,9 @@
#include <limits>
#include "partition_alloc/build_config.h"
#include "partition_alloc/buildflags.h"
#if !defined(NDEBUG)
#if PA_BUILDFLAG(IS_DEBUG)
// In debug builds, we use RAW_CHECK() to print useful error messages, if
// SafeSPrintf() is called with broken arguments.
// As our contract promises that SafeSPrintf() can be called from any
@ -41,7 +42,7 @@
if (x) { \
} \
} while (0)
#endif
#endif // PA_BUILDFLAG(IS_DEBUG)
namespace partition_alloc::internal::base::strings {
@ -74,7 +75,7 @@ const char kUpCaseHexDigits[] = "0123456789ABCDEF";
const char kDownCaseHexDigits[] = "0123456789abcdef";
} // namespace
#if defined(NDEBUG)
#if !PA_BUILDFLAG(IS_DEBUG)
// We would like to define kSSizeMax as std::numeric_limits<ssize_t>::max(),
// but C++ doesn't allow us to do that for constants. Instead, we have to
// use careful casting and shifting. We later use a static_assert to
@ -82,7 +83,7 @@ const char kDownCaseHexDigits[] = "0123456789abcdef";
namespace {
const size_t kSSizeMax = kSSizeMaxConst;
}
#else // defined(NDEBUG)
#else // !PA_BUILDFLAG(IS_DEBUG)
// For efficiency, we really need kSSizeMax to be a constant. But for unit
// tests, it should be adjustable. This allows us to verify edge cases without
// having to fill the entire available address space. As a compromise, we make
@ -101,7 +102,7 @@ size_t GetSafeSPrintfSSizeMaxForTest() {
return kSSizeMax;
}
} // namespace internal
#endif // defined(NDEBUG)
#endif // !PA_BUILDFLAG(IS_DEBUG)
namespace {
class Buffer {
@ -111,10 +112,7 @@ class Buffer {
// to ensure that the buffer is at least one byte in size, so that it fits
// the trailing NUL that will be added by the destructor. The buffer also
// must be smaller or equal to kSSizeMax in size.
Buffer(char* buffer, size_t size)
: buffer_(buffer),
size_(size - 1), // Account for trailing NUL byte
count_(0) {
Buffer(char* buffer, size_t size) : buffer_(buffer), size_(size - 1) {
// MSVS2013's standard library doesn't mark max() as constexpr yet. cl.exe
// supports static_cast but doesn't really implement constexpr yet so it doesn't
// complain, but clang does.
@ -276,7 +274,7 @@ class Buffer {
// Number of bytes that would have been emitted to the buffer, if the buffer
// was sufficiently big. This number always excludes the trailing NUL byte
// and it is guaranteed to never grow bigger than kSSizeMax-1.
size_t count_;
size_t count_ = 0;
};
bool Buffer::IToASCII(bool sign,

View file

@ -20,6 +20,7 @@
#if PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS)
#include <sys/syscall.h>
#include <atomic>
#endif
@ -27,6 +28,10 @@
#include <zircon/process.h>
#endif
#if defined(__MUSL__)
#include "partition_alloc/shim/allocator_shim.h"
#endif
namespace partition_alloc::internal::base {
#if PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS)
@ -58,7 +63,22 @@ thread_local bool g_is_main_thread = true;
class InitAtFork {
public:
InitAtFork() {
#if defined(__MUSL__)
allocator_shim::AllocatorDispatch d =
*allocator_shim::GetAllocatorDispatchChainHeadForTesting();
d.alloc_function = +[](size_t size, void*) -> void* {
// The size of the scratch fits struct atfork_funcs in Musl pthread_atfork.c.
static char scratch[5 * sizeof(void*)];
return size != sizeof(scratch) ? nullptr : scratch;
};
allocator_shim::InsertAllocatorDispatch(&d);
#endif
pthread_atfork(nullptr, nullptr, internal::InvalidateTidCache);
#if defined(__MUSL__)
allocator_shim::RemoveAllocatorDispatchForTesting(&d);
#endif
}
};

View file

@ -0,0 +1,19 @@
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_TYPES_SAME_AS_ANY_H_
#define PARTITION_ALLOC_PARTITION_ALLOC_BASE_TYPES_SAME_AS_ANY_H_
#include <type_traits>
namespace partition_alloc::internal::base {
// True when `T` is any of the subsequent types.
// TODO(crbug.com/344963951): Switch to a concept when C++20 is allowed.
template <typename T, typename... Ts>
inline constexpr bool kSameAsAny = (std::is_same_v<T, Ts> || ...);
} // namespace partition_alloc::internal::base
#endif // PARTITION_ALLOC_PARTITION_ALLOC_BASE_TYPES_SAME_AS_ANY_H_

View file

@ -10,6 +10,7 @@
// Needed for function prototypes.
#include <specstrings.h>
#include <cstdint>
#ifdef __cplusplus
@ -41,6 +42,11 @@ typedef DWORD ULONG;
typedef unsigned short WORD;
typedef WORD UWORD;
typedef WORD ATOM;
#if defined(_WIN64)
typedef int64_t PA_LONG_PTR, *PA_PLONG_PTR;
#else
typedef int32_t PA_LONG_PTR, *PA_PLONG_PTR;
#endif
// Forward declare some Windows struct/typedef sets.
@ -53,6 +59,16 @@ struct PA_CHROME_SRWLOCK {
PVOID Ptr;
};
// Define some commonly used Windows constants. Note that the layout of these
// macros - including internal spacing - must be 100% consistent with windows.h.
// clang-format off
#ifndef INVALID_HANDLE_VALUE
// Work around there being two slightly different definitions in the SDK.
#define INVALID_HANDLE_VALUE ((HANDLE)(PA_LONG_PTR)-1)
#endif
// The trailing white-spaces after this macro are required, for compatibility
// with the definition in winnt.h.
// clang-format off

View file

@ -61,11 +61,11 @@
// Expensive dchecks that run within *Scan. These checks are only enabled in
// debug builds with dchecks enabled.
#if !defined(NDEBUG)
#if PA_BUILDFLAG(IS_DEBUG)
#define PA_SCAN_DCHECK_IS_ON() PA_BUILDFLAG(DCHECKS_ARE_ON)
#else
#define PA_SCAN_DCHECK_IS_ON() 0
#endif
#endif // PA_BUILDFLAG(IS_DEBUG)
#if PA_SCAN_DCHECK_IS_ON()
#define PA_SCAN_DCHECK(expr) PA_DCHECK(expr)

View file

@ -63,9 +63,7 @@ enum class FreeFlags {
kNoHooks = 1 << 1, // Internal.
// Quarantine for a while to ensure no UaF from on-stack pointers.
kSchedulerLoopQuarantine = 1 << 2,
// Zap the object region on `Free()`.
kZap = 1 << 3,
kMaxValue = kZap,
kMaxValue = kSchedulerLoopQuarantine,
};
PA_DEFINE_OPERATORS_FOR_FLAGS(FreeFlags);
} // namespace internal

View file

@ -223,6 +223,18 @@ SlotSpanMetadata<MetadataKind::kReadOnly>* PartitionDirectMap(
PartitionPageMetadata<MetadataKind::kReadOnly>* page_metadata = nullptr;
{
#if PA_CONFIG(ENABLE_SHADOW_METADATA)
// Because of the performance reason, PartitionRoot's lock is unlocked
// here. However this causes multi-thread issue when running
// EnableShadowMetadata(). If some thread is running PartitionDirectMap()
// and unlock PartitionRoot lock and also another thread is running
// EnableShadowMetadata(), the metadata page's permission will be modified
// by both threads and chrome will crash. c.f. crbug.com/378809882
// Be careful. This should not block PartitionDirectMap() in another thread.
internal::SharedLock shared_lock(
PartitionRoot::g_shadow_metadata_init_mutex_);
#endif // PA_CONFIG(ENABLE_SHADOW_METADATA)
// Getting memory for direct-mapped allocations doesn't interact with the
// rest of the allocator, but takes a long time, as it involves several
// system calls. Although no mmap() (or equivalent) calls are made on
@ -672,7 +684,7 @@ PartitionBucket::AllocNewSlotSpan(PartitionRoot* root,
for (auto* page = gap_start_page->ToWritable(root);
page < gap_end_page->ToWritable(root); ++page) {
PA_DCHECK(!page->is_valid);
page->has_valid_span_after_this = 1;
page->has_valid_span_after_this = true;
}
root->next_partition_page =
adjusted_next_partition_page + slot_span_reservation_size;
@ -696,7 +708,7 @@ PartitionBucket::AllocNewSlotSpan(PartitionRoot* root,
PA_DEBUG_DATA_ON_STACK("spancmt", slot_span_committed_size);
root->RecommitSystemPagesForData(
slot_span_start, slot_span_committed_size,
slot_span_start, SlotSpanCommittedSize(root),
PageAccessibilityDisposition::kRequireUpdate,
slot_size <= kMaxMemoryTaggingSize);
}
@ -1578,4 +1590,63 @@ void PartitionBucket::InitializeSlotSpanForGwpAsan(
InitializeSlotSpan(slot_span, root);
}
size_t PartitionBucket::SlotSpanCommittedSize(PartitionRoot* root) const {
// With lazy commit, we certainly don't want to commit more than
// necessary. This is not reached, but keep the CHECK() as documentation.
PA_CHECK(!kUseLazyCommit);
// Memory is reserved in units of PartitionPage, but a given slot span may be
// smaller than the reserved area. For instance (assuming 4k pages), for a
// bucket where the slot span size is 40kiB, we reserve 4 PartitionPage = 16 *
// 4 = 48kiB, but only ever commit 40kiB out of it.
//
// This means that the address space then looks like, assuming that the
// PartitionPage next to it is committed:
// [SlotSpan range, 40kiB] rw-p
// [Unused area in the last PartitionPage, 8kiB] ---p
// [Next PartitionPages, size unknown ] rw-p
//
// So we have a "hole" of inaccessible memory, and 3 memory regions. If
// instead we commit the full PartitionPages, we get (due to the kernel
// merging neighboring regions with uniform permissions):
//
// [SlotSpan range, 40kiB + Unused area, 8kiB + next PartitionPages] rw-p
//
// So 1 memory region rather then 3. This matters, because on Linux kernels,
// there is a maximum number of VMAs per process, with the default limit a bit
// less than 2^16, and Chromium sometimes hits the limit (see
// /proc/sys/vm/max_map_count for the current limit), largely because of
// PartitionAlloc contributing thousands of regions. Locally, on a Linux
// system, this reduces the number of PartitionAlloc regions by up to ~4x.
//
// Why is it safe?
// The extra memory is not used by anything, so committing it doesn't make a
// difference. It makes it accessible though.
//
// How much does it cost?
// Almost nothing. On Linux, "committing" memory merely changes its
// permissions, it doesn't cost any memory until the pages are touched, which
// they are not. However, mprotect()-ed areas that are writable count towards
// the RLIMIT_DATA resource limit, which is used by the sandbox. So, while
// this change costs 0 physical memory (and actually saves some, by reducing
// the size of the VMA red-black tree in the kernel), it might increase
// slightly the cases where we bump into the sandbox memory limit.
//
// Is it safe to do while running?
// Since this is decided through root settings, the value changes at runtime,
// so we may decommit memory that was never committed. This is safe onLinux,
// since decommitting is just changing permissions back to PROT_NONE, which
// the tail end would already have.
//
// Can we do better?
// For simplicity, we do not "fix" the regions that were committed before the
// settings are changed (after feature list initialization). This means that
// we end up with more regions that we could. The intent is to run a field
// experiment, then change the default value, at which point we get the full
// impact, so this is only temporary.
return root->settings.fewer_memory_regions
? (get_pages_per_slot_span() << PartitionPageShift())
: get_bytes_per_span();
}
} // namespace partition_alloc::internal

View file

@ -1,7 +1,6 @@
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PARTITION_ALLOC_PARTITION_BUCKET_H_
#define PARTITION_ALLOC_PARTITION_BUCKET_H_
@ -171,6 +170,8 @@ struct PartitionBucket {
SlotSpanMetadata<MetadataKind::kReadOnly>* slot_span,
PartitionRoot* root);
size_t SlotSpanCommittedSize(PartitionRoot* root) const;
private:
// Sets `this->can_store_raw_size`.
void InitCanStoreRawSize(bool use_small_single_slot_spans);

View file

@ -248,7 +248,7 @@ void SlotSpanMetadata<MetadataKind::kWritable>::Decommit(PartitionRoot* root) {
size_t dirty_size =
base::bits::AlignUp(GetProvisionedSize(), SystemPageSize());
size_t size_to_decommit =
kUseLazyCommit ? dirty_size : bucket->get_bytes_per_span();
kUseLazyCommit ? dirty_size : bucket->SlotSpanCommittedSize(root);
PA_DCHECK(root->empty_slot_spans_dirty_bytes >= dirty_size);
root->empty_slot_spans_dirty_bytes -= dirty_size;

View file

@ -938,8 +938,7 @@ PA_ALWAYS_INLINE void SlotSpanMetadata<MetadataKind::kWritable>::Reset() {
// Iterates over all slot spans in a super-page. |Callback| must return true if
// early return is needed.
template <typename Callback>
void IterateSlotSpans(uintptr_t super_page,
Callback callback) {
void IterateSlotSpans(uintptr_t super_page, Callback callback) {
#if PA_BUILDFLAG(DCHECKS_ARE_ON)
PA_DCHECK(!(super_page % kSuperPageAlignment));
auto* extent_entry = PartitionSuperPageToExtent(super_page);

View file

@ -17,7 +17,7 @@ namespace partition_alloc::internal {
// PartitionPageSize() is 4 times the OS page size.
static constexpr size_t kMaxSlotsPerSlotSpan = 4 * (1 << 14) / kSmallestBucket;
#elif defined(PARTITION_ALLOCATOR_CONSTANTS_POSIX_NONCONST_PAGE_SIZE) && \
PA_BUILDFLAG(IS_LINUX) && \
PA_BUILDFLAG(IS_LINUX) && \
(PA_BUILDFLAG(PA_ARCH_CPU_ARM64) || PA_BUILDFLAG(PA_ARCH_CPU_PPC64))
// System page size can be 4, 16, or 64 kiB on Linux on AArch64.
// System page size can be 4 or 64 kiB on Linux on ppc64.

View file

@ -51,6 +51,10 @@
#endif // PA_CONFIG(ENABLE_SHADOW_METADATA)
#endif // PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS)
#if defined(__MUSL__)
#include "partition_alloc/shim/allocator_shim.h"
#endif
namespace partition_alloc::internal {
#if PA_BUILDFLAG(RECORD_ALLOC_INFO)
@ -105,6 +109,10 @@ PtrPosWithinAlloc IsPtrWithinSameAlloc(uintptr_t orig_address,
namespace partition_alloc {
#if PA_CONFIG(ENABLE_SHADOW_METADATA)
internal::SharedMutex PartitionRoot::g_shadow_metadata_init_mutex_;
#endif // PA_CONFIG(ENABLE_SHADOW_METADATA)
#if PA_CONFIG(USE_PARTITION_ROOT_ENUMERATOR)
namespace {
@ -293,12 +301,7 @@ void PartitionAllocMallocInitOnce() {
return;
}
#if defined(__MUSL__)
// Musl calls malloc() in pthread_atfork(), resulting in a deadlock.
static_cast<void>(BeforeForkInParent);
static_cast<void>(AfterForkInParent);
static_cast<void>(AfterForkInChild);
#elif PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS)
#if PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS)
// When fork() is called, only the current thread continues to execute in the
// child process. If the lock is held, but *not* by this thread when fork() is
// called, we have a deadlock.
@ -320,9 +323,25 @@ void PartitionAllocMallocInitOnce() {
// However, no perfect solution really exists to make threads + fork()
// cooperate, but deadlocks are real (and fork() is used in DEATH_TEST()s),
// and other malloc() implementations use the same techniques.
#if defined(__MUSL__)
allocator_shim::AllocatorDispatch d =
*allocator_shim::GetAllocatorDispatchChainHeadForTesting();
d.alloc_function = +[](size_t size, void*) -> void* {
// The size of the scratch fits struct atfork_funcs in Musl pthread_atfork.c.
static char scratch[5 * sizeof(void*)];
return size != sizeof(scratch) ? nullptr : scratch;
};
allocator_shim::InsertAllocatorDispatch(&d);
#endif
int err =
pthread_atfork(BeforeForkInParent, AfterForkInParent, AfterForkInChild);
PA_CHECK(err == 0);
#if defined(__MUSL__)
allocator_shim::RemoveAllocatorDispatchForTesting(&d);
#endif
#endif // PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS)
}
@ -1155,6 +1174,8 @@ void PartitionRoot::Init(PartitionOptions opts) {
opts.zapping_by_free_flags == PartitionOptions::kEnabled;
settings.eventually_zero_freed_memory =
opts.eventually_zero_freed_memory == PartitionOptions::kEnabled;
settings.fewer_memory_regions =
opts.fewer_memory_regions == PartitionOptions::kEnabled;
settings.scheduler_loop_quarantine =
opts.scheduler_loop_quarantine == PartitionOptions::kEnabled;
@ -1219,6 +1240,7 @@ void PartitionRoot::Init(PartitionOptions opts) {
if (brp_enabled()) {
settings.in_slot_metadata_size = internal::kInSlotMetadataSizeAdjustment;
settings.extras_size += internal::kInSlotMetadataSizeAdjustment;
settings.extras_size += opts.backup_ref_ptr_extra_extras_size;
#if PA_CONFIG(MAYBE_ENABLE_MAC11_MALLOC_SIZE_HACK)
EnableMac11MallocSizeHackIfNeeded();
#endif
@ -1352,6 +1374,9 @@ void PartitionRoot::EnableThreadCacheIfSupported() {
thread_caches_being_constructed_.fetch_add(1, std::memory_order_acquire);
PA_CHECK(before == 0);
ThreadCache::Init(this);
// Create thread cache for this thread so that we can start using it right
// after.
ThreadCache::Create(this);
thread_caches_being_constructed_.fetch_sub(1, std::memory_order_release);
settings.with_thread_cache = true;
#endif // PA_CONFIG(THREAD_CACHE_SUPPORTED)
@ -1971,6 +1996,7 @@ void PartitionRoot::EnableShadowMetadata(internal::PoolHandleMask mask) {
// This is required to enable ShadowMetadata on utility processes.
{ close(memfd_create("module_cache", MFD_CLOEXEC)); }
#endif
internal::UniqueLock unique_lock(g_shadow_metadata_init_mutex_);
internal::ScopedGuard guard(g_root_enumerator_lock);
// Must lock all PartitionRoot-s and ThreadCache.

View file

@ -71,6 +71,7 @@
#include "partition_alloc/partition_lock.h"
#include "partition_alloc/partition_oom.h"
#include "partition_alloc/partition_page.h"
#include "partition_alloc/partition_shared_mutex.h"
#include "partition_alloc/reservation_offset_table.h"
#include "partition_alloc/tagging.h"
#include "partition_alloc/thread_cache.h"
@ -165,10 +166,12 @@ struct PartitionOptions {
static constexpr auto kEnabled = EnableToggle::kEnabled;
EnableToggle thread_cache = kDisabled;
AllowToggle star_scan_quarantine = kDisallowed;
EnableToggle backup_ref_ptr = kDisabled;
AllowToggle use_configurable_pool = kDisallowed;
// TODO(https://crbug.com/371135823): Remove after the investigation.
size_t backup_ref_ptr_extra_extras_size = 0;
EnableToggle scheduler_loop_quarantine = kDisabled;
size_t scheduler_loop_quarantine_branch_capacity_in_bytes = 0;
@ -179,6 +182,7 @@ struct PartitionOptions {
// compression ratio of freed memory inside partially allocated pages (due to
// fragmentation).
EnableToggle eventually_zero_freed_memory = kDisabled;
EnableToggle fewer_memory_regions = kDisabled;
struct {
EnableToggle enabled = kDisabled;
@ -258,9 +262,14 @@ struct alignas(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot {
size_t in_slot_metadata_size = 0;
#endif // PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
bool use_configurable_pool = false;
// Despite its name, `FreeFlags` for zapping is deleted and does not exist.
// This value is used for SchedulerLoopQuarantine.
// TODO(https://crbug.com/351974425): group this setting and quarantine
// setting in one place.
bool zapping_by_free_flags = false;
bool eventually_zero_freed_memory = false;
bool scheduler_loop_quarantine = false;
bool fewer_memory_regions = false;
#if PA_BUILDFLAG(HAS_MEMORY_TAGGING)
bool memory_tagging_enabled_ = false;
bool use_random_memory_tagging_ = false;
@ -387,6 +396,12 @@ struct alignas(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot {
internal::base::TimeTicks (*now_maybe_overridden_for_testing)() =
internal::base::TimeTicks::Now;
#if PA_CONFIG(ENABLE_SHADOW_METADATA)
// Locks not to run EnableShadowMetadata() and PartitionDirectMap()
// at the same time.
static internal::SharedMutex g_shadow_metadata_init_mutex_;
#endif // PA_CONFIG(ENABLE_SHADOW_METADATA)
PartitionRoot();
explicit PartitionRoot(PartitionOptions opts);
@ -884,6 +899,14 @@ struct alignas(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot {
return GetSchedulerLoopQuarantineBranch();
}
void SetSchedulerLoopQuarantineThreadLocalBranchCapacity(
size_t capacity_in_bytes) {
ThreadCache* thread_cache = this->GetOrCreateThreadCache();
PA_CHECK(ThreadCache::IsValid(thread_cache));
thread_cache->GetSchedulerLoopQuarantineBranch().SetCapacityInBytes(
capacity_in_bytes);
}
const internal::PartitionFreelistDispatcher* get_freelist_dispatcher() {
#if PA_BUILDFLAG(USE_FREELIST_DISPATCHER)
if (settings.use_pool_offset_freelists) {
@ -1499,16 +1522,11 @@ PA_ALWAYS_INLINE void PartitionRoot::FreeInline(void* object) {
// cacheline ping-pong.
PA_PREFETCH(slot_span);
// Further down, we may zap the memory, no point in doing it twice. We may
// zap twice if kZap is enabled without kSchedulerLoopQuarantine. Make sure it
// does not happen. This is not a hard requirement: if this is deemed cheap
// enough, it can be relaxed, the static_assert() is here to make it a
// conscious decision.
static_assert(!ContainsFlags(flags, FreeFlags::kZap) ||
ContainsFlags(flags, FreeFlags::kSchedulerLoopQuarantine),
"kZap and kSchedulerLoopQuarantine should be used together to "
"avoid double zapping");
if constexpr (ContainsFlags(flags, FreeFlags::kZap)) {
// TODO(crbug.com/40287058): Collecting objects for
// `kSchedulerLoopQuarantineBranch` here means it "delays" other checks (BRP
// refcount, cookie, etc.)
// For better debuggability, we should do these checks before quarantining.
if constexpr (ContainsFlags(flags, FreeFlags::kSchedulerLoopQuarantine)) {
// No need to zap direct mapped allocations, as they are unmapped right
// away. This also ensures that we don't needlessly memset() very large
// allocations.
@ -1517,12 +1535,7 @@ PA_ALWAYS_INLINE void PartitionRoot::FreeInline(void* object) {
internal::SecureMemset(object, internal::kFreedByte,
GetSlotUsableSize(slot_span));
}
}
// TODO(crbug.com/40287058): Collecting objects for
// `kSchedulerLoopQuarantineBranch` here means it "delays" other checks (BRP
// refcount, cookie, etc.)
// For better debuggability, we should do these checks before quarantining.
if constexpr (ContainsFlags(flags, FreeFlags::kSchedulerLoopQuarantine)) {
if (settings.scheduler_loop_quarantine) {
#if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
// TODO(keishi): Add `[[likely]]` when brp is fully enabled as

View file

@ -0,0 +1,82 @@
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PARTITION_ALLOC_PARTITION_SHARED_MUTEX_H_
#define PARTITION_ALLOC_PARTITION_SHARED_MUTEX_H_
#include "partition_alloc/partition_alloc_base/thread_annotations.h"
#include "partition_alloc/partition_lock.h"
namespace partition_alloc::internal {
// A partial implementation of `std::shared_mutex` for PartitionAllocator.
// Since `std::shared_mutex` allocates memory, we cannot use it inside
// PartitionAllocator. The difference between `std::shared_mutex` and this
// SharedMutex, this SharedMutex doesn't support try_lock() and
// try_lock_shared(), because no code uses the methods.
class PA_LOCKABLE SharedMutex {
public:
inline constexpr SharedMutex() = default;
void lock() PA_EXCLUSIVE_LOCK_FUNCTION() { writer_lock_.Acquire(); }
void unlock() PA_UNLOCK_FUNCTION() { writer_lock_.Release(); }
void lock_shared() PA_SHARED_LOCK_FUNCTION() {
ScopedGuard lock(reader_lock_);
++counter_;
if (counter_ == 1u) {
writer_lock_.Acquire();
}
}
void unlock_shared() PA_UNLOCK_FUNCTION() {
ScopedGuard lock(reader_lock_);
--counter_;
if (counter_ == 0u) {
writer_lock_.Release();
}
}
private:
Lock reader_lock_;
Lock writer_lock_;
size_t counter_ PA_GUARDED_BY(reader_lock_) = 0;
};
static_assert(std::is_trivially_destructible_v<SharedMutex>,
"SharedMutex must be trivally destructible.");
// A partial implementation of `std::unique_lock` for PartitionAllocator.
// Locking a UniqueLock locks the associated shared mutex in exclusive mode.
class PA_SCOPED_LOCKABLE UniqueLock {
public:
explicit UniqueLock(SharedMutex& mutex) PA_EXCLUSIVE_LOCK_FUNCTION(mutex)
: mutex_(mutex) {
mutex_.lock();
}
~UniqueLock() PA_UNLOCK_FUNCTION() { mutex_.unlock(); }
private:
SharedMutex& mutex_;
};
// A partial implementation of `std::shared_lock` for PartitionAllocator.
// Locking a SharedLock locks the associated shared mutex in shared mode.
// (like std::shared_lock).
class PA_SCOPED_LOCKABLE SharedLock {
public:
explicit SharedLock(SharedMutex& mutex) PA_SHARED_LOCK_FUNCTION(mutex)
: mutex_(mutex) {
mutex_.lock_shared();
}
~SharedLock() PA_UNLOCK_FUNCTION() { mutex_.unlock_shared(); }
private:
SharedMutex& mutex_;
};
} // namespace partition_alloc::internal
#endif // PARTITION_ALLOC_PARTITION_SHARED_MUTEX_H_

View file

@ -10,6 +10,8 @@
#include <cstddef>
#include <cstdint>
#include <functional>
#include <iterator>
#include <memory>
#include <type_traits>
#include <utility>
@ -20,6 +22,7 @@
#include "partition_alloc/partition_alloc_base/compiler_specific.h"
#include "partition_alloc/partition_alloc_base/component_export.h"
#include "partition_alloc/partition_alloc_base/cxx20_is_constant_evaluated.h"
#include "partition_alloc/partition_alloc_base/types/same_as_any.h"
#include "partition_alloc/partition_alloc_config.h"
#include "partition_alloc/partition_alloc_forward.h"
#include "partition_alloc/pointers/instance_tracer.h"
@ -69,7 +72,7 @@ class TextureLayerImpl;
namespace base::internal {
class DelayTimerBase;
class JobTaskSource;
}
} // namespace base::internal
namespace base::test {
struct RawPtrCountingImplForTest;
}
@ -175,84 +178,29 @@ namespace raw_ptr_traits {
// that raw_ptr is not used with unsupported types. As an example, see how
// base::internal::Unretained(Ref)Wrapper uses IsSupportedType to decide whether
// it should use `raw_ptr<T>` or `T*`.
template <typename T, typename SFINAE = void>
struct IsSupportedType {
static constexpr bool value = true;
};
// raw_ptr<T> is not compatible with function pointer types. Also, they don't
// even need the raw_ptr protection, because they don't point on heap.
template <typename T>
struct IsSupportedType<T, std::enable_if_t<std::is_function_v<T>>> {
static constexpr bool value = false;
};
// This section excludes some types from raw_ptr<T> to avoid them from being
// used inside base::Unretained in performance sensitive places.
// The ones below were identified from sampling profiler data. See
// crbug.com/1287151 for more info.
template <>
struct IsSupportedType<cc::Scheduler> {
static constexpr bool value = false;
};
template <>
struct IsSupportedType<base::internal::DelayTimerBase> {
static constexpr bool value = false;
};
template <>
struct IsSupportedType<content::responsiveness::Calculator> {
static constexpr bool value = false;
};
// The ones below were identified from speedometer3. See crbug.com/335556942 for
// more info.
template <>
struct IsSupportedType<v8::JobTask> {
static constexpr bool value = false;
};
template <>
struct IsSupportedType<blink::scheduler::MainThreadTaskQueue> {
static constexpr bool value = false;
};
template <>
struct IsSupportedType<base::sequence_manager::internal::TaskQueueImpl> {
static constexpr bool value = false;
};
template <>
struct IsSupportedType<base::internal::JobTaskSource> {
static constexpr bool value = false;
};
template <>
struct IsSupportedType<mojo::Connector> {
static constexpr bool value = false;
};
template <>
struct IsSupportedType<blink::scheduler::NonMainThreadTaskQueue> {
static constexpr bool value = false;
};
// The ones below were identified from MotionMark. See crbug.com/335556942 for
// more info.
template <>
struct IsSupportedType<cc::ImageDecodeCache> {
static constexpr bool value = false;
};
template <>
struct IsSupportedType<cc::TextureLayerImpl> {
static constexpr bool value = false;
};
struct IsSupportedType {
static constexpr bool value =
// raw_ptr<T> is not compatible with function pointer types. Also, they
// don't even need the raw_ptr protection, because they don't point on
// heap.
!std::is_function_v<T> &&
#if __OBJC__
// raw_ptr<T> is not compatible with pointers to Objective-C classes for a
// multitude of reasons. They may fail to compile in many cases, and wouldn't
// work well with tagged pointers. Anyway, Objective-C objects have their own
// way of tracking lifespan, hence don't need the raw_ptr protection as much.
//
// Such pointers are detected by checking if they're convertible to |id| type.
template <typename T>
struct IsSupportedType<T, std::enable_if_t<std::is_convertible_v<T*, id>>> {
static constexpr bool value = false;
};
// raw_ptr<T> is not compatible with pointers to Objective-C classes for a
// multitude of reasons. They may fail to compile in many cases, and
// wouldn't work well with tagged pointers. Anyway, Objective-C objects
// have their own way of tracking lifespan, hence don't need the raw_ptr
// protection as much.
//
// Such pointers are detected by checking if they're convertible to |id|
// type.
!std::is_convertible_v<T*, id> &&
#endif // __OBJC__
// Specific disallowed types.
!partition_alloc::internal::base::kSameAsAny<
T,
#if PA_BUILDFLAG(IS_WIN)
// raw_ptr<HWND__> is unsafe at runtime - if the handle happens to also
// represent a valid pointer into a PartitionAlloc-managed region then it can
@ -268,14 +216,30 @@ struct IsSupportedType<T, std::enable_if_t<std::is_convertible_v<T*, id>>> {
// upside of this approach is that it will safely handle base::Bind closing over
// HANDLE. The downside of this approach is that base::Bind closing over a
// void* pointer will not get UaF protection.
#define PA_WINDOWS_HANDLE_TYPE(name) \
template <> \
struct IsSupportedType<name##__, void> { \
static constexpr bool value = false; \
};
#define PA_WINDOWS_HANDLE_TYPE(name) name##__,
#include "partition_alloc/partition_alloc_base/win/win_handle_types_list.inc"
#undef PA_WINDOWS_HANDLE_TYPE
#endif
// Performance-sensitive types identified via sampling profiler data;
// see crbug.com/1287151
base::internal::DelayTimerBase,
cc::Scheduler,
content::responsiveness::Calculator,
// Performance-sensitive types identified via speedometer3; see
// crbug.com/335556942
base::internal::JobTaskSource,
base::sequence_manager::internal::TaskQueueImpl,
blink::scheduler::MainThreadTaskQueue,
blink::scheduler::NonMainThreadTaskQueue,
mojo::Connector,
v8::JobTask,
// Performance-sensitive types identified via MotionMark; see
// crbug.com/335556942
cc::ImageDecodeCache,
cc::TextureLayerImpl>;
};
#if PA_BUILDFLAG(USE_RAW_PTR_BACKUP_REF_IMPL)
template <RawPtrTraits Traits>
@ -1102,51 +1066,32 @@ PA_ALWAYS_INLINE constexpr bool operator>=(const raw_ptr<U, Traits1>& lhs,
#endif
template <typename T>
struct IsRawPtr : std::false_type {};
inline constexpr bool IsRawPtr = false;
template <typename T, RawPtrTraits Traits>
struct IsRawPtr<raw_ptr<T, Traits>> : std::true_type {};
inline constexpr bool IsRawPtr<raw_ptr<T, Traits>> = true;
template <typename T>
inline constexpr bool IsRawPtrV = IsRawPtr<T>::value;
template <typename T>
inline constexpr bool IsRawPtrMayDangleV = false;
inline constexpr bool IsRawPtrMayDangle = false;
template <typename T, RawPtrTraits Traits>
inline constexpr bool IsRawPtrMayDangleV<raw_ptr<T, Traits>> =
inline constexpr bool IsRawPtrMayDangle<raw_ptr<T, Traits>> =
partition_alloc::internal::ContainsFlags(Traits, RawPtrTraits::kMayDangle);
// Template helpers for working with T* or raw_ptr<T>.
template <typename T>
struct IsRawPointerHelper : std::false_type {};
template <typename T>
struct IsRawPointerHelper<T*> : std::true_type {};
inline constexpr bool IsPointerOrRawPtr = std::is_pointer_v<T>;
template <typename T, RawPtrTraits Traits>
struct IsRawPointerHelper<raw_ptr<T, Traits>> : std::true_type {};
inline constexpr bool IsPointerOrRawPtr<raw_ptr<T, Traits>> = true;
// Like `std::remove_pointer_t<>`, but also converts `raw_ptr<T>` => `T`.
template <typename T>
inline constexpr bool IsRawPointer = IsRawPointerHelper<T>::value;
template <typename T>
struct RemoveRawPointer {
using type = T;
struct RemovePointer {
using type = std::remove_pointer_t<T>;
};
template <typename T>
struct RemoveRawPointer<T*> {
using type = T;
};
template <typename T, RawPtrTraits Traits>
struct RemoveRawPointer<raw_ptr<T, Traits>> {
struct RemovePointer<raw_ptr<T, Traits>> {
using type = T;
};
template <typename T>
using RemoveRawPointerT = typename RemoveRawPointer<T>::type;
using RemovePointerT = typename RemovePointer<T>::type;
} // namespace base
@ -1310,6 +1255,36 @@ struct pointer_traits<::raw_ptr<T, Traits>> {
}
};
// Mark `raw_ptr<T>` and `T*` as having a common reference type (the type to
// which both can be converted or bound) of `T*`. This makes them satisfy
// `std::equality_comparable`, which allows usage like:
// ```
// std::vector<raw_ptr<T>> v;
// T* e;
// auto it = std::ranges::find(v, e);
// ```
// Without this, the `find()` call above would fail to compile with a cryptic
// error about being unable to invoke `std::ranges::equal_to()`.
template <typename T,
base::RawPtrTraits Traits,
template <typename>
typename TQ,
template <typename>
typename UQ>
struct std::basic_common_reference<raw_ptr<T, Traits>, T*, TQ, UQ> {
using type = T*;
};
template <typename T,
base::RawPtrTraits Traits,
template <typename>
typename TQ,
template <typename>
typename UQ>
struct std::basic_common_reference<T*, raw_ptr<T, Traits>, TQ, UQ> {
using type = T*;
};
} // namespace std
#endif // PARTITION_ALLOC_POINTERS_RAW_PTR_H_

View file

@ -5,6 +5,7 @@
#include "partition_alloc/pointers/raw_ptr_asan_unowned_impl.h"
#include <sanitizer/asan_interface.h>
#include <cstdint>
#include "partition_alloc/partition_alloc_base/compiler_specific.h"

View file

@ -26,18 +26,10 @@ namespace base {
template <class T, RawPtrTraits Traits>
class raw_ref;
namespace internal {
template <class T>
struct is_raw_ref : std::false_type {};
inline constexpr bool IsRawRef = false;
template <class T, RawPtrTraits Traits>
struct is_raw_ref<::base::raw_ref<T, Traits>> : std::true_type {};
template <class T>
constexpr inline bool is_raw_ref_v = is_raw_ref<T>::value;
} // namespace internal
inline constexpr bool IsRawRef<::base::raw_ref<T, Traits>> = true;
// A smart pointer for a pointer which can not be null, and which provides
// Use-after-Free protection in the same ways as raw_ptr. This class acts like a
@ -256,25 +248,25 @@ class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ref {
const raw_ref<V, Traits2>& rhs);
#endif
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
template <class U, class = std::enable_if_t<!IsRawRef<U>, void>>
PA_ALWAYS_INLINE friend constexpr bool operator==(const raw_ref& lhs,
const U& rhs) {
PA_RAW_PTR_CHECK(lhs.inner_); // Catch use-after-move.
return lhs.inner_ == &rhs;
}
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
template <class U, class = std::enable_if_t<!IsRawRef<U>, void>>
PA_ALWAYS_INLINE friend constexpr bool operator!=(const raw_ref& lhs,
const U& rhs) {
PA_RAW_PTR_CHECK(lhs.inner_); // Catch use-after-move.
return lhs.inner_ != &rhs;
}
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
template <class U, class = std::enable_if_t<!IsRawRef<U>, void>>
PA_ALWAYS_INLINE friend constexpr bool operator==(const U& lhs,
const raw_ref& rhs) {
PA_RAW_PTR_CHECK(rhs.inner_); // Catch use-after-move.
return &lhs == rhs.inner_;
}
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
template <class U, class = std::enable_if_t<!IsRawRef<U>, void>>
PA_ALWAYS_INLINE friend constexpr bool operator!=(const U& lhs,
const raw_ref& rhs) {
PA_RAW_PTR_CHECK(rhs.inner_); // Catch use-after-move.
@ -282,62 +274,62 @@ class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ref {
}
#if PA_HAVE_SPACESHIP_OPERATOR
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
template <class U, class = std::enable_if_t<!IsRawRef<U>, void>>
PA_ALWAYS_INLINE friend constexpr auto operator<=>(const raw_ref& lhs,
const U& rhs) {
PA_RAW_PTR_CHECK(lhs.inner_); // Catch use-after-move.
return lhs.inner_ <=> &rhs;
}
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
template <class U, class = std::enable_if_t<!IsRawRef<U>, void>>
PA_ALWAYS_INLINE friend constexpr auto operator<=>(const U& lhs,
const raw_ref& rhs) {
PA_RAW_PTR_CHECK(rhs.inner_); // Catch use-after-move.
return &lhs <=> rhs.inner_;
}
#else
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
template <class U, class = std::enable_if_t<!IsRawRef<U>, void>>
PA_ALWAYS_INLINE friend constexpr bool operator<(const raw_ref& lhs,
const U& rhs) {
PA_RAW_PTR_CHECK(lhs.inner_); // Catch use-after-move.
return lhs.inner_ < &rhs;
}
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
template <class U, class = std::enable_if_t<!IsRawRef<U>, void>>
PA_ALWAYS_INLINE friend constexpr bool operator>(const raw_ref& lhs,
const U& rhs) {
PA_RAW_PTR_CHECK(lhs.inner_); // Catch use-after-move.
return lhs.inner_ > &rhs;
}
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
template <class U, class = std::enable_if_t<!IsRawRef<U>, void>>
PA_ALWAYS_INLINE friend constexpr bool operator<=(const raw_ref& lhs,
const U& rhs) {
PA_RAW_PTR_CHECK(lhs.inner_); // Catch use-after-move.
return lhs.inner_ <= &rhs;
}
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
template <class U, class = std::enable_if_t<!IsRawRef<U>, void>>
PA_ALWAYS_INLINE friend constexpr bool operator>=(const raw_ref& lhs,
const U& rhs) {
PA_RAW_PTR_CHECK(lhs.inner_); // Catch use-after-move.
return lhs.inner_ >= &rhs;
}
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
template <class U, class = std::enable_if_t<!IsRawRef<U>, void>>
PA_ALWAYS_INLINE friend constexpr bool operator<(const U& lhs,
const raw_ref& rhs) {
PA_RAW_PTR_CHECK(rhs.inner_); // Catch use-after-move.
return &lhs < rhs.inner_;
}
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
template <class U, class = std::enable_if_t<!IsRawRef<U>, void>>
PA_ALWAYS_INLINE friend constexpr bool operator>(const U& lhs,
const raw_ref& rhs) {
PA_RAW_PTR_CHECK(rhs.inner_); // Catch use-after-move.
return &lhs > rhs.inner_;
}
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
template <class U, class = std::enable_if_t<!IsRawRef<U>, void>>
PA_ALWAYS_INLINE friend constexpr bool operator<=(const U& lhs,
const raw_ref& rhs) {
PA_RAW_PTR_CHECK(rhs.inner_); // Catch use-after-move.
return &lhs <= rhs.inner_;
}
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
template <class U, class = std::enable_if_t<!IsRawRef<U>, void>>
PA_ALWAYS_INLINE friend constexpr bool operator>=(const U& lhs,
const raw_ref& rhs) {
PA_RAW_PTR_CHECK(rhs.inner_); // Catch use-after-move.
@ -411,26 +403,15 @@ raw_ref(T&) -> raw_ref<T>;
template <class T>
raw_ref(const T&) -> raw_ref<const T>;
// Template helpers for working with raw_ref<T>.
template <typename T>
struct IsRawRef : std::false_type {};
template <typename T, RawPtrTraits Traits>
struct IsRawRef<raw_ref<T, Traits>> : std::true_type {};
template <typename T>
inline constexpr bool IsRawRefV = IsRawRef<T>::value;
// Converts `raw_ref<T>` => `T`; leaves l/rvalue refs alone.
template <typename T>
struct RemoveRawRef {
using type = T;
};
template <typename T, RawPtrTraits Traits>
struct RemoveRawRef<raw_ref<T, Traits>> {
using type = T;
};
template <typename T>
using RemoveRawRefT = typename RemoveRawRef<T>::type;

View file

@ -27,7 +27,7 @@ class RandomGenerator {
}
private:
::partition_alloc::internal::Lock lock_ = {};
::partition_alloc::internal::Lock lock_;
bool initialized_ PA_GUARDED_BY(lock_) = false;
union {
internal::base::InsecureRandomGenerator instance_ PA_GUARDED_BY(lock_);

View file

@ -8,7 +8,6 @@
#include <cstddef>
#include <cstdint>
#include <limits>
#include <tuple>
#include "partition_alloc/address_pool_manager.h"
#include "partition_alloc/build_config.h"

View file

@ -31,7 +31,6 @@
// noexcept needs to be routed to
// allocator_shim::internal::PartitionMallocUnchecked through the shim layer.
#include "partition_alloc/shim/allocator_shim_override_cpp_symbols.h"
#include "partition_alloc/shim/allocator_shim_override_libc_symbols.h"
// Some glibc versions (until commit 6c444ad6e953dbdf9c7be065308a0a777)

View file

@ -150,6 +150,9 @@ using ZappingByFreeFlags =
bool>;
using EventuallyZeroFreedMemory = partition_alloc::internal::base::
StrongAlias<class EventuallyZeroFreedMemoryTag, bool>;
using FewerMemoryRegions =
partition_alloc::internal::base::StrongAlias<class FewerMemoryRegionsTag,
bool>;
using UsePoolOffsetFreelists = partition_alloc::internal::base::
StrongAlias<class UsePoolOffsetFreelistsTag, bool>;
@ -162,6 +165,7 @@ using UseSmallSingleSlotSpans = partition_alloc::internal::base::
PA_COMPONENT_EXPORT(ALLOCATOR_SHIM)
void ConfigurePartitions(
EnableBrp enable_brp,
size_t brp_extra_extras_size,
EnableMemoryTagging enable_memory_tagging,
partition_alloc::TagViolationReportingMode memory_tagging_reporting_mode,
BucketDistribution distribution,
@ -169,6 +173,7 @@ void ConfigurePartitions(
size_t scheduler_loop_quarantine_branch_capacity_in_bytes,
ZappingByFreeFlags zapping_by_free_flags,
EventuallyZeroFreedMemory eventually_zero_freed_memory,
FewerMemoryRegions fewer_memory_regions,
UsePoolOffsetFreelists use_pool_offset_freelists,
UseSmallSingleSlotSpans use_small_single_slot_spans);

View file

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <dlfcn.h>
#include <malloc.h>
#include <limits>
#include "partition_alloc/oom.h"
@ -9,9 +12,6 @@
#include "partition_alloc/partition_alloc_base/numerics/checked_math.h"
#include "partition_alloc/shim/allocator_shim.h"
#include <dlfcn.h>
#include <malloc.h>
// This translation unit defines a default dispatch for the allocator shim which
// routes allocations to libc functions.
// The code here is strongly inspired from tcmalloc's libc_override_glibc.h.

View file

@ -26,6 +26,7 @@
#include "partition_alloc/partition_root.h"
#include "partition_alloc/partition_stats.h"
#include "partition_alloc/shim/allocator_dispatch.h"
#include "partition_alloc/shim/allocator_shim.h"
#include "partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc_internal.h"
#include "partition_alloc/shim/allocator_shim_internals.h"
@ -101,7 +102,7 @@ class LeakySingleton {
__cpp_lib_atomic_value_initialization < 201911L
alignas(T) uint8_t instance_buffer_[sizeof(T)];
#else
alignas(T) uint8_t instance_buffer_[sizeof(T)] = {0};
alignas(T) uint8_t instance_buffer_[sizeof(T)] = {};
#endif
std::atomic<bool> initialization_lock_;
};
@ -148,7 +149,6 @@ class MainPartitionConstructor {
// the decision to turn the thread cache on until then.
// Also tests, such as the ThreadCache tests create a thread cache.
opts.thread_cache = partition_alloc::PartitionOptions::kDisabled;
opts.star_scan_quarantine = partition_alloc::PartitionOptions::kAllowed;
opts.backup_ref_ptr = partition_alloc::PartitionOptions::kDisabled;
auto* new_root = new (buffer) partition_alloc::PartitionRoot(opts);
@ -571,7 +571,6 @@ template class PA_COMPONENT_EXPORT(ALLOCATOR_SHIM)
PartitionAllocFunctionsInternal<
partition_alloc::AllocFlags::kNoHooks,
partition_alloc::FreeFlags::kNoHooks |
partition_alloc::FreeFlags::kZap |
partition_alloc::FreeFlags::kSchedulerLoopQuarantine>;
// static
@ -612,6 +611,7 @@ void EnablePartitionAllocMemoryReclaimer() {
void ConfigurePartitions(
EnableBrp enable_brp,
size_t brp_extra_extras_size,
EnableMemoryTagging enable_memory_tagging,
partition_alloc::TagViolationReportingMode memory_tagging_reporting_mode,
BucketDistribution distribution,
@ -619,6 +619,7 @@ void ConfigurePartitions(
size_t scheduler_loop_quarantine_branch_capacity_in_bytes,
ZappingByFreeFlags zapping_by_free_flags,
EventuallyZeroFreedMemory eventually_zero_freed_memory,
FewerMemoryRegions fewer_memory_regions,
UsePoolOffsetFreelists use_pool_offset_freelists,
UseSmallSingleSlotSpans use_small_single_slot_spans) {
// Calling Get() is actually important, even if the return value isn't
@ -640,10 +641,10 @@ void ConfigurePartitions(
// another partition will have the thread cache enabled, by calling
// EnableThreadCacheIfSupported().
opts.thread_cache = partition_alloc::PartitionOptions::kDisabled;
opts.star_scan_quarantine = partition_alloc::PartitionOptions::kAllowed;
opts.backup_ref_ptr =
enable_brp ? partition_alloc::PartitionOptions::kEnabled
: partition_alloc::PartitionOptions::kDisabled;
opts.backup_ref_ptr_extra_extras_size = brp_extra_extras_size;
opts.zapping_by_free_flags =
zapping_by_free_flags
? partition_alloc::PartitionOptions::kEnabled
@ -652,6 +653,9 @@ void ConfigurePartitions(
eventually_zero_freed_memory
? partition_alloc::PartitionOptions::kEnabled
: partition_alloc::PartitionOptions::kDisabled;
opts.fewer_memory_regions =
fewer_memory_regions ? partition_alloc::PartitionOptions::kEnabled
: partition_alloc::PartitionOptions::kDisabled;
opts.scheduler_loop_quarantine =
scheduler_loop_quarantine
? partition_alloc::PartitionOptions::kEnabled
@ -739,7 +743,7 @@ SHIM_ALWAYS_EXPORT int mallopt(int cmd, int value) __THROW {
#endif // !PA_BUILDFLAG(IS_APPLE) && !PA_BUILDFLAG(IS_ANDROID)
#if defined(__MUSL__)
#if defined(__MUSL__)
// Musl does not support struct mallinfo.
#elif PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS)
SHIM_ALWAYS_EXPORT struct mallinfo mallinfo(void) __THROW {

View file

@ -135,7 +135,6 @@ using PartitionAllocWithAdvancedChecksFunctions =
PartitionAllocFunctionsInternal<
partition_alloc::AllocFlags::kNoHooks,
partition_alloc::FreeFlags::kNoHooks |
partition_alloc::FreeFlags::kZap |
partition_alloc::FreeFlags::kSchedulerLoopQuarantine>;
// `PartitionAllocFunctions` in instantiated in cc file.
@ -147,7 +146,6 @@ extern template class PA_COMPONENT_EXPORT(ALLOCATOR_SHIM)
PartitionAllocFunctionsInternal<
partition_alloc::AllocFlags::kNoHooks,
partition_alloc::FreeFlags::kNoHooks |
partition_alloc::FreeFlags::kZap |
partition_alloc::FreeFlags::kSchedulerLoopQuarantine>;
} // namespace internal
@ -164,6 +162,7 @@ extern template class PA_COMPONENT_EXPORT(ALLOCATOR_SHIM)
// this function. They should call ConfigurePartitions() directly.
PA_ALWAYS_INLINE void ConfigurePartitionsForTesting() {
auto enable_brp = allocator_shim::EnableBrp(true);
size_t brp_extra_extras_size = 0;
// Embedders's tests might benefit from MTE checks. However, this is costly
// and shouldn't be used in benchmarks.
@ -181,15 +180,16 @@ PA_ALWAYS_INLINE void ConfigurePartitionsForTesting() {
size_t scheduler_loop_quarantine_capacity_in_bytes = 0;
auto zapping_by_free_flags = ZappingByFreeFlags(false);
auto eventually_zero_freed_memory = EventuallyZeroFreedMemory(false);
auto fewer_memory_regions = FewerMemoryRegions(false);
auto use_pool_offset_freelists = UsePoolOffsetFreelists(true);
auto use_small_single_slot_spans = UseSmallSingleSlotSpans(true);
ConfigurePartitions(enable_brp, enable_memory_tagging,
memory_tagging_reporting_mode, distribution,
scheduler_loop_quarantine,
scheduler_loop_quarantine_capacity_in_bytes,
zapping_by_free_flags, eventually_zero_freed_memory,
use_pool_offset_freelists, use_small_single_slot_spans);
ConfigurePartitions(
enable_brp, brp_extra_extras_size, enable_memory_tagging,
memory_tagging_reporting_mode, distribution, scheduler_loop_quarantine,
scheduler_loop_quarantine_capacity_in_bytes, zapping_by_free_flags,
eventually_zero_freed_memory, fewer_memory_regions,
use_pool_offset_freelists, use_small_single_slot_spans);
}
#endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)

View file

@ -2,11 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "partition_alloc/shim/allocator_shim.h"
#include <ostream>
#include "partition_alloc/partition_alloc_check.h"
#include "partition_alloc/shim/allocator_shim.h"
#include "partition_alloc/shim/winheap_stubs_win.h"
namespace {

View file

@ -276,7 +276,7 @@ errno_t _wdupenv_s(wchar_t** buffer,
}
#endif
#if !defined(NDEBUG)
#if PA_BUILDFLAG(IS_DEBUG)
typedef void (*_CRT_DUMP_CLIENT)(void*, size_t);
int _crtDbgFlag = 0;
@ -451,9 +451,9 @@ errno_t _wdupenv_s_dbg(wchar_t** buffer,
}
#endif // defined(COMPONENT_BUILD)
#endif // !defined(NDEBUG)
#endif // PA_BUILDFLAG(IS_DEBUG)
} // extern "C"
} // extern "C"
#endif // PA_BUILDFLAG(USE_ALLOCATOR_SHIM)
#endif // PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_OVERRIDE_UCRT_SYMBOLS_WIN_H_

View file

@ -142,8 +142,33 @@ void SpinningMutex::LockSlow() {
#elif PA_BUILDFLAG(IS_APPLE)
// TODO(verwaest): We should use the constants from the header, but they aren't
// exposed until macOS 15. See their definition here:
// https://github.com/apple-oss-distributions/libplatform/blob/4f6349dfea579c35b8fa838d785644e441d14e0e/private/os/lock_private.h#L265
//
// The first flag prevents the runtime from creating more threads in response to
// contention. The second will spin in the kernel if the lock owner is currently
// running.
#define OS_UNFAIR_LOCK_DATA_SYNCHRONIZATION 0x00010000
#define OS_UNFAIR_LOCK_ADAPTIVE_SPIN 0x00040000
typedef uint32_t os_unfair_lock_options_t;
extern "C" {
void __attribute__((weak))
os_unfair_lock_lock_with_options(os_unfair_lock* lock,
os_unfair_lock_options_t);
}
void SpinningMutex::LockSlow() {
return os_unfair_lock_lock(&unfair_lock_);
if (os_unfair_lock_lock_with_options) {
const os_unfair_lock_options_t options =
static_cast<os_unfair_lock_options_t>(
OS_UNFAIR_LOCK_DATA_SYNCHRONIZATION | OS_UNFAIR_LOCK_ADAPTIVE_SPIN);
os_unfair_lock_lock_with_options(&unfair_lock_, options);
} else {
os_unfair_lock_lock(&unfair_lock_);
}
}
#elif PA_BUILDFLAG(IS_POSIX)

View file

@ -4,7 +4,7 @@ Version: 409.40.6
Revision: 387a5a03c017801ecdfe9cbe7f8d69a9b427df68
Security Critical: yes
Shipped: yes
License: Apple Public Source License 2.0
License: APSL-2.0
License File: LICENSE
Local Modifications:

View file

@ -377,7 +377,11 @@ void ThreadCache::SwapForTesting(PartitionRoot* root) {
// static
void ThreadCache::RemoveTombstoneForTesting() {
PA_CHECK(IsTombstone(Get()));
#if PA_CONFIG(THREAD_CACHE_FAST_TLS)
internal::g_thread_cache = nullptr;
#else
internal::PartitionTlsSet(internal::g_thread_cache_key, nullptr);
#endif
}
// static

View file

@ -12,7 +12,6 @@
#include <cstddef>
#include <cstdint>
#include "partition_alloc/buildflags.h"
#include "partition_alloc/partition_alloc_base/component_export.h"
#include "partition_alloc/thread_isolation/alignment.h"

View file

@ -12,7 +12,6 @@
#include <cstddef>
#include <cstdint>
#include "partition_alloc/buildflags.h"
#include "partition_alloc/partition_alloc_base/component_export.h"
#if PA_BUILDFLAG(ENABLE_PKEYS)

View file

@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <jni.h>
#include "base/android/apk_assets.h"
#include <jni.h>
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
@ -26,8 +26,7 @@ int OpenApkAsset(const std::string& file_path,
// resources :(
JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jlongArray> jarr =
Java_ApkAssets_open(env, ConvertUTF8ToJavaString(env, file_path),
ConvertUTF8ToJavaString(env, split_name));
Java_ApkAssets_open(env, file_path, split_name);
std::vector<jlong> results;
base::android::JavaLongArrayToLongVector(env, jarr, &results);
CHECK_EQ(3U, results.size());
@ -48,8 +47,9 @@ bool RegisterApkAssetWithFileDescriptorStore(const std::string& key,
base::MemoryMappedFile::Region region =
base::MemoryMappedFile::Region::kWholeFile;
int asset_fd = OpenApkAsset(file_path.value(), &region);
if (asset_fd == -1)
if (asset_fd == -1) {
return false;
}
base::FileDescriptorStore::GetInstance().Set(key, base::ScopedFD(asset_fd),
region);
return true;
@ -57,13 +57,11 @@ bool RegisterApkAssetWithFileDescriptorStore(const std::string& key,
void DumpLastOpenApkAssetFailure() {
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jstring> error =
Java_ApkAssets_takeLastErrorString(env);
if (!error) {
std::string error = Java_ApkAssets_takeLastErrorString(env);
if (error.empty()) {
return;
}
SCOPED_CRASH_KEY_STRING256("base", "OpenApkAssetError",
ConvertJavaStringToUTF8(env, error));
SCOPED_CRASH_KEY_STRING256("base", "OpenApkAssetError", error);
base::debug::DumpWithoutCrashing();
}

View file

@ -26,9 +26,8 @@ namespace android {
BASE_EXPORT int OpenApkAsset(const std::string& file_path,
const std::string& split_name,
base::MemoryMappedFile::Region* region);
BASE_EXPORT int OpenApkAsset(
const std::string& file_path,
base::MemoryMappedFile::Region* region);
BASE_EXPORT int OpenApkAsset(const std::string& file_path,
base::MemoryMappedFile::Region* region);
// Registers an uncompressed asset from within the apk in the
// FileDescriptorStore.

View file

@ -66,8 +66,9 @@ class ApplicationStatusListenerImpl : public ApplicationStatusListener {
}
void Notify(ApplicationState state) override {
if (callback_)
if (callback_) {
callback_.Run(state);
}
}
private:
@ -113,9 +114,8 @@ ApplicationState ApplicationStatusListener::GetState() {
Java_ApplicationStatus_getStateForApplication(AttachCurrentThread()));
}
static void JNI_ApplicationStatus_OnApplicationStateChange(
JNIEnv* env,
jint new_state) {
static void JNI_ApplicationStatus_OnApplicationStateChange(JNIEnv* env,
jint new_state) {
ApplicationState application_state = static_cast<ApplicationState>(new_state);
ApplicationStatusListener::NotifyApplicationStateChange(application_state);
}

View file

@ -6,6 +6,7 @@
#define BASE_ANDROID_APPLICATION_STATUS_LISTENER_H_
#include <jni.h>
#include <memory>
#include "base/android/jni_android.h"

View file

@ -22,8 +22,8 @@ const base::Feature* const kFeaturesExposedToJava[] = {
// static
base::android::FeatureMap* GetFeatureMap() {
static base::NoDestructor<base::android::FeatureMap> kFeatureMap(std::vector(
std::begin(kFeaturesExposedToJava), std::end(kFeaturesExposedToJava)));
static base::NoDestructor<base::android::FeatureMap> kFeatureMap(
kFeaturesExposedToJava);
return kFeatureMap.get();
}

View file

@ -106,13 +106,12 @@ void BuildInfo::set_gms_version_code_for_test(
std::string BuildInfo::host_signing_cert_sha256() {
JNIEnv* env = AttachCurrentThread();
return base::android::ConvertJavaStringToUTF8(
env, Java_BuildInfo_lazyGetHostSigningCertSha256(env));
return Java_BuildInfo_lazyGetHostSigningCertSha256(env);
}
// static
BuildInfo* BuildInfo::GetInstance() {
return Singleton<BuildInfo, BuildInfoSingletonTraits >::get();
return Singleton<BuildInfo, BuildInfoSingletonTraits>::get();
}
} // namespace android

View file

@ -60,33 +60,19 @@ class BASE_EXPORT BuildInfo {
// available even if the process is in a crash state. Sadly
// std::string.c_str() doesn't guarantee that memory won't be allocated when
// it is called.
const char* device() const {
return device_;
}
const char* device() const { return device_; }
const char* manufacturer() const {
return manufacturer_;
}
const char* manufacturer() const { return manufacturer_; }
const char* model() const {
return model_;
}
const char* model() const { return model_; }
const char* brand() const {
return brand_;
}
const char* brand() const { return brand_; }
const char* android_build_id() const {
return android_build_id_;
}
const char* android_build_id() const { return android_build_id_; }
const char* android_build_fp() const {
return android_build_fp_;
}
const char* android_build_fp() const { return android_build_fp_; }
const char* gms_version_code() const {
return gms_version_code_;
}
const char* gms_version_code() const { return gms_version_code_; }
void set_gms_version_code_for_test(const std::string& gms_version_code);
@ -111,25 +97,17 @@ class BASE_EXPORT BuildInfo {
// This will default to an empty string if we were unable to retrieve it.
std::string host_signing_cert_sha256();
const char* package_version_code() const {
return package_version_code_;
}
const char* package_version_code() const { return package_version_code_; }
const char* package_version_name() const {
return package_version_name_;
}
const char* package_version_name() const { return package_version_name_; }
const char* package_name() const {
return package_name_;
}
const char* package_name() const { return package_name_; }
const char* custom_themes() const { return custom_themes_; }
const char* resources_version() const { return resources_version_; }
const char* build_type() const {
return build_type_;
}
const char* build_type() const { return build_type_; }
const char* board() const { return board_; }
@ -137,9 +115,7 @@ class BASE_EXPORT BuildInfo {
const char* abi_name() const { return abi_name_; }
int sdk_int() const {
return sdk_int_;
}
int sdk_int() const { return sdk_int_; }
// Returns the targetSdkVersion of the currently running app. If called from a
// library, this returns the embedding app's targetSdkVersion.

View file

@ -55,19 +55,12 @@ UNSAFE_BUFFER_USAGE void* ReadRelPtr(int32_t* relptr) {
std::string BundleUtils::ResolveLibraryPath(const std::string& library_name,
const std::string& split_name) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jstring> java_path = Java_BundleUtils_getNativeLibraryPath(
env, ConvertUTF8ToJavaString(env, library_name),
ConvertUTF8ToJavaString(env, split_name));
// TODO(crbug.com/40656179): Remove this tolerance.
if (!java_path) {
return std::string();
}
return ConvertJavaStringToUTF8(env, java_path);
return Java_BundleUtils_getNativeLibraryPath(env, library_name, split_name);
}
// static
bool BundleUtils::IsBundle() {
return Java_BundleUtils_isBundleForNative(AttachCurrentThread());
return Java_BundleUtils_isBundle(AttachCurrentThread());
}
// static
@ -114,7 +107,7 @@ void* BundleUtils::DlOpenModuleLibraryPartition(const std::string& library_name,
#else
// When targeting pre-N, such as for Cronet, android_dlopen_ext() might
// not be available on the system.
CHECK(0) << "android_dlopen_ext not available";
NOTREACHED() << "android_dlopen_ext not available";
#endif
}
}

View file

@ -7,6 +7,7 @@
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/android/library_loader/library_loader_hooks.h"
#include "base/android/pre_freeze_background_memory_trimmer.h"
#include "base/debug/dump_without_crashing.h"
#include "base/file_descriptor_store.h"
#include "base/logging.h"
@ -82,5 +83,9 @@ NOINLINE void JNI_ChildProcessService_DumpProcessStack(JNIEnv* env) {
base::debug::DumpWithoutCrashing();
}
void JNI_ChildProcessService_OnSelfFreeze(JNIEnv* env) {
PreFreezeBackgroundMemoryTrimmer::OnSelfFreeze();
}
} // namespace android
} // namespace base

View file

@ -14,15 +14,16 @@
#include "base/command_line_jni/CommandLine_jni.h"
#endif
using base::CommandLine;
using base::android::JavaParamRef;
using base::android::ScopedJavaLocalRef;
using base::CommandLine;
namespace {
void AppendToCommandLine(std::vector<std::string>& vec, bool includes_program) {
if (!includes_program)
if (!includes_program) {
vec.insert(vec.begin(), std::string());
}
CommandLine extra_command_line(vec);
CommandLine::ForCurrentProcess()->AppendArguments(extra_command_line,
includes_program);
@ -40,21 +41,8 @@ static std::string JNI_CommandLine_GetSwitchValue(JNIEnv* env,
return CommandLine::ForCurrentProcess()->GetSwitchValueNative(switch_string);
}
static std::vector<std::string> JNI_CommandLine_GetSwitchesFlattened(
JNIEnv* env) {
// JNI doesn't support returning Maps. Instead, express this map as a 1
// dimensional array: [ key1, value1, key2, value2, ... ]
std::vector<std::string> keys_and_values;
for (const auto& entry : CommandLine::ForCurrentProcess()->GetSwitches()) {
keys_and_values.push_back(entry.first);
keys_and_values.push_back(entry.second);
}
return keys_and_values;
}
static void JNI_CommandLine_AppendSwitch(JNIEnv* env,
std::string& switch_string) {
CommandLine::ForCurrentProcess()->AppendSwitch(switch_string);
static CommandLine::SwitchMap JNI_CommandLine_GetSwitches(JNIEnv* env) {
return CommandLine::ForCurrentProcess()->GetSwitches();
}
static void JNI_CommandLine_AppendSwitchWithValue(JNIEnv* env,

View file

@ -22,15 +22,6 @@ using base::android::JavaRef;
using base::android::ScopedJavaLocalRef;
namespace base {
namespace {
std::string SafeConvertJavaStringToUTF8(JNIEnv* env,
const JavaRef<jstring>& str) {
if (str.is_null()) {
return std::string();
}
return base::android::ConvertJavaStringToUTF8(env, str);
}
} // namespace
namespace internal {
@ -114,33 +105,30 @@ bool IsDocumentUri(const FilePath& content_uri) {
} // namespace internal
void JNI_ContentUriUtils_AddFileInfoToVector(
JNIEnv* env,
jlong vector_pointer,
const JavaParamRef<jstring>& uri,
const JavaParamRef<jstring>& display_name,
jboolean is_directory,
jlong size,
jlong last_modified) {
void JNI_ContentUriUtils_AddFileInfoToVector(JNIEnv* env,
jlong vector_pointer,
std::string& uri,
std::string& display_name,
jboolean is_directory,
jlong size,
jlong last_modified) {
auto* result =
reinterpret_cast<std::vector<FileEnumerator::FileInfo>*>(vector_pointer);
result->emplace_back(FilePath(SafeConvertJavaStringToUTF8(env, uri)),
FilePath(SafeConvertJavaStringToUTF8(env, display_name)),
is_directory, size,
result->emplace_back(FilePath(uri), FilePath(display_name), is_directory,
size,
Time::FromMillisecondsSinceUnixEpoch(last_modified));
}
std::string GetContentUriMimeType(const FilePath& content_uri) {
JNIEnv* env = android::AttachCurrentThread();
ScopedJavaLocalRef<jstring> j_mime =
Java_ContentUriUtils_getMimeType(env, content_uri.value());
return SafeConvertJavaStringToUTF8(env, j_mime);
return Java_ContentUriUtils_getMimeType(env, content_uri.value());
}
bool MaybeGetFileDisplayName(const FilePath& content_uri,
std::u16string* file_display_name) {
if (!content_uri.IsContentUri())
if (!content_uri.IsContentUri()) {
return false;
}
DCHECK(file_display_name);
@ -148,8 +136,9 @@ bool MaybeGetFileDisplayName(const FilePath& content_uri,
ScopedJavaLocalRef<jstring> j_display_name =
Java_ContentUriUtils_maybeGetDisplayName(env, content_uri.value());
if (j_display_name.is_null())
if (j_display_name.is_null()) {
return false;
}
*file_display_name = android::ConvertJavaStringToUTF16(j_display_name);
return true;
@ -159,10 +148,9 @@ FilePath ContentUriBuildDocumentUriUsingTree(
const FilePath& tree_uri,
const std::string& encoded_document_id) {
JNIEnv* env = android::AttachCurrentThread();
ScopedJavaLocalRef<jstring> j_uri =
Java_ContentUriUtils_buildDocumentUriUsingTree(env, tree_uri.value(),
encoded_document_id);
return FilePath(SafeConvertJavaStringToUTF8(env, j_uri));
std::string j_uri = Java_ContentUriUtils_buildDocumentUriUsingTree(
env, tree_uri.value(), encoded_document_id);
return FilePath(j_uri);
}
FilePath ContentUriGetChildDocumentOrQuery(const FilePath& parent,
@ -171,10 +159,9 @@ FilePath ContentUriGetChildDocumentOrQuery(const FilePath& parent,
bool is_directory,
bool create) {
JNIEnv* env = android::AttachCurrentThread();
ScopedJavaLocalRef<jstring> j_uri =
Java_ContentUriUtils_getChildDocumentOrQuery(
env, parent.value(), display_name, mime_type, is_directory, create);
return FilePath(SafeConvertJavaStringToUTF8(env, j_uri));
std::string j_uri = Java_ContentUriUtils_getChildDocumentOrQuery(
env, parent.value(), display_name, mime_type, is_directory, create);
return FilePath(j_uri);
}
bool ContentUriIsCreateChildDocumentQuery(const FilePath& content_uri) {
@ -186,9 +173,9 @@ bool ContentUriIsCreateChildDocumentQuery(const FilePath& content_uri) {
FilePath ContentUriGetDocumentFromQuery(const FilePath& content_uri,
bool create) {
JNIEnv* env = android::AttachCurrentThread();
ScopedJavaLocalRef<jstring> j_uri = Java_ContentUriUtils_getDocumentFromQuery(
std::string j_uri = Java_ContentUriUtils_getDocumentFromQuery(
env, content_uri.value(), create);
return FilePath(SafeConvertJavaStringToUTF8(env, j_uri));
return FilePath(j_uri);
}
} // namespace base

View file

@ -18,15 +18,12 @@
namespace base {
namespace android {
static void JNI_EarlyTraceEvent_RecordEarlyBeginEvent(
JNIEnv* env,
const JavaParamRef<jstring>& jname,
jlong time_ns,
jint thread_id,
jlong thread_time_ms) {
static void JNI_EarlyTraceEvent_RecordEarlyBeginEvent(JNIEnv* env,
std::string& name,
jlong time_ns,
jint thread_id,
jlong thread_time_ms) {
#if BUILDFLAG(ENABLE_BASE_TRACING)
std::string name = ConvertJavaStringToUTF8(env, jname);
static const unsigned char* category_group_enabled =
TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(internal::kJavaTraceCategory);
trace_event_internal::AddTraceEventWithThreadIdAndTimestamps(
@ -38,15 +35,12 @@ static void JNI_EarlyTraceEvent_RecordEarlyBeginEvent(
#endif // BUILDFLAG(ENABLE_BASE_TRACING)
}
static void JNI_EarlyTraceEvent_RecordEarlyEndEvent(
JNIEnv* env,
const JavaParamRef<jstring>& jname,
jlong time_ns,
jint thread_id,
jlong thread_time_ms) {
static void JNI_EarlyTraceEvent_RecordEarlyEndEvent(JNIEnv* env,
std::string& name,
jlong time_ns,
jint thread_id,
jlong thread_time_ms) {
#if BUILDFLAG(ENABLE_BASE_TRACING)
std::string name = ConvertJavaStringToUTF8(env, jname);
static const unsigned char* category_group_enabled =
TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(internal::kJavaTraceCategory);
trace_event_internal::AddTraceEventWithThreadIdAndTimestamps(
@ -60,13 +54,11 @@ static void JNI_EarlyTraceEvent_RecordEarlyEndEvent(
static void JNI_EarlyTraceEvent_RecordEarlyToplevelBeginEvent(
JNIEnv* env,
const JavaParamRef<jstring>& jname,
std::string& name,
jlong time_ns,
jint thread_id,
jlong thread_time_ms) {
#if BUILDFLAG(ENABLE_BASE_TRACING)
std::string name = ConvertJavaStringToUTF8(env, jname);
static const unsigned char* category_group_enabled =
TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
internal::kToplevelTraceCategory);
@ -81,13 +73,11 @@ static void JNI_EarlyTraceEvent_RecordEarlyToplevelBeginEvent(
static void JNI_EarlyTraceEvent_RecordEarlyToplevelEndEvent(
JNIEnv* env,
const JavaParamRef<jstring>& jname,
std::string& name,
jlong time_ns,
jint thread_id,
jlong thread_time_ms) {
#if BUILDFLAG(ENABLE_BASE_TRACING)
std::string name = ConvertJavaStringToUTF8(env, jname);
static const unsigned char* category_group_enabled =
TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
internal::kToplevelTraceCategory);
@ -100,16 +90,14 @@ static void JNI_EarlyTraceEvent_RecordEarlyToplevelEndEvent(
#endif // BUILDFLAG(ENABLE_BASE_TRACING)
}
static void JNI_EarlyTraceEvent_RecordEarlyAsyncBeginEvent(
JNIEnv* env,
const JavaParamRef<jstring>& jname,
jlong id,
jlong time_ns) {
static void JNI_EarlyTraceEvent_RecordEarlyAsyncBeginEvent(JNIEnv* env,
std::string& name,
jlong id,
jlong time_ns) {
TRACE_EVENT_BEGIN(internal::kJavaTraceCategory, nullptr,
perfetto::Track(static_cast<uint64_t>(id)),
TimeTicks::FromJavaNanoTime(time_ns),
[&](::perfetto::EventContext& ctx) {
std::string name = ConvertJavaStringToUTF8(env, jname);
ctx.event()->set_name(name.c_str());
});
}

View file

@ -24,7 +24,8 @@ std::pair<std::string_view, const Feature*> MakeNameToFeaturePair(
return std::make_pair(feature->name, feature);
}
FeatureMap::FeatureMap(std::vector<const Feature*> features_exposed_to_java) {
FeatureMap::FeatureMap(
base::span<const Feature* const> features_exposed_to_java) {
mapping_ =
MakeFlatMap<std::string_view, raw_ptr<const Feature, CtnExperimental>>(
features_exposed_to_java, {}, &MakeNameToFeaturePair);

View file

@ -9,6 +9,7 @@
#include "base/base_export.h"
#include "base/containers/flat_map.h"
#include "base/containers/span.h"
#include "base/feature_list.h"
#include "base/memory/raw_ptr.h"
@ -22,7 +23,8 @@ namespace base::android {
// Each component should have its own FeatureMap.
class BASE_EXPORT FeatureMap {
public:
explicit FeatureMap(std::vector<const Feature*> featuresExposedToJava);
explicit FeatureMap(
base::span<const Feature* const> features_exposed_to_java);
~FeatureMap();
// Map a |feature_name| to a Feature*.

View file

@ -34,8 +34,8 @@ class TrialLogger : public base::FieldTrialList::Observer {
// Changes to format of the log message below must be accompanied by
// changes to finch smoke tests since they look for this log message
// in the logcat.
LOG(INFO) << "Active field trial \"" << trial_name
<< "\" in group \"" << group_name<< '"';
LOG(INFO) << "Active field trial \"" << trial_name << "\" in group \""
<< group_name << '"';
}
protected:
@ -89,7 +89,7 @@ class AndroidFieldTrialListLogActiveTrialsFriendHelper {
};
static void JNI_FieldTrialList_LogActiveTrials(JNIEnv* env) {
DCHECK(!g_trial_logger.IsCreated()); // This need only be called once.
DCHECK(!g_trial_logger.IsCreated()); // This need only be called once.
LOG(INFO) << "Logging active field trials...";
AndroidFieldTrialListLogActiveTrialsFriendHelper::AddObserver(

View file

@ -41,13 +41,14 @@ InputHintChecker* g_test_instance;
BASE_EXPORT
BASE_FEATURE(kYieldWithInputHint,
"YieldWithInputHint",
base::FEATURE_DISABLED_BY_DEFAULT);
base::FEATURE_ENABLED_BY_DEFAULT);
// Min time delta between checks for the input hint. Must be a smaller than
// time to produce a frame, but a bit longer than the time it takes to retrieve
// the hint.
// Note: Do not use the prepared macro as of no need for a local cache.
const base::FeatureParam<int> kPollIntervalMillisParam{&kYieldWithInputHint,
"poll_interval_ms", 3};
"poll_interval_ms", 1};
// Class calling a private method of InputHintChecker.
// This allows not to declare the method called by pthread_create in the public

View file

@ -22,8 +22,7 @@ void RunIntStringCallbackAndroid(const JavaRef<jobject>& callback,
int int_arg,
const std::string& str_arg) {
JNIEnv* env = jni_zero::AttachCurrentThread();
Java_IntStringCallback_onResult(env, callback, int_arg,
ConvertUTF8ToJavaString(env, str_arg));
Java_IntStringCallback_onResult(env, callback, int_arg, str_arg);
}
} // namespace android

View file

@ -81,14 +81,14 @@ void JavaHandlerThread::Stop() {
Java_JavaHandlerThread_joinThread(env, java_thread_);
}
void JavaHandlerThread::InitializeThread(JNIEnv* env,
jlong event) {
void JavaHandlerThread::InitializeThread(JNIEnv* env, jlong event) {
base::ThreadIdNameManager::GetInstance()->RegisterThread(
base::PlatformThread::CurrentHandle().platform_handle(),
base::PlatformThread::CurrentId());
if (name_)
if (name_) {
PlatformThread::SetName(name_);
}
thread_id_ = base::PlatformThread::CurrentId();
state_ = std::make_unique<State>();
@ -178,5 +178,5 @@ JavaHandlerThread::State::State()
JavaHandlerThread::State::~State() = default;
} // namespace android
} // namespace base
} // namespace android
} // namespace base

View file

@ -52,8 +52,7 @@ class BASE_EXPORT JavaHandlerThread {
// Called from java on the newly created thread.
// Start() will not return before this methods has finished.
void InitializeThread(JNIEnv* env,
jlong event);
void InitializeThread(JNIEnv* env, jlong event);
// Called from java on this thread.
void OnLooperStopped(JNIEnv* env);

View file

@ -112,7 +112,6 @@ void InitVM(JavaVM* vm) {
DCHECK(g_out_of_memory_error_class);
}
void CheckException(JNIEnv* env) {
if (!jni_zero::HasException(env)) {
return;
@ -204,8 +203,7 @@ void CheckException(JNIEnv* env) {
LOG(ERROR) << "Native stack trace:" << std::endl << native_stack_trace;
ScopedJavaLocalRef<jthrowable> secondary_exception =
Java_JniAndroid_handleException(
env, throwable, ConvertUTF8ToJavaString(env, native_stack_trace));
Java_JniAndroid_handleException(env, throwable, native_stack_trace);
// Ideally handleException() should have terminated the process and we should
// not get here. This can happen in the case of OutOfMemoryError or if the
@ -227,11 +225,11 @@ void CheckException(JNIEnv* env) {
std::string GetJavaExceptionInfo(JNIEnv* env,
const JavaRef<jthrowable>& throwable) {
ScopedJavaLocalRef<jstring> sanitized_exception_string =
std::string sanitized_exception_string =
Java_JniAndroid_sanitizedStacktraceForUnhandledException(env, throwable);
// Returns null when PiiElider results in an OutOfMemoryError.
return sanitized_exception_string
? ConvertJavaStringToUTF8(sanitized_exception_string)
return !sanitized_exception_string.empty()
? sanitized_exception_string
: kOomInGetJavaExceptionInfoMessage;
}

View file

@ -23,7 +23,7 @@ namespace base {
namespace android {
// Used to mark symbols to be exported in a shared library's symbol table.
#define JNI_EXPORT __attribute__ ((visibility("default")))
#define JNI_EXPORT __attribute__((visibility("default")))
// Contains the registration method information for initializing JNI bindings.
struct RegistrationMethod {
@ -91,7 +91,6 @@ inline ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env,
return jni_zero::GetClass(env, class_name);
}
// Returns true if an exception is pending in the provided JNIEnv*.
inline bool HasException(JNIEnv* env) {
return jni_zero::HasException(env);

Some files were not shown because too many files have changed in this diff Show more