2020
2121namespace swift {
2222class SourceFile ;
23+ class SyntaxParsingCache ;
2324class Token ;
2425class DiagnosticEngine ;
2526
@@ -74,9 +75,17 @@ class alignas(1 << SyntaxAlignInBits) SyntaxParsingContext {
7475 // Storage for Collected parts.
7576 std::vector<RC<RawSyntax>> Storage;
7677
78+ SyntaxArena &Arena;
79+
80+ // / A cache of nodes that can be reused when creating the current syntax
81+ // / tree
82+ SyntaxParsingCache *SyntaxCache = nullptr ;
83+
7784 RootContextData (SourceFile &SF, DiagnosticEngine &Diags,
78- SourceManager &SourceMgr, unsigned BufferID)
79- : SF (SF), Diags (Diags), SourceMgr (SourceMgr), BufferID (BufferID) {}
85+ SourceManager &SourceMgr, unsigned BufferID,
86+ SyntaxArena &Arena, SyntaxParsingCache *SyntaxCache)
87+ : SF (SF), Diags (Diags), SourceMgr (SourceMgr), BufferID (BufferID),
88+ Arena (Arena), SyntaxCache (SyntaxCache) {}
8089 };
8190
8291private:
@@ -97,6 +106,9 @@ class alignas(1 << SyntaxAlignInBits) SyntaxParsingContext {
97106 // Discard all parts in the context.
98107 Discard,
99108
109+ // The node has been loaded from the cache and all parts shall be discarded.
110+ LoadedFromCache,
111+
100112 // Construct SourceFile syntax to the specified SF.
101113 Root,
102114
@@ -112,9 +124,7 @@ class alignas(1 << SyntaxAlignInBits) SyntaxParsingContext {
112124 // Reference to the
113125 SyntaxParsingContext *&CtxtHolder;
114126
115- SyntaxArena &Arena;
116-
117- std::vector<RC<RawSyntax>> &Storage;
127+ RootContextData *RootData;
118128
119129 // Offet for 'Storage' this context owns from.
120130 const size_t Offset;
@@ -138,7 +148,7 @@ class alignas(1 << SyntaxAlignInBits) SyntaxParsingContext {
138148 void createNodeInPlace (SyntaxKind Kind, size_t N);
139149
140150 ArrayRef<RC<RawSyntax>> getParts () const {
141- return makeArrayRef (Storage ).drop_front (Offset);
151+ return makeArrayRef (getStorage () ).drop_front (Offset);
142152 }
143153
144154 RC<RawSyntax> makeUnknownSyntax (SyntaxKind Kind,
@@ -154,11 +164,12 @@ class alignas(1 << SyntaxAlignInBits) SyntaxParsingContext {
154164 // / Designated constructor for child context.
155165 SyntaxParsingContext (SyntaxParsingContext *&CtxtHolder)
156166 : RootDataOrParent (CtxtHolder), CtxtHolder (CtxtHolder),
157- Arena (CtxtHolder->Arena ),
158- Storage (CtxtHolder->Storage ), Offset (Storage.size ()),
167+ RootData (CtxtHolder->RootData ), Offset (RootData->Storage .size ()),
159168 Enabled (CtxtHolder->isEnabled ()) {
160169 assert (CtxtHolder->isTopOfContextStack () &&
161170 " SyntaxParsingContext cannot have multiple children" );
171+ assert (CtxtHolder->Mode != AccumulationMode::LoadedFromCache &&
172+ " Cannot create child context for a node loaded from the cache" );
162173 CtxtHolder = this ;
163174 }
164175
@@ -174,20 +185,41 @@ class alignas(1 << SyntaxAlignInBits) SyntaxParsingContext {
174185
175186 ~SyntaxParsingContext ();
176187
188+ // / Try loading the current node from the \c SyntaxParsingCache by looking up
189+ // / if an unmodified node exists at \p LexerOffset of the same kind. If a node
190+ // / is found, replace the node that is currently being constructed by the
191+ // / parsing context with the node from the cache and return the number of
192+ // / bytes the loaded node took up in the original source. The lexer should
193+ // / pretend it has read these bytes and continue from the advanced offset.
194+ // / If nothing is found \c 0 is returned.
195+ size_t loadFromCache (size_t LexerOffset);
196+
177197 void disable () { Enabled = false ; }
178198 bool isEnabled () const { return Enabled; }
179199 bool isRoot () const { return RootDataOrParent.is <RootContextData*>(); }
180200 bool isTopOfContextStack () const { return this == CtxtHolder; }
181201
182- SyntaxParsingContext *getParent () {
202+ SyntaxParsingContext *getParent () const {
183203 return RootDataOrParent.get <SyntaxParsingContext*>();
184204 }
185205
186- RootContextData &getRootData () {
187- return *getRoot ()->RootDataOrParent .get <RootContextData*>();
206+ RootContextData *getRootData () { return RootData; }
207+
208+ const RootContextData *getRootData () const { return RootData; }
209+
210+ std::vector<RC<RawSyntax>> &getStorage () { return getRootData ()->Storage ; }
211+
212+ const std::vector<RC<RawSyntax>> &getStorage () const {
213+ return getRootData ()->Storage ;
214+ }
215+
216+ SyntaxParsingCache *getSyntaxParsingCache () const {
217+ return getRootData ()->SyntaxCache ;
188218 }
189219
190- SyntaxParsingContext *getRoot ();
220+ SyntaxArena &getArena () const { return getRootData ()->Arena ; }
221+
222+ const SyntaxParsingContext *getRoot () const ;
191223
192224 // / Add RawSyntax to the parts.
193225 void addRawSyntax (RC<RawSyntax> Raw);
@@ -201,6 +233,7 @@ class alignas(1 << SyntaxAlignInBits) SyntaxParsingContext {
201233
202234 template <typename SyntaxNode>
203235 llvm::Optional<SyntaxNode> popIf () {
236+ auto &Storage = getStorage ();
204237 assert (Storage.size () > Offset);
205238 if (auto Node = make<Syntax>(Storage.back ()).getAs <SyntaxNode>()) {
206239 Storage.pop_back ();
@@ -210,6 +243,7 @@ class alignas(1 << SyntaxAlignInBits) SyntaxParsingContext {
210243 }
211244
212245 TokenSyntax popToken () {
246+ auto &Storage = getStorage ();
213247 assert (Storage.size () > Offset);
214248 assert (Storage.back ()->getKind () == SyntaxKind::Token);
215249 auto Node = make<TokenSyntax>(std::move (Storage.back ()));
@@ -263,6 +297,10 @@ class alignas(1 << SyntaxAlignInBits) SyntaxParsingContext {
263297 // / Make a missing node corresponding to the given node kind, and
264298 // / push this node into the context.
265299 void synthesize (SyntaxKind Kind);
300+
301+ // / Dump the nodes that are in the storage stack of the SyntaxParsingContext
302+ LLVM_ATTRIBUTE_DEPRECATED (void dumpStorage () const LLVM_ATTRIBUTE_USED,
303+ " Only meant for use in the debugger" );
266304};
267305
268306} // namespace swift
0 commit comments