Skip to content

Commit 4ef30a4

Browse files
committed
Sema: Recycle ConstraintGraphNode
1 parent cab6982 commit 4ef30a4

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

include/swift/Sema/ConstraintGraph.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ class ConstraintGraphNode {
5757
/// Retrieve the type variable this node represents.
5858
TypeVariableType *getTypeVariable() const { return TypeVar; }
5959

60+
void reset();
61+
62+
void initTypeVariable(TypeVariableType *typeVar) {
63+
ASSERT(!TypeVar);
64+
TypeVar = typeVar;
65+
}
66+
6067
/// Retrieve the set of constraints that mention this type variable.
6168
///
6269
/// These are the hyperedges of the graph, connecting this node to
@@ -435,6 +442,9 @@ class ConstraintGraph {
435442
/// Constraints that are "orphaned" because they contain no type variables.
436443
SmallVector<Constraint *, 4> OrphanedConstraints;
437444

445+
/// Unused nodes.
446+
SmallVector<ConstraintGraphNode *> FreeList;
447+
438448
/// Increment the number of constraints considered per attempt
439449
/// to contract constraint graph edges.
440450
void incrementConstraintsPerContractionCounter();

lib/Sema/ConstraintGraph.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ ConstraintGraph::~ConstraintGraph() {
4343
delete impl.getGraphNode();
4444
impl.setGraphNode(nullptr);
4545
}
46+
for (auto *node : FreeList) {
47+
delete node;
48+
}
4649
}
4750

4851
#pragma mark Graph accessors
@@ -55,11 +58,20 @@ ConstraintGraph::lookupNode(TypeVariableType *typeVar) {
5558
assert(impl.getGraphIndex() < TypeVariables.size() && "Out-of-bounds index");
5659
assert(TypeVariables[impl.getGraphIndex()] == typeVar &&
5760
"Type variable mismatch");
61+
ASSERT(nodePtr->TypeVar == typeVar &&
62+
"Use-after-free");
5863
return { *nodePtr, impl.getGraphIndex() };
5964
}
6065

6166
// Allocate the new node.
62-
auto nodePtr = new ConstraintGraphNode(*this, typeVar);
67+
ConstraintGraphNode *nodePtr;
68+
if (FreeList.empty())
69+
nodePtr = new ConstraintGraphNode(*this, typeVar);
70+
else {
71+
nodePtr = FreeList.back();
72+
FreeList.pop_back();
73+
nodePtr->initTypeVariable(typeVar);
74+
}
6375
unsigned index = TypeVariables.size();
6476
impl.setGraphNode(nodePtr);
6577
impl.setGraphIndex(index);
@@ -84,6 +96,17 @@ ConstraintGraph::lookupNode(TypeVariableType *typeVar) {
8496
return { *nodePtr, index };
8597
}
8698

99+
void ConstraintGraphNode::reset() {
100+
ASSERT(TypeVar);
101+
TypeVar = nullptr;
102+
Bindings.reset();
103+
Constraints.clear();
104+
ConstraintIndex.clear();
105+
ReferencedBy.clear();
106+
References.clear();
107+
EquivalenceClass.clear();
108+
}
109+
87110
bool ConstraintGraphNode::forRepresentativeVar() const {
88111
auto *typeVar = getTypeVariable();
89112
return typeVar == typeVar->getImpl().getRepresentative(nullptr);
@@ -422,7 +445,9 @@ void ConstraintGraph::removeNode(TypeVariableType *typeVar) {
422445
// Remove this node.
423446
auto &impl = typeVar->getImpl();
424447
unsigned index = impl.getGraphIndex();
425-
delete impl.getGraphNode();
448+
auto *node = impl.getGraphNode();
449+
node->reset();
450+
FreeList.push_back(node);
426451
impl.setGraphNode(nullptr);
427452

428453
// Remove this type variable from the list.

0 commit comments

Comments
 (0)