From f91519282714248c8eeea4723fe28cb5d66cf3c2 Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Mon, 8 May 2017 10:47:44 +0200 Subject: [PATCH] Minor. Clean and refactoring after convertion --- .../inline/AnonymousObjectTransformer.kt | 88 ++++++++----------- .../kotlin/codegen/inline/MethodInliner.java | 4 +- .../codegen/inline/MethodInlinerUtil.kt | 31 +++++-- 3 files changed, 62 insertions(+), 61 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt index d8100f0b12a..80aa629de5a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt @@ -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() @@ -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() - //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() + 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 diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java index e8a890f5062..c810c7930b5 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java @@ -541,9 +541,7 @@ public class MethodInliner { } } - for (AbstractInsnNode insnNode : toDelete) { - instructions.remove(insnNode); - } + MethodInlinerUtilKt.remove(node, toDelete); //clean dead try/catch blocks List blocks = node.tryCatchBlocks; diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInlinerUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInlinerUtil.kt index 385fcf47cd8..f7485ec65cd 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInlinerUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInlinerUtil.kt @@ -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): Array { var offset = 0 return Array(valueParameters.size) { index -> @@ -100,4 +99,26 @@ fun parameterOffsets(valueParameters: List): Array< offset += valueParameters[index - 1].asmType.size } } +} + +fun MethodNode.remove(instructions: Collection) { + instructions.forEach { + this@remove.instructions.remove(it) + } +} + +fun MethodNode.findCapturedFieldAssignmentInstructions(): Sequence { + return InsnSequence(instructions).filterIsInstance(). + 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 + } } \ No newline at end of file