From e68fed7a9e2ab74a3974863ed23e785f24769307 Mon Sep 17 00:00:00 2001 From: Graham Date: Sun, 22 Dec 2019 15:03:33 +0000 Subject: [PATCH] Convert StackMetadata to Kotlin --- .../java/dev/openrs2/asm/InsnNodeUtils.java | 2 +- .../java/dev/openrs2/asm/StackMetadata.java | 353 ------------------ .../java/dev/openrs2/asm/StackMetadata.kt | 211 +++++++++++ .../deob/transform/DummyArgTransformer.java | 4 +- 4 files changed, 214 insertions(+), 356 deletions(-) delete mode 100644 asm/src/main/java/dev/openrs2/asm/StackMetadata.java create mode 100644 asm/src/main/java/dev/openrs2/asm/StackMetadata.kt diff --git a/asm/src/main/java/dev/openrs2/asm/InsnNodeUtils.java b/asm/src/main/java/dev/openrs2/asm/InsnNodeUtils.java index e6ddd1f5..0712370d 100644 --- a/asm/src/main/java/dev/openrs2/asm/InsnNodeUtils.java +++ b/asm/src/main/java/dev/openrs2/asm/InsnNodeUtils.java @@ -320,7 +320,7 @@ public final class InsnNodeUtils { var height = 0; var insn = last; do { - var metadata = StackMetadata.get(insn); + var metadata = StackMetadataKt.stackMetadata(insn); if (insn != last) { deadInsns.add(insn); height -= metadata.getPushes(); diff --git a/asm/src/main/java/dev/openrs2/asm/StackMetadata.java b/asm/src/main/java/dev/openrs2/asm/StackMetadata.java deleted file mode 100644 index 12e5e1e0..00000000 --- a/asm/src/main/java/dev/openrs2/asm/StackMetadata.java +++ /dev/null @@ -1,353 +0,0 @@ -package dev.openrs2.asm; - -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.FieldInsnNode; -import org.objectweb.asm.tree.LdcInsnNode; -import org.objectweb.asm.tree.MethodInsnNode; -import org.objectweb.asm.tree.MultiANewArrayInsnNode; - -public final class StackMetadata { - private static final StackMetadata NONE = new StackMetadata(0, 0); - private static final StackMetadata POP1 = new StackMetadata(1, 0); - private static final StackMetadata POP1_PUSH1 = new StackMetadata(1, 1); - private static final StackMetadata POP1_PUSH2 = new StackMetadata(1, 2); - private static final StackMetadata POP2 = new StackMetadata(2, 0); - private static final StackMetadata POP2_PUSH1 = new StackMetadata(2, 1); - private static final StackMetadata POP2_PUSH2 = new StackMetadata(2, 2); - private static final StackMetadata POP2_PUSH3 = new StackMetadata(2, 3); - private static final StackMetadata POP2_PUSH4 = new StackMetadata(2, 4); - private static final StackMetadata POP3 = new StackMetadata(3, 0); - private static final StackMetadata POP3_PUSH2 = new StackMetadata(3, 2); - private static final StackMetadata POP3_PUSH4 = new StackMetadata(3, 4); - private static final StackMetadata POP3_PUSH5 = new StackMetadata(3, 5); - private static final StackMetadata POP4 = new StackMetadata(4, 0); - private static final StackMetadata POP4_PUSH1 = new StackMetadata(4, 1); - private static final StackMetadata POP4_PUSH2 = new StackMetadata(4, 2); - private static final StackMetadata POP4_PUSH6 = new StackMetadata(4, 6); - private static final StackMetadata PUSH1 = new StackMetadata(0, 1); - private static final StackMetadata PUSH2 = new StackMetadata(0, 2); - - public static StackMetadata get(AbstractInsnNode insn) { - var opcode = insn.getOpcode(); - switch (opcode) { - case -1: - case Opcodes.NOP: - return NONE; - case Opcodes.ACONST_NULL: - case Opcodes.ICONST_M1: - case Opcodes.ICONST_0: - case Opcodes.ICONST_1: - case Opcodes.ICONST_2: - case Opcodes.ICONST_3: - case Opcodes.ICONST_4: - case Opcodes.ICONST_5: - return PUSH1; - case Opcodes.LCONST_0: - case Opcodes.LCONST_1: - return PUSH2; - case Opcodes.FCONST_0: - case Opcodes.FCONST_1: - case Opcodes.FCONST_2: - return PUSH1; - case Opcodes.DCONST_0: - case Opcodes.DCONST_1: - return PUSH2; - case Opcodes.BIPUSH: - case Opcodes.SIPUSH: - return PUSH1; - case Opcodes.LDC: - var cst = ((LdcInsnNode) insn).cst; - if (cst instanceof Double || cst instanceof Long) { - return PUSH2; - } else { - return PUSH1; - } - case Opcodes.ILOAD: - return PUSH1; - case Opcodes.LLOAD: - return PUSH2; - case Opcodes.FLOAD: - return PUSH1; - case Opcodes.DLOAD: - return PUSH2; - case Opcodes.ALOAD: - return PUSH1; - case Opcodes.IALOAD: - return POP2_PUSH1; - case Opcodes.LALOAD: - return POP2_PUSH2; - case Opcodes.FALOAD: - return POP2_PUSH1; - case Opcodes.DALOAD: - return POP2_PUSH2; - case Opcodes.AALOAD: - case Opcodes.BALOAD: - case Opcodes.CALOAD: - case Opcodes.SALOAD: - return POP2_PUSH1; - case Opcodes.ISTORE: - return POP1; - case Opcodes.LSTORE: - return POP2; - case Opcodes.FSTORE: - return POP1; - case Opcodes.DSTORE: - return POP2; - case Opcodes.ASTORE: - return POP1; - case Opcodes.IASTORE: - return POP3; - case Opcodes.LASTORE: - return POP4; - case Opcodes.FASTORE: - return POP3; - case Opcodes.DASTORE: - return POP4; - case Opcodes.AASTORE: - case Opcodes.BASTORE: - case Opcodes.CASTORE: - case Opcodes.SASTORE: - return POP3; - case Opcodes.POP: - return POP1; - case Opcodes.POP2: - return POP2; - case Opcodes.DUP: - return POP1_PUSH2; - case Opcodes.DUP_X1: - return POP2_PUSH3; - case Opcodes.DUP_X2: - return POP3_PUSH4; - case Opcodes.DUP2: - return POP2_PUSH4; - case Opcodes.DUP2_X1: - return POP3_PUSH5; - case Opcodes.DUP2_X2: - return POP4_PUSH6; - case Opcodes.SWAP: - return POP2_PUSH2; - case Opcodes.IADD: - return POP2_PUSH1; - case Opcodes.LADD: - return POP4_PUSH2; - case Opcodes.FADD: - return POP2_PUSH1; - case Opcodes.DADD: - return POP4_PUSH2; - case Opcodes.ISUB: - return POP2_PUSH1; - case Opcodes.LSUB: - return POP4_PUSH2; - case Opcodes.FSUB: - return POP2_PUSH1; - case Opcodes.DSUB: - return POP4_PUSH2; - case Opcodes.IMUL: - return POP2_PUSH1; - case Opcodes.LMUL: - return POP4_PUSH2; - case Opcodes.FMUL: - return POP2_PUSH1; - case Opcodes.DMUL: - return POP4_PUSH2; - case Opcodes.IDIV: - return POP2_PUSH1; - case Opcodes.LDIV: - return POP4_PUSH2; - case Opcodes.FDIV: - return POP2_PUSH1; - case Opcodes.DDIV: - return POP4_PUSH2; - case Opcodes.IREM: - return POP2_PUSH1; - case Opcodes.LREM: - return POP4_PUSH2; - case Opcodes.FREM: - return POP2_PUSH1; - case Opcodes.DREM: - return POP4_PUSH2; - case Opcodes.INEG: - return POP1_PUSH1; - case Opcodes.LNEG: - return POP2_PUSH2; - case Opcodes.FNEG: - return POP1_PUSH1; - case Opcodes.DNEG: - return POP2_PUSH2; - case Opcodes.ISHL: - return POP2_PUSH1; - case Opcodes.LSHL: - return POP3_PUSH2; - case Opcodes.ISHR: - return POP2_PUSH1; - case Opcodes.LSHR: - return POP3_PUSH2; - case Opcodes.IUSHR: - return POP2_PUSH1; - case Opcodes.LUSHR: - return POP3_PUSH2; - case Opcodes.IAND: - return POP2_PUSH1; - case Opcodes.LAND: - return POP4_PUSH2; - case Opcodes.IOR: - return POP2_PUSH1; - case Opcodes.LOR: - return POP4_PUSH2; - case Opcodes.IXOR: - return POP2_PUSH1; - case Opcodes.LXOR: - return POP4_PUSH2; - case Opcodes.IINC: - return NONE; - case Opcodes.I2L: - return POP1_PUSH2; - case Opcodes.I2F: - return POP1_PUSH1; - case Opcodes.I2D: - return POP1_PUSH2; - case Opcodes.L2I: - return POP2_PUSH1; - case Opcodes.L2F: - return POP2_PUSH1; - case Opcodes.L2D: - return POP2_PUSH2; - case Opcodes.F2I: - return POP1_PUSH1; - case Opcodes.F2L: - return POP1_PUSH2; - case Opcodes.F2D: - return POP1_PUSH2; - case Opcodes.D2I: - return POP2_PUSH1; - case Opcodes.D2L: - return POP2_PUSH2; - case Opcodes.D2F: - return POP2_PUSH1; - case Opcodes.I2B: - case Opcodes.I2C: - case Opcodes.I2S: - return POP1_PUSH1; - case Opcodes.LCMP: - return POP4_PUSH1; - case Opcodes.FCMPL: - case Opcodes.FCMPG: - return POP2_PUSH1; - case Opcodes.DCMPL: - case Opcodes.DCMPG: - return POP4_PUSH1; - case Opcodes.IFEQ: - case Opcodes.IFNE: - case Opcodes.IFLT: - case Opcodes.IFGE: - case Opcodes.IFGT: - case Opcodes.IFLE: - return POP1; - case Opcodes.IF_ICMPEQ: - case Opcodes.IF_ICMPNE: - case Opcodes.IF_ICMPLT: - case Opcodes.IF_ICMPGE: - case Opcodes.IF_ICMPGT: - case Opcodes.IF_ICMPLE: - case Opcodes.IF_ACMPEQ: - case Opcodes.IF_ACMPNE: - return POP2; - case Opcodes.GOTO: - return NONE; - case Opcodes.JSR: - return PUSH1; - case Opcodes.RET: - return NONE; - case Opcodes.TABLESWITCH: - case Opcodes.LOOKUPSWITCH: - return POP1; - case Opcodes.IRETURN: - return POP1; - case Opcodes.LRETURN: - return POP2; - case Opcodes.FRETURN: - return POP1; - case Opcodes.DRETURN: - return POP2; - case Opcodes.ARETURN: - return POP1; - case Opcodes.RETURN: - return NONE; - case Opcodes.GETSTATIC: - case Opcodes.PUTSTATIC: - case Opcodes.GETFIELD: - case Opcodes.PUTFIELD: - var fieldInsn = (FieldInsnNode) insn; - var fieldSize = Type.getType(fieldInsn.desc).getSize(); - - int pushes = 0, pops = 0; - - if (opcode == Opcodes.GETFIELD || opcode == Opcodes.PUTFIELD) { - pops++; - } - - if (opcode == Opcodes.PUTFIELD || opcode == Opcodes.PUTSTATIC) { - pushes += fieldSize; - } else { - pops += fieldSize; - } - - return new StackMetadata(pops, pushes); - case Opcodes.INVOKEVIRTUAL: - case Opcodes.INVOKESPECIAL: - case Opcodes.INVOKESTATIC: - case Opcodes.INVOKEINTERFACE: - var methodInsn = (MethodInsnNode) insn; - var argumentsAndReturnSizes = Type.getArgumentsAndReturnSizes(methodInsn.desc); - - pushes = argumentsAndReturnSizes >> 2; - pops = argumentsAndReturnSizes & 0x3; - - if (opcode != Opcodes.INVOKESTATIC) { - pops++; - } - - return new StackMetadata(pops, pushes); - case Opcodes.INVOKEDYNAMIC: - throw new UnsupportedOperationException(); - case Opcodes.NEW: - return POP1; - case Opcodes.NEWARRAY: - case Opcodes.ANEWARRAY: - case Opcodes.ARRAYLENGTH: - return POP1_PUSH1; - case Opcodes.ATHROW: - return POP1; - case Opcodes.CHECKCAST: - case Opcodes.INSTANCEOF: - return POP1_PUSH1; - case Opcodes.MONITORENTER: - case Opcodes.MONITOREXIT: - return POP1; - case Opcodes.MULTIANEWARRAY: - return new StackMetadata(((MultiANewArrayInsnNode) insn).dims, 1); - case Opcodes.IFNULL: - case Opcodes.IFNONNULL: - return POP1; - } - - throw new IllegalArgumentException(); - } - - private final int pops, pushes; - - private StackMetadata(int pops, int pushes) { - this.pops = pops; - this.pushes = pushes; - } - - public int getPops() { - return pops; - } - - public int getPushes() { - return pushes; - } -} diff --git a/asm/src/main/java/dev/openrs2/asm/StackMetadata.kt b/asm/src/main/java/dev/openrs2/asm/StackMetadata.kt new file mode 100644 index 00000000..e6d9e64c --- /dev/null +++ b/asm/src/main/java/dev/openrs2/asm/StackMetadata.kt @@ -0,0 +1,211 @@ +package dev.openrs2.asm + +import org.objectweb.asm.Opcodes +import org.objectweb.asm.Type +import org.objectweb.asm.tree.* + +data class StackMetadata(val pops: Int, val pushes: Int) + +private val NONE = StackMetadata(0, 0) +private val POP1 = StackMetadata(1, 0) +private val POP1_PUSH1 = StackMetadata(1, 1) +private val POP1_PUSH2 = StackMetadata(1, 2) +private val POP2 = StackMetadata(2, 0) +private val POP2_PUSH1 = StackMetadata(2, 1) +private val POP2_PUSH2 = StackMetadata(2, 2) +private val POP2_PUSH3 = StackMetadata(2, 3) +private val POP2_PUSH4 = StackMetadata(2, 4) +private val POP3 = StackMetadata(3, 0) +private val POP3_PUSH2 = StackMetadata(3, 2) +private val POP3_PUSH4 = StackMetadata(3, 4) +private val POP3_PUSH5 = StackMetadata(3, 5) +private val POP4 = StackMetadata(4, 0) +private val POP4_PUSH1 = StackMetadata(4, 1) +private val POP4_PUSH2 = StackMetadata(4, 2) +private val POP4_PUSH6 = StackMetadata(4, 6) +private val PUSH1 = StackMetadata(0, 1) +private val PUSH2 = StackMetadata(0, 2) + +private val SIMPLE_OPCODES = mapOf( + -1 to NONE, + Opcodes.NOP to NONE, + Opcodes.ACONST_NULL to PUSH1, + Opcodes.ICONST_M1 to PUSH1, + Opcodes.ICONST_0 to PUSH1, + Opcodes.ICONST_1 to PUSH1, + Opcodes.ICONST_2 to PUSH1, + Opcodes.ICONST_3 to PUSH1, + Opcodes.ICONST_4 to PUSH1, + Opcodes.ICONST_5 to PUSH1, + Opcodes.LCONST_0 to PUSH2, + Opcodes.LCONST_1 to PUSH2, + Opcodes.FCONST_0 to PUSH1, + Opcodes.FCONST_1 to PUSH1, + Opcodes.FCONST_2 to PUSH1, + Opcodes.DCONST_0 to PUSH2, + Opcodes.DCONST_1 to PUSH2, + Opcodes.BIPUSH to PUSH1, + Opcodes.SIPUSH to PUSH1, + Opcodes.ILOAD to PUSH1, + Opcodes.LLOAD to PUSH2, + Opcodes.FLOAD to PUSH1, + Opcodes.DLOAD to PUSH2, + Opcodes.ALOAD to PUSH1, + Opcodes.IALOAD to POP2_PUSH1, + Opcodes.LALOAD to POP2_PUSH2, + Opcodes.FALOAD to POP2_PUSH1, + Opcodes.DALOAD to POP2_PUSH2, + Opcodes.AALOAD to POP2_PUSH1, + Opcodes.BALOAD to POP2_PUSH1, + Opcodes.CALOAD to POP2_PUSH1, + Opcodes.SALOAD to POP2_PUSH1, + Opcodes.ISTORE to POP1, + Opcodes.LSTORE to POP2, + Opcodes.FSTORE to POP1, + Opcodes.DSTORE to POP2, + Opcodes.ASTORE to POP1, + Opcodes.IASTORE to POP3, + Opcodes.LASTORE to POP4, + Opcodes.FASTORE to POP3, + Opcodes.DASTORE to POP4, + Opcodes.AASTORE to POP3, + Opcodes.BASTORE to POP3, + Opcodes.CASTORE to POP3, + Opcodes.SASTORE to POP3, + Opcodes.POP to POP1, + Opcodes.POP2 to POP2, + Opcodes.DUP to POP1_PUSH2, + Opcodes.DUP_X1 to POP2_PUSH3, + Opcodes.DUP_X2 to POP3_PUSH4, + Opcodes.DUP2 to POP2_PUSH4, + Opcodes.DUP2_X1 to POP3_PUSH5, + Opcodes.DUP2_X2 to POP4_PUSH6, + Opcodes.SWAP to POP2_PUSH2, + Opcodes.IADD to POP2_PUSH1, + Opcodes.LADD to POP4_PUSH2, + Opcodes.FADD to POP2_PUSH1, + Opcodes.DADD to POP4_PUSH2, + Opcodes.ISUB to POP2_PUSH1, + Opcodes.LSUB to POP4_PUSH2, + Opcodes.FSUB to POP2_PUSH1, + Opcodes.DSUB to POP4_PUSH2, + Opcodes.IMUL to POP2_PUSH1, + Opcodes.LMUL to POP4_PUSH2, + Opcodes.FMUL to POP2_PUSH1, + Opcodes.DMUL to POP4_PUSH2, + Opcodes.IDIV to POP2_PUSH1, + Opcodes.LDIV to POP4_PUSH2, + Opcodes.FDIV to POP2_PUSH1, + Opcodes.DDIV to POP4_PUSH2, + Opcodes.IREM to POP2_PUSH1, + Opcodes.LREM to POP4_PUSH2, + Opcodes.FREM to POP2_PUSH1, + Opcodes.DREM to POP4_PUSH2, + Opcodes.INEG to POP1_PUSH1, + Opcodes.LNEG to POP2_PUSH2, + Opcodes.FNEG to POP1_PUSH1, + Opcodes.DNEG to POP2_PUSH2, + Opcodes.ISHL to POP2_PUSH1, + Opcodes.LSHL to POP3_PUSH2, + Opcodes.ISHR to POP2_PUSH1, + Opcodes.LSHR to POP3_PUSH2, + Opcodes.IUSHR to POP2_PUSH1, + Opcodes.LUSHR to POP3_PUSH2, + Opcodes.IAND to POP2_PUSH1, + Opcodes.LAND to POP4_PUSH2, + Opcodes.IOR to POP2_PUSH1, + Opcodes.LOR to POP4_PUSH2, + Opcodes.IXOR to POP2_PUSH1, + Opcodes.LXOR to POP4_PUSH2, + Opcodes.IINC to NONE, + Opcodes.I2L to POP1_PUSH2, + Opcodes.I2F to POP1_PUSH1, + Opcodes.I2D to POP1_PUSH2, + Opcodes.L2I to POP2_PUSH1, + Opcodes.L2F to POP2_PUSH1, + Opcodes.L2D to POP2_PUSH2, + Opcodes.F2I to POP1_PUSH1, + Opcodes.F2L to POP1_PUSH2, + Opcodes.F2D to POP1_PUSH2, + Opcodes.D2I to POP2_PUSH1, + Opcodes.D2L to POP2_PUSH2, + Opcodes.D2F to POP2_PUSH1, + Opcodes.I2B to POP1_PUSH1, + Opcodes.I2C to POP1_PUSH1, + Opcodes.I2S to POP1_PUSH1, + Opcodes.LCMP to POP4_PUSH1, + Opcodes.FCMPL to POP2_PUSH1, + Opcodes.FCMPG to POP2_PUSH1, + Opcodes.DCMPL to POP4_PUSH1, + Opcodes.DCMPG to POP4_PUSH1, + Opcodes.IFEQ to POP1, + Opcodes.IFNE to POP1, + Opcodes.IFLT to POP1, + Opcodes.IFGE to POP1, + Opcodes.IFGT to POP1, + Opcodes.IFLE to POP1, + Opcodes.IF_ICMPEQ to POP2, + Opcodes.IF_ICMPNE to POP2, + Opcodes.IF_ICMPLT to POP2, + Opcodes.IF_ICMPGE to POP2, + Opcodes.IF_ICMPGT to POP2, + Opcodes.IF_ICMPLE to POP2, + Opcodes.IF_ACMPEQ to POP2, + Opcodes.IF_ACMPNE to POP2, + Opcodes.GOTO to NONE, + Opcodes.JSR to PUSH1, + Opcodes.RET to NONE, + Opcodes.TABLESWITCH to POP1, + Opcodes.LOOKUPSWITCH to POP1, + Opcodes.IRETURN to POP1, + Opcodes.LRETURN to POP2, + Opcodes.FRETURN to POP1, + Opcodes.DRETURN to POP2, + Opcodes.ARETURN to POP1, + Opcodes.RETURN to NONE, + Opcodes.NEW to POP1, + Opcodes.NEWARRAY to POP1_PUSH1, + Opcodes.ANEWARRAY to POP1_PUSH1, + Opcodes.ARRAYLENGTH to POP1_PUSH1, + Opcodes.ATHROW to POP1, + Opcodes.CHECKCAST to POP1_PUSH1, + Opcodes.INSTANCEOF to POP1_PUSH1, + Opcodes.MONITORENTER to POP1, + Opcodes.MONITOREXIT to POP1, + Opcodes.IFNULL to POP1, + Opcodes.IFNONNULL to POP1 +) + +fun AbstractInsnNode.stackMetadata(): StackMetadata = when (this) { + is LdcInsnNode -> if (cst is Double || cst is Long) { + PUSH2 + } else { + PUSH1 + } + is FieldInsnNode -> { + val fieldSize = Type.getType(desc).size + var pushes = 0 + var pops = 0 + if (opcode == Opcodes.GETFIELD || opcode == Opcodes.PUTFIELD) { + pops++ + } + if (opcode == Opcodes.PUTFIELD || opcode == Opcodes.PUTSTATIC) { + pushes += fieldSize + } else { + pops += fieldSize + } + StackMetadata(pops, pushes) + } + is MethodInsnNode -> { + val argumentsAndReturnSizes = Type.getArgumentsAndReturnSizes(desc) + val pushes = argumentsAndReturnSizes shr 2 + var pops = argumentsAndReturnSizes and 0x3 + if (opcode != Opcodes.INVOKESTATIC) { + pops++ + } + StackMetadata(pops, pushes) + } + is InvokeDynamicInsnNode -> throw UnsupportedOperationException() + is MultiANewArrayInsnNode -> StackMetadata(dims, 1) + else -> SIMPLE_OPCODES[opcode] ?: throw IllegalArgumentException() +} diff --git a/deob/src/main/java/dev/openrs2/deob/transform/DummyArgTransformer.java b/deob/src/main/java/dev/openrs2/deob/transform/DummyArgTransformer.java index a5f10677..7a37b7cf 100644 --- a/deob/src/main/java/dev/openrs2/deob/transform/DummyArgTransformer.java +++ b/deob/src/main/java/dev/openrs2/deob/transform/DummyArgTransformer.java @@ -14,7 +14,7 @@ import com.google.common.collect.Multimap; import dev.openrs2.asm.InsnMatcher; import dev.openrs2.asm.InsnNodeUtils; import dev.openrs2.asm.MemberRef; -import dev.openrs2.asm.StackMetadata; +import dev.openrs2.asm.StackMetadataKt; import dev.openrs2.asm.classpath.ClassPath; import dev.openrs2.asm.classpath.Library; import dev.openrs2.asm.transform.Transformer; @@ -390,7 +390,7 @@ public final class DummyArgTransformer extends Transformer { continue; } - if (StackMetadata.get(insn).getPushes() != 1) { + if (StackMetadataKt.stackMetadata(insn).getPushes() != 1) { continue; }