[JVM] Replace AbstractInsnNode.getType with new util function
This change speeds up backend by approximately 0.96%.
This commit is contained in:
@@ -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 ->
|
||||
|
||||
+2
-1
@@ -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
|
||||
|
||||
+4
-2
@@ -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
|
||||
}
|
||||
|
||||
+3
-2
@@ -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?
|
||||
|
||||
+1
-1
@@ -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 ->
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+1
-1
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -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
|
||||
|
||||
+3
-2
@@ -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 ->
|
||||
|
||||
Reference in New Issue
Block a user