Skip to content

Commit

Permalink
Add support of allocating different sizes of storage in StorageProvid…
Browse files Browse the repository at this point in the history
…er (facebook#1504)

Summary:
Pull Request resolved: facebook#1504

Large segment needs to be backed by a large storage size.
StorageProvider currently always allocate fixed size of storage
determined by HERMESVM_LOG_HEAP_SEGMENT_SIZE.

This diffs adds support of allocating larger storage with below
changes:
1. `newStorage()` and `deleteStorage()` takes additional `sz` parameter.
2. For `MallocStorageProvider` and `VMAllocateStorageProvider`, simply
change the previous fixed storage size to passed in `sz`.
3. For `ContiguousVAStorageProvider`, use a BitVector to manage
allocations and deallocations. This can be improved later if we observe
fragmentations.

The support of enabling different sizes of heap segment will be added
later.

Differential Revision: D61676721
  • Loading branch information
lavenzg authored and facebook-github-bot committed Dec 20, 2024
1 parent 87cbad1 commit c542cb8
Show file tree
Hide file tree
Showing 10 changed files with 256 additions and 133 deletions.
2 changes: 2 additions & 0 deletions include/hermes/Support/ErrorHandling.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ enum class OOMError : int {
Effective,
// When an allocation is requested that is larger than a heap segment.
SuperSegmentAlloc,
// When requesting a segment that is too large to create.
TooLargeSegmentRequest,
// When a CopyableVector's capacity overflows what an integer can hold.
CopyableVectorCapacityIntegerOverflow,
// This happens when a unit test attempts to allocate more storages
Expand Down
9 changes: 4 additions & 5 deletions include/hermes/VM/HeapRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class HeapRuntime {
public:
~HeapRuntime() {
runtime_->~RT();
sp_->deleteStorage(runtime_);
sp_->deleteStorage(runtime_, kHeapRuntimeStorageSize);
}

/// Allocate a segment and create an aliased shared_ptr that points to the
Expand All @@ -36,17 +36,16 @@ class HeapRuntime {

private:
HeapRuntime(std::shared_ptr<StorageProvider> sp) : sp_{std::move(sp)} {
auto ptrOrError = sp_->newStorage("hermes-rt");
auto ptrOrError = sp_->newStorage(kHeapRuntimeStorageSize, "hermes-rt");
if (!ptrOrError)
hermes_fatal("Cannot initialize Runtime storage.", ptrOrError.getError());
static_assert(
sizeof(RT) < FixedSizeHeapSegment::storageSize(),
"Segments too small.");
static_assert(sizeof(RT) < kHeapRuntimeStorageSize, "Segments too small.");
runtime_ = static_cast<RT *>(*ptrOrError);
}

std::shared_ptr<StorageProvider> sp_;
RT *runtime_;
static constexpr size_t kHeapRuntimeStorageSize = FixedSizeHeapSegment::kSize;
};
} // namespace vm
} // namespace hermes
Expand Down
4 changes: 2 additions & 2 deletions include/hermes/VM/LimitedStorageProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ class LimitedStorageProvider final : public StorageProvider {
: delegate_(std::move(provider)), limit_(limit) {}

protected:
llvh::ErrorOr<void *> newStorageImpl(const char *name) override;
llvh::ErrorOr<void *> newStorageImpl(size_t sz, const char *name) override;

void deleteStorageImpl(void *storage) override;
void deleteStorageImpl(void *storage, size_t sz) override;
};

} // namespace vm
Expand Down
30 changes: 15 additions & 15 deletions include/hermes/VM/StorageProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,17 @@ class StorageProvider {

/// @}

/// Create a new segment memory space.
llvh::ErrorOr<void *> newStorage() {
return newStorage(nullptr);
}
/// Create a new segment memory space and give this memory the name \p name.
/// \return A pointer to a block of memory that has
/// FixedSizeHeapSegment::storageSize() bytes, and is aligned on
/// FixedSizeHeapSegment::storageSize().
llvh::ErrorOr<void *> newStorage(const char *name);
/// \return A pointer to a block of memory that has \p sz bytes, and is
/// aligned on AlignedHeapSegment::kSegmentUnitSize. Note that \p sz must
/// be non-zero and equals to a multiple of
/// AlignedHeapSegment::kSegmentUnitSize.
llvh::ErrorOr<void *> newStorage(size_t sz, const char *name = nullptr);

/// Delete the given segment's memory space, and make it available for re-use.
/// \post Nothing in the range [storage, storage +
/// FixedSizeHeapSegment::storageSize()) is valid memory to be read or
/// written.
void deleteStorage(void *storage);
/// Note that \p sz must be the same as used to allocating \p storage.
/// \post Nothing in the range [storage, storage + sz) is valid memory to be
/// read or written.
void deleteStorage(void *storage, size_t sz);

/// The number of storages this provider has allocated in its lifetime.
size_t numSucceededAllocs() const;
Expand All @@ -68,8 +64,12 @@ class StorageProvider {
size_t numLiveAllocs() const;

protected:
virtual llvh::ErrorOr<void *> newStorageImpl(const char *name) = 0;
virtual void deleteStorageImpl(void *storage) = 0;
/// \pre \p sz is non-zero and equal to a multiple of
/// AlignedHeapSegment::kSegmentUnitSize.
virtual llvh::ErrorOr<void *> newStorageImpl(size_t sz, const char *name) = 0;
/// \pre \p sz is non-zero and equal to a multiple of
/// AlignedHeapSegment::kSegmentUnitSize.
virtual void deleteStorageImpl(void *storage, size_t sz) = 0;

private:
size_t numSucceededAllocs_{0};
Expand Down
2 changes: 2 additions & 0 deletions lib/Support/ErrorHandling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ const std::error_category &oom_category() {
return "Effective OOM";
case OOMError::SuperSegmentAlloc:
return "Allocation occurred that was larger than a heap segment";
case OOMError::TooLargeSegmentRequest:
return "Requesting a heap segment that is too large to create";
case OOMError::CopyableVectorCapacityIntegerOverflow:
return "CopyableVector capacity integer overflow";
case OOMError::TestVMLimitReached:
Expand Down
14 changes: 8 additions & 6 deletions lib/VM/LimitedStorageProvider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,22 @@
namespace hermes {
namespace vm {

llvh::ErrorOr<void *> LimitedStorageProvider::newStorageImpl(const char *name) {
llvh::ErrorOr<void *> LimitedStorageProvider::newStorageImpl(
size_t sz,
const char *name) {
if (limit_ < FixedSizeHeapSegment::storageSize()) {
return make_error_code(OOMError::TestVMLimitReached);
}
limit_ -= FixedSizeHeapSegment::storageSize();
return delegate_->newStorage(name);
limit_ -= sz;
return delegate_->newStorage(sz, name);
}

void LimitedStorageProvider::deleteStorageImpl(void *storage) {
void LimitedStorageProvider::deleteStorageImpl(void *storage, size_t sz) {
if (!storage) {
return;
}
delegate_->deleteStorage(storage);
limit_ += FixedSizeHeapSegment::storageSize();
delegate_->deleteStorage(storage, sz);
limit_ += sz;
}

} // namespace vm
Expand Down
Loading

0 comments on commit c542cb8

Please sign in to comment.