Minor. Clean and refactoring after convertion
This commit is contained in:
+35
-53
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.codegen.ClassBuilder
|
|||||||
import org.jetbrains.kotlin.codegen.StackValue
|
import org.jetbrains.kotlin.codegen.StackValue
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.COROUTINE_IMPL_ASM_TYPE
|
import org.jetbrains.kotlin.codegen.coroutines.COROUTINE_IMPL_ASM_TYPE
|
||||||
import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.isThis0
|
import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.isThis0
|
||||||
|
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.Companion.NO_ORIGIN
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.Companion.NO_ORIGIN
|
||||||
import org.jetbrains.org.objectweb.asm.*
|
import org.jetbrains.org.objectweb.asm.*
|
||||||
@@ -42,7 +43,7 @@ class AnonymousObjectTransformer(
|
|||||||
private var constructor: MethodNode? = null
|
private var constructor: MethodNode? = null
|
||||||
private var sourceInfo: String? = null
|
private var sourceInfo: String? = null
|
||||||
private var debugInfo: String? = null
|
private var debugInfo: String? = null
|
||||||
private var sourceMapper: SourceMapper? = null
|
private lateinit var sourceMapper: SourceMapper
|
||||||
|
|
||||||
override fun doTransform(parentRemapper: FieldRemapper): InlineResult {
|
override fun doTransform(parentRemapper: FieldRemapper): InlineResult {
|
||||||
val innerClassNodes = ArrayList<InnerClassNode>()
|
val innerClassNodes = ArrayList<InnerClassNode>()
|
||||||
@@ -143,11 +144,12 @@ class AnonymousObjectTransformer(
|
|||||||
method.visitEnd()
|
method.visitEnd()
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceMapper.flushToClassBuilder(sourceMapper!!, classBuilder)
|
SourceMapper.flushToClassBuilder(sourceMapper, classBuilder)
|
||||||
|
|
||||||
val visitor = classBuilder.visitor
|
val visitor = classBuilder.visitor
|
||||||
innerClassNodes.forEach {
|
innerClassNodes.forEach {
|
||||||
node -> visitor.visitInnerClass(node.name, node.outerName, node.innerName, node.access)
|
node ->
|
||||||
|
visitor.visitInnerClass(node.name, node.outerName, node.innerName, node.access)
|
||||||
}
|
}
|
||||||
|
|
||||||
writeOuterInfo(visitor)
|
writeOuterInfo(visitor)
|
||||||
@@ -197,7 +199,7 @@ class AnonymousObjectTransformer(
|
|||||||
remapper,
|
remapper,
|
||||||
isSameModule,
|
isSameModule,
|
||||||
"Transformer for " + transformationInfo.oldClassName,
|
"Transformer for " + transformationInfo.oldClassName,
|
||||||
sourceMapper!!,
|
sourceMapper,
|
||||||
InlineCallSiteInfo(
|
InlineCallSiteInfo(
|
||||||
transformationInfo.oldClassName,
|
transformationInfo.oldClassName,
|
||||||
sourceNode.name,
|
sourceNode.name,
|
||||||
@@ -341,60 +343,40 @@ class AnonymousObjectTransformer(
|
|||||||
val indexToLambda = transformationInfo.lambdasToInline
|
val indexToLambda = transformationInfo.lambdasToInline
|
||||||
val capturedParams = HashSet<Int>()
|
val capturedParams = HashSet<Int>()
|
||||||
|
|
||||||
//load captured parameters and patch instruction list (NB: there is also could be object fields)
|
//load captured parameters and patch instruction list
|
||||||
var cur: AbstractInsnNode? = constructor.instructions.first
|
// NB: there is also could be object fields
|
||||||
while (cur != null) {
|
val toDelete = arrayListOf<AbstractInsnNode>()
|
||||||
if (cur is FieldInsnNode) {
|
constructor.findCapturedFieldAssignmentInstructions().
|
||||||
val fieldNode = cur as FieldInsnNode?
|
forEach { fieldNode ->
|
||||||
val fieldName = fieldNode!!.name
|
val fieldName = fieldNode.name
|
||||||
if (fieldNode.opcode == Opcodes.PUTFIELD && InlineCodegenUtil.isCapturedFieldName(fieldName)) {
|
val parameterAload = fieldNode.previous as VarInsnNode
|
||||||
val isPrevVarNode = fieldNode.previous is VarInsnNode
|
val varIndex = parameterAload.`var`
|
||||||
val isPrevPrevVarNode = isPrevVarNode && fieldNode.previous.previous is VarInsnNode
|
val lambdaInfo = indexToLambda[varIndex]
|
||||||
|
val newFieldName = if (isThis0(fieldName) && shouldRenameThis0(parentFieldRemapper, indexToLambda.values))
|
||||||
if (isPrevPrevVarNode) {
|
getNewFieldName(fieldName, true)
|
||||||
val node = fieldNode.previous.previous as VarInsnNode
|
else
|
||||||
if (node.`var` == 0) {
|
fieldName
|
||||||
val previous = fieldNode.previous as VarInsnNode
|
val info = capturedParamBuilder.addCapturedParam(
|
||||||
val varIndex = previous.`var`
|
Type.getObjectType(transformationInfo.oldClassName), fieldName, newFieldName,
|
||||||
val lambdaInfo = indexToLambda[varIndex]
|
Type.getType(fieldNode.desc), lambdaInfo != null, null
|
||||||
val newFieldName = if (isThis0(fieldName) && shouldRenameThis0(parentFieldRemapper, indexToLambda.values))
|
)
|
||||||
getNewFieldName(fieldName, true)
|
if (lambdaInfo != null) {
|
||||||
else
|
info.lambda = lambdaInfo
|
||||||
fieldName
|
capturedLambdas.add(lambdaInfo)
|
||||||
val info = capturedParamBuilder.addCapturedParam(
|
|
||||||
Type.getObjectType(transformationInfo.oldClassName), fieldName, newFieldName,
|
|
||||||
Type.getType(fieldNode.desc), lambdaInfo != null, null
|
|
||||||
)
|
|
||||||
if (lambdaInfo != null) {
|
|
||||||
info.lambda = lambdaInfo
|
|
||||||
capturedLambdas.add(lambdaInfo)
|
|
||||||
}
|
|
||||||
constructorAdditionalFakeParams.add(info)
|
|
||||||
capturedParams.add(varIndex)
|
|
||||||
|
|
||||||
constructor.instructions.remove(previous.previous)
|
|
||||||
constructor.instructions.remove(previous)
|
|
||||||
val temp = cur
|
|
||||||
cur = cur.next
|
|
||||||
constructor.instructions.remove(temp)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
constructorAdditionalFakeParams.add(info)
|
||||||
|
capturedParams.add(varIndex)
|
||||||
|
|
||||||
|
toDelete.add(parameterAload.previous)
|
||||||
|
toDelete.add(parameterAload)
|
||||||
|
toDelete.add(fieldNode)
|
||||||
}
|
}
|
||||||
}
|
constructor.remove(toDelete)
|
||||||
cur = cur.next
|
|
||||||
}
|
|
||||||
|
|
||||||
constructorParamBuilder.addThis(oldObjectType, false)
|
constructorParamBuilder.addThis(oldObjectType, false)
|
||||||
var constructorDesc = transformationInfo.constructorDesc
|
|
||||||
|
|
||||||
if (constructorDesc == null) {
|
val paramTypes = transformationInfo.constructorDesc?.let { Type.getArgumentTypes(it) } ?: emptyArray()
|
||||||
// in case of anonymous object with empty closure
|
for (type in paramTypes) {
|
||||||
constructorDesc = Type.getMethodDescriptor(Type.VOID_TYPE)
|
|
||||||
}
|
|
||||||
|
|
||||||
val types = Type.getArgumentTypes(constructorDesc!!)
|
|
||||||
for (type in types) {
|
|
||||||
val info = indexToLambda[constructorParamBuilder.nextParameterOffset]
|
val info = indexToLambda[constructorParamBuilder.nextParameterOffset]
|
||||||
val parameterInfo = constructorParamBuilder.addNextParameter(type, info != null)
|
val parameterInfo = constructorParamBuilder.addNextParameter(type, info != null)
|
||||||
parameterInfo.lambda = info
|
parameterInfo.lambda = info
|
||||||
|
|||||||
@@ -541,9 +541,7 @@ public class MethodInliner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (AbstractInsnNode insnNode : toDelete) {
|
MethodInlinerUtilKt.remove(node, toDelete);
|
||||||
instructions.remove(insnNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
//clean dead try/catch blocks
|
//clean dead try/catch blocks
|
||||||
List<TryCatchBlockNode> blocks = node.tryCatchBlocks;
|
List<TryCatchBlockNode> blocks = node.tryCatchBlocks;
|
||||||
|
|||||||
@@ -16,13 +16,12 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.codegen.inline
|
package org.jetbrains.kotlin.codegen.inline
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
|
||||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
|
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature
|
||||||
import org.jetbrains.kotlin.utils.SmartSet
|
import org.jetbrains.kotlin.utils.SmartSet
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
import org.jetbrains.org.objectweb.asm.tree.*
|
||||||
import org.jetbrains.org.objectweb.asm.tree.InsnList
|
|
||||||
import org.jetbrains.org.objectweb.asm.tree.VarInsnNode
|
|
||||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||||
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
|
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
|
||||||
|
|
||||||
@@ -45,6 +44,8 @@ fun MethodInliner.getLambdaIfExistsAndMarkInstructions(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun SourceValue.singleOrNullInsn() = insns.singleOrNull()
|
||||||
|
|
||||||
private fun MethodInliner.getLambdaIfExistsAndMarkInstructions(
|
private fun MethodInliner.getLambdaIfExistsAndMarkInstructions(
|
||||||
insnNode: AbstractInsnNode?,
|
insnNode: AbstractInsnNode?,
|
||||||
processSwap: Boolean,
|
processSwap: Boolean,
|
||||||
@@ -88,8 +89,6 @@ private fun MethodInliner.getLambdaIfExistsAndMarkInstructions(
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun SourceValue.singleOrNullInsn() = insns.singleOrNull()
|
|
||||||
|
|
||||||
fun parameterOffsets(valueParameters: List<JvmMethodParameterSignature>): Array<Int> {
|
fun parameterOffsets(valueParameters: List<JvmMethodParameterSignature>): Array<Int> {
|
||||||
var offset = 0
|
var offset = 0
|
||||||
return Array(valueParameters.size) { index ->
|
return Array(valueParameters.size) { index ->
|
||||||
@@ -100,4 +99,26 @@ fun parameterOffsets(valueParameters: List<JvmMethodParameterSignature>): Array<
|
|||||||
offset += valueParameters[index - 1].asmType.size
|
offset += valueParameters[index - 1].asmType.size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun MethodNode.remove(instructions: Collection<AbstractInsnNode>) {
|
||||||
|
instructions.forEach {
|
||||||
|
this@remove.instructions.remove(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun MethodNode.findCapturedFieldAssignmentInstructions(): Sequence<FieldInsnNode> {
|
||||||
|
return InsnSequence(instructions).filterIsInstance<FieldInsnNode>().
|
||||||
|
filter { fieldNode ->
|
||||||
|
//filter captured field assignment
|
||||||
|
// aload 0
|
||||||
|
// aload x
|
||||||
|
// PUTFIELD $fieldName
|
||||||
|
|
||||||
|
val prevPrev = fieldNode.previous?.previous as? VarInsnNode
|
||||||
|
|
||||||
|
fieldNode.opcode == Opcodes.PUTFIELD &&
|
||||||
|
InlineCodegenUtil.isCapturedFieldName(fieldNode.name) &&
|
||||||
|
fieldNode.previous is VarInsnNode && prevPrev != null && prevPrev.`var` == 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user