34using InMemoryIndexValueT = InMemoryIndexT::value_type;
49 Kind getKind()
const {
return IndexAndKind.getInt(); }
50 const InMemoryIndexValueT &getIndex()
const {
51 assert(IndexAndKind.getPointer());
52 return *IndexAndKind.getPointer();
55 ArrayRef<uint8_t> getHash()
const {
return getIndex().Hash; }
57 InMemoryObject() =
delete;
58 InMemoryObject(InMemoryObject &&) =
delete;
59 InMemoryObject(
const InMemoryObject &) =
delete;
60 InMemoryObject &operator=(
const InMemoryObject &) =
delete;
61 InMemoryObject &operator=(InMemoryObject &&) =
delete;
62 virtual ~InMemoryObject() =
default;
65 InMemoryObject(Kind K,
const InMemoryIndexValueT &
I) : IndexAndKind(&
I,
K) {}
71 PointerIntPair<const InMemoryIndexValueT *, NumKindBits, Kind> IndexAndKind;
72 static_assert((1U << NumKindBits) <=
alignof(InMemoryIndexValueT),
73 "Kind will clobber pointer");
74 static_assert(((int)Kind::Max >> NumKindBits) == 0,
"Kind will be truncated");
77 ArrayRef<char> getData()
const;
82class InMemoryRefObject final :
public InMemoryObject {
84 static constexpr Kind KindValue = Kind::RefNode;
85 static bool classof(
const InMemoryObject *O) {
86 return O->getKind() == KindValue;
91 ArrayRef<char> getDataImpl()
const {
return Data; }
92 ArrayRef<char> getData()
const {
return Data; }
94 static InMemoryRefObject &create(function_ref<
void *(
size_t Size)> Allocate,
95 const InMemoryIndexValueT &
I,
97 ArrayRef<char> Data) {
98 void *Mem = Allocate(
sizeof(InMemoryRefObject));
99 return *
new (Mem) InMemoryRefObject(
I, Refs, Data);
103 InMemoryRefObject(
const InMemoryIndexValueT &
I,
105 : InMemoryObject(KindValue,
I), Refs(Refs), Data(Data) {
108 assert(*Data.end() == 0 &&
"Expected null-termination");
115class InMemoryInlineObject final
116 :
public InMemoryObject,
120 static constexpr Kind KindValue = Kind::InlineNode;
121 static bool classof(
const InMemoryObject *O) {
122 return O->getKind() == KindValue;
127 return ArrayRef(getTrailingObjects<const InMemoryObject *>(), NumRefs);
130 ArrayRef<char> getData()
const {
return getDataImpl(); }
131 ArrayRef<char> getDataImpl()
const {
132 return ArrayRef(getTrailingObjects<char>(), DataSize);
135 static InMemoryInlineObject &
136 create(function_ref<
void *(
size_t Size)> Allocate,
138 ArrayRef<char>
Data) {
139 void *Mem = Allocate(
sizeof(InMemoryInlineObject) +
140 sizeof(uintptr_t) * Refs.
size() +
Data.size() + 1);
141 return *
new (Mem) InMemoryInlineObject(
I, Refs,
Data);
144 size_t numTrailingObjects(OverloadToken<const InMemoryObject *>)
const {
149 InMemoryInlineObject(
const InMemoryIndexValueT &
I,
152 : InMemoryObject(KindValue,
I), NumRefs(Refs.
size()),
154 auto *BeginRefs =
reinterpret_cast<const InMemoryObject **
>(
this + 1);
156 auto *BeginData =
reinterpret_cast<char *
>(BeginRefs + NumRefs);
158 BeginData[
Data.size()] = 0;
167 Expected<ObjectRef> storeImpl(ArrayRef<uint8_t> ComputedHash,
169 ArrayRef<char>
Data)
final;
172 storeFromNullTerminatedRegion(ArrayRef<uint8_t> ComputedHash,
173 sys::fs::mapped_file_region Map)
override;
175 CASID getID(
const InMemoryIndexValueT &
I)
const {
179 CASID getID(
const InMemoryObject &O)
const {
return getID(
O.getIndex()); }
181 ObjectHandle getObjectHandle(
const InMemoryObject &Node)
const {
182 assert(!(
reinterpret_cast<uintptr_t
>(&Node) & 0x1ULL));
183 return makeObjectHandle(
reinterpret_cast<uintptr_t
>(&Node));
186 Expected<std::optional<ObjectHandle>> loadIfExists(ObjectRef
Ref)
override {
187 return getObjectHandle(asInMemoryObject(
Ref));
190 InMemoryIndexValueT &indexHash(ArrayRef<uint8_t> Hash) {
191 return *Index.insertLazy(
192 Hash, [](
auto ValueConstructor) { ValueConstructor.emplace(
nullptr); });
197 const InMemoryObject *getInMemoryObject(CASID
ID)
const {
198 assert(
ID.getContext().getHashSchemaIdentifier() ==
200 "Expected ID from same hash schema");
201 if (InMemoryIndexT::const_pointer
P = Index.find(
ID.getHash()))
206 const InMemoryObject &getInMemoryObject(ObjectHandle OH)
const {
207 return *
reinterpret_cast<const InMemoryObject *
>(
211 const InMemoryObject &asInMemoryObject(ReferenceBase
Ref)
const {
212 uintptr_t
P =
Ref.getInternalRef(*
this);
213 return *
reinterpret_cast<const InMemoryObject *
>(
P);
215 ObjectRef toReference(
const InMemoryObject &O)
const {
216 return makeObjectRef(
reinterpret_cast<uintptr_t
>(&O));
219 CASID getID(ObjectRef
Ref)
const final {
return getIDImpl(
Ref); }
220 CASID getIDImpl(ReferenceBase
Ref)
const {
221 return getID(asInMemoryObject(
Ref));
224 std::optional<ObjectRef> getReference(
const CASID &
ID)
const final {
225 if (
const InMemoryObject *Object = getInMemoryObject(
ID))
226 return toReference(*Object);
230 Expected<bool> isMaterialized(ObjectRef
Ref)
const final {
return true; }
232 ArrayRef<char> getDataConst(ObjectHandle Node)
const final {
236 InMemoryCAS() =
default;
239 size_t getNumRefs(ObjectHandle Node)
const final {
240 return getInMemoryObject(Node).getRefs().size();
242 ObjectRef readRef(ObjectHandle Node,
size_t I)
const final {
243 return toReference(*getInMemoryObject(Node).getRefs()[
I]);
245 Error forEachRef(ObjectHandle Node,
246 function_ref<
Error(ObjectRef)> Callback)
const final;
253 InMemoryIndexT Index;
255 ThreadSafeAllocator<BumpPtrAllocator> Objects;
256 ThreadSafeAllocator<SpecificBumpPtrAllocator<sys::fs::mapped_file_region>>
264 return Derived->getDataImpl();
270 return Derived->getRefsImpl();
275InMemoryCAS::storeFromNullTerminatedRegion(ArrayRef<uint8_t> ComputedHash,
276 sys::fs::mapped_file_region Map) {
279 auto &
I = indexHash(ComputedHash);
283 return Objects.Allocate(
Size,
alignof(InMemoryObject));
285 auto Generator = [&]() ->
const InMemoryObject * {
288 const InMemoryObject &
Node =
293 if (RefNode->getData().data() ==
Map.data())
294 new (MemoryMaps.Allocate(1)) sys::fs::mapped_file_region(std::move(Map));
296 return toReference(Node);
299Expected<ObjectRef> InMemoryCAS::storeImpl(ArrayRef<uint8_t> ComputedHash,
301 ArrayRef<char>
Data) {
303 auto &
I = indexHash(ComputedHash);
307 for (ObjectRef
Ref : Refs)
310 return Objects.Allocate(
Size,
alignof(InMemoryObject));
312 auto Generator = [&]() ->
const InMemoryObject * {
313 return &InMemoryInlineObject::create(
Allocator,
I, InternalRefs,
Data);
318Error InMemoryCAS::forEachRef(ObjectHandle Handle,
319 function_ref<
Error(ObjectRef)> Callback)
const {
320 auto &
Node = getInMemoryObject(Handle);
321 for (
const InMemoryObject *
Ref :
Node.getRefs())
328 return std::make_unique<InMemoryCAS>();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the BumpPtrAllocator interface.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the PointerIntPair class.
This header defines support for implementing classes that have some trailing object (or arrays of obj...
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
static ErrorSuccess success()
Create a success value.
void push_back(const T &Elt)
Lock-free thread-safe hash-mapped trie.
See the file comment for details on the usage of the TrailingObjects type.
static CASID create(const CASContext *Context, StringRef Hash)
Create CASID from CASContext and raw hash bytes.
uint64_t getInternalRef(const ObjectStore &ExpectedCAS) const
Get an internal reference.
Common base class for builtin CAS implementations using the same CASContext.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
decltype(HasherT::hash(std::declval< ArrayRef< uint8_t > & >())) HashType
std::unique_ptr< ObjectStore > createInMemoryCAS()
llvm::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
NodeAddr< NodeBase * > Node
Context & getContext() const
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
@ Ref
The access may reference the value stored in memory.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
StringRef toStringRef(bool B)
Construct a string ref from a boolean.
bool isAddrAligned(Align Lhs, const void *Addr)
Checks that Addr is a multiple of the alignment.