blob: 2a2c221cf1f075ddd7c23e6036bd59ca3bb22773 [file] [log] [blame]
// Copyright 2024 the V8 project 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 V8_INIT_ISOLATE_GROUP_H_
#define V8_INIT_ISOLATE_GROUP_H_
#include <memory>
#include "src/base/page-allocator.h"
#include "src/common/globals.h"
#include "src/flags/flags.h"
#include "src/utils/allocation.h"
namespace v8 {
namespace base {
template <typename T>
class LeakyObject;
} // namespace base
namespace internal {
// An IsolateGroup allows an API user to control which isolates get allocated
// together in a shared pointer cage.
//
// The standard configuration of V8 is to enable pointer compression and to
// allocate all isolates in a single shared pointer cage
// (V8_COMPRESS_POINTERS_IN_SHARED_CAGE). This also enables the sandbox
// (V8_ENABLE_SANDBOX), of which there can currently be only one per process, as
// it requires a large part of the virtual address space.
//
// The standard configuration comes with a limitation, in that the total size of
// the compressed pointer cage is limited to 4 GB. Some API users would like
// pointer compression but also want to avoid the 4 GB limit of the shared
// pointer cage. Isolate groups allow users to declare which isolates should be
// co-located in a single pointer cage.
//
// Isolate groups are useful only if pointer compression is enabled. Otherwise,
// the isolate could just allocate pages from the global system allocator;
// there's no need to stay within any particular address range. If pointer
// compression is disabled, isolate groups are a no-op.
//
// Note that JavaScript objects can only be passed between isolates of the same
// group. Ensuring this invariant is the responsibility of the API user.
class V8_EXPORT_PRIVATE IsolateGroup final {
public:
// Create a new isolate group, allocating a fresh pointer cage if pointer
// compression is enabled.
//
// The pointer cage for isolates in this group will be released when the
// group's refcount drops to zero. The group's initial refcount is 1.
//
// Note that if pointer compression is disabled, isolates are not grouped and
// no memory is associated with the isolate group.
static IsolateGroup* New();
// Some configurations (e.g. V8_ENABLE_SANDBOX) put all isolates into a single
// group. InitializeOncePerProcess should be called early on to initialize
// the process-wide group. If this configuration has no process-wide isolate
// group, the result is nullptr.
static IsolateGroup* AcquireGlobal();
static void InitializeOncePerProcess();
// Obtain a fresh reference on the isolate group.
IsolateGroup* Acquire() {
DCHECK_LT(0, reference_count_.load());
reference_count_++;
return this;
}
// Release a reference on an isolate group, possibly freeing any shared memory
// resources.
void Release() {
DCHECK_LT(0, reference_count_.load());
if (--reference_count_ == 0) delete this;
}
v8::PageAllocator* page_allocator() const { return page_allocator_; }
VirtualMemoryCage* GetPtrComprCage() const {
return pointer_compression_cage_;
}
VirtualMemoryCage* GetTrustedPtrComprCage() const {
return trusted_pointer_compression_cage_;
}
Address GetPtrComprCageBase() const { return GetPtrComprCage()->base(); }
Address GetTrustedPtrComprCageBase() const {
return GetTrustedPtrComprCage()->base();
}
private:
friend class ::v8::base::LeakyObject<IsolateGroup>;
static IsolateGroup* GetProcessWideIsolateGroup();
IsolateGroup() {}
~IsolateGroup() { DCHECK_EQ(reference_count_.load(), 0); }
IsolateGroup(const IsolateGroup&) = delete;
IsolateGroup& operator=(const IsolateGroup&) = delete;
friend class PoolTest;
// Only used for testing.
static void ReleaseGlobal();
std::atomic<int> reference_count_{1};
v8::PageAllocator* page_allocator_ = nullptr;
VirtualMemoryCage* trusted_pointer_compression_cage_ = nullptr;
VirtualMemoryCage* pointer_compression_cage_ = nullptr;
VirtualMemoryCage reservation_;
};
} // namespace internal
} // namespace v8
#endif // V8_INIT_ISOLATE_GROUP_H_