package org.openrs2.bundler.transform import com.github.michaelbull.logging.InlineLogger import org.objectweb.asm.tree.ClassNode import org.objectweb.asm.tree.FieldInsnNode import org.objectweb.asm.tree.LdcInsnNode import org.objectweb.asm.tree.MethodNode import org.openrs2.asm.InsnMatcher import org.openrs2.asm.MemberRef import org.openrs2.asm.classpath.ClassPath import org.openrs2.asm.classpath.Library import org.openrs2.asm.hasCode import org.openrs2.asm.toAbstractInsnNode import org.openrs2.asm.transform.Transformer import javax.inject.Singleton @Singleton public class BufferSizeTransformer : Transformer() { private var buffer: MemberRef? = null private var buffersResized = 0 override fun preTransform(classPath: ClassPath) { buffer = null buffersResized = 0 for (library in classPath.libraries) { for (clazz in library) { for (method in clazz.methods) { if (!method.hasCode) { continue } this.buffer = findBuffer(method) ?: continue logger.info { "Identified buffer ${this.buffer}" } break } } } } override fun transformCode(classPath: ClassPath, library: Library, clazz: ClassNode, method: MethodNode): Boolean { if (buffer == null) { return false } for (match in NEW_BUFFER_MATCHER.match(method)) { val putstatic = match[4] as FieldInsnNode if (MemberRef(putstatic) == buffer!!) { method.instructions[match[2]] = 65536.toAbstractInsnNode() buffersResized++ } } return false } override fun postTransform(classPath: ClassPath) { logger.info { "Resized $buffersResized buffers to 65536 bytes" } } private companion object { private val logger = InlineLogger() private val GPP1_POS_MATCHER = InsnMatcher.compile("LDC (INVOKESPECIAL | INVOKEVIRTUAL) GETSTATIC") private val NEW_BUFFER_MATCHER = InsnMatcher.compile("NEW DUP (SIPUSH | LDC) INVOKESPECIAL PUTSTATIC") private fun findBuffer(method: MethodNode): MemberRef? { return GPP1_POS_MATCHER.match(method).filter { val ldc = it[0] as LdcInsnNode ldc.cst == "gpp1 pos:" }.map { val getstatic = it[2] as FieldInsnNode MemberRef(getstatic) }.firstOrNull() } } }