[JVM] Replace AbstractInsnNode.getType with new util function

This change speeds up backend by approximately 0.96%.
This commit is contained in:
Ivan Kylchik
2023-08-23 15:55:56 +02:00
committed by Space Team
parent 67460962c3
commit a30d0aeeb0
11 changed files with 61 additions and 20 deletions
@@ -647,7 +647,7 @@ class MethodInliner(
} else {
//given frame is <tt>null</tt> if and only if the corresponding instruction cannot be reached (dead code).
//clean dead code otherwise there is problems in unreachable finally block, don't touch label it cause try/catch/finally problems
if (cur.type == AbstractInsnNode.LABEL) {
if (cur.nodeType == AbstractInsnNode.LABEL) {
//NB: Cause we generate exception table for default handler using gaps (see ExpressionCodegen.visitTryExpression)
//it may occurs that interval for default handler starts before catch start label, so this label seems as dead,
//but as result all this labels will be merged into one (see KT-5863)
@@ -856,9 +856,9 @@ class MethodInliner(
// - there's a local variable table entry for this variable
val usedIntegerVar = BooleanArray(node.maxLocals)
for (insn in insnArray) {
if (insn.type == AbstractInsnNode.VAR_INSN && insn.opcode == Opcodes.ILOAD) {
if (insn.nodeType == AbstractInsnNode.VAR_INSN && insn.opcode == Opcodes.ILOAD) {
usedIntegerVar[(insn as VarInsnNode).`var`] = true
} else if (insn.type == AbstractInsnNode.IINC_INSN) {
} else if (insn.nodeType == AbstractInsnNode.IINC_INSN) {
usedIntegerVar[(insn as IincInsnNode).`var`] = true
}
}
@@ -883,7 +883,7 @@ class MethodInliner(
if (p1.opcode != Opcodes.ISTORE) continue
val p2 = p1.next ?: break
if (p2.type != AbstractInsnNode.LABEL) continue
if (p2.nodeType != AbstractInsnNode.LABEL) continue
val varIndex = (p1 as VarInsnNode).`var`
if (!usedIntegerVar[varIndex]) {
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspend
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
import org.jetbrains.kotlin.codegen.optimization.common.intConstant
import org.jetbrains.kotlin.codegen.optimization.common.nodeType
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapperBase
@@ -375,7 +376,7 @@ fun MethodNode.dumpBody(): String {
}
for ((i, insn) in this.instructions.toArray().withIndex()) {
when (insn.type) {
when (insn.nodeType) {
AbstractInsnNode.INSN ->
pw.println("$i\t${Printer.OPCODES[insn.opcode]}")
AbstractInsnNode.INT_INSN ->
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.codegen.optimization
import org.jetbrains.kotlin.codegen.optimization.common.nodeType
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
@@ -23,7 +24,7 @@ class NegatedJumpsMethodTransformer : MethodTransformer() {
// IF_ICMPGE L2 = negatedJumpInsn
// L1: = next2
for (insn in insnList.toArray()) {
if (insn.type != AbstractInsnNode.JUMP_INSN || insn.opcode == Opcodes.GOTO) continue
if (insn.nodeType != AbstractInsnNode.JUMP_INSN || insn.opcode == Opcodes.GOTO) continue
val next1 = insn.next ?: continue
if (next1.opcode != Opcodes.GOTO) continue
val next2 = next1.next ?: continue
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.codegen.optimization.boxing.PopBackwardPropagationTr
import org.jetbrains.kotlin.codegen.optimization.boxing.RedundantBoxingMethodTransformer
import org.jetbrains.kotlin.codegen.optimization.boxing.StackPeepholeOptimizationsTransformer
import org.jetbrains.kotlin.codegen.optimization.common.prepareForEmitting
import org.jetbrains.kotlin.codegen.optimization.common.nodeType
import org.jetbrains.kotlin.codegen.optimization.nullCheck.RedundantNullCheckMethodTransformer
import org.jetbrains.kotlin.codegen.optimization.temporaryVals.TemporaryVariablesEliminationTransformer
import org.jetbrains.kotlin.codegen.optimization.transformer.CompositeMethodTransformer
@@ -107,8 +108,9 @@ class OptimizationMethodVisitor(
// by anything other than a jump-targeted label, so those instructions consume no extra memory.
// To avoid checking all jumps, here we assume all labels are potentially targeted.
// (Effectively, all of this means that adding line numbers should not inhibit optimization.)
if ((it.type != AbstractInsnNode.LINE && it.type != AbstractInsnNode.FRAME && it.type != AbstractInsnNode.LABEL &&
it.opcode != Opcodes.NOP) || it.next?.type == AbstractInsnNode.LABEL
val type = it.nodeType
if ((type != AbstractInsnNode.LINE && type != AbstractInsnNode.FRAME && type != AbstractInsnNode.LABEL &&
it.opcode != Opcodes.NOP) || it.next?.nodeType == AbstractInsnNode.LABEL
) result++
it = it.next
}
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.codegen.optimization.boxing
import org.jetbrains.kotlin.codegen.optimization.common.FastAnalyzer
import org.jetbrains.kotlin.codegen.optimization.common.findPreviousOrNull
import org.jetbrains.kotlin.codegen.optimization.common.nodeType
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
@@ -40,8 +41,8 @@ class StackPeepholeOptimizationsTransformer : MethodTransformer() {
fun AbstractInsnNode.previousMeaningful() =
findPreviousOrNull {
it.opcode != Opcodes.NOP && it.type != AbstractInsnNode.LINE &&
(it.type != AbstractInsnNode.LABEL || isMergeNode[instructions.indexOf(it)])
it.opcode != Opcodes.NOP && it.nodeType != AbstractInsnNode.LINE &&
(it.nodeType != AbstractInsnNode.LABEL || isMergeNode[instructions.indexOf(it)])
}
var insn: AbstractInsnNode?
@@ -60,7 +60,7 @@ class ControlFlowGraph private constructor(private val insns: InsnList) {
val insnNode = method.instructions[insn]
val insnOpcode = insnNode.opcode
when (insnNode.type) {
when (insnNode.nodeType) {
AbstractInsnNode.LABEL, AbstractInsnNode.LINE, AbstractInsnNode.FRAME ->
visitOpInsn(insn)
AbstractInsnNode.JUMP_INSN ->
@@ -96,7 +96,7 @@ abstract class FastAnalyzer<V : Value, F : Frame<V>>(
handler: F
) {
val insnOpcode = insnNode.opcode
val insnType = insnNode.type
val insnType = insnNode.nodeType
if (insnType == AbstractInsnNode.LABEL ||
insnType == AbstractInsnNode.LINE ||
@@ -349,7 +349,7 @@ abstract class FastAnalyzer<V : Value, F : Frame<V>>(
fun findMergeNodes(method: MethodNode): BooleanArray {
val isMergeNode = BooleanArray(method.instructions.size())
for (insn in method.instructions) {
when (insn.type) {
when (insn.nodeType) {
AbstractInsnNode.JUMP_INSN -> {
val jumpInsn = insn as JumpInsnNode
isMergeNode[method.instructions.indexOf(jumpInsn.label)] = true
@@ -79,7 +79,7 @@ class InstructionLivenessAnalyzer(
val insnNode = method.instructions[insn]
val insnOpcode = insnNode.opcode
when (insnNode.type) {
when (insnNode.nodeType) {
AbstractInsnNode.LABEL, AbstractInsnNode.LINE, AbstractInsnNode.FRAME ->
visitOpInsn(insn)
AbstractInsnNode.JUMP_INSN ->
@@ -27,14 +27,14 @@ import org.jetbrains.org.objectweb.asm.tree.*
val AbstractInsnNode.isMeaningful: Boolean
get() =
when (this.type) {
when (this.nodeType) {
AbstractInsnNode.LABEL, AbstractInsnNode.LINE, AbstractInsnNode.FRAME -> false
else -> true
}
val AbstractInsnNode.isBranchOrCall: Boolean
get() =
when (this.type) {
when (this.nodeType) {
AbstractInsnNode.JUMP_INSN,
AbstractInsnNode.TABLESWITCH_INSN,
AbstractInsnNode.LOOKUPSWITCH_INSN,
@@ -42,6 +42,40 @@ val AbstractInsnNode.isBranchOrCall: Boolean
else -> false
}
private val opcodeToNodeType = IntArray(IFNONNULL + 1) {
when (it) {
in NOP..DCONST_1, in IALOAD..SALOAD, in IASTORE..LXOR, in I2L..DCMPG, in IRETURN..RETURN,
ARRAYLENGTH, ATHROW, MONITORENTER, MONITOREXIT -> AbstractInsnNode.INSN
in BIPUSH..SIPUSH, NEWARRAY -> AbstractInsnNode.INT_INSN
in ILOAD..ALOAD, in ISTORE..ASTORE, RET -> AbstractInsnNode.VAR_INSN
NEW, ANEWARRAY, CHECKCAST, INSTANCEOF -> AbstractInsnNode.TYPE_INSN
in GETSTATIC..PUTFIELD -> AbstractInsnNode.FIELD_INSN
in INVOKEVIRTUAL..INVOKEINTERFACE -> AbstractInsnNode.METHOD_INSN
INVOKEDYNAMIC -> AbstractInsnNode.INVOKE_DYNAMIC_INSN
in IFEQ..JSR, IFNULL, IFNONNULL -> AbstractInsnNode.JUMP_INSN
LDC -> AbstractInsnNode.LDC_INSN
IINC -> AbstractInsnNode.IINC_INSN
TABLESWITCH -> AbstractInsnNode.TABLESWITCH_INSN
LOOKUPSWITCH -> AbstractInsnNode.LOOKUPSWITCH_INSN
MULTIANEWARRAY -> AbstractInsnNode.MULTIANEWARRAY_INSN
else -> -1
}
}
// Faster version of `AbstractInsnNode.getType`
val AbstractInsnNode.nodeType: Int
get() {
return when (val opcode = this.opcode) {
-1 -> when (this) {
is LabelNode -> AbstractInsnNode.LABEL
is FrameNode -> AbstractInsnNode.FRAME
is LineNumberNode -> AbstractInsnNode.LINE
else -> -1
}
else -> opcodeToNodeType.getOrElse(opcode) { -1 }
}
}
class InsnSequence(val from: AbstractInsnNode, val to: AbstractInsnNode?) : Sequence<AbstractInsnNode> {
constructor(insnList: InsnList) : this(insnList.first, null)
@@ -77,7 +111,7 @@ fun MethodNode.prepareForEmitting() {
while (!current.isMeaningful) {
val prev = current.previous
if (current.type == AbstractInsnNode.LINE) {
if (current.nodeType == AbstractInsnNode.LINE) {
instructions.remove(current)
}
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.codegen.optimization.temporaryVals
import org.jetbrains.kotlin.codegen.optimization.OptimizationMethodVisitor
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
import org.jetbrains.kotlin.codegen.optimization.common.isStoreOperation
import org.jetbrains.kotlin.codegen.optimization.common.nodeType
import org.jetbrains.kotlin.utils.SmartSet
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Opcodes.API_VERSION
@@ -53,7 +54,7 @@ class TemporaryValsAnalyzer {
potentiallyTemporaryStores.remove(p)
break
} else if (
p.type == AbstractInsnNode.LABEL ||
p.nodeType == AbstractInsnNode.LABEL ||
p.opcode in Opcodes.IRETURN..Opcodes.RETURN ||
p.opcode == Opcodes.GOTO ||
p.opcode == Opcodes.ATHROW
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.codegen.inline.isSuspendInlineMarker
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
import org.jetbrains.kotlin.codegen.optimization.common.removeUnusedLocalVariables
import org.jetbrains.kotlin.codegen.optimization.common.nodeType
import org.jetbrains.kotlin.codegen.optimization.nullCheck.isCheckExpressionValueIsNotNull
import org.jetbrains.kotlin.codegen.optimization.nullCheck.isCheckNotNullWithMessage
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
@@ -168,7 +169,7 @@ class TemporaryVariablesEliminationTransformer(private val state: GenerationStat
}
for (insn in insnList) {
when (insn.type) {
when (insn.nodeType) {
AbstractInsnNode.LINE -> {
usedLabels.add((insn as LineNumberNode).start)
}
@@ -570,7 +571,7 @@ class TemporaryVariablesEliminationTransformer(private val state: GenerationStat
}
private fun AbstractInsnNode.isIntervening(context: ControlFlowGraph): Boolean =
when (this.type) {
when (this.nodeType) {
AbstractInsnNode.LINE, AbstractInsnNode.FRAME ->
false
AbstractInsnNode.LABEL ->