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 7cc11b89324..f8134e2d34f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt @@ -29,10 +29,10 @@ import org.jetbrains.org.objectweb.asm.tree.* import java.util.* class AnonymousObjectTransformer( - transformationInfo: AnonymousObjectTransformationInfo, - private val inliningContext: InliningContext, - private val isSameModule: Boolean, - private val continuationClassName: String? + transformationInfo: AnonymousObjectTransformationInfo, + private val inliningContext: InliningContext, + private val isSameModule: Boolean, + private val continuationClassName: String? ) : ObjectTransformer(transformationInfo, inliningContext.state) { private val oldObjectType = Type.getObjectType(transformationInfo.oldClassName) @@ -75,7 +75,7 @@ class AnonymousObjectTransformer( } override fun visitMethod( - access: Int, name: String, desc: String, signature: String?, exceptions: Array? + access: Int, name: String, desc: String, signature: String?, exceptions: Array? ): MethodVisitor { val node = MethodNode(access, name, desc, signature, exceptions) if (name == "") { @@ -83,8 +83,7 @@ class AnonymousObjectTransformer( throw RuntimeException("Lambda, SAM or anonymous object should have only one constructor") } constructor = node - } - else { + } else { methodsToTransform.add(node) } return node @@ -94,8 +93,7 @@ class AnonymousObjectTransformer( addUniqueField(name) return if (isCapturedFieldName(name)) { null - } - else { + } else { classBuilder.newField(JvmDeclarationOrigin.NO_ORIGIN, access, name, desc, signature, value) } } @@ -111,16 +109,14 @@ class AnonymousObjectTransformer( if (!inliningContext.isInliningLambda) { sourceMapper = if (debugInfo != null && !debugInfo!!.isEmpty()) { SourceMapper.createFromSmap(SMAPParser.parse(debugInfo!!)) - } - else { + } else { //seems we can't do any clever mapping cause we don't know any about original class name IdenticalSourceMapper } if (sourceInfo != null && !GENERATE_SMAP) { classBuilder.visitSource(sourceInfo!!, debugInfo) } - } - else { + } else { if (sourceInfo != null) { classBuilder.visitSource(sourceInfo!!, debugInfo) } @@ -130,7 +126,7 @@ class AnonymousObjectTransformer( val allCapturedParamBuilder = ParametersBuilder.newBuilder() val constructorParamBuilder = ParametersBuilder.newBuilder() val additionalFakeParams = extractParametersMappingAndPatchConstructor( - constructor!!, allCapturedParamBuilder, constructorParamBuilder,transformationInfo, parentRemapper + constructor!!, allCapturedParamBuilder, constructorParamBuilder, transformationInfo, parentRemapper ) val deferringMethods = ArrayList() @@ -172,8 +168,7 @@ class AnonymousObjectTransformer( SourceMapper.flushToClassBuilder(sourceMapper, classBuilder) val visitor = classBuilder.visitor - innerClassNodes.forEach { - node -> + innerClassNodes.forEach { node -> visitor.visitInnerClass(node.name, node.outerName, node.innerName, node.access) } @@ -194,7 +189,7 @@ class AnonymousObjectTransformer( } private fun writeTransformedMetadata(header: KotlinClassHeader, classBuilder: ClassBuilder) { - writeKotlinMetadata(classBuilder, state, header.kind, header.extraInt) action@ { av -> + writeKotlinMetadata(classBuilder, state, header.kind, header.extraInt) action@{ av -> val (newProto, newStringTable) = transformMetadata(header) ?: run { val data = header.data val strings = header.strings @@ -238,11 +233,11 @@ class AnonymousObjectTransformer( } private fun inlineMethodAndUpdateGlobalResult( - parentRemapper: FieldRemapper, - deferringVisitor: MethodVisitor, - next: MethodNode, - allCapturedParamBuilder: ParametersBuilder, - isConstructor: Boolean + parentRemapper: FieldRemapper, + deferringVisitor: MethodVisitor, + next: MethodNode, + allCapturedParamBuilder: ParametersBuilder, + isConstructor: Boolean ): InlineResult { val funResult = inlineMethod(parentRemapper, deferringVisitor, next, allCapturedParamBuilder, isConstructor) transformationResult.merge(funResult) @@ -251,33 +246,34 @@ class AnonymousObjectTransformer( } private fun inlineMethod( - parentRemapper: FieldRemapper, - deferringVisitor: MethodVisitor, - sourceNode: MethodNode, - capturedBuilder: ParametersBuilder, - isConstructor: Boolean + parentRemapper: FieldRemapper, + deferringVisitor: MethodVisitor, + sourceNode: MethodNode, + capturedBuilder: ParametersBuilder, + isConstructor: Boolean ): InlineResult { val typeParametersToReify = inliningContext.root.inlineMethodReifier.reifyInstructions(sourceNode) - val parameters = if (isConstructor) capturedBuilder.buildParameters() else getMethodParametersWithCaptured(capturedBuilder, sourceNode) + val parameters = + if (isConstructor) capturedBuilder.buildParameters() else getMethodParametersWithCaptured(capturedBuilder, sourceNode) val remapper = RegeneratedLambdaFieldRemapper( - oldObjectType.internalName, transformationInfo.newClassName, parameters, - transformationInfo.capturedLambdasToInline, parentRemapper, isConstructor + oldObjectType.internalName, transformationInfo.newClassName, parameters, + transformationInfo.capturedLambdasToInline, parentRemapper, isConstructor ) val inliner = MethodInliner( - sourceNode, - parameters, - inliningContext.subInline(transformationInfo.nameGenerator), - remapper, - isSameModule, - "Transformer for " + transformationInfo.oldClassName, - sourceMapper, - InlineCallSiteInfo( - transformationInfo.oldClassName, - sourceNode.name, - if (isConstructor) transformationInfo.newConstructorDescriptor else sourceNode.desc - ), null + sourceNode, + parameters, + inliningContext.subInline(transformationInfo.nameGenerator), + remapper, + isSameModule, + "Transformer for " + transformationInfo.oldClassName, + sourceMapper, + InlineCallSiteInfo( + transformationInfo.oldClassName, + sourceNode.name, + if (isConstructor) transformationInfo.newConstructorDescriptor else sourceNode.desc + ), null ) val result = inliner.doInline(deferringVisitor, LocalVarRemapper(parameters, 0), false, LabelOwner.NOT_APPLICABLE) @@ -287,11 +283,11 @@ class AnonymousObjectTransformer( } private fun generateConstructorAndFields( - classBuilder: ClassBuilder, - allCapturedBuilder: ParametersBuilder, - constructorInlineBuilder: ParametersBuilder, - parentRemapper: FieldRemapper, - constructorAdditionalFakeParams: List + classBuilder: ClassBuilder, + allCapturedBuilder: ParametersBuilder, + constructorInlineBuilder: ParametersBuilder, + parentRemapper: FieldRemapper, + constructorAdditionalFakeParams: List ) { val descTypes = ArrayList() @@ -319,7 +315,7 @@ class AnonymousObjectTransformer( //TODO for inline method make public class transformationInfo.newConstructorDescriptor = constructorDescriptor val constructorVisitor = classBuilder.newMethod( - NO_ORIGIN, constructor!!.access, "", constructorDescriptor, null, ArrayUtil.EMPTY_STRING_ARRAY + NO_ORIGIN, constructor!!.access, "", constructorDescriptor, null, ArrayUtil.EMPTY_STRING_ARRAY ) val newBodyStartLabel = Label() @@ -345,11 +341,11 @@ class AnonymousObjectTransformer( if (fake.lambda != null) { //set remap value to skip this fake (captured with lambda already skipped) val composed = StackValue.field( - fake.getType(), - oldObjectType, - fake.newFieldName, - false, - StackValue.LOCAL_0 + fake.getType(), + oldObjectType, + fake.newFieldName, + false, + StackValue.LOCAL_0 ) fake.remapValue = composed } @@ -363,19 +359,19 @@ class AnonymousObjectTransformer( val oldStartLabel = (first as? LabelNode)?.label intermediateMethodNode.accept(object : MethodBodyVisitor(capturedFieldInitializer) { override fun visitLocalVariable( - name: String, desc: String, signature: String?, start: Label, end: Label, index: Int + name: String, desc: String, signature: String?, start: Label, end: Label, index: Int ) { super.visitLocalVariable( - name, desc, signature, - //patch for jack&jill - if (oldStartLabel === start) newBodyStartLabel else start, - end, index + name, desc, signature, + //patch for jack&jill + if (oldStartLabel === start) newBodyStartLabel else start, + end, index ) } }) constructorVisitor.visitEnd() AsmUtil.genClosureFields( - toNameTypePair(filterSkipped(newFieldsWithSkipped)), classBuilder + toNameTypePair(filterSkipped(newFieldsWithSkipped)), classBuilder ) } @@ -393,24 +389,24 @@ class AnonymousObjectTransformer( private fun newMethod(builder: ClassBuilder, original: MethodNode): DeferredMethodVisitor { return DeferredMethodVisitor( - MethodNode( - original.access, original.name, original.desc, original.signature, - ArrayUtil.toStringArray(original.exceptions) - ) + MethodNode( + original.access, original.name, original.desc, original.signature, + ArrayUtil.toStringArray(original.exceptions) + ) ) { builder.newMethod( - NO_ORIGIN, original.access, original.name, original.desc, original.signature, - ArrayUtil.toStringArray(original.exceptions) + NO_ORIGIN, original.access, original.name, original.desc, original.signature, + ArrayUtil.toStringArray(original.exceptions) ) } } private fun extractParametersMappingAndPatchConstructor( - constructor: MethodNode, - capturedParamBuilder: ParametersBuilder, - constructorParamBuilder: ParametersBuilder, - transformationInfo: AnonymousObjectTransformationInfo, - parentFieldRemapper: FieldRemapper + constructor: MethodNode, + capturedParamBuilder: ParametersBuilder, + constructorParamBuilder: ParametersBuilder, + transformationInfo: AnonymousObjectTransformationInfo, + parentFieldRemapper: FieldRemapper ): List { val capturedLambdas = LinkedHashSet() //captured var of inlined parameter val constructorAdditionalFakeParams = ArrayList() @@ -420,31 +416,30 @@ class AnonymousObjectTransformer( //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) + 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) - } + toDelete.add(parameterAload.previous) + toDelete.add(parameterAload) + toDelete.add(fieldNode) + } constructor.remove(toDelete) constructorParamBuilder.addThis(oldObjectType, false) @@ -456,8 +451,7 @@ class AnonymousObjectTransformer( parameterInfo.lambda = info if (capturedParams.contains(parameterInfo.index)) { parameterInfo.isCaptured = true - } - else { + } else { //otherwise it's super constructor parameter } } @@ -466,7 +460,8 @@ class AnonymousObjectTransformer( //TODO: some of such parameters could be skipped - we should perform additional analysis val capturedLambdasToInline = HashMap() //captured var of inlined parameter val allRecapturedParameters = ArrayList() - val addCapturedNotAddOuter = parentFieldRemapper.isRoot || parentFieldRemapper is InlinedLambdaRemapper && parentFieldRemapper.parent!!.isRoot + val addCapturedNotAddOuter = + parentFieldRemapper.isRoot || parentFieldRemapper is InlinedLambdaRemapper && parentFieldRemapper.parent!!.isRoot val alreadyAdded = HashMap() for (info in capturedLambdas) { if (addCapturedNotAddOuter) { @@ -475,16 +470,16 @@ class AnonymousObjectTransformer( val alreadyAddedParam = alreadyAdded[key] val recapturedParamInfo = capturedParamBuilder.addCapturedParam( - desc, - alreadyAddedParam?.newFieldName ?: getNewFieldName(desc.fieldName, false), - alreadyAddedParam != null + desc, + alreadyAddedParam?.newFieldName ?: getNewFieldName(desc.fieldName, false), + alreadyAddedParam != null ) val composed = StackValue.field( - desc.type, - oldObjectType, /*TODO owner type*/ - recapturedParamInfo.newFieldName, - false, - StackValue.LOCAL_0 + desc.type, + oldObjectType, /*TODO owner type*/ + recapturedParamInfo.newFieldName, + false, + StackValue.LOCAL_0 ) recapturedParamInfo.remapValue = composed allRecapturedParameters.add(desc) @@ -501,8 +496,8 @@ class AnonymousObjectTransformer( if (parentFieldRemapper is InlinedLambdaRemapper && !capturedLambdas.isEmpty() && !addCapturedNotAddOuter) { //lambda with non InlinedLambdaRemapper already have outer - val parent = parentFieldRemapper.parent as? RegeneratedLambdaFieldRemapper ?: - throw AssertionError("Expecting RegeneratedLambdaFieldRemapper, but ${parentFieldRemapper.parent}") + val parent = parentFieldRemapper.parent as? RegeneratedLambdaFieldRemapper + ?: throw AssertionError("Expecting RegeneratedLambdaFieldRemapper, but ${parentFieldRemapper.parent}") val ownerType = Type.getObjectType(parent.originalLambdaInternalName) val desc = CapturedParamDesc(ownerType, AsmUtil.THIS, ownerType) val recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, AsmUtil.CAPTURED_THIS_FIELD/*outer lambda/object*/, false) @@ -521,17 +516,15 @@ class AnonymousObjectTransformer( private fun shouldRenameThis0(parentFieldRemapper: FieldRemapper, values: Collection): Boolean { return if (isFirstDeclSiteLambdaFieldRemapper(parentFieldRemapper)) { - values.any { it.capturedVars.any { isThis0(it.fieldName) }} - } - else false + values.any { it.capturedVars.any { isThis0(it.fieldName) } } + } else false } private fun getNewFieldName(oldName: String, originalField: Boolean): String { if (AsmUtil.CAPTURED_THIS_FIELD == oldName) { return if (!originalField) { oldName - } - else { + } else { //rename original 'this$0' in declaration site lambda (inside inline function) to use this$0 only for outer lambda/object access on call site addUniqueField(oldName + INLINE_FUN_THIS_0_SUFFIX) } @@ -548,5 +541,5 @@ class AnonymousObjectTransformer( } private fun isFirstDeclSiteLambdaFieldRemapper(parentRemapper: FieldRemapper): Boolean = - parentRemapper !is RegeneratedLambdaFieldRemapper && parentRemapper !is InlinedLambdaRemapper + parentRemapper !is RegeneratedLambdaFieldRemapper && parentRemapper !is InlinedLambdaRemapper } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/CoveringTryCatchNodeProcessor.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/CoveringTryCatchNodeProcessor.kt index 2d9fa07d12d..977b9b985e9 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/CoveringTryCatchNodeProcessor.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/CoveringTryCatchNodeProcessor.kt @@ -133,8 +133,7 @@ class IntervalMetaInfo>(private val processor: Coverin val split = interval.split(by, keepStart) if (!keepStart) { remapStartLabel(split.newPart.startLabel, split.patchedPart) - } - else { + } else { remapEndLabel(split.newPart.endLabel, split.patchedPart) } addNewInterval(split.newPart) @@ -149,7 +148,7 @@ class IntervalMetaInfo>(private val processor: Coverin } private fun getInterval(curIns: LabelNode, isOpen: Boolean) = - if (isOpen) intervalStarts.get(curIns) else intervalEnds.get(curIns) + if (isOpen) intervalStarts.get(curIns) else intervalEnds.get(curIns) } fun TryCatchBlockNode.isMeaningless() = SimpleInterval(start, end).isMeaningless() @@ -191,15 +190,16 @@ class LocalVarNodeWrapper(val node: LocalVariableNode) : Interval, SplittableInt val oldEnd = endLabel node.end = splitBy.startLabel Pair(splitBy.endLabel, oldEnd) - } - else { + } else { val oldStart = startLabel node.start = splitBy.endLabel Pair(oldStart, splitBy.startLabel) } - return SplitPair(this, LocalVarNodeWrapper( + return SplitPair( + this, LocalVarNodeWrapper( LocalVariableNode(node.name, node.desc, node.signature, newPartInterval.first, newPartInterval.second, node.index) - )) + ) + ) } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/DeferredMethodVisitor.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/DeferredMethodVisitor.kt index 60a510c5cde..cb4f2ec5c0c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/DeferredMethodVisitor.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/DeferredMethodVisitor.kt @@ -21,8 +21,8 @@ import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.tree.MethodNode class DeferredMethodVisitor( - val intermediate: MethodNode, - private val resultNode: () -> MethodVisitor + val intermediate: MethodNode, + private val resultNode: () -> MethodVisitor ) : MethodVisitor(Opcodes.API_VERSION, intermediate) { override fun visitEnd() { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/FictitiousArrayConstructor.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/FictitiousArrayConstructor.kt index ac0e1eaea71..2616e328523 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/FictitiousArrayConstructor.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/FictitiousArrayConstructor.kt @@ -21,16 +21,18 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl internal class FictitiousArrayConstructor(arrayClass: ClassDescriptor) : SimpleFunctionDescriptorImpl( - arrayClass.containingDeclaration, null, Annotations.EMPTY, arrayClass.name, CallableMemberDescriptor.Kind.SYNTHESIZED, - SourceElement.NO_SOURCE + arrayClass.containingDeclaration, null, Annotations.EMPTY, arrayClass.name, CallableMemberDescriptor.Kind.SYNTHESIZED, + SourceElement.NO_SOURCE ) { companion object Factory { @JvmStatic fun create(arrayConstructor: ConstructorDescriptor): FictitiousArrayConstructor { val arrayClass = arrayConstructor.constructedClass return FictitiousArrayConstructor(arrayClass).apply { - this.initialize(null, null, arrayConstructor.typeParameters, arrayConstructor.valueParameters, arrayClass.defaultType, - Modality.FINAL, Visibilities.PUBLIC) + this.initialize( + null, null, arrayConstructor.typeParameters, arrayConstructor.valueParameters, arrayClass.defaultType, + Modality.FINAL, Visibilities.PUBLIC + ) this.isInline = true } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/FieldRemapper.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/FieldRemapper.kt index 3f557cd7993..bbacf04ec6f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/FieldRemapper.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/FieldRemapper.kt @@ -24,9 +24,9 @@ import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode import org.jetbrains.org.objectweb.asm.tree.MethodNode open class FieldRemapper( - val originalLambdaInternalName: String?, - @JvmField val parent: FieldRemapper?, - protected val parameters: Parameters + val originalLambdaInternalName: String?, + @JvmField val parent: FieldRemapper?, + protected val parameters: Parameters ) { val isRoot = parent == null @@ -34,15 +34,15 @@ open class FieldRemapper( protected open fun canProcess(fieldOwner: String, fieldName: String, isFolding: Boolean): Boolean { return fieldOwner == originalLambdaInternalName && - //don't process general field of anonymous objects - isCapturedFieldName(fieldName) + //don't process general field of anonymous objects + isCapturedFieldName(fieldName) } fun foldFieldAccessChainIfNeeded(capturedFieldAccess: List, node: MethodNode): AbstractInsnNode? = - if (capturedFieldAccess.size == 1) - null //single aload - else - foldFieldAccessChainIfNeeded(capturedFieldAccess, 1, node) + if (capturedFieldAccess.size == 1) + null //single aload + else + foldFieldAccessChainIfNeeded(capturedFieldAccess, 1, node) /**constructors could access outer not through * ALOAD 0 //this @@ -51,13 +51,13 @@ open class FieldRemapper( * but directly through constructor parameter * ALOAD X //outer * GETFIELD this$0 //outer of outer - */ + */ open fun shouldProcessNonAload0FieldAccessChains(): Boolean = false private fun foldFieldAccessChainIfNeeded( - capturedFieldAccess: List, - currentInstruction: Int, - node: MethodNode + capturedFieldAccess: List, + currentInstruction: Int, + node: MethodNode ): AbstractInsnNode? { if (currentInstruction < capturedFieldAccess.lastIndex) { //try to fold longest chain first @@ -94,10 +94,10 @@ open class FieldRemapper( get() = originalLambdaInternalName!! open fun getFieldForInline(node: FieldInsnNode, prefix: StackValue?): StackValue? = - MethodInliner.findCapturedField(node, this).remapValue + MethodInliner.findCapturedField(node, this).remapValue companion object { fun foldName(fieldName: String) = - CAPTURED_FIELD_FOLD_PREFIX + fieldName + CAPTURED_FIELD_FOLD_PREFIX + fieldName } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCache.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCache.kt index 46ffc6430b2..1ebc0d7cd45 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCache.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCache.kt @@ -33,8 +33,7 @@ inline fun SLRUMap.getOrPut(key: K, defaultValue: () -> V): V { val answer = defaultValue() put(key, answer) answer - } - else { + } else { value } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt index 3f0d5152e09..e8890eeaa8d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt @@ -224,10 +224,10 @@ abstract class InlineCodegen( val originalSuspendLambdaDescriptor = parentContext.originalSuspendLambdaDescriptor ?: error("No original lambda descriptor found") codegen.genCoroutineInstanceForSuspendLambda(originalSuspendLambdaDescriptor) - ?: error("No stack value for coroutine instance of lambda found") + ?: error("No stack value for coroutine instance of lambda found") } else codegen.getContinuationParameterFromEnclosingSuspendFunctionDescriptor(codegen.context.functionDescriptor) - ?: error("No stack value for continuation parameter of suspend function") + ?: error("No stack value for continuation parameter of suspend function") } protected fun inlineCall(nodeAndSmap: SMAPAndMethodNode, callDefault: Boolean): InlineResult { @@ -514,10 +514,10 @@ abstract class InlineCodegen( val resultInCache = state.inlineCache.methodNodeById.getOrPut(methodId) { val result = doCreateMethodNodeFromCompiled(directMember, state, asmMethod) - ?: if (functionDescriptor.isSuspend) - doCreateMethodNodeFromCompiled(directMember, state, jvmSignature.asmMethod) - else - null + ?: if (functionDescriptor.isSuspend) + doCreateMethodNodeFromCompiled(directMember, state, jvmSignature.asmMethod) + else + null result ?: throw IllegalStateException("Couldn't obtain compiled function body for $functionDescriptor") } @@ -567,7 +567,7 @@ abstract class InlineCodegen( val bytes = state.inlineCache.classBytes.getOrPut(containerId) { findVirtualFile(state, containerId)?.contentsToByteArray() - ?: throw IllegalStateException("Couldn't find declaration file for " + containerId) + ?: throw IllegalStateException("Couldn't find declaration file for " + containerId) } val methodNode = diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlinedLambdaRemapper.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlinedLambdaRemapper.kt index c1099c2ff69..d11f5f7806d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlinedLambdaRemapper.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlinedLambdaRemapper.kt @@ -21,29 +21,29 @@ import org.jetbrains.kotlin.codegen.StackValue import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode class InlinedLambdaRemapper( - originalLambdaInternalName: String, - parent: FieldRemapper, - methodParams: Parameters, - private val isDefaultBoundCallableReference: Boolean + originalLambdaInternalName: String, + parent: FieldRemapper, + methodParams: Parameters, + private val isDefaultBoundCallableReference: Boolean ) : FieldRemapper(originalLambdaInternalName, parent, methodParams) { public override fun canProcess(fieldOwner: String, fieldName: String, isFolding: Boolean) = - isFolding && (isMyBoundReceiverForDefaultLambda(fieldOwner, fieldName) || super.canProcess(fieldOwner, fieldName, true)) + isFolding && (isMyBoundReceiverForDefaultLambda(fieldOwner, fieldName) || super.canProcess(fieldOwner, fieldName, true)) private fun isMyBoundReceiverForDefaultLambda(fieldOwner: String, fieldName: String) = - isDefaultBoundCallableReference && fieldName == AsmUtil.BOUND_REFERENCE_RECEIVER && fieldOwner == originalLambdaInternalName + isDefaultBoundCallableReference && fieldName == AsmUtil.BOUND_REFERENCE_RECEIVER && fieldOwner == originalLambdaInternalName override fun getFieldNameForFolding(insnNode: FieldInsnNode): String = - if (isMyBoundReceiverForDefaultLambda(insnNode.owner, insnNode.name)) AsmUtil.RECEIVER_PARAMETER_NAME else insnNode.name + if (isMyBoundReceiverForDefaultLambda(insnNode.owner, insnNode.name)) AsmUtil.RECEIVER_PARAMETER_NAME else insnNode.name override fun findField(fieldInsnNode: FieldInsnNode, captured: Collection) = - parent!!.findField(fieldInsnNode, captured) + parent!!.findField(fieldInsnNode, captured) override val isInsideInliningLambda: Boolean = true override fun getFieldForInline(node: FieldInsnNode, prefix: StackValue?) = - if (parent!!.isRoot) - super.getFieldForInline(node, prefix) - else - parent.getFieldForInline(node, prefix) + if (parent!!.isRoot) + super.getFieldForInline(node, prefix) + else + parent.getFieldForInline(node, prefix) } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InliningContext.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InliningContext.kt index 6ef45f69db1..fb0749a5ee1 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InliningContext.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InliningContext.kt @@ -9,39 +9,39 @@ import org.jetbrains.kotlin.codegen.ClassBuilder import org.jetbrains.kotlin.codegen.state.GenerationState class RootInliningContext( - expressionMap: Map, - state: GenerationState, - nameGenerator: NameGenerator, - val sourceCompilerForInline: SourceCompilerForInline, - override val callSiteInfo: InlineCallSiteInfo, - val inlineMethodReifier: ReifiedTypeInliner, - typeParameterMappings: TypeParameterMappings + expressionMap: Map, + state: GenerationState, + nameGenerator: NameGenerator, + val sourceCompilerForInline: SourceCompilerForInline, + override val callSiteInfo: InlineCallSiteInfo, + val inlineMethodReifier: ReifiedTypeInliner, + typeParameterMappings: TypeParameterMappings ) : InliningContext( - null, expressionMap, state, nameGenerator, TypeRemapper.createRoot(typeParameterMappings), null, false + null, expressionMap, state, nameGenerator, TypeRemapper.createRoot(typeParameterMappings), null, false ) class RegeneratedClassContext( - parent: InliningContext, - expressionMap: Map, - state: GenerationState, - nameGenerator: NameGenerator, - typeRemapper: TypeRemapper, - lambdaInfo: LambdaInfo?, - override val callSiteInfo: InlineCallSiteInfo + parent: InliningContext, + expressionMap: Map, + state: GenerationState, + nameGenerator: NameGenerator, + typeRemapper: TypeRemapper, + lambdaInfo: LambdaInfo?, + override val callSiteInfo: InlineCallSiteInfo ) : InliningContext( - parent, expressionMap, state, nameGenerator, typeRemapper, lambdaInfo, true + parent, expressionMap, state, nameGenerator, typeRemapper, lambdaInfo, true ) { val continuationBuilders: MutableMap = hashMapOf() } open class InliningContext( - val parent: InliningContext?, - val expressionMap: Map, - val state: GenerationState, - val nameGenerator: NameGenerator, - val typeRemapper: TypeRemapper, - val lambdaInfo: LambdaInfo?, - val classRegeneration: Boolean + val parent: InliningContext?, + val expressionMap: Map, + val state: GenerationState, + val nameGenerator: NameGenerator, + val typeRemapper: TypeRemapper, + val lambdaInfo: LambdaInfo?, + val classRegeneration: Boolean ) { val isInliningLambda = lambdaInfo != null @@ -57,45 +57,45 @@ open class InliningContext( fun findAnonymousObjectTransformationInfo(internalName: String, searchInParent: Boolean = true): AnonymousObjectTransformationInfo? = internalNameToAnonymousObjectTransformationInfo[internalName] - ?: if (searchInParent) parent?.findAnonymousObjectTransformationInfo(internalName, searchInParent) else null + ?: if (searchInParent) parent?.findAnonymousObjectTransformationInfo(internalName, searchInParent) else null fun recordIfNotPresent(internalName: String, info: AnonymousObjectTransformationInfo) { internalNameToAnonymousObjectTransformationInfo.putIfAbsent(internalName, info) } fun subInlineLambda(lambdaInfo: LambdaInfo): InliningContext = - subInline( - nameGenerator.subGenerator("lambda"), - //mark lambda inlined - hashMapOf(lambdaInfo.lambdaClassType.internalName to null), - lambdaInfo - ) + subInline( + nameGenerator.subGenerator("lambda"), + //mark lambda inlined + hashMapOf(lambdaInfo.lambdaClassType.internalName to null), + lambdaInfo + ) fun subInlineWithClassRegeneration( - generator: NameGenerator, - newTypeMappings: MutableMap, - callSiteInfo: InlineCallSiteInfo + generator: NameGenerator, + newTypeMappings: MutableMap, + callSiteInfo: InlineCallSiteInfo ): InliningContext = RegeneratedClassContext( - this, expressionMap, state, generator, TypeRemapper.createFrom(typeRemapper, newTypeMappings), - lambdaInfo, callSiteInfo + this, expressionMap, state, generator, TypeRemapper.createFrom(typeRemapper, newTypeMappings), + lambdaInfo, callSiteInfo ) @JvmOverloads fun subInline( - generator: NameGenerator, - additionalTypeMappings: Map = emptyMap(), - lambdaInfo: LambdaInfo? = this.lambdaInfo + generator: NameGenerator, + additionalTypeMappings: Map = emptyMap(), + lambdaInfo: LambdaInfo? = this.lambdaInfo ): InliningContext { val isInliningLambda = lambdaInfo != null return InliningContext( - this, expressionMap, state, generator, - TypeRemapper.createFrom( - typeRemapper, - additionalTypeMappings, - //root inline lambda - isInliningLambda && !this.isInliningLambda - ), - lambdaInfo, classRegeneration + this, expressionMap, state, generator, + TypeRemapper.createFrom( + typeRemapper, + additionalTypeMappings, + //root inline lambda + isInliningLambda && !this.isInliningLambda + ), + lambdaInfo, classRegeneration ) } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InternalFinallyBlockInliner.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InternalFinallyBlockInliner.java index 9d63df08747..34873255a30 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InternalFinallyBlockInliner.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InternalFinallyBlockInliner.java @@ -55,7 +55,6 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor { public boolean isEmpty() { if (!(startIns instanceof LabelNode)) { return false; - } AbstractInsnNode end = endInsExclusive; while (end != startIns && end instanceof LabelNode) { @@ -78,7 +77,8 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor { } if (hasFinallyBlocks(inlineFunTryBlockInfo)) { - new InternalFinallyBlockInliner(inlineFun, inlineFunTryBlockInfo, localVars, finallyParamOffset).processInlineFunFinallyBlocks(); + new InternalFinallyBlockInliner(inlineFun, inlineFunTryBlockInfo, localVars, finallyParamOffset) + .processInlineFunFinallyBlocks(); } } @@ -88,10 +88,12 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor { //lambdaTryCatchBlockNodes is number of TryCatchBlockNodes that was inlined with lambdas into function //due to code generation specific they placed before function TryCatchBlockNodes - private InternalFinallyBlockInliner(@NotNull MethodNode inlineFun, + private InternalFinallyBlockInliner( + @NotNull MethodNode inlineFun, @NotNull List inlineFunTryBlockInfo, @NotNull List localVariableInfo, - int finallyParamOffset) { + int finallyParamOffset + ) { super(finallyParamOffset); this.inlineFun = inlineFun; for (TryCatchBlockNodeInfo block : inlineFunTryBlockInfo) { @@ -166,7 +168,8 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor { List clusterBlocks = clusterToFindFinally.getBlocks(); TryCatchBlockNodeInfo nodeWithDefaultHandlerIfExists = clusterBlocks.get(clusterBlocks.size() - 1); - FinallyBlockInfo finallyInfo = findFinallyBlockBody(nodeWithDefaultHandlerIfExists, getTryBlocksMetaInfo().getAllIntervals()); + FinallyBlockInfo finallyInfo = + findFinallyBlockBody(nodeWithDefaultHandlerIfExists, getTryBlocksMetaInfo().getAllIntervals()); if (finallyInfo == null) continue; if (nodeWithDefaultHandlerIfExists.getOnlyCopyNotProcess()) { @@ -253,7 +256,8 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor { if (isFinallyMarker(currentIns.getNext())) { Integer constant = getConstant(currentIns); finallyBlockCopy.visitLdcInsn(constant + depthShift); - } else { + } + else { currentIns.accept(finallyBlockCopy); //VISIT } } @@ -286,7 +290,9 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor { @NotNull private static Set rememberOriginalLabelNodes(@NotNull FinallyBlockInfo finallyInfo) { Set labelsInsideFinally = new HashSet<>(); - for (AbstractInsnNode currentIns = finallyInfo.startIns; currentIns != finallyInfo.endInsExclusive; currentIns = currentIns.getNext()) { + for (AbstractInsnNode currentIns = finallyInfo.startIns; + currentIns != finallyInfo.endInsExclusive; + currentIns = currentIns.getNext()) { if (currentIns instanceof LabelNode) { labelsInsideFinally.add((LabelNode) currentIns); } @@ -326,7 +332,8 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor { tryCatchBlockNode.type); - assert inlineFun.instructions.indexOf(additionalTryCatchBlock.start) <= inlineFun.instructions.indexOf(additionalTryCatchBlock.end); + assert inlineFun.instructions.indexOf(additionalTryCatchBlock.start) <= + inlineFun.instructions.indexOf(additionalTryCatchBlock.end); tryBlocksMetaInfo.addNewInterval(new TryCatchBlockNodeInfo(additionalTryCatchBlock, true)); } @@ -350,7 +357,10 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor { TryCatchBlockNodeInfo startNode = startBlockPositions.next().getNodeInfo(); TryCatchBlockNodeInfo endNode = endBlockPosition.getNodeInfo(); - assert Objects.equal(startNode.getType(), endNode.getType()) : "Different handler types : " + startNode.getType() + " " + endNode.getType(); + assert Objects.equal(startNode.getType(), endNode.getType()) : "Different handler types : " + + startNode.getType() + + " " + + endNode.getType(); getTryBlocksMetaInfo() .split(endNode, new SimpleInterval((LabelNode) endNode.getNode().end.getLabel().info, @@ -427,9 +437,10 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor { } if (afterStartBlock) { - if (block.getNode().type == null && (firstLabelInChain(tryCatchBlock.getNode().start) == firstLabelInChain(block.getNode().start) && - firstLabelInChain(tryCatchBlock.getNode().end) == firstLabelInChain(block.getNode().end) - || defaultHandler == firstLabelInChain(block.getNode().handler))) { + if (block.getNode().type == null && + (firstLabelInChain(tryCatchBlock.getNode().start) == firstLabelInChain(block.getNode().start) && + firstLabelInChain(tryCatchBlock.getNode().end) == firstLabelInChain(block.getNode().end) + || defaultHandler == firstLabelInChain(block.getNode().handler))) { sameDefaultHandler.add(block); //first is tryCatchBlock if no catch clauses if (defaultHandler == null) { defaultHandler = firstLabelInChain(block.getNode().handler); @@ -545,5 +556,4 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor { String text = getNodeText(inlineFun); System.out.println(text); } - } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt index b4b5381daeb..9f44531ac4f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt @@ -57,7 +57,7 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : LabelOwner { for (info in capturedVars) { val field = remapper.findField(FieldInsnNode(0, info.containingLambdaName, info.fieldName, "")) - ?: error("Captured field not found: " + info.containingLambdaName + "." + info.fieldName) + ?: error("Captured field not found: " + info.containingLambdaName + "." + info.fieldName) builder.addCapturedParam(field, info.fieldName) } @@ -124,13 +124,13 @@ class DefaultLambda( }, ClassReader.SKIP_CODE or ClassReader.SKIP_FRAMES or ClassReader.SKIP_DEBUG) invokeMethodDescriptor = - parameterDescriptor.type.memberScope - .getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND) - .single() - .let { - //property reference generates erased 'get' method - if (isPropertyReference) it.original else it - } + parameterDescriptor.type.memberScope + .getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND) + .single() + .let { + //property reference generates erased 'get' method + if (isPropertyReference) it.original else it + } val descriptor = Type.getMethodDescriptor(Type.VOID_TYPE, *capturedArgs) val constructor = getMethodNode( @@ -145,15 +145,15 @@ class DefaultLambda( } capturedVars = - if (isFunctionReference || isPropertyReference) - constructor?.desc?.let { Type.getArgumentTypes(it) }?.singleOrNull()?.let { - originalBoundReceiverType = it - listOf(capturedParamDesc(AsmUtil.RECEIVER_PARAMETER_NAME, it.boxReceiverForBoundReference())) - } ?: emptyList() - else - constructor?.findCapturedFieldAssignmentInstructions()?.map { fieldNode -> - capturedParamDesc(fieldNode.name, Type.getType(fieldNode.desc)) - }?.toList() ?: emptyList() + if (isFunctionReference || isPropertyReference) + constructor?.desc?.let { Type.getArgumentTypes(it) }?.singleOrNull()?.let { + originalBoundReceiverType = it + listOf(capturedParamDesc(AsmUtil.RECEIVER_PARAMETER_NAME, it.boxReceiverForBoundReference())) + } ?: emptyList() + else + constructor?.findCapturedFieldAssignmentInstructions()?.map { fieldNode -> + capturedParamDesc(fieldNode.name, Type.getType(fieldNode.desc)) + }?.toList() ?: emptyList() isBoundCallableReference = (isFunctionReference || isPropertyReference) && capturedVars.isNotEmpty() @@ -234,7 +234,7 @@ class PsiExpressionLambda( if (function == null && expression is KtCallableReferenceExpression) { val variableDescriptor = bindingContext.get(BindingContext.VARIABLE, functionWithBodyOrCallableReference) as? VariableDescriptorWithAccessors - ?: throw AssertionError("""Reference expression not resolved to variable descriptor with accessors: ${expression.getText()}""") + ?: throw AssertionError("""Reference expression not resolved to variable descriptor with accessors: ${expression.getText()}""") classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor) lambdaClassType = typeMapper.mapClass(classDescriptor) val getFunction = PropertyReferenceCodegen.findGetFunction(variableDescriptor) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LegacyInlineSuspendUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LegacyInlineSuspendUtil.kt index 2101f93164c..f38d26f6f83 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LegacyInlineSuspendUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LegacyInlineSuspendUtil.kt @@ -28,7 +28,7 @@ import org.jetbrains.org.objectweb.asm.tree.MethodNode // before/after suspension point marks, so we detect those functions here and insert the corresponding marks fun insertLegacySuspendInlineMarks(node: MethodNode) { - with (node.instructions) { + with(node.instructions) { // look for return instruction before the end and insert "afterSuspendMarker" there insertBefore(findLastReturn(last) ?: return, produceSuspendMarker(false).instructions) // insert "beforeSuspendMarker" at the beginning diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LocalVarRemapper.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LocalVarRemapper.kt index 847ccf6a4d8..b6400d1c5e9 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LocalVarRemapper.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LocalVarRemapper.kt @@ -36,8 +36,7 @@ class LocalVarRemapper(private val params: Parameters, private val additionalShi if (!info.isSkippedOrRemapped) { remapValues[shift] = StackValue.local(realSize, AsmTypes.OBJECT_TYPE) realSize += info.getType().size - } - else { + } else { remapValues[shift] = if (info.isRemapped) info.remapValue else null if (CapturedParamInfo.isSynthetic(info)) { realSize += info.getType().size @@ -59,12 +58,10 @@ class LocalVarRemapper(private val params: Parameters, private val additionalShi } if (info.isRemapped) { return RemapInfo(info, remapped, REMAPPED) - } - else { + } else { remappedIndex = (remapped as StackValue.Local).index } - } - else { + } else { //captured params are not used directly in this inlined method, they are used in closure //except captured ones for default lambdas, they are generated in default body remappedIndex = actualParamsSize - params.argsSizeOnStack + index @@ -115,8 +112,7 @@ class LocalVarRemapper(private val params: Parameters, private val additionalShi if (remapInfo.parameterInfo != null && !isStore) { StackValue.coerce(value.type, remapInfo.parameterInfo.type, mv) } - } - else { + } else { assert(remapInfo.parameterInfo != null) { "Non local value should have parameter info" } value!!.put(remapInfo.parameterInfo!!.type, mv) } @@ -129,8 +125,8 @@ class LocalVarRemapper(private val params: Parameters, private val additionalShi } class RemapInfo( - @JvmField val parameterInfo: ParameterInfo?, - @JvmField val value: StackValue? = null, - @JvmField val status: RemapStatus = FAIL + @JvmField val parameterInfo: ParameterInfo?, + @JvmField val value: StackValue? = null, + @JvmField val status: RemapStatus = FAIL ) } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MaxLocalsCalculator.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MaxLocalsCalculator.java index db3803708c3..4ddfafa5464 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MaxLocalsCalculator.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MaxLocalsCalculator.java @@ -86,5 +86,4 @@ public class MaxLocalsCalculator extends MethodVisitor { maxLocals = nextFreeSlotNumber; } } - } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MaxStackFrameSizeAndLocalsCalculator.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MaxStackFrameSizeAndLocalsCalculator.java index efb70328e9d..2868d597c01 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MaxStackFrameSizeAndLocalsCalculator.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MaxStackFrameSizeAndLocalsCalculator.java @@ -61,6 +61,7 @@ import java.util.*; */ public class MaxStackFrameSizeAndLocalsCalculator extends MaxLocalsCalculator { private static final int[] FRAME_SIZE_CHANGE_BY_OPCODE; + static { // copy-pasted from org.jetbrains.org.objectweb.asm.Frame int i; @@ -375,7 +376,7 @@ public class MaxStackFrameSizeAndLocalsCalculator extends MaxLocalsCalculator { @NotNull Label handler, String type ) { ExceptionHandler exceptionHandler = new ExceptionHandler( - getLabelWrapper(start), getLabelWrapper(end), getLabelWrapper(handler) + getLabelWrapper(start), getLabelWrapper(end), getLabelWrapper(handler) ); exceptionHandlers.add(exceptionHandler); @@ -418,6 +419,7 @@ public class MaxStackFrameSizeAndLocalsCalculator extends MaxLocalsCalculator { private int outputStackMax = 0; private int inputStackSize = 0; + public LabelWrapper(Label label) { this.label = label; } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt index 6d01324e42e..edaae3f0824 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt @@ -45,16 +45,16 @@ import org.jetbrains.org.objectweb.asm.util.Printer import java.util.* class MethodInliner( - private val node: MethodNode, - private val parameters: Parameters, - private val inliningContext: InliningContext, - private val nodeRemapper: FieldRemapper, - private val isSameModule: Boolean, - private val errorPrefix: String, - private val sourceMapper: SourceMapper, - private val inlineCallSiteInfo: InlineCallSiteInfo, - private val inlineOnlySmapSkipper: InlineOnlySmapSkipper?, //non null only for root - private val shouldPreprocessApiVersionCalls: Boolean = false + private val node: MethodNode, + private val parameters: Parameters, + private val inliningContext: InliningContext, + private val nodeRemapper: FieldRemapper, + private val isSameModule: Boolean, + private val errorPrefix: String, + private val sourceMapper: SourceMapper, + private val inlineCallSiteInfo: InlineCallSiteInfo, + private val inlineOnlySmapSkipper: InlineOnlySmapSkipper?, //non null only for root + private val shouldPreprocessApiVersionCalls: Boolean = false ) { private val typeMapper = inliningContext.state.typeMapper private val languageVersionSettings = inliningContext.state.languageVersionSettings @@ -67,10 +67,10 @@ class MethodInliner( private var lambdasFinallyBlocks: Int = 0 fun doInline( - adapter: MethodVisitor, - remapper: LocalVarRemapper, - remapReturn: Boolean, - labelOwner: LabelOwner + adapter: MethodVisitor, + remapper: LocalVarRemapper, + remapReturn: Boolean, + labelOwner: LabelOwner ): InlineResult { return doInline(adapter, remapper, remapReturn, labelOwner, 0) } @@ -83,11 +83,11 @@ class MethodInliner( } private fun doInline( - adapter: MethodVisitor, - remapper: LocalVarRemapper, - remapReturn: Boolean, - labelOwner: LabelOwner, - finallyDeepShift: Int + adapter: MethodVisitor, + remapper: LocalVarRemapper, + remapReturn: Boolean, + labelOwner: LabelOwner, + finallyDeepShift: Int ): InlineResult { //analyze body var transformedNode = markPlacesForInlineAndRemoveInlinable(node, labelOwner, finallyDeepShift) @@ -120,8 +120,7 @@ class MethodInliner( visitor } else MethodBodyVisitor(visitor) ) - } - catch (e: Throwable) { + } catch (e: Throwable) { throw wrapException(e, transformedNode, "couldn't inline method call") } @@ -130,7 +129,7 @@ class MethodInliner( if (inliningContext.isRoot) { val remapValue = remapper.remap(parameters.argsSizeOnStack + 1).value InternalFinallyBlockInliner.processInlineFunFinallyBlocks( - resultNode, lambdasFinallyBlocks, (remapValue as StackValue.Local).index + resultNode, lambdasFinallyBlocks, (remapValue as StackValue.Local).index ) } @@ -176,9 +175,9 @@ class MethodInliner( remapper.addMapping(oldClassName, newClassName) val childInliningContext = inliningContext.subInlineWithClassRegeneration( - inliningContext.nameGenerator, - currentTypeMapping, - inlineCallSiteInfo + inliningContext.nameGenerator, + currentTypeMapping, + inlineCallSiteInfo ) val transformer = transformationInfo!!.createTransformer( childInliningContext, @@ -203,8 +202,7 @@ class MethodInliner( ReifiedTypeInliner.putNeedClassReificationMarker(mv) result.reifiedTypeParametersUsages.mergeAll(transformResult.reifiedTypeParametersUsages) } - } - else if (!transformationInfo!!.wasAlreadyRegenerated) { + } else if (!transformationInfo!!.wasAlreadyRegenerated) { result.addNotChangedClass(oldClassName) } } @@ -278,27 +276,26 @@ class MethodInliner( val lambdaParameters = info.addAllParameters(nodeRemapper) val newCapturedRemapper = InlinedLambdaRemapper( - info.lambdaClassType.internalName, nodeRemapper, lambdaParameters, - info is DefaultLambda && info.isBoundCallableReference + info.lambdaClassType.internalName, nodeRemapper, lambdaParameters, + info is DefaultLambda && info.isBoundCallableReference ) setLambdaInlining(true) val lambdaSMAP = info.node.classSMAP val childSourceMapper = - if (inliningContext.classRegeneration && !inliningContext.isInliningLambda) - NestedSourceMapper(sourceMapper, lambdaSMAP.intervals, lambdaSMAP.sourceInfo) - else if (info is DefaultLambda) { - NestedSourceMapper(sourceMapper.parent!!, lambdaSMAP.intervals, lambdaSMAP.sourceInfo) - } - else InlineLambdaSourceMapper(sourceMapper.parent!!, info.node) + if (inliningContext.classRegeneration && !inliningContext.isInliningLambda) + NestedSourceMapper(sourceMapper, lambdaSMAP.intervals, lambdaSMAP.sourceInfo) + else if (info is DefaultLambda) { + NestedSourceMapper(sourceMapper.parent!!, lambdaSMAP.intervals, lambdaSMAP.sourceInfo) + } else InlineLambdaSourceMapper(sourceMapper.parent!!, info.node) val inliner = MethodInliner( - info.node.node, lambdaParameters, inliningContext.subInlineLambda(info), - newCapturedRemapper, - if (info is DefaultLambda) isSameModule else true /*cause all nested objects in same module as lambda*/, - "Lambda inlining " + info.lambdaClassType.internalName, - childSourceMapper, inlineCallSiteInfo, null + info.node.node, lambdaParameters, inliningContext.subInlineLambda(info), + newCapturedRemapper, + if (info is DefaultLambda) isSameModule else true /*cause all nested objects in same module as lambda*/, + "Lambda inlining " + info.lambdaClassType.internalName, + childSourceMapper, inlineCallSiteInfo, null ) val varRemapper = LocalVarRemapper(lambdaParameters, valueParamShift) @@ -315,8 +312,7 @@ class MethodInliner( addInlineMarker(this, false) childSourceMapper.endMapping() inlineOnlySmapSkipper?.markCallSiteLineNumber(remappingMethodAdapter) - } - else if (isAnonymousConstructorCall(owner, name)) { //TODO add method + } else if (isAnonymousConstructorCall(owner, name)) { //TODO add method //TODO add proper message assert(transformationInfo is AnonymousObjectTransformationInfo) { " call doesn't correspond to object transformation info for '$owner.$name': $transformationInfo" @@ -366,16 +362,14 @@ class MethodInliner( } transformationInfo = null - } - else { + } else { super.visitMethodInsn(opcode, owner, name, desc, itf) } - } - else if ((!inliningContext.isInliningLambda || isDefaultLambdaWithReification(inliningContext.lambdaInfo!!)) && - ReifiedTypeInliner.isNeedClassReificationMarker(MethodInsnNode(opcode, owner, name, desc, false))) { + } else if ((!inliningContext.isInliningLambda || isDefaultLambdaWithReification(inliningContext.lambdaInfo!!)) && + ReifiedTypeInliner.isNeedClassReificationMarker(MethodInsnNode(opcode, owner, name, desc, false)) + ) { //we shouldn't process here content of inlining lambda it should be reified at external level except default lambdas - } - else { + } else { super.visitMethodInsn(opcode, owner, name, desc, itf) } } @@ -399,7 +393,7 @@ class MethodInliner( } private fun isDefaultLambdaWithReification(lambdaInfo: LambdaInfo) = - lambdaInfo is DefaultLambda && lambdaInfo.needReification + lambdaInfo is DefaultLambda && lambdaInfo.needReification private fun prepareNode(node: MethodNode, finallyDeepShift: Int): MethodNode { node.instructions.resetLabels() @@ -457,24 +451,25 @@ class MethodInliner( if (DEFAULT_LAMBDA_FAKE_CALL == owner) { val index = name.substringAfter(DEFAULT_LAMBDA_FAKE_CALL).toInt() val lambda = getLambdaIfExists(index) as DefaultLambda - lambda.parameterOffsetsInDefault.zip(lambda.capturedVars).asReversed().forEach { - (_, captured) -> + lambda.parameterOffsetsInDefault.zip(lambda.capturedVars).asReversed().forEach { (_, captured) -> val originalBoundReceiverType = lambda.originalBoundReceiverType if (lambda.isBoundCallableReference && AsmUtil.isPrimitive(originalBoundReceiverType)) { StackValue.onStack(originalBoundReceiverType!!).put(captured.type, InstructionAdapter(this)) } super.visitFieldInsn( - Opcodes.PUTSTATIC, captured.containingLambdaName, CAPTURED_FIELD_FOLD_PREFIX + captured.fieldName, captured.type.descriptor + Opcodes.PUTSTATIC, + captured.containingLambdaName, + CAPTURED_FIELD_FOLD_PREFIX + captured.fieldName, + captured.type.descriptor ) } - } - else { + } else { super.visitMethodInsn(opcode, owner, name, desc, itf) } } override fun visitLocalVariable( - name: String, desc: String, signature: String?, start: Label, end: Label, index: Int + name: String, desc: String, signature: String?, start: Label, end: Label, index: Int ) { if (isInliningLambda || GENERATE_DEBUG_INFO) { val varSuffix = if (inliningContext.isRoot && !isFakeLocalVariableForInline(name)) INLINE_FUN_VAR_SUFFIX else "" @@ -493,7 +488,7 @@ class MethodInliner( } private fun markPlacesForInlineAndRemoveInlinable( - node: MethodNode, labelOwner: LabelOwner, finallyDeepShift: Int + node: MethodNode, labelOwner: LabelOwner, finallyDeepShift: Int ): MethodNode { val processingNode = prepareNode(node, finallyDeepShift) @@ -532,23 +527,21 @@ class MethodInliner( val sourceValue = frame.getStack(firstParameterIndex) val lambdaInfo = getLambdaIfExistsAndMarkInstructions(sourceValue, true, instructions, sources, toDelete) invokeCalls.add(InvokeCall(lambdaInfo, currentFinallyDeep)) - } - else if (isSamWrapperConstructorCall(owner, name)) { + } else if (isSamWrapperConstructorCall(owner, name)) { recordTransformation(SamWrapperTransformationInfo(owner, inliningContext, isAlreadyRegenerated(owner))) - } - else if (isAnonymousConstructorCall(owner, name)) { + } else if (isAnonymousConstructorCall(owner, name)) { val lambdaMapping = HashMap() var offset = 0 var capturesAnonymousObjectThatMustBeRegenerated = false for (i in 0 until paramCount) { val sourceValue = frame.getStack(firstParameterIndex + i) - val lambdaInfo = getLambdaIfExistsAndMarkInstructions(sourceValue, false, instructions, sources, toDelete + val lambdaInfo = getLambdaIfExistsAndMarkInstructions( + sourceValue, false, instructions, sources, toDelete ) if (lambdaInfo != null) { lambdaMapping.put(offset, lambdaInfo) - } - else if (i < argTypes.size && isAnonymousClassThatMustBeRegenerated(argTypes[i])) { + } else if (i < argTypes.size && isAnonymousClassThatMustBeRegenerated(argTypes[i])) { capturesAnonymousObjectThatMustBeRegenerated = true } @@ -556,13 +549,12 @@ class MethodInliner( } recordTransformation( - buildConstructorInvocation( - owner, cur.desc, lambdaMapping, awaitClassReification, capturesAnonymousObjectThatMustBeRegenerated - ) + buildConstructorInvocation( + owner, cur.desc, lambdaMapping, awaitClassReification, capturesAnonymousObjectThatMustBeRegenerated + ) ) awaitClassReification = false - } - else if (inliningContext.isInliningLambda && ReifiedTypeInliner.isOperationReifiedMarker(cur)) { + } else if (inliningContext.isInliningLambda && ReifiedTypeInliner.isOperationReifiedMarker(cur)) { val reificationArgument = cur.reificationArgument val parameterName = reificationArgument!!.parameterName result.reifiedTypeParametersUsages.addUsedReifiedParameter(parameterName) @@ -574,23 +566,28 @@ class MethodInliner( val className = fieldInsnNode!!.owner if (isAnonymousSingletonLoad(className, fieldInsnNode.name)) { recordTransformation( - AnonymousObjectTransformationInfo( - className, awaitClassReification, isAlreadyRegenerated(className), true, - inliningContext.nameGenerator - ) + AnonymousObjectTransformationInfo( + className, awaitClassReification, isAlreadyRegenerated(className), true, + inliningContext.nameGenerator + ) ) awaitClassReification = false - } - else if (isWhenMappingAccess(className, fieldInsnNode.name)) { + } else if (isWhenMappingAccess(className, fieldInsnNode.name)) { recordTransformation( - WhenMappingTransformationInfo( - className, inliningContext.nameGenerator, isAlreadyRegenerated(className), fieldInsnNode - ) + WhenMappingTransformationInfo( + className, inliningContext.nameGenerator, isAlreadyRegenerated(className), fieldInsnNode + ) ) } } - cur.opcode == Opcodes.POP -> getLambdaIfExistsAndMarkInstructions(frame.top()!!, true, instructions, sources, toDelete)?.let { + cur.opcode == Opcodes.POP -> getLambdaIfExistsAndMarkInstructions( + frame.top()!!, + true, + instructions, + sources, + toDelete + )?.let { toDelete.add(cur) } @@ -605,9 +602,11 @@ class MethodInliner( val fieldInsn = cur as FieldInsnNode if (isCapturedFieldName(fieldInsn.name) && nodeRemapper is InlinedLambdaRemapper && - nodeRemapper.originalLambdaInternalName == fieldInsn.owner) { + nodeRemapper.originalLambdaInternalName == fieldInsn.owner + ) { val stackTransformations = mutableSetOf() - val lambdaInfo = getLambdaIfExistsAndMarkInstructions(frame.peek(1)!!, false, instructions, sources, stackTransformations) + val lambdaInfo = + getLambdaIfExistsAndMarkInstructions(frame.peek(1)!!, false, instructions, sources, stackTransformations) if (lambdaInfo != null && stackTransformations.all { it is VarInsnNode }) { assert(lambdaInfo.lambdaClassType.internalName == nodeRemapper.originalLambdaInternalName) { "Wrong bytecode template for contract template: ${lambdaInfo.lambdaClassType.internalName} != ${nodeRemapper.originalLambdaInternalName}" @@ -619,16 +618,14 @@ class MethodInliner( } } } - } - else { + } else { //given frame is null if and only if the corresponding instruction cannot be reached (dead code). //clean dead code otherwise there is problems in unreachable finally block, don't touch label it cause try/catch/finally problems if (cur.type == AbstractInsnNode.LABEL) { //NB: Cause we generate exception table for default handler using gaps (see ExpressionCodegen.visitTryExpression) //it may occurs that interval for default handler starts before catch start label, so this label seems as dead, //but as result all this labels will be merged into one (see KT-5863) - } - else { + } else { toDelete.add(cur) } } @@ -758,8 +755,7 @@ class MethodInliner( private fun preprocessNodeBeforeInline(node: MethodNode, labelOwner: LabelOwner) { try { FixStackWithLabelNormalizationMethodTransformer().transform("fake", node) - } - catch (e: Throwable) { + } catch (e: Throwable) { throw wrapException(e, node, "couldn't inline method call") } @@ -800,21 +796,21 @@ class MethodInliner( } private fun buildConstructorInvocation( - anonymousType: String, - desc: String, - lambdaMapping: Map, - needReification: Boolean, - capturesAnonymousObjectThatMustBeRegenerated: Boolean + anonymousType: String, + desc: String, + lambdaMapping: Map, + needReification: Boolean, + capturesAnonymousObjectThatMustBeRegenerated: Boolean ): AnonymousObjectTransformationInfo { val info = AnonymousObjectTransformationInfo( - anonymousType, needReification, lambdaMapping, - inliningContext.classRegeneration, - isAlreadyRegenerated(anonymousType), - desc, - false, - inliningContext.nameGenerator, - capturesAnonymousObjectThatMustBeRegenerated + anonymousType, needReification, lambdaMapping, + inliningContext.classRegeneration, + isAlreadyRegenerated(anonymousType), + desc, + false, + inliningContext.nameGenerator, + capturesAnonymousObjectThatMustBeRegenerated ) val memoizeAnonymousObject = inliningContext.findAnonymousObjectTransformationInfo(anonymousType) @@ -911,17 +907,16 @@ class MethodInliner( private fun wrapException(originalException: Throwable, node: MethodNode, errorSuffix: String): RuntimeException { return if (originalException is InlineException) { InlineException("$errorPrefix: $errorSuffix", originalException) - } - else { + } else { InlineException("$errorPrefix: $errorSuffix\nCause: ${node.nodeText}", originalException) } } private class LocalReturnsNormalizer { private class LocalReturn( - private val returnInsn: AbstractInsnNode, - private val insertBeforeInsn: AbstractInsnNode, - private val frame: Frame + private val returnInsn: AbstractInsnNode, + private val insertBeforeInsn: AbstractInsnNode, + private val frame: Frame ) { fun transform(insnList: InsnList, returnVariableIndex: Int) { @@ -958,9 +953,9 @@ class MethodInliner( private var returnOpcode = -1 internal fun addLocalReturnToTransform( - returnInsn: AbstractInsnNode, - insertBeforeInsn: AbstractInsnNode, - sourceValueFrame: Frame + returnInsn: AbstractInsnNode, + insertBeforeInsn: AbstractInsnNode, + sourceValueFrame: Frame ) { assert(isReturnOpcode(returnInsn.opcode)) { "return instruction expected" } assert(returnOpcode < 0 || returnOpcode == returnInsn.opcode) { "Return op should be " + Printer.OPCODES[returnOpcode] + ", got " + Printer.OPCODES[returnInsn.opcode] } @@ -971,8 +966,7 @@ class MethodInliner( if (returnInsn.opcode != Opcodes.RETURN) { returnVariableSize = if (returnInsn.opcode == Opcodes.LRETURN || returnInsn.opcode == Opcodes.DRETURN) { 2 - } - else { + } else { 1 } } @@ -993,9 +987,9 @@ class MethodInliner( //Place to insert finally blocks from try blocks that wraps inline fun call class PointForExternalFinallyBlocks( - @JvmField val beforeIns: AbstractInsnNode, - @JvmField val returnType: Type, - @JvmField val finallyIntervalEnd: LabelNode + @JvmField val beforeIns: AbstractInsnNode, + @JvmField val returnType: Type, + @JvmField val finallyIntervalEnd: LabelNode ) companion object { @@ -1007,7 +1001,7 @@ class MethodInliner( } val fin = FieldInsnNode(node.opcode, node.owner, node.name.substring(3), node.desc) return fieldRemapper.findField(fin) ?: throw IllegalStateException( - "Couldn't find captured field ${node.owner}.${node.name} in ${fieldRemapper.originalLambdaInternalName}" + "Couldn't find captured field ${node.owner}.${node.name} in ${fieldRemapper.originalLambdaInternalName}" ) } @@ -1028,8 +1022,7 @@ class MethodInliner( try { return analyzer.analyze("fake", node) - } - catch (e: AnalyzerException) { + } catch (e: AnalyzerException) { throw RuntimeException(e) } @@ -1041,8 +1034,7 @@ class MethodInliner( // INTRINSICS_CLASS_NAME.checkParameterIsNotNull(...) private fun removeClosureAssertions(node: MethodNode) { val toDelete = arrayListOf() - InsnSequence(node.instructions).filterIsInstance().forEach { - methodInsnNode -> + InsnSequence(node.instructions).filterIsInstance().forEach { methodInsnNode -> if (methodInsnNode.name == "checkParameterIsNotNull" && methodInsnNode.owner == IntrinsicMethods.INTRINSICS_CLASS_NAME) { val prev = methodInsnNode.previous assert(Opcodes.LDC == prev?.opcode) { "'checkParameterIsNotNull' should go after LDC but $prev" } @@ -1077,8 +1069,7 @@ class MethodInliner( private fun getCapturedFieldAccessChain(aload0: VarInsnNode): List { val lambdaAccessChain = mutableListOf(aload0).apply { - addAll(InsnSequence(aload0.next, null).filter { it.isMeaningful }.takeWhile { - insnNode -> + addAll(InsnSequence(aload0.next, null).filter { it.isMeaningful }.takeWhile { insnNode -> insnNode is FieldInsnNode && "this$0" == insnNode.name }.toList()) } @@ -1086,7 +1077,8 @@ class MethodInliner( return lambdaAccessChain.apply { last().getNextMeaningful().takeIf { insn -> insn is FieldInsnNode }?.also { //captured field access - insn -> add(insn) + insn -> + add(insn) } } } @@ -1134,7 +1126,7 @@ class MethodInliner( //process local and global returns (local substituted with goto end-label global kept unchanged) @JvmStatic fun processReturns( - node: MethodNode, labelOwner: LabelOwner, remapReturn: Boolean, endLabel: Label? + node: MethodNode, labelOwner: LabelOwner, remapReturn: Boolean, endLabel: Label? ): List { if (!remapReturn) { return emptyList() @@ -1170,9 +1162,11 @@ class MethodInliner( //generate finally block before nonLocalReturn flag/return/goto val label = LabelNode() instructions.insert(insnNode, label) - result.add(PointForExternalFinallyBlocks( + result.add( + PointForExternalFinallyBlocks( getInstructionToInsertFinallyBefore(insnNode, isLocalReturn), getReturnType(insnNode.opcode), label - )) + ) + ) } insnNode = insnNode.next } 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 1281ff84396..24d53c77ef0 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInlinerUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInlinerUtil.kt @@ -27,11 +27,11 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.Frame import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue fun MethodInliner.getLambdaIfExistsAndMarkInstructions( - sourceValue: SourceValue, - processSwap: Boolean, - insnList: InsnList, - frames: Array?>, - toDelete: MutableSet + sourceValue: SourceValue, + processSwap: Boolean, + insnList: InsnList, + frames: Array?>, + toDelete: MutableSet ): LambdaInfo? { val toDeleteInner = SmartSet.create() @@ -48,11 +48,11 @@ fun MethodInliner.getLambdaIfExistsAndMarkInstructions( private fun SourceValue.singleOrNullInsn() = insns.singleOrNull() private fun MethodInliner.getLambdaIfExistsAndMarkInstructions( - insnNode: AbstractInsnNode?, - processSwap: Boolean, - insnList: InsnList, - frames: Array?>, - toDelete: MutableSet + insnNode: AbstractInsnNode?, + processSwap: Boolean, + insnList: InsnList, + frames: Array?>, + toDelete: MutableSet ): LambdaInfo? { if (insnNode == null) return null @@ -76,8 +76,7 @@ private fun MethodInliner.getLambdaIfExistsAndMarkInstructions( return it } } - } - else if (processSwap && insnNode.opcode == Opcodes.SWAP) { + } else if (processSwap && insnNode.opcode == Opcodes.SWAP) { val swapFrame = frames[insnList.indexOf(insnNode)] ?: return null val dispatchReceiver = swapFrame.top()!! getLambdaIfExistsAndMarkInstructions(dispatchReceiver, false, insnList, frames, toDelete)?.let { @@ -100,9 +99,9 @@ fun parameterOffsets(isStatic: Boolean, valueParameters: List) = - instructions.forEach { - this@remove.instructions.remove(it) - } + instructions.forEach { + this@remove.instructions.remove(it) + } fun MethodNode.remove(instructions: Collection) { instructions.forEach { @@ -111,19 +110,18 @@ fun MethodNode.remove(instructions: Collection) { } fun MethodNode.findCapturedFieldAssignmentInstructions(): Sequence { - return InsnSequence(instructions).filterIsInstance(). - filter { fieldNode -> - //filter captured field assignment - // aload 0 - // aload x - // PUTFIELD $fieldName + return InsnSequence(instructions).filterIsInstance().filter { fieldNode -> + //filter captured field assignment + // aload 0 + // aload x + // PUTFIELD $fieldName - val prevPrev = fieldNode.previous?.previous as? VarInsnNode + val prevPrev = fieldNode.previous?.previous as? VarInsnNode - fieldNode.opcode == Opcodes.PUTFIELD && + fieldNode.opcode == Opcodes.PUTFIELD && isCapturedFieldName(fieldNode.name) && fieldNode.previous is VarInsnNode && prevPrev != null && prevPrev.`var` == 0 - } + } } fun AbstractInsnNode.getNextMeaningful(): AbstractInsnNode? { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ParametersBuilder.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ParametersBuilder.kt index a28369e7dfc..f0ee7879b48 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ParametersBuilder.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ParametersBuilder.kt @@ -28,10 +28,12 @@ class ParametersBuilder private constructor() { } fun addNextValueParameter(type: Type, skipped: Boolean, remapValue: StackValue?, parameterIndex: Int): ParameterInfo { - return addParameter(ParameterInfo( + return addParameter( + ParameterInfo( type, skipped, nextParameterOffset, remapValue, if (parameterIndex == -1) nextValueParameterIndex else parameterIndex + valueParamFirstIndex - )) + ) + ) } fun addCapturedParam(original: CapturedParamInfo, newFieldName: String): CapturedParamInfo { @@ -49,15 +51,15 @@ class ParametersBuilder private constructor() { } fun addCapturedParam( - containingLambdaType: Type, - fieldName: String, - newFieldName: String, - type: Type, - skipped: Boolean, - original: ParameterInfo? + containingLambdaType: Type, + fieldName: String, + newFieldName: String, + type: Type, + skipped: Boolean, + original: ParameterInfo? ): CapturedParamInfo { val info = CapturedParamInfo( - CapturedParamDesc(containingLambdaType, fieldName, type), newFieldName, skipped, nextParameterOffset, original?.index ?: -1 + CapturedParamDesc(containingLambdaType, fieldName, type), newFieldName, skipped, nextParameterOffset, original?.index ?: -1 ) if (original != null) { info.lambda = original.lambda @@ -65,7 +67,7 @@ class ParametersBuilder private constructor() { return addParameter(info) } - private fun addParameter(info: T): T { + private fun addParameter(info: T): T { params.add(info) nextParameterOffset += info.getType().size if (info !is CapturedParamInfo) { @@ -94,8 +96,7 @@ class ParametersBuilder private constructor() { return Parameters(params.map { param -> if (param is CapturedParamInfo) { param.cloneWithNewDeclarationIndex(nextDeclarationIndex++) - } - else { + } else { param } }) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PropertyReferenceInfo.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PropertyReferenceInfo.kt index 04d75214704..00abff3d8cc 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PropertyReferenceInfo.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PropertyReferenceInfo.kt @@ -20,5 +20,6 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptor class PropertyReferenceInfo( - val target: VariableDescriptor, - val getFunction: FunctionDescriptor) \ No newline at end of file + val target: VariableDescriptor, + val getFunction: FunctionDescriptor +) \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RegeneratedLambdaFieldRemapper.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RegeneratedLambdaFieldRemapper.kt index 8ab39f12e36..34faa979abf 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RegeneratedLambdaFieldRemapper.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RegeneratedLambdaFieldRemapper.kt @@ -24,19 +24,19 @@ import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode class RegeneratedLambdaFieldRemapper( - originalLambdaInternalName: String, - override val newLambdaInternalName: String, - parameters: Parameters, - val recapturedLambdas: Map, - remapper: FieldRemapper, - private val isConstructor: Boolean + originalLambdaInternalName: String, + override val newLambdaInternalName: String, + parameters: Parameters, + val recapturedLambdas: Map, + remapper: FieldRemapper, + private val isConstructor: Boolean ) : FieldRemapper(originalLambdaInternalName, remapper, parameters) { public override fun canProcess(fieldOwner: String, fieldName: String, isFolding: Boolean) = - super.canProcess(fieldOwner, fieldName, isFolding) || isRecapturedLambdaType(fieldOwner, isFolding) + super.canProcess(fieldOwner, fieldName, isFolding) || isRecapturedLambdaType(fieldOwner, isFolding) private fun isRecapturedLambdaType(owner: String, isFolding: Boolean) = - recapturedLambdas.containsKey(owner) && (isFolding || parent !is InlinedLambdaRemapper) + recapturedLambdas.containsKey(owner) && (isFolding || parent !is InlinedLambdaRemapper) override fun findField(fieldInsnNode: FieldInsnNode, captured: Collection): CapturedParamInfo? { val searchInParent = !canProcess(fieldInsnNode.owner, fieldInsnNode.name, false) @@ -65,22 +65,23 @@ class RegeneratedLambdaFieldRemapper( val fin = FieldInsnNode(node.opcode, node.owner, fieldName.substringAfter(CAPTURED_FIELD_FOLD_PREFIX), node.desc) var fromParent = false val field = findFieldInSuper(fin) ?: - //search in parent - findFieldInSuper(FieldInsnNode( - Opcodes.GETSTATIC, originalLambdaInternalName, AsmUtil.CAPTURED_THIS_FIELD, - Type.getObjectType(parent!!.originalLambdaInternalName!!).descriptor - ))?.also { fromParent = true } ?: - throw AssertionError("Couldn't find captured this $originalLambdaInternalName for $fieldName") + //search in parent + findFieldInSuper( + FieldInsnNode( + Opcodes.GETSTATIC, originalLambdaInternalName, AsmUtil.CAPTURED_THIS_FIELD, + Type.getObjectType(parent!!.originalLambdaInternalName!!).descriptor + ) + )?.also { fromParent = true } ?: throw AssertionError("Couldn't find captured this $originalLambdaInternalName for $fieldName") val result = StackValue.field( - if (field.isSkipped) - Type.getObjectType(parent!!.parent!!.newLambdaInternalName) - else - field.getType(), - Type.getObjectType(newLambdaInternalName), /*TODO owner type*/ - field.newFieldName, false, - prefix ?: StackValue.LOCAL_0 + if (field.isSkipped) + Type.getObjectType(parent!!.parent!!.newLambdaInternalName) + else + field.getType(), + Type.getObjectType(newLambdaInternalName), /*TODO owner type*/ + field.newFieldName, false, + prefix ?: StackValue.LOCAL_0 ) return if (fromParent) parent!!.getFieldForInline(node, result) else result diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt index 3fd1cfe8603..8be634909cf 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt @@ -32,18 +32,21 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter import org.jetbrains.org.objectweb.asm.tree.* class ReificationArgument( - val parameterName: String, val nullable: Boolean, private val arrayDepth: Int + val parameterName: String, val nullable: Boolean, private val arrayDepth: Int ) { fun asString() = "[".repeat(arrayDepth) + parameterName + (if (nullable) "?" else "") fun combine(replacement: ReificationArgument) = - ReificationArgument( - replacement.parameterName, - this.nullable || (replacement.nullable && this.arrayDepth == 0), - this.arrayDepth + replacement.arrayDepth - ) + ReificationArgument( + replacement.parameterName, + this.nullable || (replacement.nullable && this.arrayDepth == 0), + this.arrayDepth + replacement.arrayDepth + ) fun reify(replacementAsmType: Type, kotlinType: KotlinType) = - Pair(Type.getType("[".repeat(arrayDepth) + replacementAsmType), TypeUtils.makeNullableIfNeeded(kotlinType.arrayOf(arrayDepth), nullable)) + Pair( + Type.getType("[".repeat(arrayDepth) + replacementAsmType), + TypeUtils.makeNullableIfNeeded(kotlinType.arrayOf(arrayDepth), nullable) + ) private fun KotlinType.arrayOf(arrayDepth: Int): KotlinType { val builtins = this.builtIns @@ -69,7 +72,7 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?, const val NEED_CLASS_REIFICATION_MARKER_METHOD_NAME = "needClassReification" fun isOperationReifiedMarker(insn: AbstractInsnNode) = - isReifiedMarker(insn) { it == REIFIED_OPERATION_MARKER_METHOD_NAME } + isReifiedMarker(insn) { it == REIFIED_OPERATION_MARKER_METHOD_NAME } private fun isReifiedMarker(insn: AbstractInsnNode, namePredicate: (String) -> Boolean): Boolean { if (insn.opcode != Opcodes.INVOKESTATIC || insn !is MethodInsnNode) return false @@ -78,14 +81,14 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?, @JvmStatic fun isNeedClassReificationMarker(insn: AbstractInsnNode): Boolean = - isReifiedMarker(insn) { s -> s == NEED_CLASS_REIFICATION_MARKER_METHOD_NAME } + isReifiedMarker(insn) { s -> s == NEED_CLASS_REIFICATION_MARKER_METHOD_NAME } @JvmStatic fun putNeedClassReificationMarker(v: MethodVisitor) { v.visitMethodInsn( - Opcodes.INVOKESTATIC, - IntrinsicMethods.INTRINSICS_CLASS_NAME, NEED_CLASS_REIFICATION_MARKER_METHOD_NAME, - Type.getMethodDescriptor(Type.VOID_TYPE), false + Opcodes.INVOKESTATIC, + IntrinsicMethods.INTRINSICS_CLASS_NAME, NEED_CLASS_REIFICATION_MARKER_METHOD_NAME, + Type.getMethodDescriptor(Type.VOID_TYPE), false ) } } @@ -134,21 +137,21 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?, val (asmType, kotlinType) = reificationArgument.reify(mapping.asmType, mapping.type) if (when (operationKind) { - OperationKind.NEW_ARRAY -> processNewArray(insn, asmType) - OperationKind.AS -> processAs(insn, instructions, kotlinType, asmType, safe = false) - OperationKind.SAFE_AS -> processAs(insn, instructions, kotlinType, asmType, safe = true) - OperationKind.IS -> processIs(insn, instructions, kotlinType, asmType) - OperationKind.JAVA_CLASS -> processJavaClass(insn, asmType) - OperationKind.ENUM_REIFIED -> processSpecialEnumFunction(insn, instructions, asmType) - }) { + OperationKind.NEW_ARRAY -> processNewArray(insn, asmType) + OperationKind.AS -> processAs(insn, instructions, kotlinType, asmType, safe = false) + OperationKind.SAFE_AS -> processAs(insn, instructions, kotlinType, asmType, safe = true) + OperationKind.IS -> processIs(insn, instructions, kotlinType, asmType) + OperationKind.JAVA_CLASS -> processJavaClass(insn, asmType) + OperationKind.ENUM_REIFIED -> processSpecialEnumFunction(insn, instructions, asmType) + } + ) { instructions.remove(insn.previous.previous!!) // PUSH operation ID instructions.remove(insn.previous!!) // PUSH type parameter instructions.remove(insn) // INVOKESTATIC marker method } return null - } - else { + } else { val newReificationArgument = reificationArgument.combine(mapping.reificationArgument!!) instructions.set(insn.previous!!, LdcInsnNode(newReificationArgument.asString())) return mapping.reificationArgument.parameterName @@ -156,14 +159,14 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?, } private fun processNewArray(insn: MethodInsnNode, parameter: Type) = - processNextTypeInsn(insn, parameter, Opcodes.ANEWARRAY) + processNextTypeInsn(insn, parameter, Opcodes.ANEWARRAY) private fun processAs( - insn: MethodInsnNode, - instructions: InsnList, - kotlinType: KotlinType, - asmType: Type, - safe: Boolean + insn: MethodInsnNode, + instructions: InsnList, + kotlinType: KotlinType, + asmType: Type, + safe: Boolean ) = rewriteNextTypeInsn(insn, Opcodes.CHECKCAST) { stubCheckcast: AbstractInsnNode -> if (stubCheckcast !is TypeInsnNode) return false @@ -180,10 +183,10 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?, } private fun processIs( - insn: MethodInsnNode, - instructions: InsnList, - kotlinType: KotlinType, - asmType: Type + insn: MethodInsnNode, + instructions: InsnList, + kotlinType: KotlinType, + asmType: Type ) = rewriteNextTypeInsn(insn, Opcodes.INSTANCEOF) { stubInstanceOf: AbstractInsnNode -> if (stubInstanceOf !is TypeInsnNode) return false @@ -199,9 +202,9 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?, } inline private fun rewriteNextTypeInsn( - marker: MethodInsnNode, - expectedNextOpcode: Int, - rewrite: (AbstractInsnNode) -> Boolean + marker: MethodInsnNode, + expectedNextOpcode: Int, + rewrite: (AbstractInsnNode) -> Boolean ): Boolean { val next = marker.next ?: return false if (next.opcode != expectedNextOpcode) return false @@ -232,8 +235,7 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?, next3.desc = getSpecialEnumFunDescriptor(parameter, true) return true } - } - else if (next1.opcode == Opcodes.ICONST_0 && next2.opcode == Opcodes.ANEWARRAY) { + } else if (next1.opcode == Opcodes.ICONST_0 && next2.opcode == Opcodes.ANEWARRAY) { instructions.remove(next1) instructions.remove(next2) val desc = getSpecialEnumFunDescriptor(parameter, false) @@ -261,23 +263,29 @@ val MethodInsnNode.reificationArgument: ReificationArgument? return ReificationArgument(parameterName, nullable, arrayDepth) } -val MethodInsnNode.operationKind: ReifiedTypeInliner.OperationKind? get() = - previous?.previous?.intConstant?.let { - ReifiedTypeInliner.OperationKind.values().getOrNull(it) - } +val MethodInsnNode.operationKind: ReifiedTypeInliner.OperationKind? + get() = + previous?.previous?.intConstant?.let { + ReifiedTypeInliner.OperationKind.values().getOrNull(it) + } class TypeParameterMappings() { private val mappingsByName = hashMapOf() fun addParameterMappingToType(name: String, type: KotlinType, asmType: Type, signature: String, isReified: Boolean) { mappingsByName[name] = TypeParameterMapping( - name, type, asmType, reificationArgument = null, signature = signature, isReified = isReified + name, type, asmType, reificationArgument = null, signature = signature, isReified = isReified ) } - fun addParameterMappingForFurtherReification(name: String, type: KotlinType, reificationArgument: ReificationArgument, isReified: Boolean) { + fun addParameterMappingForFurtherReification( + name: String, + type: KotlinType, + reificationArgument: ReificationArgument, + isReified: Boolean + ) { mappingsByName[name] = TypeParameterMapping( - name, type, asmType = null, reificationArgument = reificationArgument, signature = null, isReified = isReified + name, type, asmType = null, reificationArgument = reificationArgument, signature = null, isReified = isReified ) } @@ -285,18 +293,18 @@ class TypeParameterMappings() { fun hasReifiedParameters() = mappingsByName.values.any { it.isReified } - internal inline fun forEach(l: (TypeParameterMapping) -> Unit) { + internal inline fun forEach(l: (TypeParameterMapping) -> Unit) { mappingsByName.values.forEach(l) } } class TypeParameterMapping( - val name: String, - val type: KotlinType, - val asmType: Type?, - val reificationArgument: ReificationArgument?, - val signature: String?, - val isReified: Boolean + val name: String, + val type: KotlinType, + val asmType: Type?, + val reificationArgument: ReificationArgument?, + val signature: String?, + val isReified: Boolean ) class ReifiedTypeParametersUsages { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RemappingClassBuilder.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RemappingClassBuilder.java index a17e613eb42..25c682c5942 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RemappingClassBuilder.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RemappingClassBuilder.java @@ -54,7 +54,8 @@ public class RemappingClassBuilder extends DelegatingClassBuilder { @NotNull String superName, @NotNull String[] interfaces ) { - super.defineClass(origin, version, access, remapper.mapType(name), remapper.mapSignature(signature, false), remapper.mapType(superName), remapper.mapTypes(interfaces)); + super.defineClass(origin, version, access, remapper.mapType(name), remapper.mapSignature(signature, false), + remapper.mapType(superName), remapper.mapTypes(interfaces)); } @Override diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAP.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAP.kt index d860d88b412..8c8600281e0 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAP.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAP.kt @@ -109,7 +109,7 @@ open class NestedSourceMapper( } else { val rangeForMapping = (if (lastVisitedRange?.contains(lineNumber) == true) lastVisitedRange!! else findMappingIfExists(lineNumber)) - ?: error("Can't find range to map line $lineNumber in ${sourceInfo.source}: ${sourceInfo.pathOrCleanFQN}") + ?: error("Can't find range to map line $lineNumber in ${sourceInfo.source}: ${sourceInfo.pathOrCleanFQN}") val sourceLineNumber = rangeForMapping.mapDestToSource(lineNumber) val newLineNumber = parent.mapLineNumber(sourceLineNumber, rangeForMapping.parent!!.name, rangeForMapping.parent!!.path) if (newLineNumber > 0) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPAndMethodNode.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPAndMethodNode.kt index c3cc2fc2146..55834a9131d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPAndMethodNode.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPAndMethodNode.kt @@ -30,8 +30,7 @@ class SMAPAndMethodNode(val node: MethodNode, val classSMAP: SMAP) { private fun createLineNumberSequence(node: MethodNode, classSMAP: SMAP): Sequence { return InsnSequence(node.instructions.first, null).filterIsInstance().map { lineNumber -> - val index = classSMAP.intervals.binarySearch(RangeMapping(lineNumber.line, lineNumber.line, 1), Comparator { - value, key -> + val index = classSMAP.intervals.binarySearch(RangeMapping(lineNumber.line, lineNumber.line, 1), Comparator { value, key -> if (key.dest in value) 0 else RangeMapping.Comparator.compare(value, key) }) if (index < 0) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPParser.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPParser.kt index be82f1d879c..9106cbd5f12 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPParser.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPParser.kt @@ -25,15 +25,15 @@ object SMAPParser { } val mapping = - if (source == null || source.isEmpty() || methodStartLine > methodEndLine) - FileMapping.SKIP - else - FileMapping(source, path).apply { - if (methodStartLine <= methodEndLine) { - //one to one - addRangeMapping(RangeMapping(methodStartLine, methodStartLine, methodEndLine - methodStartLine + 1)) - } + if (source == null || source.isEmpty() || methodStartLine > methodEndLine) + FileMapping.SKIP + else + FileMapping(source, path).apply { + if (methodStartLine <= methodEndLine) { + //one to one + addRangeMapping(RangeMapping(methodStartLine, methodStartLine, methodEndLine - methodStartLine + 1)) } + } return SMAP(listOf(mapping)) } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SamWrapperTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SamWrapperTransformer.kt index cf2246ff549..db67b66d6bd 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SamWrapperTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SamWrapperTransformer.kt @@ -20,19 +20,23 @@ import org.jetbrains.org.objectweb.asm.ClassReader import org.jetbrains.org.objectweb.asm.ClassVisitor import org.jetbrains.org.objectweb.asm.Opcodes -class SamWrapperTransformationInfo(override val oldClassName: String, private val inliningContext: InliningContext, private val alreadyRegenerated: Boolean): TransformationInfo { +class SamWrapperTransformationInfo( + override val oldClassName: String, + private val inliningContext: InliningContext, + private val alreadyRegenerated: Boolean +) : TransformationInfo { override val nameGenerator: NameGenerator - get() = object: NameGenerator("stub") { + get() = object : NameGenerator("stub") { override fun getGeneratorClass(): String { - error ("Shouldn't be called on $oldClassName transformation") + error("Shouldn't be called on $oldClassName transformation") } override fun subGenerator(inliningMethod: String?): NameGenerator { - error ("Shouldn't be called on $oldClassName transformation") + error("Shouldn't be called on $oldClassName transformation") } override fun subGenerator(lambdaNoWhen: Boolean, nameSuffix: String?): NameGenerator { - error ("Shouldn't be called on $oldClassName transformation") + error("Shouldn't be called on $oldClassName transformation") } } @@ -45,11 +49,11 @@ class SamWrapperTransformationInfo(override val oldClassName: String, private va override fun canRemoveAfterTransformation() = false override fun createTransformer(inliningContext: InliningContext, sameModule: Boolean, continuationClassName: String?) = - SamWrapperTransformer(this, inliningContext) + SamWrapperTransformer(this, inliningContext) } class SamWrapperTransformer(transformationInfo: SamWrapperTransformationInfo, private val inliningContext: InliningContext) : - ObjectTransformer(transformationInfo, inliningContext.state) { + ObjectTransformer(transformationInfo, inliningContext.state) { override fun doTransform(parentRemapper: FieldRemapper): InlineResult { val classReader = createClassReader() diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TransformationInfo.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TransformationInfo.kt index ff5237e7bd3..141a5cd4f17 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TransformationInfo.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TransformationInfo.kt @@ -38,10 +38,10 @@ interface TransformationInfo { } class WhenMappingTransformationInfo( - override val oldClassName: String, - parentNameGenerator: NameGenerator, - private val alreadyRegenerated: Boolean, - val fieldNode: FieldInsnNode + override val oldClassName: String, + parentNameGenerator: NameGenerator, + private val alreadyRegenerated: Boolean, + val fieldNode: FieldInsnNode ) : TransformationInfo { override val nameGenerator by lazy { @@ -52,8 +52,12 @@ class WhenMappingTransformationInfo( override fun canRemoveAfterTransformation(): Boolean = true - override fun createTransformer(inliningContext: InliningContext, sameModule: Boolean, continuationClassName: String?): ObjectTransformer<*> = - WhenMappingTransformer(this, inliningContext) + override fun createTransformer( + inliningContext: InliningContext, + sameModule: Boolean, + continuationClassName: String? + ): ObjectTransformer<*> = + WhenMappingTransformer(this, inliningContext) companion object { const val TRANSFORMED_WHEN_MAPPING_MARKER = "\$wm$" @@ -61,15 +65,15 @@ class WhenMappingTransformationInfo( } class AnonymousObjectTransformationInfo internal constructor( - override val oldClassName: String, - private val needReification: Boolean, - val lambdasToInline: Map, - private val capturedOuterRegenerated: Boolean, - private val alreadyRegenerated: Boolean, - val constructorDesc: String?, - private val isStaticOrigin: Boolean, - parentNameGenerator: NameGenerator, - private val capturesAnonymousObjectThatMustBeRegenerated: Boolean = false + override val oldClassName: String, + private val needReification: Boolean, + val lambdasToInline: Map, + private val capturedOuterRegenerated: Boolean, + private val alreadyRegenerated: Boolean, + val constructorDesc: String?, + private val isStaticOrigin: Boolean, + parentNameGenerator: NameGenerator, + private val capturesAnonymousObjectThatMustBeRegenerated: Boolean = false ) : TransformationInfo { override val nameGenerator by lazy { @@ -86,16 +90,16 @@ class AnonymousObjectTransformationInfo internal constructor( get() = alreadyRegenerated constructor( - ownerInternalName: String, - needReification: Boolean, - alreadyRegenerated: Boolean, - isStaticOrigin: Boolean, - nameGenerator: NameGenerator + ownerInternalName: String, + needReification: Boolean, + alreadyRegenerated: Boolean, + isStaticOrigin: Boolean, + nameGenerator: NameGenerator ) : this(ownerInternalName, needReification, hashMapOf(), false, alreadyRegenerated, null, isStaticOrigin, nameGenerator) override fun shouldRegenerate(sameModule: Boolean): Boolean = - !alreadyRegenerated && - (!lambdasToInline.isEmpty() || !sameModule || capturedOuterRegenerated || needReification || capturesAnonymousObjectThatMustBeRegenerated) + !alreadyRegenerated && + (!lambdasToInline.isEmpty() || !sameModule || capturedOuterRegenerated || needReification || capturesAnonymousObjectThatMustBeRegenerated) override fun canRemoveAfterTransformation(): Boolean { // Note: It is unsafe to remove anonymous class that is referenced by GETSTATIC within lambda diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TryBlockClustering.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TryBlockClustering.kt index ecd19139e41..faf38bc9db6 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TryBlockClustering.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TryBlockClustering.kt @@ -38,7 +38,7 @@ interface Interval { fun isEmpty(): Boolean = startLabel == endLabel fun verify(processor: CoveringTryCatchNodeProcessor) { - assert (processor.instructionIndex(startLabel) <= processor.instructionIndex(endLabel)) { + assert(processor.instructionIndex(startLabel) <= processor.instructionIndex(endLabel)) { "Try block body starts after body end: ${processor.instructionIndex(startLabel)} > ${processor.instructionIndex(endLabel)}" } } @@ -54,8 +54,8 @@ interface IntervalWithHandler : Interval { } class TryCatchBlockNodeInfo( - val node: TryCatchBlockNode, - val onlyCopyNotProcess: Boolean + val node: TryCatchBlockNode, + val onlyCopyNotProcess: Boolean ) : IntervalWithHandler, SplittableInterval { override val startLabel: LabelNode get() = node.start @@ -71,15 +71,14 @@ class TryCatchBlockNodeInfo( val oldEnd = endLabel node.end = splitBy.startLabel Pair(splitBy.endLabel, oldEnd) - } - else { + } else { val oldStart = startLabel node.start = splitBy.endLabel Pair(oldStart, splitBy.startLabel) } return SplitPair( - this, - TryCatchBlockNodeInfo(TryCatchBlockNode(newPartInterval.first, newPartInterval.second, handler, type), onlyCopyNotProcess) + this, + TryCatchBlockNodeInfo(TryCatchBlockNode(newPartInterval.first, newPartInterval.second, handler, type), onlyCopyNotProcess) ) } } @@ -88,8 +87,8 @@ val TryCatchBlockNodeInfo.bodyInstuctions get() = InsnSequence(startLabel, endLabel) class TryCatchBlockNodePosition( - val nodeInfo: TryCatchBlockNodeInfo, - var position: TryCatchPosition + val nodeInfo: TryCatchBlockNodeInfo, + var position: TryCatchPosition ) : IntervalWithHandler by nodeInfo class TryBlockCluster(val blocks: MutableList) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TypeRemapper.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TypeRemapper.kt index 23969de4940..c0ff87950cc 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TypeRemapper.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TypeRemapper.kt @@ -22,9 +22,9 @@ class TypeParameter(val oldName: String, val newName: String?, val isReified: Bo //typeMapping data could be changed outside through method processing class TypeRemapper private constructor( - private val typeMapping: MutableMap, - val parent: TypeRemapper? = null, - private val isRootInlineLambda: Boolean = false + private val typeMapping: MutableMap, + val parent: TypeRemapper? = null, + private val isRootInlineLambda: Boolean = false ) { private val additionalMappings = hashMapOf() private val typeParametersMapping = hashMapOf() @@ -54,7 +54,7 @@ class TypeRemapper private constructor( fun registerTypeParameter(mapping: TypeParameterMapping) { typeParametersMapping[mapping.name] = TypeParameter( - mapping.name, mapping.reificationArgument?.parameterName, mapping.isReified, mapping.signature + mapping.name, mapping.reificationArgument?.parameterName, mapping.isReified, mapping.signature ) } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/defaultMethodUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/defaultMethodUtil.kt index 8ef3da3c80a..1576a0eb879 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/defaultMethodUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/defaultMethodUtil.kt @@ -32,21 +32,24 @@ import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.tree.* private data class Condition( - val mask: Int, val constant: Int, - val maskInstruction: VarInsnNode, - val jumpInstruction: JumpInsnNode, - val varInsNode: VarInsnNode? + val mask: Int, val constant: Int, + val maskInstruction: VarInsnNode, + val jumpInstruction: JumpInsnNode, + val varInsNode: VarInsnNode? ) { val expandNotDelete = mask and constant != 0 val varIndex = varInsNode?.`var` ?: 0 } -fun extractDefaultLambdaOffsetAndDescriptor(jvmSignature: JvmMethodSignature, functionDescriptor: FunctionDescriptor): Map { +fun extractDefaultLambdaOffsetAndDescriptor( + jvmSignature: JvmMethodSignature, + functionDescriptor: FunctionDescriptor +): Map { val valueParameters = jvmSignature.valueParameters val containingDeclaration = functionDescriptor.containingDeclaration val kind = - if (DescriptorUtils.isInterface(containingDeclaration)) OwnerKind.DEFAULT_IMPLS - else OwnerKind.getMemberOwnerKind(containingDeclaration) + if (DescriptorUtils.isInterface(containingDeclaration)) OwnerKind.DEFAULT_IMPLS + else OwnerKind.getMemberOwnerKind(containingDeclaration) val parameterOffsets = parameterOffsets(AsmUtil.isStaticMethod(kind, functionDescriptor), valueParameters) val valueParameterOffset = valueParameters.takeWhile { it.kind != JvmMethodParameterKind.VALUE }.size @@ -59,11 +62,11 @@ fun extractDefaultLambdaOffsetAndDescriptor(jvmSignature: JvmMethodSignature, fu fun expandMaskConditionsAndUpdateVariableNodes( - node: MethodNode, - maskStartIndex: Int, - masks: List, - methodHandlerIndex: Int, - defaultLambdas: Map + node: MethodNode, + maskStartIndex: Int, + masks: List, + methodHandlerIndex: Int, + defaultLambdas: Map ): List { fun isMaskIndex(varIndex: Int): Boolean { return maskStartIndex <= varIndex && varIndex < maskStartIndex + masks.size @@ -74,8 +77,7 @@ fun expandMaskConditionsAndUpdateVariableNodes( if (isMaskIndex(it.`var`)) { /*if slot for default mask is updated than we occurred in actual function body*/ return@takeWhile it.opcode == Opcodes.ILOAD - } - else if (methodHandlerIndex == it.`var`) { + } else if (methodHandlerIndex == it.`var`) { return@takeWhile it.opcode == Opcodes.ALOAD } } @@ -85,24 +87,24 @@ fun expandMaskConditionsAndUpdateVariableNodes( val conditions = maskProcessingHeader.filterIsInstance().mapNotNull { if (isMaskIndex(it.`var`) && it.next?.next?.opcode == Opcodes.IAND && - it.next.next.next?.opcode == Opcodes.IFEQ) { + it.next.next.next?.opcode == Opcodes.IFEQ + ) { val jumpInstruction = it.next?.next?.next as JumpInsnNode Condition( - masks[it.`var` - maskStartIndex], - getConstant(it.next), - it, - jumpInstruction, - jumpInstruction.label.previous as VarInsnNode + masks[it.`var` - maskStartIndex], + getConstant(it.next), + it, + jumpInstruction, + jumpInstruction.label.previous as VarInsnNode ) - } - else if (methodHandlerIndex == it.`var` && - it.next?.opcode == Opcodes.IFNULL && - it.next.next?.opcode == Opcodes.NEW) { + } else if (methodHandlerIndex == it.`var` && + it.next?.opcode == Opcodes.IFNULL && + it.next.next?.opcode == Opcodes.NEW + ) { //Always delete method handle for now //This logic should be updated when method handles would be supported Condition(0, 0, it, it.next as JumpInsnNode, null) - } - else null + } else null }.toList() val toDelete = linkedSetOf() @@ -136,10 +138,10 @@ fun expandMaskConditionsAndUpdateVariableNodes( private fun extractDefaultLambdasInfo( - conditions: List, - defaultLambdas: Map, - toDelete: MutableCollection, - toInsert: MutableList> + conditions: List, + defaultLambdas: Map, + toDelete: MutableCollection, + toInsert: MutableList> ): List { val defaultLambdaConditions = conditions.filter { it.expandNotDelete && defaultLambdas.contains(it.varIndex) } return defaultLambdaConditions.map { @@ -166,14 +168,16 @@ private fun extractDefaultLambdasInfo( addAll(InsnSequence(instanceInstuction, varAssignmentInstruction.next).toList()) } - val needReification = instanceCreation.previous.takeIf { isNeedClassReificationMarker(it) }?.let { toDelete.add(it) } != null + val needReification = + instanceCreation.previous.takeIf { isNeedClassReificationMarker(it) }?.let { toDelete.add(it) } != null Triple(Type.getObjectType(instanceInstuction.owner), Type.getArgumentTypes(instanceInstuction.desc), needReification) } is FieldInsnNode -> { toDelete.addAll(InsnSequence(instanceInstuction, varAssignmentInstruction.next).toList()) - val needReification = instanceInstuction.previous.takeIf { isNeedClassReificationMarker(it) }?.let { toDelete.add(it) } != null + val needReification = + instanceInstuction.previous.takeIf { isNeedClassReificationMarker(it) }?.let { toDelete.add(it) } != null Triple(Type.getObjectType(instanceInstuction.owner), emptyArray(), needReification) } @@ -190,10 +194,10 @@ private fun extractDefaultLambdasInfo( //at inlining it would be substituted with parameters store private fun defaultLambdaFakeCallStub(args: Array, lambdaOffset: Int): MethodInsnNode { return MethodInsnNode( - Opcodes.INVOKESTATIC, - DEFAULT_LAMBDA_FAKE_CALL, - DEFAULT_LAMBDA_FAKE_CALL + lambdaOffset, - Type.getMethodDescriptor(Type.VOID_TYPE, *args), - false + Opcodes.INVOKESTATIC, + DEFAULT_LAMBDA_FAKE_CALL, + DEFAULT_LAMBDA_FAKE_CALL + lambdaOffset, + Type.getMethodDescriptor(Type.VOID_TYPE, *args), + false ) } \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/inlineCodegenUtils.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/inlineCodegenUtils.kt index 27f7f907d8b..b5581814ef6 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/inlineCodegenUtils.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/inlineCodegenUtils.kt @@ -469,8 +469,10 @@ internal fun isAfterSuspendMarker(insn: AbstractInsnNode) = isSuspendMarker(insn internal fun isReturnsUnitMarker(insn: AbstractInsnNode) = isSuspendMarker(insn, INLINE_MARKER_RETURNS_UNIT) internal fun isFakeContinuationMarker(insn: AbstractInsnNode) = insn.previous != null && isSuspendMarker(insn.previous, INLINE_MARKER_FAKE_CONTINUATION) && insn.opcode == Opcodes.ACONST_NULL + internal fun isBeforeFakeContinuationConstructorCallMarker(insn: AbstractInsnNode) = isSuspendMarker(insn, INLINE_MARKER_BEFORE_FAKE_CONTINUATION_CONSTRUCTOR_CALL) + internal fun isAfterFakeContinuationConstructorCallMarker(insn: AbstractInsnNode) = isSuspendMarker(insn, INLINE_MARKER_AFTER_FAKE_CONTINUATION_CONSTRUCTOR_CALL) @@ -599,7 +601,7 @@ fun FunctionDescriptor.getClassFilePath(typeMapper: KotlinTypeMapper, cache: Inc return when (source) { is KotlinJvmBinaryPackageSourceElement -> { val directMember = JvmCodegenUtil.getDirectMember(this) as? DeserializedCallableMemberDescriptor - ?: throw AssertionError("Expected DeserializedCallableMemberDescriptor, got: $this") + ?: throw AssertionError("Expected DeserializedCallableMemberDescriptor, got: $this") val kotlinClass = source.getContainingBinaryClass(directMember) ?: throw AssertionError("Descriptor $this is not found, in: $source") if (kotlinClass !is VirtualFileKotlinClass) {