Move allocator into TypeManager

Currently the TypeManger is a UniqueAllocator. This works as long as the
TypeManager only manages one specific thing. In order to support
ArrayCount, which is type related, but not a type, the TypeManager will
need to be able to store two types of things.

This CL changes the TypeManager to contain a UniqueAllocator and proxies
the needed Get, Find and iteration methods to that allocator. This will
allow another allocator to be added for ArrayCount later.

Bug: tint:1718
Change-Id: I0f952eb5c3ef90a7c85dead14d11b657dceba951
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/112640
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
dan sinclair 2022-12-01 21:42:47 +00:00 committed by Dawn LUCI CQ
parent 2939c4531e
commit 847cfa07c5
2 changed files with 58 additions and 18 deletions

View File

@ -25,10 +25,10 @@
namespace tint::sem {
/// The type manager holds all the pointers to the known types.
class TypeManager final : public utils::UniqueAllocator<Type> {
class TypeManager final {
public:
/// Iterator is the type returned by begin() and end()
using Iterator = utils::BlockAllocator<Type>::ConstIterator;
using TypeIterator = utils::BlockAllocator<Type>::ConstIterator;
/// Constructor
TypeManager();
@ -55,30 +55,38 @@ class TypeManager final : public utils::UniqueAllocator<Type> {
/// @return the Manager that wraps `inner`
static TypeManager Wrap(const TypeManager& inner) {
TypeManager out;
out.items = inner.items;
out.types_.Wrap(inner.types_);
return out;
}
/// @param args the arguments used to create the temporary type used for the search.
/// @return a pointer to an instance of `T` with the provided arguments, or nullptr if the type
/// @param args the arguments used to construct the object.
/// @return a pointer to an instance of `T` with the provided arguments.
/// If an existing instance of `T` has been constructed, then the same
/// pointer is returned.
template <typename TYPE,
typename _ = std::enable_if<traits::IsTypeOrDerived<TYPE, sem::Type>>,
typename... ARGS>
TYPE* Get(ARGS&&... args) {
return types_.Get<TYPE>(std::forward<ARGS>(args)...);
}
/// @param args the arguments used to create the temporary used for the search.
/// @return a pointer to an instance of `T` with the provided arguments, or nullptr if the item
/// was not found.
template <typename TYPE, typename... ARGS>
template <typename TYPE,
typename _ = std::enable_if<traits::IsTypeOrDerived<TYPE, sem::Type>>,
typename... ARGS>
TYPE* Find(ARGS&&... args) const {
// Create a temporary T instance on the stack so that we can hash it, and
// use it for equality lookup for the std::unordered_set.
TYPE key{args...};
auto hash = Hasher{}(key);
auto it = items.find(Entry{hash, &key});
if (it != items.end()) {
return static_cast<TYPE*>(it->ptr);
}
return nullptr;
return types_.Find<TYPE>(std::forward<ARGS>(args)...);
}
/// @returns an iterator to the beginning of the types
Iterator begin() const { return allocator.Objects().begin(); }
TypeIterator begin() const { return types_.begin(); }
/// @returns an iterator to the end of the types
Iterator end() const { return allocator.Objects().end(); }
TypeIterator end() const { return types_.end(); }
private:
utils::UniqueAllocator<Type> types_;
};
} // namespace tint::sem

View File

@ -28,6 +28,9 @@ namespace tint::utils {
template <typename T, typename HASH = std::hash<T>, typename EQUAL = std::equal_to<T>>
class UniqueAllocator {
public:
/// Iterator is the type returned by begin() and end()
using Iterator = typename BlockAllocator<T>::ConstIterator;
/// @param args the arguments used to construct the object.
/// @return a pointer to an instance of `T` with the provided arguments.
/// If an existing instance of `T` has been constructed, then the same
@ -49,7 +52,36 @@ class UniqueAllocator {
return ptr;
}
protected:
/// @param args the arguments used to create the temporary used for the search.
/// @return a pointer to an instance of `T` with the provided arguments, or nullptr if the item
/// was not found.
template <typename TYPE = T, typename... ARGS>
TYPE* Find(ARGS&&... args) const {
// Create a temporary T instance on the stack so that we can hash it, and
// use it for equality lookup for the std::unordered_set.
TYPE key{args...};
auto hash = Hasher{}(key);
auto it = items.find(Entry{hash, &key});
if (it != items.end()) {
return static_cast<TYPE*>(it->ptr);
}
return nullptr;
}
/// Wrap sets this allocator to the objects created with the content of `inner`.
/// The allocator after Wrap is intended to temporarily extend the objects
/// of an existing immutable UniqueAllocator.
/// As the copied objects are owned by `inner`, `inner` must not be destructed
/// or assigned while using this allocator.
/// @param o the immutable UniqueAlllocator to extend
void Wrap(const UniqueAllocator<T, HASH, EQUAL>& o) { items = o.items; }
/// @returns an iterator to the beginning of the types
Iterator begin() const { return allocator.Objects().begin(); }
/// @returns an iterator to the end of the types
Iterator end() const { return allocator.Objects().end(); }
private:
/// The hash function
using Hasher = HASH;
/// The equality function