JVM skip methods without NEW insns in UninitializedStoresProcessor

This commit is contained in:
Dmitry Petrov
2021-07-22 08:23:38 +03:00
committed by teamcityserver
parent eff7c375ce
commit 6c734289be
@@ -73,8 +73,8 @@ import kotlin.math.max
* - restore constructor arguments * - restore constructor arguments
*/ */
class UninitializedStoresProcessor( class UninitializedStoresProcessor(
private val methodNode: MethodNode, private val methodNode: MethodNode,
private val shouldPreserveClassInitialization: Boolean private val shouldPreserveClassInitialization: Boolean
) { ) {
// <init> method is "special", because it will invoke <init> from this class or from a base class for #0 // <init> method is "special", because it will invoke <init> from this class or from a base class for #0
// //
@@ -87,10 +87,10 @@ class UninitializedStoresProcessor(
fun run() { fun run() {
val interpreter = UninitializedNewValueMarkerInterpreter(methodNode.instructions) val interpreter = UninitializedNewValueMarkerInterpreter(methodNode.instructions)
val frames = CustomFramesMethodAnalyzer( if (methodNode.instructions.toArray().none { it.opcode == Opcodes.NEW })
"fake", methodNode, interpreter, return
this::UninitializedNewValueFrame
).analyze() val frames = CustomFramesMethodAnalyzer("fake", methodNode, interpreter, this::UninitializedNewValueFrame).analyze()
interpreter.analyzePopInstructions(frames) interpreter.analyzePopInstructions(frames)
@@ -115,12 +115,12 @@ class UninitializedStoresProcessor(
// POP // POP
val typeNameForClass = newInsn.desc.replace('/', '.') val typeNameForClass = newInsn.desc.replace('/', '.')
insertBefore(newInsn, LdcInsnNode(typeNameForClass)) insertBefore(newInsn, LdcInsnNode(typeNameForClass))
insertBefore(newInsn, MethodInsnNode( insertBefore(
Opcodes.INVOKESTATIC, "java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false newInsn,
)) MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false)
)
set(newInsn, InsnNode(Opcodes.POP)) set(newInsn, InsnNode(Opcodes.POP))
} } else {
else {
remove(newInsn) remove(newInsn)
} }
} }
@@ -138,10 +138,7 @@ class UninitializedStoresProcessor(
} }
methodNode.maxLocals = max(methodNode.maxLocals, nextVarIndex) methodNode.maxLocals = max(methodNode.maxLocals, nextVarIndex)
methodNode.instructions.insertBefore(insn, insnListOf( methodNode.instructions.insertBefore(insn, insnListOf(TypeInsnNode(Opcodes.NEW, newInsn.desc), InsnNode(Opcodes.DUP)))
TypeInsnNode(Opcodes.NEW, newInsn.desc),
InsnNode(Opcodes.DUP)
))
for (type in storedTypes.reversed()) { for (type in storedTypes.reversed()) {
nextVarIndex -= type.size nextVarIndex -= type.size
@@ -174,11 +171,11 @@ class UninitializedStoresProcessor(
assert(insn.opcode == Opcodes.INVOKESPECIAL) { "Expected opcode Opcodes.INVOKESPECIAL for <init>, but ${insn.opcode} found" } assert(insn.opcode == Opcodes.INVOKESPECIAL) { "Expected opcode Opcodes.INVOKESPECIAL for <init>, but ${insn.opcode} found" }
val paramsCountIncludingReceiver = Type.getArgumentTypes((insn as MethodInsnNode).desc).size + 1 val paramsCountIncludingReceiver = Type.getArgumentTypes((insn as MethodInsnNode).desc).size + 1
val newValue = peek(paramsCountIncludingReceiver) as? UninitializedNewValue ?: val newValue = peek(paramsCountIncludingReceiver) as? UninitializedNewValue
if (isInSpecialMethod) ?: if (isInSpecialMethod)
return null return null
else else
error("Expected value generated with NEW") error("Expected value generated with NEW")
assert(peek(paramsCountIncludingReceiver - 1) is UninitializedNewValue) { assert(peek(paramsCountIncludingReceiver - 1) is UninitializedNewValue) {
"Next value after NEW should be one generated by DUP" "Next value after NEW should be one generated by DUP"
@@ -188,8 +185,8 @@ class UninitializedStoresProcessor(
} }
private class UninitializedNewValue( private class UninitializedNewValue(
val newInsn: TypeInsnNode, val newInsn: TypeInsnNode,
val internalName: String val internalName: String
) : StrictBasicValue(Type.getObjectType(internalName)) { ) : StrictBasicValue(Type.getObjectType(internalName)) {
override fun toString() = "UninitializedNewValue(internalName='$internalName')" override fun toString() = "UninitializedNewValue(internalName='$internalName')"
} }
@@ -236,7 +233,8 @@ class UninitializedStoresProcessor(
private fun checkUninitializedObjectCopy(newInsn: TypeInsnNode, usageInsn: AbstractInsnNode) { private fun checkUninitializedObjectCopy(newInsn: TypeInsnNode, usageInsn: AbstractInsnNode) {
when (usageInsn.opcode) { when (usageInsn.opcode) {
Opcodes.DUP, Opcodes.ASTORE, Opcodes.ALOAD -> {} Opcodes.DUP, Opcodes.ASTORE, Opcodes.ALOAD -> {
}
else -> error("Unexpected copy instruction for ${newInsn.debugText}: ${usageInsn.debugText}") else -> error("Unexpected copy instruction for ${newInsn.debugText}: ${usageInsn.debugText}")
} }
} }