Finding all functions and caller-callee relationships in the latest Closure

40 views
Skip to first unread message

GRAMS TYPE

unread,
May 11, 2022, 3:26:58 PM5/11/22
to Closure Compiler Discuss
Hello,

I am working on a project where I need to construct a call graph, with fully qualified function names as nodes and caller-callee relationships as directed edges. I see that "CallGraph" class and its associates (like NameBasedDefinitionsProvider, DefinitionsUseSiteFinder, etc.) were removed from the codebase one by one over the last few years since 2017.

Does anyone have suggestions for the best way to construct a call graph (as above described) within the current version of closure? Specifically, I need help to obtain:

1. the set of all functions
2. the set of all callsites
3. the subset of target functions that *may* be invoked at a particular call-site

I suppose the data structures such as OptimizeCalls.ReferenceMap and SymbolTable contain some relevant information, but there is much code to sift through, and I'm not sure if these are the right places to look. Once I have the above information, I see https://github.com/google/closure-compiler/wiki/Writing-Compiler-Pass provides a head-start on writing my own compiler pass.

Any pointers to obtaining the caller-callee relationships will be much appreciated.

Thanks!

Lisa Velden

unread,
May 16, 2022, 11:25:21 AM5/16/22
to Closure Compiler Discuss
Yes, you are correct that these data structures were removed and that you'd have to build your own compiler pass for it.

There's a "CallGraphCompilerPass" interface that is implemented by the PureFunctionIdentifier pass. This pass could be helpful for inspiration as it builds a call graph to propagate side effect information.

Bradford Smith

unread,
May 25, 2022, 11:28:46 AM5/25/22
to Closure Compiler Discuss
It's unfortunate that we have 2 code paths that try to connect function calls with function definitions.
You should be aware that they have are different in their focus.

PureFunctionIdentifier is concerned with detecting any possible side-effects from a function call,
so it is motivated to err on the side of caution by assuming if a call might be connected with a definition, it is connected with that definition.
If it decides a connection exists that really doesn't, that won't lead to incorrect code, just less optimization.

OptimizeCalls and the passes built on it intend to actually modify the call sites and definitions.
If they decide that a call is connected with a definition when it really isn't,
then they will generate broken code.

You should decide which approach makes the most sense for your intended use-case.
Reply all
Reply to author
Forward
0 new messages