Skip to content

Commit 9c5b76f

Browse files
author
david
committed
feat: USING_FAST_MALLOC uses the util namespace
1 parent e66d509 commit 9c5b76f

File tree

16 files changed

+1171
-22
lines changed

16 files changed

+1171
-22
lines changed

bridge/CMakeLists.txt

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -619,17 +619,21 @@ elseif ($ENV{WEBF_JS_ENGINE} MATCHES "v8")
619619
bindings/v8/platform/wtf/conditional_destructor.h
620620
bindings/v8/platform/wtf/construct_traits.h
621621
bindings/v8/platform/wtf/sanitizers.h
622-
bindings/v8/platform/wtf/allocator/partition_allocator.h
623-
bindings/v8/base/apple/scoped_cftyperef.h
624-
bindings/v8/base/apple/scoped_typeref.h
625-
bindings/v8/base/memory/scoped_policy.h
622+
bindings/v8/platform/util/allocator/partition_allocator.h
623+
bindings/v8/platform/util/allocator/allocator.h
624+
bindings/v8/platform/util/allocator/partitions.cc
625+
bindings/v8/base/apple/scoped_cftyperef.h
626+
bindings/v8/base/apple/scoped_typeref.h
627+
bindings/v8/base/memory/scoped_policy.h
626628
bindings/v8/base/threading/platform_thread.cc
627-
bindings/v8/base/threading/thread_local_storage.cc
629+
bindings/v8/base/threading/thread_local_storage.cc
628630
bindings/v8/base/allocator/allocator.h
629631
bindings/v8/base/allocator/partitions.cc
630632
bindings/v8/base/allocator/partitions.h
631-
bindings/v8/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internal.h
632-
bindings/v8/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_posix.cc
633+
bindings/v8/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internal.h
634+
bindings/v8/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_posix.cc
635+
bindings/v8/base/allocator/partition_allocator/src/partition_alloc/partition_alloc.cc
636+
bindings/v8/base/allocator/partition_allocator/src/partition_alloc/memory_reclaimer.cc
633637
bindings/v8/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_constants.h
634638
bindings/v8/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager_types.h
635639
bindings/v8/base/allocator/partition_allocator/src/partition_alloc/page_allocator_constants.h
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright (C) 2019-2022 The Kraken authors. All rights reserved.
3+
* Copyright (C) 2022-present The WebF authors. All rights reserved.
4+
*/
5+
6+
#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/memory_reclaimer.h"
7+
8+
#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/partition_alloc.h"
9+
#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/no_destructor.h"
10+
#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_buildflags.h"
11+
#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_check.h"
12+
#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_config.h"
13+
14+
#if PA_BUILDFLAG(USE_STARSCAN)
15+
#include "partition_alloc/starscan/pcscan.h"
16+
#endif
17+
18+
namespace partition_alloc {
19+
20+
// static
21+
MemoryReclaimer* MemoryReclaimer::Instance() {
22+
static internal::base::NoDestructor<MemoryReclaimer> instance;
23+
return instance.get();
24+
}
25+
26+
void MemoryReclaimer::RegisterPartition(PartitionRoot* partition) {
27+
internal::ScopedGuard lock(lock_);
28+
PA_DCHECK(partition);
29+
auto it_and_whether_inserted = partitions_.insert(partition);
30+
PA_DCHECK(it_and_whether_inserted.second);
31+
}
32+
33+
void MemoryReclaimer::UnregisterPartition(PartitionRoot* partition) {
34+
internal::ScopedGuard lock(lock_);
35+
PA_DCHECK(partition);
36+
size_t erased_count = partitions_.erase(partition);
37+
PA_DCHECK(erased_count == 1u);
38+
}
39+
40+
MemoryReclaimer::MemoryReclaimer() = default;
41+
MemoryReclaimer::~MemoryReclaimer() = default;
42+
43+
void MemoryReclaimer::ReclaimAll() {
44+
constexpr int kFlags = PurgeFlags::kDecommitEmptySlotSpans |
45+
PurgeFlags::kDiscardUnusedSystemPages |
46+
PurgeFlags::kAggressiveReclaim;
47+
Reclaim(kFlags);
48+
}
49+
50+
void MemoryReclaimer::ReclaimNormal() {
51+
constexpr int kFlags = PurgeFlags::kDecommitEmptySlotSpans |
52+
PurgeFlags::kDiscardUnusedSystemPages;
53+
Reclaim(kFlags);
54+
}
55+
56+
void MemoryReclaimer::ReclaimFast() {
57+
constexpr int kFlags = PurgeFlags::kDecommitEmptySlotSpans |
58+
PurgeFlags::kDiscardUnusedSystemPages |
59+
PurgeFlags::kLimitDuration;
60+
Reclaim(kFlags);
61+
}
62+
63+
void MemoryReclaimer::Reclaim(int flags) {
64+
internal::ScopedGuard lock(
65+
lock_); // Has to protect from concurrent (Un)Register calls.
66+
67+
// PCScan quarantines freed slots. Trigger the scan first to let it call
68+
// FreeNoHooksImmediate on slots that pass the quarantine.
69+
//
70+
// In turn, FreeNoHooksImmediate may add slots to thread cache. Purge it next
71+
// so that the slots are actually freed. (This is done synchronously only for
72+
// the current thread.)
73+
//
74+
// Lastly decommit empty slot spans and lastly try to discard unused pages at
75+
// the end of the remaining active slots.
76+
#if PA_CONFIG(STARSCAN_ENABLE_STARSCAN_ON_RECLAIM) && PA_BUILDFLAG(USE_STARSCAN)
77+
{
78+
using PCScan = internal::PCScan;
79+
const auto invocation_mode = flags & PurgeFlags::kAggressiveReclaim
80+
? PCScan::InvocationMode::kForcedBlocking
81+
: PCScan::InvocationMode::kBlocking;
82+
PCScan::PerformScanIfNeeded(invocation_mode);
83+
}
84+
#endif // PA_CONFIG(STARSCAN_ENABLE_STARSCAN_ON_RECLAIM) &&
85+
// PA_BUILDFLAG(USE_STARSCAN)
86+
87+
#if PA_CONFIG(THREAD_CACHE_SUPPORTED)
88+
// Don't completely empty the thread cache outside of low memory situations,
89+
// as there is periodic purge which makes sure that it doesn't take too much
90+
// space.
91+
if (flags & PurgeFlags::kAggressiveReclaim) {
92+
ThreadCacheRegistry::Instance().PurgeAll();
93+
}
94+
#endif // PA_CONFIG(THREAD_CACHE_SUPPORTED)
95+
96+
for (auto* partition : partitions_) {
97+
partition->PurgeMemory(flags);
98+
}
99+
}
100+
101+
void MemoryReclaimer::ResetForTesting() {
102+
internal::ScopedGuard lock(lock_);
103+
partitions_.clear();
104+
}
105+
106+
} // namespace partition_alloc
107+
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright (C) 2019-2022 The Kraken authors. All rights reserved.
3+
* Copyright (C) 2022-present The WebF authors. All rights reserved.
4+
*/
5+
6+
#ifndef PARTITION_ALLOC_MEMORY_RECLAIMER_H_
7+
#define PARTITION_ALLOC_MEMORY_RECLAIMER_H_
8+
9+
#include <memory>
10+
#include <set>
11+
12+
#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/component_export.h"
13+
#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/no_destructor.h"
14+
#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/thread_annotations.h"
15+
#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time.h"
16+
#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_forward.h"
17+
#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/partition_lock.h"
18+
19+
namespace partition_alloc {
20+
21+
// Posts and handles memory reclaim tasks for PartitionAlloc.
22+
//
23+
// PartitionAlloc users are responsible for scheduling and calling the
24+
// reclamation methods with their own timers / event loops.
25+
//
26+
// Singleton as this runs as long as the process is alive, and
27+
// having multiple instances would be wasteful.
28+
class PA_COMPONENT_EXPORT(PARTITION_ALLOC) MemoryReclaimer {
29+
public:
30+
static MemoryReclaimer* Instance();
31+
32+
MemoryReclaimer(const MemoryReclaimer&) = delete;
33+
MemoryReclaimer& operator=(const MemoryReclaimer&) = delete;
34+
35+
// Internal. Do not use.
36+
// Registers a partition to be tracked by the reclaimer.
37+
void RegisterPartition(PartitionRoot* partition);
38+
// Internal. Do not use.
39+
// Unregisters a partition to be tracked by the reclaimer.
40+
void UnregisterPartition(PartitionRoot* partition);
41+
42+
// Triggers an explicit reclaim now to reclaim as much free memory as
43+
// possible. The API callers need to invoke this method periodically
44+
// if they want to use memory reclaimer.
45+
// See also GetRecommendedReclaimIntervalInMicroseconds()'s comment.
46+
void ReclaimNormal();
47+
48+
// Returns a recommended interval to invoke ReclaimNormal.
49+
int64_t GetRecommendedReclaimIntervalInMicroseconds() {
50+
return internal::base::Seconds(4).InMicroseconds();
51+
}
52+
53+
// Triggers an explicit reclaim now reclaiming all free memory
54+
void ReclaimAll();
55+
// Same as ReclaimNormal(), but return early if reclaim takes too long.
56+
void ReclaimFast();
57+
58+
private:
59+
MemoryReclaimer();
60+
~MemoryReclaimer();
61+
// |flags| is an OR of base::PartitionPurgeFlags
62+
void Reclaim(int flags);
63+
void ResetForTesting();
64+
65+
internal::Lock lock_;
66+
std::set<PartitionRoot*> partitions_ PA_GUARDED_BY(lock_);
67+
68+
friend class internal::base::NoDestructor<MemoryReclaimer>;
69+
friend class MemoryReclaimerTest;
70+
};
71+
72+
} // namespace partition_alloc
73+
74+
#endif // PARTITION_ALLOC_MEMORY_RECLAIMER_H_
75+
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
* Copyright (C) 2019-2022 The Kraken authors. All rights reserved.
3+
* Copyright (C) 2022-present The WebF authors. All rights reserved.
4+
*/
5+
6+
#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/partition_alloc.h"
7+
8+
#include <cstdint>
9+
#include <cstring>
10+
#include <memory>
11+
12+
#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager.h"
13+
#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/memory_reclaimer.h"
14+
#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/partition_address_space.h"
15+
//#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/debugging_buildflags.h"
16+
#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_buildflags.h"
17+
#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_hooks.h"
18+
#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/partition_direct_map_extent.h"
19+
#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/partition_oom.h"
20+
#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/partition_page.h"
21+
#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/partition_root.h"
22+
#include "bindings/v8/base/allocator/partition_allocator/src/partition_alloc/partition_stats.h"
23+
24+
#if PA_BUILDFLAG(USE_STARSCAN)
25+
#include "partition_alloc/starscan/pcscan.h"
26+
#endif
27+
28+
namespace partition_alloc {
29+
30+
void PartitionAllocGlobalInit(OomFunction on_out_of_memory) {
31+
// This is from page_allocator_constants.h and doesn't really fit here, but
32+
// there isn't a centralized initialization function in page_allocator.cc, so
33+
// there's no good place in that file to do a STATIC_ASSERT_OR_PA_CHECK.
34+
STATIC_ASSERT_OR_PA_CHECK(
35+
(internal::SystemPageSize() & internal::SystemPageOffsetMask()) == 0,
36+
"SystemPageSize() must be power of 2");
37+
38+
// Two partition pages are used as guard / metadata page so make sure the
39+
// super page size is bigger.
40+
STATIC_ASSERT_OR_PA_CHECK(
41+
internal::PartitionPageSize() * 4 <= internal::kSuperPageSize,
42+
"ok super page size");
43+
STATIC_ASSERT_OR_PA_CHECK(
44+
(internal::kSuperPageSize & internal::SystemPageOffsetMask()) == 0,
45+
"ok super page multiple");
46+
// Four system pages gives us room to hack out a still-guard-paged piece
47+
// of metadata in the middle of a guard partition page.
48+
STATIC_ASSERT_OR_PA_CHECK(
49+
internal::SystemPageSize() * 4 <= internal::PartitionPageSize(),
50+
"ok partition page size");
51+
STATIC_ASSERT_OR_PA_CHECK(
52+
(internal::PartitionPageSize() & internal::SystemPageOffsetMask()) == 0,
53+
"ok partition page multiple");
54+
static_assert(
55+
sizeof(internal::PartitionPageMetadata) <= internal::kPageMetadataSize,
56+
"PartitionPage should not be too big");
57+
STATIC_ASSERT_OR_PA_CHECK(
58+
internal::kPageMetadataSize * internal::NumPartitionPagesPerSuperPage() <=
59+
internal::SystemPageSize(),
60+
"page metadata fits in hole");
61+
62+
// Limit to prevent callers accidentally overflowing an int size.
63+
STATIC_ASSERT_OR_PA_CHECK(
64+
internal::MaxDirectMapped() <=
65+
(1UL << 31) + internal::DirectMapAllocationGranularity(),
66+
"maximum direct mapped allocation");
67+
68+
// Check that some of our zanier calculations worked out as expected.
69+
static_assert(internal::kSmallestBucket == internal::kAlignment,
70+
"generic smallest bucket");
71+
static_assert(internal::kMaxBucketed == 983040, "generic max bucketed");
72+
STATIC_ASSERT_OR_PA_CHECK(
73+
internal::MaxSystemPagesPerRegularSlotSpan() <= 16,
74+
"System pages per slot span must be no greater than 16.");
75+
76+
#if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
77+
STATIC_ASSERT_OR_PA_CHECK(
78+
internal::GetInSlotMetadataIndexMultiplierShift() <
79+
std::numeric_limits<size_t>::max() / 2,
80+
"Calculation in GetInSlotMetadataIndexMultiplierShift() must not "
81+
"underflow.");
82+
// Check that the GetInSlotMetadataIndexMultiplierShift() calculation is
83+
// correct.
84+
STATIC_ASSERT_OR_PA_CHECK(
85+
(1 << internal::GetInSlotMetadataIndexMultiplierShift()) ==
86+
(internal::SystemPageSize() /
87+
(sizeof(internal::InSlotMetadata) *
88+
(internal::kSuperPageSize / internal::SystemPageSize()))),
89+
"Bitshift must match the intended multiplication.");
90+
STATIC_ASSERT_OR_PA_CHECK(
91+
((sizeof(internal::InSlotMetadata) *
92+
(internal::kSuperPageSize / internal::SystemPageSize()))
93+
<< internal::GetInSlotMetadataIndexMultiplierShift()) <=
94+
internal::SystemPageSize(),
95+
"InSlotMetadata table size must be smaller than or equal to "
96+
"<= SystemPageSize().");
97+
#endif // PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
98+
99+
PA_DCHECK(on_out_of_memory);
100+
internal::g_oom_handling_function = on_out_of_memory;
101+
}
102+
103+
void PartitionAllocGlobalUninitForTesting() {
104+
#if PA_BUILDFLAG(ENABLE_THREAD_ISOLATION)
105+
internal::PartitionAddressSpace::UninitThreadIsolatedPoolForTesting();
106+
#endif
107+
internal::g_oom_handling_function = nullptr;
108+
}
109+
110+
PartitionAllocator::PartitionAllocator() = default;
111+
112+
PartitionAllocator::~PartitionAllocator() {
113+
MemoryReclaimer::Instance()->UnregisterPartition(&partition_root_);
114+
}
115+
116+
void PartitionAllocator::init(PartitionOptions opts) {
117+
#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
118+
PA_CHECK(opts.thread_cache == PartitionOptions::kDisabled)
119+
<< "Cannot use a thread cache when PartitionAlloc is malloc().";
120+
#endif
121+
partition_root_.Init(opts);
122+
#if PA_BUILDFLAG(ENABLE_THREAD_ISOLATION)
123+
// The MemoryReclaimer won't have write access to the partition, so skip
124+
// registration.
125+
const bool use_memory_reclaimer = !opts.thread_isolation.enabled;
126+
#else
127+
constexpr bool use_memory_reclaimer = true;
128+
#endif
129+
if (use_memory_reclaimer) {
130+
MemoryReclaimer::Instance()->RegisterPartition(&partition_root_);
131+
}
132+
}
133+
134+
} // namespace partition_alloc
135+

0 commit comments

Comments
 (0)