Skip to content

Commit d7b5dfc

Browse files
committed
RequirementMachine: Don't keep protocol requirement machines around
1 parent 75ade66 commit d7b5dfc

File tree

4 files changed

+33
-46
lines changed

4 files changed

+33
-46
lines changed

lib/AST/RequirementMachine/RequirementMachine.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class InferredGenericSignatureRequestRQM;
3636
class LayoutConstraint;
3737
class ProtocolDecl;
3838
class Requirement;
39+
class RequirementSignatureRequestRQM;
3940
class Type;
4041
class UnifiedStatsReporter;
4142

@@ -47,6 +48,7 @@ class RewriteContext;
4748
class RequirementMachine final {
4849
friend class swift::ASTContext;
4950
friend class swift::rewriting::RewriteContext;
51+
friend class swift::RequirementSignatureRequestRQM;
5052
friend class swift::AbstractGenericSignatureRequestRQM;
5153
friend class swift::InferredGenericSignatureRequestRQM;
5254

lib/AST/RequirementMachine/RequirementMachineRequests.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,16 +241,23 @@ RequirementSignatureRequestRQM::evaluate(Evaluator &evaluator,
241241

242242
// We build requirement signatures for all protocols in a strongly connected
243243
// component at the same time.
244-
auto *machine = ctx.getRewriteContext().getRequirementMachine(proto);
245-
auto requirements = machine->computeMinimalProtocolRequirements();
244+
auto component = ctx.getRewriteContext().getProtocolComponent(proto);
245+
246+
// Heap-allocate the requirement machine to save stack space.
247+
std::unique_ptr<RequirementMachine> machine(new RequirementMachine(
248+
ctx.getRewriteContext()));
249+
250+
machine->initWithProtocols(component);
251+
252+
auto minimalRequirements = machine->computeMinimalProtocolRequirements();
246253

247254
bool debug = machine->getDebugOptions().contains(DebugFlags::Minimization);
248255

249256
// The requirement signature for the actual protocol that the result
250257
// was kicked off with.
251258
ArrayRef<Requirement> result;
252259

253-
for (const auto &pair : requirements) {
260+
for (const auto &pair : minimalRequirements) {
254261
auto *otherProto = pair.first;
255262
const auto &reqs = pair.second;
256263

lib/AST/RequirementMachine/RewriteContext.cpp

Lines changed: 17 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,7 @@ bool RewriteContext::isRecursivelyConstructingRequirementMachine(
553553

554554
/// Implement Tarjan's algorithm to compute strongly-connected components in
555555
/// the protocol dependency graph.
556-
void RewriteContext::getRequirementMachineRec(
556+
void RewriteContext::getProtocolComponentRec(
557557
const ProtocolDecl *proto,
558558
SmallVectorImpl<const ProtocolDecl *> &stack) {
559559
assert(Protos.count(proto) == 0);
@@ -575,7 +575,7 @@ void RewriteContext::getRequirementMachineRec(
575575
auto found = Protos.find(depProto);
576576
if (found == Protos.end()) {
577577
// Successor has not yet been visited. Recurse.
578-
getRequirementMachineRec(depProto, stack);
578+
getProtocolComponentRec(depProto, stack);
579579

580580
auto &entry = Protos[proto];
581581
assert(Protos.count(depProto) != 0);
@@ -620,18 +620,18 @@ void RewriteContext::getRequirementMachineRec(
620620
llvm::dbgs() << "]\n";
621621
}
622622

623-
Components[id] = {Context.AllocateCopy(protos), nullptr};
623+
Components[id].Protos = Context.AllocateCopy(protos);
624624
}
625625
}
626626

627627
/// Lazily construct a requirement machine for the given protocol's strongly
628628
/// connected component (SCC) in the protocol dependency graph.
629-
RequirementMachine *RewriteContext::getRequirementMachine(
629+
ArrayRef<const ProtocolDecl *> RewriteContext::getProtocolComponent(
630630
const ProtocolDecl *proto) {
631631
auto found = Protos.find(proto);
632632
if (found == Protos.end()) {
633633
SmallVector<const ProtocolDecl *, 3> stack;
634-
getRequirementMachineRec(proto, stack);
634+
getProtocolComponentRec(proto, stack);
635635
assert(stack.empty());
636636

637637
found = Protos.find(proto);
@@ -641,36 +641,23 @@ RequirementMachine *RewriteContext::getRequirementMachine(
641641
assert(Components.count(found->second.ComponentID) != 0);
642642
auto &component = Components[found->second.ComponentID];
643643

644-
auto *&machine = component.Machine;
645-
646-
if (machine) {
647-
// If this component has a machine already, make sure it is ready
648-
// for use.
649-
if (!machine->isComplete()) {
650-
llvm::errs() << "Re-entrant construction of requirement "
651-
<< "machine for:";
652-
for (auto *proto : component.Protos)
653-
llvm::errs() << " " << proto->getName();
654-
llvm::errs() << "\n";
655-
abort();
656-
}
657-
658-
return machine;
644+
if (component.InProgress) {
645+
llvm::errs() << "Re-entrant construction of requirement "
646+
<< "machine for:";
647+
for (auto *proto : component.Protos)
648+
llvm::errs() << " " << proto->getName();
649+
llvm::errs() << "\n";
650+
abort();
659651
}
660652

661-
// Construct a requirement machine from the structural requirements of
662-
// the given set of protocols.
663-
auto *newMachine = new RequirementMachine(*this);
664-
machine = newMachine;
665-
666-
// This might re-entrantly invalidate 'machine', which is a reference
667-
// into Protos.
668-
newMachine->initWithProtocols(component.Protos);
669-
return newMachine;
653+
return component.Protos;
670654
}
671655

672656
bool RewriteContext::isRecursivelyConstructingRequirementMachine(
673657
const ProtocolDecl *proto) {
658+
if (proto->isRequirementSignatureComputed())
659+
return false;
660+
674661
auto found = Protos.find(proto);
675662
if (found == Protos.end())
676663
return false;
@@ -679,11 +666,7 @@ bool RewriteContext::isRecursivelyConstructingRequirementMachine(
679666
if (component == Components.end())
680667
return false;
681668

682-
if (!component->second.Machine ||
683-
component->second.Machine->isComplete())
684-
return false;
685-
686-
return true;
669+
return component->second.InProgress;
687670
}
688671

689672
/// We print stats in the destructor, which should get executed at the end of
@@ -694,11 +677,6 @@ RewriteContext::~RewriteContext() {
694677

695678
Machines.clear();
696679

697-
for (const auto &pair : Components)
698-
delete pair.second.Machine;
699-
700-
Components.clear();
701-
702680
if (Context.LangOpts.AnalyzeRequirementMachine) {
703681
llvm::dbgs() << "--- Requirement Machine Statistics ---\n";
704682
llvm::dbgs() << "\n* Symbol kind:\n";

lib/AST/RequirementMachine/RewriteContext.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ class RewriteContext final {
9494
ArrayRef<const ProtocolDecl *> Protos;
9595

9696
/// Each connected component has a lazily-created requirement machine.
97-
RequirementMachine *Machine = nullptr;
97+
bool InProgress = false;
9898
};
9999

100100
/// The protocol dependency graph.
@@ -116,8 +116,8 @@ class RewriteContext final {
116116
RewriteContext &operator=(const RewriteContext &) = delete;
117117
RewriteContext &operator=(RewriteContext &&) = delete;
118118

119-
void getRequirementMachineRec(const ProtocolDecl *proto,
120-
SmallVectorImpl<const ProtocolDecl *> &stack);
119+
void getProtocolComponentRec(const ProtocolDecl *proto,
120+
SmallVectorImpl<const ProtocolDecl *> &stack);
121121

122122
public:
123123
/// Statistics.
@@ -179,7 +179,7 @@ class RewriteContext final {
179179
RequirementMachine *getRequirementMachine(CanGenericSignature sig);
180180
bool isRecursivelyConstructingRequirementMachine(CanGenericSignature sig);
181181

182-
RequirementMachine *getRequirementMachine(const ProtocolDecl *proto);
182+
ArrayRef<const ProtocolDecl *> getProtocolComponent(const ProtocolDecl *proto);
183183
bool isRecursivelyConstructingRequirementMachine(const ProtocolDecl *proto);
184184

185185
~RewriteContext();

0 commit comments

Comments
 (0)