diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/backwardAnalysis.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/backwardAnalysis.kt new file mode 100644 index 00000000000..e3ba541c3de --- /dev/null +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/backwardAnalysis.kt @@ -0,0 +1,65 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.codegen.optimization.common + +import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode +import org.jetbrains.org.objectweb.asm.tree.MethodNode + +interface VarFrame> { + fun mergeFrom(other: F) + override fun equals(other: Any?): Boolean + override fun hashCode(): Int +} + +interface BackwardAnalysisInterpreter> { + fun newFrame(maxLocals: Int): F + fun def(frame: F, insn: AbstractInsnNode) + fun use(frame: F, insn: AbstractInsnNode) +} + +fun > analyze(node: MethodNode, interpreter: BackwardAnalysisInterpreter): List { + val graph = ControlFlowGraph.build(node) + val insnList = node.instructions + + val frames = (1..insnList.size()).map { interpreter.newFrame(node.maxLocals) }.toMutableList() + val insnArray = insnList.toArray() + + // see Figure 9.16 from Dragon book + var wereChanges: Boolean + + do { + wereChanges = false + for (insn in insnArray) { + val index = insnList.indexOf(insn) + val newFrame = interpreter.newFrame(node.maxLocals) + for (successorIndex in graph.getSuccessorsIndices(insn)) { + newFrame.mergeFrom(frames[successorIndex]) + } + + interpreter.def(newFrame, insn) + interpreter.use(newFrame, insn) + + if (frames[index] != newFrame) { + frames[index] = newFrame + wereChanges = true + } + } + + } while (wereChanges) + + return frames +} diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/variableLiveness.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/variableLiveness.kt index 3c9947b529f..df5e702238b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/variableLiveness.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/variableLiveness.kt @@ -27,10 +27,10 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.Frame import java.util.* -class VariableLivenessFrame(val maxLocals: Int) { +class VariableLivenessFrame(val maxLocals: Int) : VarFrame { private val bitSet = BitSet(maxLocals) - fun mergeFrom(other: VariableLivenessFrame) { + override fun mergeFrom(other: VariableLivenessFrame) { bitSet.or(other.bitSet) } @@ -51,48 +51,24 @@ class VariableLivenessFrame(val maxLocals: Int) { override fun hashCode() = bitSet.hashCode() } - -fun analyzeLiveness(node: MethodNode): Array { +fun analyzeLiveness(node: MethodNode): List { val typeAnnotatedFrames = MethodTransformer.analyze("fake", node, OptimizationBasicInterpreter()) + return analyze(node, object : BackwardAnalysisInterpreter { + override fun newFrame(maxLocals: Int) = VariableLivenessFrame(maxLocals) + override fun def(frame: VariableLivenessFrame, insn: AbstractInsnNode) = defVar(frame, insn) + override fun use(frame: VariableLivenessFrame, insn: AbstractInsnNode) = + useVar(frame, insn, node, typeAnnotatedFrames[node.instructions.indexOf(insn)]) - val graph = ControlFlowGraph.build(node) - val insnList = node.instructions - val frames = Array(insnList.size()) { VariableLivenessFrame(node.maxLocals) } - val insnArray = insnList.toArray() - - // see Figure 9.16 from Dragon book - var wereChanges: Boolean - - do { - wereChanges = false - for (insn in insnArray) { - val index = insnList.indexOf(insn) - val newFrame = VariableLivenessFrame(node.maxLocals) - for (successorIndex in graph.getSuccessorsIndices(insn)) { - newFrame.mergeFrom(frames[successorIndex]) - } - - def(newFrame, insn) - use(newFrame, insn, node, typeAnnotatedFrames[index]) - - if (frames[index] != newFrame) { - frames[index] = newFrame - wereChanges = true - } - } - - } while (wereChanges) - - return frames + }) } -private fun def(frame: VariableLivenessFrame, insn: AbstractInsnNode) { +private fun defVar(frame: VariableLivenessFrame, insn: AbstractInsnNode) { if (insn is VarInsnNode && insn.isStoreOperation()) { frame.markDead(insn.`var`) } } -private fun use( +private fun useVar( frame: VariableLivenessFrame, insn: AbstractInsnNode, node: MethodNode,