JVM prune exception edges in DFA in some cases
This commit is contained in:
+6
-4
@@ -82,13 +82,15 @@ class UninitializedStoresProcessor(private val methodNode: MethodNode) {
|
||||
private val isInSpecialMethod = methodNode.name == "<init>" || methodNode.name == "<clinit>"
|
||||
|
||||
fun run() {
|
||||
val interpreter = UninitializedNewValueMarkerInterpreter(methodNode.instructions)
|
||||
|
||||
if (methodNode.instructions.toArray().none { it.opcode == Opcodes.NEW })
|
||||
return
|
||||
|
||||
val frames = CustomFramesMethodAnalyzer("fake", methodNode, interpreter, this::UninitializedNewValueFrame).analyze()
|
||||
|
||||
val interpreter = UninitializedNewValueMarkerInterpreter(methodNode.instructions)
|
||||
val analyzer = object : FastMethodAnalyzer<BasicValue>("fake", methodNode, interpreter, pruneExceptionEdges = true) {
|
||||
override fun newFrame(nLocals: Int, nStack: Int): Frame<BasicValue> =
|
||||
UninitializedNewValueFrame(nLocals, nStack)
|
||||
}
|
||||
val frames = analyzer.analyze()
|
||||
interpreter.analyzePopInstructions(frames)
|
||||
|
||||
for ((index, insn) in methodNode.instructions.toArray().withIndex()) {
|
||||
|
||||
+6
-6
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.codegen.optimization
|
||||
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.FastMethodAnalyzer
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.InstructionLivenessAnalyzer
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
|
||||
@@ -49,22 +50,21 @@ class RedundantCheckCastEliminationMethodTransformer : MethodTransformer() {
|
||||
|
||||
val redundantCheckCasts = ArrayList<TypeInsnNode>()
|
||||
|
||||
val frames = analyze(internalClassName, methodNode, interpreter)
|
||||
val frames = FastMethodAnalyzer(internalClassName, methodNode, interpreter, pruneExceptionEdges = true).analyze()
|
||||
for (i in insns.indices) {
|
||||
val valueType = frames[i]?.top()?.type ?: continue
|
||||
val insn = insns[i]
|
||||
|
||||
if (insn is TypeInsnNode) {
|
||||
val insnType = Type.getObjectType(insn.desc)
|
||||
if (insn.opcode == Opcodes.CHECKCAST) {
|
||||
val typeInsn = insn as TypeInsnNode
|
||||
val insnType = Type.getObjectType(typeInsn.desc)
|
||||
if (!isTrivialSubtype(insnType, valueType)) continue
|
||||
|
||||
//Keep casts to multiarray types cause dex doesn't recognize ANEWARRAY [Ljava/lang/Object; as Object [][], but Object [] type
|
||||
//It's not clear is it bug in dex or not and maybe best to distinguish such types from MULTINEWARRRAY ones in method analyzer
|
||||
if (isMultiArrayType(insnType)) continue
|
||||
|
||||
if (insn.opcode == Opcodes.CHECKCAST) {
|
||||
redundantCheckCasts.add(insn)
|
||||
}
|
||||
redundantCheckCasts.add(typeInsn)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* 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.MethodNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Value
|
||||
|
||||
class CustomFramesMethodAnalyzer<V : Value>(
|
||||
owner: String, method: MethodNode, interpreter: Interpreter<V>,
|
||||
private val frameFactory: (Int, Int) -> Frame<V>
|
||||
) : FastMethodAnalyzer<V>(owner, method, interpreter) {
|
||||
override fun newFrame(nLocals: Int, nStack: Int) = frameFactory(nLocals, nStack)
|
||||
}
|
||||
+23
-10
@@ -47,10 +47,12 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.Value
|
||||
* @see org.jetbrains.kotlin.codegen.optimization.fixStack.FastStackAnalyzer
|
||||
*/
|
||||
@Suppress("DuplicatedCode")
|
||||
open class FastMethodAnalyzer<V : Value>(
|
||||
open class FastMethodAnalyzer<V : Value>
|
||||
@JvmOverloads constructor(
|
||||
private val owner: String,
|
||||
val method: MethodNode,
|
||||
private val interpreter: Interpreter<V>
|
||||
private val method: MethodNode,
|
||||
private val interpreter: Interpreter<V>,
|
||||
private val pruneExceptionEdges: Boolean = false
|
||||
) {
|
||||
private val insnsArray = method.instructions.toArray()
|
||||
private val nInsns = method.instructions.size()
|
||||
@@ -74,6 +76,11 @@ open class FastMethodAnalyzer<V : Value>(
|
||||
computeExceptionHandlersForEachInsn(method)
|
||||
initMergeNodes()
|
||||
|
||||
val isTcbStart = BooleanArray(nInsns)
|
||||
for (tcb in method.tryCatchBlocks) {
|
||||
isTcbStart[tcb.start.indexOf()] = true
|
||||
}
|
||||
|
||||
val current = newFrame(method.maxLocals, method.maxStack)
|
||||
val handler = newFrame(method.maxLocals, method.maxStack)
|
||||
initLocals(current)
|
||||
@@ -107,14 +114,20 @@ open class FastMethodAnalyzer<V : Value>(
|
||||
}
|
||||
}
|
||||
|
||||
handlers[insn]?.forEach { tcb ->
|
||||
val exnType = Type.getObjectType(tcb.type ?: "java/lang/Throwable")
|
||||
val jump = tcb.handler.indexOf()
|
||||
// Jump by an exception edge clears the stack, putting exception on top.
|
||||
// So, unless we have a store operation, anything we change on stack would be lost,
|
||||
// and there's no need to analyze exception handler again.
|
||||
// Add an exception edge from TCB start to make sure handler itself is still visited.
|
||||
if (!pruneExceptionEdges || insnOpcode in Opcodes.ISTORE..Opcodes.ASTORE || insnOpcode == Opcodes.IINC || isTcbStart[insn]) {
|
||||
handlers[insn]?.forEach { tcb ->
|
||||
val exnType = Type.getObjectType(tcb.type ?: "java/lang/Throwable")
|
||||
val jump = tcb.handler.indexOf()
|
||||
|
||||
handler.init(f)
|
||||
handler.clearStack()
|
||||
handler.push(interpreter.newValue(exnType))
|
||||
mergeControlFlowEdge(jump, handler)
|
||||
handler.init(f)
|
||||
handler.clearStack()
|
||||
handler.push(interpreter.newValue(exnType))
|
||||
mergeControlFlowEdge(jump, handler)
|
||||
}
|
||||
}
|
||||
|
||||
} catch (e: AnalyzerException) {
|
||||
|
||||
Reference in New Issue
Block a user