Skip to content

Commit 2617ce6

Browse files
lavenzgfacebook-github-bot
authored andcommitted
Move memory layout and common methods of AlignedHeapSegment to a base class (#1510)
Summary: The large heap segment type should have the same storage layout as current AlignedHeapSegment, and share a few common methods. Abstract these to a base class, and make both FixedSizeHeapSegment and JumboHeapSegment inherit from the base type. Differential Revision: D61675022
1 parent c0b2c60 commit 2617ce6

23 files changed

+540
-487
lines changed

include/hermes/VM/AlignedHeapSegment.h

+286-245
Large diffs are not rendered by default.

include/hermes/VM/CardTableNC.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ namespace vm {
2323

2424
/// The card table optimizes young gen collections by restricting the amount of
2525
/// heap belonging to the old gen that must be scanned. The card table expects
26-
/// to be constructed inside an AlignedHeapSegment's storage, at some position
26+
/// to be constructed inside an FixedSizeHeapSegment's storage, at some position
2727
/// before the allocation region, and covers the extent of that storage's
2828
/// memory.
2929
///

include/hermes/VM/GCBase.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ enum XorPtrKeyID {
226226
/// Return the maximum amount of bytes holdable by this heap.
227227
/// gcheapsize_t max() const;
228228
/// Return the total amount of bytes of storage this GC will require.
229-
/// This will be a multiple of AlignedHeapSegment::storageSize().
229+
/// This will be a multiple of FixedSizeHeapSegment::storageSize().
230230
/// gcheapsize_t storageFootprint() const;
231231
///
232232
class GCBase {

include/hermes/VM/HadesGC.h

+25-25
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class HadesGC final : public GCBase {
7676
static constexpr uint32_t maxAllocationSizeImpl() {
7777
// The largest allocation allowable in Hades is the max size a single
7878
// segment supports.
79-
return AlignedHeapSegment::maxSize();
79+
return FixedSizeHeapSegment::maxSize();
8080
}
8181

8282
static constexpr uint32_t minAllocationSizeImpl() {
@@ -297,7 +297,7 @@ class HadesGC final : public GCBase {
297297

298298
/// \return true if the pointer lives in the young generation.
299299
bool inYoungGen(const void *p) const override {
300-
return youngGen_.lowLim() == AlignedHeapSegment::storageStart(p);
300+
return youngGen_.lowLim() == FixedSizeHeapSegment::storageStart(p);
301301
}
302302
bool inYoungGen(CompressedPointer p) const {
303303
return p.getSegmentStart() == youngGenCP_;
@@ -361,34 +361,34 @@ class HadesGC final : public GCBase {
361361
/// Call \p callback on every non-freelist cell allocated in this segment.
362362
template <typename CallbackFunction>
363363
static void forAllObjsInSegment(
364-
AlignedHeapSegment &seg,
364+
FixedSizeHeapSegment &seg,
365365
CallbackFunction callback);
366366
/// Only call the callback on cells without forwarding pointers.
367367
template <typename CallbackFunction>
368368
static void forCompactedObjsInSegment(
369-
AlignedHeapSegment &seg,
369+
FixedSizeHeapSegment &seg,
370370
CallbackFunction callback,
371371
PointerBase &base);
372372

373373
class OldGen final {
374374
public:
375375
explicit OldGen(HadesGC &gc);
376376

377-
std::deque<AlignedHeapSegment>::iterator begin();
378-
std::deque<AlignedHeapSegment>::iterator end();
379-
std::deque<AlignedHeapSegment>::const_iterator begin() const;
380-
std::deque<AlignedHeapSegment>::const_iterator end() const;
377+
std::deque<FixedSizeHeapSegment>::iterator begin();
378+
std::deque<FixedSizeHeapSegment>::iterator end();
379+
std::deque<FixedSizeHeapSegment>::const_iterator begin() const;
380+
std::deque<FixedSizeHeapSegment>::const_iterator end() const;
381381

382382
size_t numSegments() const;
383383

384-
AlignedHeapSegment &operator[](size_t i);
384+
FixedSizeHeapSegment &operator[](size_t i);
385385

386386
/// Take ownership of the given segment.
387-
void addSegment(AlignedHeapSegment seg);
387+
void addSegment(FixedSizeHeapSegment seg);
388388

389389
/// Remove the last segment from the OG.
390390
/// \return the segment that was removed.
391-
AlignedHeapSegment popSegment();
391+
FixedSizeHeapSegment popSegment();
392392

393393
/// Indicate that OG should target having a size of \p targetSizeBytes.
394394
void setTargetSizeBytes(size_t targetSizeBytes);
@@ -507,7 +507,7 @@ class HadesGC final : public GCBase {
507507
static constexpr size_t kMinSizeForLargeBlock = 1
508508
<< kLogMinSizeForLargeBlock;
509509
static constexpr size_t kNumLargeFreelistBuckets =
510-
llvh::detail::ConstantLog2<AlignedHeapSegment::maxSize()>::value -
510+
llvh::detail::ConstantLog2<FixedSizeHeapSegment::maxSize()>::value -
511511
kLogMinSizeForLargeBlock + 1;
512512
static constexpr size_t kNumFreelistBuckets =
513513
kNumSmallFreelistBuckets + kNumLargeFreelistBuckets;
@@ -578,7 +578,7 @@ class HadesGC final : public GCBase {
578578

579579
/// Use a std::deque instead of a std::vector so that references into it
580580
/// remain valid across a push_back.
581-
std::deque<AlignedHeapSegment> segments_;
581+
std::deque<FixedSizeHeapSegment> segments_;
582582

583583
/// See \c targetSizeBytes() above.
584584
ExponentialMovingAverage targetSizeBytes_{0, 0};
@@ -660,9 +660,9 @@ class HadesGC final : public GCBase {
660660
/// Keeps the storage provider alive until after the GC is fully destructed.
661661
std::shared_ptr<StorageProvider> provider_;
662662

663-
/// youngGen is a bump-pointer space, so it can re-use AlignedHeapSegment.
663+
/// youngGen is a bump-pointer space, so it can re-use FixedSizeHeapSegment.
664664
/// Protected by gcMutex_.
665-
AlignedHeapSegment youngGen_;
665+
FixedSizeHeapSegment youngGen_;
666666
AssignableCompressedPointer youngGenCP_;
667667

668668
/// List of cells in YG that have finalizers. Iterate through this to clean
@@ -672,7 +672,7 @@ class HadesGC final : public GCBase {
672672

673673
/// Since YG collection times are the primary driver of pause times, it is
674674
/// useful to have a knob to reduce the effective size of the YG. This number
675-
/// is the fraction of AlignedHeapSegment::maxSize() that we should use for
675+
/// is the fraction of FixedSizeHeapSegment::maxSize() that we should use for
676676
/// the YG.. Note that we only set the YG size using this at the end of the
677677
/// first real YG, since doing it for direct promotions would waste OG memory
678678
/// without a pause time benefit.
@@ -772,7 +772,7 @@ class HadesGC final : public GCBase {
772772
/// \return true if the pointer lives in the segment that is being marked or
773773
/// evacuated for compaction.
774774
bool contains(const void *p) const {
775-
return start == AlignedHeapSegment::storageStart(p);
775+
return start == FixedSizeHeapSegment::storageStart(p);
776776
}
777777
bool contains(CompressedPointer p) const {
778778
return p.getSegmentStart() == startCP;
@@ -781,7 +781,7 @@ class HadesGC final : public GCBase {
781781
/// \return true if the pointer lives in the segment that is currently being
782782
/// evacuated for compaction.
783783
bool evacContains(const void *p) const {
784-
return evacStart == AlignedHeapSegment::storageStart(p);
784+
return evacStart == FixedSizeHeapSegment::storageStart(p);
785785
}
786786
bool evacContains(CompressedPointer p) const {
787787
return p.getSegmentStart() == evacStartCP;
@@ -829,7 +829,7 @@ class HadesGC final : public GCBase {
829829
/// The segment being compacted. This should be removed from the OG right
830830
/// after it is identified, and freed entirely once the compaction is
831831
/// complete.
832-
std::shared_ptr<AlignedHeapSegment> segment;
832+
std::shared_ptr<FixedSizeHeapSegment> segment;
833833
} compactee_;
834834

835835
/// The number of compactions this GC has performed.
@@ -964,7 +964,7 @@ class HadesGC final : public GCBase {
964964
template <bool CompactionEnabled>
965965
void scanDirtyCardsForSegment(
966966
EvacAcceptor<CompactionEnabled> &acceptor,
967-
AlignedHeapSegment &segment);
967+
FixedSizeHeapSegment &segment);
968968

969969
/// Find all pointers from OG into the YG/compactee during a YG collection.
970970
/// This is done quickly through use of write barriers that detect the
@@ -1011,19 +1011,19 @@ class HadesGC final : public GCBase {
10111011
uint64_t heapFootprint() const;
10121012

10131013
/// Accessor for the YG.
1014-
AlignedHeapSegment &youngGen() {
1014+
FixedSizeHeapSegment &youngGen() {
10151015
return youngGen_;
10161016
}
1017-
const AlignedHeapSegment &youngGen() const {
1017+
const FixedSizeHeapSegment &youngGen() const {
10181018
return youngGen_;
10191019
}
10201020

10211021
/// Create a new segment (to be used by either YG or OG).
1022-
llvh::ErrorOr<AlignedHeapSegment> createSegment();
1022+
llvh::ErrorOr<FixedSizeHeapSegment> createSegment();
10231023

10241024
/// Set a given segment as the YG segment.
10251025
/// \return the previous YG segment.
1026-
AlignedHeapSegment setYoungGen(AlignedHeapSegment seg);
1026+
FixedSizeHeapSegment setYoungGen(FixedSizeHeapSegment seg);
10271027

10281028
/// Get/set the current number of external bytes used by the YG.
10291029
size_t getYoungGenExternalBytes() const;
@@ -1048,7 +1048,7 @@ class HadesGC final : public GCBase {
10481048
/// \param extraName append this to the name of the segment. Must be
10491049
/// non-empty.
10501050
void addSegmentExtentToCrashManager(
1051-
const AlignedHeapSegment &seg,
1051+
const FixedSizeHeapSegment &seg,
10521052
const std::string &extraName);
10531053

10541054
/// Deletes a segment from the CrashManager's custom data.

include/hermes/VM/HeapRuntime.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ class HeapRuntime {
4040
if (!ptrOrError)
4141
hermes_fatal("Cannot initialize Runtime storage.", ptrOrError.getError());
4242
static_assert(
43-
sizeof(RT) < AlignedHeapSegment::storageSize(), "Segments too small.");
43+
sizeof(RT) < FixedSizeHeapSegment::storageSize(),
44+
"Segments too small.");
4445
runtime_ = static_cast<RT *>(*ptrOrError);
4546
}
4647

include/hermes/VM/StorageProvider.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,14 @@ class StorageProvider {
4343
}
4444
/// Create a new segment memory space and give this memory the name \p name.
4545
/// \return A pointer to a block of memory that has
46-
/// AlignedHeapSegment::storageSize() bytes, and is aligned on
47-
/// AlignedHeapSegment::storageSize().
46+
/// FixedSizeHeapSegment::storageSize() bytes, and is aligned on
47+
/// FixedSizeHeapSegment::storageSize().
4848
llvh::ErrorOr<void *> newStorage(const char *name);
4949

5050
/// Delete the given segment's memory space, and make it available for re-use.
5151
/// \post Nothing in the range [storage, storage +
52-
/// AlignedHeapSegment::storageSize()) is valid memory to be read or written.
52+
/// FixedSizeHeapSegment::storageSize()) is valid memory to be read or
53+
/// written.
5354
void deleteStorage(void *storage);
5455

5556
/// The number of storages this provider has allocated in its lifetime.

lib/VM/LimitedStorageProvider.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ namespace hermes {
1414
namespace vm {
1515

1616
llvh::ErrorOr<void *> LimitedStorageProvider::newStorageImpl(const char *name) {
17-
if (limit_ < AlignedHeapSegment::storageSize()) {
17+
if (limit_ < FixedSizeHeapSegment::storageSize()) {
1818
return make_error_code(OOMError::TestVMLimitReached);
1919
}
20-
limit_ -= AlignedHeapSegment::storageSize();
20+
limit_ -= FixedSizeHeapSegment::storageSize();
2121
return delegate_->newStorage(name);
2222
}
2323

@@ -26,7 +26,7 @@ void LimitedStorageProvider::deleteStorageImpl(void *storage) {
2626
return;
2727
}
2828
delegate_->deleteStorage(storage);
29-
limit_ += AlignedHeapSegment::storageSize();
29+
limit_ += FixedSizeHeapSegment::storageSize();
3030
}
3131

3232
} // namespace vm

lib/VM/Runtime.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ std::shared_ptr<Runtime> Runtime::create(const RuntimeConfig &runtimeConfig) {
159159
uint64_t maxHeapSize = runtimeConfig.getGCConfig().getMaxHeapSize();
160160
// Allow some extra segments for the runtime, and as a buffer for the GC.
161161
uint64_t providerSize = std::min<uint64_t>(
162-
1ULL << 32, maxHeapSize + AlignedHeapSegment::storageSize() * 4);
162+
1ULL << 32, maxHeapSize + FixedSizeHeapSegment::storageSize() * 4);
163163
std::shared_ptr<StorageProvider> sp =
164164
StorageProvider::contiguousVAProvider(providerSize);
165165
auto rt = HeapRuntime<Runtime>::create(sp);
@@ -252,7 +252,6 @@ void RuntimeBase::registerHeapSegment(unsigned idx, void *lowLim) {
252252
reinterpret_cast<char *>(lowLim) - (idx << AlignedHeapSegment::kLogSize);
253253
segmentMap[idx] = bias;
254254
#endif
255-
assert(lowLim == AlignedHeapSegment::storageStart(lowLim) && "Precondition");
256255
AlignedHeapSegment::setSegmentIndexFromStart(lowLim, idx);
257256
}
258257

lib/VM/StorageProvider.cpp

+18-17
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,12 @@ namespace {
5757

5858
bool isAligned(void *p) {
5959
return (reinterpret_cast<uintptr_t>(p) &
60-
(AlignedHeapSegment::storageSize() - 1)) == 0;
60+
(FixedSizeHeapSegment::storageSize() - 1)) == 0;
6161
}
6262

6363
char *alignAlloc(void *p) {
6464
return reinterpret_cast<char *>(llvh::alignTo(
65-
reinterpret_cast<uintptr_t>(p), AlignedHeapSegment::storageSize()));
65+
reinterpret_cast<uintptr_t>(p), FixedSizeHeapSegment::storageSize()));
6666
}
6767

6868
void *getMmapHint() {
@@ -85,9 +85,9 @@ class VMAllocateStorageProvider final : public StorageProvider {
8585
class ContiguousVAStorageProvider final : public StorageProvider {
8686
public:
8787
ContiguousVAStorageProvider(size_t size)
88-
: size_(llvh::alignTo<AlignedHeapSegment::storageSize()>(size)) {
88+
: size_(llvh::alignTo<FixedSizeHeapSegment::storageSize()>(size)) {
8989
auto result = oscompat::vm_reserve_aligned(
90-
size_, AlignedHeapSegment::storageSize(), getMmapHint());
90+
size_, FixedSizeHeapSegment::storageSize(), getMmapHint());
9191
if (!result)
9292
hermes_fatal("Contiguous storage allocation failed.", result.getError());
9393
level_ = start_ = static_cast<char *>(*result);
@@ -104,26 +104,27 @@ class ContiguousVAStorageProvider final : public StorageProvider {
104104
freelist_.pop_back();
105105
} else if (level_ < start_ + size_) {
106106
storage =
107-
std::exchange(level_, level_ + AlignedHeapSegment::storageSize());
107+
std::exchange(level_, level_ + FixedSizeHeapSegment::storageSize());
108108
} else {
109109
return make_error_code(OOMError::MaxStorageReached);
110110
}
111-
auto res = oscompat::vm_commit(storage, AlignedHeapSegment::storageSize());
111+
auto res =
112+
oscompat::vm_commit(storage, FixedSizeHeapSegment::storageSize());
112113
if (res) {
113-
oscompat::vm_name(storage, AlignedHeapSegment::storageSize(), name);
114+
oscompat::vm_name(storage, FixedSizeHeapSegment::storageSize(), name);
114115
}
115116
return res;
116117
}
117118

118119
void deleteStorageImpl(void *storage) override {
119120
assert(
120121
!llvh::alignmentAdjustment(
121-
storage, AlignedHeapSegment::storageSize()) &&
122+
storage, FixedSizeHeapSegment::storageSize()) &&
122123
"Storage not aligned");
123124
assert(storage >= start_ && storage < level_ && "Storage not in region");
124125
oscompat::vm_name(
125-
storage, AlignedHeapSegment::storageSize(), kFreeRegionName);
126-
oscompat::vm_uncommit(storage, AlignedHeapSegment::storageSize());
126+
storage, FixedSizeHeapSegment::storageSize(), kFreeRegionName);
127+
oscompat::vm_uncommit(storage, FixedSizeHeapSegment::storageSize());
127128
freelist_.push_back(storage);
128129
}
129130

@@ -149,11 +150,11 @@ class MallocStorageProvider final : public StorageProvider {
149150

150151
llvh::ErrorOr<void *> VMAllocateStorageProvider::newStorageImpl(
151152
const char *name) {
152-
assert(AlignedHeapSegment::storageSize() % oscompat::page_size() == 0);
153+
assert(FixedSizeHeapSegment::storageSize() % oscompat::page_size() == 0);
153154
// Allocate the space, hoping it will be the correct alignment.
154155
auto result = oscompat::vm_allocate_aligned(
155-
AlignedHeapSegment::storageSize(),
156-
AlignedHeapSegment::storageSize(),
156+
FixedSizeHeapSegment::storageSize(),
157+
FixedSizeHeapSegment::storageSize(),
157158
getMmapHint());
158159
if (!result) {
159160
return result;
@@ -162,25 +163,25 @@ llvh::ErrorOr<void *> VMAllocateStorageProvider::newStorageImpl(
162163
assert(isAligned(mem));
163164
(void)&isAligned;
164165
#ifdef HERMESVM_ALLOW_HUGE_PAGES
165-
oscompat::vm_hugepage(mem, AlignedHeapSegment::storageSize());
166+
oscompat::vm_hugepage(mem, FixedSizeHeapSegment::storageSize());
166167
#endif
167168

168169
// Name the memory region on platforms that support naming.
169-
oscompat::vm_name(mem, AlignedHeapSegment::storageSize(), name);
170+
oscompat::vm_name(mem, FixedSizeHeapSegment::storageSize(), name);
170171
return mem;
171172
}
172173

173174
void VMAllocateStorageProvider::deleteStorageImpl(void *storage) {
174175
if (!storage) {
175176
return;
176177
}
177-
oscompat::vm_free_aligned(storage, AlignedHeapSegment::storageSize());
178+
oscompat::vm_free_aligned(storage, FixedSizeHeapSegment::storageSize());
178179
}
179180

180181
llvh::ErrorOr<void *> MallocStorageProvider::newStorageImpl(const char *name) {
181182
// name is unused, can't name malloc memory.
182183
(void)name;
183-
void *mem = checkedMalloc2(AlignedHeapSegment::storageSize(), 2u);
184+
void *mem = checkedMalloc2(FixedSizeHeapSegment::storageSize(), 2u);
184185
void *lowLim = alignAlloc(mem);
185186
assert(isAligned(lowLim) && "New storage should be aligned");
186187
lowLimToAllocHandle_[lowLim] = mem;

0 commit comments

Comments
 (0)