JVM specially hacked method analyzer for FixStack

This commit is contained in:
Dmitry Petrov
2021-07-19 18:46:18 +03:00
committed by teamcityserver
parent 3ecd612ce7
commit 8763235053
4 changed files with 28 additions and 89 deletions
@@ -45,7 +45,7 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
import org.jetbrains.org.objectweb.asm.tree.analysis.Value
/**
* @see FlexibleMethodAnalyzer
* @see org.jetbrains.kotlin.codegen.optimization.fixStack.HackedFixStackMethodAnalyzerBase
*/
@Suppress("DuplicatedCode")
open class FastMethodAnalyzer<V : Value>(
@@ -20,7 +20,6 @@ import com.intellij.util.containers.Stack
import org.jetbrains.kotlin.codegen.inline.isAfterInlineMarker
import org.jetbrains.kotlin.codegen.inline.isBeforeInlineMarker
import org.jetbrains.kotlin.codegen.inline.isMarkedReturn
import org.jetbrains.kotlin.codegen.optimization.common.FlexibleMethodAnalyzer
import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsn
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.org.objectweb.asm.Opcodes
@@ -93,7 +92,7 @@ internal class FixStackAnalyzer(
private val analyzer = InternalAnalyzer(owner)
private inner class InternalAnalyzer(owner: String) :
FlexibleMethodAnalyzer<FixStackValue>(owner, method, FixStackInterpreter()) {
HackedFixStackMethodAnalyzerBase<FixStackValue>(owner, method, FixStackInterpreter()) {
val spilledStacks = hashMapOf<AbstractInsnNode, List<FixStackValue>>()
var maxExtraStackSize = 0; private set
@@ -1,50 +1,9 @@
/*
* Copyright 2010-2015 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.
*
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* 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.common
package org.jetbrains.kotlin.codegen.optimization.fixStack
import org.jetbrains.kotlin.codegen.inline.insnText
import org.jetbrains.org.objectweb.asm.Opcodes
@@ -56,15 +15,10 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
import org.jetbrains.org.objectweb.asm.tree.analysis.Value
/**
* This class is a modified version of `org.objectweb.asm.tree.analysis.Analyzer`
*
* @see FastMethodAnalyzer
*
* @author Eric Bruneton
* @author Dmitry Petrov
* @see org.jetbrains.kotlin.codegen.optimization.common.FastMethodAnalyzer
*/
@Suppress("DuplicatedCode")
open class FlexibleMethodAnalyzer<V : Value>(
internal open class HackedFixStackMethodAnalyzerBase<V : Value>(
private val owner: String,
val method: MethodNode,
protected val interpreter: Interpreter<V>
@@ -72,7 +26,7 @@ open class FlexibleMethodAnalyzer<V : Value>(
protected val insnsArray: Array<AbstractInsnNode> = method.instructions.toArray()
private val nInsns = insnsArray.size
val frames: Array<Frame<V>?> = arrayOfNulls(nInsns)
private val frames: Array<Frame<V>?> = arrayOfNulls(nInsns)
private val handlers: Array<MutableList<TryCatchBlockNode>?> = arrayOfNulls(nInsns)
private val queued = BooleanArray(nInsns)
@@ -92,7 +46,7 @@ open class FlexibleMethodAnalyzer<V : Value>(
checkAssertions()
computeExceptionHandlersForEachInsn()
computeExceptionEdges()
initSinglePredBlocks()
@@ -136,7 +90,7 @@ open class FlexibleMethodAnalyzer<V : Value>(
handler.init(f)
handler.clearStack()
handler.push(interpreter.newValue(exnType))
mergeControlFlowEdge(insn, jump, handler)
mergeControlFlowEdge(jump, handler)
}
}
@@ -281,7 +235,7 @@ open class FlexibleMethodAnalyzer<V : Value>(
private fun processControlFlowEdge(current: Frame<V>, insn: Int, jump: Int) {
if (visitControlFlowEdge(insn, jump)) {
mergeControlFlowEdge(insn, jump, current)
mergeControlFlowEdge(jump, current)
}
}
@@ -302,44 +256,31 @@ open class FlexibleMethodAnalyzer<V : Value>(
while (local < m.maxLocals) {
current.setLocal(local++, interpreter.newValue(null))
}
mergeControlFlowEdge(0, 0, current)
mergeControlFlowEdge(0, current)
}
private fun computeExceptionHandlersForEachInsn() {
private fun computeExceptionEdges() {
for (tcb in method.tryCatchBlocks) {
val begin = tcb.start.indexOf()
val end = tcb.end.indexOf()
for (j in begin until end) {
val insn = insnsArray[j]
if (!insn.isMeaningful) continue
var insnHandlers: MutableList<TryCatchBlockNode>? = handlers[j]
if (insnHandlers == null) {
insnHandlers = ArrayList<TryCatchBlockNode>()
handlers[j] = insnHandlers
}
insnHandlers.add(tcb)
// Don't have to visit same exception handler multiple times - we care only about stack state at TCB start.
val start = tcb.start.indexOf()
var insnHandlers: MutableList<TryCatchBlockNode>? = handlers[start]
if (insnHandlers == null) {
insnHandlers = ArrayList()
handlers[start] = insnHandlers
}
insnHandlers.add(tcb)
}
}
private fun mergeControlFlowEdge(src: Int, dest: Int, frame: Frame<V>) {
val oldFrame = frames[dest]
val changes = when {
oldFrame == null -> {
frames[dest] = newFrame(frame.locals, frame.maxStackSize).apply { init(frame) }
true
private fun mergeControlFlowEdge(dest: Int, frame: Frame<V>) {
val destFrame = frames[dest]
if (destFrame == null) {
// Don't have to visit same instruction multiple times - we care only about "initial" stack state.
frames[dest] = newFrame(frame.locals, frame.maxStackSize).apply { init(frame) }
if (!queued[dest]) {
queued[dest] = true
queue[top++] = dest
}
dest == src + 1 && singlePredBlock[src] == singlePredBlock[dest] -> {
// Forward jump within a single predecessor block, no need to merge.
oldFrame.init(frame)
true
}
else ->
oldFrame.merge(frame, interpreter)
}
if (changes && !queued[dest]) {
queued[dest] = true
queue[top++] = dest
}
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM
// WITH_RUNTIME
// WITH_COROUTINES
// KT-27830