11package org.usvm.jvm
22
3+ import org.jacodb.api.JcClasspath
34import org.jacodb.api.JcMethod
5+ import org.jacodb.api.JcTypedMethod
46import org.jacodb.api.cfg.JcBasicBlock
57import org.jacodb.api.cfg.JcBlockGraph
6- import org.jacodb.api.cfg.JcGraph
78import org.jacodb.api.cfg.JcInst
8- import org.jacodb.impl.cfg.JcBlockGraphImpl
9+ import org.jacodb.api.ext.toType
910import org.usvm.ApplicationBlockGraph
1011import org.usvm.machine.JcApplicationGraph
12+ import java.util.concurrent.ConcurrentHashMap
1113
12- class JcApplicationBlockGraph (jcGraph : JcGraph ) :
14+ class JcApplicationBlockGraph (cp : JcClasspath ) :
1315 ApplicationBlockGraph <JcMethod , JcBasicBlock , JcInst > {
14- private val jcBlockGraphImpl: JcBlockGraph = JcBlockGraphImpl (jcGraph)
15- private val jcApplicationGraph: JcApplicationGraph = JcApplicationGraph (jcGraph.classpath)
16- override fun predecessors (node : JcBasicBlock ): Sequence <JcBasicBlock > =
17- jcBlockGraphImpl.predecessors(node).asSequence()
16+ val jcApplicationGraph: JcApplicationGraph = JcApplicationGraph (cp)
17+ var initialStatement: JcInst ? = null
18+ private fun getInitialStatement (): JcInst {
19+ if (initialStatement == null ) {
20+ throw RuntimeException (" initial statement not set" )
21+ }
22+ return initialStatement!!
23+ }
24+
25+ private fun getBlockGraph () = getInitialStatement().location.method.flowGraph().blockGraph()
1826
19- override fun successors (node : JcBasicBlock ): Sequence <JcBasicBlock > = jcBlockGraphImpl.successors(node).asSequence()
27+ override fun predecessors (node : JcBasicBlock ): Sequence <JcBasicBlock > {
28+ val jcBlockGraphImpl: JcBlockGraph = getBlockGraph()
29+ return jcBlockGraphImpl.predecessors(node).asSequence()
30+ }
31+
32+ override fun successors (node : JcBasicBlock ): Sequence <JcBasicBlock > {
33+ val jcBlockGraphImpl: JcBlockGraph = getBlockGraph()
34+ return jcBlockGraphImpl.successors(node).asSequence()
35+ }
2036
2137 override fun callees (node : JcBasicBlock ): Sequence <JcMethod > {
38+ val jcBlockGraphImpl: JcBlockGraph = getBlockGraph()
39+
2240 return jcBlockGraphImpl.instructions(node)
2341 .map { jcApplicationGraph.callees(it) }
2442 .reduce { acc, sequence -> acc + sequence }
@@ -29,26 +47,53 @@ class JcApplicationBlockGraph(jcGraph: JcGraph) :
2947 override fun callers (method : JcMethod ): Sequence <JcBasicBlock > {
3048 return jcApplicationGraph
3149 .callers(method)
32- .map { stmt -> block (stmt) }
50+ .map { stmt -> blockOf (stmt) }
3351 .toSet()
3452 .asSequence()
3553 }
3654
37- override fun entryPoints (method : JcMethod ): Sequence <JcBasicBlock > = jcBlockGraphImpl.entries.asSequence()
55+ override fun entryPoints (method : JcMethod ): Sequence <JcBasicBlock > =
56+ method.flowGraph().blockGraph().entries.asSequence()
57+
58+ override fun exitPoints (method : JcMethod ): Sequence <JcBasicBlock > =
59+ method.flowGraph().blockGraph().exits.asSequence()
3860
39- override fun exitPoints (method : JcMethod ): Sequence <JcBasicBlock > = jcBlockGraphImpl.exits.asSequence()
61+ override fun methodOf (node : JcBasicBlock ): JcMethod {
62+ val firstInstruction = getBlockGraph().instructions(node).first()
63+ return jcApplicationGraph.methodOf(firstInstruction)
64+ }
4065
41- override fun methodOf (node : JcBasicBlock ): JcMethod = jcBlockGraphImpl.instructions(node).first().location.method
66+ override fun instructions (block : JcBasicBlock ): Sequence <JcInst > {
67+ return getBlockGraph().instructions(block).asSequence()
68+ }
4269
4370 override fun statementsOf (method : JcMethod ): Sequence <JcBasicBlock > {
4471 return jcApplicationGraph
4572 .statementsOf(method)
46- .map { stmt -> block (stmt) }
73+ .map { stmt -> blockOf (stmt) }
4774 .toSet()
4875 .asSequence()
4976 }
5077
51- override fun block (stmt : JcInst ): JcBasicBlock = jcBlockGraphImpl.block(stmt)
52- override fun instructions (block : JcBasicBlock ): Sequence <JcInst > = jcBlockGraphImpl.instructions(block).asSequence()
53- override fun blocks (): Sequence <JcBasicBlock > = jcBlockGraphImpl.asSequence()
78+ override fun blockOf (stmt : JcInst ): JcBasicBlock {
79+ val jcBlockGraphImpl: JcBlockGraph = stmt.location.method.flowGraph().blockGraph()
80+ val blocks = blocks()
81+ for (block in blocks) {
82+ if (stmt in jcBlockGraphImpl.instructions(block)) {
83+ return block
84+ }
85+ }
86+ throw IllegalStateException (" block not found for $stmt in ${jcBlockGraphImpl.jcGraph.method} " )
87+ }
88+
89+ override fun blocks (): Sequence <JcBasicBlock > {
90+ return getInitialStatement().location.method.flowGraph().blockGraph().asSequence()
91+ }
92+
93+ private val typedMethodsCache = ConcurrentHashMap <JcMethod , JcTypedMethod >()
94+
95+ val JcMethod .typed
96+ get() = typedMethodsCache.getOrPut(this ) {
97+ enclosingClass.toType().declaredMethods.first { it.method == this }
98+ }
5499}
0 commit comments