Compare commits

...

No commits in common. "43d9635938309c9dd331cfb8302a840e2818a9a7" and "676417d610798e47d16d439f046fc57e71baa4dc" have entirely different histories.

2291 changed files with 27086 additions and 35893 deletions

View File

@ -123,7 +123,7 @@ jobs:
- name: Cache sysroot - name: Cache sysroot
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: src/out/sysroot-build/bullseye/bullseye_* path: src/out/sysroot-build/sid/sid_*
key: sysroot-linux-${{ matrix.arch }}-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }} key: sysroot-linux-${{ matrix.arch }}-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }}
- id: ccache-timestamp - id: ccache-timestamp
run: echo "::set-output name=date::$(date +%s)" run: echo "::set-output name=date::$(date +%s)"

View File

@ -1 +1 @@
102.0.5005.61 101.0.4951.41

View File

@ -82,12 +82,6 @@ no_check_targets = [
"//v8:cppgc_base", # 1 error "//v8:cppgc_base", # 1 error
"//v8:v8_internal_headers", # 11 errors "//v8:v8_internal_headers", # 11 errors
"//v8:v8_libplatform", # 2 errors "//v8:v8_libplatform", # 2 errors
# After making partition_alloc a standalone library, remove partition_alloc
# target from the skip list, because partition_aloc will depend on its own
# base.
# partition alloc standalone library bug is https://crbug.com/1151236.
"//base/allocator/partition_allocator:partition_alloc", # 292 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 whitelist exists

View File

@ -92,7 +92,6 @@ anatoly techtonik <techtonik@gmail.com>
Ancil George <ancilgeorge@samsung.com> Ancil George <ancilgeorge@samsung.com>
Andra Paraschiv <andra.paraschiv@intel.com> Andra Paraschiv <andra.paraschiv@intel.com>
Andras Tokodi <a.tokodi@eyeo.com> Andras Tokodi <a.tokodi@eyeo.com>
Andreas Nazlidis <andreas221b@gmail.com>
Andreas Papacharalampous <andreas@apap04.com> Andreas Papacharalampous <andreas@apap04.com>
Andrei Borza <andrei.borza@gmail.com> Andrei Borza <andrei.borza@gmail.com>
Andrei Parvu <andrei.prv@gmail.com> Andrei Parvu <andrei.prv@gmail.com>
@ -116,13 +115,11 @@ Anne Kao <annekao94@gmail.com>
Anshul Jain <anshul.jain@samsung.com> Anshul Jain <anshul.jain@samsung.com>
Anssi Hannula <anssi.hannula@iki.fi> Anssi Hannula <anssi.hannula@iki.fi>
Anthony Halliday <anth.halliday12@gmail.com> Anthony Halliday <anth.halliday12@gmail.com>
Anton Bershanskiy <8knots@protonmail.com> Anton Bershanskiy <bershanskiy@pm.me>
Anton Obzhirov <a.obzhirov@samsung.com> Anton Obzhirov <a.obzhirov@samsung.com>
Antonin Hildebrand <antonin.hildebrand@gmail.com> Antonin Hildebrand <antonin.hildebrand@gmail.com>
Antonio Gomes <a1.gomes@sisa.samsung.com> Antonio Gomes <a1.gomes@sisa.samsung.com>
Anuj Kumar Sharma <anujk.sharma@samsung.com> Anuj Kumar Sharma <anujk.sharma@samsung.com>
Ao Sun <ntusunao@gmail.com>
Ao Wang <wangao.james@bytedance.com>
Arjun Karthik <arjunkar@amazon.com> Arjun Karthik <arjunkar@amazon.com>
Arman Ghotb <armanghotb@gmail.com> Arman Ghotb <armanghotb@gmail.com>
Armin Burgmeier <aburgmeier@bloomberg.net> Armin Burgmeier <aburgmeier@bloomberg.net>
@ -251,7 +248,6 @@ Daniel Bomar <dbdaniel42@gmail.com>
Daniel Carvalho Liedke <dliedke@gmail.com> Daniel Carvalho Liedke <dliedke@gmail.com>
Daniel Charles <daniel.charles@intel.com> Daniel Charles <daniel.charles@intel.com>
Daniel Imms <daniimms@amazon.com> Daniel Imms <daniimms@amazon.com>
Daniel Izquierdo <daniel.izquierdo@gmail.com>
Daniel Johnson <danielj41@gmail.com> Daniel Johnson <danielj41@gmail.com>
Daniel Lockyer <thisisdaniellockyer@gmail.com> Daniel Lockyer <thisisdaniellockyer@gmail.com>
Daniel Nishi <dhnishi@gmail.com> Daniel Nishi <dhnishi@gmail.com>
@ -353,7 +349,6 @@ Evgeniy Dushistov <dushistov@gmail.com>
Evgeny Agafonchikov <evgeny.agafonchikov@akvelon.com> Evgeny Agafonchikov <evgeny.agafonchikov@akvelon.com>
Fabian Henneke <fabian.henneke@gmail.com> Fabian Henneke <fabian.henneke@gmail.com>
Fabien Tassin <fta@sofaraway.org> Fabien Tassin <fta@sofaraway.org>
Feifei Wang <alexswang@tencent.com>
Felipe Erias Morandeira <felipeerias@gmail.com> Felipe Erias Morandeira <felipeerias@gmail.com>
Felix H. Dahlke <fhd@ubercode.de> Felix H. Dahlke <fhd@ubercode.de>
Felix Weilbach <feweilbach@gmail.com> Felix Weilbach <feweilbach@gmail.com>
@ -581,7 +576,6 @@ Jongsoo Lee <leejongsoo@gmail.com>
Joone Hur <joone.hur@intel.com> Joone Hur <joone.hur@intel.com>
Joonghun Park <pjh0718@gmail.com> Joonghun Park <pjh0718@gmail.com>
Jorge Villatoro <jorge@tomatocannon.com> Jorge Villatoro <jorge@tomatocannon.com>
Jorrit Jongma <jorrit@jongma.org>
Joseph Gentle <josephg@gmail.com> Joseph Gentle <josephg@gmail.com>
Joseph Lolak <joseph.lolak@samsung.com> Joseph Lolak <joseph.lolak@samsung.com>
Josh Triplett <josh.triplett@intel.com> Josh Triplett <josh.triplett@intel.com>
@ -719,7 +713,6 @@ Luke Seunghoe Gu <gulukesh@gmail.com>
Luke Zarko <lukezarko@gmail.com> Luke Zarko <lukezarko@gmail.com>
Luoxi Pan <l.panpax@gmail.com> Luoxi Pan <l.panpax@gmail.com>
Lu Yahan <yahan@iscas.ac.cn> Lu Yahan <yahan@iscas.ac.cn>
Ma Aiguo <maaiguo@uniontech.com>
Maarten Lankhorst <m.b.lankhorst@gmail.com> Maarten Lankhorst <m.b.lankhorst@gmail.com>
Maciej Pawlowski <m.pawlowski@eyeo.com> Maciej Pawlowski <m.pawlowski@eyeo.com>
Magnus Danielsson <fuzzac@gmail.com> Magnus Danielsson <fuzzac@gmail.com>
@ -956,7 +949,6 @@ Ravi Nanjundappa <nravi.n@samsung.com>
Ravi Phaneendra Kasibhatla <r.kasibhatla@samsung.com> Ravi Phaneendra Kasibhatla <r.kasibhatla@samsung.com>
Ravi Phaneendra Kasibhatla <ravi.kasibhatla@motorola.com> Ravi Phaneendra Kasibhatla <ravi.kasibhatla@motorola.com>
Raviraj Sitaram <raviraj.p.sitaram@intel.com> Raviraj Sitaram <raviraj.p.sitaram@intel.com>
Rebecca Chang Swee Fun <rebecca.chang@starfivetech.com>
Reda Tawfik <redatawfik@noogler.google.com> Reda Tawfik <redatawfik@noogler.google.com>
Réda Housni Alaoui <alaoui.rda@gmail.com> Réda Housni Alaoui <alaoui.rda@gmail.com>
Refael Ackermann <refack@gmail.com> Refael Ackermann <refack@gmail.com>
@ -1167,7 +1159,6 @@ Tibor Dusnoki <tibor.dusnoki.91@gmail.com>
Tibor Dusnoki <tdusnoki@inf.u-szeged.hu> Tibor Dusnoki <tdusnoki@inf.u-szeged.hu>
Tim Ansell <mithro@mithis.com> Tim Ansell <mithro@mithis.com>
Tim Niederhausen <tim@rnc-ag.de> Tim Niederhausen <tim@rnc-ag.de>
Tim Steiner <twsteiner@gmail.com>
Timo Gurr <timo.gurr@gmail.com> Timo Gurr <timo.gurr@gmail.com>
Timo Reimann <ttr314@googlemail.com> Timo Reimann <ttr314@googlemail.com>
Timo Witte <timo.witte@gmail.com> Timo Witte <timo.witte@gmail.com>
@ -1242,7 +1233,6 @@ Xiaolei Yu <dreifachstein@gmail.com>
Xiaoshu Zhang <xiaoshu@amazon.com> Xiaoshu Zhang <xiaoshu@amazon.com>
Xiaoyin Liu <xiaoyin.l@outlook.com> Xiaoyin Liu <xiaoyin.l@outlook.com>
Xinchao He <hexinchao@gmail.com> Xinchao He <hexinchao@gmail.com>
Xinchao Tian <tianxinchao@360.cn>
Xing Zhang <xzhang@adobe.com> Xing Zhang <xzhang@adobe.com>
Xinghua Cao <xinghua.cao@intel.com> Xinghua Cao <xinghua.cao@intel.com>
Xu Samuel <samuel.xu@intel.com> Xu Samuel <samuel.xu@intel.com>
@ -1256,7 +1246,6 @@ Xunran Ding <dingxunran@gmail.com>
Yael Aharon <yael.aharon@intel.com> Yael Aharon <yael.aharon@intel.com>
Yan Wang <yan0422.wang@samsung.com> Yan Wang <yan0422.wang@samsung.com>
Yang Gu <yang.gu@intel.com> Yang Gu <yang.gu@intel.com>
Yang Liu <jd9668954@gmail.com>
Yannic Bonenberger <yannic.bonenberger@gmail.com> Yannic Bonenberger <yannic.bonenberger@gmail.com>
Yarin Kaul <yarin.kaul@gmail.com> Yarin Kaul <yarin.kaul@gmail.com>
Yash Vempati <vempatiy@amazon.com> Yash Vempati <vempatiy@amazon.com>
@ -1271,7 +1260,6 @@ Yi Zhang <yi.y.zhang@intel.com>
Yizhou Jiang <yizhou.jiang@intel.com> Yizhou Jiang <yizhou.jiang@intel.com>
Yoav Weiss <yoav@yoav.ws> Yoav Weiss <yoav@yoav.ws>
Yoav Zilberberg <yoav.zilberberg@gmail.com> Yoav Zilberberg <yoav.zilberberg@gmail.com>
Yong Ling <yongling@tencent.com>
Yong Shin <sy3620@gmail.com> Yong Shin <sy3620@gmail.com>
Yong Wang <ccyongwang@tencent.com> Yong Wang <ccyongwang@tencent.com>
Yongha Lee <yongha78.lee@samsung.com> Yongha Lee <yongha78.lee@samsung.com>

248
src/DEPS
View File

@ -105,10 +105,10 @@ vars = {
# be overridden by gclient variables. # be overridden by gclient variables.
'checkout_google_benchmark': False, 'checkout_google_benchmark': False,
# By default, checkout JavaScript coverage node modules. These packages # By default, do not checkout JavaScript coverage node modules. These packages
# are used to post-process raw v8 coverage reports into IstanbulJS compliant # are used to post-process raw v8 coverage reports into IstanbulJS compliant
# output. # output.
'checkout_js_coverage_modules': True, 'checkout_js_coverage_modules': False,
# Check out and download nacl by default, unless on an arm mac. # Check out and download nacl by default, unless on an arm mac.
# This can be disabled e.g. with custom_vars. # This can be disabled e.g. with custom_vars.
@ -213,7 +213,7 @@ vars = {
# luci-go CIPD package version. # luci-go CIPD package version.
# Make sure the revision is uploaded by infra-packagers builder. # Make sure the revision is uploaded by infra-packagers builder.
# https://ci.chromium.org/p/infra-internal/g/infra-packagers/console # https://ci.chromium.org/p/infra-internal/g/infra-packagers/console
'luci_go': 'git_revision:6da0608e4fa8a3c6d1fa4f855485c0038b05bf72', 'luci_go': 'git_revision:cb424e70e75136736a86359ef070aa96425fe7a3',
# This can be overridden, e.g. with custom_vars, to build clang from HEAD # This can be overridden, e.g. with custom_vars, to build clang from HEAD
# instead of downloading the prebuilt pinned revision. # instead of downloading the prebuilt pinned revision.
@ -238,7 +238,7 @@ vars = {
'dawn_standalone': False, 'dawn_standalone': False,
# reclient CIPD package version # reclient CIPD package version
'reclient_version': 're_client_version:0.59.0.7914303-gomaip', 'reclient_version': 're_client_version:0.57.0.4865132-gomaip',
'android_git': 'https://android.googlesource.com', 'android_git': 'https://android.googlesource.com',
'aomedia_git': 'https://aomedia.googlesource.com', 'aomedia_git': 'https://aomedia.googlesource.com',
@ -253,30 +253,30 @@ vars = {
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling Skia # the commit queue can handle CLs rolling Skia
# and whatever else without interference from each other. # and whatever else without interference from each other.
'skia_revision': '3338e90707323d2cd3a150276acb9f39933deee2', 'skia_revision': 'ef69dcf0c2dbda06cd47082f42a2433f7ba86a78',
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling V8 # the commit queue can handle CLs rolling V8
# and whatever else without interference from each other. # and whatever else without interference from each other.
'v8_revision': '87c27db79e6a35a6bdedcbfe732f978812bf6ced', 'v8_revision': 'e92a31cfd7d06ea1b45a428bf90e1c910b3c003c',
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling ANGLE # the commit queue can handle CLs rolling ANGLE
# and whatever else without interference from each other. # and whatever else without interference from each other.
'angle_revision': '6661eb4900dae62cbe9af5023f9c1e7105798b50', 'angle_revision': 'e37380e62a427cbb7172b6c17f8752ab96abf356',
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling SwiftShader # the commit queue can handle CLs rolling SwiftShader
# and whatever else without interference from each other. # and whatever else without interference from each other.
'swiftshader_revision': '103a69bd6c82980c967c2f4002c9a302ea67c716', 'swiftshader_revision': 'd01dca1d18d03f055d0dabd99a210b5f666715ed',
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling PDFium # the commit queue can handle CLs rolling PDFium
# and whatever else without interference from each other. # and whatever else without interference from each other.
'pdfium_revision': '62ad9af8a9f9494645b659674b64bb51775cde05', 'pdfium_revision': 'f4c62094abe20ade3a29328bc370238b7e7812b2',
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling BoringSSL # the commit queue can handle CLs rolling BoringSSL
# and whatever else without interference from each other. # and whatever else without interference from each other.
# #
# Note this revision should be updated with # Note this revision should be updated with
# third_party/boringssl/roll_boringssl.py, not roll-dep. # third_party/boringssl/roll_boringssl.py, not roll-dep.
'boringssl_revision': '27ffcc6e19bbafddf1b59ec0bc6df2904de7eb2c', 'boringssl_revision': '4d955d20d27bcf3ae71df091ad17d95229a7eb56',
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling google-toolbox-for-mac # the commit queue can handle CLs rolling google-toolbox-for-mac
# and whatever else without interference from each other. # and whatever else without interference from each other.
@ -284,7 +284,7 @@ vars = {
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling googletest # the commit queue can handle CLs rolling googletest
# and whatever else without interference from each other. # and whatever else without interference from each other.
'googletest_revision': 'af29db7ec28d6df1c7f0f745186884091e602e07', 'googletest_revision': 'b007c54f2944e193ac44fba1bc997cb65826a0b9',
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling lighttpd # the commit queue can handle CLs rolling lighttpd
# and whatever else without interference from each other. # and whatever else without interference from each other.
@ -296,11 +296,11 @@ vars = {
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling NaCl # the commit queue can handle CLs rolling NaCl
# and whatever else without interference from each other. # and whatever else without interference from each other.
'nacl_revision': 'f231a6e8c08f6733c072ae9cca3ce00f42edd9ff', 'nacl_revision': 'cd81f598e8de34678c9d9de21742c7e56654e8d3',
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling freetype # the commit queue can handle CLs rolling freetype
# and whatever else without interference from each other. # and whatever else without interference from each other.
'freetype_revision': '3100c8120e0ff423db8d8134a8073e639371993e', 'freetype_revision': '1e2eb65048f75c64b68708efed6ce904c31f3b2f',
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling freetype # the commit queue can handle CLs rolling freetype
# and whatever else without interference from each other. # and whatever else without interference from each other.
@ -308,7 +308,7 @@ vars = {
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling HarfBuzz # the commit queue can handle CLs rolling HarfBuzz
# and whatever else without interference from each other. # and whatever else without interference from each other.
'harfbuzz_revision': '6454cec085ba51cefcd12b1f8027bc4a647347d5', 'harfbuzz_revision': '965cf1d66589b0db60e75961cc58f5a65521078e',
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling Emoji Segmenter # the commit queue can handle CLs rolling Emoji Segmenter
# and whatever else without interference from each other. # and whatever else without interference from each other.
@ -320,7 +320,7 @@ vars = {
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling catapult # the commit queue can handle CLs rolling catapult
# and whatever else without interference from each other. # and whatever else without interference from each other.
'catapult_revision': '3cf2f4f0e03be4dc0f4a26cb3943b4a719643e1b', 'catapult_revision': '46cc0e470b61a3ba12ae80efffa41f7c9bb87205',
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling libFuzzer # the commit queue can handle CLs rolling libFuzzer
# and whatever else without interference from each other. # and whatever else without interference from each other.
@ -328,7 +328,7 @@ vars = {
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling devtools-frontend # the commit queue can handle CLs rolling devtools-frontend
# and whatever else without interference from each other. # and whatever else without interference from each other.
'devtools_frontend_revision': '46a28a3c5dadb2a79680c35a61000e908aee74dc', 'devtools_frontend_revision': 'b2a3923617328a970bf07eca721bb8f6ad9c4574',
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling libprotobuf-mutator # the commit queue can handle CLs rolling libprotobuf-mutator
# and whatever else without interference from each other. # and whatever else without interference from each other.
@ -364,11 +364,15 @@ vars = {
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling feed # the commit queue can handle CLs rolling feed
# and whatever else without interference from each other. # and whatever else without interference from each other.
'dawn_revision': 'fa8cc68ff7c055512e83a538e5517400f5f053bc', 'shaderc_revision': '96b1dd72a827304817470274a470c4d3b2293451',
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling feed # the commit queue can handle CLs rolling feed
# and whatever else without interference from each other. # and whatever else without interference from each other.
'quiche_revision': '7e841d3541a113b5ed577824c9aa71b8a1c7617f', 'dawn_revision': '211e96c6069c66c6d503cfa2b35226c7118c7927',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling feed
# and whatever else without interference from each other.
'quiche_revision': '41a1bdecabbd03b35702bacb51f6b14775a07e4d',
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling ios_webkit # the commit queue can handle CLs rolling ios_webkit
# and whatever else without interference from each other. # and whatever else without interference from each other.
@ -388,11 +392,11 @@ vars = {
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling libavif # the commit queue can handle CLs rolling libavif
# and whatever else without interference from each other. # and whatever else without interference from each other.
'libavif_revision': 'ccf5a781238b43fee428519ba6e9508204835b9c', 'libavif_revision': '632d13188f9b7faa40f20d870e792174b8b5b8e6',
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling nearby # the commit queue can handle CLs rolling nearby
# and whatever else without interference from each other. # and whatever else without interference from each other.
'nearby_revision': '0c8838ad9b9ba5e03ea9dadd0cba5f4ea9c949fd', 'nearby_revision': '517d77f5aa4fea8f4437125830cfc55f84705e3d',
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling securemessage # the commit queue can handle CLs rolling securemessage
# and whatever else without interference from each other. # and whatever else without interference from each other.
@ -404,15 +408,15 @@ vars = {
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling feed # the commit queue can handle CLs rolling feed
# and whatever else without interference from each other. # and whatever else without interference from each other.
'resultdb_version': 'git_revision:6cc18e2763e180929d70c786b419c1f8e6bcc66c', 'resultdb_version': 'git_revision:735a8a662d3874d8b1d795a40e46ea0f57b52758',
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling feed # the commit queue can handle CLs rolling feed
# and whatever else without interference from each other. # and whatever else without interference from each other.
'libcxxabi_revision': 'e025ba5dc85202540099d7cd8e72eae2d4ee9e33', 'libcxxabi_revision': '93b8dcd57bd8ebe201ec24f7257339988ed2ef7c',
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling feed # the commit queue can handle CLs rolling feed
# and whatever else without interference from each other. # and whatever else without interference from each other.
'libunwind_revision': '1acfbbb4747081789ba48bc8c042fa3c5c8ccaa3', 'libunwind_revision': 'd1c7f92b8b0bff8d9f710ca40e44563a63db376e',
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling feed # the commit queue can handle CLs rolling feed
# and whatever else without interference from each other. # and whatever else without interference from each other.
@ -431,7 +435,7 @@ vars = {
'libcxx_revision': '79a2e924d96e2fc1e4b937c42efd08898fa472d7', 'libcxx_revision': '79a2e924d96e2fc1e4b937c42efd08898fa472d7',
# GN CIPD package version. # GN CIPD package version.
'gn_version': 'git_revision:fd9f2036f26d83f9fcfe93042fb952e5a7fe2167', 'gn_version': 'git_revision:bd99dbf98cbdefe18a4128189665c5761263bcfb',
} }
# Only these hosts are allowed for dependencies in this DEPS file. # Only these hosts are allowed for dependencies in this DEPS file.
@ -558,7 +562,7 @@ deps = {
'packages': [ 'packages': [
{ {
'package': 'chromium/android_webview/tools/cts_archive', 'package': 'chromium/android_webview/tools/cts_archive',
'version': 'rzLrTykLB2J7ON1a9_5F7qmkjH3U246nHDPHiTruibUC', 'version': 'ai8Ig4HlO0vG6aP_JP2uhyruE2yPzze8PFP1g8Z4_hgC',
}, },
], ],
'condition': 'checkout_android', 'condition': 'checkout_android',
@ -654,6 +658,17 @@ deps = {
], ],
}, },
'src/tools/clang/dsymutil': {
'packages': [
{
'package': 'chromium/llvm-build-tools/dsymutil',
'version': 'M56jPzDv1620Rnm__jTMYS62Zi8rxHVq7yw0qeBFEgkC',
}
],
'condition': 'checkout_mac or checkout_ios',
'dep_type': 'cipd',
},
'src/chrome/test/data/autofill/captured_sites': { 'src/chrome/test/data/autofill/captured_sites': {
'packages': [ 'packages': [
{ {
@ -720,16 +735,16 @@ deps = {
Var('chromium_git') + '/external/github.com/toji/webvr.info.git' + '@' + 'c58ae99b9ff9e2aa4c524633519570bf33536248', Var('chromium_git') + '/external/github.com/toji/webvr.info.git' + '@' + 'c58ae99b9ff9e2aa4c524633519570bf33536248',
'src/docs/website': { 'src/docs/website': {
'url': Var('chromium_git') + '/website.git' + '@' + '17a7f6a95704dc84abc24ba06252d048de1f54df', 'url': Var('chromium_git') + '/website.git' + '@' + '9f939dcab5c4c8fc5be67578d2da6236349cbd49',
}, },
'src/ios/third_party/earl_grey2/src': { 'src/ios/third_party/earl_grey2/src': {
'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '98801869816f5272ad89f7f66bec7941960a28ea', 'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '583953e8001af0d0242d6464b382420ccab6bb18',
'condition': 'checkout_ios', 'condition': 'checkout_ios',
}, },
'src/ios/third_party/edo/src': { 'src/ios/third_party/edo/src': {
'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git' + '@' + '727e556705278598fce683522beedbb9946bfda0', 'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git' + '@' + 'f7dea1a5bdc745493aeffece692a4883e85c0e78',
'condition': 'checkout_ios', 'condition': 'checkout_ios',
}, },
@ -744,7 +759,7 @@ deps = {
}, },
'src/ios/third_party/material_components_ios/src': { 'src/ios/third_party/material_components_ios/src': {
'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '04424d224ee9e98c7e5a31e140e31105f07e73f1', 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '5dce9626ae787c33d7bdbda5f156c1415b986c08',
'condition': 'checkout_ios', 'condition': 'checkout_ios',
}, },
@ -825,7 +840,7 @@ deps = {
'packages': [ 'packages': [
{ {
'package': 'chromium/rts/model/linux-amd64', 'package': 'chromium/rts/model/linux-amd64',
'version': 'YoP4kTClaepmmjRqVgIPL-uE44odWGlVM8pBRVdTx2AC', 'version': 'l1xDoCBm1rDEFIlePkzB2hTG4r1YvYoxdNBU3SGjTDoC',
}, },
], ],
'dep_type': 'cipd', 'dep_type': 'cipd',
@ -836,7 +851,7 @@ deps = {
'packages': [ 'packages': [
{ {
'package': 'chromium/rts/model/mac-amd64', 'package': 'chromium/rts/model/mac-amd64',
'version': 'mL4NyynmT1Ubjyy2JUXN4SX80VIVKV66MfgBDu-HLRAC', 'version': 'ScMUxoCQFi3vFXDAlBj3VezWCnqk9hxpFW8GznMw454C',
}, },
], ],
'dep_type': 'cipd', 'dep_type': 'cipd',
@ -847,7 +862,7 @@ deps = {
'packages': [ 'packages': [
{ {
'package': 'chromium/rts/model/windows-amd64', 'package': 'chromium/rts/model/windows-amd64',
'version': 'le7Fn-9wOJ6Ob24B0IvVQY_Sss-rzfQ9xaeovuM0WSUC', 'version': 'iZunll1kgfbUFl7u6t5VnY4-MHcjb72ZS9UVDhTAr8cC',
}, },
], ],
'dep_type': 'cipd', 'dep_type': 'cipd',
@ -868,6 +883,10 @@ deps = {
'dep_type': 'cipd', 'dep_type': 'cipd',
}, },
'src/third_party/shaderc/src':
Var('chromium_git') + '/external/github.com/google/shaderc.git@' +
Var('shaderc_revision'),
'src/third_party/accessibility_test_framework': { 'src/third_party/accessibility_test_framework': {
'packages': [ 'packages': [
{ {
@ -896,7 +915,7 @@ deps = {
}, },
'src/third_party/android_ndk': { 'src/third_party/android_ndk': {
'url': Var('chromium_git') + '/android_ndk.git' + '@' + '8388a2be5421311dc75c5f937aae13d821a27f3d', 'url': Var('chromium_git') + '/android_ndk.git' + '@' + '9644104c8cf85bf1bdce5b1c0691e9778572c3f8',
'condition': 'checkout_android_native_support', 'condition': 'checkout_android_native_support',
}, },
@ -937,7 +956,7 @@ deps = {
'packages': [ 'packages': [
{ {
'package': 'chromium/third_party/android_build_tools/aapt2', 'package': 'chromium/third_party/android_build_tools/aapt2',
'version': 'u2Cw4baoLfvlEDMwcJjq9iOJRF0_2BjsgMFl7UhJxGAC', 'version': 'wicn5Ce1ay6ivbZ1GNFF0gRSS3NYv_7hJTPtVga3O-QC',
}, },
], ],
'condition': 'checkout_android', 'condition': 'checkout_android',
@ -948,7 +967,7 @@ deps = {
'packages': [ 'packages': [
{ {
'package': 'chromium/third_party/android_build_tools/bundletool', 'package': 'chromium/third_party/android_build_tools/bundletool',
'version': 'zQILIUnCaQ93HTtR07m4ahlE9mrkkwks52L5vFaUaUUC', 'version': 'LoldiQDpZ0uTdAm5EPgZ8hBJ3La2KlTWLuaRxE7eDigC',
}, },
], ],
'condition': 'checkout_android', 'condition': 'checkout_android',
@ -1003,7 +1022,7 @@ deps = {
Var('chromium_git') + '/angle/angle.git' + '@' + Var('angle_revision'), Var('chromium_git') + '/angle/angle.git' + '@' + Var('angle_revision'),
'src/third_party/dav1d/libdav1d': 'src/third_party/dav1d/libdav1d':
Var('chromium_git') + '/external/github.com/videolan/dav1d.git' + '@' + '87f9a81cd770e49394a45deca7a3df41243de00b', Var('chromium_git') + '/external/github.com/videolan/dav1d.git' + '@' + 'b1a5189c9d37c837099ce50852b6ce9597b89b0c',
'src/third_party/dawn': 'src/third_party/dawn':
Var('dawn_git') + '/dawn.git' + '@' + Var('dawn_revision'), Var('dawn_git') + '/dawn.git' + '@' + Var('dawn_revision'),
@ -1027,6 +1046,17 @@ deps = {
'condition': 'checkout_src_internal and checkout_chromeos', 'condition': 'checkout_src_internal and checkout_chromeos',
}, },
'src/third_party/cast_core/prebuilts': {
'packages': [
{
'package': 'cast3p/cast_core/package_qa_vizio_castos_armv7a.tar',
'version': 'ZOzcgmEj32ltQEYvSSBfLbwcEo4MA_qtruinWrbbpGAC',
},
],
'condition': 'checkout_cast3p',
'dep_type': 'cipd',
},
'src/third_party/google_benchmark/src': { 'src/third_party/google_benchmark/src': {
'url': Var('chromium_git') + '/external/github.com/google/benchmark.git' + '@' + 'f730846b0a3c0dc0699978846fb14ffb2fad0bdc', 'url': Var('chromium_git') + '/external/github.com/google/benchmark.git' + '@' + 'f730846b0a3c0dc0699978846fb14ffb2fad0bdc',
'condition': 'checkout_google_benchmark', 'condition': 'checkout_google_benchmark',
@ -1047,7 +1077,7 @@ deps = {
}, },
'src/third_party/breakpad/breakpad': 'src/third_party/breakpad/breakpad':
Var('chromium_git') + '/breakpad/breakpad.git' + '@' + '8b68c72a3fff2bb687c7f411e5c1c09e356b8603', Var('chromium_git') + '/breakpad/breakpad.git' + '@' + '08bd844599bf04c71707e8f59a8013a941264695',
'src/third_party/byte_buddy': { 'src/third_party/byte_buddy': {
'packages': [ 'packages': [
@ -1101,12 +1131,12 @@ deps = {
# Tools used when building Chrome for Chrome OS. This affects both the Simple # Tools used when building Chrome for Chrome OS. This affects both the Simple
# Chrome workflow, as well as the chromeos-chrome ebuild. # Chrome workflow, as well as the chromeos-chrome ebuild.
'src/third_party/chromite': { 'src/third_party/chromite': {
'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'eb3547e17504b0d603b4faf2b0caebcc5d9dca93', 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '3d2387a672b437b2d32d83120080a5e593b0e5af',
'condition': 'checkout_chromeos', 'condition': 'checkout_chromeos',
}, },
'src/third_party/cld_3/src': 'src/third_party/cld_3/src':
Var('chromium_git') + '/external/github.com/google/cld_3.git' + '@' + 'b48dc46512566f5a2d41118c8c1116c4f96dc661', Var('chromium_git') + '/external/github.com/google/cld_3.git' + '@' + '576305689d23da93e2f5e04a3de5afbe60d339da',
'src/third_party/colorama/src': 'src/third_party/colorama/src':
Var('chromium_git') + '/external/colorama.git' + '@' + '799604a1041e9b3bc5d2789ecbd7e8db2e18e6b8', Var('chromium_git') + '/external/colorama.git' + '@' + '799604a1041e9b3bc5d2789ecbd7e8db2e18e6b8',
@ -1116,12 +1146,12 @@ deps = {
# For Linux and Chromium OS. # For Linux and Chromium OS.
'src/third_party/cros_system_api': { 'src/third_party/cros_system_api': {
'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '90c3a2f21e7d8c6668c9f7daaaf39c5fd8ffe58a', 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '82881bbde1f5ec168806e3b144622aefd66bb2ae',
'condition': 'checkout_linux', 'condition': 'checkout_linux',
}, },
'src/third_party/depot_tools': 'src/third_party/depot_tools':
Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '932a621ece2316026926d615bb04d3006077ab79', Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '950a6b4225ed3280aa0fbca2de51bfbaecd7695a',
'src/third_party/devtools-frontend/src': 'src/third_party/devtools-frontend/src':
Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@ -1152,7 +1182,7 @@ deps = {
Var('chromium_git') + '/external/github.com/google/farmhash.git' + '@' + '816a4ae622e964763ca0862d9dbd19324a1eaf45', Var('chromium_git') + '/external/github.com/google/farmhash.git' + '@' + '816a4ae622e964763ca0862d9dbd19324a1eaf45',
'src/third_party/ffmpeg': 'src/third_party/ffmpeg':
Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + 'e481fc655a6287e657a88e8c2bcd6f411d254d70', Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '574c39cce3231c69bc9a02ac475c27d944bdb113',
'src/third_party/flac': 'src/third_party/flac':
Var('chromium_git') + '/chromium/deps/flac.git' + '@' + 'af862024c8c8fa0ae07ced05e89013d881b00596', Var('chromium_git') + '/chromium/deps/flac.git' + '@' + 'af862024c8c8fa0ae07ced05e89013d881b00596',
@ -1173,7 +1203,7 @@ deps = {
Var('chromium_git') + '/external/github.com/google/gemmlowp.git' + '@' + '13d57703abca3005d97b19df1f2db731607a7dc2', Var('chromium_git') + '/external/github.com/google/gemmlowp.git' + '@' + '13d57703abca3005d97b19df1f2db731607a7dc2',
'src/third_party/grpc/src': { 'src/third_party/grpc/src': {
'url': Var('chromium_git') + '/external/github.com/grpc/grpc.git' + '@' + 'ee2b75e33740d1a88c0e2aeec1b14435e17a889e', 'url': Var('chromium_git') + '/external/github.com/grpc/grpc.git' + '@' + '2a0d6234cb2ccebb265c035ffd09ecc9a347b4bf',
}, },
'src/third_party/freetype/src': 'src/third_party/freetype/src':
@ -1261,7 +1291,7 @@ deps = {
Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + '41cdffd71c9948f63c7ad36e1fb0ff519aa7a37e', Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + '41cdffd71c9948f63c7ad36e1fb0ff519aa7a37e',
'src/third_party/icu': 'src/third_party/icu':
Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'e1f2f4f42368555835a7a0894188716556c32871', Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'ea8c08d8783fceda86c19618694881149e23f305',
'src/third_party/icu4j': { 'src/third_party/icu4j': {
'packages': [ 'packages': [
@ -1332,7 +1362,7 @@ deps = {
Var('chromium_git') + '/external/libaddressinput.git' + '@' + '3b8ee157a8f3536bbf5ad2448e9e3370463c1e40', Var('chromium_git') + '/external/libaddressinput.git' + '@' + '3b8ee157a8f3536bbf5ad2448e9e3370463c1e40',
'src/third_party/libaom/source/libaom': 'src/third_party/libaom/source/libaom':
Var('aomedia_git') + '/aom.git' + '@' + 'e24a83a72b507b93a94f299f0eead1213dbac214', Var('aomedia_git') + '/aom.git' + '@' + 'ee1ed1ccf2b9ecedd6aee438eafc7cc61c23342d',
'src/third_party/libavif/src': 'src/third_party/libavif/src':
Var('chromium_git') + '/external/github.com/AOMediaCodec/libavif.git' + '@' + Var('libavif_revision'), Var('chromium_git') + '/external/github.com/AOMediaCodec/libavif.git' + '@' + Var('libavif_revision'),
@ -1365,7 +1395,7 @@ deps = {
Var('chromium_git') + '/chromium/deps/libjpeg_turbo.git' + '@' + '22f1a22c99e9dde8cd3c72ead333f425c5a7aa77', Var('chromium_git') + '/chromium/deps/libjpeg_turbo.git' + '@' + '22f1a22c99e9dde8cd3c72ead333f425c5a7aa77',
'src/third_party/liblouis/src': { 'src/third_party/liblouis/src': {
'url': Var('chromium_git') + '/external/liblouis-github.git' + '@' + 'c05f3bfb0990434bd12bf6697d16ed943f2203c2', 'url': Var('chromium_git') + '/external/liblouis-github.git' + '@' + '10f66b2735b7d1e3e44d98f6dedbb859d197ea57',
'condition': 'checkout_linux', 'condition': 'checkout_linux',
}, },
@ -1390,13 +1420,13 @@ deps = {
}, },
'src/third_party/libvpx/source/libvpx': 'src/third_party/libvpx/source/libvpx':
Var('chromium_git') + '/webm/libvpx.git' + '@' + 'bf672f23a5336cb54dbcb2e4417142139f44cc3e', Var('chromium_git') + '/webm/libvpx.git' + '@' + 'df0d06de6d3b64e35b9e75ad72c571af061bc7b3',
'src/third_party/libwebm/source': 'src/third_party/libwebm/source':
Var('chromium_git') + '/webm/libwebm.git' + '@' + 'e4fbea0c9751ae8aa86629b197a28d8276a2b0da', Var('chromium_git') + '/webm/libwebm.git' + '@' + 'e4fbea0c9751ae8aa86629b197a28d8276a2b0da',
'src/third_party/libyuv': 'src/third_party/libyuv':
Var('chromium_git') + '/libyuv/libyuv.git' + '@' + '18f91105162a6ebe7a46ee1c81e9ab67ca97a02b', Var('chromium_git') + '/libyuv/libyuv.git' + '@' + '3aebf69d668177e7ee6dbbe0025e5c3dbb525ff2',
'src/third_party/lighttpd': { 'src/third_party/lighttpd': {
'url': Var('chromium_git') + '/chromium/deps/lighttpd.git' + '@' + Var('lighttpd_revision'), 'url': Var('chromium_git') + '/chromium/deps/lighttpd.git' + '@' + Var('lighttpd_revision'),
@ -1487,7 +1517,7 @@ deps = {
Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + 'b52786888ddce9d6bc06b7825ba9bffc65924e0c', Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + 'b52786888ddce9d6bc06b7825ba9bffc65924e0c',
'src/third_party/openscreen/src': 'src/third_party/openscreen/src':
Var('chromium_git') + '/openscreen' + '@' + 'ee7d4e8c5eb35509288a8f238bbf8ef9c3cb9d35', Var('chromium_git') + '/openscreen' + '@' + 'adafe0ae3ed0032a6f96db719f26c511d09f1518',
'src/third_party/openxr/src': { 'src/third_party/openxr/src': {
'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + 'bf21ccb1007bb531b45d9978919a56ea5059c245', 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + 'bf21ccb1007bb531b45d9978919a56ea5059c245',
@ -1504,7 +1534,7 @@ deps = {
}, },
'src/third_party/perfetto': 'src/third_party/perfetto':
Var('android_git') + '/platform/external/perfetto.git' + '@' + '4c15672c0a9e16ac762aa5148f1264350fd49b98', Var('android_git') + '/platform/external/perfetto.git' + '@' + '943905de31ebf8d6a35016a170457dbae3efbecc',
'src/third_party/perl': { 'src/third_party/perl': {
'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@ -1529,7 +1559,7 @@ deps = {
}, },
'src/third_party/quic_trace/src': 'src/third_party/quic_trace/src':
Var('chromium_git') + '/external/github.com/google/quic-trace.git' + '@' + 'c7b993eb750e60c307e82f75763600d9c06a6de1', Var('chromium_git') + '/external/github.com/google/quic-trace.git' + '@' + '413c3a4a641c014193eabb8d282c2348ccec3c5b',
'src/third_party/pywebsocket3/src': 'src/third_party/pywebsocket3/src':
Var('chromium_git') + '/external/github.com/GoogleChromeLabs/pywebsocket3.git' + '@' + '50602a14f1b6da17e0b619833a13addc6ea78bc2', Var('chromium_git') + '/external/github.com/GoogleChromeLabs/pywebsocket3.git' + '@' + '50602a14f1b6da17e0b619833a13addc6ea78bc2',
@ -1582,7 +1612,7 @@ deps = {
'packages': [ 'packages': [
{ {
'package': 'fuchsia/third_party/android/aemu/release/linux-amd64', 'package': 'fuchsia/third_party/android/aemu/release/linux-amd64',
'version': 'lbYV0rO8V4GxeqmRrKZeRgQmbFxh2BwafFgd9cjYmWYC' 'version': 'jbMpjSzTRngktfwC6FszY0ASXYXkR77i2_dDrvQsa9oC'
}, },
], ],
'condition': 'host_os == "linux" and checkout_fuchsia', 'condition': 'host_os == "linux" and checkout_fuchsia',
@ -1601,7 +1631,7 @@ deps = {
}, },
'src/third_party/re2/src': 'src/third_party/re2/src':
Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + 'f5c782e5d02b3e7f244274c9b6d9d3d7a9b6e737', Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + '3be7d1b6b486ecd47b0daa58210051e29fb31122',
'src/third_party/r8': { 'src/third_party/r8': {
'packages': [ 'packages': [
@ -1643,7 +1673,7 @@ deps = {
Var('chromium_git') + '/external/github.com/google/snappy.git' + '@' + '65dc7b383985eb4f63cd3e752136db8d9b4be8c0', Var('chromium_git') + '/external/github.com/google/snappy.git' + '@' + '65dc7b383985eb4f63cd3e752136db8d9b4be8c0',
'src/third_party/sqlite/src': 'src/third_party/sqlite/src':
Var('chromium_git') + '/chromium/deps/sqlite.git' + '@' + 'a54d5d154f4b349705a67107ed190d1943f94646', Var('chromium_git') + '/chromium/deps/sqlite.git' + '@' + '803a31044a01ca3984f7c321c8821974e4100d07',
'src/third_party/sqlite4java': { 'src/third_party/sqlite4java': {
'packages': [ 'packages': [
@ -1656,31 +1686,22 @@ deps = {
'dep_type': 'cipd', 'dep_type': 'cipd',
}, },
'src/third_party/swift-format': {
'packages': [
{
'package': 'infra/3pp/tools/swift-format/${{platform}}',
'version': 'version:2@505.chromium.1',
},
],
'condition': 'host_os == mac',
'dep_type': 'cipd',
},
'src/third_party/swiftshader': 'src/third_party/swiftshader':
Var('swiftshader_git') + '/SwiftShader.git' + '@' + Var('swiftshader_revision'), Var('swiftshader_git') + '/SwiftShader.git' + '@' + Var('swiftshader_revision'),
'src/third_party/text-fragments-polyfill/src': 'src/third_party/text-fragments-polyfill/src': {
Var('chromium_git') + '/external/github.com/GoogleChromeLabs/text-fragments-polyfill.git' + '@' + '428dd13167f3ce02e3ca7c086d291d7c079da0dc', 'url': Var('chromium_git') + '/external/github.com/GoogleChromeLabs/text-fragments-polyfill.git' + '@' + '5959682856f165b1dc7ddeecdc9d890bfaeb6449',
'condition': 'checkout_ios',
},
'src/third_party/tflite/src': 'src/third_party/tflite/src':
Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + '551a50e768fc48db8e68356a575763278fa1b3b6', Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + '9768822159624e54ade255b55b8e6a6c7ec5a962',
'src/third_party/turbine': { 'src/third_party/turbine': {
'packages': [ 'packages': [
{ {
'package': 'chromium/third_party/turbine', 'package': 'chromium/third_party/turbine',
'version': 'y4x80kUnDOxC5QyG48MlVoiRIEn09eaHcIJQFavlqgMC', 'version': 'Go9J3Mz5ankZAgxmn5GxeXKdEDV73zaZp2ojNfGC1RQC',
}, },
], ],
'condition': 'checkout_android', 'condition': 'checkout_android',
@ -1692,7 +1713,10 @@ deps = {
'condition': 'checkout_android', 'condition': 'checkout_android',
}, },
'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@65b7b8de281ca44627456ade69c7cba884bd1c87', 'src/third_party/usrsctp/usrsctplib':
Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + '62d7d0c928c9a040dce96aa2f16c00e7e67d59cb',
'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@5fe1b21d6ba47a8dee59068d6927a4c157ec13a3',
'src/third_party/vulkan_memory_allocator': 'src/third_party/vulkan_memory_allocator':
Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907', Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907',
@ -1705,7 +1729,7 @@ deps = {
# Wayland protocols that add functionality not available in the core protocol. # Wayland protocols that add functionality not available in the core protocol.
'src/third_party/wayland-protocols/src': { 'src/third_party/wayland-protocols/src': {
'url': Var('chromium_git') + '/external/anongit.freedesktop.org/git/wayland/wayland-protocols.git' + '@' + 'd324986823519c15b2162fc3e0a720f349e43b0c', 'url': Var('chromium_git') + '/external/anongit.freedesktop.org/git/wayland/wayland-protocols.git' + '@' + '177ff9119da526462e5d35fbfde6c84794913787',
'condition': 'checkout_linux', 'condition': 'checkout_linux',
}, },
@ -1728,10 +1752,10 @@ deps = {
Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'cf04aebdf9b53bb2853f22a81465688daf879ec6', Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'cf04aebdf9b53bb2853f22a81465688daf879ec6',
'src/third_party/webgpu-cts/src': 'src/third_party/webgpu-cts/src':
Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '958d732db02c2a70bcf4a2b0986f09318db4adfb', Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'a630866d89f74aa95cf3aecd78987637ee195b68',
'src/third_party/webrtc': 'src/third_party/webrtc':
Var('webrtc_git') + '/src.git' + '@' + '6ff73180ad01aca444c9856f91148eb2b948ce63', Var('webrtc_git') + '/src.git' + '@' + '34e12465a46da3c220eab0489881cd89a4d659d2',
'src/third_party/libgifcodec': 'src/third_party/libgifcodec':
Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'),
@ -1758,7 +1782,7 @@ deps = {
'packages': [ 'packages': [
{ {
'package': 'skia/tools/goldctl/linux-amd64', 'package': 'skia/tools/goldctl/linux-amd64',
'version': 'iqtz2prn9CUv6A8KCcxJzadmPEDLY1FPP-b2YqIFQ1cC', 'version': 'wjKDZ5vJELJ_j3O037nIWhBEMF0cY4Y1g4tLc47hPJoC',
}, },
], ],
'dep_type': 'cipd', 'dep_type': 'cipd',
@ -1768,7 +1792,7 @@ deps = {
'packages': [ 'packages': [
{ {
'package': 'skia/tools/goldctl/windows-amd64', 'package': 'skia/tools/goldctl/windows-amd64',
'version': 'EbVQXa1u0hbZ8pxb0Il6Rbc1ErHpIN_-kMVOzBXMQyoC', 'version': 'Vg04A_bOadtB2ljbA9DGKe69_Uc6pmX5mk_ABoO2R3EC',
}, },
], ],
'dep_type': 'cipd', 'dep_type': 'cipd',
@ -1779,7 +1803,7 @@ deps = {
'packages': [ 'packages': [
{ {
'package': 'skia/tools/goldctl/mac-amd64', 'package': 'skia/tools/goldctl/mac-amd64',
'version': 'Y4l14LBqCsT9EhffPIOtso9VSpwqQE9WccjZdDBZmLoC', 'version': 'jw5QK1qcTGSBr-yjH0d-9F_MNeq6e5_5aWLq_oGWy0QC',
}, },
], ],
'dep_type': 'cipd', 'dep_type': 'cipd',
@ -1790,7 +1814,7 @@ deps = {
'packages': [ 'packages': [
{ {
'package': 'skia/tools/goldctl/mac-arm64', 'package': 'skia/tools/goldctl/mac-arm64',
'version': 'INEqc8JI_mtww_X0ShOlDkF3S8OG4tjF4Nkei0K7ci8C', 'version': 'o4BSMT1hKtY4T4VBfANeSm-NuhxoxPYUp3lF0EpoUvMC',
}, },
], ],
'dep_type': 'cipd', 'dep_type': 'cipd',
@ -1801,7 +1825,7 @@ deps = {
Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'),
'src-internal': { 'src-internal': {
'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@ae99ebde2a4de4d30a66c278c396dba703d2845f', 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@730d978fb36fbd1d7658f3b8c337a89bfe704cf9',
'condition': 'checkout_src_internal', 'condition': 'checkout_src_internal',
}, },
@ -1809,7 +1833,7 @@ deps = {
'packages': [ 'packages': [
{ {
'package': 'chromeos_internal/assistant/ambient', 'package': 'chromeos_internal/assistant/ambient',
'version': 'version:float_on_by_slower', 'version': 'version:float_on_by_initial_version',
}, },
], ],
'condition': 'checkout_chromeos and checkout_src_internal', 'condition': 'checkout_chromeos and checkout_src_internal',
@ -1820,7 +1844,7 @@ deps = {
'packages': [ 'packages': [
{ {
'package': 'chromeos_internal/apps/eche_app/app', 'package': 'chromeos_internal/apps/eche_app/app',
'version': 'mO7HIkligmD70YaR0NC-cEilQ0xhQYkaBq-8xFFsHAMC', 'version': 'ZpuWWOZwhn4j7SwQMvPc-NJOqV4p32nHSxVOFDH3a3MC',
}, },
], ],
'condition': 'checkout_chromeos and checkout_src_internal', 'condition': 'checkout_chromeos and checkout_src_internal',
@ -1831,7 +1855,7 @@ deps = {
'packages': [ 'packages': [
{ {
'package': 'chromeos_internal/apps/help_app/app', 'package': 'chromeos_internal/apps/help_app/app',
'version': 'XqfD0KEkd76pT0UI2DhgmgL-CfLXmHeGmHqZ8eSBu-gC', 'version': '_fsfATiokrgU562IXkEUlu49ttGo2GP6B_3KMV4YGj8C',
}, },
], ],
'condition': 'checkout_chromeos and checkout_src_internal', 'condition': 'checkout_chromeos and checkout_src_internal',
@ -1842,7 +1866,7 @@ deps = {
'packages': [ 'packages': [
{ {
'package': 'chromeos_internal/apps/media_app/app', 'package': 'chromeos_internal/apps/media_app/app',
'version': 'u3LIEepgYh4Lf4_iS5eKnL1K17o6cTHozTZQ6gkS3oUC', 'version': '74VBtd9mFKuJjJ4wsplDS7Av21ogn2oCHw3eTIqwGnwC',
}, },
], ],
'condition': 'checkout_chromeos and checkout_src_internal', 'condition': 'checkout_chromeos and checkout_src_internal',
@ -1853,7 +1877,7 @@ deps = {
'packages': [ 'packages': [
{ {
'package': 'chromeos_internal/apps/projector_app/app', 'package': 'chromeos_internal/apps/projector_app/app',
'version': 'zvssMRGkrSKVTUnN3dSa_d3_xPuVJ2aPSmegU-rHbMQC', 'version': 'cvaInkU-R_Gp-n2T4FBD02VwkF3VjZEuBh5sAFLoCf8C',
}, },
], ],
'condition': 'checkout_chromeos and checkout_src_internal', 'condition': 'checkout_chromeos and checkout_src_internal',
@ -3239,7 +3263,7 @@ deps = {
'packages': [ 'packages': [
{ {
'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib', 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib',
'version': 'version:2@1.6.20.cr1', 'version': 'version:2@1.6.10.cr1',
}, },
], ],
'condition': 'checkout_android', 'condition': 'checkout_android',
@ -3250,7 +3274,7 @@ deps = {
'packages': [ 'packages': [
{ {
'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_common', 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_common',
'version': 'version:2@1.6.20.cr1', 'version': 'version:2@1.6.10.cr1',
}, },
], ],
'condition': 'checkout_android', 'condition': 'checkout_android',
@ -3261,7 +3285,7 @@ deps = {
'packages': [ 'packages': [
{ {
'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_jdk7', 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_jdk7',
'version': 'version:2@1.6.20.cr1', 'version': 'version:2@1.5.0.cr1',
}, },
], ],
'condition': 'checkout_android', 'condition': 'checkout_android',
@ -3272,7 +3296,7 @@ deps = {
'packages': [ 'packages': [
{ {
'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_jdk8', 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_jdk8',
'version': 'version:2@1.6.20.cr1', 'version': 'version:2@1.5.0.cr1',
}, },
], ],
'condition': 'checkout_android', 'condition': 'checkout_android',
@ -3283,7 +3307,7 @@ deps = {
'packages': [ 'packages': [
{ {
'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_coroutines_android', 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_coroutines_android',
'version': 'version:2@1.6.1.cr1', 'version': 'version:2@1.5.0.cr1',
}, },
], ],
'condition': 'checkout_android', 'condition': 'checkout_android',
@ -3294,7 +3318,7 @@ deps = {
'packages': [ 'packages': [
{ {
'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_coroutines_core_jvm', 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_coroutines_core_jvm',
'version': 'version:2@1.6.1.cr1', 'version': 'version:2@1.5.0.cr1',
}, },
], ],
'condition': 'checkout_android', 'condition': 'checkout_android',
@ -3866,34 +3890,6 @@ hooks = [
'-s', 'src/third_party/skia', '-s', 'src/third_party/skia',
'--header', 'src/skia/ext/skia_commit_hash.h'], '--header', 'src/skia/ext/skia_commit_hash.h'],
}, },
# Pull dsymutil binaries using checked-in hashes.
{
'name': 'dsymutil_mac_arm64',
'pattern': '.',
'condition': 'host_os == "mac" and host_cpu == "arm64"',
'action': [ 'python3',
'src/third_party/depot_tools/download_from_google_storage.py',
'--no_resume',
'--no_auth',
'--bucket', 'chromium-browser-clang',
'-s', 'src/tools/clang/dsymutil/bin/dsymutil.arm64.sha1',
'-o', 'src/tools/clang/dsymutil/bin/dsymutil',
],
},
{
'name': 'dsymutil_mac_x64',
'pattern': '.',
'condition': 'host_os == "mac" and host_cpu == "x64"',
'action': [ 'python3',
'src/third_party/depot_tools/download_from_google_storage.py',
'--no_resume',
'--no_auth',
'--bucket', 'chromium-browser-clang',
'-s', 'src/tools/clang/dsymutil/bin/dsymutil.x64.sha1',
'-o', 'src/tools/clang/dsymutil/bin/dsymutil',
],
},
# Pull clang-format binaries using checked-in hashes. # Pull clang-format binaries using checked-in hashes.
{ {
'name': 'clang_format_win', 'name': 'clang_format_win',
@ -4071,14 +4067,10 @@ hooks = [
'-s', 'src/third_party/node/linux/node-linux-x64.tar.gz.sha1', '-s', 'src/third_party/node/linux/node-linux-x64.tar.gz.sha1',
], ],
}, },
# The Mac x64/arm64 binaries are downloaded regardless of host architecture
# since it's possible to cross-compile for the other architecture. This can
# cause problems for tests that use node if the test device architecture does
# not match the architecture of the compile machine.
{ {
'name': 'node_mac', 'name': 'node_mac',
'pattern': '.', 'pattern': '.',
'condition': 'host_os == "mac"', 'condition': 'host_os == "mac" and host_cpu == "x64"',
'action': [ 'python3', 'action': [ 'python3',
'src/third_party/depot_tools/download_from_google_storage.py', 'src/third_party/depot_tools/download_from_google_storage.py',
'--no_resume', '--no_resume',
@ -4091,7 +4083,7 @@ hooks = [
{ {
'name': 'node_mac_arm64', 'name': 'node_mac_arm64',
'pattern': '.', 'pattern': '.',
'condition': 'host_os == "mac"', 'condition': 'host_os == "mac" and host_cpu == "arm64"',
'action': [ 'python3', 'action': [ 'python3',
'src/third_party/depot_tools/download_from_google_storage.py', 'src/third_party/depot_tools/download_from_google_storage.py',
'--no_resume', '--no_resume',
@ -4626,13 +4618,13 @@ hooks = [
], ],
}, },
# Download Cast3p Binaries # Download Cast Web Runtime
{ {
'name': 'cast3p_binaries', 'name': 'cast_web_runtime',
'pattern': '.', 'pattern': '.',
'action': [ 'action': [
'python3', 'python3',
'src/tools/cast3p/update_binaries.py', 'src/tools/cast3p/update_runtime.py',
], ],
'condition': 'checkout_cast3p', 'condition': 'checkout_cast3p',
}, },
@ -4656,7 +4648,7 @@ hooks = [
recursedeps = [ recursedeps = [
# ANGLE manages DEPS that it also owns the build files for, such as dEQP. # ANGLE manages DEPS that it also owns the build files for, such as dEQP.
'src/third_party/angle', 'src/third_party/angle',
# Dawn needs CTS from its DEPS # Dawn and Tint's revision are linked
'src/third_party/dawn', 'src/third_party/dawn',
'src/third_party/openscreen/src', 'src/third_party/openscreen/src',
'src/third_party/vulkan-deps', 'src/third_party/vulkan-deps',

View File

@ -36,6 +36,7 @@ import("//build/config/ui.gni")
import("//build/rust/mixed_component.gni") import("//build/rust/mixed_component.gni")
import("//build/timestamp.gni") import("//build/timestamp.gni")
import("//build_overrides/build.gni") import("//build_overrides/build.gni")
import("//third_party/icu/config.gni")
if (is_mac) { if (is_mac) {
# Used to generate fuzzer corpus :base_mach_port_rendezvous_convert_corpus. # Used to generate fuzzer corpus :base_mach_port_rendezvous_convert_corpus.
@ -114,6 +115,22 @@ config("todo_buildflag_build_rust_json_parser") {
] ]
} }
config("memory_tagging") {
if (current_cpu == "arm64" && is_clang &&
(is_linux || is_chromeos || is_android || is_fuchsia)) {
# base/ has access to the MTE intrinsics because it needs to use them,
# but they're not backwards compatible. Use base::CPU::has_mte()
# beforehand to confirm or use indirect functions (ifuncs) to select
# an MTE-specific implementation at dynamic link-time.
cflags = [
"-Xclang",
"-target-feature",
"-Xclang",
"+mte",
]
}
}
config("base_implementation") { config("base_implementation") {
defines = [ "BASE_IMPLEMENTATION" ] defines = [ "BASE_IMPLEMENTATION" ]
configs = [ "//build/config/compiler:wexit_time_destructors" ] configs = [ "//build/config/compiler:wexit_time_destructors" ]
@ -317,6 +334,7 @@ mixed_component("base") {
"files/file_error_or.h", "files/file_error_or.h",
"files/file_path.cc", "files/file_path.cc",
"files/file_path.h", "files/file_path.h",
"files/file_path_constants.cc",
"files/file_path_watcher.cc", "files/file_path_watcher.cc",
"files/file_path_watcher.h", "files/file_path_watcher.h",
"files/file_proxy.cc", "files/file_proxy.cc",
@ -393,10 +411,6 @@ mixed_component("base") {
"memory/nonscannable_memory.cc", "memory/nonscannable_memory.cc",
"memory/nonscannable_memory.h", "memory/nonscannable_memory.h",
"memory/page_size.h", "memory/page_size.h",
"memory/platform_shared_memory_handle.cc",
"memory/platform_shared_memory_handle.h",
"memory/platform_shared_memory_mapper.cc",
"memory/platform_shared_memory_mapper.h",
"memory/platform_shared_memory_region.cc", "memory/platform_shared_memory_region.cc",
"memory/platform_shared_memory_region.h", "memory/platform_shared_memory_region.h",
"memory/ptr_util.h", "memory/ptr_util.h",
@ -479,8 +493,6 @@ mixed_component("base") {
"metrics/persistent_memory_allocator.h", "metrics/persistent_memory_allocator.h",
"metrics/persistent_sample_map.cc", "metrics/persistent_sample_map.cc",
"metrics/persistent_sample_map.h", "metrics/persistent_sample_map.h",
"metrics/ranges_manager.cc",
"metrics/ranges_manager.h",
"metrics/record_histogram_checker.h", "metrics/record_histogram_checker.h",
"metrics/sample_map.cc", "metrics/sample_map.cc",
"metrics/sample_map.h", "metrics/sample_map.h",
@ -1081,8 +1093,6 @@ mixed_component("base") {
"win/core_winrt_util.cc", "win/core_winrt_util.cc",
"win/core_winrt_util.h", "win/core_winrt_util.h",
"win/current_module.h", "win/current_module.h",
"win/default_apps_util.cc",
"win/default_apps_util.h",
"win/embedded_i18n/language_selector.cc", "win/embedded_i18n/language_selector.cc",
"win/embedded_i18n/language_selector.h", "win/embedded_i18n/language_selector.h",
"win/enum_variant.cc", "win/enum_variant.cc",
@ -1336,6 +1346,8 @@ mixed_component("base") {
"debug/proc_maps_linux.cc", "debug/proc_maps_linux.cc",
"debug/proc_maps_linux.h", "debug/proc_maps_linux.h",
"files/dir_reader_linux.h", "files/dir_reader_linux.h",
"files/file_path_watcher_linux.cc",
"files/file_path_watcher_linux.h",
"files/file_util_linux.cc", "files/file_util_linux.cc",
"files/scoped_file_linux.cc", "files/scoped_file_linux.cc",
"process/internal_linux.cc", "process/internal_linux.cc",
@ -1349,13 +1361,6 @@ mixed_component("base") {
] ]
} }
if (is_linux || is_chromeos || is_android || is_fuchsia) {
sources += [
"files/file_path_watcher_inotify.cc",
"files/file_path_watcher_inotify.h",
]
}
if (!is_nacl) { if (!is_nacl) {
sources += [ sources += [
"base_paths.cc", "base_paths.cc",
@ -1409,6 +1414,7 @@ mixed_component("base") {
configs += [ configs += [
":base_implementation", ":base_implementation",
":memory_tagging",
"//build/config:precompiled_headers", "//build/config:precompiled_headers",
"//build/config/compiler:wglobal_constructors", "//build/config/compiler:wglobal_constructors",
] ]
@ -1492,14 +1498,10 @@ mixed_component("base") {
sources += [ sources += [
"allocator/allocator_shim.cc", "allocator/allocator_shim.cc",
"allocator/allocator_shim.h", "allocator/allocator_shim.h",
"allocator/allocator_shim_default_dispatch_to_partition_alloc.cc",
"allocator/allocator_shim_default_dispatch_to_partition_alloc.h",
"allocator/allocator_shim_internals.h", "allocator/allocator_shim_internals.h",
] ]
if (use_partition_alloc) {
sources += [
"allocator/allocator_shim_default_dispatch_to_partition_alloc.cc",
"allocator/allocator_shim_default_dispatch_to_partition_alloc.h",
]
}
if (is_android) { if (is_android) {
sources += [ sources += [
"allocator/allocator_shim_override_cpp_symbols.h", "allocator/allocator_shim_override_cpp_symbols.h",
@ -1605,7 +1607,6 @@ mixed_component("base") {
"android/scoped_java_ref.cc", "android/scoped_java_ref.cc",
"android/scoped_java_ref.h", "android/scoped_java_ref.h",
"android/sys_utils.h", "android/sys_utils.h",
"memory/platform_shared_memory_mapper_android.cc",
"memory/platform_shared_memory_region_android.cc", "memory/platform_shared_memory_region_android.cc",
"system/sys_info_android.cc", "system/sys_info_android.cc",
@ -1614,6 +1615,8 @@ mixed_component("base") {
"debug/elf_reader.h", "debug/elf_reader.h",
"debug/proc_maps_linux.cc", "debug/proc_maps_linux.cc",
"debug/proc_maps_linux.h", "debug/proc_maps_linux.h",
"files/file_path_watcher_linux.cc",
"files/file_path_watcher_linux.h",
"process/internal_linux.cc", "process/internal_linux.cc",
"process/internal_linux.h", "process/internal_linux.h",
"process/memory_linux.cc", "process/memory_linux.cc",
@ -1685,6 +1688,7 @@ mixed_component("base") {
"files/file_descriptor_watcher_posix.cc", "files/file_descriptor_watcher_posix.cc",
"files/file_descriptor_watcher_posix.h", "files/file_descriptor_watcher_posix.h",
"files/file_enumerator_posix.cc", "files/file_enumerator_posix.cc",
"files/file_path_watcher_fuchsia.cc",
"files/file_posix.cc", "files/file_posix.cc",
"files/file_util_fuchsia.cc", "files/file_util_fuchsia.cc",
"files/file_util_posix.cc", "files/file_util_posix.cc",
@ -1719,7 +1723,6 @@ mixed_component("base") {
"fuchsia/startup_context.cc", "fuchsia/startup_context.cc",
"fuchsia/startup_context.h", "fuchsia/startup_context.h",
"memory/page_size_posix.cc", "memory/page_size_posix.cc",
"memory/platform_shared_memory_mapper_fuchsia.cc",
"memory/platform_shared_memory_region_fuchsia.cc", "memory/platform_shared_memory_region_fuchsia.cc",
"message_loop/message_pump_fuchsia.cc", "message_loop/message_pump_fuchsia.cc",
"message_loop/message_pump_fuchsia.h", "message_loop/message_pump_fuchsia.h",
@ -1836,7 +1839,6 @@ mixed_component("base") {
"files/file_path_watcher_stub.cc", "files/file_path_watcher_stub.cc",
"memory/page_size_nacl.cc", "memory/page_size_nacl.cc",
"process/process_stubs.cc", "process/process_stubs.cc",
"profiler/stack_sampler_posix.cc",
"sync_socket_nacl.cc", "sync_socket_nacl.cc",
"threading/platform_thread_linux.cc", "threading/platform_thread_linux.cc",
] ]
@ -1917,16 +1919,124 @@ mixed_component("base") {
"allocator/partition_alloc_features.h", "allocator/partition_alloc_features.h",
"allocator/partition_alloc_support.cc", "allocator/partition_alloc_support.cc",
"allocator/partition_alloc_support.h", "allocator/partition_alloc_support.h",
"allocator/partition_allocator/address_pool_manager.cc",
"allocator/partition_allocator/address_pool_manager.h",
"allocator/partition_allocator/address_pool_manager_bitmap.cc",
"allocator/partition_allocator/address_pool_manager_bitmap.h",
"allocator/partition_allocator/address_pool_manager_types.h",
"allocator/partition_allocator/address_space_randomization.cc",
"allocator/partition_allocator/address_space_randomization.h",
"allocator/partition_allocator/address_space_stats.h",
"allocator/partition_allocator/allocation_guard.cc",
"allocator/partition_allocator/allocation_guard.h",
"allocator/partition_allocator/dangling_raw_ptr_checks.cc",
"allocator/partition_allocator/dangling_raw_ptr_checks.h",
"allocator/partition_allocator/extended_api.cc",
"allocator/partition_allocator/extended_api.h",
"allocator/partition_allocator/memory_reclaimer.cc",
"allocator/partition_allocator/memory_reclaimer.h",
"allocator/partition_allocator/oom.cc",
"allocator/partition_allocator/oom.h",
"allocator/partition_allocator/oom_callback.cc",
"allocator/partition_allocator/oom_callback.h",
"allocator/partition_allocator/page_allocator.cc",
"allocator/partition_allocator/page_allocator.h",
"allocator/partition_allocator/page_allocator_constants.h",
"allocator/partition_allocator/page_allocator_internal.h",
"allocator/partition_allocator/partition_address_space.cc",
"allocator/partition_allocator/partition_address_space.h",
"allocator/partition_allocator/partition_alloc-inl.h",
"allocator/partition_allocator/partition_alloc.cc",
"allocator/partition_allocator/partition_alloc.h",
"allocator/partition_allocator/partition_alloc_check.h",
"allocator/partition_allocator/partition_alloc_config.h",
"allocator/partition_allocator/partition_alloc_constants.h",
"allocator/partition_allocator/partition_alloc_forward.h",
"allocator/partition_allocator/partition_alloc_hooks.cc",
"allocator/partition_allocator/partition_alloc_hooks.h",
"allocator/partition_allocator/partition_alloc_notreached.h",
"allocator/partition_allocator/partition_bucket.cc",
"allocator/partition_allocator/partition_bucket.h",
"allocator/partition_allocator/partition_bucket_lookup.h",
"allocator/partition_allocator/partition_cookie.h",
"allocator/partition_allocator/partition_direct_map_extent.h",
"allocator/partition_allocator/partition_freelist_entry.h",
"allocator/partition_allocator/partition_lock.h",
"allocator/partition_allocator/partition_oom.cc",
"allocator/partition_allocator/partition_oom.h",
"allocator/partition_allocator/partition_page.cc",
"allocator/partition_allocator/partition_page.h",
"allocator/partition_allocator/partition_ref_count.h",
"allocator/partition_allocator/partition_root.cc",
"allocator/partition_allocator/partition_root.h",
"allocator/partition_allocator/partition_stats.cc",
"allocator/partition_allocator/partition_stats.h",
"allocator/partition_allocator/partition_tls.h",
"allocator/partition_allocator/random.cc",
"allocator/partition_allocator/random.h",
"allocator/partition_allocator/reservation_offset_table.cc",
"allocator/partition_allocator/reservation_offset_table.h",
"allocator/partition_allocator/spinning_mutex.cc",
"allocator/partition_allocator/spinning_mutex.h",
"allocator/partition_allocator/starscan/logging.h",
"allocator/partition_allocator/starscan/metadata_allocator.cc",
"allocator/partition_allocator/starscan/metadata_allocator.h",
"allocator/partition_allocator/starscan/pcscan.cc",
"allocator/partition_allocator/starscan/pcscan.h",
"allocator/partition_allocator/starscan/pcscan_internal.cc",
"allocator/partition_allocator/starscan/pcscan_internal.h",
"allocator/partition_allocator/starscan/pcscan_scheduling.cc",
"allocator/partition_allocator/starscan/pcscan_scheduling.h",
"allocator/partition_allocator/starscan/raceful_worklist.h",
"allocator/partition_allocator/starscan/scan_loop.h",
"allocator/partition_allocator/starscan/snapshot.cc",
"allocator/partition_allocator/starscan/snapshot.h",
"allocator/partition_allocator/starscan/stack/stack.cc",
"allocator/partition_allocator/starscan/stack/stack.h",
"allocator/partition_allocator/starscan/starscan_fwd.h",
"allocator/partition_allocator/starscan/state_bitmap.h",
"allocator/partition_allocator/starscan/stats_collector.cc",
"allocator/partition_allocator/starscan/stats_collector.h",
"allocator/partition_allocator/starscan/stats_reporter.h",
"allocator/partition_allocator/starscan/write_protector.cc",
"allocator/partition_allocator/starscan/write_protector.h",
"allocator/partition_allocator/tagging.cc",
"allocator/partition_allocator/tagging.h",
"allocator/partition_allocator/thread_cache.cc",
"allocator/partition_allocator/thread_cache.h",
"allocator/partition_allocator/yield_processor.h",
] ]
} if (is_win) {
sources += [
"allocator/partition_allocator/page_allocator_internals_win.h",
"allocator/partition_allocator/partition_tls_win.cc",
]
} else if (is_posix) {
sources += [
"allocator/partition_allocator/page_allocator_internals_posix.cc",
"allocator/partition_allocator/page_allocator_internals_posix.h",
]
} else if (is_fuchsia) {
sources += [
"allocator/partition_allocator/page_allocator_internals_fuchsia.h",
]
}
# Need this to pass gn check, because gn check doesn't see if (current_cpu == "x64") {
# BUILDFLAG(USE_PARTITION_ALLOC). A linker will remove all defines += [ "PA_PCSCAN_STACK_SUPPORTED" ]
# partition_alloc code if use_partition_alloc = false because no code uses sources += [ "allocator/partition_allocator/starscan/stack/asm/x64/push_registers_asm.cc" ]
# partition_alloc. } else if (current_cpu == "x86") {
public_deps += [ "allocator/partition_allocator:partition_alloc" ] defines += [ "PA_PCSCAN_STACK_SUPPORTED" ]
if (current_os == "openwrt") { sources += [ "allocator/partition_allocator/starscan/stack/asm/x86/push_registers_asm.cc" ]
public_deps -= [ "allocator/partition_allocator:partition_alloc" ] } else if (current_cpu == "arm") {
defines += [ "PA_PCSCAN_STACK_SUPPORTED" ]
sources += [ "allocator/partition_allocator/starscan/stack/asm/arm/push_registers_asm.cc" ]
} else if (current_cpu == "arm64") {
defines += [ "PA_PCSCAN_STACK_SUPPORTED" ]
sources += [ "allocator/partition_allocator/starscan/stack/asm/arm64/push_registers_asm.cc" ]
} else {
# To support a trampoline for another arch, please refer to v8/src/heap/base.
}
} }
} }
@ -1934,7 +2044,6 @@ mixed_component("base") {
if (is_win) { if (is_win) {
sources += [ sources += [
"files/file_enumerator_win.cc", "files/file_enumerator_win.cc",
"memory/platform_shared_memory_mapper_win.cc",
"memory/platform_shared_memory_region_win.cc", "memory/platform_shared_memory_region_win.cc",
"power_monitor/power_monitor_device_source_win.cc", "power_monitor/power_monitor_device_source_win.cc",
"power_monitor/speed_limit_observer_win.cc", "power_monitor/speed_limit_observer_win.cc",
@ -1989,7 +2098,6 @@ mixed_component("base") {
"files/file_path_watcher_kqueue.cc", "files/file_path_watcher_kqueue.cc",
"files/file_path_watcher_kqueue.h", "files/file_path_watcher_kqueue.h",
"mac/scoped_typeref.h", "mac/scoped_typeref.h",
"memory/platform_shared_memory_mapper_mac.cc",
"memory/platform_shared_memory_region_mac.cc", "memory/platform_shared_memory_region_mac.cc",
"message_loop/message_pump_kqueue.cc", "message_loop/message_pump_kqueue.cc",
"message_loop/message_pump_kqueue.h", "message_loop/message_pump_kqueue.h",
@ -2176,10 +2284,7 @@ mixed_component("base") {
# Android and MacOS have their own custom shared memory handle # Android and MacOS have their own custom shared memory handle
# implementations. e.g. due to supporting both POSIX and native handles. # implementations. e.g. due to supporting both POSIX and native handles.
if (is_posix && !is_android && !is_mac) { if (is_posix && !is_android && !is_mac) {
sources += [ sources += [ "memory/platform_shared_memory_region_posix.cc" ]
"memory/platform_shared_memory_mapper_posix.cc",
"memory/platform_shared_memory_region_posix.cc",
]
} }
if (is_posix && !is_apple) { if (is_posix && !is_apple) {
@ -2497,11 +2602,7 @@ buildflag_header("profiler_buildflags") {
header = "profiler_buildflags.h" header = "profiler_buildflags.h"
header_dir = "base/profiler" header_dir = "base/profiler"
flags = [ flags = [ "ENABLE_ARM_CFI_TABLE=$enable_arm_cfi_table" ]
"ENABLE_ARM_CFI_TABLE=$enable_arm_cfi_table",
"IOS_STACK_PROFILER_ENABLED=$ios_stack_profiler_enabled",
"USE_ANDROID_UNWINDER_V2=$use_android_unwinder_v2",
]
} }
# This is the subset of files from base that should not be used with a dynamic # This is the subset of files from base that should not be used with a dynamic

View File

@ -7,6 +7,7 @@ danakj@chromium.org
dcheng@chromium.org dcheng@chromium.org
fdoray@chromium.org fdoray@chromium.org
gab@chromium.org gab@chromium.org
jdoerrie@chromium.org
kylechar@chromium.org kylechar@chromium.org
mark@chromium.org mark@chromium.org
thakis@chromium.org thakis@chromium.org

View File

@ -22,10 +22,6 @@ buildflag_header("buildflags") {
_enable_dangling_raw_ptr_checks = _enable_dangling_raw_ptr_checks =
enable_dangling_raw_ptr_checks && _use_backup_ref_ptr enable_dangling_raw_ptr_checks && _use_backup_ref_ptr
# MTECheckedPtr is exclusive against BRP (asserted at declaration).
# MTECheckedPtr requires 64-bit pointers (not available in NaCl).
_use_mte_checked_ptr = use_mte_checked_ptr && !is_nacl
_record_alloc_info = false _record_alloc_info = false
flags = [ flags = [
@ -39,9 +35,6 @@ buildflag_header("buildflags") {
"ENABLE_DANGLING_RAW_PTR_CHECKS=$_enable_dangling_raw_ptr_checks", "ENABLE_DANGLING_RAW_PTR_CHECKS=$_enable_dangling_raw_ptr_checks",
"PUT_REF_COUNT_IN_PREVIOUS_SLOT=$_put_ref_count_in_previous_slot", "PUT_REF_COUNT_IN_PREVIOUS_SLOT=$_put_ref_count_in_previous_slot",
# Not to be used directly - see `partition_alloc_config.h`.
"USE_MTE_CHECKED_PTR=$_use_mte_checked_ptr",
"USE_FAKE_BINARY_EXPERIMENT=$use_fake_binary_experiment", "USE_FAKE_BINARY_EXPERIMENT=$use_fake_binary_experiment",
"RECORD_ALLOC_INFO=$_record_alloc_info", "RECORD_ALLOC_INFO=$_record_alloc_info",

View File

@ -87,13 +87,8 @@ declare_args() {
# Set use_backup_ref_ptr true to use BackupRefPtr (BRP) as the implementation # Set use_backup_ref_ptr true to use BackupRefPtr (BRP) as the implementation
# of raw_ptr<T>, and enable PartitionAlloc support for it. # of raw_ptr<T>, and enable PartitionAlloc support for it.
use_backup_ref_ptr = _is_brp_supported use_backup_ref_ptr = _is_brp_supported
use_mte_checked_ptr = false
} }
assert(!(use_backup_ref_ptr && use_mte_checked_ptr),
"MTECheckedPtr conflicts with BRP.")
declare_args() { declare_args() {
# If BRP is enabled, additional options are available: # If BRP is enabled, additional options are available:
# - put_ref_count_in_previous_slot: place the ref-count at the end of the # - put_ref_count_in_previous_slot: place the ref-count at the end of the
@ -103,7 +98,7 @@ declare_args() {
# are too expensive to have on by default. # are too expensive to have on by default.
# - enable_dangling_raw_ptr_checks: enable checking raw_ptr do not become # - enable_dangling_raw_ptr_checks: enable checking raw_ptr do not become
# dangling during their lifetime. # dangling during their lifetime.
put_ref_count_in_previous_slot = use_backup_ref_ptr put_ref_count_in_previous_slot = false
enable_backup_ref_ptr_slow_checks = false enable_backup_ref_ptr_slow_checks = false
enable_dangling_raw_ptr_checks = false enable_dangling_raw_ptr_checks = false

View File

@ -20,16 +20,14 @@
#include "base/bits.h" #include "base/bits.h"
#include "base/logging.h" #include "base/logging.h"
namespace partition_alloc { namespace base {
// Defined in base/allocator/partition_allocator/partition_root.cc // Defined in base/allocator/partition_allocator/partition_root.cc
void PartitionAllocMallocHookOnBeforeForkInParent(); void PartitionAllocMallocHookOnBeforeForkInParent();
void PartitionAllocMallocHookOnAfterForkInParent(); void PartitionAllocMallocHookOnAfterForkInParent();
void PartitionAllocMallocHookOnAfterForkInChild(); void PartitionAllocMallocHookOnAfterForkInChild();
} // namespace partition_alloc namespace allocator {
namespace base::allocator {
namespace { namespace {
@ -68,12 +66,12 @@ void MallocIntrospectionLog(malloc_zone_t* zone, void* address) {
void MallocIntrospectionForceLock(malloc_zone_t* zone) { void MallocIntrospectionForceLock(malloc_zone_t* zone) {
// Called before fork(2) to acquire the lock. // Called before fork(2) to acquire the lock.
partition_alloc::PartitionAllocMallocHookOnBeforeForkInParent(); PartitionAllocMallocHookOnBeforeForkInParent();
} }
void MallocIntrospectionForceUnlock(malloc_zone_t* zone) { void MallocIntrospectionForceUnlock(malloc_zone_t* zone) {
// Called in the parent process after fork(2) to release the lock. // Called in the parent process after fork(2) to release the lock.
partition_alloc::PartitionAllocMallocHookOnAfterForkInParent(); PartitionAllocMallocHookOnAfterForkInParent();
} }
void MallocIntrospectionStatistics(malloc_zone_t* zone, void MallocIntrospectionStatistics(malloc_zone_t* zone,
@ -113,7 +111,7 @@ void MallocIntrospectionEnumerateDischargedPointers(
void MallocIntrospectionReinitLock(malloc_zone_t* zone) { void MallocIntrospectionReinitLock(malloc_zone_t* zone) {
// Called in a child process after fork(2) to re-initialize the lock. // Called in a child process after fork(2) to re-initialize the lock.
partition_alloc::PartitionAllocMallocHookOnAfterForkInChild(); PartitionAllocMallocHookOnAfterForkInChild();
} }
void MallocIntrospectionPrintTask(task_t task, void MallocIntrospectionPrintTask(task_t task,
@ -374,4 +372,5 @@ InitializeDefaultMallocZoneWithPartitionAlloc() {
} // namespace } // namespace
} // namespace base::allocator } // namespace allocator
} // namespace base

View File

@ -4,7 +4,6 @@
#include "base/allocator/partition_alloc_features.h" #include "base/allocator/partition_alloc_features.h"
#include "base/base_export.h"
#include "base/feature_list.h" #include "base/feature_list.h"
#include "build/build_config.h" #include "build/build_config.h"

View File

@ -79,7 +79,7 @@ constexpr const char* MutatorIdToTracingString(
} }
// Inject TRACE_EVENT_BEGIN/END, TRACE_COUNTER1, and UmaHistogramTimes. // Inject TRACE_EVENT_BEGIN/END, TRACE_COUNTER1, and UmaHistogramTimes.
class StatsReporterImpl final : public partition_alloc::StatsReporter { class StatsReporterImpl final : public StatsReporter {
public: public:
void ReportTraceEvent(internal::StatsCollector::ScannerId id, void ReportTraceEvent(internal::StatsCollector::ScannerId id,
[[maybe_unused]] const PlatformThreadId tid, [[maybe_unused]] const PlatformThreadId tid,
@ -147,10 +147,8 @@ void RegisterPCScanStatsReporter() {
namespace { namespace {
void RunThreadCachePeriodicPurge() { void RunThreadCachePeriodicPurge() {
// Micros, since periodic purge should typically take at most a few ms.
SCOPED_UMA_HISTOGRAM_TIMER_MICROS("Memory.PartitionAlloc.PeriodicPurge");
TRACE_EVENT0("memory", "PeriodicPurge"); TRACE_EVENT0("memory", "PeriodicPurge");
auto& instance = ::partition_alloc::ThreadCacheRegistry::Instance(); auto& instance = internal::ThreadCacheRegistry::Instance();
instance.RunPeriodicPurge(); instance.RunPeriodicPurge();
TimeDelta delay = TimeDelta delay =
Microseconds(instance.GetPeriodicPurgeNextIntervalInMicroseconds()); Microseconds(instance.GetPeriodicPurgeNextIntervalInMicroseconds());
@ -177,7 +175,7 @@ void RunMemoryReclaimer(scoped_refptr<SequencedTaskRunner> task_runner) {
} // namespace } // namespace
void StartThreadCachePeriodicPurge() { void StartThreadCachePeriodicPurge() {
auto& instance = ::partition_alloc::ThreadCacheRegistry::Instance(); auto& instance = internal::ThreadCacheRegistry::Instance();
TimeDelta delay = TimeDelta delay =
Microseconds(instance.GetPeriodicPurgeNextIntervalInMicroseconds()); Microseconds(instance.GetPeriodicPurgeNextIntervalInMicroseconds());
ThreadTaskRunnerHandle::Get()->PostDelayedTask( ThreadTaskRunnerHandle::Get()->PostDelayedTask(

View File

@ -1,222 +0,0 @@
# Copyright (c) 2022 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//base/allocator/allocator.gni")
import("//base/allocator/partition_allocator/partition_alloc.gni")
# Add partition_alloc.gni and import it for partition_alloc configs.
config("partition_alloc_implementation") {
# After introducing partition_alloc_export, replace BASE_IMPLEMENTATION with
# PARTITION_ALLOC_IMPLEMENTATION.
defines = [ "BASE_IMPLEMENTATION" ]
}
config("memory_tagging") {
if (current_cpu == "arm64" && is_clang &&
(is_linux || is_chromeos || is_android || is_fuchsia)) {
# base/ has access to the MTE intrinsics because it needs to use them,
# but they're not backwards compatible. Use base::CPU::has_mte()
# beforehand to confirm or use indirect functions (ifuncs) to select
# an MTE-specific implementation at dynamic link-time.
cflags = [
"-Xclang",
"-target-feature",
"-Xclang",
"+mte",
]
}
}
if (is_fuchsia) {
config("fuchsia_sync_lib") {
libs = [
"sync", # Used by spinning_mutex.h.
]
}
}
if (make_partition_alloc_standalone) {
partition_alloc_target_type = "component"
} else {
partition_alloc_target_type = "source_set"
}
target(partition_alloc_target_type, "partition_alloc") {
sources = [
"address_pool_manager.cc",
"address_pool_manager.h",
"address_pool_manager_bitmap.cc",
"address_pool_manager_bitmap.h",
"address_pool_manager_types.h",
"address_space_randomization.cc",
"address_space_randomization.h",
"address_space_stats.h",
"allocation_guard.cc",
"allocation_guard.h",
"base/bits.h",
"base/migration_adapter.h",
"base/sys_byteorder.h",
"dangling_raw_ptr_checks.cc",
"dangling_raw_ptr_checks.h",
"extended_api.cc",
"extended_api.h",
"memory_reclaimer.cc",
"memory_reclaimer.h",
"oom.cc",
"oom.h",
"oom_callback.cc",
"oom_callback.h",
"page_allocator.cc",
"page_allocator.h",
"page_allocator_constants.h",
"page_allocator_internal.h",
"partition_address_space.cc",
"partition_address_space.h",
"partition_alloc-inl.h",
"partition_alloc.cc",
"partition_alloc.h",
"partition_alloc_check.h",
"partition_alloc_config.h",
"partition_alloc_constants.h",
"partition_alloc_forward.h",
"partition_alloc_hooks.cc",
"partition_alloc_hooks.h",
"partition_alloc_notreached.h",
"partition_bucket.cc",
"partition_bucket.h",
"partition_bucket_lookup.h",
"partition_cookie.h",
"partition_direct_map_extent.h",
"partition_freelist_entry.h",
"partition_lock.h",
"partition_oom.cc",
"partition_oom.h",
"partition_page.cc",
"partition_page.h",
"partition_ref_count.h",
"partition_root.cc",
"partition_root.h",
"partition_stats.cc",
"partition_stats.h",
"partition_tag.h",
"partition_tag_bitmap.h",
"partition_tls.h",
"random.cc",
"random.h",
"reservation_offset_table.cc",
"reservation_offset_table.h",
"spinning_mutex.cc",
"spinning_mutex.h",
"starscan/logging.h",
"starscan/metadata_allocator.cc",
"starscan/metadata_allocator.h",
"starscan/pcscan.cc",
"starscan/pcscan.h",
"starscan/pcscan_internal.cc",
"starscan/pcscan_internal.h",
"starscan/pcscan_scheduling.cc",
"starscan/pcscan_scheduling.h",
"starscan/raceful_worklist.h",
"starscan/scan_loop.h",
"starscan/snapshot.cc",
"starscan/snapshot.h",
"starscan/stack/stack.cc",
"starscan/stack/stack.h",
"starscan/starscan_fwd.h",
"starscan/state_bitmap.h",
"starscan/stats_collector.cc",
"starscan/stats_collector.h",
"starscan/stats_reporter.h",
"starscan/write_protector.cc",
"starscan/write_protector.h",
"tagging.cc",
"tagging.h",
"thread_cache.cc",
"thread_cache.h",
"yield_processor.h",
]
defines = []
if (is_win) {
sources += [
"page_allocator_internals_win.h",
"partition_tls_win.cc",
]
} else if (is_posix) {
sources += [
"page_allocator_internals_posix.cc",
"page_allocator_internals_posix.h",
]
} else if (is_fuchsia) {
sources += [ "page_allocator_internals_fuchsia.h" ]
}
if (current_cpu == "x64") {
defines += [ "PA_PCSCAN_STACK_SUPPORTED" ]
sources += [ "starscan/stack/asm/x64/push_registers_asm.cc" ]
} else if (current_cpu == "x86") {
defines += [ "PA_PCSCAN_STACK_SUPPORTED" ]
sources += [ "starscan/stack/asm/x86/push_registers_asm.cc" ]
} else if (current_cpu == "arm") {
defines += [ "PA_PCSCAN_STACK_SUPPORTED" ]
sources += [ "starscan/stack/asm/arm/push_registers_asm.cc" ]
} else if (current_cpu == "arm64") {
defines += [ "PA_PCSCAN_STACK_SUPPORTED" ]
sources += [ "starscan/stack/asm/arm64/push_registers_asm.cc" ]
} else {
# To support a trampoline for another arch, please refer to v8/src/heap/base.
}
public_deps = [
"//base:debugging_buildflags",
"//base:logging_buildflags",
"//base:synchronization_buildflags",
"//base:tracing_buildflags",
"//base/allocator:buildflags",
"//build:branding_buildflags",
"//build:chromecast_buildflags",
"//build:chromeos_buildflags",
"//build/config/compiler:compiler_buildflags",
]
deps = []
configs += [
":partition_alloc_implementation",
":memory_tagging",
]
public_configs = []
if (is_android) {
# tagging.cc requires __arm_mte_set_* functions.
deps += [ "//third_party/android_ndk:cpu_features" ]
}
if (is_fuchsia) {
public_deps += [
"//third_party/fuchsia-sdk/sdk/pkg/fit",
"//third_party/fuchsia-sdk/sdk/pkg/sync",
"//third_party/fuchsia-sdk/sdk/pkg/zx",
]
# Needed for users of spinning_mutex.h, which for performance reasons,
# contains inlined calls to `libsync` inside the header file.
# It appends an entry to the "libs" section of the dependent target.
public_configs += [ ":fuchsia_sync_lib" ]
}
frameworks = []
if (is_mac) {
# SecTaskGetCodeSignStatus needs:
frameworks += [ "Security.framework" ]
}
}
# TODO(crbug.com/1151236): After making partition_alloc a standalone library,
# move test code here. i.e. test("partition_alloc_tests") { ... } and
# test("partition_alloc_perftests").
# TODO(crbug.com/1151236): Generate partition_alloc_buildflags. The following
# flags will be defined by the buildflags:
# "USE_BACKUP_REF_PTR=$_use_backup_ref_ptr",
# "ENABLE_BACKUP_REF_PTR_SLOW_CHECKS=$_enable_backup_ref_ptr_slow_checks",
# "ENABLE_DANGLING_RAW_PTR_CHECKS=$_enable_dangling_raw_ptr_checks",
# "PUT_REF_COUNT_IN_PREVIOUS_SLOT=$_put_ref_count_in_previous_slot",
# "USE_MTE_CHECKED_PTR=$_use_mte_checked_ptr",
# "RECORD_ALLOC_INFO=$_record_alloc_info",

View File

@ -8,6 +8,7 @@ include_rules = [
"+base/allocator/buildflags.h", "+base/allocator/buildflags.h",
"+base/base_export.h", "+base/base_export.h",
"+base/bind.h", "+base/bind.h",
"+base/bits.h",
"+base/callback.h", "+base/callback.h",
"+base/check.h", "+base/check.h",
"+base/check_op.h", "+base/check_op.h",
@ -36,6 +37,7 @@ include_rules = [
"+base/process/memory.h", "+base/process/memory.h",
"+base/rand_util.h", "+base/rand_util.h",
"+base/strings/stringprintf.h", "+base/strings/stringprintf.h",
"+base/sys_byteorder.h",
"+base/system/sys_info.h", "+base/system/sys_info.h",
"+base/test/bind.h", "+base/test/bind.h",
"+base/test/gtest_util.h", "+base/test/gtest_util.h",

View File

@ -15,7 +15,6 @@
#include "base/allocator/partition_allocator/partition_alloc_config.h" #include "base/allocator/partition_allocator/partition_alloc_config.h"
#include "base/allocator/partition_allocator/partition_alloc_constants.h" #include "base/allocator/partition_allocator/partition_alloc_constants.h"
#include "base/allocator/partition_allocator/partition_lock.h" #include "base/allocator/partition_allocator/partition_lock.h"
#include "base/base_export.h"
#include "base/thread_annotations.h" #include "base/thread_annotations.h"
#include "build/build_config.h" #include "build/build_config.h"

View File

@ -15,7 +15,6 @@
#include "base/allocator/partition_allocator/partition_alloc_config.h" #include "base/allocator/partition_allocator/partition_alloc_config.h"
#include "base/allocator/partition_allocator/partition_alloc_constants.h" #include "base/allocator/partition_allocator/partition_alloc_constants.h"
#include "base/allocator/partition_allocator/partition_lock.h" #include "base/allocator/partition_allocator/partition_lock.h"
#include "base/base_export.h"
#include "build/build_config.h" #include "build/build_config.h"
#if !defined(PA_HAS_64_BITS_POINTERS) #if !defined(PA_HAS_64_BITS_POINTERS)

View File

@ -121,21 +121,6 @@ AslrMask(uintptr_t bits) {
return AslrAddress(0x20000000ULL); return AslrAddress(0x20000000ULL);
} }
#elif BUILDFLAG(IS_LINUX)
// Linux on arm64 can use 39, 42, 48, or 52-bit user space, depending on
// page size and number of levels of translation pages used. We use
// 39-bit as base as all setups should support this, lowered to 38-bit
// as ASLROffset() could cause a carry.
PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE uintptr_t
ASLRMask() {
return AslrMask(38);
}
PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE uintptr_t
ASLROffset() {
return AslrAddress(0x1000000000ULL);
}
#else #else
// ARM64 on Linux has 39-bit user space. Use 38 bits since ASLROffset() // ARM64 on Linux has 39-bit user space. Use 38 bits since ASLROffset()

View File

@ -6,7 +6,6 @@
#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_ALLOCATION_GUARD_H_ #define BASE_ALLOCATOR_PARTITION_ALLOCATOR_ALLOCATION_GUARD_H_
#include "base/allocator/partition_allocator/partition_alloc_config.h" #include "base/allocator/partition_allocator/partition_alloc_config.h"
#include "base/base_export.h"
#include "build/build_config.h" #include "build/build_config.h"
namespace partition_alloc { namespace partition_alloc {
@ -14,14 +13,14 @@ namespace partition_alloc {
#if defined(PA_HAS_ALLOCATION_GUARD) #if defined(PA_HAS_ALLOCATION_GUARD)
// Disallow allocations in the scope. Does not nest. // Disallow allocations in the scope. Does not nest.
class BASE_EXPORT ScopedDisallowAllocations { class ScopedDisallowAllocations {
public: public:
ScopedDisallowAllocations(); ScopedDisallowAllocations();
~ScopedDisallowAllocations(); ~ScopedDisallowAllocations();
}; };
// Disallow allocations in the scope. Does not nest. // Disallow allocations in the scope. Does not nest.
class BASE_EXPORT ScopedAllowAllocations { class ScopedAllowAllocations {
public: public:
ScopedAllowAllocations(); ScopedAllowAllocations();
~ScopedAllowAllocations(); ~ScopedAllowAllocations();

View File

@ -1,240 +0,0 @@
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file defines some bit utilities.
#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_BASE_BITS_H_
#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_BASE_BITS_H_
#include <climits>
#include <cstddef>
#include <cstdint>
#include <type_traits>
#include "base/allocator/partition_allocator/base/migration_adapter.h"
#include "base/allocator/partition_allocator/partition_alloc_check.h"
#include "base/compiler_specific.h"
#include "build/build_config.h"
#if defined(COMPILER_MSVC)
#include <intrin.h>
#endif
namespace partition_alloc::internal::base::bits {
// Returns true iff |value| is a power of 2.
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
constexpr bool IsPowerOfTwo(T value) {
// From "Hacker's Delight": Section 2.1 Manipulating Rightmost Bits.
//
// Only positive integers with a single bit set are powers of two. If only one
// bit is set in x (e.g. 0b00000100000000) then |x-1| will have that bit set
// to zero and all bits to its right set to 1 (e.g. 0b00000011111111). Hence
// |x & (x-1)| is 0 iff x is a power of two.
return value > 0 && (value & (value - 1)) == 0;
}
// Round down |size| to a multiple of alignment, which must be a power of two.
inline constexpr size_t AlignDown(size_t size, size_t alignment) {
PA_DCHECK(IsPowerOfTwo(alignment));
return size & ~(alignment - 1);
}
// Move |ptr| back to the previous multiple of alignment, which must be a power
// of two. Defined for types where sizeof(T) is one byte.
template <typename T, typename = typename std::enable_if<sizeof(T) == 1>::type>
inline T* AlignDown(T* ptr, size_t alignment) {
return reinterpret_cast<T*>(
AlignDown(reinterpret_cast<size_t>(ptr), alignment));
}
// Round up |size| to a multiple of alignment, which must be a power of two.
inline constexpr size_t AlignUp(size_t size, size_t alignment) {
PA_DCHECK(IsPowerOfTwo(alignment));
return (size + alignment - 1) & ~(alignment - 1);
}
// Advance |ptr| to the next multiple of alignment, which must be a power of
// two. Defined for types where sizeof(T) is one byte.
template <typename T, typename = typename std::enable_if<sizeof(T) == 1>::type>
inline T* AlignUp(T* ptr, size_t alignment) {
return reinterpret_cast<T*>(
AlignUp(reinterpret_cast<size_t>(ptr), alignment));
}
// CountLeadingZeroBits(value) returns the number of zero bits following the
// most significant 1 bit in |value| if |value| is non-zero, otherwise it
// returns {sizeof(T) * 8}.
// Example: 00100010 -> 2
//
// CountTrailingZeroBits(value) returns the number of zero bits preceding the
// least significant 1 bit in |value| if |value| is non-zero, otherwise it
// returns {sizeof(T) * 8}.
// Example: 00100010 -> 1
//
// C does not have an operator to do this, but fortunately the various
// compilers have built-ins that map to fast underlying processor instructions.
//
// Prefer the clang path on Windows, as _BitScanReverse() and friends are not
// constexpr.
#if defined(COMPILER_MSVC) && !defined(__clang__)
template <typename T, unsigned bits = sizeof(T) * 8>
ALWAYS_INLINE
typename std::enable_if<std::is_unsigned<T>::value && sizeof(T) <= 4,
unsigned>::type
CountLeadingZeroBits(T x) {
static_assert(bits > 0, "invalid instantiation");
unsigned long index;
return LIKELY(_BitScanReverse(&index, static_cast<uint32_t>(x)))
? (31 - index - (32 - bits))
: bits;
}
template <typename T, unsigned bits = sizeof(T) * 8>
ALWAYS_INLINE
typename std::enable_if<std::is_unsigned<T>::value && sizeof(T) == 8,
unsigned>::type
CountLeadingZeroBits(T x) {
static_assert(bits > 0, "invalid instantiation");
unsigned long index;
// MSVC only supplies _BitScanReverse64 when building for a 64-bit target.
#if defined(ARCH_CPU_64_BITS)
return LIKELY(_BitScanReverse64(&index, static_cast<uint64_t>(x)))
? (63 - index)
: 64;
#else
uint32_t left = static_cast<uint32_t>(x >> 32);
if (LIKELY(_BitScanReverse(&index, left)))
return 31 - index;
uint32_t right = static_cast<uint32_t>(x);
if (LIKELY(_BitScanReverse(&index, right)))
return 63 - index;
return 64;
#endif
}
template <typename T, unsigned bits = sizeof(T) * 8>
ALWAYS_INLINE
typename std::enable_if<std::is_unsigned<T>::value && sizeof(T) <= 4,
unsigned>::type
CountTrailingZeroBits(T x) {
static_assert(bits > 0, "invalid instantiation");
unsigned long index;
return LIKELY(_BitScanForward(&index, static_cast<uint32_t>(x))) ? index
: bits;
}
template <typename T, unsigned bits = sizeof(T) * 8>
ALWAYS_INLINE
typename std::enable_if<std::is_unsigned<T>::value && sizeof(T) == 8,
unsigned>::type
CountTrailingZeroBits(T x) {
static_assert(bits > 0, "invalid instantiation");
unsigned long index;
// MSVC only supplies _BitScanForward64 when building for a 64-bit target.
#if defined(ARCH_CPU_64_BITS)
return LIKELY(_BitScanForward64(&index, static_cast<uint64_t>(x))) ? index
: 64;
#else
uint32_t right = static_cast<uint32_t>(x);
if (LIKELY(_BitScanForward(&index, right)))
return index;
uint32_t left = static_cast<uint32_t>(x >> 32);
if (LIKELY(_BitScanForward(&index, left)))
return 32 + index;
return 64;
#endif
}
ALWAYS_INLINE uint32_t CountLeadingZeroBits32(uint32_t x) {
return CountLeadingZeroBits(x);
}
ALWAYS_INLINE uint64_t CountLeadingZeroBits64(uint64_t x) {
return CountLeadingZeroBits(x);
}
#elif defined(COMPILER_GCC) || defined(__clang__)
// __builtin_clz has undefined behaviour for an input of 0, even though there's
// clearly a return value that makes sense, and even though some processor clz
// instructions have defined behaviour for 0. We could drop to raw __asm__ to
// do better, but we'll avoid doing that unless we see proof that we need to.
template <typename T, unsigned bits = sizeof(T) * 8>
ALWAYS_INLINE constexpr
typename std::enable_if<std::is_unsigned<T>::value && sizeof(T) <= 8,
unsigned>::type
CountLeadingZeroBits(T value) {
static_assert(bits > 0, "invalid instantiation");
return LIKELY(value)
? bits == 64
? __builtin_clzll(static_cast<uint64_t>(value))
: __builtin_clz(static_cast<uint32_t>(value)) - (32 - bits)
: bits;
}
template <typename T, unsigned bits = sizeof(T) * 8>
ALWAYS_INLINE constexpr
typename std::enable_if<std::is_unsigned<T>::value && sizeof(T) <= 8,
unsigned>::type
CountTrailingZeroBits(T value) {
return LIKELY(value) ? bits == 64
? __builtin_ctzll(static_cast<uint64_t>(value))
: __builtin_ctz(static_cast<uint32_t>(value))
: bits;
}
ALWAYS_INLINE constexpr uint32_t CountLeadingZeroBits32(uint32_t x) {
return CountLeadingZeroBits(x);
}
ALWAYS_INLINE constexpr uint64_t CountLeadingZeroBits64(uint64_t x) {
return CountLeadingZeroBits(x);
}
#endif
ALWAYS_INLINE constexpr size_t CountLeadingZeroBitsSizeT(size_t x) {
return CountLeadingZeroBits(x);
}
ALWAYS_INLINE constexpr size_t CountTrailingZeroBitsSizeT(size_t x) {
return CountTrailingZeroBits(x);
}
// Returns the integer i such as 2^i <= n < 2^(i+1).
//
// There is a common `BitLength` function, which returns the number of bits
// required to represent a value. Rather than implement that function,
// use `Log2Floor` and add 1 to the result.
constexpr int Log2Floor(uint32_t n) {
return 31 - CountLeadingZeroBits(n);
}
// Returns the integer i such as 2^(i-1) < n <= 2^i.
constexpr int Log2Ceiling(uint32_t n) {
// When n == 0, we want the function to return -1.
// When n == 0, (n - 1) will underflow to 0xFFFFFFFF, which is
// why the statement below starts with (n ? 32 : -1).
return (n ? 32 : -1) - CountLeadingZeroBits(n - 1);
}
// Returns a value of type T with a single bit set in the left-most position.
// Can be used instead of manually shifting a 1 to the left.
template <typename T>
constexpr T LeftmostBit() {
static_assert(std::is_integral<T>::value,
"This function can only be used with integral types.");
T one(1u);
return one << ((CHAR_BIT * sizeof(T) - 1));
}
} // namespace partition_alloc::internal::base::bits
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_BASE_BITS_H_

View File

@ -1,132 +0,0 @@
// Copyright (c) 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_BASE_MIGRATION_ADAPTER_H_
#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_BASE_MIGRATION_ADAPTER_H_
#include <cstdint>
#include <string>
#include "base/base_export.h"
#include "build/build_config.h"
#if BUILDFLAG(IS_MAC)
#include <CoreFoundation/CoreFoundation.h>
#endif
namespace base {
class LapTimer;
class PlatformThread;
class PlatformThreadHandle;
class PlatformThreadRef;
class TimeDelta;
class TimeTicks;
class CPU;
template <typename Type, typename Traits>
class LazyInstance;
template <typename Type>
struct LazyInstanceTraitsBase;
template <typename T>
constexpr TimeDelta Seconds(T n);
template <typename T>
constexpr TimeDelta Milliseconds(T n);
template <typename T>
constexpr TimeDelta Microseconds(T n);
BASE_EXPORT uint64_t RandGenerator(uint64_t range);
BASE_EXPORT std::string StringPrintf(const char* format, ...);
template <typename T, typename O>
class NoDestructor;
namespace debug {
void BASE_EXPORT Alias(const void* var);
} // namespace debug
namespace internal {
template <typename T>
class CheckedNumeric;
}
#if BUILDFLAG(IS_MAC)
namespace internal {
template <typename CFT>
struct ScopedCFTypeRefTraits;
} // namespace internal
template <typename T, typename Traits>
class ScopedTypeRef;
namespace mac {
template <typename T>
T CFCast(const CFTypeRef& cf_val);
template <typename T>
T CFCastStrict(const CFTypeRef& cf_val);
bool IsAtLeastOS10_14();
bool IsOS10_11();
} // namespace mac
#endif // BUILDFLAG(IS_MAC)
} // namespace base
namespace partition_alloc::internal::base {
// TODO(https://crbug.com/1288247): Remove these 'using' declarations once
// the migration to the new namespaces gets done.
using ::base::CPU;
using ::base::LapTimer;
using ::base::LazyInstance;
using ::base::LazyInstanceTraitsBase;
using ::base::Microseconds;
using ::base::Milliseconds;
using ::base::NoDestructor;
using ::base::PlatformThread;
using ::base::PlatformThreadHandle;
using ::base::PlatformThreadRef;
using ::base::RandGenerator;
using ::base::Seconds;
using ::base::StringPrintf;
using ::base::TimeDelta;
using ::base::TimeTicks;
using ::base::internal::CheckedNumeric;
#if BUILDFLAG(IS_MAC)
template <typename CFT>
using ScopedCFTypeRef =
::base::ScopedTypeRef<CFT, ::base::internal::ScopedCFTypeRefTraits<CFT>>;
#endif
namespace debug {
using ::base::debug::Alias;
} // namespace debug
#if BUILDFLAG(IS_MAC)
namespace mac {
using ::base::mac::CFCast;
using ::base::mac::IsAtLeastOS10_14;
using ::base::mac::IsOS10_11;
} // namespace mac
#endif // BUILDFLAG(IS_MAC)
} // namespace partition_alloc::internal::base
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_BASE_MIGRATION_ADAPTER_H_

View File

@ -1,144 +0,0 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This header defines cross-platform ByteSwap() implementations for 16, 32 and
// 64-bit values, and NetToHostXX() / HostToNextXX() functions equivalent to
// the traditional ntohX() and htonX() functions.
// Use the functions defined here rather than using the platform-specific
// functions directly.
#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_BASE_SYS_BYTEORDER_H_
#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_BASE_SYS_BYTEORDER_H_
#include <cstdint>
#include "base/allocator/partition_allocator/base/migration_adapter.h"
#include "build/build_config.h"
#if defined(COMPILER_MSVC)
#include <cstdlib>
#endif
namespace partition_alloc::internal::base {
// Returns a value with all bytes in |x| swapped, i.e. reverses the endianness.
inline uint16_t ByteSwap(uint16_t x) {
#if defined(COMPILER_MSVC) && !defined(__clang__)
return _byteswap_ushort(x);
#else
return __builtin_bswap16(x);
#endif
}
inline uint32_t ByteSwap(uint32_t x) {
#if defined(COMPILER_MSVC) && !defined(__clang__)
return _byteswap_ulong(x);
#else
return __builtin_bswap32(x);
#endif
}
inline constexpr uint64_t ByteSwap(uint64_t x) {
// Per build/build_config.h, clang masquerades as MSVC on Windows. If we are
// actually using clang, we can rely on the builtin.
//
// This matters in practice, because on x86(_64), this is a single "bswap"
// instruction. MSVC correctly replaces the call with an inlined bswap at /O2
// as of 2021, but clang as we use it in Chromium doesn't, keeping a function
// call for a single instruction.
#if defined(COMPILER_MSVC) && !defined(__clang__)
return _byteswap_uint64(x);
#else
return __builtin_bswap64(x);
#endif
}
inline constexpr uintptr_t ByteSwapUintPtrT(uintptr_t x) {
// We do it this way because some build configurations are ILP32 even when
// defined(ARCH_CPU_64_BITS). Unfortunately, we can't use sizeof in #ifs. But,
// because these conditionals are constexprs, the irrelevant branches will
// likely be optimized away, so this construction should not result in code
// bloat.
static_assert(sizeof(uintptr_t) == 4 || sizeof(uintptr_t) == 8,
"Unsupported uintptr_t size");
if (sizeof(uintptr_t) == 4)
return ByteSwap(static_cast<uint32_t>(x));
return ByteSwap(static_cast<uint64_t>(x));
}
// Converts the bytes in |x| from host order (endianness) to little endian, and
// returns the result.
inline uint16_t ByteSwapToLE16(uint16_t x) {
#if defined(ARCH_CPU_LITTLE_ENDIAN)
return x;
#else
return ByteSwap(x);
#endif
}
inline uint32_t ByteSwapToLE32(uint32_t x) {
#if defined(ARCH_CPU_LITTLE_ENDIAN)
return x;
#else
return ByteSwap(x);
#endif
}
inline uint64_t ByteSwapToLE64(uint64_t x) {
#if defined(ARCH_CPU_LITTLE_ENDIAN)
return x;
#else
return ByteSwap(x);
#endif
}
// Converts the bytes in |x| from network to host order (endianness), and
// returns the result.
inline uint16_t NetToHost16(uint16_t x) {
#if defined(ARCH_CPU_LITTLE_ENDIAN)
return ByteSwap(x);
#else
return x;
#endif
}
inline uint32_t NetToHost32(uint32_t x) {
#if defined(ARCH_CPU_LITTLE_ENDIAN)
return ByteSwap(x);
#else
return x;
#endif
}
inline uint64_t NetToHost64(uint64_t x) {
#if defined(ARCH_CPU_LITTLE_ENDIAN)
return ByteSwap(x);
#else
return x;
#endif
}
// Converts the bytes in |x| from host to network order (endianness), and
// returns the result.
inline uint16_t HostToNet16(uint16_t x) {
#if defined(ARCH_CPU_LITTLE_ENDIAN)
return ByteSwap(x);
#else
return x;
#endif
}
inline uint32_t HostToNet32(uint32_t x) {
#if defined(ARCH_CPU_LITTLE_ENDIAN)
return ByteSwap(x);
#else
return x;
#endif
}
inline uint64_t HostToNet64(uint64_t x) {
#if defined(ARCH_CPU_LITTLE_ENDIAN)
return ByteSwap(x);
#else
return x;
#endif
}
} // namespace partition_alloc::internal::base
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_BASE_SYS_BYTEORDER_H_

View File

@ -1,90 +0,0 @@
# Build Config
PartitionAlloc's behavior and operation can be influenced by many
different settings. Broadly, these are controlled at the top-level by
[GN args][gn-declare-args], which propagate via
[buildflags][buildflag-header] and `#defined` clauses.
*** promo
Most of what you'll want to know exists between
* [`//base/allocator/partition_allocator/BUILD.gn`][pa-build-gn],
* [`allocator.gni`][allocator-gni],
* [`//base/allocator/BUILD.gn`][base-allocator-build-gn], and
* [`//base/BUILD.gn`][base-build-gn].
***
*** aside
While Chromium promotes the `#if BUILDFLAG(FOO)` construct, some of
PartitionAlloc's behavior is governed by compound conditions `#defined`
in [`partition_alloc_config.h`][partition-alloc-config].
***
## Select GN Args
### `use_partition_alloc`
Defines whether PartitionAlloc is at all available.
Setting this `false` will entirely remove PartitionAlloc from the
Chromium build. _You probably do not want this._
*** note
Back when PartitionAlloc was the dedicated allocator in Blink, disabling
it was logically identical to wholly disabling it in Chromium. This GN
arg organically grew in scope with the advent of
PartitionAlloc-Everywhere and must be `true` as a prerequisite for
enabling PA-E.
***
### `use_allocator`
Does nothing special when value is `"none"`. Enables
[PartitionAlloc-Everywhere (PA-E)][pae-public-doc] when value is
`"partition"`.
*** note
* While "everywhere" (in "PartitionAlloc-Everywhere") tautologically
includes Blink where PartitionAlloc originated, setting
`use_allocator = "none"` does not disable PA usage in Blink.
* `use_allocator = "partition"` internally sets
`use_partition_alloc_as_malloc = true`, which must not be confused
with `use_partition_alloc` (see above).
***
### `use_backup_ref_ptr`
Specifies `BackupRefPtr` as the implementation for `base::raw_ptr<T>`
when `true`. See the [MiraclePtr documentation][miracleptr-doc].
*** aside
BRP requires support from PartitionAlloc, so `use_backup_ref_ptr` also
compiles the relevant code into PA. However, this arg does _not_ govern
whether or not BRP is actually enabled at runtime - that functionality
is controlled by a Finch flag.
***
## Note: Component Builds
When working on PartitionAlloc, know that `is_debug` defaults to
implying `is_component_build`, which interferes with the allocator
shim. A typical set of GN args should include
```none
is_debug = true
is_component_build = false
```
Conversely, build configurations that have `is_component_build = true`
without explicitly specifying PA-specific args will not build with PA-E
enabled.
[gn-declare-args]: https://gn.googlesource.com/gn/+/refs/heads/main/docs/reference.md#func_declare_args
[buildflag-header]: https://source.chromium.org/chromium/chromium/src/+/main:build/buildflag_header.gni
[pa-build-gn]: https://source.chromium.org/chromium/chromium/src/+/main:base/allocator/partition_allocator/BUILD.gn
[allocator-gni]: https://source.chromium.org/chromium/chromium/src/+/main:base/allocator/allocator.gni
[base-allocator-build-gn]: https://source.chromium.org/chromium/chromium/src/+/main:base/allocator/BUILD.gn
[base-build-gn]: https://source.chromium.org/chromium/chromium/src/+/main:base/BUILD.gn
[partition-alloc-config]: https://source.chromium.org/chromium/chromium/src/+/main:base/allocator/partition_allocator/partition_alloc_config.h
[pae-public-doc]: https://docs.google.com/document/d/1R1H9z5IVUAnXJgDjnts3nTJVcRbufWWT9ByXLgecSUM/preview
[miracleptr-doc]: https://docs.google.com/document/d/1pnnOAIz_DMWDI4oIOFoMAqLnf_MZ2GsrJNb_dbQ3ZBg/preview

View File

@ -8,7 +8,7 @@
#include "base/allocator/buildflags.h" #include "base/allocator/buildflags.h"
#include "base/allocator/partition_allocator/thread_cache.h" #include "base/allocator/partition_allocator/thread_cache.h"
namespace partition_alloc::internal { namespace base {
#if defined(PA_THREAD_CACHE_SUPPORTED) #if defined(PA_THREAD_CACHE_SUPPORTED)
@ -20,7 +20,7 @@ void DisableThreadCacheForRootIfEnabled(ThreadSafePartitionRoot* root) {
if (!root || !root->with_thread_cache) if (!root || !root->with_thread_cache)
return; return;
ThreadCacheRegistry::Instance().PurgeAll(); internal::ThreadCacheRegistry::Instance().PurgeAll();
root->with_thread_cache = false; root->with_thread_cache = false;
// Doesn't destroy the thread cache object(s). For background threads, they // Doesn't destroy the thread cache object(s). For background threads, they
// will be collected (and free cached memory) at thread destruction // will be collected (and free cached memory) at thread destruction
@ -36,14 +36,13 @@ void EnablePartitionAllocThreadCacheForRootIfDisabled(
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
void DisablePartitionAllocThreadCacheForProcess() { void DisablePartitionAllocThreadCacheForProcess() {
auto* regular_allocator = ::base::internal::PartitionAllocMalloc::Allocator(); auto* regular_allocator = internal::PartitionAllocMalloc::Allocator();
auto* aligned_allocator = auto* aligned_allocator = internal::PartitionAllocMalloc::AlignedAllocator();
::base::internal::PartitionAllocMalloc::AlignedAllocator();
DisableThreadCacheForRootIfEnabled(regular_allocator); DisableThreadCacheForRootIfEnabled(regular_allocator);
if (aligned_allocator != regular_allocator) if (aligned_allocator != regular_allocator)
DisableThreadCacheForRootIfEnabled(aligned_allocator); DisableThreadCacheForRootIfEnabled(aligned_allocator);
DisableThreadCacheForRootIfEnabled( DisableThreadCacheForRootIfEnabled(
::base::internal::PartitionAllocMalloc::OriginalAllocator()); internal::PartitionAllocMalloc::OriginalAllocator());
} }
#endif // defined(USE_PARTITION_ALLOC_AS_MALLOC) #endif // defined(USE_PARTITION_ALLOC_AS_MALLOC)
@ -57,10 +56,10 @@ void SwapOutProcessThreadCacheForTesting(ThreadSafePartitionRoot* root) {
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
DisablePartitionAllocThreadCacheForProcess(); DisablePartitionAllocThreadCacheForProcess();
#else #else
PA_CHECK(!ThreadCache::IsValid(ThreadCache::Get())); PA_CHECK(!internal::ThreadCache::IsValid(internal::ThreadCache::Get()));
#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) #endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
ThreadCache::SwapForTesting(root); internal::ThreadCache::SwapForTesting(root);
EnablePartitionAllocThreadCacheForRootIfDisabled(root); EnablePartitionAllocThreadCacheForRootIfDisabled(root);
#endif // defined(PA_THREAD_CACHE_SUPPORTED) #endif // defined(PA_THREAD_CACHE_SUPPORTED)
@ -73,15 +72,15 @@ void SwapInProcessThreadCacheForTesting(ThreadSafePartitionRoot* root) {
DisableThreadCacheForRootIfEnabled(root); DisableThreadCacheForRootIfEnabled(root);
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
auto* regular_allocator = ::base::internal::PartitionAllocMalloc::Allocator(); auto* regular_allocator = internal::PartitionAllocMalloc::Allocator();
EnablePartitionAllocThreadCacheForRootIfDisabled(regular_allocator); EnablePartitionAllocThreadCacheForRootIfDisabled(regular_allocator);
ThreadCache::SwapForTesting(regular_allocator); internal::ThreadCache::SwapForTesting(regular_allocator);
#else #else
ThreadCache::SwapForTesting(nullptr); internal::ThreadCache::SwapForTesting(nullptr);
#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) #endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
#endif // defined(PA_THREAD_CACHE_SUPPORTED) #endif // defined(PA_THREAD_CACHE_SUPPORTED)
} }
} // namespace partition_alloc::internal } // namespace base

View File

@ -9,7 +9,7 @@
#include "base/allocator/partition_allocator/thread_cache.h" #include "base/allocator/partition_allocator/thread_cache.h"
#include "base/base_export.h" #include "base/base_export.h"
namespace partition_alloc::internal { namespace base {
// These two functions are unsafe to run if there are multiple threads running // These two functions are unsafe to run if there are multiple threads running
// in the process. // in the process.
// //
@ -22,6 +22,6 @@ BASE_EXPORT void SwapOutProcessThreadCacheForTesting(
BASE_EXPORT void SwapInProcessThreadCacheForTesting( BASE_EXPORT void SwapInProcessThreadCacheForTesting(
ThreadSafePartitionRoot* root); ThreadSafePartitionRoot* root);
} // namespace partition_alloc::internal } // namespace base
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_EXTENDED_API_H_ #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_EXTENDED_API_H_

View File

@ -81,7 +81,7 @@ void MemoryReclaimer::Reclaim(int flags) {
// as there is periodic purge which makes sure that it doesn't take too much // as there is periodic purge which makes sure that it doesn't take too much
// space. // space.
if (flags & PurgeFlags::kAggressiveReclaim) if (flags & PurgeFlags::kAggressiveReclaim)
ThreadCacheRegistry::Instance().PurgeAll(); base::internal::ThreadCacheRegistry::Instance().PurgeAll();
#endif #endif
for (auto* partition : partitions_) for (auto* partition : partitions_)

View File

@ -10,7 +10,6 @@
#include "base/allocator/partition_allocator/partition_alloc_forward.h" #include "base/allocator/partition_allocator/partition_alloc_forward.h"
#include "base/allocator/partition_allocator/partition_lock.h" #include "base/allocator/partition_allocator/partition_lock.h"
#include "base/base_export.h"
#include "base/no_destructor.h" #include "base/no_destructor.h"
#include "base/thread_annotations.h" #include "base/thread_annotations.h"
#include "base/time/time.h" #include "base/time/time.h"

View File

@ -8,10 +8,10 @@
#include <cstdint> #include <cstdint>
#include "base/allocator/partition_allocator/address_space_randomization.h" #include "base/allocator/partition_allocator/address_space_randomization.h"
#include "base/allocator/partition_allocator/base/bits.h"
#include "base/allocator/partition_allocator/page_allocator_internal.h" #include "base/allocator/partition_allocator/page_allocator_internal.h"
#include "base/allocator/partition_allocator/partition_alloc_check.h" #include "base/allocator/partition_allocator/partition_alloc_check.h"
#include "base/allocator/partition_allocator/partition_lock.h" #include "base/allocator/partition_allocator/partition_lock.h"
#include "base/bits.h"
#include "build/build_config.h" #include "build/build_config.h"
#if BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_WIN)
@ -76,7 +76,7 @@ uintptr_t TrimMapping(uintptr_t base_address,
uintptr_t alignment_offset, uintptr_t alignment_offset,
PageAccessibilityConfiguration accessibility) { PageAccessibilityConfiguration accessibility) {
PA_DCHECK(base_length >= trim_length); PA_DCHECK(base_length >= trim_length);
PA_DCHECK(internal::base::bits::IsPowerOfTwo(alignment)); PA_DCHECK(base::bits::IsPowerOfTwo(alignment));
PA_DCHECK(alignment_offset < alignment); PA_DCHECK(alignment_offset < alignment);
uintptr_t new_base = uintptr_t new_base =
NextAlignedWithOffset(base_address, alignment, alignment_offset); NextAlignedWithOffset(base_address, alignment, alignment_offset);
@ -105,7 +105,7 @@ uintptr_t TrimMapping(uintptr_t base_address,
uintptr_t NextAlignedWithOffset(uintptr_t address, uintptr_t NextAlignedWithOffset(uintptr_t address,
uintptr_t alignment, uintptr_t alignment,
uintptr_t requested_offset) { uintptr_t requested_offset) {
PA_DCHECK(internal::base::bits::IsPowerOfTwo(alignment)); PA_DCHECK(base::bits::IsPowerOfTwo(alignment));
PA_DCHECK(requested_offset < alignment); PA_DCHECK(requested_offset < alignment);
uintptr_t actual_offset = address & (alignment - 1); uintptr_t actual_offset = address & (alignment - 1);
@ -175,7 +175,7 @@ uintptr_t AllocPagesWithAlignOffset(
PA_DCHECK(!(length & internal::PageAllocationGranularityOffsetMask())); PA_DCHECK(!(length & internal::PageAllocationGranularityOffsetMask()));
PA_DCHECK(align >= internal::PageAllocationGranularity()); PA_DCHECK(align >= internal::PageAllocationGranularity());
// Alignment must be power of 2 for masking math to work. // Alignment must be power of 2 for masking math to work.
PA_DCHECK(internal::base::bits::IsPowerOfTwo(align)); PA_DCHECK(base::bits::IsPowerOfTwo(align));
PA_DCHECK(align_offset < align); PA_DCHECK(align_offset < align);
PA_DCHECK(!(align_offset & internal::PageAllocationGranularityOffsetMask())); PA_DCHECK(!(align_offset & internal::PageAllocationGranularityOffsetMask()));
PA_DCHECK(!(address & internal::PageAllocationGranularityOffsetMask())); PA_DCHECK(!(address & internal::PageAllocationGranularityOffsetMask()));

View File

@ -24,31 +24,6 @@
// elimination. // elimination.
#define PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR __attribute__((const)) #define PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR __attribute__((const))
#elif BUILDFLAG(IS_LINUX) && defined(ARCH_CPU_ARM64)
// This should work for all POSIX (if needed), but currently all other
// supported OS/architecture combinations use either hard-coded values
// (such as x86) or have means to determine these values without needing
// atomics (such as macOS on arm64).
// Page allocator constants are run-time constant
#define PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR __attribute__((const))
#include <unistd.h>
#include <atomic>
namespace partition_alloc::internal {
// Holds the current page size and shift, where size = 1 << shift
// Use PageAllocationGranularity(), PageAllocationGranularityShift()
// to initialize and retrieve these values safely.
struct PageCharacteristics {
std::atomic<int> size;
std::atomic<int> shift;
};
extern PageCharacteristics page_characteristics;
} // namespace partition_alloc::internal
#else #else
// When defined, page size constants are fixed at compile time. When not // When defined, page size constants are fixed at compile time. When not
@ -63,10 +38,6 @@ extern PageCharacteristics page_characteristics;
namespace partition_alloc::internal { namespace partition_alloc::internal {
// Forward declaration, implementation below
PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t
PageAllocationGranularity();
PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t
PageAllocationGranularityShift() { PageAllocationGranularityShift() {
#if BUILDFLAG(IS_WIN) || defined(ARCH_CPU_PPC64) #if BUILDFLAG(IS_WIN) || defined(ARCH_CPU_PPC64)
@ -79,15 +50,6 @@ PageAllocationGranularityShift() {
return 14; // 16kB return 14; // 16kB
#elif BUILDFLAG(IS_APPLE) && defined(ARCH_CPU_64_BITS) #elif BUILDFLAG(IS_APPLE) && defined(ARCH_CPU_64_BITS)
return vm_page_shift; return vm_page_shift;
#elif BUILDFLAG(IS_LINUX) && defined(ARCH_CPU_ARM64)
// arm64 supports 4kb (shift = 12), 16kb (shift = 14), and 64kb (shift = 16)
// page sizes. Retrieve from or initialize cache.
int shift = page_characteristics.shift.load(std::memory_order_relaxed);
if (UNLIKELY(shift == 0)) {
shift = __builtin_ctz((int)PageAllocationGranularity());
page_characteristics.shift.store(shift, std::memory_order_relaxed);
}
return shift;
#else #else
return 12; // 4kB return 12; // 4kB
#endif #endif
@ -97,17 +59,8 @@ PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t
PageAllocationGranularity() { PageAllocationGranularity() {
#if BUILDFLAG(IS_APPLE) && defined(ARCH_CPU_64_BITS) #if BUILDFLAG(IS_APPLE) && defined(ARCH_CPU_64_BITS)
// This is literally equivalent to |1 << PageAllocationGranularityShift()| // This is literally equivalent to |1 << PageAllocationGranularityShift()|
// below, but was separated out for IS_APPLE to avoid << on a non-constexpr. // below, but was separated out for OS_APPLE to avoid << on a non-constexpr.
return vm_page_size; return vm_page_size;
#elif BUILDFLAG(IS_LINUX) && defined(ARCH_CPU_ARM64)
// arm64 supports 4kb, 16kb, and 64kb page sizes. Retrieve from or
// initialize cache.
int size = page_characteristics.size.load(std::memory_order_relaxed);
if (UNLIKELY(size == 0)) {
size = getpagesize();
page_characteristics.size.store(size, std::memory_order_relaxed);
}
return size;
#else #else
return 1 << PageAllocationGranularityShift(); return 1 << PageAllocationGranularityShift();
#endif #endif
@ -137,11 +90,9 @@ SystemPageShift() {
PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t
SystemPageSize() { SystemPageSize() {
#if (BUILDFLAG(IS_APPLE) && defined(ARCH_CPU_64_BITS)) || \ #if BUILDFLAG(IS_APPLE) && defined(ARCH_CPU_64_BITS)
(BUILDFLAG(IS_LINUX) && defined(ARCH_CPU_ARM64))
// This is literally equivalent to |1 << SystemPageShift()| below, but was // This is literally equivalent to |1 << SystemPageShift()| below, but was
// separated out for 64-bit IS_APPLE and arm64 on Linux to avoid << on a // separated out for 64-bit OS_APPLE to avoid << on a non-constexpr.
// non-constexpr.
return PageAllocationGranularity(); return PageAllocationGranularity();
#else #else
return 1 << SystemPageShift(); return 1 << SystemPageShift();

View File

@ -9,12 +9,12 @@
#include <ostream> #include <ostream>
#include "base/allocator/partition_allocator/address_pool_manager.h" #include "base/allocator/partition_allocator/address_pool_manager.h"
#include "base/allocator/partition_allocator/base/bits.h"
#include "base/allocator/partition_allocator/page_allocator.h" #include "base/allocator/partition_allocator/page_allocator.h"
#include "base/allocator/partition_allocator/partition_alloc_check.h" #include "base/allocator/partition_allocator/partition_alloc_check.h"
#include "base/allocator/partition_allocator/partition_alloc_config.h" #include "base/allocator/partition_allocator/partition_alloc_config.h"
#include "base/allocator/partition_allocator/partition_alloc_constants.h" #include "base/allocator/partition_allocator/partition_alloc_constants.h"
#include "base/allocator/partition_allocator/tagging.h" #include "base/allocator/partition_allocator/tagging.h"
#include "base/bits.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/debug/alias.h" #include "base/debug/alias.h"
#include "build/build_config.h" #include "build/build_config.h"
@ -43,7 +43,7 @@ NOINLINE void HandleGigaCageAllocFailureOutOfCommitCharge() {
NOINLINE void HandleGigaCageAllocFailure() { NOINLINE void HandleGigaCageAllocFailure() {
NO_CODE_FOLDING(); NO_CODE_FOLDING();
uint32_t alloc_page_error_code = GetAllocPageErrorCode(); uint32_t alloc_page_error_code = base::GetAllocPageErrorCode();
PA_DEBUG_DATA_ON_STACK("error", static_cast<size_t>(alloc_page_error_code)); PA_DEBUG_DATA_ON_STACK("error", static_cast<size_t>(alloc_page_error_code));
// It's important to easily differentiate these two failures on Windows, so // It's important to easily differentiate these two failures on Windows, so
// crash with different stacks. // crash with different stacks.
@ -184,12 +184,6 @@ void PartitionAddressSpace::UninitConfigurablePoolForTesting() {
setup_.configurable_pool_ = 0; setup_.configurable_pool_ = 0;
} }
#if BUILDFLAG(IS_LINUX) && defined(ARCH_CPU_ARM64)
PageCharacteristics page_characteristics;
#endif // BUILDFLAG(IS_LINUX) && defined(ARCH_CPU_ARM64)
#endif // defined(PA_HAS_64_BITS_POINTERS) #endif // defined(PA_HAS_64_BITS_POINTERS)
} // namespace partition_alloc::internal } // namespace partition_alloc::internal

View File

@ -11,7 +11,6 @@
#include "base/allocator/buildflags.h" #include "base/allocator/buildflags.h"
#include "base/allocator/partition_allocator/address_pool_manager_types.h" #include "base/allocator/partition_allocator/address_pool_manager_types.h"
#include "base/allocator/partition_allocator/base/bits.h"
#include "base/allocator/partition_allocator/page_allocator_constants.h" #include "base/allocator/partition_allocator/page_allocator_constants.h"
#include "base/allocator/partition_allocator/partition_alloc_check.h" #include "base/allocator/partition_allocator/partition_alloc_check.h"
#include "base/allocator/partition_allocator/partition_alloc_config.h" #include "base/allocator/partition_allocator/partition_alloc_config.h"
@ -20,6 +19,7 @@
#include "base/allocator/partition_allocator/partition_alloc_notreached.h" #include "base/allocator/partition_allocator/partition_alloc_notreached.h"
#include "base/allocator/partition_allocator/tagging.h" #include "base/allocator/partition_allocator/tagging.h"
#include "base/base_export.h" #include "base/base_export.h"
#include "base/bits.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "build/buildflag.h" #include "build/buildflag.h"

View File

@ -22,52 +22,44 @@
#include "base/allocator/partition_allocator/starscan/pcscan.h" #include "base/allocator/partition_allocator/starscan/pcscan.h"
#include "base/dcheck_is_on.h" #include "base/dcheck_is_on.h"
namespace partition_alloc { namespace base {
void PartitionAllocGlobalInit(OomFunction on_out_of_memory) { void PartitionAllocGlobalInit(OomFunction on_out_of_memory) {
// This is from page_allocator_constants.h and doesn't really fit here, but // This is from page_allocator_constants.h and doesn't really fit here, but
// there isn't a centralized initialization function in page_allocator.cc, so // there isn't a centralized initialization function in page_allocator.cc, so
// there's no good place in that file to do a STATIC_ASSERT_OR_PA_CHECK. // there's no good place in that file to do a STATIC_ASSERT_OR_PA_CHECK.
STATIC_ASSERT_OR_PA_CHECK( STATIC_ASSERT_OR_PA_CHECK((SystemPageSize() & SystemPageOffsetMask()) == 0,
(internal::SystemPageSize() & internal::SystemPageOffsetMask()) == 0, "SystemPageSize() must be power of 2");
"SystemPageSize() must be power of 2");
// Two partition pages are used as guard / metadata page so make sure the // Two partition pages are used as guard / metadata page so make sure the
// super page size is bigger. // super page size is bigger.
STATIC_ASSERT_OR_PA_CHECK( STATIC_ASSERT_OR_PA_CHECK(PartitionPageSize() * 4 <= kSuperPageSize,
internal::PartitionPageSize() * 4 <= internal::kSuperPageSize, "ok super page size");
"ok super page size"); STATIC_ASSERT_OR_PA_CHECK((kSuperPageSize & SystemPageOffsetMask()) == 0,
STATIC_ASSERT_OR_PA_CHECK( "ok super page multiple");
(internal::kSuperPageSize & internal::SystemPageOffsetMask()) == 0,
"ok super page multiple");
// Four system pages gives us room to hack out a still-guard-paged piece // Four system pages gives us room to hack out a still-guard-paged piece
// of metadata in the middle of a guard partition page. // of metadata in the middle of a guard partition page.
STATIC_ASSERT_OR_PA_CHECK( STATIC_ASSERT_OR_PA_CHECK(SystemPageSize() * 4 <= PartitionPageSize(),
internal::SystemPageSize() * 4 <= internal::PartitionPageSize(), "ok partition page size");
"ok partition page size"); STATIC_ASSERT_OR_PA_CHECK((PartitionPageSize() & SystemPageOffsetMask()) == 0,
STATIC_ASSERT_OR_PA_CHECK( "ok partition page multiple");
(internal::PartitionPageSize() & internal::SystemPageOffsetMask()) == 0,
"ok partition page multiple");
static_assert(sizeof(internal::PartitionPage<internal::ThreadSafe>) <= static_assert(sizeof(internal::PartitionPage<internal::ThreadSafe>) <=
internal::kPageMetadataSize, kPageMetadataSize,
"PartitionPage should not be too big"); "PartitionPage should not be too big");
STATIC_ASSERT_OR_PA_CHECK( STATIC_ASSERT_OR_PA_CHECK(
internal::kPageMetadataSize * internal::NumPartitionPagesPerSuperPage() <= kPageMetadataSize * NumPartitionPagesPerSuperPage() <= SystemPageSize(),
internal::SystemPageSize(),
"page metadata fits in hole"); "page metadata fits in hole");
// Limit to prevent callers accidentally overflowing an int size. // Limit to prevent callers accidentally overflowing an int size.
STATIC_ASSERT_OR_PA_CHECK( STATIC_ASSERT_OR_PA_CHECK(
internal::MaxDirectMapped() <= MaxDirectMapped() <= (1UL << 31) + DirectMapAllocationGranularity(),
(1UL << 31) + internal::DirectMapAllocationGranularity(),
"maximum direct mapped allocation"); "maximum direct mapped allocation");
// Check that some of our zanier calculations worked out as expected. // Check that some of our zanier calculations worked out as expected.
static_assert(internal::kSmallestBucket == internal::kAlignment, static_assert(kSmallestBucket == kAlignment, "generic smallest bucket");
"generic smallest bucket"); static_assert(kMaxBucketed == 917504, "generic max bucketed");
static_assert(internal::kMaxBucketed == 917504, "generic max bucketed");
STATIC_ASSERT_OR_PA_CHECK( STATIC_ASSERT_OR_PA_CHECK(
internal::MaxSystemPagesPerRegularSlotSpan() <= 16, MaxSystemPagesPerRegularSlotSpan() <= 16,
"System pages per slot span must be no greater than 16."); "System pages per slot span must be no greater than 16.");
PA_DCHECK(on_out_of_memory); PA_DCHECK(on_out_of_memory);
@ -118,4 +110,4 @@ void CheckThatSlotOffsetIsZero(uintptr_t address) {
} // namespace internal } // namespace internal
} // namespace partition_alloc } // namespace base

View File

@ -1,14 +0,0 @@
# Copyright (c) 2022 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
declare_args() {
make_partition_alloc_standalone = false
}
# TODO(): move partition allocator's own args defined by
# //base/allocator/allocator.gni here. e.g. put_ref_count_in_previous_slot
# (this changes partition alloc's behavior.)
# On the otherhand, partition_aloc_as_malloc is related to allocator_shim.
# Caller sides should init PA-E. e.g. PartitionAllocMallocInitOnce()

View File

@ -11,7 +11,7 @@
#include "base/base_export.h" #include "base/base_export.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
namespace partition_alloc { namespace base {
BASE_EXPORT void PartitionAllocGlobalInit(OomFunction on_out_of_memory); BASE_EXPORT void PartitionAllocGlobalInit(OomFunction on_out_of_memory);
BASE_EXPORT void PartitionAllocGlobalUninitForTesting(); BASE_EXPORT void PartitionAllocGlobalUninitForTesting();
@ -37,16 +37,14 @@ struct BASE_EXPORT PartitionAllocator {
using PartitionAllocator = internal::PartitionAllocator<internal::ThreadSafe>; using PartitionAllocator = internal::PartitionAllocator<internal::ThreadSafe>;
} // namespace partition_alloc } // namespace base
namespace base { namespace partition_alloc {
// TODO(https://crbug.com/1288247): Remove these 'using' declarations once // TODO(https://crbug.com/1288247): Remove these 'using' declarations once
// the migration to the new namespaces gets done. // the migration to the new namespaces gets done.
using ::partition_alloc::PartitionAllocator; using ::base::PartitionAllocator;
using ::partition_alloc::PartitionAllocGlobalInit;
using ::partition_alloc::PartitionAllocGlobalUninitForTesting;
} // namespace base } // namespace partition_alloc
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_H_ #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_H_

View File

@ -12,7 +12,6 @@
#include "base/check.h" #include "base/check.h"
#include "base/debug/alias.h" #include "base/debug/alias.h"
#include "base/immediate_crash.h" #include "base/immediate_crash.h"
#include "build/build_config.h"
#define PA_STRINGIFY_IMPL(s) #s #define PA_STRINGIFY_IMPL(s) #s
#define PA_STRINGIFY(s) PA_STRINGIFY_IMPL(s) #define PA_STRINGIFY(s) PA_STRINGIFY_IMPL(s)
@ -97,19 +96,10 @@
#endif #endif
// alignas(16) DebugKv causes breakpad_unittests and sandbox_linux_unittests
// failures on android-marshmallow-x86-rel because of SIGSEGV.
#if BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_X86_FAMILY) && \
defined(ARCH_CPU_32_BITS)
#define PA_DEBUGKV_ALIGN alignas(8)
#else
#define PA_DEBUGKV_ALIGN alignas(16)
#endif
namespace partition_alloc::internal { namespace partition_alloc::internal {
// Used for PA_DEBUG_DATA_ON_STACK, below. // Used for PA_DEBUG_DATA_ON_STACK, below.
struct PA_DEBUGKV_ALIGN DebugKv { struct alignas(16) DebugKv {
// 16 bytes object aligned on 16 bytes, to make it easier to see in crash // 16 bytes object aligned on 16 bytes, to make it easier to see in crash
// reports. // reports.
char k[8] = {}; // Not necessarily 0-terminated. char k[8] = {}; // Not necessarily 0-terminated.

View File

@ -205,16 +205,6 @@ constexpr bool kUseLazyCommit = false;
#define PA_REF_COUNT_CHECK_COOKIE #define PA_REF_COUNT_CHECK_COOKIE
#endif #endif
// Use available space in the reference count to store the initially requested
// size from the application. This is used for debugging, hence disabled by
// default.
// #define PA_REF_COUNT_STORE_REQUESTED_SIZE
#if defined(PA_REF_COUNT_STORE_REQUESTED_SIZE) && \
defined(PA_REF_COUNT_CHECK_COOKIE)
#error "Cannot use a cookie *and* store the allocation size"
#endif
// Prefer smaller slot spans. // Prefer smaller slot spans.
// //
// Smaller slot spans may improve dirty memory fragmentation, but may also // Smaller slot spans may improve dirty memory fragmentation, but may also
@ -222,21 +212,8 @@ constexpr bool kUseLazyCommit = false;
// //
// This is intended to roll out more broadly, but only enabled on Linux for now // This is intended to roll out more broadly, but only enabled on Linux for now
// to get performance bot and real-world data pre-A/B experiment. // to get performance bot and real-world data pre-A/B experiment.
// #if BUILDFLAG(IS_LINUX)
// Also enabled on ARM64 macOS, as the 16kiB pages on this platform lead to
// larger slot spans.
#if BUILDFLAG(IS_LINUX) || (BUILDFLAG(IS_MAC) && defined(ARCH_CPU_ARM64))
#define PA_PREFER_SMALLER_SLOT_SPANS #define PA_PREFER_SMALLER_SLOT_SPANS
#endif // BUILDFLAG(IS_LINUX) #endif // BUILDFLAG(IS_LINUX)
// Build MTECheckedPtr code.
//
// Only applicable to code with 64-bit pointers. Currently conflicts with true
// hardware MTE.
#if BUILDFLAG(USE_MTE_CHECKED_PTR) && defined(PA_HAS_64_BITS_POINTERS) && \
!defined(PA_HAS_MEMORY_TAGGING)
#define PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS
#endif // BUILDFLAG(USE_MTE_CHECKED_PTR) && defined(PA_HAS_64_BITS_POINTERS) &&
// !defined(PA_HAS_MEMORY_TAGGING)
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_CONFIG_H_ #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_CONFIG_H_

View File

@ -79,11 +79,10 @@ PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t
PartitionPageShift() { PartitionPageShift() {
return 18; // 256 KiB return 18; // 256 KiB
} }
#elif (BUILDFLAG(IS_APPLE) && defined(ARCH_CPU_64_BITS)) || \ #elif BUILDFLAG(IS_APPLE) && defined(ARCH_CPU_64_BITS)
(BUILDFLAG(IS_LINUX) && defined(ARCH_CPU_ARM64))
PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t
PartitionPageShift() { PartitionPageShift() {
return PageAllocationGranularityShift() + 2; return vm_page_shift + 2;
} }
#else #else
PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t
@ -152,7 +151,6 @@ MaxRegularSlotSpanSize() {
// | Guard page (4 KiB) | // | Guard page (4 KiB) |
// | Metadata page (4 KiB) | // | Metadata page (4 KiB) |
// | Guard pages (8 KiB) | // | Guard pages (8 KiB) |
// | TagBitmap |
// | *Scan State Bitmap | // | *Scan State Bitmap |
// | Slot span | // | Slot span |
// | Slot span | // | Slot span |
@ -161,9 +159,7 @@ MaxRegularSlotSpanSize() {
// | Guard pages (16 KiB) | // | Guard pages (16 KiB) |
// +-----------------------+ // +-----------------------+
// //
// TagBitmap is only present when // State Bitmap is inserted for partitions that may have quarantine enabled.
// defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS) is true. State Bitmap
// is inserted for partitions that may have quarantine enabled.
// //
// If refcount_at_end_allocation is enabled, RefcountBitmap(4KiB) is inserted // If refcount_at_end_allocation is enabled, RefcountBitmap(4KiB) is inserted
// after the Metadata page for BackupRefPtr. The guard pages after the bitmap // after the Metadata page for BackupRefPtr. The guard pages after the bitmap
@ -241,14 +237,11 @@ constexpr size_t kNumPools = 3;
// to keep for now only because nothing uses PartitionAlloc on iOS yet. // to keep for now only because nothing uses PartitionAlloc on iOS yet.
#if BUILDFLAG(IS_IOS) #if BUILDFLAG(IS_IOS)
constexpr size_t kPoolMaxSize = kGiB / 4; constexpr size_t kPoolMaxSize = kGiB / 4;
#elif BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) #elif BUILDFLAG(IS_MAC)
// Special-case macOS. Contrary to other platforms, there is no sandbox limit // Special-case macOS. Contrary to other platforms, there is no sandbox limit
// there, meaning that a single renderer could "happily" consume >8GiB. So the // there, meaning that a single renderer could "happily" consume >8GiB. So the
// 8GiB pool size is a regression. Make the limit higher on this platform only // 8GiB pool size is a regression. Make the limit higher on this platform only
// to be consistent with previous behavior. See crbug.com/1232567 for details. // to be consistent with previous behavior. See crbug.com/1232567 for details.
//
// On Linux, reserving memory is not costly, and we have cases where heaps can
// grow to more than 8GiB without being a memory leak.
constexpr size_t kPoolMaxSize = 16 * kGiB; constexpr size_t kPoolMaxSize = 16 * kGiB;
#else #else
constexpr size_t kPoolMaxSize = 8 * kGiB; constexpr size_t kPoolMaxSize = 8 * kGiB;
@ -360,6 +353,7 @@ constexpr size_t kMinDirectMappedDownsize = kMaxBucketed + 1;
// Intentionally set to less than 2GiB to make sure that a 2GiB allocation // Intentionally set to less than 2GiB to make sure that a 2GiB allocation
// fails. This is a security choice in Chrome, to help making size_t vs int bugs // fails. This is a security choice in Chrome, to help making size_t vs int bugs
// harder to exploit. // harder to exploit.
//
PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t
MaxDirectMapped() { MaxDirectMapped() {

View File

@ -44,29 +44,17 @@ constexpr bool ThreadSafe = true;
template <bool thread_safe> template <bool thread_safe>
struct SlotSpanMetadata; struct SlotSpanMetadata;
#if (DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)) && \
BUILDFLAG(USE_BACKUP_REF_PTR)
void CheckThatSlotOffsetIsZero(uintptr_t address);
#endif
} // namespace internal } // namespace internal
class PartitionStatsDumper; class PartitionStatsDumper;
template <bool thread_safe = internal::ThreadSafe>
struct PartitionRoot;
using ThreadSafePartitionRoot = PartitionRoot<internal::ThreadSafe>;
} // namespace partition_alloc } // namespace partition_alloc
namespace base { namespace base {
// TODO(https://crbug.com/1288247): Remove these 'using' declarations once // TODO(https://crbug.com/1288247): Remove these 'using' declarations once
// the migration to the new namespaces gets done. // the migration to the new namespaces gets done.
using ::partition_alloc::PartitionRoot;
using ::partition_alloc::PartitionStatsDumper; using ::partition_alloc::PartitionStatsDumper;
using ::partition_alloc::ThreadSafePartitionRoot;
using ::partition_alloc::internal::kAlignment; using ::partition_alloc::internal::kAlignment;
namespace internal { namespace internal {
@ -76,13 +64,35 @@ using ::partition_alloc::internal::ThreadSafe;
#if (DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)) && \ #if (DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)) && \
BUILDFLAG(USE_BACKUP_REF_PTR) BUILDFLAG(USE_BACKUP_REF_PTR)
using ::partition_alloc::internal::CheckThatSlotOffsetIsZero; BASE_EXPORT void CheckThatSlotOffsetIsZero(uintptr_t address);
#endif #endif
} // namespace internal } // namespace internal
template <bool thread_safe = true>
struct PartitionRoot;
using ThreadSafePartitionRoot = PartitionRoot<internal::ThreadSafe>;
} // namespace base } // namespace base
namespace partition_alloc {
// TODO(https://crbug.com/1288247): Remove these 'using' declarations once
// the migration to the new namespaces gets done.
using ::base::PartitionRoot;
namespace internal {
#if (DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)) && \
BUILDFLAG(USE_BACKUP_REF_PTR)
using ::base::internal::CheckThatSlotOffsetIsZero;
#endif
} // namespace internal
} // namespace partition_alloc
// From https://clang.llvm.org/docs/AttributeReference.html#malloc: // From https://clang.llvm.org/docs/AttributeReference.html#malloc:
// //
// The malloc attribute indicates that the function acts like a system memory // The malloc attribute indicates that the function acts like a system memory

View File

@ -8,7 +8,6 @@
#include "base/allocator/buildflags.h" #include "base/allocator/buildflags.h"
#include "base/allocator/partition_allocator/address_pool_manager.h" #include "base/allocator/partition_allocator/address_pool_manager.h"
#include "base/allocator/partition_allocator/base/bits.h"
#include "base/allocator/partition_allocator/oom.h" #include "base/allocator/partition_allocator/oom.h"
#include "base/allocator/partition_allocator/page_allocator.h" #include "base/allocator/partition_allocator/page_allocator.h"
#include "base/allocator/partition_allocator/page_allocator_constants.h" #include "base/allocator/partition_allocator/page_allocator_constants.h"
@ -20,11 +19,10 @@
#include "base/allocator/partition_allocator/partition_direct_map_extent.h" #include "base/allocator/partition_allocator/partition_direct_map_extent.h"
#include "base/allocator/partition_allocator/partition_oom.h" #include "base/allocator/partition_allocator/partition_oom.h"
#include "base/allocator/partition_allocator/partition_page.h" #include "base/allocator/partition_allocator/partition_page.h"
#include "base/allocator/partition_allocator/partition_tag.h"
#include "base/allocator/partition_allocator/partition_tag_bitmap.h"
#include "base/allocator/partition_allocator/reservation_offset_table.h" #include "base/allocator/partition_allocator/reservation_offset_table.h"
#include "base/allocator/partition_allocator/starscan/state_bitmap.h" #include "base/allocator/partition_allocator/starscan/state_bitmap.h"
#include "base/allocator/partition_allocator/tagging.h" #include "base/allocator/partition_allocator/tagging.h"
#include "base/bits.h"
#include "base/check.h" #include "base/check.h"
#include "base/debug/alias.h" #include "base/debug/alias.h"
#include "build/build_config.h" #include "build/build_config.h"
@ -636,28 +634,6 @@ PartitionBucket<thread_safe>::AllocNewSlotSpan(PartitionRoot<thread_safe>* root,
// Double check that we had enough space in the super page for the new slot // Double check that we had enough space in the super page for the new slot
// span. // span.
PA_DCHECK(root->next_partition_page <= root->next_partition_page_end); PA_DCHECK(root->next_partition_page <= root->next_partition_page_end);
#if defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
PA_DCHECK(root->next_tag_bitmap_page);
uintptr_t next_tag_bitmap_page =
base::bits::AlignUp(reinterpret_cast<uintptr_t>(
PartitionTagPointer(root->next_partition_page)),
SystemPageSize());
if (root->next_tag_bitmap_page < next_tag_bitmap_page) {
#if DCHECK_IS_ON()
uintptr_t super_page =
reinterpret_cast<uintptr_t>(slot_span) & kSuperPageBaseMask;
uintptr_t tag_bitmap = super_page + PartitionPageSize();
PA_DCHECK(next_tag_bitmap_page <= tag_bitmap + ActualTagBitmapSize());
PA_DCHECK(next_tag_bitmap_page > tag_bitmap);
#endif
SetSystemPagesAccess(root->next_tag_bitmap_page,
next_tag_bitmap_page - root->next_tag_bitmap_page,
PageAccessibilityConfiguration::kReadWrite);
root->next_tag_bitmap_page = next_tag_bitmap_page;
}
#endif // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
return slot_span; return slot_span;
} }
@ -690,9 +666,7 @@ ALWAYS_INLINE uintptr_t PartitionBucket<thread_safe>::AllocNewSuperPage(
std::memory_order_relaxed); std::memory_order_relaxed);
root->next_super_page = super_page + kSuperPageSize; root->next_super_page = super_page + kSuperPageSize;
// TODO(crbug.com/1307514): Add direct map support. uintptr_t state_bitmap = super_page + PartitionPageSize();
uintptr_t state_bitmap = super_page + PartitionPageSize() +
(is_direct_mapped() ? 0 : ReservedTagBitmapSize());
PA_DCHECK(SuperPageStateBitmapAddr(super_page) == state_bitmap); PA_DCHECK(SuperPageStateBitmapAddr(super_page) == state_bitmap);
const size_t state_bitmap_reservation_size = const size_t state_bitmap_reservation_size =
root->IsQuarantineAllowed() ? ReservedStateBitmapSize() : 0; root->IsQuarantineAllowed() ? ReservedStateBitmapSize() : 0;
@ -771,19 +745,6 @@ ALWAYS_INLINE uintptr_t PartitionBucket<thread_safe>::AllocNewSuperPage(
payload < SuperPagesEndFromExtent(current_extent)); payload < SuperPagesEndFromExtent(current_extent));
} }
#if defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
// `root->next_partition_page` currently points at the start of the
// super page payload. We point `root->next_tag_bitmap_page` to the
// corresponding point in the tag bitmap and let the caller
// (slot span allocation) take care of the rest.
root->next_tag_bitmap_page =
base::bits::AlignDown(reinterpret_cast<uintptr_t>(
PartitionTagPointer(root->next_partition_page)),
SystemPageSize());
PA_DCHECK(root->next_tag_bitmap_page >= super_page + PartitionPageSize())
<< "tag bitmap can never intrude on metadata partition page";
#endif // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
// If PCScan is used, commit the state bitmap. Otherwise, leave it uncommitted // If PCScan is used, commit the state bitmap. Otherwise, leave it uncommitted
// and let PartitionRoot::RegisterScannableRoot() commit it when needed. Make // and let PartitionRoot::RegisterScannableRoot() commit it when needed. Make
// sure to register the super-page after it has been fully initialized. // sure to register the super-page after it has been fully initialized.
@ -880,9 +841,6 @@ PartitionBucket<thread_safe>::ProvisionMoreSlotsAndAllocOne(
return_slot = return_slot =
::partition_alloc::internal::TagMemoryRangeRandomly(return_slot, size); ::partition_alloc::internal::TagMemoryRangeRandomly(return_slot, size);
} }
#if defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
PartitionTagSetValue(return_slot, size, root->GetNewPartitionTag());
#endif // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
// Add all slots that fit within so far committed pages to the free list. // Add all slots that fit within so far committed pages to the free list.
PartitionFreelistEntry* prev_entry = nullptr; PartitionFreelistEntry* prev_entry = nullptr;
@ -893,9 +851,6 @@ PartitionBucket<thread_safe>::ProvisionMoreSlotsAndAllocOne(
next_slot = next_slot =
::partition_alloc::internal::TagMemoryRangeRandomly(next_slot, size); ::partition_alloc::internal::TagMemoryRangeRandomly(next_slot, size);
} }
#if defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
PartitionTagSetValue(next_slot, size, root->GetNewPartitionTag());
#endif // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
auto* entry = PartitionFreelistEntry::EmplaceAndInitNull(next_slot); auto* entry = PartitionFreelistEntry::EmplaceAndInitNull(next_slot);
if (!slot_span->get_freelist_head()) { if (!slot_span->get_freelist_head()) {
PA_DCHECK(!prev_entry); PA_DCHECK(!prev_entry);

View File

@ -7,10 +7,10 @@
#include <cstdint> #include <cstdint>
#include "base/allocator/partition_allocator/base/bits.h"
#include "base/allocator/partition_allocator/partition_alloc_check.h" #include "base/allocator/partition_allocator/partition_alloc_check.h"
#include "base/allocator/partition_allocator/partition_alloc_config.h" #include "base/allocator/partition_allocator/partition_alloc_config.h"
#include "base/allocator/partition_allocator/partition_alloc_constants.h" #include "base/allocator/partition_allocator/partition_alloc_constants.h"
#include "base/bits.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
namespace partition_alloc::internal { namespace partition_alloc::internal {

View File

@ -9,16 +9,16 @@
#include <cstdint> #include <cstdint>
#include "base/allocator/buildflags.h" #include "base/allocator/buildflags.h"
#include "base/allocator/partition_allocator/base/bits.h"
#include "base/allocator/partition_allocator/base/sys_byteorder.h"
#include "base/allocator/partition_allocator/partition_alloc-inl.h" #include "base/allocator/partition_allocator/partition_alloc-inl.h"
#include "base/allocator/partition_allocator/partition_alloc_check.h" #include "base/allocator/partition_allocator/partition_alloc_check.h"
#include "base/allocator/partition_allocator/partition_alloc_config.h" #include "base/allocator/partition_allocator/partition_alloc_config.h"
#include "base/allocator/partition_allocator/partition_alloc_constants.h" #include "base/allocator/partition_allocator/partition_alloc_constants.h"
#include "base/allocator/partition_allocator/partition_ref_count.h" #include "base/allocator/partition_allocator/partition_ref_count.h"
#include "base/bits.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/dcheck_is_on.h" #include "base/dcheck_is_on.h"
#include "base/immediate_crash.h" #include "base/immediate_crash.h"
#include "base/sys_byteorder.h"
#include "build/build_config.h" #include "build/build_config.h"
namespace partition_alloc::internal { namespace partition_alloc::internal {
@ -289,13 +289,6 @@ ALWAYS_INLINE PartitionFreelistEntry* PartitionFreelistEntry::GetNextInternal(
// |for_thread_cache|, since the argument is always a compile-time constant. // |for_thread_cache|, since the argument is always a compile-time constant.
if (UNLIKELY(!IsSane(this, ret, for_thread_cache))) { if (UNLIKELY(!IsSane(this, ret, for_thread_cache))) {
if constexpr (crash_on_corruption) { if constexpr (crash_on_corruption) {
// Put the corrupted data on the stack, it may give us more information
// about what kind of corruption that was.
PA_DEBUG_DATA_ON_STACK("first",
static_cast<size_t>(encoded_next_.encoded_));
#if defined(PA_HAS_FREELIST_SHADOW_ENTRY)
PA_DEBUG_DATA_ON_STACK("second", static_cast<size_t>(shadow_));
#endif
FreelistCorruptionDetected(extra); FreelistCorruptionDetected(extra);
} else { } else {
return nullptr; return nullptr;

View File

@ -9,7 +9,6 @@
#include "base/allocator/buildflags.h" #include "base/allocator/buildflags.h"
#include "base/allocator/partition_allocator/address_pool_manager.h" #include "base/allocator/partition_allocator/address_pool_manager.h"
#include "base/allocator/partition_allocator/base/bits.h"
#include "base/allocator/partition_allocator/page_allocator.h" #include "base/allocator/partition_allocator/page_allocator.h"
#include "base/allocator/partition_allocator/page_allocator_constants.h" #include "base/allocator/partition_allocator/page_allocator_constants.h"
#include "base/allocator/partition_allocator/partition_address_space.h" #include "base/allocator/partition_allocator/partition_address_space.h"
@ -21,6 +20,7 @@
#include "base/allocator/partition_allocator/partition_root.h" #include "base/allocator/partition_allocator/partition_root.h"
#include "base/allocator/partition_allocator/reservation_offset_table.h" #include "base/allocator/partition_allocator/reservation_offset_table.h"
#include "base/allocator/partition_allocator/tagging.h" #include "base/allocator/partition_allocator/tagging.h"
#include "base/bits.h"
#include "base/dcheck_is_on.h" #include "base/dcheck_is_on.h"
namespace partition_alloc::internal { namespace partition_alloc::internal {

View File

@ -5,26 +5,25 @@
#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_PAGE_H_ #ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_PAGE_H_
#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_PAGE_H_ #define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_PAGE_H_
#include <string.h>
#include <cstdint> #include <cstdint>
#include <cstring>
#include <limits> #include <limits>
#include <utility> #include <utility>
#include "base/allocator/buildflags.h"
#include "base/allocator/partition_allocator/address_pool_manager.h" #include "base/allocator/partition_allocator/address_pool_manager.h"
#include "base/allocator/partition_allocator/address_pool_manager_types.h" #include "base/allocator/partition_allocator/address_pool_manager_types.h"
#include "base/allocator/partition_allocator/base/bits.h"
#include "base/allocator/partition_allocator/partition_address_space.h" #include "base/allocator/partition_allocator/partition_address_space.h"
#include "base/allocator/partition_allocator/partition_alloc_check.h" #include "base/allocator/partition_allocator/partition_alloc_check.h"
#include "base/allocator/partition_allocator/partition_alloc_constants.h" #include "base/allocator/partition_allocator/partition_alloc_constants.h"
#include "base/allocator/partition_allocator/partition_alloc_forward.h" #include "base/allocator/partition_allocator/partition_alloc_forward.h"
#include "base/allocator/partition_allocator/partition_bucket.h" #include "base/allocator/partition_allocator/partition_bucket.h"
#include "base/allocator/partition_allocator/partition_freelist_entry.h" #include "base/allocator/partition_allocator/partition_freelist_entry.h"
#include "base/allocator/partition_allocator/partition_tag_bitmap.h"
#include "base/allocator/partition_allocator/reservation_offset_table.h" #include "base/allocator/partition_allocator/reservation_offset_table.h"
#include "base/allocator/partition_allocator/starscan/state_bitmap.h" #include "base/allocator/partition_allocator/starscan/state_bitmap.h"
#include "base/allocator/partition_allocator/tagging.h" #include "base/allocator/partition_allocator/tagging.h"
#include "base/base_export.h" #include "base/base_export.h"
#include "base/bits.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/dcheck_is_on.h" #include "base/dcheck_is_on.h"
#include "base/thread_annotations.h" #include "base/thread_annotations.h"
@ -64,8 +63,8 @@ static_assert(
// CAUTION! |extent| must point to the extent of the first super page in the // CAUTION! |extent| must point to the extent of the first super page in the
// range of consecutive super pages. // range of consecutive super pages.
template <bool thread_safe> template <bool thread_safe>
ALWAYS_INLINE uintptr_t SuperPagesBeginFromExtent( ALWAYS_INLINE uintptr_t
const PartitionSuperPageExtentEntry<thread_safe>* extent) { SuperPagesBeginFromExtent(PartitionSuperPageExtentEntry<thread_safe>* extent) {
PA_DCHECK(0 < extent->number_of_consecutive_super_pages); PA_DCHECK(0 < extent->number_of_consecutive_super_pages);
uintptr_t extent_as_uintptr = reinterpret_cast<uintptr_t>(extent); uintptr_t extent_as_uintptr = reinterpret_cast<uintptr_t>(extent);
PA_DCHECK(IsManagedByNormalBuckets(extent_as_uintptr)); PA_DCHECK(IsManagedByNormalBuckets(extent_as_uintptr));
@ -78,13 +77,13 @@ ALWAYS_INLINE uintptr_t SuperPagesBeginFromExtent(
// CAUTION! |extent| must point to the extent of the first super page in the // CAUTION! |extent| must point to the extent of the first super page in the
// range of consecutive super pages. // range of consecutive super pages.
template <bool thread_safe> template <bool thread_safe>
ALWAYS_INLINE uintptr_t SuperPagesEndFromExtent( ALWAYS_INLINE uintptr_t
const PartitionSuperPageExtentEntry<thread_safe>* extent) { SuperPagesEndFromExtent(PartitionSuperPageExtentEntry<thread_safe>* extent) {
return SuperPagesBeginFromExtent(extent) + return SuperPagesBeginFromExtent(extent) +
(extent->number_of_consecutive_super_pages * kSuperPageSize); (extent->number_of_consecutive_super_pages * kSuperPageSize);
} }
using AllocationStateMap = using AllocationStateMap = ::base::internal::
StateBitmap<kSuperPageSize, kSuperPageAlignment, kAlignment>; StateBitmap<kSuperPageSize, kSuperPageAlignment, kAlignment>;
// Metadata of the slot span. // Metadata of the slot span.
@ -135,12 +134,6 @@ struct __attribute__((packed)) SlotSpanMetadata {
// PartitionPageSize() is 4 times the OS page size. // PartitionPageSize() is 4 times the OS page size.
static constexpr size_t kMaxSlotsPerSlotSpan = static constexpr size_t kMaxSlotsPerSlotSpan =
4 * (1 << 14) / kSmallestBucket; 4 * (1 << 14) / kSmallestBucket;
#elif BUILDFLAG(IS_LINUX) && defined(ARCH_CPU_ARM64)
// System page size can be 4, 16, or 64 kiB on Linux on arm64. 64 kiB is
// currently (kMaxSlotsPerSlotSpanBits == 13) not supported by the code,
// so we use the 16 kiB maximum (64 kiB will crash).
static constexpr size_t kMaxSlotsPerSlotSpan =
4 * (1 << 14) / kSmallestBucket;
#else #else
// A slot span can "span" multiple PartitionPages, but then its slot size is // A slot span can "span" multiple PartitionPages, but then its slot size is
// larger, so it doesn't have as many slots. // larger, so it doesn't have as many slots.
@ -417,27 +410,17 @@ CommittedStateBitmapSize() {
// caller's responsibility to ensure that the bitmaps even exist. // caller's responsibility to ensure that the bitmaps even exist.
ALWAYS_INLINE uintptr_t SuperPageStateBitmapAddr(uintptr_t super_page) { ALWAYS_INLINE uintptr_t SuperPageStateBitmapAddr(uintptr_t super_page) {
PA_DCHECK(!(super_page % kSuperPageAlignment)); PA_DCHECK(!(super_page % kSuperPageAlignment));
return super_page + PartitionPageSize() + return super_page + PartitionPageSize();
(IsManagedByNormalBuckets(super_page) ? ReservedTagBitmapSize() : 0);
} }
ALWAYS_INLINE AllocationStateMap* SuperPageStateBitmap(uintptr_t super_page) { ALWAYS_INLINE AllocationStateMap* SuperPageStateBitmap(uintptr_t super_page) {
return reinterpret_cast<AllocationStateMap*>( return reinterpret_cast<AllocationStateMap*>(
SuperPageStateBitmapAddr(super_page)); SuperPageStateBitmapAddr(super_page));
} }
// Returns the address of the tag bitmap of the `super_page`. Caller must ensure
// that bitmap exists.
ALWAYS_INLINE uintptr_t SuperPageTagBitmapAddr(uintptr_t super_page) {
PA_DCHECK(IsReservationStart(super_page));
// Skip over the guard pages / metadata.
return super_page + PartitionPageSize();
}
ALWAYS_INLINE uintptr_t SuperPagePayloadBegin(uintptr_t super_page, ALWAYS_INLINE uintptr_t SuperPagePayloadBegin(uintptr_t super_page,
bool with_quarantine) { bool with_quarantine) {
PA_DCHECK(!(super_page % kSuperPageAlignment)); PA_DCHECK(!(super_page % kSuperPageAlignment));
return super_page + PartitionPageSize() + return super_page + PartitionPageSize() +
(IsManagedByNormalBuckets(super_page) ? ReservedTagBitmapSize() : 0) +
(with_quarantine ? ReservedStateBitmapSize() : 0); (with_quarantine ? ReservedStateBitmapSize() : 0);
} }

View File

@ -220,13 +220,6 @@ class BASE_EXPORT PartitionRefCount {
return alive; return alive;
} }
#if defined(PA_REF_COUNT_STORE_REQUESTED_SIZE)
ALWAYS_INLINE void SetRequestedSize(size_t size) {
requested_size_ = static_cast<uint32_t>(size);
}
ALWAYS_INLINE uint32_t requested_size() const { return requested_size_; }
#endif // defined(PA_REF_COUNT_STORE_REQUESTED_SIZE)
private: private:
// The common parts shared by Release() and ReleaseFromUnprotectedPtr(). // The common parts shared by Release() and ReleaseFromUnprotectedPtr().
// Called after updating the ref counts, |count| is the new value of |count_| // Called after updating the ref counts, |count| is the new value of |count_|
@ -293,10 +286,6 @@ class BASE_EXPORT PartitionRefCount {
static constexpr uint32_t kCookieSalt = 0xc01dbeef; static constexpr uint32_t kCookieSalt = 0xc01dbeef;
volatile uint32_t brp_cookie_; volatile uint32_t brp_cookie_;
#endif #endif
#if defined(PA_REF_COUNT_STORE_REQUESTED_SIZE)
uint32_t requested_size_;
#endif
}; };
ALWAYS_INLINE PartitionRefCount::PartitionRefCount() ALWAYS_INLINE PartitionRefCount::PartitionRefCount()
@ -308,7 +297,7 @@ ALWAYS_INLINE PartitionRefCount::PartitionRefCount()
#if BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT) #if BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT)
static_assert(kAlignment % alignof(PartitionRefCount) == 0, static_assert(base::kAlignment % alignof(PartitionRefCount) == 0,
"kAlignment must be multiples of alignof(PartitionRefCount)."); "kAlignment must be multiples of alignof(PartitionRefCount).");
// Allocate extra space for the reference count to satisfy the alignment // Allocate extra space for the reference count to satisfy the alignment
@ -355,7 +344,7 @@ ALWAYS_INLINE PartitionRefCount* PartitionRefCountPointer(
// Allocate extra space for the reference count to satisfy the alignment // Allocate extra space for the reference count to satisfy the alignment
// requirement. // requirement.
static constexpr size_t kInSlotRefCountBufferSize = kAlignment; static constexpr size_t kInSlotRefCountBufferSize = base::kAlignment;
constexpr size_t kPartitionRefCountOffsetAdjustment = kInSlotRefCountBufferSize; constexpr size_t kPartitionRefCountOffsetAdjustment = kInSlotRefCountBufferSize;
// This is for adjustment of pointers right past the allocation, which may point // This is for adjustment of pointers right past the allocation, which may point

View File

@ -8,7 +8,6 @@
#include "base/allocator/buildflags.h" #include "base/allocator/buildflags.h"
#include "base/allocator/partition_allocator/address_pool_manager_bitmap.h" #include "base/allocator/partition_allocator/address_pool_manager_bitmap.h"
#include "base/allocator/partition_allocator/base/bits.h"
#include "base/allocator/partition_allocator/oom.h" #include "base/allocator/partition_allocator/oom.h"
#include "base/allocator/partition_allocator/page_allocator.h" #include "base/allocator/partition_allocator/page_allocator.h"
#include "base/allocator/partition_allocator/partition_address_space.h" #include "base/allocator/partition_allocator/partition_address_space.h"
@ -22,6 +21,7 @@
#include "base/allocator/partition_allocator/reservation_offset_table.h" #include "base/allocator/partition_allocator/reservation_offset_table.h"
#include "base/allocator/partition_allocator/starscan/pcscan.h" #include "base/allocator/partition_allocator/starscan/pcscan.h"
#include "base/allocator/partition_allocator/tagging.h" #include "base/allocator/partition_allocator/tagging.h"
#include "base/bits.h"
#include "build/build_config.h" #include "build/build_config.h"
#if BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_WIN)
@ -48,17 +48,18 @@ void RecordAllocOrFree(uintptr_t addr, size_t size) {
} // namespace partition_alloc::internal } // namespace partition_alloc::internal
#endif // BUILDFLAG(RECORD_ALLOC_INFO) #endif // BUILDFLAG(RECORD_ALLOC_INFO)
namespace partition_alloc { namespace base {
#if defined(PA_USE_PARTITION_ROOT_ENUMERATOR) #if defined(PA_USE_PARTITION_ROOT_ENUMERATOR)
namespace { namespace {
internal::Lock g_root_enumerator_lock; internal::PartitionLock g_root_enumerator_lock;
} }
template <bool thread_safe> template <bool thread_safe>
internal::Lock& PartitionRoot<thread_safe>::GetEnumeratorLock() { internal::PartitionLock& PartitionRoot<thread_safe>::GetEnumeratorLock() {
return g_root_enumerator_lock; return g_root_enumerator_lock;
} }
@ -96,7 +97,8 @@ class PartitionRootEnumerator {
} }
void Register(ThreadSafePartitionRoot* root) { void Register(ThreadSafePartitionRoot* root) {
internal::ScopedGuard guard(ThreadSafePartitionRoot::GetEnumeratorLock()); internal::PartitionAutoLock guard(
ThreadSafePartitionRoot::GetEnumeratorLock());
root->next_root = partition_roots_; root->next_root = partition_roots_;
root->prev_root = nullptr; root->prev_root = nullptr;
if (partition_roots_) if (partition_roots_)
@ -105,7 +107,8 @@ class PartitionRootEnumerator {
} }
void Unregister(ThreadSafePartitionRoot* root) { void Unregister(ThreadSafePartitionRoot* root) {
internal::ScopedGuard guard(ThreadSafePartitionRoot::GetEnumeratorLock()); internal::PartitionAutoLock guard(
ThreadSafePartitionRoot::GetEnumeratorLock());
ThreadSafePartitionRoot* prev = root->prev_root; ThreadSafePartitionRoot* prev = root->prev_root;
ThreadSafePartitionRoot* next = root->next_root; ThreadSafePartitionRoot* next = root->next_root;
if (prev) { if (prev) {
@ -170,7 +173,7 @@ void BeforeForkInParent() NO_THREAD_SAFETY_ANALYSIS {
LockRoot, false, LockRoot, false,
internal::PartitionRootEnumerator::EnumerateOrder::kNormal); internal::PartitionRootEnumerator::EnumerateOrder::kNormal);
ThreadCacheRegistry::GetLock().Acquire(); internal::ThreadCacheRegistry::GetLock().Acquire();
} }
template <typename T> template <typename T>
@ -190,7 +193,7 @@ void UnlockOrReinitRoot(PartitionRoot<internal::ThreadSafe>* root,
void ReleaseLocks(bool in_child) NO_THREAD_SAFETY_ANALYSIS { void ReleaseLocks(bool in_child) NO_THREAD_SAFETY_ANALYSIS {
// In reverse order, even though there are no lock ordering dependencies. // In reverse order, even though there are no lock ordering dependencies.
UnlockOrReinit(ThreadCacheRegistry::GetLock(), in_child); UnlockOrReinit(internal::ThreadCacheRegistry::GetLock(), in_child);
internal::PartitionRootEnumerator::Instance().Enumerate( internal::PartitionRootEnumerator::Instance().Enumerate(
UnlockOrReinitRoot, in_child, UnlockOrReinitRoot, in_child,
internal::PartitionRootEnumerator::EnumerateOrder::kReverse); internal::PartitionRootEnumerator::EnumerateOrder::kReverse);
@ -214,7 +217,8 @@ void AfterForkInChild() {
// If we don't reclaim this memory, it is lost forever. Note that this is only // If we don't reclaim this memory, it is lost forever. Note that this is only
// really an issue if we fork() a multi-threaded process without calling // really an issue if we fork() a multi-threaded process without calling
// exec() right away, which is discouraged. // exec() right away, which is discouraged.
ThreadCacheRegistry::Instance().ForcePurgeAllThreadAfterForkUnsafe(); internal::ThreadCacheRegistry::Instance()
.ForcePurgeAllThreadAfterForkUnsafe();
} }
#endif // defined(PA_HAS_ATFORK_HANDLER) #endif // defined(PA_HAS_ATFORK_HANDLER)
@ -305,17 +309,15 @@ static size_t PartitionPurgeSlotSpan(
constexpr size_t kMaxSlotCount = constexpr size_t kMaxSlotCount =
(PartitionPageSize() * kMaxPartitionPagesPerRegularSlotSpan) / (PartitionPageSize() * kMaxPartitionPagesPerRegularSlotSpan) /
SystemPageSize(); SystemPageSize();
#elif BUILDFLAG(IS_APPLE) || (BUILDFLAG(IS_LINUX) && defined(ARCH_CPU_ARM64)) #elif BUILDFLAG(IS_APPLE)
// It's better for slot_usage to be stack-allocated and fixed-size, which // It's better for slot_usage to be stack-allocated and fixed-size, which
// demands that its size be constexpr. On IS_APPLE and Linux on arm64, // demands that its size be constexpr. On OS_APPLE, PartitionPageSize() is
// PartitionPageSize() is always SystemPageSize() << 2, so regardless of // always SystemPageSize() << 2, so regardless of what the run time page size
// what the run time page size is, kMaxSlotCount can always be simplified // is, kMaxSlotCount can always be simplified to this expression.
// to this expression. constexpr size_t kMaxSlotCount = 4 * kMaxPartitionPagesPerRegularSlotSpan;
constexpr size_t kMaxSlotCount = PA_CHECK(kMaxSlotCount ==
4 * internal::kMaxPartitionPagesPerRegularSlotSpan; (PartitionPageSize() * kMaxPartitionPagesPerRegularSlotSpan) /
PA_CHECK(kMaxSlotCount == (PartitionPageSize() * SystemPageSize());
internal::kMaxPartitionPagesPerRegularSlotSpan) /
SystemPageSize());
#endif #endif
PA_DCHECK(bucket_num_slots <= kMaxSlotCount); PA_DCHECK(bucket_num_slots <= kMaxSlotCount);
PA_DCHECK(slot_span->num_unprovisioned_slots < bucket_num_slots); PA_DCHECK(slot_span->num_unprovisioned_slots < bucket_num_slots);
@ -571,7 +573,7 @@ template <bool thread_safe>
// Check whether this OOM is due to a lot of super pages that are allocated // Check whether this OOM is due to a lot of super pages that are allocated
// but not committed, probably due to http://crbug.com/421387. // but not committed, probably due to http://crbug.com/421387.
if (uncommitted_size > internal::kReasonableSizeOfUnusedPages) { if (uncommitted_size > kReasonableSizeOfUnusedPages) {
internal::PartitionOutOfMemoryWithLotsOfUncommitedPages(size); internal::PartitionOutOfMemoryWithLotsOfUncommitedPages(size);
} }
@ -623,39 +625,14 @@ void PartitionRoot<thread_safe>::DecommitEmptySlotSpans() {
PA_DCHECK(empty_slot_spans_dirty_bytes == 0); PA_DCHECK(empty_slot_spans_dirty_bytes == 0);
} }
template <bool thread_safe>
void PartitionRoot<thread_safe>::DestructForTesting() {
// We need to destruct the thread cache before we unreserve any of the super
// pages below, which we currently are not doing. So, we should only call
// this function on PartitionRoots without a thread cache.
PA_CHECK(!with_thread_cache);
auto pool_handle = ChoosePool();
auto* curr = first_extent;
while (curr != nullptr) {
auto* next = curr->next;
internal::AddressPoolManager::GetInstance()->UnreserveAndDecommit(
pool_handle, reinterpret_cast<uintptr_t>(curr),
internal::kSuperPageSize * curr->number_of_consecutive_super_pages);
curr = next;
}
}
template <bool thread_safe> template <bool thread_safe>
void PartitionRoot<thread_safe>::Init(PartitionOptions opts) { void PartitionRoot<thread_safe>::Init(PartitionOptions opts) {
{ {
#if BUILDFLAG(IS_APPLE) #if BUILDFLAG(IS_APPLE)
// Needed to statically bound page size, which is a runtime constant on // Needed to statically bound page size, which is a runtime constant on
// apple OSes. // apple OSes.
PA_CHECK((internal::SystemPageSize() == (size_t{1} << 12)) || PA_CHECK((SystemPageSize() == (size_t{1} << 12)) ||
(internal::SystemPageSize() == (size_t{1} << 14))); (SystemPageSize() == (size_t{1} << 14)));
#elif BUILDFLAG(IS_LINUX) && defined(ARCH_CPU_ARM64)
// Check runtime pagesize. Though the code is currently the same, it is
// not merged with the IS_APPLE case above as a 1 << 16 case needs to be
// added here in the future, to allow 64 kiB pagesize. That is only
// supported on Linux on arm64, not on IS_APPLE, but not yet present here
// as the rest of the partition allocator does not currently support it.
PA_CHECK((internal::SystemPageSize() == (size_t{1} << 12)) ||
(internal::SystemPageSize() == (size_t{1} << 14)));
#endif #endif
::partition_alloc::internal::ScopedGuard guard{lock_}; ::partition_alloc::internal::ScopedGuard guard{lock_};
@ -739,18 +716,17 @@ void PartitionRoot<thread_safe>::Init(PartitionOptions opts) {
// Set up the actual usable buckets first. // Set up the actual usable buckets first.
constexpr internal::BucketIndexLookup lookup{}; constexpr internal::BucketIndexLookup lookup{};
size_t bucket_index = 0; size_t bucket_index = 0;
while (lookup.bucket_sizes()[bucket_index] != while (lookup.bucket_sizes()[bucket_index] != kInvalidBucketSize) {
internal::kInvalidBucketSize) {
buckets[bucket_index].Init(lookup.bucket_sizes()[bucket_index]); buckets[bucket_index].Init(lookup.bucket_sizes()[bucket_index]);
bucket_index++; bucket_index++;
} }
PA_DCHECK(bucket_index < internal::kNumBuckets); PA_DCHECK(bucket_index < kNumBuckets);
// Remaining buckets are not usable, and not real. // Remaining buckets are not usable, and not real.
for (size_t index = bucket_index; index < internal::kNumBuckets; index++) { for (size_t index = bucket_index; index < kNumBuckets; index++) {
// Cannot init with size 0 since it computes 1 / size, but make sure the // Cannot init with size 0 since it computes 1 / size, but make sure the
// bucket is invalid. // bucket is invalid.
buckets[index].Init(internal::kInvalidBucketSize); buckets[index].Init(kInvalidBucketSize);
buckets[index].active_slot_spans_head = nullptr; buckets[index].active_slot_spans_head = nullptr;
PA_DCHECK(!buckets[index].is_valid()); PA_DCHECK(!buckets[index].is_valid());
} }
@ -759,12 +735,12 @@ void PartitionRoot<thread_safe>::Init(PartitionOptions opts) {
// TLS in ThreadCache not supported on other OSes. // TLS in ThreadCache not supported on other OSes.
with_thread_cache = false; with_thread_cache = false;
#else #else
ThreadCache::EnsureThreadSpecificDataInitialized(); internal::ThreadCache::EnsureThreadSpecificDataInitialized();
with_thread_cache = with_thread_cache =
(opts.thread_cache == PartitionOptions::ThreadCache::kEnabled); (opts.thread_cache == PartitionOptions::ThreadCache::kEnabled);
if (with_thread_cache) if (with_thread_cache)
ThreadCache::Init(this); internal::ThreadCache::Init(this);
#endif // !defined(PA_THREAD_CACHE_SUPPORTED) #endif // !defined(PA_THREAD_CACHE_SUPPORTED)
#if defined(PA_USE_PARTITION_ROOT_ENUMERATOR) #if defined(PA_USE_PARTITION_ROOT_ENUMERATOR)
@ -810,7 +786,7 @@ void PartitionRoot<thread_safe>::EnableThreadCacheIfSupported() {
int before = int before =
thread_caches_being_constructed_.fetch_add(1, std::memory_order_acquire); thread_caches_being_constructed_.fetch_add(1, std::memory_order_acquire);
PA_CHECK(before == 0); PA_CHECK(before == 0);
ThreadCache::Init(this); internal::ThreadCache::Init(this);
thread_caches_being_constructed_.fetch_sub(1, std::memory_order_release); thread_caches_being_constructed_.fetch_sub(1, std::memory_order_release);
with_thread_cache = true; with_thread_cache = true;
#endif // defined(PA_THREAD_CACHE_SUPPORTED) #endif // defined(PA_THREAD_CACHE_SUPPORTED)
@ -841,15 +817,15 @@ bool PartitionRoot<thread_safe>::TryReallocInPlaceForDirectMap(
// Make this check before comparing slot sizes, as even with equal or similar // Make this check before comparing slot sizes, as even with equal or similar
// slot sizes we can save a lot if the original allocation was heavily padded // slot sizes we can save a lot if the original allocation was heavily padded
// for alignment. // for alignment.
if ((new_reservation_size >> internal::SystemPageShift()) * 5 < if ((new_reservation_size >> SystemPageShift()) * 5 <
(current_reservation_size >> internal::SystemPageShift()) * 4) (current_reservation_size >> SystemPageShift()) * 4)
return false; return false;
// Note that the new size isn't a bucketed size; this function is called // Note that the new size isn't a bucketed size; this function is called
// whenever we're reallocating a direct mapped allocation, so calculate it // whenever we're reallocating a direct mapped allocation, so calculate it
// the way PartitionDirectMap() would. // the way PartitionDirectMap() would.
size_t new_slot_size = GetDirectMapSlotSize(raw_size); size_t new_slot_size = GetDirectMapSlotSize(raw_size);
if (new_slot_size < internal::kMinDirectMappedDownsize) if (new_slot_size < kMinDirectMappedDownsize)
return false; return false;
// Past this point, we decided we'll attempt to reallocate without relocating, // Past this point, we decided we'll attempt to reallocate without relocating,
@ -865,12 +841,11 @@ bool PartitionRoot<thread_safe>::TryReallocInPlaceForDirectMap(
current_reservation_size - extent->padding_for_alignment - current_reservation_size - extent->padding_for_alignment -
PartitionRoot<thread_safe>::GetDirectMapMetadataAndGuardPagesSize(); PartitionRoot<thread_safe>::GetDirectMapMetadataAndGuardPagesSize();
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
uintptr_t reservation_start = slot_start & internal::kSuperPageBaseMask; uintptr_t reservation_start = slot_start & kSuperPageBaseMask;
PA_DCHECK(internal::IsReservationStart(reservation_start)); PA_DCHECK(internal::IsReservationStart(reservation_start));
PA_DCHECK(slot_start + available_reservation_size == PA_DCHECK(slot_start + available_reservation_size ==
reservation_start + current_reservation_size - reservation_start + current_reservation_size -
GetDirectMapMetadataAndGuardPagesSize() + GetDirectMapMetadataAndGuardPagesSize() + PartitionPageSize());
internal::PartitionPageSize());
#endif #endif
if (new_slot_size == current_slot_size) { if (new_slot_size == current_slot_size) {
@ -896,7 +871,7 @@ bool PartitionRoot<thread_safe>::TryReallocInPlaceForDirectMap(
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
memset(reinterpret_cast<void*>(slot_start + current_slot_size), memset(reinterpret_cast<void*>(slot_start + current_slot_size),
internal::kUninitializedByte, recommit_slot_size_growth); kUninitializedByte, recommit_slot_size_growth);
#endif #endif
} else { } else {
// We can't perform the realloc in-place. // We can't perform the realloc in-place.
@ -986,10 +961,9 @@ void* PartitionRoot<thread_safe>::ReallocWithFlags(int flags,
bool no_hooks = flags & AllocFlags::kNoHooks; bool no_hooks = flags & AllocFlags::kNoHooks;
if (UNLIKELY(!ptr)) { if (UNLIKELY(!ptr)) {
return no_hooks return no_hooks
? AllocWithFlagsNoHooks(flags, new_size, ? AllocWithFlagsNoHooks(flags, new_size, PartitionPageSize())
internal::PartitionPageSize()) : AllocWithFlagsInternal(flags, new_size, PartitionPageSize(),
: AllocWithFlagsInternal( type_name);
flags, new_size, internal::PartitionPageSize(), type_name);
} }
if (UNLIKELY(!new_size)) { if (UNLIKELY(!new_size)) {
@ -997,7 +971,7 @@ void* PartitionRoot<thread_safe>::ReallocWithFlags(int flags,
return nullptr; return nullptr;
} }
if (new_size > internal::MaxDirectMapped()) { if (new_size > MaxDirectMapped()) {
if (flags & AllocFlags::kReturnNull) if (flags & AllocFlags::kReturnNull)
return nullptr; return nullptr;
internal::PartitionExcessiveAllocationSize(new_size); internal::PartitionExcessiveAllocationSize(new_size);
@ -1045,11 +1019,10 @@ void* PartitionRoot<thread_safe>::ReallocWithFlags(int flags,
} }
// This realloc cannot be resized in-place. Sadness. // This realloc cannot be resized in-place. Sadness.
void* ret = void* ret = no_hooks
no_hooks ? AllocWithFlagsNoHooks(flags, new_size, ? AllocWithFlagsNoHooks(flags, new_size, PartitionPageSize())
internal::PartitionPageSize()) : AllocWithFlagsInternal(flags, new_size, PartitionPageSize(),
: AllocWithFlagsInternal( type_name);
flags, new_size, internal::PartitionPageSize(), type_name);
if (!ret) { if (!ret) {
if (flags & AllocFlags::kReturnNull) if (flags & AllocFlags::kReturnNull)
return nullptr; return nullptr;
@ -1077,10 +1050,10 @@ void PartitionRoot<thread_safe>::PurgeMemory(int flags) {
DecommitEmptySlotSpans(); DecommitEmptySlotSpans();
if (flags & PurgeFlags::kDiscardUnusedSystemPages) { if (flags & PurgeFlags::kDiscardUnusedSystemPages) {
for (Bucket& bucket : buckets) { for (Bucket& bucket : buckets) {
if (bucket.slot_size == internal::kInvalidBucketSize) if (bucket.slot_size == kInvalidBucketSize)
continue; continue;
if (bucket.slot_size >= internal::SystemPageSize()) if (bucket.slot_size >= SystemPageSize())
internal::PartitionPurgeBucket(&bucket); internal::PartitionPurgeBucket(&bucket);
else else
bucket.SortSlotSpanFreelists(); bucket.SortSlotSpanFreelists();
@ -1109,7 +1082,7 @@ void PartitionRoot<thread_safe>::ShrinkEmptySlotSpansRing(size_t limit) {
// are unused, if global_empty_slot_span_ring_size is smaller than // are unused, if global_empty_slot_span_ring_size is smaller than
// kMaxFreeableSpans. It's simpler, and does not cost anything, since all // kMaxFreeableSpans. It's simpler, and does not cost anything, since all
// the pointers are going to be nullptr. // the pointers are going to be nullptr.
if (index == internal::kMaxFreeableSpans) if (index == kMaxFreeableSpans)
index = 0; index = 0;
// Went around the whole ring, since this is locked, // Went around the whole ring, since this is locked,
@ -1136,7 +1109,7 @@ void PartitionRoot<thread_safe>::DumpStats(const char* partition_name,
direct_map_lengths = direct_map_lengths =
std::unique_ptr<uint32_t[]>(new uint32_t[kMaxReportableDirectMaps]); std::unique_ptr<uint32_t[]>(new uint32_t[kMaxReportableDirectMaps]);
} }
PartitionBucketMemoryStats bucket_stats[internal::kNumBuckets]; PartitionBucketMemoryStats bucket_stats[kNumBuckets];
size_t num_direct_mapped_allocations = 0; size_t num_direct_mapped_allocations = 0;
PartitionMemoryStats stats = {0}; PartitionMemoryStats stats = {0};
@ -1167,7 +1140,7 @@ void PartitionRoot<thread_safe>::DumpStats(const char* partition_name,
#endif #endif
size_t direct_mapped_allocations_total_size = 0; size_t direct_mapped_allocations_total_size = 0;
for (size_t i = 0; i < internal::kNumBuckets; ++i) { for (size_t i = 0; i < kNumBuckets; ++i) {
const Bucket* bucket = &bucket_at(i); const Bucket* bucket = &bucket_at(i);
// Don't report the pseudo buckets that the generic allocator sets up in // Don't report the pseudo buckets that the generic allocator sets up in
// order to preserve a fast size->bucket map (see // order to preserve a fast size->bucket map (see
@ -1201,10 +1174,10 @@ void PartitionRoot<thread_safe>::DumpStats(const char* partition_name,
stats.has_thread_cache = with_thread_cache; stats.has_thread_cache = with_thread_cache;
if (stats.has_thread_cache) { if (stats.has_thread_cache) {
ThreadCacheRegistry::Instance().DumpStats( internal::ThreadCacheRegistry::Instance().DumpStats(
true, &stats.current_thread_cache_stats); true, &stats.current_thread_cache_stats);
ThreadCacheRegistry::Instance().DumpStats(false, internal::ThreadCacheRegistry::Instance().DumpStats(
&stats.all_thread_caches_stats); false, &stats.all_thread_caches_stats);
} }
} }
@ -1236,7 +1209,7 @@ template <bool thread_safe>
void PartitionRoot<thread_safe>::DeleteForTesting( void PartitionRoot<thread_safe>::DeleteForTesting(
PartitionRoot* partition_root) { PartitionRoot* partition_root) {
if (partition_root->with_thread_cache) { if (partition_root->with_thread_cache) {
ThreadCache::SwapForTesting(nullptr); internal::ThreadCache::SwapForTesting(nullptr);
partition_root->with_thread_cache = false; partition_root->with_thread_cache = false;
} }
@ -1254,10 +1227,10 @@ template <>
uintptr_t PartitionRoot<internal::ThreadSafe>::MaybeInitThreadCacheAndAlloc( uintptr_t PartitionRoot<internal::ThreadSafe>::MaybeInitThreadCacheAndAlloc(
uint16_t bucket_index, uint16_t bucket_index,
size_t* slot_size) { size_t* slot_size) {
auto* tcache = ThreadCache::Get(); auto* tcache = internal::ThreadCache::Get();
// See comment in `EnableThreadCacheIfSupport()` for why this is an acquire // See comment in `EnableThreadCacheIfSupport()` for why this is an acquire
// load. // load.
if (ThreadCache::IsTombstone(tcache) || if (internal::ThreadCache::IsTombstone(tcache) ||
thread_caches_being_constructed_.load(std::memory_order_acquire)) { thread_caches_being_constructed_.load(std::memory_order_acquire)) {
// Two cases: // Two cases:
// 1. Thread is being terminated, don't try to use the thread cache, and // 1. Thread is being terminated, don't try to use the thread cache, and
@ -1286,7 +1259,7 @@ uintptr_t PartitionRoot<internal::ThreadSafe>::MaybeInitThreadCacheAndAlloc(
int before = int before =
thread_caches_being_constructed_.fetch_add(1, std::memory_order_relaxed); thread_caches_being_constructed_.fetch_add(1, std::memory_order_relaxed);
PA_CHECK(before < std::numeric_limits<int>::max()); PA_CHECK(before < std::numeric_limits<int>::max());
tcache = ThreadCache::Create(this); tcache = internal::ThreadCache::Create(this);
thread_caches_being_constructed_.fetch_sub(1, std::memory_order_relaxed); thread_caches_being_constructed_.fetch_sub(1, std::memory_order_relaxed);
// Cache is created empty, but at least this will trigger batch fill, which // Cache is created empty, but at least this will trigger batch fill, which
@ -1299,11 +1272,11 @@ template struct BASE_EXPORT PartitionRoot<internal::ThreadSafe>;
static_assert(offsetof(PartitionRoot<internal::ThreadSafe>, sentinel_bucket) == static_assert(offsetof(PartitionRoot<internal::ThreadSafe>, sentinel_bucket) ==
offsetof(PartitionRoot<internal::ThreadSafe>, buckets) + offsetof(PartitionRoot<internal::ThreadSafe>, buckets) +
internal::kNumBuckets * kNumBuckets *
sizeof(PartitionRoot<internal::ThreadSafe>::Bucket), sizeof(PartitionRoot<internal::ThreadSafe>::Bucket),
"sentinel_bucket must be just after the regular buckets."); "sentinel_bucket must be just after the regular buckets.");
static_assert( static_assert(
offsetof(PartitionRoot<internal::ThreadSafe>, lock_) >= 64, offsetof(PartitionRoot<internal::ThreadSafe>, lock_) >= 64,
"The lock should not be on the same cacheline as the read-mostly flags"); "The lock should not be on the same cacheline as the read-mostly flags");
} // namespace partition_alloc } // namespace base

View File

@ -38,7 +38,6 @@
#include "base/allocator/buildflags.h" #include "base/allocator/buildflags.h"
#include "base/allocator/partition_allocator/address_pool_manager_types.h" #include "base/allocator/partition_allocator/address_pool_manager_types.h"
#include "base/allocator/partition_allocator/allocation_guard.h" #include "base/allocator/partition_allocator/allocation_guard.h"
#include "base/allocator/partition_allocator/base/bits.h"
#include "base/allocator/partition_allocator/page_allocator.h" #include "base/allocator/partition_allocator/page_allocator.h"
#include "base/allocator/partition_allocator/page_allocator_constants.h" #include "base/allocator/partition_allocator/page_allocator_constants.h"
#include "base/allocator/partition_allocator/partition_address_space.h" #include "base/allocator/partition_allocator/partition_address_space.h"
@ -57,13 +56,12 @@
#include "base/allocator/partition_allocator/partition_oom.h" #include "base/allocator/partition_allocator/partition_oom.h"
#include "base/allocator/partition_allocator/partition_page.h" #include "base/allocator/partition_allocator/partition_page.h"
#include "base/allocator/partition_allocator/partition_ref_count.h" #include "base/allocator/partition_allocator/partition_ref_count.h"
#include "base/allocator/partition_allocator/partition_tag.h"
#include "base/allocator/partition_allocator/reservation_offset_table.h" #include "base/allocator/partition_allocator/reservation_offset_table.h"
#include "base/allocator/partition_allocator/starscan/pcscan.h" #include "base/allocator/partition_allocator/starscan/pcscan.h"
#include "base/allocator/partition_allocator/starscan/state_bitmap.h" #include "base/allocator/partition_allocator/starscan/state_bitmap.h"
#include "base/allocator/partition_allocator/tagging.h" #include "base/allocator/partition_allocator/tagging.h"
#include "base/allocator/partition_allocator/thread_cache.h" #include "base/allocator/partition_allocator/thread_cache.h"
#include "base/base_export.h" #include "base/bits.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "build/build_config.h" #include "build/build_config.h"
@ -71,12 +69,12 @@
// We use this to make MEMORY_TOOL_REPLACES_ALLOCATOR behave the same for max // We use this to make MEMORY_TOOL_REPLACES_ALLOCATOR behave the same for max
// size as other alloc code. // size as other alloc code.
#define CHECK_MAX_SIZE_OR_RETURN_NULLPTR(size, flags) \ #define CHECK_MAX_SIZE_OR_RETURN_NULLPTR(size, flags) \
if (size > partition_alloc::internal::MaxDirectMapped()) { \ if (size > MaxDirectMapped()) { \
if (flags & AllocFlags::kReturnNull) { \ if (flags & AllocFlags::kReturnNull) { \
return nullptr; \ return nullptr; \
} \ } \
PA_CHECK(false); \ PA_CHECK(false); \
} }
namespace partition_alloc::internal { namespace partition_alloc::internal {
@ -98,7 +96,7 @@ void RecordAllocOrFree(uintptr_t addr, size_t size);
#endif // BUILDFLAG(RECORD_ALLOC_INFO) #endif // BUILDFLAG(RECORD_ALLOC_INFO)
} // namespace partition_alloc::internal } // namespace partition_alloc::internal
namespace partition_alloc { namespace base {
namespace internal { namespace internal {
// Avoid including partition_address_space.h from this .h file, by moving the // Avoid including partition_address_space.h from this .h file, by moving the
@ -258,7 +256,7 @@ struct ALIGNAS(64) BASE_EXPORT PartitionRoot {
// The flags above are accessed for all (de)allocations, and are mostly // The flags above are accessed for all (de)allocations, and are mostly
// read-only. They should not share a cacheline with the data below, which // read-only. They should not share a cacheline with the data below, which
// is only touched when the lock is taken. // is only touched when the lock is taken.
uint8_t one_cacheline[internal::kPartitionCachelineSize]; uint8_t one_cacheline[kPartitionCachelineSize];
}; };
// Not used on the fastest path (thread cache allocations), but on the fast // Not used on the fastest path (thread cache allocations), but on the fast
@ -266,7 +264,7 @@ struct ALIGNAS(64) BASE_EXPORT PartitionRoot {
static_assert(thread_safe, "Only the thread-safe root is supported."); static_assert(thread_safe, "Only the thread-safe root is supported.");
::partition_alloc::internal::Lock lock_; ::partition_alloc::internal::Lock lock_;
Bucket buckets[internal::kNumBuckets] = {}; Bucket buckets[kNumBuckets] = {};
Bucket sentinel_bucket{}; Bucket sentinel_bucket{};
// All fields below this comment are not accessed on the fast path. // All fields below this comment are not accessed on the fast path.
@ -323,11 +321,11 @@ struct ALIGNAS(64) BASE_EXPORT PartitionRoot {
SuperPageExtentEntry* current_extent = nullptr; SuperPageExtentEntry* current_extent = nullptr;
SuperPageExtentEntry* first_extent = nullptr; SuperPageExtentEntry* first_extent = nullptr;
DirectMapExtent* direct_map_list GUARDED_BY(lock_) = nullptr; DirectMapExtent* direct_map_list GUARDED_BY(lock_) = nullptr;
SlotSpan* global_empty_slot_span_ring[internal::kMaxFreeableSpans] GUARDED_BY( SlotSpan* global_empty_slot_span_ring[kMaxFreeableSpans] GUARDED_BY(
lock_) = {}; lock_) = {};
int16_t global_empty_slot_span_ring_index GUARDED_BY(lock_) = 0; int16_t global_empty_slot_span_ring_index GUARDED_BY(lock_) = 0;
int16_t global_empty_slot_span_ring_size GUARDED_BY(lock_) = int16_t global_empty_slot_span_ring_size GUARDED_BY(lock_) =
internal::kDefaultEmptySlotSpanRingSize; kDefaultEmptySlotSpanRingSize;
// Integrity check = ~reinterpret_cast<uintptr_t>(this). // Integrity check = ~reinterpret_cast<uintptr_t>(this).
uintptr_t inverted_self = 0; uintptr_t inverted_self = 0;
@ -335,24 +333,12 @@ struct ALIGNAS(64) BASE_EXPORT PartitionRoot {
bool quarantine_always_for_testing = false; bool quarantine_always_for_testing = false;
#if defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
partition_alloc::PartitionTag current_partition_tag = 0;
// Points to the end of the committed tag bitmap region.
uintptr_t next_tag_bitmap_page = 0;
#endif // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
PartitionRoot() PartitionRoot()
: quarantine_mode(QuarantineMode::kAlwaysDisabled), : quarantine_mode(QuarantineMode::kAlwaysDisabled),
scan_mode(ScanMode::kDisabled) {} scan_mode(ScanMode::kDisabled) {}
explicit PartitionRoot(PartitionOptions opts) { Init(opts); } explicit PartitionRoot(PartitionOptions opts) { Init(opts); }
~PartitionRoot(); ~PartitionRoot();
// This will unreserve any space in the GigaCage that the PartitionRoot is
// using. This is needed because many tests create and destroy many
// PartitionRoots over the lifetime of a process, which can exhaust the
// GigaCage and cause tests to fail.
void DestructForTesting();
// Public API // Public API
// //
// Allocates out of the given bucket. Properly, this function should probably // Allocates out of the given bucket. Properly, this function should probably
@ -497,7 +483,7 @@ struct ALIGNAS(64) BASE_EXPORT PartitionRoot {
// memory usage. // memory usage.
void EnableLargeEmptySlotSpanRing() { void EnableLargeEmptySlotSpanRing() {
::partition_alloc::internal::ScopedGuard locker{lock_}; ::partition_alloc::internal::ScopedGuard locker{lock_};
global_empty_slot_span_ring_size = internal::kMaxFreeableSpans; global_empty_slot_span_ring_size = kMaxFreeableSpans;
} }
void DumpStats(const char* partition_name, void DumpStats(const char* partition_name,
@ -541,8 +527,8 @@ struct ALIGNAS(64) BASE_EXPORT PartitionRoot {
with_denser_bucket_distribution = false; with_denser_bucket_distribution = false;
} }
ThreadCache* thread_cache_for_testing() const { internal::ThreadCache* thread_cache_for_testing() const {
return with_thread_cache ? ThreadCache::Get() : nullptr; return with_thread_cache ? internal::ThreadCache::Get() : nullptr;
} }
size_t get_total_size_of_committed_pages() const { size_t get_total_size_of_committed_pages() const {
return total_size_of_committed_pages.load(std::memory_order_relaxed); return total_size_of_committed_pages.load(std::memory_order_relaxed);
@ -591,7 +577,7 @@ struct ALIGNAS(64) BASE_EXPORT PartitionRoot {
// If quarantine is enabled and the tag overflows, move the containing slot // If quarantine is enabled and the tag overflows, move the containing slot
// to quarantine, to prevent the attacker from exploiting a pointer that has // to quarantine, to prevent the attacker from exploiting a pointer that has
// an old tag. // an old tag.
return internal::HasOverflowTag(object); return HasOverflowTag(object);
#else #else
return true; return true;
#endif #endif
@ -617,7 +603,7 @@ struct ALIGNAS(64) BASE_EXPORT PartitionRoot {
// to match granularity of the BRP pool bitmap. For cosistency, we'll use // to match granularity of the BRP pool bitmap. For cosistency, we'll use
// a partition page everywhere, which is cheap as it's uncommitted address // a partition page everywhere, which is cheap as it's uncommitted address
// space anyway. // space anyway.
return 2 * internal::PartitionPageSize(); return 2 * PartitionPageSize();
} }
static PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t static PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t
@ -625,9 +611,8 @@ struct ALIGNAS(64) BASE_EXPORT PartitionRoot {
// Caller must check that the size is not above the MaxDirectMapped() // Caller must check that the size is not above the MaxDirectMapped()
// limit before calling. This also guards against integer overflow in the // limit before calling. This also guards against integer overflow in the
// calculation here. // calculation here.
PA_DCHECK(raw_size <= internal::MaxDirectMapped()); PA_DCHECK(raw_size <= MaxDirectMapped());
return partition_alloc::internal::base::bits::AlignUp( return bits::AlignUp(raw_size, SystemPageSize());
raw_size, internal::SystemPageSize());
} }
static ALWAYS_INLINE size_t static ALWAYS_INLINE size_t
@ -635,10 +620,10 @@ struct ALIGNAS(64) BASE_EXPORT PartitionRoot {
// Caller must check that the size is not above the MaxDirectMapped() // Caller must check that the size is not above the MaxDirectMapped()
// limit before calling. This also guards against integer overflow in the // limit before calling. This also guards against integer overflow in the
// calculation here. // calculation here.
PA_DCHECK(padded_raw_size <= internal::MaxDirectMapped()); PA_DCHECK(padded_raw_size <= MaxDirectMapped());
return partition_alloc::internal::base::bits::AlignUp( return bits::AlignUp(
padded_raw_size + GetDirectMapMetadataAndGuardPagesSize(), padded_raw_size + GetDirectMapMetadataAndGuardPagesSize(),
internal::DirectMapAllocationGranularity()); DirectMapAllocationGranularity());
} }
ALWAYS_INLINE size_t AdjustSize0IfNeeded(size_t size) const { ALWAYS_INLINE size_t AdjustSize0IfNeeded(size_t size) const {
@ -731,17 +716,6 @@ struct ALIGNAS(64) BASE_EXPORT PartitionRoot {
max_empty_slot_spans_dirty_bytes_shift = 0; max_empty_slot_spans_dirty_bytes_shift = 0;
} }
#if defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
ALWAYS_INLINE partition_alloc::PartitionTag GetNewPartitionTag() {
// TODO(crbug.com/1298696): performance is not an issue. We can use
// random tags in lieu of sequential ones.
auto tag = ++current_partition_tag;
tag += !tag; // Avoid 0.
current_partition_tag = tag;
return tag;
}
#endif // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
private: private:
// |buckets| has `kNumBuckets` elements, but we sometimes access it at index // |buckets| has `kNumBuckets` elements, but we sometimes access it at index
// `kNumBuckets`, which is occupied by the sentinel bucket. The correct layout // `kNumBuckets`, which is occupied by the sentinel bucket. The correct layout
@ -753,7 +727,7 @@ struct ALIGNAS(64) BASE_EXPORT PartitionRoot {
// this. // this.
ALWAYS_INLINE const Bucket& NO_SANITIZE("undefined") ALWAYS_INLINE const Bucket& NO_SANITIZE("undefined")
bucket_at(size_t i) const { bucket_at(size_t i) const {
PA_DCHECK(i <= internal::kNumBuckets); PA_DCHECK(i <= kNumBuckets);
return buckets[i]; return buckets[i];
} }
@ -813,7 +787,7 @@ struct ALIGNAS(64) BASE_EXPORT PartitionRoot {
size_t* slot_size); size_t* slot_size);
#if defined(PA_USE_PARTITION_ROOT_ENUMERATOR) #if defined(PA_USE_PARTITION_ROOT_ENUMERATOR)
static internal::Lock& GetEnumeratorLock(); static internal::PartitionLock& GetEnumeratorLock();
PartitionRoot* GUARDED_BY(GetEnumeratorLock()) next_root = nullptr; PartitionRoot* GUARDED_BY(GetEnumeratorLock()) next_root = nullptr;
PartitionRoot* GUARDED_BY(GetEnumeratorLock()) prev_root = nullptr; PartitionRoot* GUARDED_BY(GetEnumeratorLock()) prev_root = nullptr;
@ -821,7 +795,7 @@ struct ALIGNAS(64) BASE_EXPORT PartitionRoot {
friend class internal::PartitionRootEnumerator; friend class internal::PartitionRootEnumerator;
#endif // defined(PA_USE_PARTITION_ROOT_ENUMERATOR) #endif // defined(PA_USE_PARTITION_ROOT_ENUMERATOR)
friend class ThreadCache; friend class internal::ThreadCache;
}; };
namespace internal { namespace internal {
@ -1005,9 +979,8 @@ PartitionRoot<thread_safe>::AllocFromBucket(Bucket* bucket,
size_t slot_span_alignment, size_t slot_span_alignment,
size_t* usable_size, size_t* usable_size,
bool* is_already_zeroed) { bool* is_already_zeroed) {
PA_DCHECK( PA_DCHECK((slot_span_alignment >= PartitionPageSize()) &&
(slot_span_alignment >= internal::PartitionPageSize()) && bits::IsPowerOfTwo(slot_span_alignment));
partition_alloc::internal::base::bits::IsPowerOfTwo(slot_span_alignment));
SlotSpan* slot_span = bucket->active_slot_spans_head; SlotSpan* slot_span = bucket->active_slot_spans_head;
// There always must be a slot span on the active list (could be a sentinel). // There always must be a slot span on the active list (could be a sentinel).
PA_DCHECK(slot_span); PA_DCHECK(slot_span);
@ -1021,8 +994,7 @@ PartitionRoot<thread_safe>::AllocFromBucket(Bucket* bucket,
// first active slot span. However, fall back to the slow path if a // first active slot span. However, fall back to the slow path if a
// higher-order alignment is requested, because an inner slot of an existing // higher-order alignment is requested, because an inner slot of an existing
// slot span is unlikely to satisfy it. // slot span is unlikely to satisfy it.
if (LIKELY(slot_span_alignment <= internal::PartitionPageSize() && if (LIKELY(slot_span_alignment <= PartitionPageSize() && slot_start)) {
slot_start)) {
*is_already_zeroed = false; *is_already_zeroed = false;
// This is a fast path, so avoid calling GetUsableSize() on Release builds // This is a fast path, so avoid calling GetUsableSize() on Release builds
// as it is more costly. Copy its small bucket path instead. // as it is more costly. Copy its small bucket path instead.
@ -1124,7 +1096,7 @@ ALWAYS_INLINE void PartitionRoot<thread_safe>::FreeNoHooks(void* object) {
#if defined(PA_HAS_MEMORY_TAGGING) #if defined(PA_HAS_MEMORY_TAGGING)
const size_t slot_size = slot_span->bucket->slot_size; const size_t slot_size = slot_span->bucket->slot_size;
if (LIKELY(slot_size <= internal::kMaxMemoryTaggingSize)) { if (LIKELY(slot_size <= kMaxMemoryTaggingSize)) {
// TODO(bartekn): |slot_start| shouldn't have MTE tag. // TODO(bartekn): |slot_start| shouldn't have MTE tag.
slot_start = ::partition_alloc::internal::TagMemoryRangeIncrement( slot_start = ::partition_alloc::internal::TagMemoryRangeIncrement(
slot_start, slot_size); slot_start, slot_size);
@ -1147,15 +1119,6 @@ ALWAYS_INLINE void PartitionRoot<thread_safe>::FreeNoHooks(void* object) {
PA_PREFETCH(slot_span); PA_PREFETCH(slot_span);
#endif // defined(PA_HAS_MEMORY_TAGGING) #endif // defined(PA_HAS_MEMORY_TAGGING)
#if defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
if (!root->IsDirectMappedBucket(slot_span->bucket)) {
size_t slot_size_less_extras =
root->AdjustSizeForExtrasSubtract(slot_span->bucket->slot_size);
partition_alloc::internal::PartitionTagIncrementValue(
object, slot_size_less_extras);
}
#endif // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
// TODO(bikineev): Change the condition to LIKELY once PCScan is enabled by // TODO(bikineev): Change the condition to LIKELY once PCScan is enabled by
// default. // default.
if (UNLIKELY(root->ShouldQuarantine(object))) { if (UNLIKELY(root->ShouldQuarantine(object))) {
@ -1241,7 +1204,7 @@ ALWAYS_INLINE void PartitionRoot<thread_safe>::FreeNoHooksImmediate(
// immediately. Otherwise, defer the operation and zap the memory to turn // immediately. Otherwise, defer the operation and zap the memory to turn
// potential use-after-free issues into unexploitable crashes. // potential use-after-free issues into unexploitable crashes.
if (UNLIKELY(!ref_count->IsAliveWithNoKnownRefs())) if (UNLIKELY(!ref_count->IsAliveWithNoKnownRefs()))
internal::SecureMemset(object, internal::kQuarantinedByte, internal::SecureMemset(object, kQuarantinedByte,
slot_span->GetUsableSize(this)); slot_span->GetUsableSize(this));
if (UNLIKELY(!(ref_count->ReleaseFromAllocator()))) { if (UNLIKELY(!(ref_count->ReleaseFromAllocator()))) {
@ -1256,7 +1219,7 @@ ALWAYS_INLINE void PartitionRoot<thread_safe>::FreeNoHooksImmediate(
// memset() can be really expensive. // memset() can be really expensive.
#if EXPENSIVE_DCHECKS_ARE_ON() #if EXPENSIVE_DCHECKS_ARE_ON()
memset(SlotStartAddr2Ptr(slot_start), internal::kFreedByte, memset(SlotStartAddr2Ptr(slot_start), kFreedByte,
slot_span->GetUtilizedSlotSize() slot_span->GetUtilizedSlotSize()
#if BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT) #if BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT)
- sizeof(internal::PartitionRefCount) - sizeof(internal::PartitionRefCount)
@ -1361,8 +1324,8 @@ ALWAYS_INLINE void PartitionRoot<thread_safe>::RawFreeWithThreadCache(
// allocations are uncommon. // allocations are uncommon.
if (LIKELY(with_thread_cache && !IsDirectMappedBucket(slot_span->bucket))) { if (LIKELY(with_thread_cache && !IsDirectMappedBucket(slot_span->bucket))) {
size_t bucket_index = slot_span->bucket - this->buckets; size_t bucket_index = slot_span->bucket - this->buckets;
auto* thread_cache = ThreadCache::Get(); auto* thread_cache = internal::ThreadCache::Get();
if (LIKELY(ThreadCache::IsValid(thread_cache) && if (LIKELY(internal::ThreadCache::IsValid(thread_cache) &&
thread_cache->MaybePutInCache(slot_start, bucket_index))) { thread_cache->MaybePutInCache(slot_start, bucket_index))) {
return; return;
} }
@ -1395,7 +1358,7 @@ template <bool thread_safe>
ALWAYS_INLINE PartitionRoot<thread_safe>* ALWAYS_INLINE PartitionRoot<thread_safe>*
PartitionRoot<thread_safe>::FromSlotSpan(SlotSpan* slot_span) { PartitionRoot<thread_safe>::FromSlotSpan(SlotSpan* slot_span) {
auto* extent_entry = reinterpret_cast<SuperPageExtentEntry*>( auto* extent_entry = reinterpret_cast<SuperPageExtentEntry*>(
reinterpret_cast<uintptr_t>(slot_span) & internal::SystemPageBaseMask()); reinterpret_cast<uintptr_t>(slot_span) & SystemPageBaseMask());
return extent_entry->root; return extent_entry->root;
} }
@ -1413,7 +1376,7 @@ PartitionRoot<thread_safe>::FromFirstSuperPage(uintptr_t super_page) {
template <bool thread_safe> template <bool thread_safe>
ALWAYS_INLINE PartitionRoot<thread_safe>* ALWAYS_INLINE PartitionRoot<thread_safe>*
PartitionRoot<thread_safe>::FromAddrInFirstSuperpage(uintptr_t address) { PartitionRoot<thread_safe>::FromAddrInFirstSuperpage(uintptr_t address) {
uintptr_t super_page = address & internal::kSuperPageBaseMask; uintptr_t super_page = address & kSuperPageBaseMask;
PA_DCHECK(internal::IsReservationStart(super_page)); PA_DCHECK(internal::IsReservationStart(super_page));
return FromFirstSuperPage(super_page); return FromFirstSuperPage(super_page);
} }
@ -1593,8 +1556,8 @@ ALWAYS_INLINE void* PartitionRoot<thread_safe>::AllocWithFlags(
int flags, int flags,
size_t requested_size, size_t requested_size,
const char* type_name) { const char* type_name) {
return AllocWithFlagsInternal(flags, requested_size, return AllocWithFlagsInternal(flags, requested_size, PartitionPageSize(),
internal::PartitionPageSize(), type_name); type_name);
} }
template <bool thread_safe> template <bool thread_safe>
@ -1603,9 +1566,8 @@ ALWAYS_INLINE void* PartitionRoot<thread_safe>::AllocWithFlagsInternal(
size_t requested_size, size_t requested_size,
size_t slot_span_alignment, size_t slot_span_alignment,
const char* type_name) { const char* type_name) {
PA_DCHECK( PA_DCHECK((slot_span_alignment >= PartitionPageSize()) &&
(slot_span_alignment >= internal::PartitionPageSize()) && bits::IsPowerOfTwo(slot_span_alignment));
partition_alloc::internal::base::bits::IsPowerOfTwo(slot_span_alignment));
PA_DCHECK(flags < AllocFlags::kLastFlag << 1); PA_DCHECK(flags < AllocFlags::kLastFlag << 1);
PA_DCHECK((flags & AllocFlags::kNoHooks) == 0); // Internal only. PA_DCHECK((flags & AllocFlags::kNoHooks) == 0); // Internal only.
@ -1646,9 +1608,8 @@ ALWAYS_INLINE void* PartitionRoot<thread_safe>::AllocWithFlagsNoHooks(
int flags, int flags,
size_t requested_size, size_t requested_size,
size_t slot_span_alignment) { size_t slot_span_alignment) {
PA_DCHECK( PA_DCHECK((slot_span_alignment >= PartitionPageSize()) &&
(slot_span_alignment >= internal::PartitionPageSize()) && bits::IsPowerOfTwo(slot_span_alignment));
partition_alloc::internal::base::bits::IsPowerOfTwo(slot_span_alignment));
// The thread cache is added "in the middle" of the main allocator, that is: // The thread cache is added "in the middle" of the main allocator, that is:
// - After all the cookie/ref-count management // - After all the cookie/ref-count management
@ -1687,12 +1648,11 @@ ALWAYS_INLINE void* PartitionRoot<thread_safe>::AllocWithFlagsNoHooks(
// thread cache will not be able to satisfy it. // thread cache will not be able to satisfy it.
// //
// LIKELY: performance-sensitive partitions use the thread cache. // LIKELY: performance-sensitive partitions use the thread cache.
if (LIKELY(with_thread_cache && if (LIKELY(with_thread_cache && slot_span_alignment <= PartitionPageSize())) {
slot_span_alignment <= internal::PartitionPageSize())) { auto* tcache = internal::ThreadCache::Get();
auto* tcache = ThreadCache::Get();
// LIKELY: Typically always true, except for the very first allocation of // LIKELY: Typically always true, except for the very first allocation of
// this thread. // this thread.
if (LIKELY(ThreadCache::IsValid(tcache))) { if (LIKELY(internal::ThreadCache::IsValid(tcache))) {
slot_start = tcache->GetFromCache(bucket_index, &slot_size); slot_start = tcache->GetFromCache(bucket_index, &slot_size);
} else { } else {
slot_start = MaybeInitThreadCacheAndAlloc(bucket_index, &slot_size); slot_start = MaybeInitThreadCacheAndAlloc(bucket_index, &slot_size);
@ -1794,7 +1754,7 @@ ALWAYS_INLINE void* PartitionRoot<thread_safe>::AllocWithFlagsNoHooks(
if (LIKELY(!zero_fill)) { if (LIKELY(!zero_fill)) {
// memset() can be really expensive. // memset() can be really expensive.
#if EXPENSIVE_DCHECKS_ARE_ON() #if EXPENSIVE_DCHECKS_ARE_ON()
memset(object, internal::kUninitializedByte, usable_size); memset(object, kUninitializedByte, usable_size);
#endif #endif
} else if (!is_already_zeroed) { } else if (!is_already_zeroed) {
memset(object, 0, usable_size); memset(object, 0, usable_size);
@ -1804,13 +1764,8 @@ ALWAYS_INLINE void* PartitionRoot<thread_safe>::AllocWithFlagsNoHooks(
// TODO(keishi): Add LIKELY when brp is fully enabled as |brp_enabled| will be // TODO(keishi): Add LIKELY when brp is fully enabled as |brp_enabled| will be
// false only for the aligned partition. // false only for the aligned partition.
if (brp_enabled()) { if (brp_enabled()) {
auto* ref_count = new (internal::PartitionRefCountPointer(slot_start)) new (internal::PartitionRefCountPointer(slot_start))
internal::PartitionRefCount(); internal::PartitionRefCount();
#if defined(PA_REF_COUNT_STORE_REQUESTED_SIZE)
ref_count->SetRequestedSize(requested_size);
#else
(void)ref_count;
#endif
} }
#endif // BUILDFLAG(USE_BACKUP_REF_PTR) #endif // BUILDFLAG(USE_BACKUP_REF_PTR)
@ -1873,13 +1828,13 @@ ALWAYS_INLINE void* PartitionRoot<thread_safe>::AlignedAllocWithFlags(
PA_DCHECK(allow_aligned_alloc); PA_DCHECK(allow_aligned_alloc);
PA_DCHECK(!extras_offset); PA_DCHECK(!extras_offset);
// This is mandated by |posix_memalign()|, so should never fire. // This is mandated by |posix_memalign()|, so should never fire.
PA_CHECK(partition_alloc::internal::base::bits::IsPowerOfTwo(alignment)); PA_CHECK(base::bits::IsPowerOfTwo(alignment));
// Catch unsupported alignment requests early. // Catch unsupported alignment requests early.
PA_CHECK(alignment <= internal::kMaxSupportedAlignment); PA_CHECK(alignment <= kMaxSupportedAlignment);
size_t raw_size = AdjustSizeForExtrasAdd(requested_size); size_t raw_size = AdjustSizeForExtrasAdd(requested_size);
size_t adjusted_size = requested_size; size_t adjusted_size = requested_size;
if (alignment <= internal::PartitionPageSize()) { if (alignment <= PartitionPageSize()) {
// Handle cases such as size = 16, alignment = 64. // Handle cases such as size = 16, alignment = 64.
// Wastes memory when a large alignment is requested with a small size, but // Wastes memory when a large alignment is requested with a small size, but
// this is hard to avoid, and should not be too common. // this is hard to avoid, and should not be too common.
@ -1889,13 +1844,11 @@ ALWAYS_INLINE void* PartitionRoot<thread_safe>::AlignedAllocWithFlags(
// PartitionAlloc only guarantees alignment for power-of-two sized // PartitionAlloc only guarantees alignment for power-of-two sized
// allocations. To make sure this applies here, round up the allocation // allocations. To make sure this applies here, round up the allocation
// size. // size.
raw_size = raw_size = static_cast<size_t>(1)
static_cast<size_t>(1) << (sizeof(size_t) * 8 -
<< (sizeof(size_t) * 8 - base::bits::CountLeadingZeroBits(raw_size - 1));
partition_alloc::internal::base::bits::CountLeadingZeroBits(
raw_size - 1));
} }
PA_DCHECK(partition_alloc::internal::base::bits::IsPowerOfTwo(raw_size)); PA_DCHECK(base::bits::IsPowerOfTwo(raw_size));
// Adjust back, because AllocWithFlagsNoHooks/Alloc will adjust it again. // Adjust back, because AllocWithFlagsNoHooks/Alloc will adjust it again.
adjusted_size = AdjustSizeForExtrasSubtract(raw_size); adjusted_size = AdjustSizeForExtrasSubtract(raw_size);
@ -1914,8 +1867,7 @@ ALWAYS_INLINE void* PartitionRoot<thread_safe>::AlignedAllocWithFlags(
// Slot spans are naturally aligned on partition page size, but make sure you // Slot spans are naturally aligned on partition page size, but make sure you
// don't pass anything less, because it'll mess up callee's calculations. // don't pass anything less, because it'll mess up callee's calculations.
size_t slot_span_alignment = size_t slot_span_alignment = std::max(alignment, PartitionPageSize());
std::max(alignment, internal::PartitionPageSize());
bool no_hooks = flags & AllocFlags::kNoHooks; bool no_hooks = flags & AllocFlags::kNoHooks;
void* object = void* object =
no_hooks no_hooks
@ -1969,11 +1921,11 @@ PartitionRoot<thread_safe>::AllocationCapacityFromRequestedSize(
auto& bucket = auto& bucket =
bucket_at(SizeToBucketIndex(size, with_denser_bucket_distribution)); bucket_at(SizeToBucketIndex(size, with_denser_bucket_distribution));
PA_DCHECK(!bucket.slot_size || bucket.slot_size >= size); PA_DCHECK(!bucket.slot_size || bucket.slot_size >= size);
PA_DCHECK(!(bucket.slot_size % internal::kSmallestBucket)); PA_DCHECK(!(bucket.slot_size % kSmallestBucket));
if (LIKELY(!bucket.is_direct_mapped())) { if (LIKELY(!bucket.is_direct_mapped())) {
size = bucket.slot_size; size = bucket.slot_size;
} else if (size > internal::MaxDirectMapped()) { } else if (size > MaxDirectMapped()) {
// Too large to allocate => return the size unchanged. // Too large to allocate => return the size unchanged.
} else { } else {
size = GetDirectMapSlotSize(size); size = GetDirectMapSlotSize(size);
@ -1986,32 +1938,26 @@ PartitionRoot<thread_safe>::AllocationCapacityFromRequestedSize(
using ThreadSafePartitionRoot = PartitionRoot<internal::ThreadSafe>; using ThreadSafePartitionRoot = PartitionRoot<internal::ThreadSafe>;
static_assert(offsetof(ThreadSafePartitionRoot, lock_) == static_assert(offsetof(ThreadSafePartitionRoot, lock_) ==
internal::kPartitionCachelineSize, kPartitionCachelineSize,
"Padding is incorrect"); "Padding is incorrect");
} // namespace partition_alloc
namespace base { } // namespace base
namespace partition_alloc {
// TODO(https://crbug.com/1288247): Remove these 'using' declarations once // TODO(https://crbug.com/1288247): Remove these 'using' declarations once
// the migration to the new namespaces gets done. // the migration to the new namespaces gets done.
using ::partition_alloc::PartitionOptions; using ::base::PartitionOptions;
using ::partition_alloc::PurgeFlags; using ::base::PurgeFlags;
using ::partition_alloc::ThreadSafePartitionRoot;
namespace internal { namespace internal {
// TODO(https://crbug.com/1288247): Remove these 'using' declarations once // TODO(https://crbug.com/1288247): Remove these 'using' declarations once
// the migration to the new namespaces gets done. // the migration to the new namespaces gets done.
using ::partition_alloc::internal::ScopedSyscallTimer; using ::base::internal::ScopedSyscallTimer;
#if BUILDFLAG(USE_BACKUP_REF_PTR)
using ::partition_alloc::internal::PartitionAllocFreeForRefCounting;
using ::partition_alloc::internal::PartitionAllocGetSlotStartInBRPPool;
using ::partition_alloc::internal::PartitionAllocIsValidPtrDelta;
#endif // BUILDFLAG(USE_BACKUP_REF_PTR)
} // namespace internal } // namespace internal
} // namespace base } // namespace partition_alloc
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ROOT_H_ #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ROOT_H_

View File

@ -1,138 +0,0 @@
// Copyright (c) 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_TAG_H_
#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_TAG_H_
// This file defines types and functions for `MTECheckedPtr<T>` (cf.
// `tagging.h`, which deals with real ARM MTE).
#include <string.h>
#include "base/allocator/buildflags.h"
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
#include "base/allocator/partition_allocator/partition_alloc_notreached.h"
#include "base/allocator/partition_allocator/partition_cookie.h"
#include "base/allocator/partition_allocator/partition_page.h"
#include "base/allocator/partition_allocator/partition_tag_bitmap.h"
#include "base/allocator/partition_allocator/reservation_offset_table.h"
#include "base/allocator/partition_allocator/tagging.h"
#include "build/build_config.h"
namespace partition_alloc {
#if defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
// Use 8 bits for the partition tag.
// TODO(tasak): add a description about the partition tag.
using PartitionTag = uint8_t;
static_assert(
sizeof(PartitionTag) == internal::tag_bitmap::kPartitionTagSize,
"sizeof(PartitionTag) must be equal to bitmap::kPartitionTagSize.");
ALWAYS_INLINE PartitionTag* PartitionTagPointer(uintptr_t addr) {
// TODO(crbug.com/1307514): Add direct map support. For now, just assume
// that direct maps don't have tags.
PA_DCHECK(internal::IsManagedByNormalBuckets(addr));
uintptr_t bitmap_base =
internal::SuperPageTagBitmapAddr(addr & internal::kSuperPageBaseMask);
const size_t bitmap_end_offset =
internal::PartitionPageSize() + internal::ReservedTagBitmapSize();
PA_DCHECK((addr & internal::kSuperPageOffsetMask) >= bitmap_end_offset);
uintptr_t offset_in_super_page =
(addr & internal::kSuperPageOffsetMask) - bitmap_end_offset;
size_t offset_in_bitmap = offset_in_super_page >>
internal::tag_bitmap::kBytesPerPartitionTagShift
<< internal::tag_bitmap::kPartitionTagSizeShift;
return reinterpret_cast<PartitionTag*>(bitmap_base + offset_in_bitmap);
}
ALWAYS_INLINE PartitionTag* PartitionTagPointer(const void* ptr) {
return PartitionTagPointer(
internal::UnmaskPtr(reinterpret_cast<uintptr_t>(ptr)));
}
namespace internal {
ALWAYS_INLINE void PartitionTagSetValue(uintptr_t addr,
size_t size,
PartitionTag value) {
PA_DCHECK((size % tag_bitmap::kBytesPerPartitionTag) == 0);
size_t tag_count = size >> tag_bitmap::kBytesPerPartitionTagShift;
PartitionTag* tag_ptr = PartitionTagPointer(addr);
if (sizeof(PartitionTag) == 1) {
memset(tag_ptr, value, tag_count);
} else {
while (tag_count-- > 0)
*tag_ptr++ = value;
}
}
ALWAYS_INLINE void PartitionTagSetValue(void* ptr,
size_t size,
PartitionTag value) {
PartitionTagSetValue(reinterpret_cast<uintptr_t>(ptr), size, value);
}
ALWAYS_INLINE PartitionTag PartitionTagGetValue(void* ptr) {
return *PartitionTagPointer(ptr);
}
ALWAYS_INLINE void PartitionTagClearValue(void* ptr, size_t size) {
size_t tag_region_size = size >> tag_bitmap::kBytesPerPartitionTagShift
<< tag_bitmap::kPartitionTagSizeShift;
PA_DCHECK(!memchr(PartitionTagPointer(ptr), 0, tag_region_size));
memset(PartitionTagPointer(ptr), 0, tag_region_size);
}
ALWAYS_INLINE void PartitionTagIncrementValue(void* ptr, size_t size) {
PartitionTag tag = PartitionTagGetValue(ptr);
PartitionTag new_tag = tag;
++new_tag;
new_tag += !new_tag; // Avoid 0.
#if DCHECK_IS_ON()
// This verifies that tags for the entire slot have the same value and that
// |size| doesn't exceed the slot size.
size_t tag_count = size >> tag_bitmap::kBytesPerPartitionTagShift;
PartitionTag* tag_ptr = PartitionTagPointer(ptr);
while (tag_count-- > 0) {
PA_DCHECK(tag == *tag_ptr);
tag_ptr++;
}
#endif
PartitionTagSetValue(ptr, size, new_tag);
}
} // namespace internal
#else // No-op versions
using PartitionTag = uint8_t;
ALWAYS_INLINE PartitionTag* PartitionTagPointer(void* ptr) {
PA_NOTREACHED();
return nullptr;
}
namespace internal {
ALWAYS_INLINE void PartitionTagSetValue(void*, size_t, PartitionTag) {}
ALWAYS_INLINE PartitionTag PartitionTagGetValue(void*) {
return 0;
}
ALWAYS_INLINE void PartitionTagClearValue(void* ptr, size_t) {}
ALWAYS_INLINE void PartitionTagIncrementValue(void* ptr, size_t size) {}
} // namespace internal
#endif // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
} // namespace partition_alloc
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_TAG_H_

View File

@ -1,145 +0,0 @@
// Copyright (c) 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_TAG_BITMAP_H_
#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_TAG_BITMAP_H_
#include "base/allocator/buildflags.h"
#include "base/allocator/partition_allocator/page_allocator_constants.h"
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
namespace partition_alloc::internal {
#if defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
namespace tag_bitmap {
// kPartitionTagSize should be equal to sizeof(PartitionTag).
// PartitionTag is defined in partition_tag.h and static_assert there
// checks the condition.
static constexpr size_t kPartitionTagSizeShift = 0;
static constexpr size_t kPartitionTagSize = 1U << kPartitionTagSizeShift;
static constexpr size_t kBytesPerPartitionTagShift = 4;
// One partition tag is assigned per |kBytesPerPartitionTag| bytes in the slot
// spans.
// +-----------+ 0
// | | ====> 1 partition tag
// +-----------+ kBytesPerPartitionTag
// | | ====> 1 partition tag
// +-----------+ 2*kBytesPerPartitionTag
// ...
// +-----------+ slot_size
static constexpr size_t kBytesPerPartitionTag = 1U
<< kBytesPerPartitionTagShift;
static_assert(
kMinBucketedOrder >= kBytesPerPartitionTagShift + 1,
"MTECheckedPtr requires kBytesPerPartitionTagShift-bytes alignment.");
static constexpr size_t kBytesPerPartitionTagRatio =
kBytesPerPartitionTag / kPartitionTagSize;
static_assert(kBytesPerPartitionTag > 0,
"kBytesPerPartitionTag should be larger than 0");
static_assert(
kBytesPerPartitionTag % kPartitionTagSize == 0,
"kBytesPerPartitionTag should be multiples of sizeof(PartitionTag).");
constexpr size_t CeilCountOfUnits(size_t size, size_t unit_size) {
return (size + unit_size - 1) / unit_size;
}
} // namespace tag_bitmap
// kTagBitmapSize is calculated in the following way:
// (1) kSuperPageSize - 2 * PartitionPageSize() = kTagBitmapSize +
// SlotSpanSize()
// (2) kTagBitmapSize >= SlotSpanSize() / kBytesPerPartitionTag *
// sizeof(PartitionTag)
//--
// (1)' SlotSpanSize() = kSuperPageSize - 2 * PartitionPageSize() -
// kTagBitmapSize
// (2)' SlotSpanSize() <= kTagBitmapSize * Y
// (3)' Y = kBytesPerPartitionTag / sizeof(PartitionTag) =
// kBytesPerPartitionTagRatio
//
// kTagBitmapSize * Y >= kSuperPageSize - 2 * PartitionPageSize() -
// kTagBitmapSize (1 + Y) * kTagBimapSize >= kSuperPageSize - 2 *
// PartitionPageSize()
// Finally,
// kTagBitmapSize >= (kSuperPageSize - 2 * PartitionPageSize()) / (1 + Y)
PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t
NumPartitionPagesPerTagBitmap() {
return tag_bitmap::CeilCountOfUnits(
kSuperPageSize / PartitionPageSize() - 2,
tag_bitmap::kBytesPerPartitionTagRatio + 1);
}
// To make guard pages between the tag bitmap and the slot span, calculate the
// number of SystemPages of TagBitmap. If kNumSystemPagesPerTagBitmap *
// SystemPageSize() < kTagBitmapSize, guard pages will be created. (c.f. no
// guard pages if sizeof(PartitionTag) == 2.)
PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t
NumSystemPagesPerTagBitmap() {
return tag_bitmap::CeilCountOfUnits(
kSuperPageSize / SystemPageSize() -
2 * PartitionPageSize() / SystemPageSize(),
tag_bitmap::kBytesPerPartitionTagRatio + 1);
}
PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t
ActualTagBitmapSize() {
return NumSystemPagesPerTagBitmap() * SystemPageSize();
}
// PartitionPageSize-aligned tag bitmap size.
PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t
ReservedTagBitmapSize() {
return PartitionPageSize() * NumPartitionPagesPerTagBitmap();
}
#if PAGE_ALLOCATOR_CONSTANTS_ARE_CONSTEXPR
static_assert(ActualTagBitmapSize() <= ReservedTagBitmapSize(),
"kActualTagBitmapSize should be smaller than or equal to "
"kReservedTagBitmapSize.");
static_assert(ReservedTagBitmapSize() - ActualTagBitmapSize() <
PartitionPageSize(),
"Unused space in the tag bitmap should be smaller than "
"PartitionPageSize()");
// The region available for slot spans is the reminder of the super page, after
// taking away the first and last partition page (for metadata and guard pages)
// and partition pages reserved for the tag bitmap.
PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t
SlotSpansSize() {
return kSuperPageSize - 2 * PartitionPageSize() - ReservedTagBitmapSize();
}
static_assert(ActualTagBitmapSize() * tag_bitmap::kBytesPerPartitionTagRatio >=
SlotSpansSize(),
"bitmap is large enough to cover slot spans");
static_assert((ActualTagBitmapSize() - PartitionPageSize()) *
tag_bitmap::kBytesPerPartitionTagRatio <
SlotSpansSize(),
"any smaller bitmap wouldn't suffice to cover slots spans");
#endif // PAGE_ALLOCATOR_CONSTANTS_ARE_CONSTEXPR
#else
constexpr ALWAYS_INLINE size_t NumPartitionPagesPerTagBitmap() {
return 0;
}
constexpr ALWAYS_INLINE size_t ActualTagBitmapSize() {
return 0;
}
constexpr ALWAYS_INLINE size_t ReservedTagBitmapSize() {
return 0;
}
#endif // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
} // namespace partition_alloc::internal
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_TAG_BITMAP_H_

View File

@ -6,7 +6,6 @@
#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_TLS_H_ #define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_TLS_H_
#include "base/allocator/partition_allocator/partition_alloc_check.h" #include "base/allocator/partition_allocator/partition_alloc_check.h"
#include "base/base_export.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "build/build_config.h" #include "build/build_config.h"

View File

@ -16,7 +16,6 @@
#include "base/allocator/partition_allocator/partition_alloc_check.h" #include "base/allocator/partition_allocator/partition_alloc_check.h"
#include "base/allocator/partition_allocator/partition_alloc_constants.h" #include "base/allocator/partition_allocator/partition_alloc_constants.h"
#include "base/allocator/partition_allocator/tagging.h" #include "base/allocator/partition_allocator/tagging.h"
#include "base/base_export.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "build/build_config.h" #include "build/build_config.h"

View File

@ -8,7 +8,8 @@
#include "base/allocator/partition_allocator/allocation_guard.h" #include "base/allocator/partition_allocator/allocation_guard.h"
#include "base/logging.h" #include "base/logging.h"
namespace partition_alloc::internal { namespace base {
namespace internal {
// Logging requires allocations. This logger allows reentrant allocations to // Logging requires allocations. This logger allows reentrant allocations to
// happen within the allocator context. // happen within the allocator context.
@ -17,9 +18,9 @@ struct LoggerWithAllowedAllocations : ScopedAllowAllocations,
using logging::LogMessage::LogMessage; using logging::LogMessage::LogMessage;
}; };
#define PA_PCSCAN_VLOG_STREAM(verbose_level) \ #define PA_PCSCAN_VLOG_STREAM(verbose_level) \
::partition_alloc::internal::LoggerWithAllowedAllocations( \ ::base::internal::LoggerWithAllowedAllocations(__FILE__, __LINE__, \
__FILE__, __LINE__, -(verbose_level)) \ -(verbose_level)) \
.stream() .stream()
// Logging macro that is meant to be used inside *Scan. Generally, reentrancy // Logging macro that is meant to be used inside *Scan. Generally, reentrancy
@ -33,6 +34,7 @@ struct LoggerWithAllowedAllocations : ScopedAllowAllocations,
#define PA_PCSCAN_VLOG(verbose_level) \ #define PA_PCSCAN_VLOG(verbose_level) \
LAZY_STREAM(PA_PCSCAN_VLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level)) LAZY_STREAM(PA_PCSCAN_VLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level))
} // namespace partition_alloc::internal } // namespace internal
} // namespace base
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_LOGGING_H_ #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_LOGGING_H_

View File

@ -8,7 +8,8 @@
#include "base/no_destructor.h" #include "base/no_destructor.h"
namespace partition_alloc::internal { namespace base {
namespace internal {
namespace { namespace {
constexpr PartitionOptions kConfig{ constexpr PartitionOptions kConfig{
@ -36,4 +37,5 @@ void ReinitPCScanMetadataAllocatorForTesting() {
PCScanMetadataAllocator().Init(kConfig); PCScanMetadataAllocator().Init(kConfig);
} }
} // namespace partition_alloc::internal } // namespace internal
} // namespace base

View File

@ -10,7 +10,8 @@
#include "base/allocator/partition_allocator/partition_alloc_constants.h" #include "base/allocator/partition_allocator/partition_alloc_constants.h"
#include "base/allocator/partition_allocator/partition_root.h" #include "base/allocator/partition_allocator/partition_root.h"
namespace partition_alloc::internal { namespace base {
namespace internal {
ThreadSafePartitionRoot& PCScanMetadataAllocator(); ThreadSafePartitionRoot& PCScanMetadataAllocator();
void ReinitPCScanMetadataAllocatorForTesting(); void ReinitPCScanMetadataAllocatorForTesting();
@ -78,18 +79,7 @@ struct PCScanMetadataDeleter final {
} }
}; };
} // namespace partition_alloc::internal } // namespace internal
} // namespace base
// TODO(crbug.com/1288247): Remove these when migration is complete.
namespace base::internal {
using ::partition_alloc::internal::AllocatedOnPCScanMetadataPartition;
using ::partition_alloc::internal::MakePCScanMetadata;
using ::partition_alloc::internal::MetadataAllocator;
using ::partition_alloc::internal::PCScanMetadataAllocator;
using ::partition_alloc::internal::PCScanMetadataDeleter;
using ::partition_alloc::internal::ReinitPCScanMetadataAllocatorForTesting;
} // namespace base::internal
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_METADATA_ALLOCATOR_H_ #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_METADATA_ALLOCATOR_H_

View File

@ -6,7 +6,8 @@
#include "base/allocator/partition_allocator/starscan/pcscan_internal.h" #include "base/allocator/partition_allocator/starscan/pcscan_internal.h"
namespace partition_alloc::internal { namespace base {
namespace internal {
void PCScan::Initialize(InitConfig config) { void PCScan::Initialize(InitConfig config) {
PCScanInternal::Instance().Initialize(config); PCScanInternal::Instance().Initialize(config);
@ -53,7 +54,7 @@ void PCScan::PerformScanIfNeeded(InvocationMode invocation_mode) {
void PCScan::PerformDelayedScan(int64_t delay_in_microseconds) { void PCScan::PerformDelayedScan(int64_t delay_in_microseconds) {
PCScanInternal::Instance().PerformDelayedScan( PCScanInternal::Instance().PerformDelayedScan(
base::Microseconds(delay_in_microseconds)); Microseconds(delay_in_microseconds));
} }
void PCScan::JoinScan() { void PCScan::JoinScan() {
@ -103,10 +104,11 @@ void PCScan::FinishScanForTesting() {
PCScanInternal::Instance().FinishScanForTesting(); // IN-TEST PCScanInternal::Instance().FinishScanForTesting(); // IN-TEST
} }
void PCScan::RegisterStatsReporter(partition_alloc::StatsReporter* reporter) { void PCScan::RegisterStatsReporter(StatsReporter* reporter) {
PCScanInternal::Instance().RegisterStatsReporter(reporter); PCScanInternal::Instance().RegisterStatsReporter(reporter);
} }
PCScan PCScan::instance_ CONSTINIT; PCScan PCScan::instance_ CONSTINIT;
} // namespace partition_alloc::internal } // namespace internal
} // namespace base

View File

@ -20,7 +20,7 @@
// We currently disable it to improve the runtime. // We currently disable it to improve the runtime.
#define PA_STARSCAN_EAGER_DOUBLE_FREE_DETECTION_ENABLED 0 #define PA_STARSCAN_EAGER_DOUBLE_FREE_DETECTION_ENABLED 0
namespace partition_alloc { namespace base {
class StatsReporter; class StatsReporter;
@ -141,7 +141,7 @@ class BASE_EXPORT PCScan final {
inline static PCScanScheduler& scheduler(); inline static PCScanScheduler& scheduler();
// Registers reporting class. // Registers reporting class.
static void RegisterStatsReporter(partition_alloc::StatsReporter* reporter); static void RegisterStatsReporter(StatsReporter* reporter);
private: private:
class PCScanThread; class PCScanThread;
@ -278,12 +278,6 @@ inline PCScanScheduler& PCScan::scheduler() {
} }
} // namespace internal } // namespace internal
} // namespace partition_alloc } // namespace base
// TODO(crbug.com/1288247): Remove this when migration is complete.
namespace base::internal {
using ::partition_alloc::internal::PCScan;
} // namespace base::internal
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_PCSCAN_H_ #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_PCSCAN_H_

View File

@ -20,7 +20,6 @@
#include "base/allocator/partition_allocator/address_pool_manager.h" #include "base/allocator/partition_allocator/address_pool_manager.h"
#include "base/allocator/partition_allocator/address_pool_manager_bitmap.h" #include "base/allocator/partition_allocator/address_pool_manager_bitmap.h"
#include "base/allocator/partition_allocator/allocation_guard.h" #include "base/allocator/partition_allocator/allocation_guard.h"
#include "base/allocator/partition_allocator/base/bits.h"
#include "base/allocator/partition_allocator/page_allocator.h" #include "base/allocator/partition_allocator/page_allocator.h"
#include "base/allocator/partition_allocator/page_allocator_constants.h" #include "base/allocator/partition_allocator/page_allocator_constants.h"
#include "base/allocator/partition_allocator/partition_address_space.h" #include "base/allocator/partition_allocator/partition_address_space.h"
@ -40,6 +39,7 @@
#include "base/allocator/partition_allocator/starscan/stats_reporter.h" #include "base/allocator/partition_allocator/starscan/stats_reporter.h"
#include "base/allocator/partition_allocator/tagging.h" #include "base/allocator/partition_allocator/tagging.h"
#include "base/allocator/partition_allocator/thread_cache.h" #include "base/allocator/partition_allocator/thread_cache.h"
#include "base/bits.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/cpu.h" #include "base/cpu.h"
#include "base/debug/alias.h" #include "base/debug/alias.h"
@ -62,14 +62,10 @@
#define PA_SCAN_INLINE ALWAYS_INLINE #define PA_SCAN_INLINE ALWAYS_INLINE
#endif #endif
namespace partition_alloc::internal {
namespace base { namespace base {
using ::base::MakeRefCounted; namespace internal {
using ::base::RefCountedThreadSafe;
} // namespace base
[[noreturn]] NOINLINE NOT_TAIL_CALLED void DoubleFreeAttempt() { [[noreturn]] BASE_EXPORT NOINLINE NOT_TAIL_CALLED void DoubleFreeAttempt() {
NO_CODE_FOLDING(); NO_CODE_FOLDING();
IMMEDIATE_CRASH(); IMMEDIATE_CRASH();
} }
@ -349,9 +345,8 @@ class SuperPageSnapshot final {
static constexpr size_t kStateBitmapMinReservedSize = static constexpr size_t kStateBitmapMinReservedSize =
__builtin_constant_p(ReservedStateBitmapSize()) __builtin_constant_p(ReservedStateBitmapSize())
? ReservedStateBitmapSize() ? ReservedStateBitmapSize()
: partition_alloc::internal::base::bits::AlignUp( : base::bits::AlignUp(sizeof(AllocationStateMap),
sizeof(AllocationStateMap), kMinPartitionPageSize);
kMinPartitionPageSize);
// Take into account guard partition page at the end of super-page. // Take into account guard partition page at the end of super-page.
static constexpr size_t kGuardPagesSize = 2 * kMinPartitionPageSize; static constexpr size_t kGuardPagesSize = 2 * kMinPartitionPageSize;
@ -989,9 +984,9 @@ void UnmarkInCardTable(uintptr_t slot_start,
const size_t slot_size = slot_span->bucket->slot_size; const size_t slot_size = slot_span->bucket->slot_size;
if (slot_size >= SystemPageSize()) { if (slot_size >= SystemPageSize()) {
const uintptr_t discard_end = const uintptr_t discard_end =
base::bits::AlignDown(slot_start + slot_size, SystemPageSize()); bits::AlignDown(slot_start + slot_size, SystemPageSize());
const uintptr_t discard_begin = const uintptr_t discard_begin =
base::bits::AlignUp(slot_start, SystemPageSize()); bits::AlignUp(slot_start, SystemPageSize());
const intptr_t discard_size = discard_end - discard_begin; const intptr_t discard_size = discard_end - discard_begin;
if (discard_size > 0) { if (discard_size > 0) {
DiscardSystemPages(discard_begin, discard_size); DiscardSystemPages(discard_begin, discard_size);
@ -1192,12 +1187,12 @@ class PCScan::PCScanThread final {
std::lock_guard<std::mutex> lock(mutex_); std::lock_guard<std::mutex> lock(mutex_);
PA_DCHECK(!posted_task_.get()); PA_DCHECK(!posted_task_.get());
posted_task_ = std::move(task); posted_task_ = std::move(task);
wanted_delay_ = base::TimeDelta(); wanted_delay_ = TimeDelta();
} }
condvar_.notify_one(); condvar_.notify_one();
} }
void PostDelayedTask(base::TimeDelta delay) { void PostDelayedTask(TimeDelta delay) {
{ {
std::lock_guard<std::mutex> lock(mutex_); std::lock_guard<std::mutex> lock(mutex_);
if (posted_task_.get()) { if (posted_task_.get()) {
@ -1261,7 +1256,7 @@ class PCScan::PCScanThread final {
// Differentiate between a posted task and a delayed task schedule. // Differentiate between a posted task and a delayed task schedule.
if (posted_task_.get()) { if (posted_task_.get()) {
std::swap(current_task, posted_task_); std::swap(current_task, posted_task_);
wanted_delay_ = base::TimeDelta(); wanted_delay_ = TimeDelta();
} else { } else {
PA_DCHECK(wanted_delay_.is_zero()); PA_DCHECK(wanted_delay_.is_zero());
} }
@ -1280,7 +1275,7 @@ class PCScan::PCScanThread final {
std::mutex mutex_; std::mutex mutex_;
std::condition_variable condvar_; std::condition_variable condvar_;
TaskHandle posted_task_; TaskHandle posted_task_;
base::TimeDelta wanted_delay_; TimeDelta wanted_delay_;
}; };
PCScanInternal::PCScanInternal() : simd_support_(DetectSimdSupport()) {} PCScanInternal::PCScanInternal() : simd_support_(DetectSimdSupport()) {}
@ -1311,7 +1306,7 @@ void PCScanInternal::Initialize(PCScan::InitConfig config) {
scannable_roots_ = RootsMap(); scannable_roots_ = RootsMap();
nonscannable_roots_ = RootsMap(); nonscannable_roots_ = RootsMap();
static partition_alloc::StatsReporter s_no_op_reporter; static StatsReporter s_no_op_reporter;
PCScan::Instance().RegisterStatsReporter(&s_no_op_reporter); PCScan::Instance().RegisterStatsReporter(&s_no_op_reporter);
// Don't initialize PCScanThread::Instance() as otherwise sandbox complains // Don't initialize PCScanThread::Instance() as otherwise sandbox complains
@ -1378,7 +1373,7 @@ void PCScanInternal::PerformScanIfNeeded(
PerformScan(invocation_mode); PerformScan(invocation_mode);
} }
void PCScanInternal::PerformDelayedScan(base::TimeDelta delay) { void PCScanInternal::PerformDelayedScan(TimeDelta delay) {
PCScan::PCScanThread::Instance().PostDelayedTask(delay); PCScan::PCScanThread::Instance().PostDelayedTask(delay);
} }
@ -1566,16 +1561,14 @@ void PCScanInternal::ProtectPages(uintptr_t begin, size_t size) {
// slot-spans doesn't need to be protected (the allocator will enter the // slot-spans doesn't need to be protected (the allocator will enter the
// safepoint before trying to allocate from it). // safepoint before trying to allocate from it).
PA_SCAN_DCHECK(write_protector_.get()); PA_SCAN_DCHECK(write_protector_.get());
write_protector_->ProtectPages( write_protector_->ProtectPages(begin,
begin, base::bits::AlignUp(size, SystemPageSize()));
partition_alloc::internal::base::bits::AlignUp(size, SystemPageSize()));
} }
void PCScanInternal::UnprotectPages(uintptr_t begin, size_t size) { void PCScanInternal::UnprotectPages(uintptr_t begin, size_t size) {
PA_SCAN_DCHECK(write_protector_.get()); PA_SCAN_DCHECK(write_protector_.get());
write_protector_->UnprotectPages( write_protector_->UnprotectPages(begin,
begin, base::bits::AlignUp(size, SystemPageSize()));
partition_alloc::internal::base::bits::AlignUp(size, SystemPageSize()));
} }
void PCScanInternal::ClearRootsForTesting() { void PCScanInternal::ClearRootsForTesting() {
@ -1613,15 +1606,15 @@ void PCScanInternal::FinishScanForTesting() {
current_task->RunFromScanner(); current_task->RunFromScanner();
} }
void PCScanInternal::RegisterStatsReporter( void PCScanInternal::RegisterStatsReporter(StatsReporter* reporter) {
partition_alloc::StatsReporter* reporter) {
PA_DCHECK(reporter); PA_DCHECK(reporter);
stats_reporter_ = reporter; stats_reporter_ = reporter;
} }
partition_alloc::StatsReporter& PCScanInternal::GetReporter() { StatsReporter& PCScanInternal::GetReporter() {
PA_DCHECK(stats_reporter_); PA_DCHECK(stats_reporter_);
return *stats_reporter_; return *stats_reporter_;
} }
} // namespace partition_alloc::internal } // namespace internal
} // namespace base

View File

@ -20,10 +20,11 @@
#include "base/memory/scoped_refptr.h" #include "base/memory/scoped_refptr.h"
#include "base/no_destructor.h" #include "base/no_destructor.h"
// TODO(crbug.com/1288247): Remove this when migration is complete. namespace base {
namespace partition_alloc::internal {
class StarScanSnapshot; class StatsReporter;
namespace internal {
class PCScanTask; class PCScanTask;
@ -60,7 +61,7 @@ class PCScanInternal final {
void PerformScan(PCScan::InvocationMode); void PerformScan(PCScan::InvocationMode);
void PerformScanIfNeeded(PCScan::InvocationMode); void PerformScanIfNeeded(PCScan::InvocationMode);
void PerformDelayedScan(base::TimeDelta delay); void PerformDelayedScan(TimeDelta delay);
void JoinScan(); void JoinScan();
TaskHandle CurrentPCScanTask() const; TaskHandle CurrentPCScanTask() const;
@ -106,19 +107,19 @@ class PCScanInternal final {
void ReinitForTesting(PCScan::InitConfig); // IN-TEST void ReinitForTesting(PCScan::InitConfig); // IN-TEST
void FinishScanForTesting(); // IN-TEST void FinishScanForTesting(); // IN-TEST
void RegisterStatsReporter(partition_alloc::StatsReporter* reporter); void RegisterStatsReporter(StatsReporter* reporter);
partition_alloc::StatsReporter& GetReporter(); StatsReporter& GetReporter();
private: private:
friend base::NoDestructor<PCScanInternal>; friend base::NoDestructor<PCScanInternal>;
friend class partition_alloc::internal::StarScanSnapshot; friend class StarScanSnapshot;
using StackTops = std::unordered_map< using StackTops = std::unordered_map<
::base::PlatformThreadId, PlatformThreadId,
void*, void*,
std::hash<::base::PlatformThreadId>, std::hash<PlatformThreadId>,
std::equal_to<>, std::equal_to<>,
MetadataAllocator<std::pair<const ::base::PlatformThreadId, void*>>>; MetadataAllocator<std::pair<const PlatformThreadId, void*>>>;
PCScanInternal(); PCScanInternal();
@ -141,18 +142,13 @@ class PCScanInternal final {
const SimdSupport simd_support_; const SimdSupport simd_support_;
std::unique_ptr<WriteProtector> write_protector_; std::unique_ptr<WriteProtector> write_protector_;
partition_alloc::StatsReporter* stats_reporter_ = nullptr; StatsReporter* stats_reporter_ = nullptr;
bool is_initialized_ = false; bool is_initialized_ = false;
}; };
} // namespace partition_alloc::internal } // namespace internal
// TODO(crbug.com/1288247): Remove this when migration is complete. } // namespace base
namespace base::internal {
using ::partition_alloc::internal::PCScanInternal;
} // namespace base::internal
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_PCSCAN_INTERNAL_H_ #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_PCSCAN_INTERNAL_H_

View File

@ -15,7 +15,8 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/time/time.h" #include "base/time/time.h"
namespace partition_alloc::internal { namespace base {
namespace internal {
// static // static
constexpr size_t QuarantineData::kQuarantineSizeMinLimit; constexpr size_t QuarantineData::kQuarantineSizeMinLimit;
@ -33,8 +34,7 @@ void PCScanSchedulingBackend::EnableScheduling() {
scheduling_enabled_.store(true, std::memory_order_relaxed); scheduling_enabled_.store(true, std::memory_order_relaxed);
// Check if *Scan needs to be run immediately. // Check if *Scan needs to be run immediately.
if (NeedsToImmediatelyScan()) if (NeedsToImmediatelyScan())
::base::internal::PCScan::PerformScan( PCScan::PerformScan(PCScan::InvocationMode::kNonBlocking);
::base::internal::PCScan::InvocationMode::kNonBlocking);
} }
size_t PCScanSchedulingBackend::ScanStarted() { size_t PCScanSchedulingBackend::ScanStarted() {
@ -43,8 +43,8 @@ size_t PCScanSchedulingBackend::ScanStarted() {
return data.current_size.exchange(0, std::memory_order_relaxed); return data.current_size.exchange(0, std::memory_order_relaxed);
} }
base::TimeDelta PCScanSchedulingBackend::UpdateDelayedSchedule() { TimeDelta PCScanSchedulingBackend::UpdateDelayedSchedule() {
return base::TimeDelta(); return TimeDelta();
} }
// static // static
@ -92,7 +92,7 @@ bool MUAwareTaskBasedBackend::LimitReached() {
bool should_reschedule = false; bool should_reschedule = false;
base::TimeDelta reschedule_delay; base::TimeDelta reschedule_delay;
{ {
ScopedGuard guard(scheduler_lock_); PartitionAutoLock guard(scheduler_lock_);
// At this point we reached a limit where the schedule generally wants to // At this point we reached a limit where the schedule generally wants to
// trigger a scan. // trigger a scan.
if (hard_limit_) { if (hard_limit_) {
@ -120,7 +120,7 @@ bool MUAwareTaskBasedBackend::LimitReached() {
// 4. Otherwise, the soft limit would trigger a scan immediately if the // 4. Otherwise, the soft limit would trigger a scan immediately if the
// mutator utilization requirement is satisfied. // mutator utilization requirement is satisfied.
reschedule_delay = earliest_next_scan_time_ - base::TimeTicks::Now(); reschedule_delay = earliest_next_scan_time_ - base::TimeTicks::Now();
if (reschedule_delay <= base::TimeDelta()) { if (reschedule_delay <= TimeDelta()) {
// May invoke scan immediately. // May invoke scan immediately.
return true; return true;
} }
@ -142,7 +142,7 @@ bool MUAwareTaskBasedBackend::LimitReached() {
} }
size_t MUAwareTaskBasedBackend::ScanStarted() { size_t MUAwareTaskBasedBackend::ScanStarted() {
ScopedGuard guard(scheduler_lock_); PartitionAutoLock guard(scheduler_lock_);
return PCScanSchedulingBackend::ScanStarted(); return PCScanSchedulingBackend::ScanStarted();
} }
@ -153,7 +153,7 @@ void MUAwareTaskBasedBackend::UpdateScheduleAfterScan(
size_t heap_size) { size_t heap_size) {
scheduler_.AccountFreed(survived_bytes); scheduler_.AccountFreed(survived_bytes);
ScopedGuard guard(scheduler_lock_); PartitionAutoLock guard(scheduler_lock_);
// |heap_size| includes the current quarantine size, we intentionally leave // |heap_size| includes the current quarantine size, we intentionally leave
// some slack till hitting the limit. // some slack till hitting the limit.
@ -180,7 +180,7 @@ bool MUAwareTaskBasedBackend::NeedsToImmediatelyScan() {
bool should_reschedule = false; bool should_reschedule = false;
base::TimeDelta reschedule_delay; base::TimeDelta reschedule_delay;
{ {
ScopedGuard guard(scheduler_lock_); PartitionAutoLock guard(scheduler_lock_);
// If |hard_limit_| was set to zero, the soft limit was reached. Bail out if // If |hard_limit_| was set to zero, the soft limit was reached. Bail out if
// it's not. // it's not.
if (hard_limit_) if (hard_limit_)
@ -188,7 +188,7 @@ bool MUAwareTaskBasedBackend::NeedsToImmediatelyScan() {
// Check if mutator utilization requiremet is satisfied. // Check if mutator utilization requiremet is satisfied.
reschedule_delay = earliest_next_scan_time_ - base::TimeTicks::Now(); reschedule_delay = earliest_next_scan_time_ - base::TimeTicks::Now();
if (reschedule_delay <= base::TimeDelta()) { if (reschedule_delay <= TimeDelta()) {
// May invoke scan immediately. // May invoke scan immediately.
return true; return true;
} }
@ -205,12 +205,13 @@ bool MUAwareTaskBasedBackend::NeedsToImmediatelyScan() {
return false; return false;
} }
base::TimeDelta MUAwareTaskBasedBackend::UpdateDelayedSchedule() { TimeDelta MUAwareTaskBasedBackend::UpdateDelayedSchedule() {
ScopedGuard guard(scheduler_lock_); PartitionAutoLock guard(scheduler_lock_);
// TODO(1197479): Adjust schedule to current heap sizing. // TODO(1197479): Adjust schedule to current heap sizing.
const auto delay = earliest_next_scan_time_ - base::TimeTicks::Now(); const auto delay = earliest_next_scan_time_ - base::TimeTicks::Now();
PA_PCSCAN_VLOG(3) << "Schedule is off by " << delay.InMillisecondsF() << "ms"; PA_PCSCAN_VLOG(3) << "Schedule is off by " << delay.InMillisecondsF() << "ms";
return delay >= base::TimeDelta() ? delay : base::TimeDelta(); return delay >= TimeDelta() ? delay : TimeDelta();
} }
} // namespace partition_alloc::internal } // namespace internal
} // namespace base

View File

@ -10,10 +10,12 @@
#include "base/allocator/partition_allocator/partition_lock.h" #include "base/allocator/partition_allocator/partition_lock.h"
#include "base/base_export.h" #include "base/base_export.h"
#include "base/callback.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/time/time.h" #include "base/time/time.h"
namespace partition_alloc::internal { namespace base {
namespace internal {
class PCScanScheduler; class PCScanScheduler;
@ -64,7 +66,7 @@ class BASE_EXPORT PCScanSchedulingBackend {
// Invoked by PCScan to ask for a new timeout for a scheduled PCScan task. // Invoked by PCScan to ask for a new timeout for a scheduled PCScan task.
// Only invoked if scheduler requests a delayed scan at some point. // Only invoked if scheduler requests a delayed scan at some point.
virtual base::TimeDelta UpdateDelayedSchedule(); virtual TimeDelta UpdateDelayedSchedule();
protected: protected:
inline bool SchedulingDisabled() const; inline bool SchedulingDisabled() const;
@ -107,7 +109,7 @@ class BASE_EXPORT MUAwareTaskBasedBackend final
bool LimitReached() final; bool LimitReached() final;
size_t ScanStarted() final; size_t ScanStarted() final;
void UpdateScheduleAfterScan(size_t, base::TimeDelta, size_t) final; void UpdateScheduleAfterScan(size_t, base::TimeDelta, size_t) final;
base::TimeDelta UpdateDelayedSchedule() final; TimeDelta UpdateDelayedSchedule() final;
private: private:
// Limit triggering the scheduler. If `kTargetMutatorUtilizationPercent` is // Limit triggering the scheduler. If `kTargetMutatorUtilizationPercent` is
@ -127,7 +129,7 @@ class BASE_EXPORT MUAwareTaskBasedBackend final
// Callback to schedule a delayed scan. // Callback to schedule a delayed scan.
const ScheduleDelayedScanFunc schedule_delayed_scan_; const ScheduleDelayedScanFunc schedule_delayed_scan_;
Lock scheduler_lock_; PartitionLock scheduler_lock_;
size_t hard_limit_ GUARDED_BY(scheduler_lock_){0}; size_t hard_limit_ GUARDED_BY(scheduler_lock_){0};
base::TimeTicks earliest_next_scan_time_ GUARDED_BY(scheduler_lock_); base::TimeTicks earliest_next_scan_time_ GUARDED_BY(scheduler_lock_);
@ -194,16 +196,7 @@ bool PCScanScheduler::AccountFreed(size_t size) {
backend_->LimitReached(); backend_->LimitReached();
} }
} // namespace partition_alloc::internal } // namespace internal
} // namespace base
// TODO(crbug.com/1288247): Remove these when migration is complete.
namespace base::internal {
using ::partition_alloc::internal::LimitBackend;
using ::partition_alloc::internal::MUAwareTaskBasedBackend;
using ::partition_alloc::internal::PCScanScheduler;
using ::partition_alloc::internal::QuarantineData;
} // namespace base::internal
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_PCSCAN_SCHEDULING_H_ #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_PCSCAN_SCHEDULING_H_

View File

@ -14,7 +14,8 @@
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/rand_util.h" #include "base/rand_util.h"
namespace partition_alloc::internal { namespace base {
namespace internal {
template <typename T> template <typename T>
class RacefulWorklist { class RacefulWorklist {
@ -137,11 +138,6 @@ void RacefulWorklist<T>::RandomizedView::Visit(Function f) {
worklist_.fully_visited_.store(true, std::memory_order_release); worklist_.fully_visited_.store(true, std::memory_order_release);
} }
} // namespace partition_alloc::internal } // namespace internal
} // namespace base
// TODO(crbug.com/1288247): Remove these when migration is complete.
namespace base::internal {
using ::partition_alloc::internal::RacefulWorklist;
}
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_RACEFUL_WORKLIST_H_ #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_RACEFUL_WORKLIST_H_

View File

@ -34,7 +34,8 @@
#include <arm_neon.h> #include <arm_neon.h>
#endif #endif
namespace partition_alloc::internal { namespace base {
namespace internal {
// Iterates over range of memory using the best available SIMD extension. // Iterates over range of memory using the best available SIMD extension.
// Assumes that 64bit platforms have cage support and the begin pointer of // Assumes that 64bit platforms have cage support and the begin pointer of
@ -222,13 +223,7 @@ void ScanLoop<Derived>::RunNEON(uintptr_t begin, uintptr_t end) {
} }
#endif // defined(PA_STARSCAN_NEON_SUPPORTED) #endif // defined(PA_STARSCAN_NEON_SUPPORTED)
} // namespace partition_alloc::internal } // namespace internal
} // namespace base
// TODO(crbug.com/1288247): Remove this when migration is complete.
namespace base::internal {
using ::partition_alloc::internal::ScanLoop;
} // namespace base::internal
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_SCAN_LOOP_H_ #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_SCAN_LOOP_H_

View File

@ -10,7 +10,8 @@
#include "base/allocator/partition_allocator/partition_alloc_check.h" #include "base/allocator/partition_allocator/partition_alloc_check.h"
#include "base/allocator/partition_allocator/starscan/pcscan_internal.h" #include "base/allocator/partition_allocator/starscan/pcscan_internal.h"
namespace partition_alloc::internal { namespace base {
namespace internal {
std::unique_ptr<StarScanSnapshot> StarScanSnapshot::Create( std::unique_ptr<StarScanSnapshot> StarScanSnapshot::Create(
const PCScanInternal& pcscan) { const PCScanInternal& pcscan) {
@ -43,4 +44,5 @@ StarScanSnapshot::StarScanSnapshot(const PCScanInternal& pcscan) {
StarScanSnapshot::~StarScanSnapshot() = default; StarScanSnapshot::~StarScanSnapshot() = default;
} // namespace partition_alloc::internal } // namespace internal
} // namespace base

View File

@ -11,7 +11,10 @@
#include "base/allocator/partition_allocator/starscan/pcscan_internal.h" #include "base/allocator/partition_allocator/starscan/pcscan_internal.h"
#include "base/allocator/partition_allocator/starscan/raceful_worklist.h" #include "base/allocator/partition_allocator/starscan/raceful_worklist.h"
namespace partition_alloc::internal { namespace base {
namespace internal {
class PCScanInternal;
class StarScanSnapshot final : public AllocatedOnPCScanMetadataPartition { class StarScanSnapshot final : public AllocatedOnPCScanMetadataPartition {
public: public:
@ -89,13 +92,7 @@ StarScanSnapshot::SweepingView::SweepingView(StarScanSnapshot& snapshot)
StarScanSnapshot::UnprotectingView::UnprotectingView(StarScanSnapshot& snapshot) StarScanSnapshot::UnprotectingView::UnprotectingView(StarScanSnapshot& snapshot)
: StarScanSnapshot::ViewBase(snapshot.unprotect_worklist_) {} : StarScanSnapshot::ViewBase(snapshot.unprotect_worklist_) {}
} // namespace partition_alloc::internal } // namespace internal
} // namespace base
// TODO(crbug.com/1288247): Remove this when migration is complete.
namespace base::internal {
using ::partition_alloc::internal::StarScanSnapshot;
} // namespace base::internal
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_SNAPSHOT_H_ #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_SNAPSHOT_H_

View File

@ -21,7 +21,8 @@
extern "C" void* __libc_stack_end; extern "C" void* __libc_stack_end;
#endif #endif
namespace partition_alloc::internal { namespace base {
namespace internal {
#if BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_WIN)
@ -143,4 +144,5 @@ void Stack::IteratePointers(StackVisitor* visitor) const {
#endif #endif
} }
} // namespace partition_alloc::internal } // namespace internal
} // namespace base

View File

@ -10,7 +10,8 @@
#include "base/base_export.h" #include "base/base_export.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
namespace partition_alloc::internal { namespace base {
namespace internal {
// Returns the current stack pointer. // Returns the current stack pointer.
// TODO(bikineev,1202644): Remove this once base/stack_util.h lands. // TODO(bikineev,1202644): Remove this once base/stack_util.h lands.
@ -43,16 +44,7 @@ class BASE_EXPORT Stack final {
void* stack_top_; void* stack_top_;
}; };
} // namespace partition_alloc::internal } // namespace internal
} // namespace base
// TODO(crbug.com/1288247): Remove these when migration is complete.
namespace base::internal {
using ::partition_alloc::internal::GetStackPointer;
using ::partition_alloc::internal::GetStackTop;
using ::partition_alloc::internal::Stack;
using ::partition_alloc::internal::StackVisitor;
} // namespace base::internal
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_STACK_STACK_H_ #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_STACK_STACK_H_

View File

@ -7,7 +7,8 @@
#include <cstdint> #include <cstdint>
namespace partition_alloc::internal { namespace base {
namespace internal {
// Defines what thread executes a StarScan task. // Defines what thread executes a StarScan task.
enum class Context { enum class Context {
@ -25,14 +26,7 @@ enum class SimdSupport : uint8_t {
kNEON, kNEON,
}; };
} // namespace partition_alloc::internal } // namespace internal
} // namespace base
// TODO(crbug.com/1288247): Remove these when migration is complete.
namespace base::internal {
using ::partition_alloc::internal::Context;
using ::partition_alloc::internal::SimdSupport;
} // namespace base::internal
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_STARSCAN_FWD_H_ #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_STARSCAN_FWD_H_

View File

@ -15,11 +15,12 @@
#include <tuple> #include <tuple>
#include <utility> #include <utility>
#include "base/allocator/partition_allocator/base/bits.h"
#include "base/allocator/partition_allocator/partition_alloc_check.h" #include "base/allocator/partition_allocator/partition_alloc_check.h"
#include "base/bits.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
namespace partition_alloc::internal { namespace base {
namespace internal {
// Bitmap which tracks allocation states. An allocation can be in one of 3 // Bitmap which tracks allocation states. An allocation can be in one of 3
// states: // states:
@ -69,7 +70,7 @@ class StateBitmap final {
using CellType = uintptr_t; using CellType = uintptr_t;
static constexpr size_t kBitsPerCell = sizeof(CellType) * CHAR_BIT; static constexpr size_t kBitsPerCell = sizeof(CellType) * CHAR_BIT;
static constexpr size_t kBitsNeededForAllocation = static constexpr size_t kBitsNeededForAllocation =
base::bits::Log2Floor(static_cast<size_t>(State::kNumOfStates)); bits::Log2Floor(static_cast<size_t>(State::kNumOfStates));
static constexpr CellType kStateMask = (1 << kBitsNeededForAllocation) - 1; static constexpr CellType kStateMask = (1 << kBitsNeededForAllocation) - 1;
static constexpr size_t kBitmapSize = static constexpr size_t kBitmapSize =
@ -482,6 +483,7 @@ void StateBitmap<PageSize, PageAlignment, AllocationAlignment>::Clear() {
std::fill(bitmap_.begin(), bitmap_.end(), '\0'); std::fill(bitmap_.begin(), bitmap_.end(), '\0');
} }
} // namespace partition_alloc::internal } // namespace internal
} // namespace base
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_STATE_BITMAP_H_ #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_STATE_BITMAP_H_

View File

@ -8,7 +8,8 @@
#include "base/allocator/partition_allocator/starscan/stats_reporter.h" #include "base/allocator/partition_allocator/starscan/stats_reporter.h"
#include "base/time/time.h" #include "base/time/time.h"
namespace partition_alloc::internal { namespace base {
namespace internal {
StatsCollector::StatsCollector(const char* process_name, StatsCollector::StatsCollector(const char* process_name,
size_t quarantine_last_size) size_t quarantine_last_size)
@ -24,8 +25,7 @@ base::TimeDelta StatsCollector::GetOverallTime() const {
ScannerId::kOverall); ScannerId::kOverall);
} }
void StatsCollector::ReportTracesAndHists( void StatsCollector::ReportTracesAndHists(StatsReporter& reporter) const {
partition_alloc::StatsReporter& reporter) const {
ReportTracesAndHistsImpl<Context::kMutator>(reporter, mutator_trace_events_); ReportTracesAndHistsImpl<Context::kMutator>(reporter, mutator_trace_events_);
ReportTracesAndHistsImpl<Context::kScanner>(reporter, scanner_trace_events_); ReportTracesAndHistsImpl<Context::kScanner>(reporter, scanner_trace_events_);
ReportSurvivalRate(reporter); ReportSurvivalRate(reporter);
@ -46,13 +46,13 @@ base::TimeDelta StatsCollector::GetTimeImpl(
template <Context context> template <Context context>
void StatsCollector::ReportTracesAndHistsImpl( void StatsCollector::ReportTracesAndHistsImpl(
partition_alloc::StatsReporter& reporter, StatsReporter& reporter,
const DeferredTraceEventMap<context>& event_map) const { const DeferredTraceEventMap<context>& event_map) const {
std::array<base::TimeDelta, static_cast<size_t>(IdType<context>::kNumIds)> std::array<base::TimeDelta, static_cast<size_t>(IdType<context>::kNumIds)>
accumulated_events{}; accumulated_events{};
// First, report traces and accumulate each trace scope to report UMA hists. // First, report traces and accumulate each trace scope to report UMA hists.
for (const auto& tid_and_events : event_map.get_underlying_map_unsafe()) { for (const auto& tid_and_events : event_map.get_underlying_map_unsafe()) {
const ::base::PlatformThreadId tid = tid_and_events.first; const PlatformThreadId tid = tid_and_events.first;
const auto& events = tid_and_events.second; const auto& events = tid_and_events.second;
PA_DCHECK(accumulated_events.size() == events.size()); PA_DCHECK(accumulated_events.size() == events.size());
for (size_t id = 0; id < events.size(); ++id) { for (size_t id = 0; id < events.size(); ++id) {
@ -79,8 +79,7 @@ void StatsCollector::ReportTracesAndHistsImpl(
} }
} }
void StatsCollector::ReportSurvivalRate( void StatsCollector::ReportSurvivalRate(StatsReporter& reporter) const {
partition_alloc::StatsReporter& reporter) const {
const double survived_rate = const double survived_rate =
static_cast<double>(survived_quarantine_size()) / quarantine_last_size_; static_cast<double>(survived_quarantine_size()) / quarantine_last_size_;
reporter.ReportSurvivedQuarantineSize(survived_quarantine_size()); reporter.ReportSurvivedQuarantineSize(survived_quarantine_size());
@ -102,10 +101,11 @@ template base::TimeDelta StatsCollector::GetTimeImpl(
IdType<Context::kScanner>) const; IdType<Context::kScanner>) const;
template void StatsCollector::ReportTracesAndHistsImpl( template void StatsCollector::ReportTracesAndHistsImpl(
partition_alloc::StatsReporter& reporter, StatsReporter& reporter,
const DeferredTraceEventMap<Context::kMutator>&) const; const DeferredTraceEventMap<Context::kMutator>&) const;
template void StatsCollector::ReportTracesAndHistsImpl( template void StatsCollector::ReportTracesAndHistsImpl(
partition_alloc::StatsReporter& reporter, StatsReporter& reporter,
const DeferredTraceEventMap<Context::kScanner>&) const; const DeferredTraceEventMap<Context::kScanner>&) const;
} // namespace partition_alloc::internal } // namespace internal
} // namespace base

View File

@ -19,7 +19,7 @@
#include "base/threading/platform_thread.h" #include "base/threading/platform_thread.h"
#include "base/time/time.h" #include "base/time/time.h"
namespace partition_alloc { namespace base {
class StatsReporter; class StatsReporter;
@ -74,12 +74,11 @@ class StatsCollector final {
using PerThreadEvents = using PerThreadEvents =
std::array<DeferredTraceEvent, static_cast<size_t>(IdType::kNumIds)>; std::array<DeferredTraceEvent, static_cast<size_t>(IdType::kNumIds)>;
using UnderlyingMap = std::unordered_map< using UnderlyingMap = std::unordered_map<
::base::PlatformThreadId, PlatformThreadId,
PerThreadEvents, PerThreadEvents,
std::hash<::base::PlatformThreadId>, std::hash<PlatformThreadId>,
std::equal_to<>, std::equal_to<>,
MetadataAllocator< MetadataAllocator<std::pair<const PlatformThreadId, PerThreadEvents>>>;
std::pair<const ::base::PlatformThreadId, PerThreadEvents>>>;
inline void RegisterBeginEventFromCurrentThread(IdType id); inline void RegisterBeginEventFromCurrentThread(IdType id);
inline void RegisterEndEventFromCurrentThread(IdType id); inline void RegisterEndEventFromCurrentThread(IdType id);
@ -134,7 +133,7 @@ class StatsCollector final {
} }
base::TimeDelta GetOverallTime() const; base::TimeDelta GetOverallTime() const;
void ReportTracesAndHists(partition_alloc::StatsReporter& reporter) const; void ReportTracesAndHists(StatsReporter& reporter) const;
private: private:
using MetadataString = using MetadataString =
@ -162,10 +161,10 @@ class StatsCollector final {
template <Context context> template <Context context>
void ReportTracesAndHistsImpl( void ReportTracesAndHistsImpl(
partition_alloc::StatsReporter& reporter, StatsReporter& reporter,
const DeferredTraceEventMap<context>& event_map) const; const DeferredTraceEventMap<context>& event_map) const;
void ReportSurvivalRate(partition_alloc::StatsReporter& reporter) const; void ReportSurvivalRate(StatsReporter& reporter) const;
DeferredTraceEventMap<Context::kMutator> mutator_trace_events_; DeferredTraceEventMap<Context::kMutator> mutator_trace_events_;
DeferredTraceEventMap<Context::kScanner> scanner_trace_events_; DeferredTraceEventMap<Context::kScanner> scanner_trace_events_;
@ -243,13 +242,6 @@ inline StatsCollector::MetadataString StatsCollector::ToUMAString(
#undef FOR_ALL_PCSCAN_SCANNER_SCOPES #undef FOR_ALL_PCSCAN_SCANNER_SCOPES
} // namespace internal } // namespace internal
} // namespace partition_alloc } // namespace base
// TODO(crbug.com/1151236): Remove this when migration is complete.
namespace base::internal {
using ::partition_alloc::internal::StatsCollector;
} // namespace base::internal
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_STATS_COLLECTOR_H_ #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_STATS_COLLECTOR_H_

View File

@ -9,7 +9,7 @@
#include "base/threading/platform_thread.h" #include "base/threading/platform_thread.h"
#include "base/time/time.h" #include "base/time/time.h"
namespace partition_alloc { namespace base {
// StatsReporter is a wrapper to invoke TRACE_EVENT_BEGIN/END, TRACE_COUNTER1, // StatsReporter is a wrapper to invoke TRACE_EVENT_BEGIN/END, TRACE_COUNTER1,
// and UmaHistogramTimes. It is used to just remove trace_log and uma // and UmaHistogramTimes. It is used to just remove trace_log and uma
@ -17,21 +17,21 @@ namespace partition_alloc {
class StatsReporter { class StatsReporter {
public: public:
virtual void ReportTraceEvent(internal::StatsCollector::ScannerId id, virtual void ReportTraceEvent(internal::StatsCollector::ScannerId id,
const base::PlatformThreadId tid, const PlatformThreadId tid,
base::TimeTicks start_time, TimeTicks start_time,
base::TimeTicks end_time) {} TimeTicks end_time) {}
virtual void ReportTraceEvent(internal::StatsCollector::MutatorId id, virtual void ReportTraceEvent(internal::StatsCollector::MutatorId id,
const base::PlatformThreadId tid, const PlatformThreadId tid,
base::TimeTicks start_time, TimeTicks start_time,
base::TimeTicks end_time) {} TimeTicks end_time) {}
virtual void ReportSurvivedQuarantineSize(size_t survived_size) {} virtual void ReportSurvivedQuarantineSize(size_t survived_size) {}
virtual void ReportSurvivedQuarantinePercent(double survivied_rate) {} virtual void ReportSurvivedQuarantinePercent(double survivied_rate) {}
virtual void ReportStats(const char* stats_name, base::TimeDelta sample) {} virtual void ReportStats(const char* stats_name, TimeDelta sample) {}
}; };
} // namespace partition_alloc } // namespace base
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_STATS_REPORTER_H_ #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_STATS_REPORTER_H_

View File

@ -25,11 +25,11 @@
#include <sys/types.h> #include <sys/types.h>
#endif // defined(PA_STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED) #endif // defined(PA_STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED)
namespace partition_alloc::internal { namespace base {
namespace internal {
::base::internal::PCScan::ClearType NoWriteProtector::SupportedClearType() PCScan::ClearType NoWriteProtector::SupportedClearType() const {
const { return PCScan::ClearType::kLazy;
return ::base::internal::PCScan::ClearType::kLazy;
} }
#if defined(PA_STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED) #if defined(PA_STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED)
@ -38,7 +38,7 @@ void UserFaultFDThread(int uffd) {
PA_DCHECK(-1 != uffd); PA_DCHECK(-1 != uffd);
static constexpr char kThreadName[] = "PCScanPFHandler"; static constexpr char kThreadName[] = "PCScanPFHandler";
::base::PlatformThread::SetName(kThreadName); base::PlatformThread::SetName(kThreadName);
while (true) { while (true) {
// Pool on the uffd descriptor for page fault events. // Pool on the uffd descriptor for page fault events.
@ -58,7 +58,7 @@ void UserFaultFDThread(int uffd) {
// Enter the safepoint. Concurrent faulted writes will wait until safepoint // Enter the safepoint. Concurrent faulted writes will wait until safepoint
// finishes. // finishes.
::base::internal::PCScan::JoinScanIfNeeded(); PCScan::JoinScanIfNeeded();
} }
} }
} // namespace } // namespace
@ -121,10 +121,8 @@ void UserFaultFDWriteProtector::UnprotectPages(uintptr_t begin, size_t length) {
UserFaultFDWPSet(uffd_, begin, length, UserFaultFDWPMode::kUnprotect); UserFaultFDWPSet(uffd_, begin, length, UserFaultFDWPMode::kUnprotect);
} }
::base::internal::PCScan::ClearType PCScan::ClearType UserFaultFDWriteProtector::SupportedClearType() const {
UserFaultFDWriteProtector::SupportedClearType() const { return IsSupported() ? PCScan::ClearType::kEager : PCScan::ClearType::kLazy;
return IsSupported() ? ::base::internal::PCScan::ClearType::kEager
: ::base::internal::PCScan::ClearType::kLazy;
} }
bool UserFaultFDWriteProtector::IsSupported() const { bool UserFaultFDWriteProtector::IsSupported() const {
@ -133,4 +131,5 @@ bool UserFaultFDWriteProtector::IsSupported() const {
#endif // defined(PA_STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED) #endif // defined(PA_STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED)
} // namespace partition_alloc::internal } // namespace internal
} // namespace base

View File

@ -14,7 +14,8 @@
#include "base/allocator/partition_allocator/starscan/raceful_worklist.h" #include "base/allocator/partition_allocator/starscan/raceful_worklist.h"
#include "build/build_config.h" #include "build/build_config.h"
namespace partition_alloc::internal { namespace base {
namespace internal {
// Interface for page protection/unprotection. This is used in DCScan to catch // Interface for page protection/unprotection. This is used in DCScan to catch
// concurrent mutator writes. Protection is done when the scanner starts // concurrent mutator writes. Protection is done when the scanner starts
@ -28,14 +29,14 @@ class WriteProtector : public AllocatedOnPCScanMetadataPartition {
virtual bool IsEnabled() const = 0; virtual bool IsEnabled() const = 0;
virtual ::base::internal::PCScan::ClearType SupportedClearType() const = 0; virtual PCScan::ClearType SupportedClearType() const = 0;
}; };
class NoWriteProtector final : public WriteProtector { class NoWriteProtector final : public WriteProtector {
public: public:
void ProtectPages(uintptr_t, size_t) final {} void ProtectPages(uintptr_t, size_t) final {}
void UnprotectPages(uintptr_t, size_t) final {} void UnprotectPages(uintptr_t, size_t) final {}
::base::internal::PCScan::ClearType SupportedClearType() const final; PCScan::ClearType SupportedClearType() const final;
inline bool IsEnabled() const override; inline bool IsEnabled() const override;
}; };
@ -55,7 +56,7 @@ class UserFaultFDWriteProtector final : public WriteProtector {
void ProtectPages(uintptr_t, size_t) final; void ProtectPages(uintptr_t, size_t) final;
void UnprotectPages(uintptr_t, size_t) final; void UnprotectPages(uintptr_t, size_t) final;
::base::internal::PCScan::ClearType SupportedClearType() const final; PCScan::ClearType SupportedClearType() const final;
inline bool IsEnabled() const override; inline bool IsEnabled() const override;
@ -71,17 +72,7 @@ bool UserFaultFDWriteProtector::IsEnabled() const {
#endif // defined(PA_STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED) #endif // defined(PA_STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED)
} // namespace partition_alloc::internal } // namespace internal
} // namespace base
// TODO(crbug.com/1288247): Remove these when migration is complete.
namespace base::internal {
using ::partition_alloc::internal::NoWriteProtector;
using ::partition_alloc::internal::WriteProtector;
#if defined(PA_STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED)
using ::partition_alloc::internal::UserFaultFDWriteProtector;
#endif // defined(PA_STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED)
} // namespace base::internal
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_WRITE_PROTECTOR_H_ #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_STARSCAN_WRITE_PROTECTOR_H_

View File

@ -5,7 +5,6 @@
#include "base/allocator/partition_allocator/thread_cache.h" #include "base/allocator/partition_allocator/thread_cache.h"
#include <sys/types.h> #include <sys/types.h>
#include <algorithm> #include <algorithm>
#include <atomic> #include <atomic>
#include <cstdint> #include <cstdint>
@ -21,24 +20,24 @@
#include "base/dcheck_is_on.h" #include "base/dcheck_is_on.h"
#include "build/build_config.h" #include "build/build_config.h"
namespace partition_alloc { namespace base::internal {
namespace { namespace {
ThreadCacheRegistry g_instance; ThreadCacheRegistry g_instance;
} // namespace } // namespace
} // namespace base::internal
namespace tools { namespace partition_alloc::internal::tools {
uintptr_t kThreadCacheNeedleArray[kThreadCacheNeedleArraySize] = { uintptr_t kThreadCacheNeedleArray[kThreadCacheNeedleArraySize] = {
kNeedle1, reinterpret_cast<uintptr_t>(&g_instance), kNeedle1, reinterpret_cast<uintptr_t>(&::base::internal::g_instance),
#if BUILDFLAG(RECORD_ALLOC_INFO) #if BUILDFLAG(RECORD_ALLOC_INFO)
reinterpret_cast<uintptr_t>(&internal::g_allocs), reinterpret_cast<uintptr_t>(&partition_alloc::internal::g_allocs),
#else #else
0, 0,
#endif #endif
kNeedle2}; kNeedle2};
} // namespace tools } // namespace partition_alloc::internal::tools
namespace internal { namespace base::internal {
BASE_EXPORT PartitionTlsKey g_thread_cache_key; BASE_EXPORT PartitionTlsKey g_thread_cache_key;
#if defined(PA_THREAD_CACHE_FAST_TLS) #if defined(PA_THREAD_CACHE_FAST_TLS)
@ -46,8 +45,6 @@ BASE_EXPORT
thread_local ThreadCache* g_thread_cache; thread_local ThreadCache* g_thread_cache;
#endif #endif
} // namespace internal
namespace { namespace {
// Since |g_thread_cache_key| is shared, make sure that no more than one // Since |g_thread_cache_key| is shared, make sure that no more than one
// PartitionRoot can use it. // PartitionRoot can use it.
@ -77,7 +74,7 @@ uint8_t ThreadCache::global_limits_[ThreadCache::kBucketCount];
// Start with the normal size, not the maximum one. // Start with the normal size, not the maximum one.
uint16_t ThreadCache::largest_active_bucket_index_ = uint16_t ThreadCache::largest_active_bucket_index_ =
internal::BucketIndexLookup::GetIndex(ThreadCache::kDefaultSizeThreshold); BucketIndexLookup::GetIndex(ThreadCache::kDefaultSizeThreshold);
// static // static
ThreadCacheRegistry& ThreadCacheRegistry::Instance() { ThreadCacheRegistry& ThreadCacheRegistry::Instance() {
@ -85,7 +82,7 @@ ThreadCacheRegistry& ThreadCacheRegistry::Instance() {
} }
void ThreadCacheRegistry::RegisterThreadCache(ThreadCache* cache) { void ThreadCacheRegistry::RegisterThreadCache(ThreadCache* cache) {
internal::ScopedGuard scoped_locker(GetLock()); PartitionAutoLock scoped_locker(GetLock());
cache->next_ = nullptr; cache->next_ = nullptr;
cache->prev_ = nullptr; cache->prev_ = nullptr;
@ -97,7 +94,7 @@ void ThreadCacheRegistry::RegisterThreadCache(ThreadCache* cache) {
} }
void ThreadCacheRegistry::UnregisterThreadCache(ThreadCache* cache) { void ThreadCacheRegistry::UnregisterThreadCache(ThreadCache* cache) {
internal::ScopedGuard scoped_locker(GetLock()); PartitionAutoLock scoped_locker(GetLock());
if (cache->prev_) if (cache->prev_)
cache->prev_->next_ = cache->next_; cache->prev_->next_ = cache->next_;
if (cache->next_) if (cache->next_)
@ -111,7 +108,7 @@ void ThreadCacheRegistry::DumpStats(bool my_thread_only,
ThreadCache::EnsureThreadSpecificDataInitialized(); ThreadCache::EnsureThreadSpecificDataInitialized();
memset(reinterpret_cast<void*>(stats), 0, sizeof(ThreadCacheStats)); memset(reinterpret_cast<void*>(stats), 0, sizeof(ThreadCacheStats));
internal::ScopedGuard scoped_locker(GetLock()); PartitionAutoLock scoped_locker(GetLock());
if (my_thread_only) { if (my_thread_only) {
auto* tcache = ThreadCache::Get(); auto* tcache = ThreadCache::Get();
if (!ThreadCache::IsValid(tcache)) if (!ThreadCache::IsValid(tcache))
@ -149,7 +146,7 @@ void ThreadCacheRegistry::PurgeAll() {
current_thread_tcache->Purge(); current_thread_tcache->Purge();
{ {
internal::ScopedGuard scoped_locker(GetLock()); PartitionAutoLock scoped_locker(GetLock());
ThreadCache* tcache = list_head_; ThreadCache* tcache = list_head_;
while (tcache) { while (tcache) {
PA_DCHECK(ThreadCache::IsValid(tcache)); PA_DCHECK(ThreadCache::IsValid(tcache));
@ -165,7 +162,7 @@ void ThreadCacheRegistry::PurgeAll() {
} }
void ThreadCacheRegistry::ForcePurgeAllThreadAfterForkUnsafe() { void ThreadCacheRegistry::ForcePurgeAllThreadAfterForkUnsafe() {
internal::ScopedGuard scoped_locker(GetLock()); PartitionAutoLock scoped_locker(GetLock());
ThreadCache* tcache = list_head_; ThreadCache* tcache = list_head_;
while (tcache) { while (tcache) {
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
@ -189,13 +186,7 @@ void ThreadCacheRegistry::ForcePurgeAllThreadAfterForkUnsafe() {
// passes. See crbug.com/1216964. // passes. See crbug.com/1216964.
tcache->cached_memory_ = tcache->CachedMemory(); tcache->cached_memory_ = tcache->CachedMemory();
// At this point, we should call |TryPurge|. However, due to the thread tcache->TryPurge();
// cache being possibly inconsistent at this point, this may crash. Rather
// than crash, we'd prefer to simply not purge, even though this may leak
// memory in some cases.
//
// see crbug.com/1289092 for details of the crashes.
tcache = tcache->next_; tcache = tcache->next_;
} }
} }
@ -210,7 +201,7 @@ void ThreadCacheRegistry::SetThreadCacheMultiplier(float multiplier) {
// - Set the global limits, which will affect newly created threads. // - Set the global limits, which will affect newly created threads.
// - Enumerate all thread caches and set the limit to the global one. // - Enumerate all thread caches and set the limit to the global one.
{ {
internal::ScopedGuard scoped_locker(GetLock()); PartitionAutoLock scoped_locker(GetLock());
ThreadCache* tcache = list_head_; ThreadCache* tcache = list_head_;
// If this is called before *any* thread cache has serviced *any* // If this is called before *any* thread cache has serviced *any*
@ -250,7 +241,7 @@ void ThreadCacheRegistry::RunPeriodicPurge() {
// which is fine. // which is fine.
size_t cached_memory_approx = 0; size_t cached_memory_approx = 0;
{ {
internal::ScopedGuard scoped_locker(GetLock()); PartitionAutoLock scoped_locker(GetLock());
ThreadCache* tcache = list_head_; ThreadCache* tcache = list_head_;
// Can run when there is no thread cache, in which case there is nothing to // Can run when there is no thread cache, in which case there is nothing to
// do, and the task should not be rescheduled. This would typically indicate // do, and the task should not be rescheduled. This would typically indicate
@ -313,12 +304,11 @@ void ThreadCacheRegistry::ResetForTesting() {
void ThreadCache::EnsureThreadSpecificDataInitialized() { void ThreadCache::EnsureThreadSpecificDataInitialized() {
// Using the registry lock to protect from concurrent initialization without // Using the registry lock to protect from concurrent initialization without
// adding a special-pupose lock. // adding a special-pupose lock.
internal::ScopedGuard scoped_locker( PartitionAutoLock scoped_locker(ThreadCacheRegistry::Instance().GetLock());
ThreadCacheRegistry::Instance().GetLock());
if (g_thread_cache_key_created) if (g_thread_cache_key_created)
return; return;
bool ok = internal::PartitionTlsCreate(&internal::g_thread_cache_key, Delete); bool ok = PartitionTlsCreate(&g_thread_cache_key, Delete);
PA_CHECK(ok); PA_CHECK(ok);
g_thread_cache_key_created = true; g_thread_cache_key_created = true;
} }
@ -340,7 +330,7 @@ void ThreadCache::SwapForTesting(PartitionRoot<>* root) {
} else { } else {
#if BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_WIN)
// OnDllProcessDetach accesses g_thread_cache_root which is nullptr now. // OnDllProcessDetach accesses g_thread_cache_root which is nullptr now.
internal::PartitionTlsSetOnDllProcessDetach(nullptr); PartitionTlsSetOnDllProcessDetach(nullptr);
#endif #endif
} }
} }
@ -348,7 +338,7 @@ void ThreadCache::SwapForTesting(PartitionRoot<>* root) {
// static // static
void ThreadCache::RemoveTombstoneForTesting() { void ThreadCache::RemoveTombstoneForTesting() {
PA_CHECK(IsTombstone(Get())); PA_CHECK(IsTombstone(Get()));
internal::PartitionTlsSet(internal::g_thread_cache_key, nullptr); PartitionTlsSet(g_thread_cache_key, nullptr);
} }
// static // static
@ -373,7 +363,7 @@ void ThreadCache::Init(PartitionRoot<>* root) {
} }
#if BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_WIN)
internal::PartitionTlsSetOnDllProcessDetach(OnDllProcessDetach); PartitionTlsSetOnDllProcessDetach(OnDllProcessDetach);
#endif #endif
SetGlobalLimits(root, kDefaultMultiplier); SetGlobalLimits(root, kDefaultMultiplier);
@ -434,7 +424,8 @@ ThreadCache* ThreadCache::Create(PartitionRoot<internal::ThreadSafe>* root) {
PA_CHECK(root); PA_CHECK(root);
// See comment in thread_cache.h, this is used to make sure // See comment in thread_cache.h, this is used to make sure
// kThreadCacheNeedleArray is kept in the final binary. // kThreadCacheNeedleArray is kept in the final binary.
PA_CHECK(tools::kThreadCacheNeedleArray[0] == tools::kNeedle1); PA_CHECK(partition_alloc::internal::tools::kThreadCacheNeedleArray[0] ==
partition_alloc::internal::tools::kNeedle1);
// Placement new and RawAlloc() are used, as otherwise when this partition is // Placement new and RawAlloc() are used, as otherwise when this partition is
// the malloc() implementation, the memory allocated for the new thread cache // the malloc() implementation, the memory allocated for the new thread cache
@ -449,13 +440,13 @@ ThreadCache* ThreadCache::Create(PartitionRoot<internal::ThreadSafe>* root) {
auto* bucket = auto* bucket =
root->buckets + PartitionRoot<internal::ThreadSafe>::SizeToBucketIndex( root->buckets + PartitionRoot<internal::ThreadSafe>::SizeToBucketIndex(
raw_size, root->with_denser_bucket_distribution); raw_size, root->with_denser_bucket_distribution);
uintptr_t buffer = root->RawAlloc(bucket, AllocFlags::kZeroFill, raw_size, uintptr_t buffer =
internal::PartitionPageSize(), &usable_size, root->RawAlloc(bucket, AllocFlags::kZeroFill, raw_size,
&already_zeroed); PartitionPageSize(), &usable_size, &already_zeroed);
ThreadCache* tcache = new (reinterpret_cast<void*>(buffer)) ThreadCache(root); ThreadCache* tcache = new (reinterpret_cast<void*>(buffer)) ThreadCache(root);
// This may allocate. // This may allocate.
internal::PartitionTlsSet(internal::g_thread_cache_key, tcache); PartitionTlsSet(g_thread_cache_key, tcache);
#if defined(PA_THREAD_CACHE_FAST_TLS) #if defined(PA_THREAD_CACHE_FAST_TLS)
// |thread_local| variables with destructors cause issues on some platforms. // |thread_local| variables with destructors cause issues on some platforms.
// Since we need a destructor (to empty the thread cache), we cannot use it // Since we need a destructor (to empty the thread cache), we cannot use it
@ -466,7 +457,7 @@ ThreadCache* ThreadCache::Create(PartitionRoot<internal::ThreadSafe>* root) {
// //
// To still get good performance, use |thread_local| to store a raw pointer, // To still get good performance, use |thread_local| to store a raw pointer,
// and rely on the platform TLS to call the destructor. // and rely on the platform TLS to call the destructor.
internal::g_thread_cache = tcache; g_thread_cache = tcache;
#endif // defined(PA_THREAD_CACHE_FAST_TLS) #endif // defined(PA_THREAD_CACHE_FAST_TLS)
return tcache; return tcache;
@ -475,7 +466,7 @@ ThreadCache* ThreadCache::Create(PartitionRoot<internal::ThreadSafe>* root) {
ThreadCache::ThreadCache(PartitionRoot<>* root) ThreadCache::ThreadCache(PartitionRoot<>* root)
: should_purge_(false), : should_purge_(false),
root_(root), root_(root),
thread_id_(base::PlatformThread::CurrentId()), thread_id_(PlatformThread::CurrentId()),
next_(nullptr), next_(nullptr),
prev_(nullptr) { prev_(nullptr) {
ThreadCacheRegistry::Instance().RegisterThreadCache(this); ThreadCacheRegistry::Instance().RegisterThreadCache(this);
@ -512,9 +503,9 @@ void ThreadCache::Delete(void* tcache_ptr) {
return; return;
#if defined(PA_THREAD_CACHE_FAST_TLS) #if defined(PA_THREAD_CACHE_FAST_TLS)
internal::g_thread_cache = nullptr; g_thread_cache = nullptr;
#else #else
internal::PartitionTlsSet(internal::g_thread_cache_key, nullptr); PartitionTlsSet(g_thread_cache_key, nullptr);
#endif #endif
auto* root = tcache->root_; auto* root = tcache->root_;
@ -526,10 +517,9 @@ void ThreadCache::Delete(void* tcache_ptr) {
// they don't resurrect the thread cache. // they don't resurrect the thread cache.
// //
// TODO(lizeb): Investigate whether this is needed on POSIX as well. // TODO(lizeb): Investigate whether this is needed on POSIX as well.
internal::PartitionTlsSet(internal::g_thread_cache_key, PartitionTlsSet(g_thread_cache_key, reinterpret_cast<void*>(kTombstone));
reinterpret_cast<void*>(kTombstone));
#if defined(PA_THREAD_CACHE_FAST_TLS) #if defined(PA_THREAD_CACHE_FAST_TLS)
internal::g_thread_cache = reinterpret_cast<ThreadCache*>(kTombstone); g_thread_cache = reinterpret_cast<ThreadCache*>(kTombstone);
#endif #endif
#endif // BUILDFLAG(IS_WIN) #endif // BUILDFLAG(IS_WIN)
@ -567,7 +557,7 @@ void ThreadCache::FillBucket(size_t bucket_index) {
// clearing which would greatly increase calls to the central allocator. (3) // clearing which would greatly increase calls to the central allocator. (3)
// tries to keep memory usage low. So clearing half of the bucket, and filling // tries to keep memory usage low. So clearing half of the bucket, and filling
// a quarter of it are sensible defaults. // a quarter of it are sensible defaults.
PA_INCREMENT_COUNTER(stats_.batch_fill_count); INCREMENT_COUNTER(stats_.batch_fill_count);
Bucket& bucket = buckets_[bucket_index]; Bucket& bucket = buckets_[bucket_index];
// Some buckets may have a limit lower than |kBatchFillRatio|, but we still // Some buckets may have a limit lower than |kBatchFillRatio|, but we still
@ -587,7 +577,7 @@ void ThreadCache::FillBucket(size_t bucket_index) {
size_t allocated_slots = 0; size_t allocated_slots = 0;
// Same as calling RawAlloc() |count| times, but acquires the lock only once. // Same as calling RawAlloc() |count| times, but acquires the lock only once.
internal::ScopedGuard guard(root_->lock_); ::partition_alloc::internal::ScopedGuard guard(root_->lock_);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
// Thread cache fill should not trigger expensive operations, to not grab // Thread cache fill should not trigger expensive operations, to not grab
// the lock for a long time needlessly, but also to not inflate memory // the lock for a long time needlessly, but also to not inflate memory
@ -602,7 +592,7 @@ void ThreadCache::FillBucket(size_t bucket_index) {
&root_->buckets[bucket_index], &root_->buckets[bucket_index],
AllocFlags::kFastPathOrReturnNull | AllocFlags::kReturnNull, AllocFlags::kFastPathOrReturnNull | AllocFlags::kReturnNull,
root_->buckets[bucket_index].slot_size /* raw_size */, root_->buckets[bucket_index].slot_size /* raw_size */,
internal::PartitionPageSize(), &usable_size, &is_already_zeroed); PartitionPageSize(), &usable_size, &is_already_zeroed);
// Either the previous allocation would require a slow path allocation, or // Either the previous allocation would require a slow path allocation, or
// the central allocator is out of memory. If the bucket was filled with // the central allocator is out of memory. If the bucket was filled with
@ -672,12 +662,11 @@ void ThreadCache::ClearBucketHelper(Bucket& bucket, size_t limit) {
} }
template <bool crash_on_corruption> template <bool crash_on_corruption>
void ThreadCache::FreeAfter(internal::PartitionFreelistEntry* head, void ThreadCache::FreeAfter(PartitionFreelistEntry* head, size_t slot_size) {
size_t slot_size) {
// Acquire the lock once. Deallocation from the same bucket are likely to be // Acquire the lock once. Deallocation from the same bucket are likely to be
// hitting the same cache lines in the central allocator, and lock // hitting the same cache lines in the central allocator, and lock
// acquisitions can be expensive. // acquisitions can be expensive.
internal::ScopedGuard guard(root_->lock_); ::partition_alloc::internal::ScopedGuard guard(root_->lock_);
while (head) { while (head) {
uintptr_t slot_start = reinterpret_cast<uintptr_t>(head); uintptr_t slot_start = reinterpret_cast<uintptr_t>(head);
head = head->GetNextForThreadCache<crash_on_corruption>(slot_size); head = head->GetNextForThreadCache<crash_on_corruption>(slot_size);
@ -730,7 +719,7 @@ void ThreadCache::AccumulateStats(ThreadCacheStats* stats) const {
stats->batch_fill_count += stats_.batch_fill_count; stats->batch_fill_count += stats_.batch_fill_count;
#if defined(PA_THREAD_CACHE_ALLOC_STATS) #if defined(PA_THREAD_CACHE_ALLOC_STATS)
for (size_t i = 0; i < internal::kNumBuckets + 1; i++) for (size_t i = 0; i < kNumBuckets + 1; i++)
stats->allocs_per_bucket_[i] += stats_.allocs_per_bucket_[i]; stats->allocs_per_bucket_[i] += stats_.allocs_per_bucket_[i];
#endif // defined(PA_THREAD_CACHE_ALLOC_STATS) #endif // defined(PA_THREAD_CACHE_ALLOC_STATS)
@ -781,4 +770,4 @@ void ThreadCache::PurgeInternalHelper() {
ClearBucketHelper<crash_on_corruption>(bucket, 0); ClearBucketHelper<crash_on_corruption>(bucket, 0);
} }
} // namespace partition_alloc } // namespace base::internal

View File

@ -18,21 +18,18 @@
#include "base/allocator/partition_allocator/partition_stats.h" #include "base/allocator/partition_allocator/partition_stats.h"
#include "base/allocator/partition_allocator/partition_tls.h" #include "base/allocator/partition_allocator/partition_tls.h"
#include "base/base_export.h" #include "base/base_export.h"
#include "base/callback.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/dcheck_is_on.h" #include "base/dcheck_is_on.h"
#include "base/gtest_prod_util.h" #include "base/gtest_prod_util.h"
#include "base/time/time.h" #include "base/no_destructor.h"
#include "build/build_config.h" #include "build/build_config.h"
#if defined(ARCH_CPU_X86_64) && defined(PA_HAS_64_BITS_POINTERS) #if defined(ARCH_CPU_X86_64) && defined(PA_HAS_64_BITS_POINTERS)
#include <algorithm> #include <algorithm>
#endif #endif
namespace partition_alloc { namespace partition_alloc::internal::tools {
class ThreadCache;
namespace tools {
// This is used from ThreadCacheInspector, which runs in a different process. It // This is used from ThreadCacheInspector, which runs in a different process. It
// scans the process memory looking for the two needles, to locate the thread // scans the process memory looking for the two needles, to locate the thread
@ -59,13 +56,16 @@ constexpr uintptr_t kNeedle2 = 0x9615ee1c;
constexpr size_t kThreadCacheNeedleArraySize = 4; constexpr size_t kThreadCacheNeedleArraySize = 4;
extern uintptr_t kThreadCacheNeedleArray[kThreadCacheNeedleArraySize]; extern uintptr_t kThreadCacheNeedleArray[kThreadCacheNeedleArraySize];
class HeapDumper;
class ThreadCacheInspector; class ThreadCacheInspector;
} // namespace tools } // namespace partition_alloc::internal::tools
namespace base {
namespace internal { namespace internal {
class ThreadCache;
extern BASE_EXPORT PartitionTlsKey g_thread_cache_key; extern BASE_EXPORT PartitionTlsKey g_thread_cache_key;
// On Android, we have to go through emutls, since this is always a shared // On Android, we have to go through emutls, since this is always a shared
// library, so don't bother. // library, so don't bother.
@ -77,8 +77,6 @@ extern BASE_EXPORT PartitionTlsKey g_thread_cache_key;
extern BASE_EXPORT thread_local ThreadCache* g_thread_cache; extern BASE_EXPORT thread_local ThreadCache* g_thread_cache;
#endif #endif
} // namespace internal
struct ThreadCacheLimits { struct ThreadCacheLimits {
// When trying to conserve memory, set the thread cache limit to this. // When trying to conserve memory, set the thread cache limit to this.
static constexpr size_t kDefaultSizeThreshold = 512; static constexpr size_t kDefaultSizeThreshold = 512;
@ -136,25 +134,23 @@ class BASE_EXPORT ThreadCacheRegistry {
void SetThreadCacheMultiplier(float multiplier); void SetThreadCacheMultiplier(float multiplier);
void SetLargestActiveBucketIndex(uint8_t largest_active_bucket_index); void SetLargestActiveBucketIndex(uint8_t largest_active_bucket_index);
static internal::Lock& GetLock() { return Instance().lock_; } static PartitionLock& GetLock() { return Instance().lock_; }
// Purges all thread caches *now*. This is completely thread-unsafe, and // Purges all thread caches *now*. This is completely thread-unsafe, and
// should only be called in a post-fork() handler. // should only be called in a post-fork() handler.
void ForcePurgeAllThreadAfterForkUnsafe(); void ForcePurgeAllThreadAfterForkUnsafe();
void ResetForTesting(); void ResetForTesting();
static constexpr base::TimeDelta kMinPurgeInterval = base::Seconds(1); static constexpr TimeDelta kMinPurgeInterval = Seconds(1);
static constexpr base::TimeDelta kMaxPurgeInterval = base::Minutes(1); static constexpr TimeDelta kMaxPurgeInterval = Minutes(1);
static constexpr base::TimeDelta kDefaultPurgeInterval = static constexpr TimeDelta kDefaultPurgeInterval = 2 * kMinPurgeInterval;
2 * kMinPurgeInterval;
static constexpr size_t kMinCachedMemoryForPurging = 500 * 1024; static constexpr size_t kMinCachedMemoryForPurging = 500 * 1024;
private: private:
friend class tools::ThreadCacheInspector; friend class partition_alloc::internal::tools::ThreadCacheInspector;
friend class tools::HeapDumper; friend class NoDestructor<ThreadCacheRegistry>;
// Not using base::Lock as the object's constructor must be constexpr. // Not using base::Lock as the object's constructor must be constexpr.
internal::Lock lock_; PartitionLock lock_;
ThreadCache* list_head_ GUARDED_BY(GetLock()) = nullptr; ThreadCache* list_head_ GUARDED_BY(GetLock()) = nullptr;
bool periodic_purge_is_initialized_ = false; bool periodic_purge_is_initialized_ = false;
base::TimeDelta periodic_purge_next_interval_ = kDefaultPurgeInterval; base::TimeDelta periodic_purge_next_interval_ = kDefaultPurgeInterval;
@ -164,25 +160,24 @@ class BASE_EXPORT ThreadCacheRegistry {
// understand enough constexpr to handle the code below. // understand enough constexpr to handle the code below.
uint8_t largest_active_bucket_index_ = 1; uint8_t largest_active_bucket_index_ = 1;
#else #else
uint8_t largest_active_bucket_index_ = internal::BucketIndexLookup::GetIndex( uint8_t largest_active_bucket_index_ =
ThreadCacheLimits::kDefaultSizeThreshold); BucketIndexLookup::GetIndex(ThreadCacheLimits::kDefaultSizeThreshold);
#endif #endif
}; };
constexpr ThreadCacheRegistry::ThreadCacheRegistry() = default; constexpr ThreadCacheRegistry::ThreadCacheRegistry() = default;
#if defined(PA_THREAD_CACHE_ENABLE_STATISTICS) #if defined(PA_THREAD_CACHE_ENABLE_STATISTICS)
#define PA_INCREMENT_COUNTER(counter) ++counter #define INCREMENT_COUNTER(counter) ++counter
#define GET_COUNTER(counter) counter
#else #else
#define PA_INCREMENT_COUNTER(counter) \ #define INCREMENT_COUNTER(counter) \
do { \ do { \
} while (0) } while (0)
#define GET_COUNTER(counter) 0
#endif // defined(PA_THREAD_CACHE_ENABLE_STATISTICS) #endif // defined(PA_THREAD_CACHE_ENABLE_STATISTICS)
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
namespace internal {
class ReentrancyGuard { class ReentrancyGuard {
public: public:
explicit ReentrancyGuard(bool& flag) : flag_(flag) { explicit ReentrancyGuard(bool& flag) : flag_(flag) {
@ -196,12 +191,10 @@ class ReentrancyGuard {
bool& flag_; bool& flag_;
}; };
} // namespace internal
#define PA_REENTRANCY_GUARD(x) \ #define PA_REENTRANCY_GUARD(x) \
internal::ReentrancyGuard guard { x } ReentrancyGuard guard { x }
#else // DCHECK_IS_ON() #else
#define PA_REENTRANCY_GUARD(x) \ #define PA_REENTRANCY_GUARD(x) \
do { \ do { \
@ -239,10 +232,9 @@ class BASE_EXPORT ThreadCache {
static ThreadCache* Get() { static ThreadCache* Get() {
#if defined(PA_THREAD_CACHE_FAST_TLS) #if defined(PA_THREAD_CACHE_FAST_TLS)
return internal::g_thread_cache; return g_thread_cache;
#else #else
return reinterpret_cast<ThreadCache*>( return reinterpret_cast<ThreadCache*>(PartitionTlsGet(g_thread_cache_key));
internal::PartitionTlsGet(internal::g_thread_cache_key));
#endif #endif
} }
@ -306,7 +298,7 @@ class BASE_EXPORT ThreadCache {
return buckets_[index].count; return buckets_[index].count;
} }
base::PlatformThreadId thread_id() const { return thread_id_; } PlatformThreadId thread_id() const { return thread_id_; }
// Sets the maximum size of allocations that may be cached by the thread // Sets the maximum size of allocations that may be cached by the thread
// cache. This applies to all threads. However, the maximum size is bounded by // cache. This applies to all threads. However, the maximum size is bounded by
@ -327,11 +319,10 @@ class BASE_EXPORT ThreadCache {
ThreadCacheLimits::kLargeSizeThreshold; ThreadCacheLimits::kLargeSizeThreshold;
private: private:
friend class tools::HeapDumper; friend class partition_alloc::internal::tools::ThreadCacheInspector;
friend class tools::ThreadCacheInspector;
struct Bucket { struct Bucket {
internal::PartitionFreelistEntry* freelist_head = nullptr; PartitionFreelistEntry* freelist_head = nullptr;
// Want to keep sizeof(Bucket) small, using small types. // Want to keep sizeof(Bucket) small, using small types.
uint8_t count = 0; uint8_t count = 0;
std::atomic<uint8_t> limit{}; // Can be changed from another thread. std::atomic<uint8_t> limit{}; // Can be changed from another thread.
@ -358,7 +349,7 @@ class BASE_EXPORT ThreadCache {
void ResetForTesting(); void ResetForTesting();
// Releases the entire freelist starting at |head| to the root. // Releases the entire freelist starting at |head| to the root.
template <bool crash_on_corruption> template <bool crash_on_corruption>
void FreeAfter(internal::PartitionFreelistEntry* head, size_t slot_size); void FreeAfter(PartitionFreelistEntry* head, size_t slot_size);
static void SetGlobalLimits(PartitionRoot<>* root, float multiplier); static void SetGlobalLimits(PartitionRoot<>* root, float multiplier);
#if BUILDFLAG(IS_NACL) #if BUILDFLAG(IS_NACL)
@ -371,7 +362,7 @@ class BASE_EXPORT ThreadCache {
1; 1;
#endif #endif
static_assert( static_assert(
kBucketCount < internal::kNumBuckets, kBucketCount < kNumBuckets,
"Cannot have more cached buckets than what the allocator supports"); "Cannot have more cached buckets than what the allocator supports");
// On some architectures, ThreadCache::Get() can be called and return // On some architectures, ThreadCache::Get() can be called and return
@ -405,7 +396,7 @@ class BASE_EXPORT ThreadCache {
// Cold data below. // Cold data below.
PartitionRoot<>* const root_; PartitionRoot<>* const root_;
const base::PlatformThreadId thread_id_; const PlatformThreadId thread_id_;
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
bool is_in_thread_cache_ = false; bool is_in_thread_cache_ = false;
#endif #endif
@ -417,7 +408,7 @@ class BASE_EXPORT ThreadCache {
friend class ThreadCacheRegistry; friend class ThreadCacheRegistry;
friend class PartitionAllocThreadCacheTest; friend class PartitionAllocThreadCacheTest;
friend class tools::ThreadCacheInspector; friend class partition_alloc::internal::tools::ThreadCacheInspector;
FRIEND_TEST_ALL_PREFIXES(PartitionAllocThreadCacheTest, Simple); FRIEND_TEST_ALL_PREFIXES(PartitionAllocThreadCacheTest, Simple);
FRIEND_TEST_ALL_PREFIXES(PartitionAllocThreadCacheTest, FRIEND_TEST_ALL_PREFIXES(PartitionAllocThreadCacheTest,
MultipleObjectsCachedPerBucket); MultipleObjectsCachedPerBucket);
@ -443,10 +434,10 @@ class BASE_EXPORT ThreadCache {
ALWAYS_INLINE bool ThreadCache::MaybePutInCache(uintptr_t slot_start, ALWAYS_INLINE bool ThreadCache::MaybePutInCache(uintptr_t slot_start,
size_t bucket_index) { size_t bucket_index) {
PA_REENTRANCY_GUARD(is_in_thread_cache_); PA_REENTRANCY_GUARD(is_in_thread_cache_);
PA_INCREMENT_COUNTER(stats_.cache_fill_count); INCREMENT_COUNTER(stats_.cache_fill_count);
if (UNLIKELY(bucket_index > largest_active_bucket_index_)) { if (UNLIKELY(bucket_index > largest_active_bucket_index_)) {
PA_INCREMENT_COUNTER(stats_.cache_fill_misses); INCREMENT_COUNTER(stats_.cache_fill_misses);
return false; return false;
} }
@ -456,7 +447,7 @@ ALWAYS_INLINE bool ThreadCache::MaybePutInCache(uintptr_t slot_start,
PutInBucket(bucket, slot_start); PutInBucket(bucket, slot_start);
cached_memory_ += bucket.slot_size; cached_memory_ += bucket.slot_size;
PA_INCREMENT_COUNTER(stats_.cache_fill_hits); INCREMENT_COUNTER(stats_.cache_fill_hits);
// Relaxed ordering: we don't care about having an up-to-date or consistent // Relaxed ordering: we don't care about having an up-to-date or consistent
// value, just want it to not change while we are using it, hence using // value, just want it to not change while we are using it, hence using
@ -481,21 +472,21 @@ ALWAYS_INLINE uintptr_t ThreadCache::GetFromCache(size_t bucket_index,
#endif #endif
PA_REENTRANCY_GUARD(is_in_thread_cache_); PA_REENTRANCY_GUARD(is_in_thread_cache_);
PA_INCREMENT_COUNTER(stats_.alloc_count); INCREMENT_COUNTER(stats_.alloc_count);
// Only handle "small" allocations. // Only handle "small" allocations.
if (UNLIKELY(bucket_index > largest_active_bucket_index_)) { if (UNLIKELY(bucket_index > largest_active_bucket_index_)) {
PA_INCREMENT_COUNTER(stats_.alloc_miss_too_large); INCREMENT_COUNTER(stats_.alloc_miss_too_large);
PA_INCREMENT_COUNTER(stats_.alloc_misses); INCREMENT_COUNTER(stats_.alloc_misses);
return 0; return 0;
} }
auto& bucket = buckets_[bucket_index]; auto& bucket = buckets_[bucket_index];
if (LIKELY(bucket.freelist_head)) { if (LIKELY(bucket.freelist_head)) {
PA_INCREMENT_COUNTER(stats_.alloc_hits); INCREMENT_COUNTER(stats_.alloc_hits);
} else { } else {
PA_DCHECK(bucket.count == 0); PA_DCHECK(bucket.count == 0);
PA_INCREMENT_COUNTER(stats_.alloc_miss_empty); INCREMENT_COUNTER(stats_.alloc_miss_empty);
PA_INCREMENT_COUNTER(stats_.alloc_misses); INCREMENT_COUNTER(stats_.alloc_misses);
FillBucket(bucket_index); FillBucket(bucket_index);
@ -539,12 +530,12 @@ ALWAYS_INLINE void ThreadCache::PutInBucket(Bucket& bucket,
// Here, only poison the current cacheline, which we are touching anyway. // Here, only poison the current cacheline, which we are touching anyway.
// TODO(lizeb): Make sure this does not hurt performance. // TODO(lizeb): Make sure this does not hurt performance.
// Everything below requires this alignment. // Everything below requires this aligment.
static_assert(internal::kAlignment == 16, ""); static_assert(kAlignment == 16, "");
#if HAS_BUILTIN(__builtin_assume_aligned) #if HAS_BUILTIN(__builtin_assume_aligned)
uintptr_t address = reinterpret_cast<uintptr_t>(__builtin_assume_aligned( uintptr_t address = reinterpret_cast<uintptr_t>(__builtin_assume_aligned(
reinterpret_cast<void*>(slot_start), internal::kAlignment)); reinterpret_cast<void*>(slot_start), kAlignment));
#else #else
uintptr_t address = slot_start; uintptr_t address = slot_start;
#endif #endif
@ -553,7 +544,7 @@ ALWAYS_INLINE void ThreadCache::PutInBucket(Bucket& bucket,
// % 16. Its distance to the next cacheline is 64 - ((address & 63) / 16) * // % 16. Its distance to the next cacheline is 64 - ((address & 63) / 16) *
// 16. // 16.
static_assert( static_assert(
internal::kPartitionCachelineSize == 64, kPartitionCachelineSize == 64,
"The computation below assumes that cache lines are 64 bytes long."); "The computation below assumes that cache lines are 64 bytes long.");
int distance_to_next_cacheline_in_16_bytes = 4 - ((address >> 4) & 3); int distance_to_next_cacheline_in_16_bytes = 4 - ((address >> 4) & 3);
int slot_size_remaining_in_16_bytes = int slot_size_remaining_in_16_bytes =
@ -581,21 +572,21 @@ ALWAYS_INLINE void ThreadCache::PutInBucket(Bucket& bucket,
#endif // defined(PA_HAS_FREELIST_SHADOW_ENTRY) && defined(ARCH_CPU_X86_64) && #endif // defined(PA_HAS_FREELIST_SHADOW_ENTRY) && defined(ARCH_CPU_X86_64) &&
// defined(PA_HAS_64_BITS_POINTERS) // defined(PA_HAS_64_BITS_POINTERS)
auto* entry = internal::PartitionFreelistEntry::EmplaceAndInitForThreadCache( auto* entry = PartitionFreelistEntry::EmplaceAndInitForThreadCache(
slot_start, bucket.freelist_head); slot_start, bucket.freelist_head);
bucket.freelist_head = entry; bucket.freelist_head = entry;
bucket.count++; bucket.count++;
} }
} // namespace partition_alloc } // namespace internal
} // namespace base
namespace base::internal { namespace partition_alloc::internal {
// TODO(https://crbug.com/1288247): Remove these 'using' declarations once // TODO(https://crbug.com/1288247): Remove these 'using' declarations once
// the migration to the new namespaces gets done. // the migration to the new namespaces gets done.
using ::partition_alloc::ThreadCache; using ::base::internal::ThreadCache;
using ::partition_alloc::ThreadCacheRegistry;
} // namespace base::internal } // namespace partition_alloc::internal
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_THREAD_CACHE_H_ #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_THREAD_CACHE_H_

View File

@ -1,46 +0,0 @@
// Copyright 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/android/base_features.h"
#include "base/android/jni_string.h"
#include "base/base_jni_headers/BaseFeatureList_jni.h"
#include "base/feature_list.h"
#include "base/notreached.h"
using base::android::ConvertJavaStringToUTF8;
using base::android::JavaParamRef;
namespace base::android {
namespace {
// Array of features exposed through the Java ContentFeatureList API. Entries in
// this array may either refer to features defined in the header of this file or
// in other locations in the code base (e.g. content_features.h).
const base::Feature* const kFeaturesExposedToJava[] = {
&features::kCrashBrowserOnChildMismatchIfBrowserChanged,
&features::kCrashBrowserOnAnyChildMismatch,
}; // namespace
const base::Feature* FindFeatureExposedToJava(const std::string& feature_name) {
for (const base::Feature* feature : kFeaturesExposedToJava) {
if (feature->name == feature_name)
return feature;
}
NOTREACHED() << "Queried feature cannot be found in BaseFeatureList: "
<< feature_name;
return nullptr;
}
} // namespace
static jboolean JNI_BaseFeatureList_IsEnabled(
JNIEnv* env,
const JavaParamRef<jstring>& jfeature_name) {
const base::Feature* feature =
FindFeatureExposedToJava(ConvertJavaStringToUTF8(env, jfeature_name));
return base::FeatureList::IsEnabled(*feature);
}
} // namespace base::android

View File

@ -1,25 +0,0 @@
// Copyright 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/android/base_features.h"
#include "base/feature_list.h"
namespace base::android::features {
// Alphabetical:
// Crash the browser process if a child process is created which does not match
// the browser process and the browser package appears to have changed since the
// browser process was launched, so that the browser process will be started
// fresh when next used, hopefully resolving the issue.
const base::Feature kCrashBrowserOnChildMismatchIfBrowserChanged{
"CrashBrowserOnChildMismatchIfBrowserChanged", FEATURE_DISABLED_BY_DEFAULT};
// Crash the browser process if a child process is created which does not match
// the browser process regardless of whether the browser package appears to have
// changed.
const base::Feature kCrashBrowserOnAnyChildMismatch{
"CrashBrowserOnAnyChildMismatch", FEATURE_DISABLED_BY_DEFAULT};
} // namespace base::android::features

View File

@ -1,21 +0,0 @@
// Copyright 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_ANDROID_BASE_FEATURES_H_
#define BASE_ANDROID_BASE_FEATURES_H_
#include "base/feature_list.h"
namespace base::android::features {
// All features in alphabetical order. The features should be documented
// alongside the definition of their values in the .cc file.
// Alphabetical:
extern const base::Feature kCrashBrowserOnChildMismatchIfBrowserChanged;
extern const base::Feature kCrashBrowserOnAnyChildMismatch;
} // namespace base::android::features
#endif // BASE_ANDROID_BASE_FEATURES_H_

View File

@ -80,8 +80,7 @@ BuildInfo::BuildInfo(const std::vector<std::string>& params)
is_debug_android_(GetIntParam(params, 22)), is_debug_android_(GetIntParam(params, 22)),
is_tv_(GetIntParam(params, 23)), is_tv_(GetIntParam(params, 23)),
version_incremental_(StrDupParam(params, 24)), version_incremental_(StrDupParam(params, 24)),
hardware_(StrDupParam(params, 25)), hardware_(StrDupParam(params, 25)) {}
is_at_least_t_(GetIntParam(params, 26)) {}
// static // static
BuildInfo* BuildInfo::GetInstance() { BuildInfo* BuildInfo::GetInstance() {

View File

@ -140,8 +140,6 @@ class BASE_EXPORT BuildInfo {
const char* hardware() const { return hardware_; } const char* hardware() const { return hardware_; }
bool is_at_least_t() const { return is_at_least_t_; }
private: private:
friend struct BuildInfoSingletonTraits; friend struct BuildInfoSingletonTraits;
@ -178,7 +176,6 @@ class BASE_EXPORT BuildInfo {
const bool is_tv_; const bool is_tv_;
const char* const version_incremental_; const char* const version_incremental_;
const char* const hardware_; const char* const hardware_;
const bool is_at_least_t_;
}; };
} // namespace android } // namespace android

View File

@ -58,8 +58,7 @@ BuildInfo::BuildInfo(const std::vector<std::string>& params)
is_debug_android_(false), is_debug_android_(false),
is_tv_(false), is_tv_(false),
version_incremental_(""), version_incremental_(""),
hardware_(""), hardware_("") {}
is_at_least_t_(false) {}
// static // static
BuildInfo* BuildInfo::GetInstance() { BuildInfo* BuildInfo::GetInstance() {

View File

@ -82,8 +82,8 @@ java_annotation_processor("jni_processor") {
# Avoids a circular dependency with base:base_java. This is okay because # Avoids a circular dependency with base:base_java. This is okay because
# no target should ever expect to package an annotation processor. # no target should ever expect to package an annotation processor.
"//build/android/java/src/org/chromium/base/annotations/CheckDiscard.java", "//base/android/java/src/org/chromium/base/annotations/CheckDiscard.java",
"//build/android/java/src/org/chromium/base/annotations/MainDex.java", "//base/android/java/src/org/chromium/base/annotations/MainDex.java",
] ]
main_class = "org.chromium.jni_generator.JniProcessor" main_class = "org.chromium.jni_generator.JniProcessor"

View File

@ -979,17 +979,12 @@ class JNIFromJavaSource(object):
class HeaderFileGeneratorHelper(object): class HeaderFileGeneratorHelper(object):
"""Include helper methods for header generators.""" """Include helper methods for header generators."""
def __init__(self, def __init__(self, class_name, fully_qualified_class, use_proxy_hash,
class_name, split_name):
fully_qualified_class,
use_proxy_hash,
split_name=None,
enable_jni_multiplexing=False):
self.class_name = class_name self.class_name = class_name
self.fully_qualified_class = fully_qualified_class self.fully_qualified_class = fully_qualified_class
self.use_proxy_hash = use_proxy_hash self.use_proxy_hash = use_proxy_hash
self.split_name = split_name self.split_name = split_name
self.enable_jni_multiplexing = enable_jni_multiplexing
def GetStubName(self, native): def GetStubName(self, native):
"""Return the name of the stub function for this native method. """Return the name of the stub function for this native method.
@ -1006,9 +1001,7 @@ class HeaderFileGeneratorHelper(object):
else: else:
method_name = EscapeClassName(native.proxy_name) method_name = EscapeClassName(native.proxy_name)
return 'Java_%s_%s' % (EscapeClassName( return 'Java_%s_%s' % (EscapeClassName(
ProxyHelpers.GetQualifiedClass( ProxyHelpers.GetQualifiedClass(self.use_proxy_hash)), method_name)
self.use_proxy_hash
or self.enable_jni_multiplexing)), method_name)
template = Template('Java_${JAVA_NAME}_native${NAME}') template = Template('Java_${JAVA_NAME}_native${NAME}')
@ -1023,9 +1016,8 @@ class HeaderFileGeneratorHelper(object):
ret = collections.OrderedDict() ret = collections.OrderedDict()
for entry in origin: for entry in origin:
if isinstance(entry, NativeMethod) and entry.is_proxy: if isinstance(entry, NativeMethod) and entry.is_proxy:
use_hash = self.use_proxy_hash or self.enable_jni_multiplexing ret[ProxyHelpers.GetClass(self.use_proxy_hash)] \
ret[ProxyHelpers.GetClass(use_hash)] \ = ProxyHelpers.GetQualifiedClass(self.use_proxy_hash)
= ProxyHelpers.GetQualifiedClass(use_hash)
continue continue
ret[self.class_name] = self.fully_qualified_class ret[self.class_name] = self.fully_qualified_class
@ -1058,8 +1050,7 @@ const char kClassPath_${JAVA_CLASS}[] = \
} }
# Since all proxy methods use the same class, defining this in every # Since all proxy methods use the same class, defining this in every
# header file would result in duplicated extern initializations. # header file would result in duplicated extern initializations.
if full_clazz != ProxyHelpers.GetQualifiedClass( if full_clazz != ProxyHelpers.GetQualifiedClass(self.use_proxy_hash):
self.use_proxy_hash or self.enable_jni_multiplexing):
ret += [template.substitute(values)] ret += [template.substitute(values)]
class_getter = """\ class_getter = """\
@ -1090,8 +1081,7 @@ JNI_REGISTRATION_EXPORT std::atomic<jclass> g_${JAVA_CLASS}_clazz(nullptr);
} }
# Since all proxy methods use the same class, defining this in every # Since all proxy methods use the same class, defining this in every
# header file would result in duplicated extern initializations. # header file would result in duplicated extern initializations.
if full_clazz != ProxyHelpers.GetQualifiedClass( if full_clazz != ProxyHelpers.GetQualifiedClass(self.use_proxy_hash):
self.use_proxy_hash or self.enable_jni_multiplexing):
ret += [template.substitute(values)] ret += [template.substitute(values)]
return ''.join(ret) return ''.join(ret)
@ -1111,12 +1101,10 @@ class InlHeaderFileGenerator(object):
self.constant_fields = constant_fields self.constant_fields = constant_fields
self.jni_params = jni_params self.jni_params = jni_params
self.options = options self.options = options
self.helper = HeaderFileGeneratorHelper( self.helper = HeaderFileGeneratorHelper(self.class_name,
self.class_name, fully_qualified_class,
fully_qualified_class, self.options.use_proxy_hash,
self.options.use_proxy_hash, self.options.split_name)
split_name=self.options.split_name,
enable_jni_multiplexing=self.options.enable_jni_multiplexing)
def GetContent(self): def GetContent(self):
"""Returns the content of the JNI binding file.""" """Returns the content of the JNI binding file."""
@ -1619,9 +1607,6 @@ See SampleForTests.java for more details.
action='store_true', action='store_true',
help='Hashes the native declaration of methods used ' help='Hashes the native declaration of methods used '
'in @JniNatives interface.') 'in @JniNatives interface.')
parser.add_argument('--enable_jni_multiplexing',
action='store_true',
help='Enables JNI multiplexing for Java native methods')
parser.add_argument( parser.add_argument(
'--split_name', '--split_name',
help='Split name that the Java classes should be loaded from.') help='Split name that the Java classes should be loaded from.')

View File

@ -13,7 +13,6 @@ file.
from __future__ import print_function from __future__ import print_function
import collections
import difflib import difflib
import inspect import inspect
import optparse import optparse
@ -60,7 +59,6 @@ class TestOptions(object):
self.enable_profiling = False self.enable_profiling = False
self.enable_tracing = False self.enable_tracing = False
self.use_proxy_hash = False self.use_proxy_hash = False
self.enable_jni_multiplexing = False
self.always_mangle = False self.always_mangle = False
self.unchecked_exceptions = False self.unchecked_exceptions = False
self.split_name = None self.split_name = None
@ -71,8 +69,7 @@ class BaseTest(unittest.TestCase):
@staticmethod @staticmethod
def _MergeRegistrationForTests(results, def _MergeRegistrationForTests(results,
header_guard='HEADER_GUARD', header_guard='HEADER_GUARD',
namespace='test', namespace='test'):
enable_jni_multiplexing=False):
results.sort(key=lambda d: d['FULL_CLASS_NAME']) results.sort(key=lambda d: d['FULL_CLASS_NAME'])
@ -82,27 +79,6 @@ class BaseTest(unittest.TestCase):
combined_dict['HEADER_GUARD'] = header_guard combined_dict['HEADER_GUARD'] = header_guard
combined_dict['NAMESPACE'] = namespace combined_dict['NAMESPACE'] = namespace
if enable_jni_multiplexing:
proxy_signatures_list = sorted(
set(combined_dict['PROXY_NATIVE_SIGNATURES'].split('\n')))
combined_dict['PROXY_NATIVE_SIGNATURES'] = '\n'.join(
signature for signature in proxy_signatures_list)
proxy_native_array_list = sorted(
set(combined_dict['PROXY_NATIVE_METHOD_ARRAY_MAIN_DEX'].split(
'},\n')))
combined_dict['PROXY_NATIVE_METHOD_ARRAY_MAIN_DEX'] = '},\n'.join(
p for p in proxy_native_array_list if p != '') + '}'
signature_to_cases = collections.defaultdict(list)
for d in results:
for signature, cases in d['SIGNATURE_TO_CASES'].items():
signature_to_cases[signature].extend(cases)
combined_dict[
'FORWARDING_CALLS'] = jni_registration_generator._AddForwardingCalls(
signature_to_cases, namespace)
return combined_dict return combined_dict
def _JoinScriptDir(self, path): def _JoinScriptDir(self, path):
@ -380,18 +356,18 @@ class TestGenerator(BaseTest):
natives, [], [], jni_params, natives, [], [], jni_params,
TestOptions()) TestOptions())
self.AssertGoldenTextEquals(h1.GetContent()) self.AssertGoldenTextEquals(h1.GetContent())
h2 = jni_registration_generator.HeaderGenerator('', h2 = jni_registration_generator.HeaderGenerator(
'', '',
'org/chromium/TestJni', 'org/chromium/TestJni',
natives, natives,
jni_params, jni_params,
True, True,
use_proxy_hash=False) use_proxy_hash=False)
content = TestGenerator._MergeRegistrationForTests([h2.Generate()]) content = TestGenerator._MergeRegistrationForTests([h2.Generate()])
self.AssertGoldenTextEquals(jni_registration_generator.CreateFromDict( self.AssertGoldenTextEquals(
content, use_hash=False, manual_jni_registration=True), jni_registration_generator.CreateFromDict(content, use_hash=False),
suffix='Registrations') suffix='Registrations')
def testInnerClassNatives(self): def testInnerClassNatives(self):
test_data = """ test_data = """
@ -481,18 +457,18 @@ class TestGenerator(BaseTest):
TestOptions()) TestOptions())
self.AssertGoldenTextEquals(h.GetContent()) self.AssertGoldenTextEquals(h.GetContent())
h2 = jni_registration_generator.HeaderGenerator('', h2 = jni_registration_generator.HeaderGenerator(
'', '',
'org/chromium/TestJni', 'org/chromium/TestJni',
natives, natives,
jni_params, jni_params,
True, True,
use_proxy_hash=False) use_proxy_hash=False)
content = TestGenerator._MergeRegistrationForTests([h2.Generate()]) content = TestGenerator._MergeRegistrationForTests([h2.Generate()])
self.AssertGoldenTextEquals(jni_registration_generator.CreateFromDict( self.AssertGoldenTextEquals(
content, use_hash=False, manual_jni_registration=True), jni_registration_generator.CreateFromDict(content, use_hash=False),
suffix='Registrations') suffix='Registrations')
def testCalledByNatives(self): def testCalledByNatives(self):
test_data = """" test_data = """"
@ -1432,7 +1408,6 @@ class ProxyTestGenerator(BaseTest):
jni_params = jni_generator.JniParams(qualified_clazz) jni_params = jni_generator.JniParams(qualified_clazz)
main_dex_header = jni_registration_generator.HeaderGenerator( main_dex_header = jni_registration_generator.HeaderGenerator(
'',
'', '',
qualified_clazz, qualified_clazz,
natives, natives,
@ -1442,9 +1417,7 @@ class ProxyTestGenerator(BaseTest):
content = TestGenerator._MergeRegistrationForTests([main_dex_header]) content = TestGenerator._MergeRegistrationForTests([main_dex_header])
self.AssertGoldenTextEquals( self.AssertGoldenTextEquals(
jni_registration_generator.CreateFromDict(content, jni_registration_generator.CreateFromDict(content, use_hash=False))
use_hash=False,
manual_jni_registration=True))
other_qualified_clazz = 'test/foo/Bar' other_qualified_clazz = 'test/foo/Bar'
other_natives = jni_generator.ProxyHelpers.ExtractStaticProxyNatives( other_natives = jni_generator.ProxyHelpers.ExtractStaticProxyNatives(
@ -1452,7 +1425,6 @@ class ProxyTestGenerator(BaseTest):
jni_params = jni_generator.JniParams(other_qualified_clazz) jni_params = jni_generator.JniParams(other_qualified_clazz)
non_main_dex_header = jni_registration_generator.HeaderGenerator( non_main_dex_header = jni_registration_generator.HeaderGenerator(
'',
'', '',
other_qualified_clazz, other_qualified_clazz,
other_natives, other_natives,
@ -1464,9 +1436,7 @@ class ProxyTestGenerator(BaseTest):
[non_main_dex_header]) [non_main_dex_header])
self.AssertGoldenTextEquals( self.AssertGoldenTextEquals(
jni_registration_generator.CreateFromDict(content, jni_registration_generator.CreateFromDict(content, use_hash=False),
use_hash=False,
manual_jni_registration=True),
'AndNonMainDex') 'AndNonMainDex')
def testProxyNatives(self): def testProxyNatives(self):
@ -1552,26 +1522,18 @@ class ProxyTestGenerator(BaseTest):
h1 = jni_generator.InlHeaderFileGenerator('', qualified_clazz, natives, [], h1 = jni_generator.InlHeaderFileGenerator('', qualified_clazz, natives, [],
[], jni_params, TestOptions()) [], jni_params, TestOptions())
self.AssertGoldenTextEquals(h1.GetContent()) self.AssertGoldenTextEquals(h1.GetContent())
h2 = jni_registration_generator.HeaderGenerator('', h2 = jni_registration_generator.HeaderGenerator(
'', '', qualified_clazz, natives, jni_params, False, use_proxy_hash=False)
qualified_clazz,
natives,
jni_params,
False,
use_proxy_hash=False)
content = TestGenerator._MergeRegistrationForTests([h2.Generate()]) content = TestGenerator._MergeRegistrationForTests([h2.Generate()])
proxy_opts = jni_registration_generator.ProxyOptions( proxy_opts = jni_registration_generator.ProxyOptions()
manual_jni_registration=True)
self.AssertGoldenTextEquals( self.AssertGoldenTextEquals(
jni_registration_generator.CreateProxyJavaFromDict(content, proxy_opts), jni_registration_generator.CreateProxyJavaFromDict(content, proxy_opts),
suffix='Java') suffix='Java')
self.AssertGoldenTextEquals(jni_registration_generator.CreateFromDict( self.AssertGoldenTextEquals(
content, jni_registration_generator.CreateFromDict(content, proxy_opts.use_hash),
proxy_opts.use_hash, suffix='Registrations')
manual_jni_registration=proxy_opts.manual_jni_registration),
suffix='Registrations')
def testProxyHashedExample(self): def testProxyHashedExample(self):
opts = TestOptions() opts = TestOptions()
@ -1689,66 +1651,6 @@ class ProxyTestGenerator(BaseTest):
self.AssertListEquals(golden_natives, _RemoveHashedNames(natives)) self.AssertListEquals(golden_natives, _RemoveHashedNames(natives))
class MultiplexTestGenerator(BaseTest):
def testProxyMultiplexGenJni(self):
path = os.path.join(_JAVA_SRC_DIR, 'SampleForAnnotationProcessor.java')
reg_dict = jni_registration_generator._DictForPath(
self._JoinScriptDir(path),
enable_jni_multiplexing=True,
namespace='test')
reg_dict = self._MergeRegistrationForTests([reg_dict],
enable_jni_multiplexing=True)
proxy_opts = jni_registration_generator.ProxyOptions(
enable_jni_multiplexing=True)
self.AssertGoldenTextEquals(
jni_registration_generator.CreateProxyJavaFromDict(
reg_dict, proxy_opts),
golden_file='testProxyMultiplexGenJni.golden')
self.AssertGoldenTextEquals(
jni_registration_generator.CreateProxyJavaFromDict(reg_dict,
proxy_opts,
forwarding=True),
golden_file='testProxyMultiplexGenJni.2.golden')
def testProxyMultiplexNatives(self):
path = os.path.join(_JAVA_SRC_DIR, 'SampleForAnnotationProcessor.java')
reg_dict = jni_registration_generator._DictForPath(
self._JoinScriptDir(path),
enable_jni_multiplexing=True,
namespace='test')
reg_dict = self._MergeRegistrationForTests([reg_dict],
enable_jni_multiplexing=True)
proxy_opts = jni_registration_generator.ProxyOptions(
enable_jni_multiplexing=True)
self.AssertGoldenTextEquals(jni_registration_generator.CreateFromDict(
reg_dict,
proxy_opts.use_hash,
enable_jni_multiplexing=proxy_opts.enable_jni_multiplexing),
golden_file='testProxyMultiplexNatives.golden')
def testProxyMultiplexNativesRegistration(self):
path = os.path.join(_JAVA_SRC_DIR, 'SampleForAnnotationProcessor.java')
reg_dict_for_registration = jni_registration_generator._DictForPath(
self._JoinScriptDir(path),
enable_jni_multiplexing=True,
namespace='test')
reg_dict_for_registration = self._MergeRegistrationForTests(
[reg_dict_for_registration], enable_jni_multiplexing=True)
proxy_opts = jni_registration_generator.ProxyOptions(
enable_jni_multiplexing=True)
self.AssertGoldenTextEquals(
jni_registration_generator.CreateFromDict(
reg_dict_for_registration,
proxy_opts.use_hash,
enable_jni_multiplexing=proxy_opts.enable_jni_multiplexing,
manual_jni_registration=True),
golden_file='testProxyMultiplexNativesRegistration.golden')
def TouchStamp(stamp_path): def TouchStamp(stamp_path):
dir_name = os.path.dirname(stamp_path) dir_name = os.path.dirname(stamp_path)
if not os.path.isdir(dir_name): if not os.path.isdir(dir_name):

View File

@ -12,7 +12,6 @@ to register all native methods that exist within an application."""
import argparse import argparse
import collections import collections
import functools import functools
import hashlib
import multiprocessing import multiprocessing
import os import os
import string import string
@ -57,16 +56,23 @@ def _Generate(java_file_paths,
header_path: If specified, generates a header file in this location. header_path: If specified, generates a header file in this location.
namespace: If specified, sets the namespace for the generated header file. namespace: If specified, sets the namespace for the generated header file.
""" """
# For JNI multiplexing, a 16-bit prefix is used to identify each individual
# java file path. This allows fewer multiplexed functions to resolve multiple
# different native functions with the same signature across the JNI boundary
# using switch statements. Should not exceed 65536 (2**16) number of paths.
assert len(java_file_paths) < 65536
java_path_prefix_tuples = [(path, index)
for index, path in enumerate(java_file_paths)]
# Without multiprocessing, script takes ~13 seconds for chrome_public_apk # Without multiprocessing, script takes ~13 seconds for chrome_public_apk
# on a z620. With multiprocessing, takes ~2 seconds. # on a z620. With multiprocessing, takes ~2 seconds.
results = [] results = []
with multiprocessing.Pool() as pool: with multiprocessing.Pool() as pool:
for d in pool.imap_unordered( for d in pool.imap_unordered(
functools.partial( functools.partial(
_DictForPath, _DictForPathAndPrefix,
use_proxy_hash=proxy_opts.use_hash, use_proxy_hash=proxy_opts.use_hash,
enable_jni_multiplexing=proxy_opts.enable_jni_multiplexing, enable_jni_multiplexing=proxy_opts.enable_jni_multiplexing),
namespace=namespace), java_file_paths): java_path_prefix_tuples):
if d: if d:
results.append(d) results.append(d)
@ -76,43 +82,25 @@ def _Generate(java_file_paths,
combined_dict = {} combined_dict = {}
for key in MERGEABLE_KEYS: for key in MERGEABLE_KEYS:
combined_dict[key] = ''.join(d.get(key, '') for d in results) combined_dict[key] = ''.join(d.get(key, '') for d in results)
# PROXY_NATIVE_SIGNATURES and PROXY_NATIVE_METHOD_ARRAY_MAIN_DEX will have # PROXY_NATIVE_SIGNATURES will have duplicates for JNI multiplexing since
# duplicates for JNI multiplexing since all native methods with similar # all native methods with similar signatures map to the same proxy.
# signatures map to the same proxy. Similarly, there may be multiple switch
# case entries for the same proxy signatures.
if proxy_opts.enable_jni_multiplexing: if proxy_opts.enable_jni_multiplexing:
proxy_signatures_list = sorted( proxy_signatures_list = sorted(
set(combined_dict['PROXY_NATIVE_SIGNATURES'].split('\n'))) set(combined_dict['PROXY_NATIVE_SIGNATURES'].split('\n')))
combined_dict['PROXY_NATIVE_SIGNATURES'] = '\n'.join( combined_dict['PROXY_NATIVE_SIGNATURES'] = '\n'.join(
signature for signature in proxy_signatures_list) signature for signature in proxy_signatures_list)
proxy_native_array_list = sorted(
set(combined_dict['PROXY_NATIVE_METHOD_ARRAY_MAIN_DEX'].split('},\n')))
combined_dict['PROXY_NATIVE_METHOD_ARRAY_MAIN_DEX'] = '},\n'.join(
p for p in proxy_native_array_list if p != '') + '}'
signature_to_cases = collections.defaultdict(list)
for d in results:
for signature, cases in d['SIGNATURE_TO_CASES'].items():
signature_to_cases[signature].extend(cases)
combined_dict['FORWARDING_CALLS'] = _AddForwardingCalls(
signature_to_cases, namespace)
if header_path: if header_path:
combined_dict['HEADER_GUARD'] = \ combined_dict['HEADER_GUARD'] = \
os.path.splitext(header_path)[0].replace('/', '_').upper() + '_' os.path.splitext(header_path)[0].replace('/', '_').upper() + '_'
combined_dict['NAMESPACE'] = namespace combined_dict['NAMESPACE'] = namespace
header_content = CreateFromDict( header_content = CreateFromDict(combined_dict, proxy_opts.use_hash)
combined_dict,
proxy_opts.use_hash,
enable_jni_multiplexing=proxy_opts.enable_jni_multiplexing,
manual_jni_registration=proxy_opts.manual_jni_registration)
with build_utils.AtomicOutput(header_path, mode='w') as f: with build_utils.AtomicOutput(header_path, mode='w') as f:
f.write(header_content) f.write(header_content)
with build_utils.AtomicOutput(srcjar_path) as f: with build_utils.AtomicOutput(srcjar_path) as f:
with zipfile.ZipFile(f, 'w') as srcjar: with zipfile.ZipFile(f, 'w') as srcjar:
if proxy_opts.use_hash or proxy_opts.enable_jni_multiplexing: if proxy_opts.use_hash:
# J/N.java # J/N.java
build_utils.AddToZipHermetic( build_utils.AddToZipHermetic(
srcjar, srcjar,
@ -132,10 +120,20 @@ def _Generate(java_file_paths,
data=CreateProxyJavaFromDict(combined_dict, proxy_opts)) data=CreateProxyJavaFromDict(combined_dict, proxy_opts))
# A wrapper for imap_ordered to call with a tuple.
def _DictForPathAndPrefix(path_prefix_tuple, use_proxy_hash,
enable_jni_multiplexing):
path, switch_prefix = path_prefix_tuple
return _DictForPath(path,
use_proxy_hash=use_proxy_hash,
enable_jni_multiplexing=enable_jni_multiplexing,
switch_prefix=switch_prefix)
def _DictForPath(path, def _DictForPath(path,
use_proxy_hash=False, use_proxy_hash=False,
enable_jni_multiplexing=False, enable_jni_multiplexing=False,
namespace=''): switch_prefix=None):
with open(path) as f: with open(path) as f:
contents = jni_generator.RemoveComments(f.read()) contents = jni_generator.RemoveComments(f.read())
if '@JniIgnoreNatives' in contents: if '@JniIgnoreNatives' in contents:
@ -151,68 +149,23 @@ def _DictForPath(path,
ptr_type='long') ptr_type='long')
if len(natives) == 0: if len(natives) == 0:
return None return None
# The namespace for the content is separate from the namespace for the namespace = jni_generator.ExtractJNINamespace(contents)
# generated header file.
content_namespace = jni_generator.ExtractJNINamespace(contents)
jni_params = jni_generator.JniParams(fully_qualified_class) jni_params = jni_generator.JniParams(fully_qualified_class)
jni_params.ExtractImportsAndInnerClasses(contents) jni_params.ExtractImportsAndInnerClasses(contents)
is_main_dex = jni_generator.IsMainDexJavaClass(contents) is_main_dex = jni_generator.IsMainDexJavaClass(contents)
header_generator = HeaderGenerator( header_generator = HeaderGenerator(
namespace, namespace,
content_namespace,
fully_qualified_class, fully_qualified_class,
natives, natives,
jni_params, jni_params,
is_main_dex, is_main_dex,
use_proxy_hash, use_proxy_hash,
enable_jni_multiplexing=enable_jni_multiplexing) enable_jni_multiplexing=enable_jni_multiplexing,
switch_prefix=switch_prefix)
return header_generator.Generate() return header_generator.Generate()
def _AddForwardingCalls(signature_to_cases, namespace): def _SetProxyRegistrationFields(registration_dict, use_hash):
template = string.Template("""
JNI_GENERATOR_EXPORT ${RETURN} Java_${CLASS_NAME}_${PROXY_SIGNATURE}(
JNIEnv* env,
jclass jcaller,
${PARAMS_IN_STUB}) {
switch (switch_num) {
${CASES}
default:
CHECK(false) << "JNI multiplexing function Java_\
${CLASS_NAME}_${PROXY_SIGNATURE} was called with an invalid switch number: "\
<< switch_num;
return${DEFAULT_RETURN};
}
}""")
switch_statements = []
for signature, cases in sorted(signature_to_cases.items()):
return_type, params_list = signature
params_in_stub = _GetJavaToNativeParamsList(params_list)
switch_statements.append(
template.substitute({
'RETURN':
jni_generator.JavaDataTypeToC(return_type),
'CLASS_NAME':
jni_generator.EscapeClassName(
jni_generator.ProxyHelpers.GetQualifiedClass(True) + namespace),
'PROXY_SIGNATURE':
jni_generator.EscapeClassName(
_GetMultiplexProxyName(return_type, params_list)),
'PARAMS_IN_STUB':
params_in_stub,
'CASES':
''.join(cases),
'DEFAULT_RETURN':
'' if return_type == 'void' else ' {}',
}))
return ''.join(s for s in switch_statements)
def _SetProxyRegistrationFields(registration_dict, use_hash,
enable_jni_multiplexing,
manual_jni_registration):
registration_template = string.Template("""\ registration_template = string.Template("""\
static const JNINativeMethod kMethods_${ESCAPED_PROXY_CLASS}[] = { static const JNINativeMethod kMethods_${ESCAPED_PROXY_CLASS}[] = {
@ -249,46 +202,17 @@ JNI_REGISTRATION_EXPORT bool ${REGISTRATION_NAME}(JNIEnv* env) {
} }
""") """)
manual_registration = string.Template("""\
// Step 3: Method declarations.
${JNI_NATIVE_METHOD_ARRAY}\
${PROXY_NATIVE_METHOD_ARRAY}\
${JNI_NATIVE_METHOD}
// Step 4: Main dex and non-main dex registration functions.
namespace ${NAMESPACE} {
bool RegisterMainDexNatives(JNIEnv* env) {\
${REGISTER_MAIN_DEX_PROXY_NATIVES}
${REGISTER_MAIN_DEX_NATIVES}
return true;
}
bool RegisterNonMainDexNatives(JNIEnv* env) {\
${REGISTER_PROXY_NATIVES}
${REGISTER_NON_MAIN_DEX_NATIVES}
return true;
}
} // namespace ${NAMESPACE}
""")
sub_dict = { sub_dict = {
'ESCAPED_PROXY_CLASS': 'ESCAPED_PROXY_CLASS':
jni_generator.EscapeClassName( jni_generator.EscapeClassName(
jni_generator.ProxyHelpers.GetQualifiedClass( jni_generator.ProxyHelpers.GetQualifiedClass(use_hash)),
use_hash or enable_jni_multiplexing)),
'PROXY_CLASS': 'PROXY_CLASS':
jni_generator.ProxyHelpers.GetQualifiedClass(use_hash jni_generator.ProxyHelpers.GetQualifiedClass(use_hash),
or enable_jni_multiplexing),
'KMETHODS': 'KMETHODS':
registration_dict['PROXY_NATIVE_METHOD_ARRAY'], registration_dict['PROXY_NATIVE_METHOD_ARRAY'],
'REGISTRATION_NAME': 'REGISTRATION_NAME':
jni_generator.GetRegistrationFunctionName( jni_generator.GetRegistrationFunctionName(
jni_generator.ProxyHelpers.GetQualifiedClass( jni_generator.ProxyHelpers.GetQualifiedClass(use_hash)),
use_hash or enable_jni_multiplexing)),
} }
if registration_dict['PROXY_NATIVE_METHOD_ARRAY']: if registration_dict['PROXY_NATIVE_METHOD_ARRAY']:
@ -312,12 +236,6 @@ ${REGISTER_NON_MAIN_DEX_NATIVES}
registration_dict['REGISTER_PROXY_NATIVES'] = proxy_natives_registration registration_dict['REGISTER_PROXY_NATIVES'] = proxy_natives_registration
registration_dict['REGISTER_MAIN_DEX_PROXY_NATIVES'] = main_dex_call registration_dict['REGISTER_MAIN_DEX_PROXY_NATIVES'] = main_dex_call
if manual_jni_registration:
registration_dict['MANUAL_REGISTRATION'] = manual_registration.substitute(
registration_dict)
else:
registration_dict['MANUAL_REGISTRATION'] = ''
def CreateProxyJavaFromDict(registration_dict, proxy_opts, forwarding=False): def CreateProxyJavaFromDict(registration_dict, proxy_opts, forwarding=False):
template = string.Template("""\ template = string.Template("""\
@ -337,13 +255,11 @@ ${METHODS}
} }
""") """)
is_natives_class = not forwarding and (proxy_opts.use_hash is_natives_class = not forwarding and proxy_opts.use_hash
or proxy_opts.enable_jni_multiplexing)
class_name = jni_generator.ProxyHelpers.GetClass(is_natives_class) class_name = jni_generator.ProxyHelpers.GetClass(is_natives_class)
package = jni_generator.ProxyHelpers.GetPackage(is_natives_class) package = jni_generator.ProxyHelpers.GetPackage(is_natives_class)
if forwarding or not (proxy_opts.use_hash if forwarding or not proxy_opts.use_hash:
or proxy_opts.enable_jni_multiplexing):
fields = string.Template("""\ fields = string.Template("""\
public static final boolean TESTING_ENABLED = ${TESTING_ENABLED}; public static final boolean TESTING_ENABLED = ${TESTING_ENABLED};
public static final boolean REQUIRE_MOCK = ${REQUIRE_MOCK}; public static final boolean REQUIRE_MOCK = ${REQUIRE_MOCK};
@ -367,10 +283,7 @@ ${METHODS}
}) })
def CreateFromDict(registration_dict, def CreateFromDict(registration_dict, use_hash):
use_hash,
enable_jni_multiplexing=False,
manual_jni_registration=False):
"""Returns the content of the header file.""" """Returns the content of the header file."""
template = string.Template("""\ template = string.Template("""\
@ -400,52 +313,54 @@ ${CLASS_PATH_DECLARATIONS}
// Step 2: Forward declarations (methods). // Step 2: Forward declarations (methods).
${FORWARD_DECLARATIONS} ${FORWARD_DECLARATIONS}
${FORWARDING_CALLS}
${MANUAL_REGISTRATION} // Step 3: Method declarations.
${JNI_NATIVE_METHOD_ARRAY}\
${PROXY_NATIVE_METHOD_ARRAY}\
${JNI_NATIVE_METHOD}
// Step 4: Main dex and non-main dex registration functions.
namespace ${NAMESPACE} {
bool RegisterMainDexNatives(JNIEnv* env) {\
${REGISTER_MAIN_DEX_PROXY_NATIVES}
${REGISTER_MAIN_DEX_NATIVES}
return true;
}
bool RegisterNonMainDexNatives(JNIEnv* env) {\
${REGISTER_PROXY_NATIVES}
${REGISTER_NON_MAIN_DEX_NATIVES}
return true;
}
} // namespace ${NAMESPACE}
#endif // ${HEADER_GUARD} #endif // ${HEADER_GUARD}
""") """)
_SetProxyRegistrationFields(registration_dict, use_hash, _SetProxyRegistrationFields(registration_dict, use_hash)
enable_jni_multiplexing, manual_jni_registration)
if not enable_jni_multiplexing:
registration_dict['FORWARDING_CALLS'] = ''
if len(registration_dict['FORWARD_DECLARATIONS']) == 0: if len(registration_dict['FORWARD_DECLARATIONS']) == 0:
return '' return ''
return template.substitute(registration_dict) return template.substitute(registration_dict)
def _GetJavaToNativeParamsList(params_list):
if not params_list:
return 'jlong switch_num'
# Parameters are named after their type, with a unique number per parameter
# type to make sure the names are unique, even within the same types.
params_type_count = collections.defaultdict(int)
params_in_stub = []
for p in params_list:
params_type_count[p] += 1
params_in_stub.append(
'%s %s_param%d' %
(jni_generator.JavaDataTypeToC(p), p.replace(
'[]', '_array').lower(), params_type_count[p]))
return 'jlong switch_num, ' + ', '.join(params_in_stub)
class HeaderGenerator(object): class HeaderGenerator(object):
"""Generates an inline header file for JNI registration.""" """Generates an inline header file for JNI registration."""
def __init__(self, def __init__(self,
namespace, namespace,
content_namespace,
fully_qualified_class, fully_qualified_class,
natives, natives,
jni_params, jni_params,
main_dex, main_dex,
use_proxy_hash, use_proxy_hash,
enable_jni_multiplexing=False): enable_jni_multiplexing=False,
switch_prefix=None):
self.namespace = namespace self.namespace = namespace
self.content_namespace = content_namespace
self.natives = natives self.natives = natives
self.proxy_natives = [n for n in natives if n.is_proxy] self.proxy_natives = [n for n in natives if n.is_proxy]
self.non_proxy_natives = [n for n in natives if not n.is_proxy] self.non_proxy_natives = [n for n in natives if not n.is_proxy]
@ -454,12 +369,12 @@ class HeaderGenerator(object):
self.class_name = self.fully_qualified_class.split('/')[-1] self.class_name = self.fully_qualified_class.split('/')[-1]
self.main_dex = main_dex self.main_dex = main_dex
self.helper = jni_generator.HeaderFileGeneratorHelper( self.helper = jni_generator.HeaderFileGeneratorHelper(
self.class_name, self.class_name, fully_qualified_class, use_proxy_hash, None)
fully_qualified_class,
use_proxy_hash,
enable_jni_multiplexing=enable_jni_multiplexing)
self.use_proxy_hash = use_proxy_hash self.use_proxy_hash = use_proxy_hash
self.enable_jni_multiplexing = enable_jni_multiplexing self.enable_jni_multiplexing = enable_jni_multiplexing
# Each java file path is assigned a 16-bit integer as a prefix to the
# switch number to ensure uniqueness across all native methods.
self.switch_prefix = switch_prefix
self.registration_dict = None self.registration_dict = None
def Generate(self): def Generate(self):
@ -479,9 +394,8 @@ class HeaderGenerator(object):
for native in self.proxy_natives)) for native in self.proxy_natives))
if self.enable_jni_multiplexing: if self.enable_jni_multiplexing:
self._AssignSwitchNumberToNatives() self._AssignSwitchNumberToNatives()
self._AddCases()
if self.use_proxy_hash or self.enable_jni_multiplexing: if self.use_proxy_hash:
self.registration_dict['FORWARDING_PROXY_METHODS'] = ('\n'.join( self.registration_dict['FORWARDING_PROXY_METHODS'] = ('\n'.join(
_MakeForwardingProxy( _MakeForwardingProxy(
native, enable_jni_multiplexing=self.enable_jni_multiplexing) native, enable_jni_multiplexing=self.enable_jni_multiplexing)
@ -546,8 +460,8 @@ ${KMETHODS}
""") """)
open_namespace = '' open_namespace = ''
close_namespace = '' close_namespace = ''
if self.content_namespace: if self.namespace:
parts = self.content_namespace.split('::') parts = self.namespace.split('::')
all_namespaces = ['namespace %s {' % ns for ns in parts] all_namespaces = ['namespace %s {' % ns for ns in parts]
open_namespace = '\n'.join(all_namespaces) + '\n' open_namespace = '\n'.join(all_namespaces) + '\n'
all_namespaces = ['} // namespace %s' % ns for ns in parts] all_namespaces = ['} // namespace %s' % ns for ns in parts]
@ -555,9 +469,8 @@ ${KMETHODS}
close_namespace = '\n'.join(all_namespaces) + '\n\n' close_namespace = '\n'.join(all_namespaces) + '\n\n'
body = self._SubstituteNativeMethods(template) body = self._SubstituteNativeMethods(template)
if body: self._SetDictValue('JNI_NATIVE_METHOD_ARRAY', ''.join((open_namespace, body,
self._SetDictValue('JNI_NATIVE_METHOD_ARRAY', ''.join( close_namespace)))
(open_namespace, body, close_namespace)))
def _GetKMethodsString(self, clazz): def _GetKMethodsString(self, clazz):
ret = [] ret = []
@ -572,39 +485,27 @@ ${KMETHODS}
'reinterpret_cast<void*>(${STUB_NAME}) },') 'reinterpret_cast<void*>(${STUB_NAME}) },')
name = 'native' + native.name name = 'native' + native.name
jni_signature = self.jni_params.Signature(native.params, native.return_type)
stub_name = self.helper.GetStubName(native)
if native.is_proxy: if native.is_proxy:
# Literal name of the native method in the class that contains the actual # Literal name of the native method in the class that contains the actual
# native declaration. # native declaration.
if self.enable_jni_multiplexing: if self.use_proxy_hash:
return_type, params_list = native.return_and_signature
class_name = jni_generator.EscapeClassName(
jni_generator.ProxyHelpers.GetQualifiedClass(True) + self.namespace)
proxy_signature = jni_generator.EscapeClassName(
_GetMultiplexProxyName(return_type, params_list))
name = _GetMultiplexProxyName(return_type, params_list)
jni_signature = self.jni_params.Signature(
[jni_generator.Param(datatype='long', name='switch_num')] +
native.params, native.return_type)
stub_name = 'Java_' + class_name + '_' + proxy_signature
elif self.use_proxy_hash:
name = native.hashed_proxy_name name = native.hashed_proxy_name
else: else:
name = native.proxy_name name = native.proxy_name
values = { values = {
'NAME': name, 'NAME':
'JNI_SIGNATURE': jni_signature, name,
'STUB_NAME': stub_name 'JNI_SIGNATURE':
self.jni_params.Signature(native.params, native.return_type),
'STUB_NAME':
self.helper.GetStubName(native)
} }
return template.substitute(values) return template.substitute(values)
def _AddProxyNativeMethodKStrings(self): def _AddProxyNativeMethodKStrings(self):
"""Returns KMethodString for wrapped native methods in all_classes """ """Returns KMethodString for wrapped native methods in all_classes """
if self.main_dex or self.enable_jni_multiplexing: if self.main_dex:
key = 'PROXY_NATIVE_METHOD_ARRAY_MAIN_DEX' key = 'PROXY_NATIVE_METHOD_ARRAY_MAIN_DEX'
else: else:
key = 'PROXY_NATIVE_METHOD_ARRAY' key = 'PROXY_NATIVE_METHOD_ARRAY'
@ -623,14 +524,13 @@ ${KMETHODS}
for clazz, full_clazz in all_classes.items(): for clazz, full_clazz in all_classes.items():
if not sub_proxy: if not sub_proxy:
if clazz == jni_generator.ProxyHelpers.GetClass( if clazz == jni_generator.ProxyHelpers.GetClass(self.use_proxy_hash):
self.use_proxy_hash or self.enable_jni_multiplexing):
continue continue
kmethods = self._GetKMethodsString(clazz) kmethods = self._GetKMethodsString(clazz)
namespace_str = '' namespace_str = ''
if self.content_namespace: if self.namespace:
namespace_str = self.content_namespace + '::' namespace_str = self.namespace + '::'
if kmethods: if kmethods:
values = { values = {
'NAMESPACE': namespace_str, 'NAMESPACE': namespace_str,
@ -694,84 +594,39 @@ ${NATIVES}\
return '' return ''
def _AssignSwitchNumberToNatives(self): def _AssignSwitchNumberToNatives(self):
# The switch number for a native method is a 64-bit long with the first # The switch number for a native method is a 32-bit integer and indicates
# bit being a sign digit. The signed two's complement is taken when # which native implementation the method should be dispatched to across
# appropriate to make use of negative numbers. # the JNI multiplexing boundary.
signature_to_methods = collections.defaultdict(list)
for native in self.proxy_natives: for native in self.proxy_natives:
hashed_long = hashlib.md5( same_signature_methods = signature_to_methods[native.return_and_signature]
native.proxy_name.encode('utf-8')).hexdigest()[:16] # Should not exceed 65536 (2**16) methods with same proxy signature.
switch_num = int(hashed_long, 16) assert len(same_signature_methods) < 65536
if (switch_num & 1 << 63):
switch_num -= (1 << 64)
native.switch_num = str(switch_num) native.switch_num = self.switch_prefix * (2**16) + len(
same_signature_methods)
def _AddCases(self): same_signature_methods.append(native.proxy_name)
# Switch cases are grouped together by the same proxy signatures.
template = string.Template("""
case ${SWITCH_NUM}:
return ${STUB_NAME}(env, jcaller${PARAMS});
""")
signature_to_cases = collections.defaultdict(list)
for native in self.proxy_natives:
signature = native.return_and_signature
params = _GetParamsListForMultiplex(signature[1], with_types=False)
values = {
'SWITCH_NUM': native.switch_num,
'STUB_NAME': self.helper.GetStubName(native),
'PARAMS': params,
}
signature_to_cases[signature].append(template.substitute(values))
self.registration_dict['SIGNATURE_TO_CASES'] = signature_to_cases
def _GetParamsListForMultiplex(params_list, with_types): def _GetParamsListForMultiplex(params_list):
if not params_list: if not params_list:
return '' return 'int switch_num'
# Parameters are named after their type, with a unique number per parameter # Parameters are named after their type, with a unique number per parameter
# type to make sure the names are unique, even within the same types. # type to make sure the names are unique, even within the same types.
params_type_count = collections.defaultdict(int) params_type_count = collections.defaultdict(int)
params = [] params_with_types = []
for p in params_list: for p in params_list:
params_type_count[p] += 1 params_type_count[p] += 1
param_type = p + ' ' if with_types else '' params_with_types.append(
params.append( '%s %s_param%d' %
'%s%s_param%d' % (p, p.replace('[]', '_array').lower(), params_type_count[p]))
(param_type, p.replace('[]', '_array').lower(), params_type_count[p]))
return ', ' + ', '.join(params) return ', '.join(params_with_types) + ', int switch_num'
def _GetMultiplexProxyName(return_type, params_list): def _GetMultiplexProxyName(return_type):
# Proxy signatures for methods are named after their return type and return 'resolve_for_' + return_type.replace('[]', '_array').lower()
# parameters to ensure uniqueness, even for the same return types.
params = ''
if params_list:
type_convert_dictionary = {
'[]': 'A',
'byte': 'B',
'char': 'C',
'double': 'D',
'float': 'F',
'int': 'I',
'long': 'J',
'Class': 'L',
'Object': 'O',
'String': 'R',
'short': 'S',
'Throwable': 'T',
'boolean': 'Z',
}
# Parameter types could contain multi-dimensional arrays and every
# instance of [] has to be replaced in the proxy signature name.
for k, v in type_convert_dictionary.items():
params_list = [p.replace(k, v) for p in params_list]
params = '_' + ''.join(p for p in params_list)
return 'resolve_for_' + return_type.replace('[]', '_array').lower() + params
def _MakeForwardingProxy(proxy_native, enable_jni_multiplexing=False): def _MakeForwardingProxy(proxy_native, enable_jni_multiplexing=False):
@ -787,11 +642,10 @@ def _MakeForwardingProxy(proxy_native, enable_jni_multiplexing=False):
if enable_jni_multiplexing: if enable_jni_multiplexing:
if not param_names: if not param_names:
param_names = proxy_native.switch_num + 'L' param_names = proxy_native.switch_num
else: else:
param_names = proxy_native.switch_num + 'L, ' + param_names param_names += ', %s' % proxy_native.switch_num
return_type, params_list = proxy_native.return_and_signature proxy_method_name = _GetMultiplexProxyName(proxy_native.return_type)
proxy_method_name = _GetMultiplexProxyName(return_type, params_list)
else: else:
proxy_method_name = proxy_native.hashed_proxy_name proxy_method_name = proxy_native.hashed_proxy_name
@ -829,9 +683,8 @@ def _MakeProxySignature(proxy_native,
alt_name = None alt_name = None
return_type, params_list = proxy_native.return_and_signature return_type, params_list = proxy_native.return_and_signature
proxy_name = _GetMultiplexProxyName(return_type, params_list) proxy_name = _GetMultiplexProxyName(return_type)
params_with_types = 'long switch_num' + _GetParamsListForMultiplex( params_with_types = _GetParamsListForMultiplex(params_list)
params_list, with_types=True)
elif use_proxy_hash: elif use_proxy_hash:
signature_template = string.Template(""" signature_template = string.Template("""
// Original name: ${ALT_NAME}""" + native_method_line) // Original name: ${ALT_NAME}""" + native_method_line)
@ -858,7 +711,6 @@ class ProxyOptions:
def __init__(self, **kwargs): def __init__(self, **kwargs):
self.use_hash = kwargs.get('use_hash', False) self.use_hash = kwargs.get('use_hash', False)
self.enable_jni_multiplexing = kwargs.get('enable_jni_multiplexing', False) self.enable_jni_multiplexing = kwargs.get('enable_jni_multiplexing', False)
self.manual_jni_registration = kwargs.get('manual_jni_registration', False)
self.enable_mocks = kwargs.get('enable_mocks', False) self.enable_mocks = kwargs.get('enable_mocks', False)
self.require_mocks = kwargs.get('require_mocks', False) self.require_mocks = kwargs.get('require_mocks', False)
# Can never require and disable. # Can never require and disable.
@ -914,10 +766,6 @@ def main(argv):
'--enable_jni_multiplexing', '--enable_jni_multiplexing',
action='store_true', action='store_true',
help='Enables JNI multiplexing for Java native methods') help='Enables JNI multiplexing for Java native methods')
arg_parser.add_argument(
'--manual_jni_registration',
action='store_true',
help='Manually do JNI registration - required for crazy linker')
args = arg_parser.parse_args(build_utils.ExpandFileArgs(argv[1:])) args = arg_parser.parse_args(build_utils.ExpandFileArgs(argv[1:]))
if not args.enable_proxy_mocks and args.require_mocks: if not args.enable_proxy_mocks and args.require_mocks:
@ -925,16 +773,10 @@ def main(argv):
'Invalid arguments: --require_mocks without --enable_proxy_mocks. ' 'Invalid arguments: --require_mocks without --enable_proxy_mocks. '
'Cannot require mocks if they are not enabled.') 'Cannot require mocks if they are not enabled.')
if not args.header_path and args.manual_jni_registration:
arg_parser.error(
'Invalid arguments: --manual_jni_registration without --header-path. '
'Cannot manually register JNI if there is no output header file.')
sources_files = sorted(set(build_utils.ParseGnList(args.sources_files))) sources_files = sorted(set(build_utils.ParseGnList(args.sources_files)))
proxy_opts = ProxyOptions( proxy_opts = ProxyOptions(
use_hash=args.use_proxy_hash, use_hash=args.use_proxy_hash,
enable_jni_multiplexing=args.enable_jni_multiplexing, enable_jni_multiplexing=args.enable_jni_multiplexing,
manual_jni_registration=args.manual_jni_registration,
require_mocks=args.require_mocks, require_mocks=args.require_mocks,
enable_mocks=args.enable_proxy_mocks) enable_mocks=args.enable_proxy_mocks)
@ -944,11 +786,12 @@ def main(argv):
java_file_paths.extend( java_file_paths.extend(
p for p in build_utils.ReadSourcesList(f) p for p in build_utils.ReadSourcesList(f)
if p.startswith('..') and p not in args.sources_exclusions) if p.startswith('..') and p not in args.sources_exclusions)
_Generate(java_file_paths, _Generate(
args.srcjar_path, java_file_paths,
proxy_opts=proxy_opts, args.srcjar_path,
header_path=args.header_path, proxy_opts=proxy_opts,
namespace=args.namespace) header_path=args.header_path,
namespace=args.namespace)
if args.depfile: if args.depfile:
build_utils.WriteDepfile(args.depfile, args.srcjar_path, build_utils.WriteDepfile(args.depfile, args.srcjar_path,

View File

@ -64,9 +64,9 @@
static boolean isDebug() return false; static boolean isDebug() return false;
} }
# Never inline classes, methods, or fields with this annotation, but allow # Never inline classes, methods, or fields with this annotation, but allow
# shrinking and obfuscation. # shrinking and obfuscation.
# Relevant to fields when they are needed to store strong references to objects # Relevant to fields when they are needed to store strong refrences to objects
# that are held as weak references by native code. # that are held as weak references by native code.
-if @org.chromium.base.annotations.DoNotInline class * { -if @org.chromium.base.annotations.DoNotInline class * {
*** *(...); *** *(...);
@ -81,10 +81,6 @@
@org.chromium.base.annotations.DoNotInline <fields>; @org.chromium.base.annotations.DoNotInline <fields>;
} }
# Never merge classes horizontally or vertically with this annotation.
# Relevant to classes being used as a key in maps or sets.
-keep,allowaccessmodification,allowobfuscation,allowshrinking @DoNotClassMerge class *
# Keep all CREATOR fields within Parcelable that are kept. # Keep all CREATOR fields within Parcelable that are kept.
-keepclassmembers class org.chromium.** implements android.os.Parcelable { -keepclassmembers class org.chromium.** implements android.os.Parcelable {
public static *** CREATOR; public static *** CREATOR;

View File

@ -32,7 +32,6 @@
#include "base/synchronization/lock.h" #include "base/synchronization/lock.h"
#include "base/task/single_thread_task_runner.h" #include "base/task/single_thread_task_runner.h"
#include "base/threading/thread.h" #include "base/threading/thread.h"
#include "base/time/time.h"
#include "base/timer/timer.h" #include "base/timer/timer.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/abseil-cpp/absl/types/optional.h"

View File

@ -36,6 +36,7 @@
// - libstdc++: captures bits/c++config.h for __GLIBCXX__ // - libstdc++: captures bits/c++config.h for __GLIBCXX__
#include <cstddef> #include <cstddef>
#include "base/base_export.h"
#include "build/build_config.h" #include "build/build_config.h"
namespace base { namespace base {

View File

@ -13,7 +13,6 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/callback.h" #include "base/callback.h"
#include "base/callback_helpers.h" #include "base/callback_helpers.h"
#include "base/check.h"
#include "base/synchronization/lock.h" #include "base/synchronization/lock.h"
#include "base/template_util.h" #include "base/template_util.h"
#include "base/thread_annotations.h" #include "base/thread_annotations.h"

View File

@ -881,7 +881,7 @@ BanUnconstructedRefCountedReceiver(const Receiver& receiver, Unused&&...) {
// ran fast enough, the newly created instance could be destroyed before `oo` // ran fast enough, the newly created instance could be destroyed before `oo`
// makes another reference. // makes another reference.
// Foo::Foo() { // Foo::Foo() {
// base::ThreadPool::PostTask(FROM_HERE, base::BindOnce(&Foo::Bar, this)); // base::PostTask(FROM_HERE, base::BindOnce(&Foo::Bar, this));
// } // }
// //
// scoped_refptr<Foo> oo = new Foo(); // scoped_refptr<Foo> oo = new Foo();
@ -896,7 +896,7 @@ BanUnconstructedRefCountedReceiver(const Receiver& receiver, Unused&&...) {
// // static // // static
// scoped_refptr<Foo> Foo::Create() { // scoped_refptr<Foo> Foo::Create() {
// auto foo = base::WrapRefCounted(new Foo()); // auto foo = base::WrapRefCounted(new Foo());
// base::ThreadPool::PostTask(FROM_HERE, base::BindOnce(&Foo::Bar, foo)); // base::PostTask(FROM_HERE, base::BindOnce(&Foo::Bar, foo));
// return foo; // return foo;
// } // }
// //

View File

@ -15,7 +15,6 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/callback_forward.h" #include "base/callback_forward.h"
#include "base/callback_internal.h" #include "base/callback_internal.h"
#include "base/check.h"
#include "base/notreached.h" #include "base/notreached.h"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@ -16,10 +16,8 @@
#include <utility> #include <utility>
#include "base/atomicops.h" #include "base/atomicops.h"
#include "base/base_export.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/callback.h" #include "base/callback.h"
#include "base/check.h"
namespace base { namespace base {

View File

@ -47,6 +47,7 @@
#include <utility> #include <utility>
#include "base/base_export.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/callback.h" #include "base/callback.h"
#include "base/callback_internal.h" #include "base/callback_internal.h"

View File

@ -9,7 +9,6 @@
#include <string> #include <string>
#include <type_traits> #include <type_traits>
#include "base/base_export.h"
#include "base/check.h" #include "base/check.h"
#include "base/template_util.h" #include "base/template_util.h"

View File

@ -12,7 +12,6 @@
#include <utility> #include <utility>
#include "base/as_const.h" #include "base/as_const.h"
#include "base/check.h"
#include "base/check_op.h" #include "base/check_op.h"
#include "base/containers/vector_buffer.h" #include "base/containers/vector_buffer.h"
#include "base/ranges/algorithm.h" #include "base/ranges/algorithm.h"

View File

@ -10,7 +10,6 @@
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include "base/check.h"
#include "base/check_op.h" #include "base/check_op.h"
#include "base/memory/raw_ptr.h" #include "base/memory/raw_ptr.h"

View File

@ -138,7 +138,6 @@
#include <vector> #include <vector>
#include "base/base_export.h" #include "base/base_export.h"
#include "base/check.h"
#include "base/check_op.h" #include "base/check_op.h"
#include "base/containers/stack_container.h" #include "base/containers/stack_container.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"

View File

@ -12,7 +12,6 @@
#include <new> #include <new>
#include <utility> #include <utility>
#include "base/check.h"
#include "base/check_op.h" #include "base/check_op.h"
#include "base/memory/raw_ptr.h" #include "base/memory/raw_ptr.h"

View File

@ -14,7 +14,6 @@
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include "base/check.h"
#include "base/check_op.h" #include "base/check_op.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/containers/checked_iterators.h" #include "base/containers/checked_iterators.h"

View File

@ -11,7 +11,6 @@
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include "base/check.h"
#include "base/check_op.h" #include "base/check_op.h"
#include "base/containers/util.h" #include "base/containers/util.h"
#include "base/numerics/checked_math.h" #include "base/numerics/checked_math.h"

View File

@ -5,7 +5,6 @@
#ifndef BASE_CPU_AFFINITY_POSIX_H_ #ifndef BASE_CPU_AFFINITY_POSIX_H_
#define BASE_CPU_AFFINITY_POSIX_H_ #define BASE_CPU_AFFINITY_POSIX_H_
#include "base/base_export.h"
#include "base/process/process_handle.h" #include "base/process/process_handle.h"
#include "base/threading/platform_thread.h" #include "base/threading/platform_thread.h"
#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/abseil-cpp/absl/types/optional.h"

View File

@ -15,7 +15,6 @@
#if BUILDFLAG(IS_IOS) #if BUILDFLAG(IS_IOS)
#include "base/bind.h" #include "base/bind.h"
#include "base/ios/scoped_critical_action.h" #include "base/ios/scoped_critical_action.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#endif #endif
namespace base { namespace base {
@ -23,37 +22,24 @@ namespace base {
namespace internal { namespace internal {
#if BUILDFLAG(IS_IOS) #if BUILDFLAG(IS_IOS)
// Returns true if multi-tasking is supported on this iOS device.
bool IsMultiTaskingSupported();
// This class wraps a closure so it can continue to run for a period of time // This class wraps a closure so it can continue to run for a period of time
// when the application goes to the background by using // when the application goes to the background by using
// |ios::ScopedCriticalAction|. // |ios::ScopedCriticalAction|.
class ImmediateCriticalClosure { class CriticalClosure {
public: public:
explicit ImmediateCriticalClosure(StringPiece task_name, OnceClosure closure); explicit CriticalClosure(StringPiece task_name, OnceClosure closure);
ImmediateCriticalClosure(const ImmediateCriticalClosure&) = delete; CriticalClosure(const CriticalClosure&) = delete;
ImmediateCriticalClosure& operator=(const ImmediateCriticalClosure&) = delete; CriticalClosure& operator=(const CriticalClosure&) = delete;
~ImmediateCriticalClosure(); ~CriticalClosure();
void Run(); void Run();
private: private:
ios::ScopedCriticalAction critical_action_; ios::ScopedCriticalAction critical_action_;
OnceClosure closure_; OnceClosure closure_;
}; };
// This class is identical to ImmediateCriticalClosure, but the critical action
// is started when the action runs, not when the CriticalAction is created.
class PendingCriticalClosure {
public:
explicit PendingCriticalClosure(StringPiece task_name, OnceClosure closure);
PendingCriticalClosure(const PendingCriticalClosure&) = delete;
PendingCriticalClosure& operator=(const PendingCriticalClosure&) = delete;
~PendingCriticalClosure();
void Run();
private:
absl::optional<ios::ScopedCriticalAction> critical_action_;
std::string task_name_;
OnceClosure closure_;
};
#endif // BUILDFLAG(IS_IOS) #endif // BUILDFLAG(IS_IOS)
} // namespace internal } // namespace internal
@ -61,9 +47,7 @@ class PendingCriticalClosure {
// Returns a closure that will continue to run for a period of time when the // Returns a closure that will continue to run for a period of time when the
// application goes to the background if possible on platforms where // application goes to the background if possible on platforms where
// applications don't execute while backgrounded, otherwise the original task is // applications don't execute while backgrounded, otherwise the original task is
// returned. If |is_immediate| is true, the closure will immediately prevent // returned.
// background suspension. Otherwise, the closure will wait to request background
// permission until it is run.
// //
// Example: // Example:
// file_task_runner_->PostTask( // file_task_runner_->PostTask(
@ -77,39 +61,28 @@ class PendingCriticalClosure {
// that do not complete in time for suspension. // that do not complete in time for suspension.
#if BUILDFLAG(IS_IOS) #if BUILDFLAG(IS_IOS)
inline OnceClosure MakeCriticalClosure(StringPiece task_name, inline OnceClosure MakeCriticalClosure(StringPiece task_name,
OnceClosure closure, OnceClosure closure) {
bool is_immediate) { DCHECK(internal::IsMultiTaskingSupported());
if (is_immediate) { return base::BindOnce(
return base::BindOnce(&internal::ImmediateCriticalClosure::Run, &internal::CriticalClosure::Run,
Owned(new internal::ImmediateCriticalClosure( Owned(new internal::CriticalClosure(task_name, std::move(closure))));
task_name, std::move(closure))));
} else {
return base::BindOnce(&internal::PendingCriticalClosure::Run,
Owned(new internal::PendingCriticalClosure(
task_name, std::move(closure))));
}
} }
inline OnceClosure MakeCriticalClosure(const Location& posted_from, inline OnceClosure MakeCriticalClosure(const Location& posted_from,
OnceClosure closure, OnceClosure closure) {
bool is_immediate) { return MakeCriticalClosure(posted_from.ToString(), std::move(closure));
return MakeCriticalClosure(posted_from.ToString(), std::move(closure),
is_immediate);
} }
#else // BUILDFLAG(IS_IOS) #else // BUILDFLAG(IS_IOS)
inline OnceClosure MakeCriticalClosure(StringPiece task_name, inline OnceClosure MakeCriticalClosure(StringPiece task_name,
OnceClosure closure, OnceClosure closure) {
bool is_immediate) {
// No-op for platforms where the application does not need to acquire // No-op for platforms where the application does not need to acquire
// background time for closures to finish when it goes into the background. // background time for closures to finish when it goes into the background.
return closure; return closure;
} }
inline OnceClosure MakeCriticalClosure(const Location& posted_from, inline OnceClosure MakeCriticalClosure(const Location& posted_from,
OnceClosure closure, OnceClosure closure) {
bool is_immediate) {
return closure; return closure;
} }

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