diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/processUninitializedStores.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/processUninitializedStores.kt index 0779ad97fce..f32d42bffd4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/processUninitializedStores.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/processUninitializedStores.kt @@ -86,10 +86,9 @@ class UninitializedStoresProcessor(private val methodNode: MethodNode) { return val interpreter = UninitializedNewValueMarkerInterpreter(methodNode.instructions) - val analyzer = object : FastMethodAnalyzer("fake", methodNode, interpreter, pruneExceptionEdges = true) { - override fun newFrame(nLocals: Int, nStack: Int): Frame = - UninitializedNewValueFrame(nLocals, nStack) - } + val analyzer = FastMethodAnalyzer( + "fake", methodNode, interpreter, pruneExceptionEdges = true + ) { nLocals, nStack -> UninitializedNewValueFrame(nLocals, nStack) } val frames = analyzer.analyze() interpreter.analyzePopInstructions(frames) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInlinerUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInlinerUtil.kt index 20f559de681..66fa30ca576 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInlinerUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInlinerUtil.kt @@ -63,7 +63,7 @@ internal class FunctionalArgumentValue( val BasicValue?.functionalArgument get() = (this as? FunctionalArgumentValue)?.functionalArgument -internal class FunctionalArgumentInterpreter(private val inliner: MethodInliner) : BasicInterpreter(Opcodes.API_VERSION) { +internal class FunctionalArgumentInterpreter(private val inliner: MethodInliner) : BasicInterpreter(API_VERSION) { override fun newParameterValue(isInstanceMethod: Boolean, local: Int, type: Type): BasicValue = inliner.getFunctionalArgumentIfExists(local)?.let { FunctionalArgumentValue(it, newValue(type)) } ?: newValue(type) @@ -95,11 +95,11 @@ internal class Aload0BasicValue private constructor(val indices: Set) : Bas operator fun plus(other: Aload0BasicValue) = Aload0BasicValue(indices + other.indices) } -internal class Aload0Interpreter(private val node: MethodNode) : BasicInterpreter(Opcodes.API_VERSION) { +internal class Aload0Interpreter(private val node: MethodNode) : BasicInterpreter(API_VERSION) { override fun copyOperation(insn: AbstractInsnNode, value: BasicValue?): BasicValue? = when { insn.isAload0() -> Aload0BasicValue(node.instructions.indexOf(insn)) - insn.opcode == Opcodes.ALOAD -> if (value == null) null else BasicValue(value.type) + insn.opcode == ALOAD -> if (value == null) null else BasicValue(value.type) else -> super.copyOperation(insn, value) } @@ -113,19 +113,19 @@ internal fun analyzeMethodNodeWithInterpreter( node: MethodNode, interpreter: BasicInterpreter ): Array?> { - val analyzer = object : FastMethodAnalyzer("fake", node, interpreter, pruneExceptionEdges = true) { - override fun newFrame(nLocals: Int, nStack: Int): Frame { - return object : Frame(nLocals, nStack) { - @Throws(AnalyzerException::class) - override fun execute(insn: AbstractInsnNode, interpreter: Interpreter) { - // This can be a void non-local return from a non-void method; Frame#execute would throw and do nothing else. - if (insn.opcode == Opcodes.RETURN) return - super.execute(insn, interpreter) - } - } + class BasicValueFrame(nLocals: Int, nStack: Int) : Frame(nLocals, nStack) { + @Throws(AnalyzerException::class) + override fun execute(insn: AbstractInsnNode, interpreter: Interpreter) { + // This can be a void non-local return from a non-void method; Frame#execute would throw and do nothing else. + if (insn.opcode == Opcodes.RETURN) return + super.execute(insn, interpreter) } } + val analyzer = FastMethodAnalyzer( + "fake", node, interpreter, pruneExceptionEdges = true + ) { nLocals, nStack -> BasicValueFrame(nLocals, nStack) } + try { return analyzer.analyze() } catch (e: AnalyzerException) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/BoxingAnalyzer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/BoxingAnalyzer.kt deleted file mode 100644 index 49c1eb06291..00000000000 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/BoxingAnalyzer.kt +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.codegen.optimization.boxing - -import org.jetbrains.kotlin.codegen.optimization.common.FastMethodAnalyzer -import org.jetbrains.org.objectweb.asm.tree.MethodNode -import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException -import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue -import org.jetbrains.org.objectweb.asm.tree.analysis.Frame -import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter - -class BoxingAnalyzer( - owner: String, - method: MethodNode, - private val boxingInterpreter: BoxingInterpreter -) : FastMethodAnalyzer(owner, method, boxingInterpreter) { - override fun newFrame(nLocals: Int, nStack: Int): Frame = - BoxingFrame(nLocals, nStack) - - private inner class BoxingFrame(nLocals: Int, nStack: Int) : Frame(nLocals, nStack) { - override fun merge(frame: Frame, interpreter: Interpreter): Boolean { - if (stackSize != frame.stackSize) { - throw AnalyzerException(null, "Incompatible stack heights") - } - - var changed = false - for (i in 0 until locals) { - val local = getLocal(i) - val merged = boxingInterpreter.mergeLocalVariableValues(local, frame.getLocal(i)) - if (local != merged) { - setLocal(i, merged) - changed = true - } - } - for (i in 0 until stackSize) { - val onStack = getStack(i) - val merged = boxingInterpreter.mergeStackValues(onStack, frame.getStack(i)) - if (onStack != merged) { - setStack(i, merged) - changed = true - } - } - return changed - } - } -} \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/BoxingFrame.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/BoxingFrame.kt new file mode 100644 index 00000000000..08b5e26ca3d --- /dev/null +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/BoxingFrame.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.codegen.optimization.boxing + +import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException +import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue +import org.jetbrains.org.objectweb.asm.tree.analysis.Frame +import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter + +class BoxingFrame(nLocals: Int, nStack: Int, private val boxingInterpreter: BoxingInterpreter) : Frame(nLocals, nStack) { + override fun merge(frame: Frame, interpreter: Interpreter): Boolean { + if (stackSize != frame.stackSize) { + throw AnalyzerException(null, "Incompatible stack heights") + } + + var changed = false + for (i in 0 until locals) { + val local = getLocal(i) + val merged = boxingInterpreter.mergeLocalVariableValues(local, frame.getLocal(i)) + if (local != merged) { + setLocal(i, merged) + changed = true + } + } + for (i in 0 until stackSize) { + val onStack = getStack(i) + val merged = boxingInterpreter.mergeStackValues(onStack, frame.getStack(i)) + if (onStack != merged) { + setStack(i, merged) + changed = true + } + } + return changed + } +} \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/RedundantBoxingMethodTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/RedundantBoxingMethodTransformer.kt index 16067344546..a08f2b016ed 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/RedundantBoxingMethodTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/RedundantBoxingMethodTransformer.kt @@ -20,6 +20,7 @@ import com.intellij.openapi.util.Pair import org.jetbrains.kotlin.codegen.inline.insnOpcodeText import org.jetbrains.kotlin.codegen.inline.insnText import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods +import org.jetbrains.kotlin.codegen.optimization.common.FastMethodAnalyzer import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue import org.jetbrains.kotlin.codegen.optimization.common.remapLocalVariables import org.jetbrains.kotlin.codegen.optimization.fixStack.peek @@ -41,7 +42,10 @@ class RedundantBoxingMethodTransformer(private val generationState: GenerationSt return val interpreter = RedundantBoxingInterpreter(node, generationState) - val frames = BoxingAnalyzer(internalClassName, node, interpreter).analyze() + val analyzer = FastMethodAnalyzer( + internalClassName, node, interpreter, pruneExceptionEdges = false + ) { nLocals, nStack -> BoxingFrame(nLocals, nStack, interpreter) } + val frames = analyzer.analyze() interpretPopInstructionsForBoxedValues(interpreter, node, frames) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/FastMethodAnalyzer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/FastMethodAnalyzer.kt index 3235fa847dc..433d23e9baf 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/FastMethodAnalyzer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/FastMethodAnalyzer.kt @@ -44,18 +44,18 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.Value /** * @see org.jetbrains.kotlin.codegen.optimization.fixStack.FastStackAnalyzer */ -open class FastMethodAnalyzer +class FastMethodAnalyzer @JvmOverloads constructor( owner: String, method: MethodNode, interpreter: Interpreter, - private val pruneExceptionEdges: Boolean = false + private val pruneExceptionEdges: Boolean = false, + private val createFrame: (Int, Int) -> Frame = { nLocals, nStack -> Frame(nLocals, nStack) } ) : FastAnalyzer, Frame>(owner, method, interpreter) { private val isMergeNode = findMergeNodes(method) private val isTcbStart = BooleanArray(nInsns) - override fun newFrame(nLocals: Int, nStack: Int): Frame = - Frame(nLocals, nStack) + override fun newFrame(nLocals: Int, nStack: Int): Frame = createFrame(nLocals, nStack) override fun beforeAnalyze() { for (tcb in method.tryCatchBlocks) {