JVM specially hacked method analyzer for FixStack
This commit is contained in:
committed by
teamcityserver
parent
3ecd612ce7
commit
8763235053
+1
-1
@@ -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>(
|
||||
|
||||
+1
-2
@@ -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
|
||||
|
||||
+26
-85
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user