This is moiling who hopes to draw another wonderful world with computer!
- 🔭 I’m currently researching on image matting.
Java Path Coverage Tools.
To obtain the 2-values(left and right) of the judgment expression, we can duplicate the two values at the top of the stack first. we don't need restore it after.
private fun getIfJudge(mv: MethodVisitor, point: String, isZero: Boolean) {
if (!isZero) {
mv.visitInsn(Opcodes.DUP2)
mv.visitLdcInsn(point)
mv.visitMethodInsn(Opcodes.INVOKESTATIC, CLASS_JUDGE, "if_setValue", "(IILjava/lang/String;)V", false)
}
else if (isZero) {
mv.visitInsn(Opcodes.DUP)
mv.visitInsn(Opcodes.ICONST_0)
mv.visitLdcInsn(point)
mv.visitMethodInsn(Opcodes.INVOKESTATIC, CLASS_JUDGE, "if_setValue", "(IILjava/lang/String;)V", false)
}
}
private fun getOtherJudge(mv: MethodVisitor, point: String, valType: Char) {
if (valType == 'D') {
mv.visitInsn(Opcodes.DUP2_X2)
mv.visitMethodInsn(Opcodes.INVOKESTATIC, CLASS_JUDGE, "if_setDouble_1", "(D)V", false)
mv.visitInsn(Opcodes.DUP2_X2)
mv.visitLdcInsn(point)
mv.visitMethodInsn(Opcodes.INVOKESTATIC, CLASS_JUDGE, "if_setDouble_2", "(DLjava/lang/String;)V", false)
}
else if (valType == 'L') {
mv.visitInsn(Opcodes.DUP2_X2)
mv.visitMethodInsn(Opcodes.INVOKESTATIC, CLASS_JUDGE, "if_setLong_1", "(J)V", false)
mv.visitInsn(Opcodes.DUP2_X2)
mv.visitLdcInsn(point)
mv.visitMethodInsn(Opcodes.INVOKESTATIC, CLASS_JUDGE, "if_setLong_2", "(JLjava/lang/String;)V", false)
}
else if (valType == 'F') {
mv.visitInsn(Opcodes.DUP2)
mv.visitLdcInsn(point)
mv.visitMethodInsn(Opcodes.INVOKESTATIC, CLASS_JUDGE, "if_setFloat", "(FFLjava/lang/String;)V", false)
}
}
private fun getSwitchJudge(mv: MethodVisitor, point: String) {
mv.visitInsn(Opcodes.DUP)
mv.visitLdcInsn(point)
mv.visitMethodInsn(Opcodes.INVOKESTATIC, CLASS_JUDGE, "switch_setValue", "(ILjava/lang/String;)V", false)
}
Japaco/src/main/kotlin/com/moi/japaco/worker/PathClassAdapter.kt
Lines 132 to 133 in 412a4c0
if (opcode == Opcodes.DCMPG || opcode == Opcodes.DCMPL) {
val judgeMark = "$owner.${currentMethod?.replace("<","")?.replace(">","")}:I${ifNum}"
getOtherJudge(mv,judgeMark,'D')
transfer = true
}
else if (opcode == Opcodes.FCMPG || opcode == Opcodes.FCMPL) {
val judgeMark = "$owner.${currentMethod?.replace("<","")?.replace(">","")}:I${ifNum}"
getOtherJudge(mv,judgeMark,'F')
transfer = true
}
else if (opcode == Opcodes.LCMP) {
val judgeMark = "$owner.${currentMethod?.replace("<","")?.replace(">","")}:I${ifNum}"
getOtherJudge(mv,judgeMark,'L')
transfer = true
}
Japaco/src/main/kotlin/com/moi/japaco/worker/PathClassAdapter.kt
Lines 166 to 177 in 412a4c0
val judgeMark = "$owner.${currentMethod?.replace("<", "")?.replace(">", "")}:I${ifNum}"
var isZero = false
val sign = when (opcode) {
Opcodes.IF_ICMPEQ, Opcodes.IFEQ -> "="
Opcodes.IF_ICMPGE, Opcodes.IFGE -> ">="
Opcodes.IF_ICMPGT, Opcodes.IFGT -> ">"
Opcodes.IF_ICMPLE, Opcodes.IFLE -> "<="
Opcodes.IF_ICMPLT, Opcodes.IFLT -> "<"
Opcodes.IF_ICMPNE, Opcodes.IFNE -> "!="
else -> "null"
}
if (opcode == Opcodes.IFEQ || opcode == Opcodes.IFGE || opcode == Opcodes.IFGT || opcode == Opcodes.IFLE || opcode == Opcodes.IFLT || opcode == Opcodes.IFNE) {
isZero = true
}
if (sign != "null") {
if (isZero && transfer) {
IfPoints[judgeMark] = sign
ifNum += 1
transfer = false
} else {
IfPoints[judgeMark] = sign
getIfJudge(mv, judgeMark, isZero)
ifNum += 1
}
}
mv.visitJumpInsn(opcode, label)
if (sign != "null") {
addPair(getPoint("$label", judgeMark))
val newPoint = addPair(getPoint("!$label", judgeMark))
if (opcode == Opcodes.GOTO) {
currentPoint = null
} else {
currentPoint = newPoint
}
} else {
if (opcode == Opcodes.GOTO) {
addPair(getPoint("$label", null))
currentPoint = null
} else {
addPair(getPoint("$label", null))
val newPoint = addPair(getPoint("!$label", null))
currentPoint = newPoint
}
}
// stub
addStub(mv, "$owner.${currentMethod?.replace("<", "")?.replace(">", "")}:!$label")
all code:
package com.moi.japaco.worker
import com.moi.japaco.config.*
import com.moi.japaco.data.Point
import org.objectweb.asm.ClassVisitor
import org.objectweb.asm.Label
import org.objectweb.asm.MethodVisitor
import org.objectweb.asm.Opcodes
import java.util.*
import kotlin.collections.ArrayList
/*
* allEdges: <method name, [path pairs]>
* eg: <"com/moi/Test.test", [<"L0", "L1">, <"L0", "l2">, ..., <"L4", "L5">]>
*/
class PathClassAdapter constructor(
private var version: Int,
cv: ClassVisitor?,
private var IfPoints: MutableMap<String, String>, //out
private var switchPoints: MutableMap<String, ArrayList<Int>>, //out
private var allEdges: MutableMap<String, ArrayList<Pair<Point, Point>>>, // out
private var classNames: MutableList<String>,
private var displayNum: Int
) : ClassVisitor(version, cv) {
private var owner: String? = null
private var isInterface: Boolean = false
private var currentMethod: String? = null
private var currentMethodDesc: String? = null
public fun getDisplay(): Int {
return displayNum
}
override fun visit(
version: Int,
access: Int,
name: String?,
signature: String?,
superName: String?,
interfaces: Array<out String>?
) {
owner = name
isInterface = (access and Opcodes.ACC_INTERFACE) != 0 // and -> &
cv.visit(version, access, name, signature, superName, interfaces)
}
override fun visitMethod(
access: Int,
name: String?,
desc: String?,
signature: String?,
exceptions: Array<out String>?
): MethodVisitor? {
currentMethod = name
currentMethodDesc = desc
val mv: MethodVisitor? = cv.visitMethod(access, name, desc, signature, exceptions)
return if (isInterface) mv else PathMethodAdapter(version, mv, allEdges)
}
/*
* Code Analyze:
* LABEL_START (when visitCode existed): set currentLabel as "LABEL_START".
* NEW LABEL (if a new label is encountered):
* - if currentLabel isn't null: pair the new label with the currentLabel,and replace the currentLabel. (in-order)
* - if currentLabel is null: set currentLabel as label. (new branch)
* JUMP:
* - isn't GOTO: pair the jump target label with the currentLabel, and pair the "!jump target label"(means not jump) with the currentLabel.
* set currentLabel as "!jump target label"
* - GOTO: pair the jump target label with the currentLabel, and clear the currentLabel.
* SWITCH: use the default and other cases target label of switch to form multiple pairs with the currentLabel, and clear the currentLabel.
* RETURN: pair the "LABEL_END" label with the currentLabel, and clear the currentLabel.
* INVOKE: if method should be test(determine package name), pair the method name and the currentLabel, and replace the currentLabel.
*/
inner class PathMethodAdapter(
version: Int,
mv: MethodVisitor?,
private var allEdges: MutableMap<String, ArrayList<Pair<Point, Point>>> // out
) : MethodVisitor(version, mv) {
private var ifNum: Int = 0
private var switchNum: Int = 0
private var paths: ArrayList<Pair<Point, Point>> = ArrayList()
private var currentPoint: Point? = null
private var passedPoints: ArrayList<Point> = ArrayList()
private var transfer = false
private fun addStub(mv: MethodVisitor, text: String) {
mv.visitFieldInsn(Opcodes.GETSTATIC, CLASS_DATA, "array", "Ljava/util/ArrayList;")
mv.visitLdcInsn(text)
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/util/ArrayList", "add", "(Ljava/lang/Object;)Z", false)
mv.visitInsn(Opcodes.POP)
}
private fun getIfJudge(mv: MethodVisitor, point: String, isZero: Boolean) {
if (!isZero) {
mv.visitInsn(Opcodes.DUP2)
mv.visitLdcInsn(point)
mv.visitMethodInsn(Opcodes.INVOKESTATIC, CLASS_JUDGE, "if_setValue", "(IILjava/lang/String;)V", false)
} else if (isZero) {
mv.visitInsn(Opcodes.DUP)
mv.visitInsn(Opcodes.ICONST_0)
mv.visitLdcInsn(point)
mv.visitMethodInsn(Opcodes.INVOKESTATIC, CLASS_JUDGE, "if_setValue", "(IILjava/lang/String;)V", false)
}
}
private fun getOtherJudge(mv: MethodVisitor, point: String, valType: Char) {
if (valType == 'D') {
mv.visitInsn(Opcodes.DUP2_X2)
mv.visitMethodInsn(Opcodes.INVOKESTATIC, CLASS_JUDGE, "if_setDouble_1", "(D)V", false)
mv.visitInsn(Opcodes.DUP2_X2)
mv.visitLdcInsn(point)
mv.visitMethodInsn(Opcodes.INVOKESTATIC, CLASS_JUDGE, "if_setDouble_2", "(DLjava/lang/String;)V", false)
} else if (valType == 'L') {
mv.visitInsn(Opcodes.DUP2_X2)
mv.visitMethodInsn(Opcodes.INVOKESTATIC, CLASS_JUDGE, "if_setLong_1", "(J)V", false)
mv.visitInsn(Opcodes.DUP2_X2)
mv.visitLdcInsn(point)
mv.visitMethodInsn(Opcodes.INVOKESTATIC, CLASS_JUDGE, "if_setLong_2", "(JLjava/lang/String;)V", false)
} else if (valType == 'F') {
mv.visitInsn(Opcodes.DUP2)
mv.visitLdcInsn(point)
mv.visitMethodInsn(Opcodes.INVOKESTATIC, CLASS_JUDGE, "if_setFloat", "(FFLjava/lang/String;)V", false)
}
}
private fun getSwitchJudge(mv: MethodVisitor, point: String) {
mv.visitInsn(Opcodes.DUP)
mv.visitLdcInsn(point)
mv.visitMethodInsn(Opcodes.INVOKESTATIC, CLASS_JUDGE, "switch_setValue", "(ILjava/lang/String;)V", false)
}
private fun getPoint(label: String, judgeMark: String?): Point {
if (!label.startsWith(LABEL_INVOKE_METHOD)) {
val pointIndex = passedPoints.indexOfFirst { it.label == label }
if (pointIndex != -1 && !label.startsWith("!")) {
return passedPoints[pointIndex]
}
}
val display = when {
label.startsWith(LABEL_INVOKE_METHOD) -> "I${displayNum++}"
else -> "L${displayNum++}"
}
val newPoint = if (label.startsWith(LABEL_INVOKE_METHOD)) {
Point(
label.split('.')[1],
label.split('.')[2].replace("<", "").replace(">", ""),
LABEL_INVOKE_METHOD,
display,
judgeMark,
label.split('.')[3]
)
} else {
if (label == LABEL_START || label == LABEL_END)
Point(
owner,
currentMethod?.replace("<", "")?.replace(">", ""),
label,
display,
judgeMark,
currentMethodDesc!!.substring(0, currentMethodDesc!!.indexOf(')') + 1)
)
else
Point(owner, currentMethod?.replace("<", "")?.replace(">", ""), label, display, judgeMark, null)
}
passedPoints.add(newPoint)
return newPoint
}
private fun addPair(newPoint: Point): Point {
currentPoint?.let { paths.add(Pair(it, newPoint)) }
return newPoint
}
override fun visitLabel(label: Label?) {
mv.visitLabel(label)
val newPoint = getPoint("$label", null)
addPair(newPoint)
currentPoint = newPoint
// stub
addStub(mv, "$owner.${currentMethod?.replace("<", "")?.replace(">", "")}:$label")
}
override fun visitCode() {
mv.visitCode()
currentPoint = getPoint(LABEL_START, null)
// stub
addStub(mv, "$owner.${currentMethod?.replace("<", "")?.replace(">", "")}:$LABEL_START")
}
override fun visitInsn(opcode: Int) {
if (opcode == Opcodes.DCMPG || opcode == Opcodes.DCMPL) {
val judgeMark = "$owner.${currentMethod?.replace("<", "")?.replace(">", "")}:I${ifNum}"
getOtherJudge(mv, judgeMark, 'D')
transfer = true
} else if (opcode == Opcodes.FCMPG || opcode == Opcodes.FCMPL) {
val judgeMark = "$owner.${currentMethod?.replace("<", "")?.replace(">", "")}:I${ifNum}"
getOtherJudge(mv, judgeMark, 'F')
transfer = true
} else if (opcode == Opcodes.LCMP) {
val judgeMark = "$owner.${currentMethod?.replace("<", "")?.replace(">", "")}:I${ifNum}"
getOtherJudge(mv, judgeMark, 'L')
transfer = true
}
if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) || opcode == Opcodes.ATHROW) {
addPair(getPoint(LABEL_END, null))
currentPoint = null
// stub
addStub(mv, "$owner.${currentMethod?.replace("<", "")?.replace(">", "")}:$LABEL_END")
}
mv.visitInsn(opcode) // RETURN
}
override fun visitMethodInsn(opcode: Int, owner: String?, name: String?, desc: String?, p4: Boolean) {
mv.visitMethodInsn(opcode, owner, name, desc, p4)
if (owner in classNames) {
val newPoint =
getPoint("$LABEL_INVOKE_METHOD.$owner.$name.${desc!!.substring(0, desc.indexOf(')') + 1)}", null)
addPair(newPoint)
currentPoint = newPoint
}
}
override fun visitTableSwitchInsn(min: Int, max: Int, dflt: Label?, vararg labels: Label?) {
val temp = ArrayList<Int>()
for (n in 0..(max - min)) {
if (labels[n] != dflt) {
temp.add(n + min)
}
}
val judgeMark = "$owner.${currentMethod?.replace("<", "")?.replace(">", "")}:S${switchNum}"
switchPoints[judgeMark] = temp
getSwitchJudge(mv, judgeMark)
switchNum += 1
mv.visitTableSwitchInsn(min, max, dflt, *labels)
addPair(getPoint("$dflt", judgeMark))
labels.forEach { addPair(getPoint("$it", judgeMark)) }
currentPoint = null
}
override fun visitLookupSwitchInsn(dflt: Label?, keys: IntArray?, labels: Array<out Label>?) {
val temp = ArrayList<Int>()
keys?.forEach {
temp.add(it)
}
val judgeMark = "$owner.${currentMethod?.replace("<", "")?.replace(">", "")}:S${switchNum}"
switchPoints[judgeMark] = temp
getSwitchJudge(mv, judgeMark)
switchNum += 1
mv.visitLookupSwitchInsn(dflt, keys, labels)
addPair(getPoint("$dflt", judgeMark))
labels?.forEach { addPair(getPoint("$it", judgeMark)) }
currentPoint = null
}
override fun visitJumpInsn(opcode: Int, label: Label?) {
val judgeMark = "$owner.${currentMethod?.replace("<", "")?.replace(">", "")}:I${ifNum}"
var isZero = false
val sign = when (opcode) {
Opcodes.IF_ICMPEQ, Opcodes.IFEQ -> "="
Opcodes.IF_ICMPGE, Opcodes.IFGE -> ">="
Opcodes.IF_ICMPGT, Opcodes.IFGT -> ">"
Opcodes.IF_ICMPLE, Opcodes.IFLE -> "<="
Opcodes.IF_ICMPLT, Opcodes.IFLT -> "<"
Opcodes.IF_ICMPNE, Opcodes.IFNE -> "!="
else -> "null"
}
if (opcode == Opcodes.IFEQ || opcode == Opcodes.IFGE || opcode == Opcodes.IFGT || opcode == Opcodes.IFLE || opcode == Opcodes.IFLT || opcode == Opcodes.IFNE) {
isZero = true
}
if (sign != "null") {
if (isZero && transfer) {
IfPoints[judgeMark] = sign
ifNum += 1
transfer = false
} else {
IfPoints[judgeMark] = sign
getIfJudge(mv, judgeMark, isZero)
ifNum += 1
}
}
mv.visitJumpInsn(opcode, label)
if (sign != "null") {
addPair(getPoint("$label", judgeMark))
val newPoint = addPair(getPoint("!$label", judgeMark))
if (opcode == Opcodes.GOTO) {
currentPoint = null
} else {
currentPoint = newPoint
}
} else {
if (opcode == Opcodes.GOTO) {
addPair(getPoint("$label", null))
currentPoint = null
} else {
addPair(getPoint("$label", null))
val newPoint = addPair(getPoint("!$label", null))
currentPoint = newPoint
}
}
// stub
addStub(mv, "$owner.${currentMethod?.replace("<", "")?.replace(">", "")}:!$label")
}
override fun visitEnd() {
// println("$owner.${currentMethod?.replace("<","")?.replace(">","")}.${currentMethodDesc!!.substring(0, currentMethodDesc!!.indexOf(')') + 1)}")
allEdges["$owner.${currentMethod?.replace("<", "")?.replace(">", "")}.${
currentMethodDesc!!.substring(
0,
currentMethodDesc!!.indexOf(')') + 1
)
}"] = paths
mv.visitEnd()
}
}
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.