Convert StackMetadata to Kotlin

pull/48/head
Graham 4 years ago
parent c02fe030fa
commit e68fed7a9e
  1. 2
      asm/src/main/java/dev/openrs2/asm/InsnNodeUtils.java
  2. 353
      asm/src/main/java/dev/openrs2/asm/StackMetadata.java
  3. 211
      asm/src/main/java/dev/openrs2/asm/StackMetadata.kt
  4. 4
      deob/src/main/java/dev/openrs2/deob/transform/DummyArgTransformer.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();

@ -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;
}
}

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

@ -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;
}

Loading…
Cancel
Save