Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a5393b4

Browse files
authored
Merge pull request #4746 from aschackmull/java/ssa-perf
Java: Improve performance of SSA.
2 parents 4226467 + 5a66d6a commit a5393b4

2 files changed

Lines changed: 52 additions & 64 deletions

File tree

java/ql/src/semmle/code/java/dataflow/SSA.qll

Lines changed: 51 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -418,21 +418,6 @@ private module SsaImpl {
418418
callEdge(c1, c2) and not intraInstanceCallEdge(c1, c2)
419419
}
420420

421-
/** Holds if a call to `x.c` can change the value of `x.f`. The actual update occurs in `setter`. */
422-
private predicate setsOwnFieldTransitive(Method c, Field f, Method setter) {
423-
setsOwnField(setter, f) and intraInstanceCallEdge*(c, setter)
424-
}
425-
426-
/** Holds if a call to `c` can change the value of `f` on some instance. The actual update occurs in `setter`. */
427-
private predicate generalSetter(Callable c, Field f, Callable setter) {
428-
exists(Method ownsetter |
429-
setsOwnFieldTransitive(ownsetter, f, setter) and
430-
crossInstanceCallEdge(c, ownsetter)
431-
)
432-
or
433-
setsOtherField(c, f) and c = setter
434-
}
435-
436421
/**
437422
* Holds if `call` occurs in the same basic block, `b`, as `f` at index `i` and
438423
* `f` has an update somewhere.
@@ -487,78 +472,79 @@ private module SsaImpl {
487472
)
488473
}
489474

490-
/**
491-
* Holds if `c` is a relevant part of the call graph for
492-
* `updatesNamedFieldPart1` based on following edges in forward direction.
493-
*/
494-
private predicate pruneFromLeft(Callable c) {
495-
exists(Call call, SsaSourceField f |
496-
generalSetter(_, f.getField(), _) and
497-
relevantCall(call, f) and
498-
c = tgt(call)
499-
)
500-
or
501-
exists(Callable mid | pruneFromLeft(mid) and callEdge(mid, c))
475+
private predicate source(Call call, TrackedField f, Field field, Callable c, boolean fresh) {
476+
relevantCall(call, f) and
477+
field = f.getField() and
478+
c = tgt(call) and
479+
if c instanceof Constructor then fresh = true else fresh = false
502480
}
503481

504482
/**
505-
* Holds if `c` is a relevant part of the call graph for
506-
* `updatesNamedFieldPart1` based on following edges in backward direction.
483+
* A callable in a potential call-chain between a source that cares about the
484+
* value of some field `f` and a sink that may overwrite `f`. The boolean
485+
* `fresh` indicates whether the instance `this` in `c` has been freshly
486+
* allocated along the call-chain.
507487
*/
508-
private predicate pruneFromRight(Callable c) {
509-
generalSetter(c, _, _)
510-
or
511-
exists(Callable mid | callEdge(c, mid) and pruneFromRight(mid))
512-
}
488+
private newtype TCallableNode =
489+
MkCallableNode(Callable c, boolean fresh) { source(_, _, _, c, fresh) or edge(_, c, fresh) }
513490

514-
/** A restriction of the call graph to the parts that are relevant for `updatesNamedFieldPart1`. */
515-
private class PrunedCallable extends Callable {
516-
PrunedCallable() { pruneFromLeft(this) and pruneFromRight(this) }
491+
private predicate edge(TCallableNode n, Callable c2, boolean f2) {
492+
exists(Callable c1, boolean f1 | n = MkCallableNode(c1, f1) |
493+
intraInstanceCallEdge(c1, c2) and f2 = f1
494+
or
495+
crossInstanceCallEdge(c1, c2) and
496+
if c2 instanceof Constructor then f2 = true else f2 = false
497+
)
517498
}
518499

519-
private predicate callEdgePruned(PrunedCallable c1, PrunedCallable c2) { callEdge(c1, c2) }
520-
521-
private predicate callEdgePlus(PrunedCallable c1, PrunedCallable c2) =
522-
fastTC(callEdgePruned/2)(c1, c2)
500+
private predicate edge(TCallableNode n1, TCallableNode n2) {
501+
exists(Callable c2, boolean f2 |
502+
edge(n1, c2, f2) and
503+
n2 = MkCallableNode(c2, f2)
504+
)
505+
}
523506

524507
pragma[noinline]
525-
private predicate updatesNamedFieldPrefix(Call call, TrackedField f, Callable c1, Field field) {
526-
relevantCall(call, f) and
527-
field = f.getField() and
528-
c1 = tgt(call)
508+
private predicate source(Call call, TrackedField f, Field field, TCallableNode n) {
509+
exists(Callable c, boolean fresh |
510+
source(call, f, field, c, fresh) and
511+
n = MkCallableNode(c, fresh)
512+
)
529513
}
530514

531-
pragma[noinline]
532-
private predicate generalSetterProj(Callable c, Field f) { generalSetter(c, f, _) }
515+
private predicate sink(Callable c, Field f, TCallableNode n) {
516+
setsOwnField(c, f) and n = MkCallableNode(c, false)
517+
or
518+
setsOtherField(c, f) and n = MkCallableNode(c, _)
519+
}
533520

534-
/**
535-
* Holds if `call` may change the value of `f` on some instance, which may or
536-
* may not alias with `this`. The actual update occurs in `setter`.
537-
*/
538-
pragma[noopt]
539-
private predicate updatesNamedFieldPart1(Call call, TrackedField f, Callable setter) {
540-
exists(Callable c1, Callable c2, Field field |
541-
updatesNamedFieldPrefix(call, f, c1, field) and
542-
generalSetterProj(c2, field) and
543-
(c1 = c2 or callEdgePlus(c1, c2)) and
544-
generalSetter(c2, field, setter)
545-
)
521+
private predicate prunedNode(TCallableNode n) {
522+
sink(_, _, n)
523+
or
524+
exists(TCallableNode mid | edge(n, mid) and prunedNode(mid))
546525
}
547526

548-
/** Holds if `call` may change the value of `f` on `this`. The actual update occurs in `setter`. */
549-
private predicate updatesNamedFieldPart2(Call call, TrackedField f, Callable setter) {
550-
relevantCall(call, f) and
551-
setsOwnFieldTransitive(tgt(call), f.getField(), setter)
527+
private predicate prunedEdge(TCallableNode n1, TCallableNode n2) {
528+
prunedNode(n1) and
529+
prunedNode(n2) and
530+
edge(n1, n2)
552531
}
553532

533+
private predicate edgePlus(TCallableNode c1, TCallableNode c2) = fastTC(prunedEdge/2)(c1, c2)
534+
554535
/**
555536
* Holds if there exists a call-chain originating in `call` that can update `f` on some instance
556537
* where `f` and `call` share the same enclosing callable in which a
557538
* `FieldRead` of `f` is reachable from `call`.
558539
*/
540+
pragma[noopt]
559541
cached
560542
predicate updatesNamedField(Call call, TrackedField f, Callable setter) {
561-
updatesNamedFieldPart1(call, f, setter) or updatesNamedFieldPart2(call, f, setter)
543+
exists(TCallableNode src, TCallableNode sink, Field field |
544+
source(call, f, field, src) and
545+
sink(setter, field, sink) and
546+
(src = sink or edgePlus(src, sink))
547+
)
562548
}
563549

564550
/** Holds if `n` might update the locally tracked variable `v`. */
@@ -806,6 +792,7 @@ private module SsaImpl {
806792
* Holds if `v` occurs at index `i1` in `b1` and at index `i2` in `b2` and
807793
* there is a path between them without any occurrence of `v`.
808794
*/
795+
pragma[nomagic]
809796
predicate adjacentVarRefs(TrackedVar v, BasicBlock b1, int i1, BasicBlock b2, int i2) {
810797
exists(int rankix |
811798
b1 = b2 and

java/ql/src/semmle/code/java/dataflow/internal/BaseSSA.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ private module SsaImpl {
357357
* Holds if `v` occurs at index `i1` in `b1` and at index `i2` in `b2` and
358358
* there is a path between them without any occurrence of `v`.
359359
*/
360+
pragma[nomagic]
360361
predicate adjacentVarRefs(BaseSsaSourceVariable v, BasicBlock b1, int i1, BasicBlock b2, int i2) {
361362
exists(int rankix |
362363
b1 = b2 and

0 commit comments

Comments
 (0)