SPLASH/ISSTA 2026 Tool Demonstrations
FlowLog: Re-thinking Datalog forFast and Extensible Static Analysis
ArecursiveDatalogruleA simple Datalog program: Reachability
A declarative logic programming language
Reach(y):-Source(y).
Reach(y):-Reach(x), Edge(x, y).
Reach = {a}{a, b, c}{a, b, c, d}{a, b, c, d, e}
Challenges in Building Datalog Engines
Building from scratch
- ✓Fine-grained control over evaluation
- ✓Datalog-specific optimizations
- ×New features require
invasive changes - ×Incrementality and scale-out
require major engineering
Building on an existing engine
- ✓Reuse mature execution primitives
- ✓Inherit parallelism or incrementality
- ×Datalog-aware optimization
becomes difficult - ×Runtime costs are dictated
by the substrate
[1] McSherry et al. “Differential Dataflow.” CIDR 2013.
FlowLog architecture
Demo 1 · One-shot mode
Efficient and scalable
static analysis
DOOP · Context-insensitive points-to analysis
ArealDatalogprogram in FlowLog
DOOP* uses Datalog rules to compute points-to information for Java programs. Here we use its context-insensitive analysis.
// Input (EDB) facts extracted from Java bytecode
.decl MainClass(class: string)
.input MainClass
// ... other input relations omitted
// Derived (IDB) relations used by the analysis
.decl Reachable(method: string)
.decl LoadInstanceField(base: string, sig: string, to: string, inmethod: string)
// Variable var may point to object heap
.decl VarPointsTo(heap: string, var: string)
// Field sig of object baseHeap may point to object heap
.decl InstanceFieldPointsTo(heap: string, sig: string, baseHeap: string)// Propagate points-to information through a field load
VarPointsTo(heap, to) :-
Reachable(inmethod),
LoadInstanceField(base, sig, to, inmethod),
VarPointsTo(baseheap, base),
InstanceFieldPointsTo(heap, sig, baseheap).// Output: variable-to-object points-to information
.output VarPointsTo
Soufflé-style syntax
.decl Relation(...)Declare a relation schema.input RelationLoad input factsHead :- Body.Derive tuples with a rule.output RelationEmit a relation as program output*DOOP Framework 101, plast-lab.github.io/doop-pldi15-tutorial/
Run DOOP with FlowLog
-D <dir>output result directory-F <dir>input fact directory-o <path>output binary-Penable profiling# Compile the DOOP analysis
$ flowlog context-insensitive.dl -o doop-one-shot -F ./facts -D ./out
# Run in parallel with 32 workers
$ ./doop-one-shot -w 32
FlowLogis faston real analyses
Figure from the SPLASH/ISSTA 2026 tool-demo paper · 32 threads · log scale · lower is better
FlowLogscaleson real analyses
Figure from the SPLASH/ISSTA 2026 tool-demo paper · speedup relative to one thread
Demo 2 · Incremental mode
Maintain analysis results
as inputs change
DOOP · Context-insensitive points-to analysis
Run DOOP in incremental mode
# Compile the same analysis in incremental mode
$ flowlog context-insensitive.dl -o doop-inc -F ./facts -D ./out --mode datalog-inc
# Launch the interactive shell with 32 workers
$ ./doop-inc -w 32
beginBegin an update roundput <rel> <tuple> <diff>Stage one tuple: +1 inserts, −1 retractsfile <rel> <path> <diff>Stage a fact file: +1 inserts, −1 retractscommitApply all staged updates togetherUpdate DOOP as input changes
DOOP · Tomcat · Retract one LoadInstanceField fact
≈ 172× faster
Measured on the current demo machine · context-insensitive analysis
Demo 3 · Profiler
Diagnose and fix
performance bottlenecks
DOOP · Context-insensitive points-to analysis
Profiler-guided diagnosis
Revisit the field-load rule with a deliberately poor join order:
VarPointsTo(heap, to) :-
Reachable(inmethod),
LoadInstanceField(base, signature, to, inmethod),
VarPointsTo(baseheap, base),
InstanceFieldPointsTo(heap, signature, baseheap).
// Pin a poor join order for this demo
.plan (1,3,4,2)
# Enable per-operator profiling with -P
$ flowlog context-insensitive.dl -o doop-prof -F ./facts -D ./out -P
$ ./doop-prof -w 32
Demo 4 · Extended semantics
Extensible recursive
semantics
K-core decomposition · Non-monotonic recursion
Control recursive evaluation
Recursive controls
fixpoint { ... }- Repeat until stable
.iterative R- R may gain or lose tuples across iterations
loop while { @it <= N } { ... }- Bound the number of iterations
loop until { Done } { ... }- Stop when Done becomes non-empty
K-core decomposition k = 3
fixpoint {
.iterative active_edge
.iterative degree
active_edge(x, y) :-
edge(x, y), !removed(x), !removed(y).
degree(x, count(y)) :- active_edge(x, y).
removed(x) :- degree(x, d), d < 3.
}
Repeatedly remove vertices with fewer than 3 neighbors.
Compile with --mode extend-batch
Real-world Applications
DOOP integration
In progress with the DOOP team
to support their analyses in FlowLog.
Agent verification
Developing FlowLog support
for agent verification.
…and more.
Efficient
- Scalable static analysis
- Profiler-guided optimization
Extensible
- Incremental updates
- Extended recursive semantics
Four Datalog systems in practice
Mature one-shot toolchain
B-tree indexes limit join parallelism to the outer loop
Lightweight, embedded in Rust macros
Features require engineering
Performance needs tuning
Incremental execution
High memory use from duplicated stateful intermediates
Datalog-aware optimization
Fine-grained join parallelism
Incremental execution & richer semantics
1 https://souffle-lang.github.io/2 https://github.com/s-arash/ascent3 https://github.com/vmware-archive/differential-datalog