mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Introduce a special memory arena in ASTContext for the type checker.
This introduces the notion of arenas into ASTContext, with two arenas currently defined: one for 'permanent' storage, and another for the current constraint checker. The latter is used when allocating any types that involve type variables, which are only used temporarily during type checking anyway. This gives us a 1% speedup on swift.swift (because we're hitting smaller hash tables when doing lookups) and < 1% memory reduction (since that's not the main source of memory usage). It's more important architecturally, so our memory usage doesn't grow with the number of type-checks performed. Note also that this arena scheme could be generalized, which we may very well want to do in the future. For example, we could easily have an arena for temporary nodes introduced by parsing (e.g., UnresolvedDeclRefExpr) or by name binding (OverloadedDeclRefExpr), and clear that arena when we successfully move onto the next phase. Or, in a REPL/debugger context, have a 'temporary' arena for statements/expressions that can be removed. Swift SVN r3175
This commit is contained in:
@@ -28,10 +28,12 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
class BumpPtrAllocator;
|
||||||
class SourceMgr;
|
class SourceMgr;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace swift {
|
namespace swift {
|
||||||
|
class ASTContext;
|
||||||
class BoundGenericType;
|
class BoundGenericType;
|
||||||
class SourceLoc;
|
class SourceLoc;
|
||||||
class Type;
|
class Type;
|
||||||
@@ -71,7 +73,53 @@ public:
|
|||||||
/// the requirements of those protocols.
|
/// the requirements of those protocols.
|
||||||
llvm::DenseMap<ProtocolDecl *, ProtocolConformance *> InheritedMapping;
|
llvm::DenseMap<ProtocolDecl *, ProtocolConformance *> InheritedMapping;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief The arena in which a particular ASTContext allocation will go.
|
||||||
|
enum class AllocationArena {
|
||||||
|
/// \brief The permanent arena, which is tied to the lifetime of
|
||||||
|
/// the ASTContext.
|
||||||
|
///
|
||||||
|
/// All global declarations and types need to be allocated into this arena.
|
||||||
|
/// At present, everything that is not a type involving a type variable is
|
||||||
|
/// allocated in this arena.
|
||||||
|
Permanent,
|
||||||
|
/// \brief The constraint solver's temporary arena, which is tied to the
|
||||||
|
/// lifetime of a particular instance of the constraint solver.
|
||||||
|
///
|
||||||
|
/// Any type involving a type variable is allocated in this arena.
|
||||||
|
ConstraintSolver
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief Introduces a new constraint checker arena, whose lifetime is
|
||||||
|
/// tied to the lifetime of this RAII object.
|
||||||
|
class ConstraintCheckerArenaRAII {
|
||||||
|
ASTContext &Self;
|
||||||
|
void *Data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// \brief Introduces a new constraint checker arena, supplanting any
|
||||||
|
/// existing constraint checker arena.
|
||||||
|
///
|
||||||
|
/// \param self The ASTContext into which this constraint checker arena
|
||||||
|
/// will be installed.
|
||||||
|
///
|
||||||
|
/// \param allocator The allocator used for allocating any data that
|
||||||
|
/// goes into the constraint checker arena.
|
||||||
|
ConstraintCheckerArenaRAII(ASTContext &self,
|
||||||
|
llvm::BumpPtrAllocator &allocator);
|
||||||
|
|
||||||
|
ConstraintCheckerArenaRAII(const ConstraintCheckerArenaRAII &) = delete;
|
||||||
|
ConstraintCheckerArenaRAII(ConstraintCheckerArenaRAII &&) = delete;
|
||||||
|
|
||||||
|
ConstraintCheckerArenaRAII &
|
||||||
|
operator=(const ConstraintCheckerArenaRAII &) = delete;
|
||||||
|
|
||||||
|
ConstraintCheckerArenaRAII &
|
||||||
|
operator=(ConstraintCheckerArenaRAII &&) = delete;
|
||||||
|
|
||||||
|
~ConstraintCheckerArenaRAII();
|
||||||
|
};
|
||||||
|
|
||||||
/// ASTContext - This object creates and owns the AST objects.
|
/// ASTContext - This object creates and owns the AST objects.
|
||||||
class ASTContext {
|
class ASTContext {
|
||||||
ASTContext(const ASTContext&) = delete;
|
ASTContext(const ASTContext&) = delete;
|
||||||
@@ -81,6 +129,8 @@ public:
|
|||||||
// Members that should only be used by ASTContext.cpp.
|
// Members that should only be used by ASTContext.cpp.
|
||||||
struct Implementation;
|
struct Implementation;
|
||||||
Implementation &Impl;
|
Implementation &Impl;
|
||||||
|
|
||||||
|
friend class ConstraintCheckerArenaRAII;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ASTContext(LangOptions &langOpts, llvm::SourceMgr &SourceMgr,
|
ASTContext(LangOptions &langOpts, llvm::SourceMgr &SourceMgr,
|
||||||
@@ -113,47 +163,63 @@ public:
|
|||||||
/// ConformsTo - Caches the results of checking whether a given (canonical)
|
/// ConformsTo - Caches the results of checking whether a given (canonical)
|
||||||
/// type conforms to a given protocol.
|
/// type conforms to a given protocol.
|
||||||
ConformsToMap ConformsTo;
|
ConformsToMap ConformsTo;
|
||||||
|
|
||||||
|
/// \brief Retrieve the allocator for the given arena.
|
||||||
|
llvm::BumpPtrAllocator &
|
||||||
|
getAllocator(AllocationArena arena = AllocationArena::Permanent) const;
|
||||||
|
|
||||||
/// Allocate - Allocate memory from the ASTContext bump pointer.
|
/// Allocate - Allocate memory from the ASTContext bump pointer.
|
||||||
void *Allocate(unsigned long Bytes, unsigned Alignment);
|
void *Allocate(unsigned long bytes, unsigned alignment,
|
||||||
|
AllocationArena arena = AllocationArena::Permanent) {
|
||||||
|
return getAllocator(arena).Allocate(bytes, alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T *Allocate(unsigned NElts) {
|
T *Allocate(unsigned numElts,
|
||||||
T *Res = (T*)Allocate(sizeof(T)*NElts, __alignof__(T));
|
AllocationArena arena = AllocationArena::Permanent) {
|
||||||
for (unsigned i = 0; i != NElts; ++i)
|
T *res = (T*)Allocate(sizeof(T)*numElts, __alignof__(T), arena);
|
||||||
new (Res+i) T();
|
for (unsigned i = 0; i != numElts; ++i)
|
||||||
return Res;
|
new (res+i) T();
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename It>
|
template <typename T, typename It>
|
||||||
T *AllocateCopy(It Start, It End) {
|
T *AllocateCopy(It start, It end,
|
||||||
T *Res = (T*)Allocate(sizeof(T)*(End-Start), __alignof__(T));
|
AllocationArena arena = AllocationArena::Permanent) {
|
||||||
for (unsigned i = 0; Start != End; ++Start, ++i)
|
T *res = (T*)Allocate(sizeof(T)*(end-start), __alignof__(T), arena);
|
||||||
new (Res+i) T(*Start);
|
for (unsigned i = 0; start != end; ++start, ++i)
|
||||||
return Res;
|
new (res+i) T(*start);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ArrayRef<T> AllocateCopy(ArrayRef<T> Arr) {
|
ArrayRef<T> AllocateCopy(ArrayRef<T> array,
|
||||||
return ArrayRef<T>(AllocateCopy<T>(Arr.begin(), Arr.end()),
|
AllocationArena arena = AllocationArena::Permanent) {
|
||||||
Arr.size());
|
return ArrayRef<T>(AllocateCopy<T>(array.begin(), array.end(), arena),
|
||||||
|
array.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
MutableArrayRef<T> AllocateCopy(MutableArrayRef<T> Arr) {
|
MutableArrayRef<T>
|
||||||
return MutableArrayRef<T>(AllocateCopy<T>(Arr.begin(), Arr.end()),
|
AllocateCopy(MutableArrayRef<T> array,
|
||||||
Arr.size());
|
AllocationArena arena = AllocationArena::Permanent) {
|
||||||
|
return MutableArrayRef<T>(AllocateCopy<T>(array.begin(), array.end(),arena),
|
||||||
|
array.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ArrayRef<T> AllocateCopy(const SmallVectorImpl<T> &Vec) {
|
ArrayRef<T> AllocateCopy(const SmallVectorImpl<T> &vec,
|
||||||
return AllocateCopy(ArrayRef<T>(Vec));
|
AllocationArena arena = AllocationArena::Permanent) {
|
||||||
|
return AllocateCopy(ArrayRef<T>(vec), arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
MutableArrayRef<T> AllocateCopy(SmallVectorImpl<T> &Vec) {
|
MutableArrayRef<T>
|
||||||
return AllocateCopy(MutableArrayRef<T>(Vec));
|
AllocateCopy(SmallVectorImpl<T> &vec,
|
||||||
|
AllocationArena arena = AllocationArena::Permanent) {
|
||||||
|
return AllocateCopy(MutableArrayRef<T>(vec), arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ namespace llvm {
|
|||||||
struct fltSemantics;
|
struct fltSemantics;
|
||||||
}
|
}
|
||||||
namespace swift {
|
namespace swift {
|
||||||
|
enum class AllocationArena;
|
||||||
class ArchetypeType;
|
class ArchetypeType;
|
||||||
class ASTContext;
|
class ASTContext;
|
||||||
class ClassDecl;
|
class ClassDecl;
|
||||||
@@ -249,8 +250,8 @@ private:
|
|||||||
public:
|
public:
|
||||||
// Only allow allocation of Types using the allocator in ASTContext
|
// Only allow allocation of Types using the allocator in ASTContext
|
||||||
// or by doing a placement new.
|
// or by doing a placement new.
|
||||||
void *operator new(size_t Bytes, ASTContext &C,
|
void *operator new(size_t bytes, ASTContext &ctx, AllocationArena arena,
|
||||||
unsigned Alignment = 8);
|
unsigned alignment = 8);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// ErrorType - This represents a type that was erroneously constructed. This
|
/// ErrorType - This represents a type that was erroneously constructed. This
|
||||||
@@ -715,10 +716,12 @@ public:
|
|||||||
void print(raw_ostream &O) const;
|
void print(raw_ostream &O) const;
|
||||||
|
|
||||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||||
Profile(ID, TheDecl, Parent, GenericArgs);
|
bool hasTypeVariable = false;
|
||||||
|
Profile(ID, TheDecl, Parent, GenericArgs, hasTypeVariable);
|
||||||
}
|
}
|
||||||
static void Profile(llvm::FoldingSetNodeID &ID, NominalTypeDecl *TheDecl,
|
static void Profile(llvm::FoldingSetNodeID &ID, NominalTypeDecl *TheDecl,
|
||||||
Type Parent, ArrayRef<Type> GenericArgs);
|
Type Parent, ArrayRef<Type> GenericArgs,
|
||||||
|
bool &hasTypeVariable);
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
// Implement isa/cast/dyncast/etc.
|
||||||
static bool classof(const TypeBase *T) {
|
static bool classof(const TypeBase *T) {
|
||||||
|
|||||||
@@ -22,6 +22,8 @@
|
|||||||
#include "llvm/Support/SourceMgr.h"
|
#include "llvm/Support/SourceMgr.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/StringMap.h"
|
#include "llvm/ADT/StringMap.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
using namespace swift;
|
using namespace swift;
|
||||||
|
|
||||||
struct ASTContext::Implementation {
|
struct ASTContext::Implementation {
|
||||||
@@ -30,34 +32,85 @@ struct ASTContext::Implementation {
|
|||||||
|
|
||||||
llvm::BumpPtrAllocator Allocator; // used in later initializations
|
llvm::BumpPtrAllocator Allocator; // used in later initializations
|
||||||
llvm::StringMap<char, llvm::BumpPtrAllocator&> IdentifierTable;
|
llvm::StringMap<char, llvm::BumpPtrAllocator&> IdentifierTable;
|
||||||
llvm::FoldingSet<TupleType> TupleTypes;
|
|
||||||
llvm::DenseMap<Type, MetaTypeType*> MetaTypeTypes;
|
/// \brief Structure that captures data that is segregated into different
|
||||||
|
/// arenas.
|
||||||
|
struct Arena {
|
||||||
|
llvm::FoldingSet<TupleType> TupleTypes;
|
||||||
|
llvm::DenseMap<Type, MetaTypeType*> MetaTypeTypes;
|
||||||
|
llvm::DenseMap<std::pair<Type,std::pair<Type,char>>, FunctionType*>
|
||||||
|
FunctionTypes;
|
||||||
|
llvm::DenseMap<std::pair<Type, uint64_t>, ArrayType*> ArrayTypes;
|
||||||
|
llvm::DenseMap<Type, ArraySliceType*> ArraySliceTypes;
|
||||||
|
llvm::DenseMap<Type, ParenType*> ParenTypes;
|
||||||
|
llvm::DenseMap<std::pair<Type, LValueType::Qual::opaque_type>, LValueType*>
|
||||||
|
LValueTypes;
|
||||||
|
llvm::DenseMap<std::pair<Type, Type>, SubstitutedType *> SubstitutedTypes;
|
||||||
|
llvm::FoldingSet<OneOfType> OneOfTypes;
|
||||||
|
llvm::FoldingSet<StructType> StructTypes;
|
||||||
|
llvm::FoldingSet<ClassType> ClassTypes;
|
||||||
|
llvm::FoldingSet<UnboundGenericType> UnboundGenericTypes;
|
||||||
|
llvm::FoldingSet<BoundGenericType> BoundGenericTypes;
|
||||||
|
};
|
||||||
|
|
||||||
llvm::DenseMap<Module*, ModuleType*> ModuleTypes;
|
llvm::DenseMap<Module*, ModuleType*> ModuleTypes;
|
||||||
llvm::DenseMap<std::pair<Type,std::pair<Type,char>>,
|
|
||||||
FunctionType*> FunctionTypes;
|
|
||||||
llvm::DenseMap<std::pair<Type, uint64_t>, ArrayType*> ArrayTypes;
|
|
||||||
llvm::DenseMap<Type, ArraySliceType*> ArraySliceTypes;
|
|
||||||
llvm::DenseMap<unsigned, BuiltinIntegerType*> IntegerTypes;
|
llvm::DenseMap<unsigned, BuiltinIntegerType*> IntegerTypes;
|
||||||
llvm::DenseMap<Type, ParenType*> ParenTypes;
|
|
||||||
llvm::DenseMap<std::pair<Type, LValueType::Qual::opaque_type>, LValueType*>
|
|
||||||
LValueTypes;
|
|
||||||
llvm::DenseMap<std::pair<Type, Type>, SubstitutedType *> SubstitutedTypes;
|
|
||||||
|
|
||||||
llvm::FoldingSet<OneOfType> OneOfTypes;
|
|
||||||
llvm::FoldingSet<StructType> StructTypes;
|
|
||||||
llvm::FoldingSet<ClassType> ClassTypes;
|
|
||||||
llvm::FoldingSet<ProtocolCompositionType> ProtocolCompositionTypes;
|
llvm::FoldingSet<ProtocolCompositionType> ProtocolCompositionTypes;
|
||||||
llvm::FoldingSet<UnboundGenericType> UnboundGenericTypes;
|
|
||||||
llvm::FoldingSet<BoundGenericType> BoundGenericTypes;
|
|
||||||
|
|
||||||
|
/// \brief The permanent arena.
|
||||||
|
Arena Permanent;
|
||||||
|
|
||||||
|
/// FIXME: Move into arena.
|
||||||
llvm::DenseMap<BoundGenericType *, ArrayRef<Substitution>>
|
llvm::DenseMap<BoundGenericType *, ArrayRef<Substitution>>
|
||||||
BoundGenericSubstitutions;
|
BoundGenericSubstitutions;
|
||||||
|
|
||||||
|
/// \brief Temporary arena used for a constraint solver.
|
||||||
|
struct ConstraintSolverArena : public Arena {
|
||||||
|
/// \brief The allocator used for all allocations within this arena.
|
||||||
|
llvm::BumpPtrAllocator &Allocator;
|
||||||
|
|
||||||
|
ConstraintSolverArena(llvm::BumpPtrAllocator &Allocator)
|
||||||
|
: Allocator(Allocator) { }
|
||||||
|
|
||||||
|
ConstraintSolverArena(const ConstraintSolverArena &) = delete;
|
||||||
|
ConstraintSolverArena(ConstraintSolverArena &&) = delete;
|
||||||
|
ConstraintSolverArena &operator=(const ConstraintSolverArena &) = delete;
|
||||||
|
ConstraintSolverArena &operator=(ConstraintSolverArena &&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief The current constraint solver arena, if any.
|
||||||
|
std::unique_ptr<ConstraintSolverArena> CurrentConstraintSolverArena;
|
||||||
|
|
||||||
|
Arena &getArena(AllocationArena arena) {
|
||||||
|
switch (arena) {
|
||||||
|
case AllocationArena::Permanent:
|
||||||
|
return Permanent;
|
||||||
|
|
||||||
|
case AllocationArena::ConstraintSolver:
|
||||||
|
assert(CurrentConstraintSolverArena && "No constraint solver active?");
|
||||||
|
return *CurrentConstraintSolverArena;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ASTContext::Implementation::Implementation()
|
ASTContext::Implementation::Implementation()
|
||||||
: IdentifierTable(Allocator) {}
|
: IdentifierTable(Allocator) {}
|
||||||
ASTContext::Implementation::~Implementation() {}
|
ASTContext::Implementation::~Implementation() {}
|
||||||
|
|
||||||
|
|
||||||
|
ConstraintCheckerArenaRAII::
|
||||||
|
ConstraintCheckerArenaRAII(ASTContext &self, llvm::BumpPtrAllocator &allocator)
|
||||||
|
: Self(self), Data(self.Impl.CurrentConstraintSolverArena.release())
|
||||||
|
{
|
||||||
|
Self.Impl.CurrentConstraintSolverArena.reset(
|
||||||
|
new ASTContext::Implementation::ConstraintSolverArena(allocator));
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstraintCheckerArenaRAII::~ConstraintCheckerArenaRAII() {
|
||||||
|
Self.Impl.CurrentConstraintSolverArena.reset(
|
||||||
|
(ASTContext::Implementation::ConstraintSolverArena *)Data);
|
||||||
|
}
|
||||||
|
|
||||||
ASTContext::ASTContext(LangOptions &langOpts, llvm::SourceMgr &sourcemgr,
|
ASTContext::ASTContext(LangOptions &langOpts, llvm::SourceMgr &sourcemgr,
|
||||||
DiagnosticEngine &Diags)
|
DiagnosticEngine &Diags)
|
||||||
: Impl(*new Implementation()),
|
: Impl(*new Implementation()),
|
||||||
@@ -65,19 +118,28 @@ ASTContext::ASTContext(LangOptions &langOpts, llvm::SourceMgr &sourcemgr,
|
|||||||
SourceMgr(sourcemgr),
|
SourceMgr(sourcemgr),
|
||||||
Diags(Diags),
|
Diags(Diags),
|
||||||
TheBuiltinModule(new (*this) BuiltinModule(getIdentifier("Builtin"),*this)),
|
TheBuiltinModule(new (*this) BuiltinModule(getIdentifier("Builtin"),*this)),
|
||||||
TheErrorType(new (*this) ErrorType(*this)),
|
TheErrorType(new (*this, AllocationArena::Permanent) ErrorType(*this)),
|
||||||
TheEmptyTupleType(TupleType::get(ArrayRef<TupleTypeElt>(), *this)),
|
TheEmptyTupleType(TupleType::get(ArrayRef<TupleTypeElt>(), *this)),
|
||||||
TheObjectPointerType(new (*this) BuiltinObjectPointerType(*this)),
|
TheObjectPointerType(new (*this, AllocationArena::Permanent)
|
||||||
TheObjCPointerType(new (*this) BuiltinObjCPointerType(*this)),
|
BuiltinObjectPointerType(*this)),
|
||||||
TheRawPointerType(new (*this) BuiltinRawPointerType(*this)),
|
TheObjCPointerType(new (*this, AllocationArena::Permanent)
|
||||||
TheUnstructuredUnresolvedType(new (*this) UnstructuredUnresolvedType(*this)),
|
BuiltinObjCPointerType(*this)),
|
||||||
TheIEEE32Type(new (*this) BuiltinFloatType(BuiltinFloatType::IEEE32,*this)),
|
TheRawPointerType(new (*this, AllocationArena::Permanent)
|
||||||
TheIEEE64Type(new (*this) BuiltinFloatType(BuiltinFloatType::IEEE64,*this)),
|
BuiltinRawPointerType(*this)),
|
||||||
TheIEEE16Type(new (*this) BuiltinFloatType(BuiltinFloatType::IEEE16,*this)),
|
TheUnstructuredUnresolvedType(new (*this, AllocationArena::Permanent)
|
||||||
TheIEEE80Type(new (*this) BuiltinFloatType(BuiltinFloatType::IEEE80,*this)),
|
UnstructuredUnresolvedType(*this)),
|
||||||
TheIEEE128Type(new (*this) BuiltinFloatType(BuiltinFloatType::IEEE128,
|
TheIEEE32Type(new (*this, AllocationArena::Permanent)
|
||||||
*this)),
|
BuiltinFloatType(BuiltinFloatType::IEEE32,*this)),
|
||||||
ThePPC128Type(new (*this) BuiltinFloatType(BuiltinFloatType::PPC128,*this)){
|
TheIEEE64Type(new (*this, AllocationArena::Permanent)
|
||||||
|
BuiltinFloatType(BuiltinFloatType::IEEE64,*this)),
|
||||||
|
TheIEEE16Type(new (*this, AllocationArena::Permanent)
|
||||||
|
BuiltinFloatType(BuiltinFloatType::IEEE16,*this)),
|
||||||
|
TheIEEE80Type(new (*this, AllocationArena::Permanent)
|
||||||
|
BuiltinFloatType(BuiltinFloatType::IEEE80,*this)),
|
||||||
|
TheIEEE128Type(new (*this, AllocationArena::Permanent)
|
||||||
|
BuiltinFloatType(BuiltinFloatType::IEEE128, *this)),
|
||||||
|
ThePPC128Type(new (*this, AllocationArena::Permanent)
|
||||||
|
BuiltinFloatType(BuiltinFloatType::PPC128,*this)){
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTContext::~ASTContext() {
|
ASTContext::~ASTContext() {
|
||||||
@@ -87,8 +149,15 @@ ASTContext::~ASTContext() {
|
|||||||
delete const_cast<ProtocolConformance*>(entry.second);
|
delete const_cast<ProtocolConformance*>(entry.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ASTContext::Allocate(unsigned long Bytes, unsigned Alignment) {
|
llvm::BumpPtrAllocator &ASTContext::getAllocator(AllocationArena arena) const {
|
||||||
return Impl.Allocator.Allocate(Bytes, Alignment);
|
switch (arena) {
|
||||||
|
case AllocationArena::Permanent:
|
||||||
|
return Impl.Allocator;
|
||||||
|
|
||||||
|
case AllocationArena::ConstraintSolver:
|
||||||
|
assert(Impl.CurrentConstraintSolverArena.get() != nullptr);
|
||||||
|
return Impl.CurrentConstraintSolverArena->Allocator;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getIdentifier - Return the uniqued and AST-Context-owned version of the
|
/// getIdentifier - Return the uniqued and AST-Context-owned version of the
|
||||||
@@ -136,15 +205,23 @@ Type UnstructuredUnresolvedType::get(ASTContext &C) {
|
|||||||
BuiltinIntegerType *BuiltinIntegerType::get(unsigned BitWidth, ASTContext &C) {
|
BuiltinIntegerType *BuiltinIntegerType::get(unsigned BitWidth, ASTContext &C) {
|
||||||
BuiltinIntegerType *&Result = C.Impl.IntegerTypes[BitWidth];
|
BuiltinIntegerType *&Result = C.Impl.IntegerTypes[BitWidth];
|
||||||
if (Result == 0)
|
if (Result == 0)
|
||||||
Result = new (C) BuiltinIntegerType(BitWidth, C);
|
Result = new (C, AllocationArena::Permanent) BuiltinIntegerType(BitWidth,C);
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Retrieve the arena from which we should allocate storage for a type.
|
||||||
|
static AllocationArena getArena(bool hasTypeVariable) {
|
||||||
|
return hasTypeVariable? AllocationArena::ConstraintSolver
|
||||||
|
: AllocationArena::Permanent;;
|
||||||
|
}
|
||||||
|
|
||||||
ParenType *ParenType::get(ASTContext &C, Type underlying) {
|
ParenType *ParenType::get(ASTContext &C, Type underlying) {
|
||||||
ParenType *&Result = C.Impl.ParenTypes[underlying];
|
|
||||||
bool hasTypeVariable = underlying->hasTypeVariable();
|
bool hasTypeVariable = underlying->hasTypeVariable();
|
||||||
if (Result == 0)
|
auto arena = getArena(hasTypeVariable);
|
||||||
Result = new (C) ParenType(underlying, hasTypeVariable);
|
ParenType *&Result = C.Impl.getArena(arena).ParenTypes[underlying];
|
||||||
|
if (Result == 0) {
|
||||||
|
Result = new (C, arena) ParenType(underlying, hasTypeVariable);
|
||||||
|
}
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,19 +259,23 @@ Type TupleType::get(ArrayRef<TupleTypeElt> Fields, ASTContext &C) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto arena = getArena(HasTypeVariable);
|
||||||
|
|
||||||
|
|
||||||
void *InsertPos = 0;
|
void *InsertPos = 0;
|
||||||
if (!HasAnyDefaultValues) {
|
if (!HasAnyDefaultValues) {
|
||||||
// Check to see if we've already seen this tuple before.
|
// Check to see if we've already seen this tuple before.
|
||||||
llvm::FoldingSetNodeID ID;
|
llvm::FoldingSetNodeID ID;
|
||||||
TupleType::Profile(ID, Fields);
|
TupleType::Profile(ID, Fields);
|
||||||
|
|
||||||
if (TupleType *TT = C.Impl.TupleTypes.FindNodeOrInsertPos(ID, InsertPos))
|
if (TupleType *TT
|
||||||
|
= C.Impl.getArena(arena).TupleTypes.FindNodeOrInsertPos(ID,InsertPos))
|
||||||
return TT;
|
return TT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a copy of the fields list into ASTContext owned memory.
|
// Make a copy of the fields list into ASTContext owned memory.
|
||||||
TupleTypeElt *FieldsCopy =
|
TupleTypeElt *FieldsCopy =
|
||||||
C.AllocateCopy<TupleTypeElt>(Fields.begin(), Fields.end());
|
C.AllocateCopy<TupleTypeElt>(Fields.begin(), Fields.end(), arena);
|
||||||
|
|
||||||
bool IsCanonical = true; // All canonical elts means this is canonical.
|
bool IsCanonical = true; // All canonical elts means this is canonical.
|
||||||
for (const TupleTypeElt &Elt : Fields) {
|
for (const TupleTypeElt &Elt : Fields) {
|
||||||
@@ -206,10 +287,10 @@ Type TupleType::get(ArrayRef<TupleTypeElt> Fields, ASTContext &C) {
|
|||||||
|
|
||||||
Fields = ArrayRef<TupleTypeElt>(FieldsCopy, Fields.size());
|
Fields = ArrayRef<TupleTypeElt>(FieldsCopy, Fields.size());
|
||||||
|
|
||||||
TupleType *New = new (C) TupleType(Fields, IsCanonical ? &C : 0,
|
TupleType *New = new (C, arena) TupleType(Fields, IsCanonical ? &C : 0,
|
||||||
HasTypeVariable);
|
HasTypeVariable);
|
||||||
if (!HasAnyDefaultValues)
|
if (!HasAnyDefaultValues)
|
||||||
C.Impl.TupleTypes.InsertNode(New, InsertPos);
|
C.Impl.getArena(arena).TupleTypes.InsertNode(New, InsertPos);
|
||||||
|
|
||||||
return New;
|
return New;
|
||||||
}
|
}
|
||||||
@@ -226,24 +307,33 @@ UnboundGenericType* UnboundGenericType::get(NominalTypeDecl *TheDecl,
|
|||||||
llvm::FoldingSetNodeID ID;
|
llvm::FoldingSetNodeID ID;
|
||||||
UnboundGenericType::Profile(ID, TheDecl, Parent);
|
UnboundGenericType::Profile(ID, TheDecl, Parent);
|
||||||
void *InsertPos = 0;
|
void *InsertPos = 0;
|
||||||
if (auto unbound = C.Impl.UnboundGenericTypes.FindNodeOrInsertPos(ID,
|
bool hasTypeVariable = Parent && Parent->hasTypeVariable();
|
||||||
InsertPos))
|
auto arena = getArena(hasTypeVariable);
|
||||||
|
|
||||||
|
if (auto unbound = C.Impl.getArena(arena).UnboundGenericTypes
|
||||||
|
.FindNodeOrInsertPos(ID, InsertPos))
|
||||||
return unbound;
|
return unbound;
|
||||||
|
|
||||||
bool hasTypeVariable = Parent && Parent->hasTypeVariable();
|
auto result = new (C, arena) UnboundGenericType(TheDecl, Parent, C,
|
||||||
auto result = new (C) UnboundGenericType(TheDecl, Parent, C, hasTypeVariable);
|
hasTypeVariable);
|
||||||
C.Impl.UnboundGenericTypes.InsertNode(result, InsertPos);
|
C.Impl.getArena(arena).UnboundGenericTypes.InsertNode(result, InsertPos);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoundGenericType::Profile(llvm::FoldingSetNodeID &ID,
|
void BoundGenericType::Profile(llvm::FoldingSetNodeID &ID,
|
||||||
NominalTypeDecl *TheDecl, Type Parent,
|
NominalTypeDecl *TheDecl, Type Parent,
|
||||||
ArrayRef<Type> GenericArgs) {
|
ArrayRef<Type> GenericArgs,
|
||||||
|
bool &hasTypeVariable) {
|
||||||
ID.AddPointer(TheDecl);
|
ID.AddPointer(TheDecl);
|
||||||
ID.AddPointer(Parent.getPointer());
|
ID.AddPointer(Parent.getPointer());
|
||||||
|
if (Parent && Parent->hasTypeVariable())
|
||||||
|
hasTypeVariable = true;
|
||||||
ID.AddInteger(GenericArgs.size());
|
ID.AddInteger(GenericArgs.size());
|
||||||
for (Type Arg : GenericArgs)
|
for (Type Arg : GenericArgs) {
|
||||||
ID.AddPointer(Arg.getPointer());
|
ID.AddPointer(Arg.getPointer());
|
||||||
|
if (Arg->hasTypeVariable())
|
||||||
|
hasTypeVariable = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundGenericType::BoundGenericType(TypeKind theKind,
|
BoundGenericType::BoundGenericType(TypeKind theKind,
|
||||||
@@ -272,48 +362,44 @@ BoundGenericType *BoundGenericType::get(NominalTypeDecl *TheDecl,
|
|||||||
ArrayRef<Type> GenericArgs) {
|
ArrayRef<Type> GenericArgs) {
|
||||||
ASTContext &C = TheDecl->getDeclContext()->getASTContext();
|
ASTContext &C = TheDecl->getDeclContext()->getASTContext();
|
||||||
llvm::FoldingSetNodeID ID;
|
llvm::FoldingSetNodeID ID;
|
||||||
BoundGenericType::Profile(ID, TheDecl, Parent, GenericArgs);
|
bool HasTypeVariable = false;
|
||||||
|
BoundGenericType::Profile(ID, TheDecl, Parent, GenericArgs, HasTypeVariable);
|
||||||
|
|
||||||
|
auto arena = getArena(HasTypeVariable);
|
||||||
|
|
||||||
void *InsertPos = 0;
|
void *InsertPos = 0;
|
||||||
if (BoundGenericType *BGT =
|
if (BoundGenericType *BGT =
|
||||||
C.Impl.BoundGenericTypes.FindNodeOrInsertPos(ID, InsertPos))
|
C.Impl.getArena(arena).BoundGenericTypes.FindNodeOrInsertPos(ID,
|
||||||
|
InsertPos))
|
||||||
return BGT;
|
return BGT;
|
||||||
|
|
||||||
bool HasTypeVariable = Parent && Parent->hasTypeVariable();
|
ArrayRef<Type> ArgsCopy = C.AllocateCopy(GenericArgs, arena);
|
||||||
ArrayRef<Type> ArgsCopy = C.AllocateCopy(GenericArgs);
|
|
||||||
bool IsCanonical = !Parent || Parent->isCanonical();
|
bool IsCanonical = !Parent || Parent->isCanonical();
|
||||||
if (IsCanonical || !HasTypeVariable) {
|
if (IsCanonical) {
|
||||||
for (Type Arg : GenericArgs) {
|
for (Type Arg : GenericArgs) {
|
||||||
if (!Arg->isCanonical()) {
|
if (!Arg->isCanonical()) {
|
||||||
IsCanonical = false;
|
IsCanonical = false;
|
||||||
if (HasTypeVariable)
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Arg->hasTypeVariable()) {
|
|
||||||
HasTypeVariable = true;
|
|
||||||
if (!IsCanonical)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundGenericType *newType;
|
BoundGenericType *newType;
|
||||||
if (auto theClass = dyn_cast<ClassDecl>(TheDecl)) {
|
if (auto theClass = dyn_cast<ClassDecl>(TheDecl)) {
|
||||||
newType = new (C) BoundGenericClassType(theClass, Parent, ArgsCopy,
|
newType = new (C, arena) BoundGenericClassType(theClass, Parent, ArgsCopy,
|
||||||
IsCanonical ? &C : 0,
|
IsCanonical ? &C : 0,
|
||||||
HasTypeVariable);
|
HasTypeVariable);
|
||||||
} else if (auto theStruct = dyn_cast<StructDecl>(TheDecl)) {
|
} else if (auto theStruct = dyn_cast<StructDecl>(TheDecl)) {
|
||||||
newType = new (C) BoundGenericStructType(theStruct, Parent, ArgsCopy,
|
newType = new (C, arena) BoundGenericStructType(theStruct, Parent, ArgsCopy,
|
||||||
IsCanonical ? &C : 0,
|
IsCanonical ? &C : 0,
|
||||||
HasTypeVariable);
|
HasTypeVariable);
|
||||||
} else {
|
} else {
|
||||||
auto theOneOf = cast<OneOfDecl>(TheDecl);
|
auto theOneOf = cast<OneOfDecl>(TheDecl);
|
||||||
newType = new (C) BoundGenericOneOfType(theOneOf, Parent, ArgsCopy,
|
newType = new (C, arena) BoundGenericOneOfType(theOneOf, Parent, ArgsCopy,
|
||||||
IsCanonical ? &C : 0,
|
IsCanonical ? &C : 0,
|
||||||
HasTypeVariable);
|
HasTypeVariable);
|
||||||
}
|
}
|
||||||
C.Impl.BoundGenericTypes.InsertNode(newType, InsertPos);
|
C.Impl.getArena(arena).BoundGenericTypes.InsertNode(newType, InsertPos);
|
||||||
|
|
||||||
return newType;
|
return newType;
|
||||||
}
|
}
|
||||||
@@ -340,15 +426,18 @@ OneOfType::OneOfType(OneOfDecl *TheDecl, Type Parent, ASTContext &C,
|
|||||||
|
|
||||||
OneOfType *OneOfType::get(OneOfDecl *D, Type Parent, ASTContext &C) {
|
OneOfType *OneOfType::get(OneOfDecl *D, Type Parent, ASTContext &C) {
|
||||||
llvm::FoldingSetNodeID id;
|
llvm::FoldingSetNodeID id;
|
||||||
OneOfType::Profile(id, D,Parent);
|
OneOfType::Profile(id, D, Parent);
|
||||||
|
|
||||||
void *insertPos = 0;
|
|
||||||
if (auto oneOfTy = C.Impl.OneOfTypes.FindNodeOrInsertPos(id, insertPos))
|
|
||||||
return oneOfTy;
|
|
||||||
|
|
||||||
bool hasTypeVariable = Parent && Parent->hasTypeVariable();
|
bool hasTypeVariable = Parent && Parent->hasTypeVariable();
|
||||||
auto oneOfTy = new (C) OneOfType(D, Parent, C, hasTypeVariable);
|
auto arena = getArena(hasTypeVariable);
|
||||||
C.Impl.OneOfTypes.InsertNode(oneOfTy, insertPos);
|
|
||||||
|
void *insertPos = 0;
|
||||||
|
if (auto oneOfTy
|
||||||
|
= C.Impl.getArena(arena).OneOfTypes.FindNodeOrInsertPos(id, insertPos))
|
||||||
|
return oneOfTy;
|
||||||
|
|
||||||
|
auto oneOfTy = new (C, arena) OneOfType(D, Parent, C, hasTypeVariable);
|
||||||
|
C.Impl.getArena(arena).OneOfTypes.InsertNode(oneOfTy, insertPos);
|
||||||
return oneOfTy;
|
return oneOfTy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,13 +454,16 @@ StructType *StructType::get(StructDecl *D, Type Parent, ASTContext &C) {
|
|||||||
llvm::FoldingSetNodeID id;
|
llvm::FoldingSetNodeID id;
|
||||||
StructType::Profile(id, D, Parent);
|
StructType::Profile(id, D, Parent);
|
||||||
|
|
||||||
|
bool hasTypeVariable = Parent && Parent->hasTypeVariable();
|
||||||
|
auto arena = getArena(hasTypeVariable);
|
||||||
|
|
||||||
void *insertPos = 0;
|
void *insertPos = 0;
|
||||||
if (auto structTy = C.Impl.StructTypes.FindNodeOrInsertPos(id, insertPos))
|
if (auto structTy
|
||||||
|
= C.Impl.getArena(arena).StructTypes.FindNodeOrInsertPos(id, insertPos))
|
||||||
return structTy;
|
return structTy;
|
||||||
|
|
||||||
bool hasTypeVariable = Parent && Parent->hasTypeVariable();
|
auto structTy = new (C, arena) StructType(D, Parent, C, hasTypeVariable);
|
||||||
auto structTy = new (C) StructType(D, Parent, C, hasTypeVariable);
|
C.Impl.getArena(arena).StructTypes.InsertNode(structTy, insertPos);
|
||||||
C.Impl.StructTypes.InsertNode(structTy, insertPos);
|
|
||||||
return structTy;
|
return structTy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,13 +480,16 @@ ClassType *ClassType::get(ClassDecl *D, Type Parent, ASTContext &C) {
|
|||||||
llvm::FoldingSetNodeID id;
|
llvm::FoldingSetNodeID id;
|
||||||
ClassType::Profile(id, D, Parent);
|
ClassType::Profile(id, D, Parent);
|
||||||
|
|
||||||
|
bool hasTypeVariable = Parent && Parent->hasTypeVariable();
|
||||||
|
auto arena = getArena(hasTypeVariable);
|
||||||
|
|
||||||
void *insertPos = 0;
|
void *insertPos = 0;
|
||||||
if (auto classTy = C.Impl.ClassTypes.FindNodeOrInsertPos(id, insertPos))
|
if (auto classTy
|
||||||
|
= C.Impl.getArena(arena).ClassTypes.FindNodeOrInsertPos(id, insertPos))
|
||||||
return classTy;
|
return classTy;
|
||||||
|
|
||||||
bool hasTypeVariable = Parent && Parent->hasTypeVariable();
|
auto classTy = new (C, arena) ClassType(D, Parent, C, hasTypeVariable);
|
||||||
auto classTy = new (C) ClassType(D, Parent, C, hasTypeVariable);
|
C.Impl.getArena(arena).ClassTypes.InsertNode(classTy, insertPos);
|
||||||
C.Impl.ClassTypes.InsertNode(classTy, insertPos);
|
|
||||||
return classTy;
|
return classTy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,7 +501,7 @@ void ClassType::Profile(llvm::FoldingSetNodeID &ID, ClassDecl *D, Type Parent) {
|
|||||||
IdentifierType *IdentifierType::getNew(ASTContext &C,
|
IdentifierType *IdentifierType::getNew(ASTContext &C,
|
||||||
MutableArrayRef<Component> Components) {
|
MutableArrayRef<Component> Components) {
|
||||||
Components = C.AllocateCopy(Components);
|
Components = C.AllocateCopy(Components);
|
||||||
return new (C) IdentifierType(Components);
|
return new (C, AllocationArena::Permanent) IdentifierType(Components);
|
||||||
}
|
}
|
||||||
|
|
||||||
ProtocolCompositionType *
|
ProtocolCompositionType *
|
||||||
@@ -426,21 +521,24 @@ ProtocolCompositionType::build(ASTContext &C, ArrayRef<Type> Protocols) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a new protocol composition type.
|
// Create a new protocol composition type.
|
||||||
ProtocolCompositionType *New =
|
ProtocolCompositionType *New
|
||||||
new (C) ProtocolCompositionType(isCanonical ? &C : nullptr,
|
= new (C, AllocationArena::Permanent)
|
||||||
C.AllocateCopy(Protocols));
|
ProtocolCompositionType(isCanonical ? &C : nullptr,
|
||||||
|
C.AllocateCopy(Protocols));
|
||||||
C.Impl.ProtocolCompositionTypes.InsertNode(New, InsertPos);
|
C.Impl.ProtocolCompositionTypes.InsertNode(New, InsertPos);
|
||||||
return New;
|
return New;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MetaTypeType *MetaTypeType::get(Type T, ASTContext &C) {
|
MetaTypeType *MetaTypeType::get(Type T, ASTContext &C) {
|
||||||
MetaTypeType *&Entry = C.Impl.MetaTypeTypes[T];
|
bool hasTypeVariable = T->hasTypeVariable();
|
||||||
|
auto arena = getArena(hasTypeVariable);
|
||||||
|
|
||||||
|
MetaTypeType *&Entry = C.Impl.getArena(arena).MetaTypeTypes[T];
|
||||||
if (Entry) return Entry;
|
if (Entry) return Entry;
|
||||||
|
|
||||||
bool hasTypeVariable = T->hasTypeVariable();
|
return Entry = new (C, arena) MetaTypeType(T, T->isCanonical() ? &C : 0,
|
||||||
return Entry = new (C) MetaTypeType(T, T->isCanonical() ? &C : 0,
|
hasTypeVariable);
|
||||||
hasTypeVariable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MetaTypeType::MetaTypeType(Type T, ASTContext *C, bool HasTypeVariable)
|
MetaTypeType::MetaTypeType(Type T, ASTContext *C, bool HasTypeVariable)
|
||||||
@@ -454,21 +552,21 @@ ModuleType *ModuleType::get(Module *M) {
|
|||||||
ModuleType *&Entry = C.Impl.ModuleTypes[M];
|
ModuleType *&Entry = C.Impl.ModuleTypes[M];
|
||||||
if (Entry) return Entry;
|
if (Entry) return Entry;
|
||||||
|
|
||||||
return Entry = new (C) ModuleType(M, C);
|
return Entry = new (C, AllocationArena::Permanent) ModuleType(M, C);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// FunctionType::get - Return a uniqued function type with the specified
|
/// FunctionType::get - Return a uniqued function type with the specified
|
||||||
/// input and result.
|
/// input and result.
|
||||||
FunctionType *FunctionType::get(Type Input, Type Result, bool isAutoClosure,
|
FunctionType *FunctionType::get(Type Input, Type Result, bool isAutoClosure,
|
||||||
ASTContext &C) {
|
ASTContext &C) {
|
||||||
FunctionType *&Entry =
|
bool hasTypeVariable = Input->hasTypeVariable() || Result->hasTypeVariable();
|
||||||
C.Impl.FunctionTypes[std::make_pair(Input,
|
auto arena = getArena(hasTypeVariable);
|
||||||
std::make_pair(Result,
|
|
||||||
(char)isAutoClosure))];
|
FunctionType *&Entry
|
||||||
|
= C.Impl.getArena(arena).FunctionTypes[{Input, {Result, isAutoClosure} }];
|
||||||
if (Entry) return Entry;
|
if (Entry) return Entry;
|
||||||
|
|
||||||
bool hasTypeVariable = Input->hasTypeVariable() || Result->hasTypeVariable();
|
return Entry = new (C, arena) FunctionType(Input, Result, isAutoClosure,
|
||||||
return Entry = new (C) FunctionType(Input, Result, isAutoClosure,
|
|
||||||
hasTypeVariable);
|
hasTypeVariable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -490,7 +588,10 @@ PolymorphicFunctionType *PolymorphicFunctionType::get(Type input, Type output,
|
|||||||
GenericParamList *params,
|
GenericParamList *params,
|
||||||
ASTContext &C) {
|
ASTContext &C) {
|
||||||
// FIXME: one day we should do canonicalization properly.
|
// FIXME: one day we should do canonicalization properly.
|
||||||
return new (C) PolymorphicFunctionType(input, output, params, C);
|
bool hasTypeVariable = input->hasTypeVariable() || output->hasTypeVariable();
|
||||||
|
auto arena = getArena(hasTypeVariable);
|
||||||
|
|
||||||
|
return new (C, arena) PolymorphicFunctionType(input, output, params, C);
|
||||||
}
|
}
|
||||||
|
|
||||||
PolymorphicFunctionType::PolymorphicFunctionType(Type input, Type output,
|
PolymorphicFunctionType::PolymorphicFunctionType(Type input, Type output,
|
||||||
@@ -511,11 +612,14 @@ PolymorphicFunctionType::PolymorphicFunctionType(Type input, Type output,
|
|||||||
ArrayType *ArrayType::get(Type BaseType, uint64_t Size, ASTContext &C) {
|
ArrayType *ArrayType::get(Type BaseType, uint64_t Size, ASTContext &C) {
|
||||||
assert(Size != 0);
|
assert(Size != 0);
|
||||||
|
|
||||||
ArrayType *&Entry = C.Impl.ArrayTypes[std::make_pair(BaseType, Size)];
|
bool hasTypeVariable = BaseType->hasTypeVariable();
|
||||||
|
auto arena = getArena(hasTypeVariable);
|
||||||
|
|
||||||
|
ArrayType *&Entry
|
||||||
|
= C.Impl.getArena(arena).ArrayTypes[std::make_pair(BaseType, Size)];
|
||||||
if (Entry) return Entry;
|
if (Entry) return Entry;
|
||||||
|
|
||||||
bool hasTypeVariable = BaseType->hasTypeVariable();
|
return Entry = new (C, arena) ArrayType(BaseType, Size, hasTypeVariable);
|
||||||
return Entry = new (C) ArrayType(BaseType, Size, hasTypeVariable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayType::ArrayType(Type base, uint64_t size, bool hasTypeVariable)
|
ArrayType::ArrayType(Type base, uint64_t size, bool hasTypeVariable)
|
||||||
@@ -527,11 +631,13 @@ ArrayType::ArrayType(Type base, uint64_t size, bool hasTypeVariable)
|
|||||||
|
|
||||||
/// Return a uniqued array slice type with the specified base type.
|
/// Return a uniqued array slice type with the specified base type.
|
||||||
ArraySliceType *ArraySliceType::get(Type base, ASTContext &C) {
|
ArraySliceType *ArraySliceType::get(Type base, ASTContext &C) {
|
||||||
ArraySliceType *&entry = C.Impl.ArraySliceTypes[base];
|
bool hasTypeVariable = base->hasTypeVariable();
|
||||||
|
auto arena = getArena(hasTypeVariable);
|
||||||
|
|
||||||
|
ArraySliceType *&entry = C.Impl.getArena(arena).ArraySliceTypes[base];
|
||||||
if (entry) return entry;
|
if (entry) return entry;
|
||||||
|
|
||||||
bool hasTypeVariable = base->hasTypeVariable();
|
return entry = new (C, arena) ArraySliceType(base, hasTypeVariable);
|
||||||
return entry = new (C) ArraySliceType(base, hasTypeVariable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ProtocolType::ProtocolType(ProtocolDecl *TheDecl, ASTContext &Ctx)
|
ProtocolType::ProtocolType(ProtocolDecl *TheDecl, ASTContext &Ctx)
|
||||||
@@ -539,25 +645,30 @@ ProtocolType::ProtocolType(ProtocolDecl *TheDecl, ASTContext &Ctx)
|
|||||||
/*HasTypeVariable=*/false) { }
|
/*HasTypeVariable=*/false) { }
|
||||||
|
|
||||||
LValueType *LValueType::get(Type objectTy, Qual quals, ASTContext &C) {
|
LValueType *LValueType::get(Type objectTy, Qual quals, ASTContext &C) {
|
||||||
auto key = std::make_pair(objectTy, quals.getOpaqueData());
|
|
||||||
auto it = C.Impl.LValueTypes.find(key);
|
|
||||||
if (it != C.Impl.LValueTypes.end()) return it->second;
|
|
||||||
|
|
||||||
bool hasTypeVariable = objectTy->hasTypeVariable();
|
bool hasTypeVariable = objectTy->hasTypeVariable();
|
||||||
|
auto arena = getArena(hasTypeVariable);
|
||||||
|
|
||||||
|
auto key = std::make_pair(objectTy, quals.getOpaqueData());
|
||||||
|
auto &entry = C.Impl.getArena(arena).LValueTypes[key];
|
||||||
|
if (entry)
|
||||||
|
return entry;
|
||||||
|
|
||||||
ASTContext *canonicalContext = (objectTy->isCanonical() ? &C : nullptr);
|
ASTContext *canonicalContext = (objectTy->isCanonical() ? &C : nullptr);
|
||||||
LValueType *type = new (C) LValueType(objectTy, quals, canonicalContext,
|
return entry = new (C, arena) LValueType(objectTy, quals, canonicalContext,
|
||||||
hasTypeVariable);
|
hasTypeVariable);
|
||||||
C.Impl.LValueTypes.insert(std::make_pair(key, type));
|
|
||||||
return type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a uniqued substituted type.
|
/// Return a uniqued substituted type.
|
||||||
SubstitutedType *SubstitutedType::get(Type Original, Type Replacement,
|
SubstitutedType *SubstitutedType::get(Type Original, Type Replacement,
|
||||||
ASTContext &C) {
|
ASTContext &C) {
|
||||||
SubstitutedType *&Known = C.Impl.SubstitutedTypes[{Original, Replacement}];
|
bool hasTypeVariable = Replacement->hasTypeVariable();
|
||||||
|
auto arena = getArena(hasTypeVariable);
|
||||||
|
|
||||||
|
SubstitutedType *&Known
|
||||||
|
= C.Impl.getArena(arena).SubstitutedTypes[{Original, Replacement}];
|
||||||
if (!Known) {
|
if (!Known) {
|
||||||
bool hasTypeVariable = Replacement->hasTypeVariable();
|
Known = new (C, arena) SubstitutedType(Original, Replacement,
|
||||||
Known = new (C) SubstitutedType(Original, Replacement, hasTypeVariable);
|
hasTypeVariable);
|
||||||
}
|
}
|
||||||
return Known;
|
return Known;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -371,7 +371,7 @@ TypeAliasDecl::TypeAliasDecl(SourceLoc TypeAliasLoc, Identifier Name,
|
|||||||
{
|
{
|
||||||
// Set the type of the TypeAlias to the right MetaTypeType.
|
// Set the type of the TypeAlias to the right MetaTypeType.
|
||||||
ASTContext &Ctx = getASTContext();
|
ASTContext &Ctx = getASTContext();
|
||||||
AliasTy = new (Ctx) NameAliasType(this);
|
AliasTy = new (Ctx, AllocationArena::Permanent) NameAliasType(this);
|
||||||
setType(MetaTypeType::get(AliasTy, Ctx));
|
setType(MetaTypeType::get(AliasTy, Ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,7 +451,7 @@ ProtocolDecl::ProtocolDecl(DeclContext *DC, SourceLoc ProtocolLoc,
|
|||||||
{
|
{
|
||||||
// Compute the associated type for this ClassDecl.
|
// Compute the associated type for this ClassDecl.
|
||||||
ASTContext &Ctx = DC->getASTContext();
|
ASTContext &Ctx = DC->getASTContext();
|
||||||
DeclaredTy = new (Ctx) ProtocolType(this, Ctx);
|
DeclaredTy = new (Ctx, AllocationArena::Permanent) ProtocolType(this, Ctx);
|
||||||
// Set the type of the ProtocolDecl to the right MetaTypeType.
|
// Set the type of the ProtocolDecl to the right MetaTypeType.
|
||||||
setType(MetaTypeType::get(DeclaredTy, Ctx));
|
setType(MetaTypeType::get(DeclaredTy, Ctx));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,9 +28,9 @@
|
|||||||
using namespace swift;
|
using namespace swift;
|
||||||
|
|
||||||
// Only allow allocation of Stmts using the allocator in ASTContext.
|
// Only allow allocation of Stmts using the allocator in ASTContext.
|
||||||
void *TypeBase::operator new(size_t Bytes, ASTContext &C,
|
void *TypeBase::operator new(size_t bytes, ASTContext &ctx,
|
||||||
unsigned Alignment) {
|
AllocationArena arena, unsigned alignment) {
|
||||||
return C.Allocate(Bytes, Alignment);
|
return ctx.Allocate(bytes, alignment, arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CanType::isActuallyCanonicalOrNull() const {
|
bool CanType::isActuallyCanonicalOrNull() const {
|
||||||
@@ -896,9 +896,10 @@ ArchetypeType *ArchetypeType::getNew(ASTContext &Ctx, ArchetypeType *Parent,
|
|||||||
llvm::array_pod_sort(ConformsToProtos.begin(), ConformsToProtos.end(),
|
llvm::array_pod_sort(ConformsToProtos.begin(), ConformsToProtos.end(),
|
||||||
compareProtocols);
|
compareProtocols);
|
||||||
|
|
||||||
return new (Ctx) ArchetypeType(Ctx, Parent, Name,
|
auto arena = AllocationArena::Permanent;
|
||||||
Ctx.AllocateCopy(ConformsToProtos),
|
return new (Ctx, arena) ArchetypeType(Ctx, Parent, Name,
|
||||||
Index);
|
Ctx.AllocateCopy(ConformsToProtos),
|
||||||
|
Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArchetypeType *
|
ArchetypeType *
|
||||||
@@ -910,8 +911,9 @@ ArchetypeType::getNew(ASTContext &Ctx, ArchetypeType *Parent,
|
|||||||
minimizeProtocols(ConformsTo);
|
minimizeProtocols(ConformsTo);
|
||||||
llvm::array_pod_sort(ConformsTo.begin(), ConformsTo.end(), compareProtocols);
|
llvm::array_pod_sort(ConformsTo.begin(), ConformsTo.end(), compareProtocols);
|
||||||
|
|
||||||
return new (Ctx) ArchetypeType(Ctx, Parent, Name,
|
auto arena = AllocationArena::Permanent;
|
||||||
Ctx.AllocateCopy(ConformsTo), Index);
|
return new (Ctx, arena) ArchetypeType(Ctx, Parent, Name,
|
||||||
|
Ctx.AllocateCopy(ConformsTo), Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -974,7 +976,8 @@ DeducibleGenericParamType *
|
|||||||
DeducibleGenericParamType::getNew(ASTContext &Ctx,
|
DeducibleGenericParamType::getNew(ASTContext &Ctx,
|
||||||
DeducibleGenericParamType *Parent,
|
DeducibleGenericParamType *Parent,
|
||||||
ArchetypeType *Archetype) {
|
ArchetypeType *Archetype) {
|
||||||
return new (Ctx) DeducibleGenericParamType(Ctx, Parent, Archetype);
|
auto arena = AllocationArena::Permanent;
|
||||||
|
return new (Ctx, arena) DeducibleGenericParamType(Ctx, Parent, Archetype);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtocolCompositionType::Profile(llvm::FoldingSetNodeID &ID,
|
void ProtocolCompositionType::Profile(llvm::FoldingSetNodeID &ID,
|
||||||
|
|||||||
@@ -762,6 +762,13 @@ namespace {
|
|||||||
/// \brief Allocator used for all of the related constraint systems.
|
/// \brief Allocator used for all of the related constraint systems.
|
||||||
llvm::BumpPtrAllocator Allocator;
|
llvm::BumpPtrAllocator Allocator;
|
||||||
|
|
||||||
|
/// \brief Arena used for memory management of constraint-checker-related
|
||||||
|
/// allocations.
|
||||||
|
///
|
||||||
|
/// This arena will automatically be destroyed when the top constraint
|
||||||
|
/// system is destroyed.
|
||||||
|
ConstraintCheckerArenaRAII Arena;
|
||||||
|
|
||||||
/// \brief Counter for type variables introduced.
|
/// \brief Counter for type variables introduced.
|
||||||
unsigned TypeCounter = 0;
|
unsigned TypeCounter = 0;
|
||||||
|
|
||||||
@@ -774,6 +781,9 @@ namespace {
|
|||||||
|
|
||||||
/// \brief Cached literal checks.
|
/// \brief Cached literal checks.
|
||||||
std::map<std::pair<TypeBase *, LiteralKind>, bool> LiteralChecks;
|
std::map<std::pair<TypeBase *, LiteralKind>, bool> LiteralChecks;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SharedStateType(TypeChecker &tc) : Arena(tc.Context, Allocator) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief The state shared among all of the related constraint systems.
|
/// \brief The state shared among all of the related constraint systems.
|
||||||
@@ -846,8 +856,8 @@ namespace {
|
|||||||
friend class OverloadSet;
|
friend class OverloadSet;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ConstraintSystem(TypeChecker &TC)
|
ConstraintSystem(TypeChecker &tc)
|
||||||
: TC(TC), SharedState(new SharedStateType)
|
: TC(tc), SharedState(new SharedStateType(tc))
|
||||||
{
|
{
|
||||||
++NumExploredConstraintSystems;
|
++NumExploredConstraintSystems;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user