Skip to content

Commit 4b01a97

Browse files
committed
[CodeCompleiton] Avoid walking the whole module to find the delayed func
Previously delayed parsing was performed by AST walker 'ParseDelayedFunctionBodies' by finding "delayed" function decl from the AST of the whole module. This is not necessary. Optimize it by remembering the "delayed" function decl in 'PersistentParserState'. NOTE: 'SourceLoader' stopped using this delayed parsing mechanism in d8b745d rdar://problem/56819166
1 parent 2207151 commit 4b01a97

File tree

7 files changed

+51
-92
lines changed

7 files changed

+51
-92
lines changed

include/swift/Parse/Parser.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,14 +167,14 @@ class Parser {
167167
LocalContext *CurLocalContext = nullptr;
168168

169169
bool isDelayedParsingEnabled() const {
170-
return DelayBodyParsing || SourceMgr.getCodeCompletionLoc().isValid();
170+
return DelayBodyParsing || isCodeCompletionFirstPass();
171171
}
172172

173173
void setCodeCompletionCallbacks(CodeCompletionCallbacks *Callbacks) {
174174
CodeCompletion = Callbacks;
175175
}
176176

177-
bool isCodeCompletionFirstPass() {
177+
bool isCodeCompletionFirstPass() const {
178178
return L->isCodeCompletion() && !CodeCompletion;
179179
}
180180

@@ -1057,6 +1057,7 @@ class Parser {
10571057
bool HasFuncKeyword = true);
10581058
void parseAbstractFunctionBody(AbstractFunctionDecl *AFD);
10591059
BraceStmt *parseAbstractFunctionBodyDelayed(AbstractFunctionDecl *AFD);
1060+
void parseAbstractFunctionBodyDelayed();
10601061
ParserResult<ProtocolDecl> parseDeclProtocol(ParseDeclOptions Flags,
10611062
DeclAttributes &Attributes);
10621063

include/swift/Parse/PersistentParserState.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class PersistentParserState {
5656
enum class DelayedDeclKind {
5757
TopLevelCodeDecl,
5858
Decl,
59+
FunctionBody,
5960
};
6061

6162
class DelayedDeclState {

include/swift/Subsystems.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,9 @@ namespace swift {
132132
PersistentParserState *PersistentState = nullptr,
133133
bool DelayBodyParsing = true);
134134

135-
/// Finish the parsing by going over the nodes that were delayed
136-
/// during the first parsing pass.
137-
void performDelayedParsing(DeclContext *DC,
138-
PersistentParserState &PersistentState,
139-
CodeCompletionCallbacksFactory *Factory);
135+
/// Finish the code completion.
136+
void performCodeCompletionSecondPass(PersistentParserState &PersistentState,
137+
CodeCompletionCallbacksFactory &Factory);
140138

141139
/// Lex and return a vector of tokens for the given buffer.
142140
std::vector<Token> tokenize(const LangOptions &LangOpts,

lib/Frontend/Frontend.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -869,8 +869,8 @@ void CompilerInstance::parseAndCheckTypesUpTo(
869869
});
870870

871871
if (Invocation.isCodeCompletion()) {
872-
performDelayedParsing(MainModule, *PersistentState.get(),
873-
Invocation.getCodeCompletionFactory());
872+
performCodeCompletionSecondPass(*PersistentState.get(),
873+
*Invocation.getCodeCompletionFactory());
874874
}
875875
finishTypeChecking(TypeCheckOptions);
876876
}

lib/IDE/REPLCodeCompletion.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ doCodeCompletion(SourceFile &SF, StringRef EnteredCode, unsigned *BufferID,
215215
performTypeChecking(SF, PersistentState.getTopLevelContext(), None,
216216
OriginalDeclCount);
217217

218-
performDelayedParsing(&SF, PersistentState, CompletionCallbacksFactory);
218+
performCodeCompletionSecondPass(PersistentState, *CompletionCallbacksFactory);
219219

220220
// Now we are done with code completion. Remove the declarations we
221221
// temporarily inserted.

lib/Parse/ParseDecl.cpp

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5340,11 +5340,16 @@ void Parser::consumeAbstractFunctionBody(AbstractFunctionDecl *AFD,
53405340

53415341
BodyRange.End = PreviousLoc;
53425342

5343-
if (SourceMgr.getCodeCompletionLoc().isInvalid() ||
5344-
SourceMgr.rangeContainsCodeCompletionLoc(BodyRange)) {
5345-
AFD->setBodyDelayed(BodyRange);
5346-
} else {
5347-
AFD->setBodySkipped(BodyRange);
5343+
AFD->setBodyDelayed(BodyRange);
5344+
5345+
if (isCodeCompletionFirstPass()) {
5346+
if (SourceMgr.rangeContainsCodeCompletionLoc(BodyRange)) {
5347+
State->delayDecl(PersistentParserState::DelayedDeclKind::FunctionBody,
5348+
PD_Default, AFD, BodyRange,
5349+
BeginParserPosition.PreviousLoc);
5350+
} else {
5351+
AFD->setBodySkipped(BodyRange);
5352+
}
53485353
}
53495354
}
53505355

@@ -5656,6 +5661,20 @@ BraceStmt *Parser::parseAbstractFunctionBodyDelayed(AbstractFunctionDecl *AFD) {
56565661
return parseBraceItemList(diag::func_decl_without_brace).getPtrOrNull();
56575662
}
56585663

5664+
/// Parse a delayed function body from the 'PersistentParserState'.
5665+
void Parser::parseAbstractFunctionBodyDelayed() {
5666+
auto DelayedState = State->takeDelayedDeclState();
5667+
assert(DelayedState.get() && "should have delayed state");
5668+
auto CD = DelayedState->ParentContext->getAsDecl();
5669+
auto AFD = cast<AbstractFunctionDecl>(CD);
5670+
5671+
// Eagarly parse local decls or nested function bodies inside the body.
5672+
llvm::SaveAndRestore<bool> DisableDelayedBody(DelayBodyParsing, false);
5673+
5674+
auto body = parseAbstractFunctionBodyDelayed(AFD);
5675+
AFD->setBodyParsed(body);
5676+
}
5677+
56595678
/// Parse a 'enum' declaration, returning true (and doing no token
56605679
/// skipping) on error.
56615680
///

lib/Parse/Parser.cpp

Lines changed: 17 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -110,75 +110,24 @@ using namespace swift::syntax;
110110

111111
void SILParserTUStateBase::anchor() { }
112112

113-
namespace {
114-
/// A visitor that does delayed parsing of function bodies.
115-
class ParseDelayedFunctionBodies : public ASTWalker {
116-
PersistentParserState &ParserState;
117-
CodeCompletionCallbacksFactory *CodeCompletionFactory;
118-
119-
public:
120-
ParseDelayedFunctionBodies(PersistentParserState &ParserState,
121-
CodeCompletionCallbacksFactory *Factory)
122-
: ParserState(ParserState), CodeCompletionFactory(Factory) {}
123-
124-
bool walkToDeclPre(Decl *D) override {
125-
if (auto AFD = dyn_cast<AbstractFunctionDecl>(D)) {
126-
if (AFD->getBodyKind() != FuncDecl::BodyKind::Unparsed)
127-
return false;
128-
parseFunctionBody(AFD);
129-
return true;
130-
}
131-
return true;
132-
}
133-
134-
private:
135-
void parseFunctionBody(AbstractFunctionDecl *AFD) {
136-
// FIXME: This duplicates the evaluation of
137-
// ParseAbstractFunctionBodyRequest, but installs a code completion
138-
// factory.
139-
assert(AFD->getBodyKind() == FuncDecl::BodyKind::Unparsed);
140-
141-
SourceFile &SF = *AFD->getDeclContext()->getParentSourceFile();
142-
SourceManager &SourceMgr = SF.getASTContext().SourceMgr;
143-
unsigned BufferID = SourceMgr.findBufferContainingLoc(AFD->getLoc());
144-
Parser TheParser(BufferID, SF, nullptr, &ParserState, nullptr,
145-
/*DelayBodyParsing=*/false);
146-
TheParser.SyntaxContext->disable();
147-
std::unique_ptr<CodeCompletionCallbacks> CodeCompletion;
148-
if (CodeCompletionFactory) {
149-
CodeCompletion.reset(
150-
CodeCompletionFactory->createCodeCompletionCallbacks(TheParser));
151-
TheParser.setCodeCompletionCallbacks(CodeCompletion.get());
152-
}
153-
auto body = TheParser.parseAbstractFunctionBodyDelayed(AFD);
154-
AFD->setBodyParsed(body);
155-
156-
if (CodeCompletion)
157-
CodeCompletion->doneParsing();
158-
}
159-
};
160-
161-
static void parseDelayedDecl(
162-
PersistentParserState &ParserState,
163-
CodeCompletionCallbacksFactory *CodeCompletionFactory) {
113+
void swift::performCodeCompletionSecondPass(
114+
PersistentParserState &ParserState,
115+
CodeCompletionCallbacksFactory &Factory) {
116+
SharedTimer timer("CodeCompletionSecondPass");
164117
if (!ParserState.hasDelayedDecl())
165118
return;
166119

167-
SourceFile &SF = *ParserState.getDelayedDeclContext()->getParentSourceFile();
168-
SourceManager &SourceMgr = SF.getASTContext().SourceMgr;
169-
unsigned BufferID =
170-
SourceMgr.findBufferContainingLoc(ParserState.getDelayedDeclLoc());
120+
auto &SF = *ParserState.getDelayedDeclContext()->getParentSourceFile();
121+
auto &SM = SF.getASTContext().SourceMgr;
122+
auto BufferID = SM.findBufferContainingLoc(ParserState.getDelayedDeclLoc());
171123
Parser TheParser(BufferID, SF, nullptr, &ParserState, nullptr);
172124

173125
// Disable libSyntax creation in the delayed parsing.
174126
TheParser.SyntaxContext->disable();
175127

176-
std::unique_ptr<CodeCompletionCallbacks> CodeCompletion;
177-
if (CodeCompletionFactory) {
178-
CodeCompletion.reset(
179-
CodeCompletionFactory->createCodeCompletionCallbacks(TheParser));
180-
TheParser.setCodeCompletionCallbacks(CodeCompletion.get());
181-
}
128+
std::unique_ptr<CodeCompletionCallbacks> CodeCompletion(
129+
Factory.createCodeCompletionCallbacks(TheParser));
130+
TheParser.setCodeCompletionCallbacks(CodeCompletion.get());
182131

183132
switch (ParserState.getDelayedDeclKind()) {
184133
case PersistentParserState::DelayedDeclKind::TopLevelCodeDecl:
@@ -188,13 +137,16 @@ static void parseDelayedDecl(
188137
case PersistentParserState::DelayedDeclKind::Decl:
189138
TheParser.parseDeclDelayed();
190139
break;
140+
141+
case PersistentParserState::DelayedDeclKind::FunctionBody: {
142+
TheParser.parseAbstractFunctionBodyDelayed();
143+
break;
191144
}
145+
}
146+
assert(!ParserState.hasDelayedDecl());
192147

193-
if (CodeCompletion)
194-
CodeCompletion->doneParsing();
148+
CodeCompletion->doneParsing();
195149
}
196-
} // unnamed namespace
197-
198150

199151
swift::Parser::BacktrackingScope::~BacktrackingScope() {
200152
if (Backtrack) {
@@ -203,18 +155,6 @@ swift::Parser::BacktrackingScope::~BacktrackingScope() {
203155
}
204156
}
205157

206-
void swift::performDelayedParsing(
207-
DeclContext *DC, PersistentParserState &PersistentState,
208-
CodeCompletionCallbacksFactory *CodeCompletionFactory) {
209-
SharedTimer timer("Parsing");
210-
ParseDelayedFunctionBodies Walker(PersistentState,
211-
CodeCompletionFactory);
212-
DC->walkContext(Walker);
213-
214-
if (CodeCompletionFactory)
215-
parseDelayedDecl(PersistentState, CodeCompletionFactory);
216-
}
217-
218158
/// Tokenizes a string literal, taking into account string interpolation.
219159
static void getStringPartTokens(const Token &Tok, const LangOptions &LangOpts,
220160
const SourceManager &SM,

0 commit comments

Comments
 (0)