Skip to content

Commit 2183b57

Browse files
committed
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
1 parent 048b50f commit 2183b57

File tree

6 files changed

+346
-153
lines changed

6 files changed

+346
-153
lines changed

include/swift/AST/ASTContext.h

Lines changed: 88 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,12 @@
2828
#include <utility>
2929

3030
namespace llvm {
31+
class BumpPtrAllocator;
3132
class SourceMgr;
3233
}
3334

3435
namespace swift {
36+
class ASTContext;
3537
class BoundGenericType;
3638
class SourceLoc;
3739
class Type;
@@ -71,7 +73,53 @@ class ProtocolConformance {
7173
/// the requirements of those protocols.
7274
llvm::DenseMap<ProtocolDecl *, ProtocolConformance *> InheritedMapping;
7375
};
74-
76+
77+
/// \brief The arena in which a particular ASTContext allocation will go.
78+
enum class AllocationArena {
79+
/// \brief The permanent arena, which is tied to the lifetime of
80+
/// the ASTContext.
81+
///
82+
/// All global declarations and types need to be allocated into this arena.
83+
/// At present, everything that is not a type involving a type variable is
84+
/// allocated in this arena.
85+
Permanent,
86+
/// \brief The constraint solver's temporary arena, which is tied to the
87+
/// lifetime of a particular instance of the constraint solver.
88+
///
89+
/// Any type involving a type variable is allocated in this arena.
90+
ConstraintSolver
91+
};
92+
93+
/// \brief Introduces a new constraint checker arena, whose lifetime is
94+
/// tied to the lifetime of this RAII object.
95+
class ConstraintCheckerArenaRAII {
96+
ASTContext &Self;
97+
void *Data;
98+
99+
public:
100+
/// \brief Introduces a new constraint checker arena, supplanting any
101+
/// existing constraint checker arena.
102+
///
103+
/// \param self The ASTContext into which this constraint checker arena
104+
/// will be installed.
105+
///
106+
/// \param allocator The allocator used for allocating any data that
107+
/// goes into the constraint checker arena.
108+
ConstraintCheckerArenaRAII(ASTContext &self,
109+
llvm::BumpPtrAllocator &allocator);
110+
111+
ConstraintCheckerArenaRAII(const ConstraintCheckerArenaRAII &) = delete;
112+
ConstraintCheckerArenaRAII(ConstraintCheckerArenaRAII &&) = delete;
113+
114+
ConstraintCheckerArenaRAII &
115+
operator=(const ConstraintCheckerArenaRAII &) = delete;
116+
117+
ConstraintCheckerArenaRAII &
118+
operator=(ConstraintCheckerArenaRAII &&) = delete;
119+
120+
~ConstraintCheckerArenaRAII();
121+
};
122+
75123
/// ASTContext - This object creates and owns the AST objects.
76124
class ASTContext {
77125
ASTContext(const ASTContext&) = delete;
@@ -81,6 +129,8 @@ class ASTContext {
81129
// Members that should only be used by ASTContext.cpp.
82130
struct Implementation;
83131
Implementation &Impl;
132+
133+
friend class ConstraintCheckerArenaRAII;
84134
public:
85135

86136
ASTContext(LangOptions &langOpts, llvm::SourceMgr &SourceMgr,
@@ -113,47 +163,63 @@ class ASTContext {
113163
/// ConformsTo - Caches the results of checking whether a given (canonical)
114164
/// type conforms to a given protocol.
115165
ConformsToMap ConformsTo;
166+
167+
/// \brief Retrieve the allocator for the given arena.
168+
llvm::BumpPtrAllocator &
169+
getAllocator(AllocationArena arena = AllocationArena::Permanent) const;
116170

117171
/// Allocate - Allocate memory from the ASTContext bump pointer.
118-
void *Allocate(unsigned long Bytes, unsigned Alignment);
172+
void *Allocate(unsigned long bytes, unsigned alignment,
173+
AllocationArena arena = AllocationArena::Permanent) {
174+
return getAllocator(arena).Allocate(bytes, alignment);
175+
}
176+
119177

120178
template <typename T>
121-
T *Allocate(unsigned NElts) {
122-
T *Res = (T*)Allocate(sizeof(T)*NElts, __alignof__(T));
123-
for (unsigned i = 0; i != NElts; ++i)
124-
new (Res+i) T();
125-
return Res;
179+
T *Allocate(unsigned numElts,
180+
AllocationArena arena = AllocationArena::Permanent) {
181+
T *res = (T*)Allocate(sizeof(T)*numElts, __alignof__(T), arena);
182+
for (unsigned i = 0; i != numElts; ++i)
183+
new (res+i) T();
184+
return res;
126185
}
127186

128187
template <typename T, typename It>
129-
T *AllocateCopy(It Start, It End) {
130-
T *Res = (T*)Allocate(sizeof(T)*(End-Start), __alignof__(T));
131-
for (unsigned i = 0; Start != End; ++Start, ++i)
132-
new (Res+i) T(*Start);
133-
return Res;
188+
T *AllocateCopy(It start, It end,
189+
AllocationArena arena = AllocationArena::Permanent) {
190+
T *res = (T*)Allocate(sizeof(T)*(end-start), __alignof__(T), arena);
191+
for (unsigned i = 0; start != end; ++start, ++i)
192+
new (res+i) T(*start);
193+
return res;
134194
}
135195

136196
template<typename T>
137-
ArrayRef<T> AllocateCopy(ArrayRef<T> Arr) {
138-
return ArrayRef<T>(AllocateCopy<T>(Arr.begin(), Arr.end()),
139-
Arr.size());
197+
ArrayRef<T> AllocateCopy(ArrayRef<T> array,
198+
AllocationArena arena = AllocationArena::Permanent) {
199+
return ArrayRef<T>(AllocateCopy<T>(array.begin(), array.end(), arena),
200+
array.size());
140201
}
141202

142203
template<typename T>
143-
MutableArrayRef<T> AllocateCopy(MutableArrayRef<T> Arr) {
144-
return MutableArrayRef<T>(AllocateCopy<T>(Arr.begin(), Arr.end()),
145-
Arr.size());
204+
MutableArrayRef<T>
205+
AllocateCopy(MutableArrayRef<T> array,
206+
AllocationArena arena = AllocationArena::Permanent) {
207+
return MutableArrayRef<T>(AllocateCopy<T>(array.begin(), array.end(),arena),
208+
array.size());
146209
}
147210

148211

149212
template<typename T>
150-
ArrayRef<T> AllocateCopy(const SmallVectorImpl<T> &Vec) {
151-
return AllocateCopy(ArrayRef<T>(Vec));
213+
ArrayRef<T> AllocateCopy(const SmallVectorImpl<T> &vec,
214+
AllocationArena arena = AllocationArena::Permanent) {
215+
return AllocateCopy(ArrayRef<T>(vec), arena);
152216
}
153217

154218
template<typename T>
155-
MutableArrayRef<T> AllocateCopy(SmallVectorImpl<T> &Vec) {
156-
return AllocateCopy(MutableArrayRef<T>(Vec));
219+
MutableArrayRef<T>
220+
AllocateCopy(SmallVectorImpl<T> &vec,
221+
AllocationArena arena = AllocationArena::Permanent) {
222+
return AllocateCopy(MutableArrayRef<T>(vec), arena);
157223
}
158224

159225

include/swift/AST/Types.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ namespace llvm {
3232
struct fltSemantics;
3333
}
3434
namespace swift {
35+
enum class AllocationArena;
3536
class ArchetypeType;
3637
class ASTContext;
3738
class ClassDecl;
@@ -249,8 +250,8 @@ class TypeBase {
249250
public:
250251
// Only allow allocation of Types using the allocator in ASTContext
251252
// or by doing a placement new.
252-
void *operator new(size_t Bytes, ASTContext &C,
253-
unsigned Alignment = 8);
253+
void *operator new(size_t bytes, ASTContext &ctx, AllocationArena arena,
254+
unsigned alignment = 8);
254255
};
255256

256257
/// ErrorType - This represents a type that was erroneously constructed. This
@@ -715,10 +716,12 @@ class BoundGenericType : public TypeBase, public llvm::FoldingSetNode {
715716
void print(raw_ostream &O) const;
716717

717718
void Profile(llvm::FoldingSetNodeID &ID) {
718-
Profile(ID, TheDecl, Parent, GenericArgs);
719+
bool hasTypeVariable = false;
720+
Profile(ID, TheDecl, Parent, GenericArgs, hasTypeVariable);
719721
}
720722
static void Profile(llvm::FoldingSetNodeID &ID, NominalTypeDecl *TheDecl,
721-
Type Parent, ArrayRef<Type> GenericArgs);
723+
Type Parent, ArrayRef<Type> GenericArgs,
724+
bool &hasTypeVariable);
722725

723726
// Implement isa/cast/dyncast/etc.
724727
static bool classof(const TypeBase *T) {

0 commit comments

Comments
 (0)