You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[MERGE #5133@boingoing] Use the generated parser state cache to skip scanning nested deferred functions again when defer-parsing
Merge pull request #5133 from boingoing:UseDeferredStubs2
Use the generated parser state cache to skip scanning nested deferred functions again when defer-parsing
When we do the initial parse of a function, we need to scan the entire function and all the functions nested inside it. We don't actually construct the AST for the function or any of it's nested functions but we must scan them all to check for early syntax errors. Later (when we execute this function) we will go back and construct the AST for the function which was previously deferred by scanning the source code once more - this is referred to as defer-parsing the function. While defer-parsing a function we currently scan all of the functions nested inside again. We don't construct an AST for these nested functions but we do scan and verify their syntax (again). This additional scan is unnecessary and can be costly, especially if there are a lot of sibling functions or deep nesting of functions. Now that we have the parser state cache, we can use it to avoid rescanning these nested functions during defer-parse.
The parser state cache is a loose term but it consists of a couple of concepts.
First, the literal cache which contains bytecode of non-deferred functions, header information for deferred functions, and deferred stubs for nested deferred functions. When we deserialize this cache, we use it to build script functions for non-deferred functions - these can be run immediately. We also hydrate the deferred functions into ParseableFunctionInfo objects which will be on-demand defer-parsed into regular script functions. The deferred functions keep the set of their nested deferred stubs and use them to skip reparsing the nested functions during defer-parse.
The second aspect of the parser state cache is these deferred stubs themselves and what they contain. The stubs are arranged into a tree structure where each stub contains information about one nested deferred function which can be used to construct a ParseNodeFnc without scanning the function script in the source code. Each stub knows the extents of the function in the source, parser flags, the set of names captured by the function, and the set of nested functions nested inside the function.
When we are defer-parsing a function and we start to parse a nested function we know that there was not a syntax error in that nested deferred function because if there was then we wouldn't have come back to try and defer-parse the function. Thus we can avoid actually scanning the nested function entirely with the deferred stub because we know the function extents. We move the parser ahead to the character position at the end of the function and we push references to any names captured within the function. Now the parser is in the same state as if we had parsed the nested function but we were able to skip it entirely.
0 commit comments