Skip to content

Commit b4e6788

Browse files
committed
CallerAnalysis: be more tolerant about missing FunctionInfos.
In theory, the analysis invalidation notifications should assure that every function has a CallerAnalysis::FunctionInfo in `funcInfos`. But it's not unlikely that we are missing some of those notifications. We got some not-reproducible crash reports because of missing function infos in CallerAnalysis. With this change the analysis accepts missing function infos and does the right thing if such an info is missing. In the long term we should replace CallerAnalysis by FunctionUses, anyway. rdar://99653954
1 parent 468b7b9 commit b4e6788

File tree

2 files changed

+31
-21
lines changed

2 files changed

+31
-21
lines changed

include/swift/SILOptimizer/Analysis/CallerAnalysis.h

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,7 @@ class CallerAnalysis final : public SILAnalysis {
9191

9292
/// Notify the analysis about a function which will be deleted from the
9393
/// module.
94-
void notifyWillDeleteFunction(SILFunction *f) override {
95-
invalidateAllInfo(f);
96-
recomputeFunctionList.remove(f);
97-
// Now that we have invalidated all references to the function, delete it.
98-
funcInfos.erase(f);
99-
}
94+
void notifyWillDeleteFunction(SILFunction *f) override;
10095

10196
/// Notify the analysis about changed witness or vtables.
10297
///
@@ -107,6 +102,9 @@ class CallerAnalysis final : public SILAnalysis {
107102

108103
/// Look up the function info that we have stored for f, recomputing all
109104
/// invalidating parts of the call graph.
105+
///
106+
/// Warning: The returned FunctionInfo is only alive until the next call to
107+
/// `getFunctionInfo`.
110108
const FunctionInfo &getFunctionInfo(SILFunction *f) const;
111109

112110
SWIFT_DEBUG_DUMP;
@@ -146,7 +144,7 @@ class CallerAnalysis final : public SILAnalysis {
146144
void invalidateKnownCallees(SILFunction *caller, FunctionInfo &callerInfo);
147145

148146
/// Invalidate both the known callees of f and the known callers of f.
149-
void invalidateAllInfo(SILFunction *f);
147+
void invalidateAllInfo(SILFunction *f, FunctionInfo &fInfo);
150148

151149
/// Helper method that reprocesses all elements of recomputeFunctionList and
152150
/// then clears the function list.

lib/SILOptimizer/Analysis/CallerAnalysis.cpp

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,14 @@ struct CallerAnalysis::ApplySiteFinderVisitor
4848
: SILInstructionVisitor<ApplySiteFinderVisitor, bool> {
4949
CallerAnalysis *analysis;
5050
SILFunction *callerFn;
51-
FunctionInfo &callerInfo;
5251

5352
#ifndef NDEBUG
5453
SmallPtrSet<SILInstruction *, 8> visitedCallSites;
5554
SmallSetVector<SILInstruction *, 8> callSitesThatMustBeVisited;
5655
#endif
5756

5857
ApplySiteFinderVisitor(CallerAnalysis *analysis, SILFunction *callerFn)
59-
: analysis(analysis), callerFn(callerFn),
60-
callerInfo(analysis->unsafeGetFunctionInfo(callerFn)) {}
58+
: analysis(analysis), callerFn(callerFn) {}
6159
~ApplySiteFinderVisitor();
6260

6361
bool visitSILInstruction(SILInstruction *) { return false; }
@@ -120,14 +118,14 @@ bool CallerAnalysis::ApplySiteFinderVisitor::visitFunctionRefBaseInst(
120118
FunctionRefBaseInst *fri) {
121119
auto optResult = findLocalApplySites(fri);
122120
auto *calleeFn = fri->getInitiallyReferencedFunction();
123-
FunctionInfo &calleeInfo = analysis->unsafeGetFunctionInfo(calleeFn);
124121

125122
// First make an edge from our callerInfo to our calleeState for invalidation
126123
// purposes.
127-
callerInfo.calleeStates.insert(calleeFn);
124+
analysis->getOrInsertFunctionInfo(callerFn).calleeStates.insert(calleeFn);
128125

129126
// Then grab our callee state and update it with state for this caller.
130-
auto iter = calleeInfo.callerStates.insert({callerFn, {}});
127+
auto iter = analysis->getOrInsertFunctionInfo(calleeFn).callerStates.
128+
insert({callerFn, {}});
131129
// If we succeeded in inserting a new value, put in an optimistic
132130
// value for escaping.
133131
if (iter.second) {
@@ -222,6 +220,10 @@ const FunctionInfo &CallerAnalysis::getFunctionInfo(SILFunction *f) const {
222220
// Recompute every function in the invalidated function list and empty the
223221
// list.
224222
auto &self = const_cast<CallerAnalysis &>(*this);
223+
if (funcInfos.find(f) == funcInfos.end()) {
224+
(void)self.getOrInsertFunctionInfo(f);
225+
self.recomputeFunctionList.insert(f);
226+
}
225227
self.processRecomputeFunctionList();
226228
return self.unsafeGetFunctionInfo(f);
227229
}
@@ -262,11 +264,7 @@ void CallerAnalysis::processFunctionCallSites(SILFunction *callerFn) {
262264
visitor.process();
263265
}
264266

265-
void CallerAnalysis::invalidateAllInfo(SILFunction *f) {
266-
// Look up the callees that our caller refers to and invalidate any
267-
// values that point back at the caller.
268-
FunctionInfo &fInfo = unsafeGetFunctionInfo(f);
269-
267+
void CallerAnalysis::invalidateAllInfo(SILFunction *f, FunctionInfo &fInfo) {
270268
// Then we first eliminate any callees that we point at.
271269
invalidateKnownCallees(f, fInfo);
272270

@@ -303,9 +301,12 @@ void CallerAnalysis::invalidateKnownCallees(SILFunction *caller,
303301
}
304302

305303
void CallerAnalysis::invalidateKnownCallees(SILFunction *caller) {
306-
// Look up the callees that our caller refers to and invalidate any
307-
// values that point back at the caller.
308-
invalidateKnownCallees(caller, unsafeGetFunctionInfo(caller));
304+
auto iter = funcInfos.find(caller);
305+
if (iter != funcInfos.end()) {
306+
// Look up the callees that our caller refers to and invalidate any
307+
// values that point back at the caller.
308+
invalidateKnownCallees(caller, iter->second);
309+
}
309310
}
310311

311312
void CallerAnalysis::verify(SILFunction *caller) const {
@@ -377,6 +378,17 @@ void CallerAnalysis::invalidate() {
377378
}
378379
}
379380

381+
void CallerAnalysis::notifyWillDeleteFunction(SILFunction *f) {
382+
auto iter = funcInfos.find(f);
383+
if (iter == funcInfos.end())
384+
return;
385+
386+
invalidateAllInfo(f, iter->second);
387+
recomputeFunctionList.remove(f);
388+
// Now that we have invalidated all references to the function, delete it.
389+
funcInfos.erase(iter);
390+
}
391+
380392
//===----------------------------------------------------------------------===//
381393
// CallerAnalysis YAML Dumper
382394
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)