JVM_IR KT-47984 allow only limited list of GETSTATICs in arg loading
This commit is contained in:
committed by
TeamCityServer
parent
32c51cbb45
commit
55663a0fb1
@@ -10,10 +10,7 @@ import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
|||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
import org.jetbrains.org.objectweb.asm.tree.*
|
||||||
import org.jetbrains.org.objectweb.asm.tree.IincInsnNode
|
|
||||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
|
||||||
import org.jetbrains.org.objectweb.asm.tree.VarInsnNode
|
|
||||||
|
|
||||||
|
|
||||||
fun canInlineArgumentsInPlace(methodNode: MethodNode): Boolean {
|
fun canInlineArgumentsInPlace(methodNode: MethodNode): Boolean {
|
||||||
@@ -45,8 +42,8 @@ fun canInlineArgumentsInPlace(methodNode: MethodNode): Boolean {
|
|||||||
// GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
|
// GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
|
||||||
// LDC "Hello, world!"
|
// LDC "Hello, world!"
|
||||||
// INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
|
// INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
|
||||||
// Such inlining is possible because we consider it OK to reorder GETSTATIC instruction with any argument evaluation instructions
|
// Such inlining is possible because we consider it OK to reorder 'GETSTATIC java/lang/System.out : Ljava/io/PrintStream;' instruction
|
||||||
// ('LDC "Hello, world!"' in this case).
|
// with any argument evaluation instructions ('LDC "Hello, world!"' in this case).
|
||||||
|
|
||||||
val tcbStartLabels = methodNode.tryCatchBlocks.mapTo(HashSet()) { it.start }
|
val tcbStartLabels = methodNode.tryCatchBlocks.mapTo(HashSet()) { it.start }
|
||||||
|
|
||||||
@@ -77,6 +74,14 @@ fun canInlineArgumentsInPlace(methodNode: MethodNode): Boolean {
|
|||||||
if (insn.isProhibitedDuringArgumentsEvaluation())
|
if (insn.isProhibitedDuringArgumentsEvaluation())
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
// Allow a limited list of 'GETSTATIC <owner> <name> <desc>' instructions.
|
||||||
|
if (insn.opcode == Opcodes.GETSTATIC) {
|
||||||
|
val fieldInsn = insn as FieldInsnNode
|
||||||
|
val fieldSignature = FieldSignature(fieldInsn.owner, fieldInsn.name, fieldInsn.desc)
|
||||||
|
if (fieldSignature !in whitelistedStaticFields)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// Writing to or incrementing an argument variable forbids in-place argument inlining.
|
// Writing to or incrementing an argument variable forbids in-place argument inlining.
|
||||||
if (insn.opcode in Opcodes.ISTORE..Opcodes.ASTORE && (insn as VarInsnNode).`var` < argumentVarEnd)
|
if (insn.opcode in Opcodes.ISTORE..Opcodes.ASTORE && (insn as VarInsnNode).`var` < argumentVarEnd)
|
||||||
return false
|
return false
|
||||||
@@ -139,6 +144,18 @@ fun canInlineArgumentsInPlace(methodNode: MethodNode): Boolean {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal data class FieldSignature(
|
||||||
|
val owner: String,
|
||||||
|
val name: String,
|
||||||
|
val desc: String
|
||||||
|
)
|
||||||
|
|
||||||
|
private val whitelistedStaticFields: Set<FieldSignature> =
|
||||||
|
hashSetOf(
|
||||||
|
FieldSignature("java/lang/System", "out", "Ljava/io/PrintStream;"),
|
||||||
|
FieldSignature("kotlin/Result", "Companion", "Lkotlin/Result\$Companion;"),
|
||||||
|
FieldSignature("kotlin/_Assertions", "ENABLED", "Z")
|
||||||
|
)
|
||||||
|
|
||||||
private fun AbstractInsnNode.isProhibitedDuringArgumentsEvaluation() =
|
private fun AbstractInsnNode.isProhibitedDuringArgumentsEvaluation() =
|
||||||
opcode in opcodeProhibitedDuringArgumentsEvaluation.indices &&
|
opcode in opcodeProhibitedDuringArgumentsEvaluation.indices &&
|
||||||
@@ -154,7 +171,7 @@ private val opcodeProhibitedDuringArgumentsEvaluation = BooleanArray(256).also {
|
|||||||
a[Opcodes.ATHROW] = true
|
a[Opcodes.ATHROW] = true
|
||||||
|
|
||||||
// Instruction with non-trivial side effects is a hazard.
|
// Instruction with non-trivial side effects is a hazard.
|
||||||
// NB here we don't care about possible class initialization caused by GETSTATIC.
|
// NB GETSTATIC is taken care of separately.
|
||||||
a[Opcodes.PUTSTATIC] = true
|
a[Opcodes.PUTSTATIC] = true
|
||||||
a[Opcodes.PUTFIELD] = true
|
a[Opcodes.PUTFIELD] = true
|
||||||
a[Opcodes.INVOKEVIRTUAL] = true
|
a[Opcodes.INVOKEVIRTUAL] = true
|
||||||
|
|||||||
Reference in New Issue
Block a user