Merge pull request #19093 from aschackmull/java/caching

Java: Adjust caching of BasicBlocks, BaseSSA, and CompileTimeConstants
This commit is contained in:
Anders Schack-Mulligen
2025-03-31 10:48:12 +02:00
committed by GitHub
4 changed files with 62 additions and 13 deletions

View File

@@ -180,7 +180,7 @@ class CompileTimeConstantExpr extends Expr {
/**
* Gets the string value of this expression, where possible.
*/
pragma[nomagic]
cached
string getStringValue() {
result = this.(StringLiteral).getValue()
or
@@ -205,7 +205,7 @@ class CompileTimeConstantExpr extends Expr {
/**
* Gets the boolean value of this expression, where possible.
*/
pragma[nomagic]
cached
boolean getBooleanValue() {
// Literal value.
result = this.(BooleanLiteral).getBooleanValue()

View File

@@ -5,6 +5,19 @@
import java
import Dominance
cached
private module BasicBlockStage {
cached
predicate ref() { any() }
cached
predicate backref() {
(exists(any(BasicBlock bb).getABBSuccessor()) implies any()) and
(exists(any(BasicBlock bb).getNode(_)) implies any()) and
(exists(any(BasicBlock bb).length()) implies any())
}
}
/**
* A control-flow node that represents the start of a basic block.
*
@@ -12,8 +25,11 @@ import Dominance
* often be treated as a unit in analyses.
*/
class BasicBlock extends ControlFlowNode {
cached
BasicBlock() {
not exists(this.getAPredecessor()) and exists(this.getASuccessor())
BasicBlockStage::ref() and
not exists(this.getAPredecessor()) and
exists(this.getASuccessor())
or
strictcount(this.getAPredecessor()) > 1
or
@@ -24,7 +40,10 @@ class BasicBlock extends ControlFlowNode {
/** Gets an immediate successor of this basic block. */
cached
BasicBlock getABBSuccessor() { result = this.getLastNode().getASuccessor() }
BasicBlock getABBSuccessor() {
BasicBlockStage::ref() and
result = this.getLastNode().getASuccessor()
}
/** Gets an immediate predecessor of this basic block. */
BasicBlock getABBPredecessor() { result.getABBSuccessor() = this }
@@ -35,7 +54,9 @@ class BasicBlock extends ControlFlowNode {
/** Gets the control-flow node at a specific (zero-indexed) position in this basic block. */
cached
ControlFlowNode getNode(int pos) {
result = this and pos = 0
BasicBlockStage::ref() and
result = this and
pos = 0
or
exists(ControlFlowNode mid, int mid_pos | pos = mid_pos + 1 |
this.getNode(mid_pos) = mid and
@@ -52,7 +73,10 @@ class BasicBlock extends ControlFlowNode {
/** Gets the number of control-flow nodes contained in this basic block. */
cached
int length() { result = strictcount(this.getANode()) }
int length() {
BasicBlockStage::ref() and
result = strictcount(this.getANode())
}
/** Holds if this basic block strictly dominates `node`. */
predicate bbStrictlyDominates(BasicBlock node) { bbStrictlyDominates(this, node) }

View File

@@ -14,9 +14,26 @@
import java
private import codeql.ssa.Ssa as SsaImplCommon
cached
private module BaseSsaStage {
cached
predicate ref() { any() }
cached
predicate backref() {
(exists(TLocalVar(_, _)) implies any()) and
(exists(any(BaseSsaSourceVariable v).getAnAccess()) implies any()) and
(exists(getAUse(_)) implies any())
}
}
cached
private newtype TBaseSsaSourceVariable =
TLocalVar(Callable c, LocalScopeVariable v) {
c = v.getCallable() or c = v.getAnAccess().getEnclosingCallable()
BaseSsaStage::ref() and
c = v.getCallable()
or
c = v.getAnAccess().getEnclosingCallable()
}
/**
@@ -31,6 +48,7 @@ class BaseSsaSourceVariable extends TBaseSsaSourceVariable {
*/
cached
VarAccess getAnAccess() {
BaseSsaStage::ref() and
exists(LocalScopeVariable v, Callable c |
this = TLocalVar(c, v) and result = v.getAnAccess() and result.getEnclosingCallable() = c
)
@@ -188,6 +206,7 @@ cached
private module Cached {
cached
VarRead getAUse(Impl::Definition def) {
BaseSsaStage::ref() and
exists(BaseSsaSourceVariable v, BasicBlock bb, int i |
Impl::ssaDefReachesRead(v, def, bb, i) and
result.getControlFlowNode() = bb.getNode(i) and

View File

@@ -269,18 +269,24 @@ private MethodCall getSystemPropertyFromSpringProperties(string propertyName) {
* for final variables.
*/
private predicate localExprFlowPlusInitializers(Expr e1, Expr e2) {
e1 = e2 or
localFlowPlusInitializers(DataFlow::exprNode(e1), DataFlow::exprNode(e2))
}
private predicate localFlowPlusInitializers(DataFlow::Node pred, DataFlow::Node succ) =
fastTC(localFlowStepPlusInitializers/2)(pred, succ)
/**
* Holds if data can flow from `pred` to `succ` in zero or more
* local (intra-procedural) steps or via instance or static variable intializers
* Holds if data can flow from `pred` to `succ` in a
* local (intra-procedural) step or via instance or static variable intializers
* for final variables.
*/
private predicate localFlowPlusInitializers(DataFlow::Node pred, DataFlow::Node succ) {
exists(Variable v | v.isFinal() and pred.asExpr() = v.getInitializer() |
DataFlow::localFlow(DataFlow::exprNode(v.getAnAccess()), succ)
private predicate localFlowStepPlusInitializers(DataFlow::Node pred, DataFlow::Node succ) {
exists(Variable v |
v.isFinal() and
pred.asExpr() = v.getInitializer() and
succ.asExpr() = v.getAnAccess()
)
or
DataFlow::localFlow(pred, succ)
DataFlow::localFlowStep(pred, succ)
}