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;
62 InMemoryObject(Kind K,
const InMemoryIndexValueT &
I) : IndexAndKind(&
I,
K) {}
68 PointerIntPair<const InMemoryIndexValueT *, NumKindBits, Kind> IndexAndKind;
69 static_assert((1U << NumKindBits) <=
alignof(InMemoryIndexValueT),
70 "Kind will clobber pointer");
71 static_assert(((int)Kind::Max >> NumKindBits) == 0,
"Kind will be truncated");
74 ArrayRef<char> getData()
const;
79class InMemoryRefObject final :
public InMemoryObject {
81 static constexpr Kind KindValue = Kind::RefNode;
82 static bool classof(
const InMemoryObject *O) {
83 return O->getKind() == KindValue;
88 ArrayRef<char> getDataImpl()
const {
return Data; }
89 ArrayRef<char> getData()
const {
return Data; }
91 static InMemoryRefObject &create(function_ref<
void *(
size_t Size)> Allocate,
92 const InMemoryIndexValueT &
I,
94 ArrayRef<char> Data) {
95 void *Mem = Allocate(
sizeof(InMemoryRefObject));
96 return *
new (Mem) InMemoryRefObject(
I, Refs, Data);
100 InMemoryRefObject(
const InMemoryIndexValueT &
I,
102 : InMemoryObject(KindValue,
I), Refs(Refs), Data(Data) {
105 assert(*Data.end() == 0 &&
"Expected null-termination");
112class InMemoryInlineObject final
113 :
public InMemoryObject,
117 static constexpr Kind KindValue = Kind::InlineNode;
118 static bool classof(
const InMemoryObject *O) {
119 return O->getKind() == KindValue;
124 return ArrayRef(getTrailingObjects<const InMemoryObject *>(), NumRefs);
127 ArrayRef<char> getData()
const {
return getDataImpl(); }
128 ArrayRef<char> getDataImpl()
const {
129 return ArrayRef(getTrailingObjects<char>(), DataSize);
132 static InMemoryInlineObject &
133 create(function_ref<
void *(
size_t Size)> Allocate,
135 ArrayRef<char>
Data) {
136 void *Mem = Allocate(
sizeof(InMemoryInlineObject) +
137 sizeof(uintptr_t) * Refs.
size() +
Data.size() + 1);
138 return *
new (Mem) InMemoryInlineObject(
I, Refs,
Data);
141 size_t numTrailingObjects(OverloadToken<const InMemoryObject *>)
const {
146 InMemoryInlineObject(
const InMemoryIndexValueT &
I,
149 : InMemoryObject(KindValue,
I), NumRefs(Refs.
size()),
151 auto *BeginRefs =
reinterpret_cast<const InMemoryObject **
>(
this + 1);
153 auto *BeginData =
reinterpret_cast<char *
>(BeginRefs + NumRefs);
155 BeginData[
Data.size()] = 0;
164 Expected<ObjectRef> storeImpl(ArrayRef<uint8_t> ComputedHash,
166 ArrayRef<char>
Data)
final;
169 storeFromNullTerminatedRegion(ArrayRef<uint8_t> ComputedHash,
170 sys::fs::mapped_file_region Map)
override;
172 CASID getID(
const InMemoryIndexValueT &
I)
const {
176 CASID getID(
const InMemoryObject &O)
const {
return getID(
O.getIndex()); }
178 ObjectHandle getObjectHandle(
const InMemoryObject &Node)
const {
179 assert(!(
reinterpret_cast<uintptr_t
>(&Node) & 0x1ULL));
180 return makeObjectHandle(
reinterpret_cast<uintptr_t
>(&Node));
183 Expected<std::optional<ObjectHandle>> loadIfExists(ObjectRef
Ref)
override {
184 return getObjectHandle(asInMemoryObject(
Ref));
187 InMemoryIndexValueT &indexHash(ArrayRef<uint8_t> Hash) {
188 return *Index.insertLazy(
189 Hash, [](
auto ValueConstructor) { ValueConstructor.emplace(
nullptr); });
194 const InMemoryObject *getInMemoryObject(CASID
ID)
const {
195 assert(
ID.getContext().getHashSchemaIdentifier() ==
197 "Expected ID from same hash schema");
198 if (InMemoryIndexT::const_pointer
P = Index.find(
ID.getHash()))
203 const InMemoryObject &getInMemoryObject(ObjectHandle OH)
const {
204 return *
reinterpret_cast<const InMemoryObject *
>(
208 const InMemoryObject &asInMemoryObject(ReferenceBase
Ref)
const {
209 uintptr_t
P =
Ref.getInternalRef(*
this);
210 return *
reinterpret_cast<const InMemoryObject *
>(
P);
212 ObjectRef toReference(
const InMemoryObject &O)
const {
213 return makeObjectRef(
reinterpret_cast<uintptr_t
>(&O));
216 CASID getID(ObjectRef
Ref)
const final {
return getIDImpl(
Ref); }
217 CASID getIDImpl(ReferenceBase
Ref)
const {
218 return getID(asInMemoryObject(
Ref));
221 std::optional<ObjectRef> getReference(
const CASID &
ID)
const final {
222 if (
const InMemoryObject *Object = getInMemoryObject(
ID))
223 return toReference(*Object);
227 Expected<bool> isMaterialized(ObjectRef
Ref)
const final {
return true; }
229 ArrayRef<char> getDataConst(ObjectHandle Node)
const final {
233 InMemoryCAS() =
default;
236 size_t getNumRefs(ObjectHandle Node)
const final {
237 return getInMemoryObject(Node).getRefs().size();
239 ObjectRef readRef(ObjectHandle Node,
size_t I)
const final {
240 return toReference(*getInMemoryObject(Node).getRefs()[
I]);
242 Error forEachRef(ObjectHandle Node,
243 function_ref<
Error(ObjectRef)> Callback)
const final;
250 InMemoryIndexT Index;
252 ThreadSafeAllocator<BumpPtrAllocator> Objects;
253 ThreadSafeAllocator<SpecificBumpPtrAllocator<sys::fs::mapped_file_region>>
261 return Derived->getDataImpl();
267 return Derived->getRefsImpl();
272InMemoryCAS::storeFromNullTerminatedRegion(ArrayRef<uint8_t> ComputedHash,
273 sys::fs::mapped_file_region Map) {
276 auto &
I = indexHash(ComputedHash);
280 return Objects.Allocate(
Size,
alignof(InMemoryObject));
282 auto Generator = [&]() ->
const InMemoryObject * {
285 const InMemoryObject &
Node =
290 if (RefNode->getData().data() ==
Map.data())
291 new (MemoryMaps.Allocate(1)) sys::fs::mapped_file_region(std::move(Map));
293 return toReference(Node);
296Expected<ObjectRef> InMemoryCAS::storeImpl(ArrayRef<uint8_t> ComputedHash,
298 ArrayRef<char>
Data) {
300 auto &
I = indexHash(ComputedHash);
304 for (ObjectRef
Ref : Refs)
307 return Objects.Allocate(
Size,
alignof(InMemoryObject));
309 auto Generator = [&]() ->
const InMemoryObject * {
310 return &InMemoryInlineObject::create(
Allocator,
I, InternalRefs,
Data);
315Error InMemoryCAS::forEachRef(ObjectHandle Handle,
316 function_ref<
Error(ObjectRef)> Callback)
const {
317 auto &
Node = getInMemoryObject(Handle);
318 for (
const InMemoryObject *
Ref :
Node.getRefs())
319 if (
Error E = Callback(toReference(*
Ref)))
325 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()
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.