Git Product home page Git Product logo

japaco's Introduction

Hi there 👋

This is moiling who hopes to draw another wonderful world with computer!

  • 🔭 I’m currently researching on image matting.

japaco's People

Contributors

moiling avatar

Watchers

 avatar

japaco's Issues

Obtain the 2-values(left and right) of the judgment expression.

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)
}

override fun visitInsn(opcode: Int) {
if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) || opcode == Opcodes.ATHROW) {

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
}

override fun visitJumpInsn(opcode: Int, label: Label?) {
mv.visitJumpInsn(opcode, label)
addPair(getPoint("$label"))
val newPoint = addPair(getPoint("!$label"))
if (opcode == Opcodes.GOTO) {
currentPoint = null
} else {
currentPoint = newPoint
}
// stub
addStub(mv, "$owner.$currentMethod:!$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")

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()
        }
    }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.