Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2010-2023 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.inline
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.tree.LabelNode
import org.jetbrains.org.objectweb.asm.tree.LineNumberNode
import org.jetbrains.org.objectweb.asm.tree.LocalVariableNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
class InlineScopesGenerator {
var inlinedScopes = 0
var currentCallSiteLineNumber = 0
private class InlineScopeNode(
// The marker variable is only null for the root node
val markerVariable: LocalVariableNode?,
val scopeNumber: Int,
var inlineNesting: Int,
val parent: InlineScopeNode?
) {
var callSiteLineNumber: Int? = null
var surroundingScopeNumber: Int? = null
val variables = mutableListOf()
val children = mutableListOf()
val isRoot: Boolean
get() = parent == null
init {
parent?.children?.add(this)
}
}
private abstract inner class VariableRenamer {
abstract fun computeInlineScopeInfo(node: InlineScopeNode)
abstract fun LocalVariableNode.belongsToInlineScope(node: InlineScopeNode): Boolean
open fun shouldSkipVariable(variable: LocalVariableNode): Boolean = false
open fun inlineNesting(): Int = -1
fun renameVariables(methodNode: MethodNode): Int {
val rootNode = computeInlineScopesTree(methodNode)
return renameVariables(rootNode)
}
private fun computeInlineScopesTree(methodNode: MethodNode): InlineScopeNode {
val rootNode = InlineScopeNode(null, 0, inlineNesting(), null)
val localVariables = methodNode.localVariables ?: return rootNode
// Inline function and lambda parameters are introduced before the corresponding inline marker variable,
// so we need to keep track of them to assign to the correct scope later.
val variablesWithNotMatchingDepth = mutableListOf()
val labelToIndex = methodNode.getLabelToIndexMap()
val sortedVariables = localVariables.sortedBy { labelToIndex[it.start.label] }
var seenInlineScopesNumber = 0
var currentNode = rootNode
for (variable in sortedVariables) {
currentNode = currentNode.findClosestSurroundingScope(variable, labelToIndex)
val name = variable.name
if (isFakeLocalVariableForInline(name)) {
seenInlineScopesNumber += 1
val newNode = InlineScopeNode(variable, seenInlineScopesNumber, currentNode.inlineNesting, currentNode)
computeInlineScopeInfo(newNode)
currentNode = newNode
currentNode.variables.addAll(variablesWithNotMatchingDepth)
variablesWithNotMatchingDepth.clear()
} else if (!currentNode.isRoot || !shouldSkipVariable(variable)) {
if (variable.belongsToInlineScope(currentNode)) {
currentNode.variables.add(variable)
} else {
variablesWithNotMatchingDepth.add(variable)
}
}
}
return rootNode
}
private fun renameVariables(rootNode: InlineScopeNode): Int {
var seenInlineScopesNumber = 0
val nodeStack = mutableListOf()
nodeStack.addAll(rootNode.children)
while (nodeStack.isNotEmpty()) {
val node = nodeStack.removeLast()
seenInlineScopesNumber += 1
with(node) {
markerVariable!!.name = computeNewVariableName(
markerVariable.name,
scopeNumber + inlinedScopes,
callSiteLineNumber,
surroundingScopeNumber
)
}
for (variable in node.variables) {
variable.name = computeNewVariableName(
variable.name,
node.scopeNumber + inlinedScopes,
null,
null
)
}
nodeStack.addAll(node.children)
}
return seenInlineScopesNumber
}
private fun InlineScopeNode.findClosestSurroundingScope(
variable: LocalVariableNode,
labelToIndex: Map