Skip to content

Typeref uniquing #2313

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 26, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
201 changes: 197 additions & 4 deletions include/swift/Reflection/TypeRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,84 @@ enum class TypeRefKind {
#undef TYPEREF
};

/// An identifier containing the unique bit pattern made up of all of the
/// instance data needed to uniquely identify a TypeRef.
///
/// This allows for uniquing (via Equal) and for keying into a dictionary for
/// caching.
///
/// TypeRefs should be comparable by pointers, so if the TypeRefBuilder
/// gets a request to build a TypeRef with the same constructor arguments,
/// it should return the one already created with those arguments, not a fresh
/// copy. This allows for fast identity comparisons and substitutions, for
/// example. We use a similar strategy for Types in the full AST.
class TypeRefID {

std::vector<uint32_t> Bits;

public:
TypeRefID() = default;

template <typename T>
void addPointer(const T *Pointer) {
auto Raw = reinterpret_cast<uint32_t *>(&Pointer);
Bits.push_back(Raw[0]);
if (sizeof(const T *) > 4) {
Bits.push_back(Raw[1]);
}
}

void addInteger(uint32_t Integer) {
Bits.push_back(Integer);
}

void addInteger(uint64_t Integer) {
Bits.push_back((uint32_t)Integer);
Bits.push_back(Integer >> 32);
}

void addString(const std::string &String) {
if (String.empty()) {
Bits.push_back(0);
} else {
size_t i = 0;
size_t chunks = String.size() / 4;
for (size_t chunk = 0; chunk < chunks; ++chunk, i+=4) {
uint32_t entry = ((uint32_t) String[i]) +
(((uint32_t) String[i+1]) << 8) +
(((uint32_t) String[i+2]) << 16) +
(((uint32_t) String[i+3]) << 24);
Bits.push_back(entry);
}
for(; i < String.size(); ++i) {
Bits.push_back(String[i]);
}
}
}

struct Hash {
std::size_t operator()(TypeRefID const &ID) const {
size_t Hash = 0;
std::hash<uint32_t> h;
for (auto x : ID.Bits) {
Hash ^= h(x) + 0x9e3779b9 + (Hash << 6) + (Hash >> 2);
}
return Hash;
}
};

struct Equal {
bool operator()(const TypeRefID &lhs, const TypeRefID &rhs) const {
return lhs.Bits == rhs.Bits;
}
};


bool operator==(const TypeRefID &Other) {
return Bits == Other.Bits;
}
};

class TypeRef;
class TypeRefBuilder;
using DepthAndIndex = std::pair<unsigned, unsigned>;
Expand Down Expand Up @@ -80,6 +158,12 @@ class BuiltinTypeRef final : public TypeRef {
return MangledName;
}

static TypeRefID Profile(const std::string &MangledName) {
TypeRefID ID;
ID.addString(MangledName);
return ID;
}

static bool classof(const TypeRef *TR) {
return TR->getKind() == TypeRefKind::Builtin;
}
Expand Down Expand Up @@ -107,6 +191,14 @@ class NominalTypeTrait {
}

unsigned getDepth() const;

static TypeRefID Profile(const std::string &MangledName,
const TypeRef *Parent) {
TypeRefID ID;
ID.addString(MangledName);
ID.addPointer(Parent);
return ID;
}
};

