Skip to content

Commit bec979c

Browse files
committed
Unified: Add caching to name binding
1 parent e387ca4 commit bec979c

2 files changed

Lines changed: 54 additions & 10 deletions

File tree

‎unified/ql/lib/codeql/unified/internal/LocalNameBinding.qll‎

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ private import codeql.unified.internal.NameBindingPlugin
99
private import codeql.unified.internal.StaticNameBinding
1010

1111
private module LocalNameBindingInput implements LocalNameBindingInputSig<Location> {
12+
predicate cacheRevRef() {
13+
(bindingContext(_, _, _) implies any())
14+
or
15+
(implicitDeclInScope(_, _, _) implies any())
16+
}
17+
1218
class AstNode = U::AstNode;
1319

1420
private class LogicalAndRoot extends LogicalAndExpr {
@@ -201,7 +207,9 @@ private module LocalNameBindingInput implements LocalNameBindingInputSig<Locatio
201207
any(NameBindingPlugin p).isNonPattern(e)
202208
}
203209

210+
cached
204211
additional predicate bindingContext(AstNode pattern, AstNode scope, AstNode declaration) {
212+
LocalNameBindingOutput::CachedStage::ref() and
205213
not isNonPattern(pattern) and
206214
(
207215
exists(SiblingShadowingDecl decl |
@@ -326,8 +334,9 @@ private module LocalNameBindingInput implements LocalNameBindingInputSig<Locatio
326334
)
327335
}
328336

329-
pragma[nomagic]
337+
cached
330338
additional predicate implicitDeclInScope(string name, AstNode scope, boolean isLocalVariable) {
339+
LocalNameBindingOutput::CachedStage::ref() and
331340
exists(Callable callable |
332341
isLocalVariable = true and
333342
name = any(NameBindingPlugin p).getImplicitReceiverParameterName(callable) and
@@ -356,7 +365,7 @@ private module LocalNameBindingInput implements LocalNameBindingInputSig<Locatio
356365
}
357366
}
358367

359-
import LocalNameBindingInput
368+
predicate bindingContext = LocalNameBindingInput::bindingContext/3;
360369

361370
module LocalNameBindingOutput = LocalNameBinding<Location, LocalNameBindingInput>;
362371

@@ -383,10 +392,10 @@ module Public {
383392

384393
/** An identifier appearing in a name-binding position, such as the `x` in `let x = 123`. */
385394
class NameBinding extends Identifier {
386-
NameBinding() { LocalNameBindingInput::bindingContext(this, _, _) }
395+
NameBinding() { bindingContext(this, _, _) }
387396

388397
/** Gets the statement-like node declaring this name, such as a `VariableDeclaration` or `CatchClause`. */
389-
AstNode getDeclaration() { LocalNameBindingInput::bindingContext(this, _, result) }
398+
AstNode getDeclaration() { bindingContext(this, _, result) }
390399

391400
/** Gets the name being declared. */
392401
string getName() { result = this.getValue() }

‎unified/ql/lib/codeql/unified/internal/StaticNameBinding.qll‎

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ private import unified
66
private import codeql.unified.internal.LocalNameBinding
77
private import codeql.unified.internal.NameBindingPlugin
88

9+
cached
910
private newtype TNameBindingNode =
10-
TIdentifier(Identifier n) or
11+
TIdentifier(Identifier n) { CachedStage::ref() } or
1112
TBulkImport(BulkImportingPattern p) or
1213
TLocalName(LocalName local) or
1314
TStaticMemberNamespace(ClassLikeDeclaration cls) or
@@ -357,10 +358,15 @@ private predicate isInheritableMemberNode(NameBindingNode node) {
357358

358359
/** A name-binding node that can have members. */
359360
class NamespaceNode extends NameBindingNode {
361+
cached
360362
NamespaceNode() {
361-
storeStep(_, _, this) or
362-
inheritanceStep(_, this) or
363-
this.isInstanceMemberNamespace(_) or
363+
CachedStage::ref() and
364+
storeStep(_, _, this)
365+
or
366+
inheritanceStep(_, this)
367+
or
368+
this.isInstanceMemberNamespace(_)
369+
or
364370
this.isStaticMemberNamespace(_)
365371
}
366372

@@ -410,8 +416,9 @@ class NamespaceNode extends NameBindingNode {
410416
NamespaceNode getAnInheritanceChild() { result.getAnInheritanceParent() = this }
411417

412418
/** Gets a member of this namespace of the given name. */
413-
pragma[nomagic]
419+
cached
414420
NameBindingNode getMember(string name) {
421+
CachedStage::ref() and
415422
result = this.getOwnMember(name)
416423
or
417424
not this.hasOwnMember(name) and
@@ -468,7 +475,7 @@ private module TrackNameBindingInput implements TrackInputSig {
468475
private module TrackNameBinding = Track<TrackNameBindingInput>;
469476

470477
/** Gets a name-binding node that may refer to the given declaration. */
471-
NameBindingNode trackNameBinding(NameBinding decl) {
478+
private NameBindingNode trackNameBinding(NameBinding decl) {
472479
exists(NameBindingNode start |
473480
start.isIdentifier(decl) and
474481
result = TrackNameBinding::track(start)
@@ -677,10 +684,12 @@ private int unqualifiedMemberAccessDepth(PotentialLocalNameAccess access) {
677684
* `accessingClass` is the enclosing class in which the member was found, and
678685
* `instanceAccess` indicates if it is an instance member or static member.
679686
*/
687+
cached
680688
predicate unqualifiedMemberAccess(
681689
PotentialLocalNameAccess access, boolean instanceAccess, NameBinding target,
682690
ClassLikeDeclaration accessingClass
683691
) {
692+
CachedStage::ref() and
684693
unqualifiedMemberAccessCand(access, instanceAccess, target, accessingClass) and
685694
accessingClass.getDepth() = unqualifiedMemberAccessDepth(access)
686695
}
@@ -708,6 +717,7 @@ module Public {
708717
predicate isInstanceAccess() { instanceAccess = true }
709718

710719
/** Gets the local variable implicitly referenced as the base of this access. */
720+
cached
711721
LocalVariable getImplicitQualifierVariable() {
712722
ResolveImplicitReceiverAccess::access(this, result)
713723
}
@@ -718,7 +728,9 @@ module Public {
718728
}
719729

720730
/** Gets the declaration being accessed by identifier `i`, as determined by static name binding. */
731+
cached
721732
NameBinding getStaticBindingTargetFromIdentifier(Identifier i) {
733+
CachedStage::ref() and
722734
// For unqualified accesses, use the shadowing-aware lookup
723735
result = i.(UnqualifiedMemberAccess).getTarget()
724736
or
@@ -758,3 +770,26 @@ private predicate implicitReceiverAccess(AstNode access, string name) {
758770

759771
private module ResolveImplicitReceiverAccess =
760772
LocalNameBindingOutput::ResolveAccesses<implicitReceiverAccess/2>;
773+
774+
cached
775+
private module CachedStage {
776+
/** Reference to the cached stage of this module. */
777+
cached
778+
predicate ref() { any() }
779+
780+
/** Reverse references to the predicates that reference `ref()`. */
781+
cached
782+
predicate revRef() {
783+
any()
784+
or
785+
(exists(NameBindingNode n) implies any())
786+
or
787+
(exists(any(NamespaceNode n).getMember(_)) implies any())
788+
or
789+
(unqualifiedMemberAccess(_, _, _, _) implies any())
790+
or
791+
(exists(any(UnqualifiedMemberAccess u).getImplicitQualifierVariable()) implies any())
792+
or
793+
(exists(getStaticBindingTargetFromIdentifier(_)) implies any())
794+
}
795+
}

0 commit comments

Comments
 (0)