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.coroutines.COROUTINE_IMPL_ASM_TYPE
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.Companion.NO_ORIGIN
import org.jetbrains.org.objectweb.asm.*
@@ -42,7 +43,7 @@ class AnonymousObjectTransformer(
private var constructor: MethodNode? = null
private var sourceInfo: String? = null
private var debugInfo: String? = null
private var sourceMapper: SourceMapper? = null
private lateinit var sourceMapper: SourceMapper
override fun doTransform(parentRemapper: FieldRemapper): InlineResult {
val innerClassNodes = ArrayList<InnerClassNode>()
@@ -143,11 +144,12 @@ class AnonymousObjectTransformer(
method.visitEnd()
}
SourceMapper.flushToClassBuilder(sourceMapper!!, classBuilder)
SourceMapper.flushToClassBuilder(sourceMapper, classBuilder)
val visitor = classBuilder.visitor
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)
@@ -197,7 +199,7 @@ class AnonymousObjectTransformer(
remapper,
isSameModule,
"Transformer for " + transformationInfo.oldClassName,
sourceMapper!!,
sourceMapper,
InlineCallSiteInfo(
transformationInfo.oldClassName,
sourceNode.name,
@@ -341,60 +343,40 @@ class AnonymousObjectTransformer(
val indexToLambda = transformationInfo.lambdasToInline
val capturedParams = HashSet<Int>()
//load captured parameters and patch instruction list (NB: there is also could be object fields)
var cur: AbstractInsnNode? = constructor.instructions.first
while (cur != null) {
if (cur is FieldInsnNode) {
val fieldNode = cur as FieldInsnNode?
val fieldName = fieldNode!!.name
if (fieldNode.opcode == Opcodes.PUTFIELD && InlineCodegenUtil.isCapturedFieldName(fieldName)) {
val isPrevVarNode = fieldNode.previous is VarInsnNode
val isPrevPrevVarNode = isPrevVarNode && fieldNode.previous.previous is VarInsnNode
if (isPrevPrevVarNode) {
val node = fieldNode.previous.previous as VarInsnNode
if (node.`var` == 0) {
val previous = fieldNode.previous as VarInsnNode
val varIndex = previous.`var`
val lambdaInfo = indexToLambda[varIndex]
val newFieldName = if (isThis0(fieldName) && shouldRenameThis0(parentFieldRemapper, indexToLambda.values))
getNewFieldName(fieldName, true)
else
fieldName
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
}
//load captured parameters and patch instruction list
// NB: there is also could be object fields
val toDelete = arrayListOf<AbstractInsnNode>()
constructor.findCapturedFieldAssignmentInstructions().
forEach { fieldNode ->
val fieldName = fieldNode.name
val parameterAload = fieldNode.previous as VarInsnNode
val varIndex = parameterAload.`var`
val lambdaInfo = indexToLambda[varIndex]
val newFieldName = if (isThis0(fieldName) && shouldRenameThis0(parentFieldRemapper, indexToLambda.values))
getNewFieldName(fieldName, true)
else
fieldName
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)
toDelete.add(parameterAload.previous)
toDelete.add(parameterAload)
toDelete.add(fieldNode)
}
}
cur = cur.next
}
constructor.remove(toDelete)
constructorParamBuilder.addThis(oldObjectType, false)
var constructorDesc = transformationInfo.constructorDesc
if (constructorDesc == null) {
// in case of anonymous object with empty closure
constructorDesc = Type.getMethodDescriptor(Type.VOID_TYPE)
}
val types = Type.getArgumentTypes(constructorDesc!!)
for (type in types) {
val paramTypes = transformationInfo.constructorDesc?.let { Type.getArgumentTypes(it) } ?: emptyArray()
for (type in paramTypes) {
val info = indexToLambda[constructorParamBuilder.nextParameterOffset]
val parameterInfo = constructorParamBuilder.addNextParameter(type, info != null)
parameterInfo.lambda = info
@@ -541,9 +541,7 @@ public class MethodInliner {
}
}
for (AbstractInsnNode insnNode : toDelete) {
instructions.remove(insnNode);
}
MethodInlinerUtilKt.remove(node, toDelete);
//clean dead try/catch blocks
List<TryCatchBlockNode> blocks = node.tryCatchBlocks;
@@ -16,13 +16,12 @@
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.resolve.jvm.jvmSignature.JvmMethodParameterSignature
import org.jetbrains.kotlin.utils.SmartSet
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.InsnList
import org.jetbrains.org.objectweb.asm.tree.VarInsnNode
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
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(
insnNode: AbstractInsnNode?,
processSwap: Boolean,
@@ -88,8 +89,6 @@ private fun MethodInliner.getLambdaIfExistsAndMarkInstructions(
return null
}
fun SourceValue.singleOrNullInsn() = insns.singleOrNull()
fun parameterOffsets(valueParameters: List<JvmMethodParameterSignature>): Array<Int> {
var offset = 0
return Array(valueParameters.size) { index ->
@@ -100,4 +99,26 @@ fun parameterOffsets(valueParameters: List<JvmMethodParameterSignature>): Array<
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
}
}