Minor. Clean and refactoring after convertion

This commit is contained in:
Mikhael Bogdanov
2017-05-08 10:47:44 +02:00
parent 3fe152aad3
commit f915192827
3 changed files with 62 additions and 61 deletions
@@ -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 ->
@@ -101,3 +100,25 @@ fun parameterOffsets(valueParameters: List<JvmMethodParameterSignature>): Array<
} }
} }
} }
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
}
}