class NominalTypeRef final : public TypeRef, public NominalTypeTrait {
Expand All @@ -122,6 +214,8 @@ class NominalTypeRef final : public TypeRef, public NominalTypeTrait {
return A.template makeTypeRef<NominalTypeRef>(MangledName, Parent);
}

using NominalTypeTrait::Profile;

static bool classof(const TypeRef *TR) {
return TR->getKind() == TypeRefKind::Nominal;
}
Expand Down Expand Up @@ -152,6 +246,17 @@ class BoundGenericTypeRef final : public TypeRef, public NominalTypeTrait {
return GenericParams;
}

static TypeRefID Profile(const std::string &MangledName,
const std::vector<const TypeRef *> &GenericParams,
const TypeRef *Parent) {
TypeRefID ID;
ID.addString(MangledName);
for (auto Param : GenericParams)
ID.addPointer(Param);
ID.addPointer(Parent);
return ID;
}

static bool classof(const TypeRef *TR) {
return TR->getKind() == TypeRefKind::BoundGeneric;
}
Expand Down Expand Up @@ -180,6 +285,16 @@ class TupleTypeRef final : public TypeRef {
return Variadic;
}

static TypeRefID Profile(const std::vector<const TypeRef *> &Elements,
bool Variadic) {
TypeRefID ID;
for (auto Element : Elements)
ID.addPointer(Element);

ID.addInteger(static_cast<uint32_t>(Variadic));
return ID;
}

static bool classof(const TypeRef *TR) {
return TR->getKind() == TypeRefKind::Tuple;
}
Expand Down Expand Up @@ -216,6 +331,18 @@ class FunctionTypeRef final : public TypeRef {
return Flags;
}

static TypeRefID Profile(const std::vector<const TypeRef *> &Arguments,
const TypeRef *Result,
FunctionTypeFlags Flags) {
TypeRefID ID;
for (auto Argument : Arguments) {
ID.addPointer(Argument);
}
ID.addPointer(Result);
ID.addInteger(static_cast<uint64_t>(Flags.getIntValue()));
return ID;
}

static bool classof(const TypeRef *TR) {
return TR->getKind() == TypeRefKind::Function;
}
Expand All @@ -238,6 +365,12 @@ class ProtocolTypeRef final : public TypeRef {
return MangledName;
}

static TypeRefID Profile(const std::string &MangledName) {
TypeRefID ID;
ID.addString(MangledName);
return ID;
}

static bool classof(const TypeRef *TR) {
return TR->getKind() == TypeRefKind::Protocol;
}
Expand Down Expand Up @@ -267,6 +400,14 @@ class ProtocolCompositionTypeRef final : public TypeRef {
return Protocols;
}

static TypeRefID Profile(const std::vector<const TypeRef *> &Protocols) {
TypeRefID ID;
for (auto Protocol : Protocols) {
ID.addPointer(Protocol);
}
return ID;
}

static bool classof(const TypeRef *TR) {
return TR->getKind() == TypeRefKind::ProtocolComposition;
}
Expand Down Expand Up @@ -296,6 +437,12 @@ class MetatypeTypeRef final : public TypeRef {
return InstanceType;
}

static TypeRefID Profile(const TypeRef *InstanceType) {
TypeRefID ID;
ID.addPointer(InstanceType);
return ID;
}

static bool classof(const TypeRef *TR) {
return TR->getKind() == TypeRefKind::Metatype;
}
Expand All @@ -318,6 +465,12 @@ class ExistentialMetatypeTypeRef final : public TypeRef {
return InstanceType;
}

static TypeRefID Profile(const TypeRef *InstanceType) {
TypeRefID ID;
ID.addPointer(InstanceType);
return ID;
}

static bool classof(const TypeRef *TR) {
return TR->getKind() == TypeRefKind::ExistentialMetatype;
}
Expand Down Expand Up @@ -345,6 +498,13 @@ class GenericTypeParameterTypeRef final : public TypeRef {
return Index;
}

static TypeRefID Profile(uint32_t Depth, uint32_t Index) {
TypeRefID ID;
ID.addInteger(Depth);
ID.addInteger(Index);
return ID;
}

static bool classof(const TypeRef *TR) {
return TR->getKind() == TypeRefKind::GenericTypeParameter;
}
Expand Down Expand Up @@ -381,21 +541,26 @@ class DependentMemberTypeRef final : public TypeRef {
return cast<ProtocolTypeRef>(Protocol);
}

static TypeRefID Profile(const std::string &Member, const TypeRef *Base,
const TypeRef *Protocol) {
TypeRefID ID;
ID.addString(Member);
ID.addPointer(Base);
ID.addPointer(Protocol);
return ID;
}

static bool classof(const TypeRef *TR) {
return TR->getKind() == TypeRefKind::DependentMember;
}
};

class ForeignClassTypeRef final : public TypeRef {
std::string Name;
static const ForeignClassTypeRef *UnnamedSingleton;
public:
ForeignClassTypeRef(const std::string &Name)
: TypeRef(TypeRefKind::ForeignClass), Name(Name) {}

static const ForeignClassTypeRef *getUnnamed();


template <typename Allocator>
static ForeignClassTypeRef *create(Allocator &A,
const std::string &Name) {
Expand All @@ -406,6 +571,12 @@ class ForeignClassTypeRef final : public TypeRef {
return Name;
}

static TypeRefID Profile(const std::string &Name) {
TypeRefID ID;
ID.addString(Name);
return ID;
}

static bool classof(const TypeRef *TR) {
return TR->getKind() == TypeRefKind::ForeignClass;
}
Expand All @@ -429,6 +600,12 @@ class ObjCClassTypeRef final : public TypeRef {
return Name;
}

static TypeRefID Profile(const std::string &Name) {
TypeRefID ID;
ID.addString(Name);
return ID;
}

static bool classof(const TypeRef *TR) {
return TR->getKind() == TypeRefKind::ObjCClass;
}
Expand All @@ -441,6 +618,10 @@ class OpaqueTypeRef final : public TypeRef {

static const OpaqueTypeRef *get();

static TypeRefID Profile() {
return TypeRefID();
}

static bool classof(const TypeRef *TR) {
return TR->getKind() == TypeRefKind::Opaque;
}
Expand All @@ -457,6 +638,12 @@ class ReferenceStorageTypeRef : public TypeRef {
const TypeRef *getType() const {
return Type;
}

static TypeRefID Profile(const TypeRef *Type) {
TypeRefID ID;
ID.addPointer(Type);
return ID;
}
};

class UnownedStorageTypeRef final : public ReferenceStorageTypeRef {
Expand All @@ -470,6 +657,8 @@ class UnownedStorageTypeRef final : public ReferenceStorageTypeRef {
return A.template makeTypeRef<UnownedStorageTypeRef>(Type);
}

using ReferenceStorageTypeRef::Profile;

static bool classof(const TypeRef *TR) {
return TR->getKind() == TypeRefKind::UnownedStorage;
}
Expand All @@ -486,6 +675,8 @@ class WeakStorageTypeRef final : public ReferenceStorageTypeRef {
return A.template makeTypeRef<WeakStorageTypeRef>(Type);
}

using ReferenceStorageTypeRef::Profile;

static bool classof(const TypeRef *TR) {
return TR->getKind() == TypeRefKind::WeakStorage;
}
Expand All @@ -502,6 +693,8 @@ class UnmanagedStorageTypeRef final : public ReferenceStorageTypeRef {
return A.template makeTypeRef<UnmanagedStorageTypeRef>(Type);
}

using ReferenceStorageTypeRef::Profile;

static bool classof(const TypeRef *TR) {
return TR->getKind() == TypeRefKind::UnmanagedStorage;
}
Expand Down
Loading