diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java index 6c7f2ea0e66..63c6f7a4bc7 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java @@ -23,8 +23,6 @@ import org.jetbrains.kotlin.codegen.AsmUtil; import org.jetbrains.kotlin.codegen.ClassBuilder; import org.jetbrains.kotlin.codegen.FieldInfo; import org.jetbrains.kotlin.codegen.StackValue; -import org.jetbrains.kotlin.codegen.state.GenerationState; -import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper; import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin; import org.jetbrains.org.objectweb.asm.*; import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; @@ -36,27 +34,16 @@ import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.isThis0; import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN; public class AnonymousObjectTransformer extends ObjectTransformer { - - protected final GenerationState state; - - protected final KotlinTypeMapper typeMapper; + private final InliningContext inliningContext; + private final Type oldObjectType; + private final boolean isSameModule; + private final Map> fieldNames = new HashMap>(); private MethodNode constructor; - private String sourceInfo; - private String debugInfo; - private SourceMapper sourceMapper; - private final InliningContext inliningContext; - - private final Type oldObjectType; - - private final boolean isSameModule; - - private final Map> fieldNames = new HashMap>(); - public AnonymousObjectTransformer( @NotNull AnonymousObjectTransformationInfo transformationInfo, @NotNull InliningContext inliningContext, @@ -64,8 +51,6 @@ public class AnonymousObjectTransformer extends ObjectTransformer")){ - if (constructor != null) + if (name.equals("")) { + if (constructor != null) { throw new RuntimeException("Lambda, SAM or anonymous object should have only one constructor"); - + } constructor = node; - } else { + } + else { methodsToTransform.add(node); } return node; } @Override - public FieldVisitor visitField( - int access, @NotNull String name, @NotNull String desc, String signature, Object value - ) { + public FieldVisitor visitField(int access, @NotNull String name, @NotNull String desc, String signature, Object value) { addUniqueField(name); if (InlineCodegenUtil.isCapturedFieldName(name)) { return null; - } else { + } + else { return classBuilder.newField(JvmDeclarationOrigin.NO_ORIGIN, access, name, desc, signature, value); } } @@ -125,7 +110,6 @@ public class AnonymousObjectTransformer extends ObjectTransformer descTypes = new ArrayList(); Parameters constructorParams = constructorInlineBuilder.buildParameters(); - int [] capturedIndexes = new int [constructorParams.getReal().size() + constructorParams.getCaptured().size()]; + int[] capturedIndexes = new int[constructorParams.getReal().size() + constructorParams.getCaptured().size()]; int index = 0; int size = 0; //complex processing cause it could have super constructor call params for (ParameterInfo info : constructorParams) { - if (!info.isSkipped()) { //not inlined + if (!info.isSkipped) { //not inlined if (info.isCaptured() || info instanceof CapturedParamInfo) { capturedIndexes[index] = size; index++; @@ -280,17 +265,16 @@ public class AnonymousObjectTransformer extends ObjectTransformer", constructorDescriptor, - null, ArrayUtil.EMPTY_STRING_ARRAY); + MethodVisitor constructorVisitor = classBuilder.newMethod( + NO_ORIGIN, AsmUtil.NO_FLAG_PACKAGE_PRIVATE, "", constructorDescriptor, null, ArrayUtil.EMPTY_STRING_ARRAY + ); final Label newBodyStartLabel = new Label(); constructorVisitor.visitLabel(newBodyStartLabel); //initialize captured fields List newFieldsWithSkipped = TransformationUtilsKt.getNewFieldsToGenerate(allCapturedBuilder.listCaptured()); - List fieldInfoWithSkipped = TransformationUtilsKt.transformToFieldInfo( - Type.getObjectType(transformationInfo.getNewClassName()), newFieldsWithSkipped); + List fieldInfoWithSkipped = + TransformationUtilsKt.transformToFieldInfo(Type.getObjectType(transformationInfo.getNewClassName()), newFieldsWithSkipped); int paramIndex = 0; InstructionAdapter capturedFieldInitializer = new InstructionAdapter(constructorVisitor); @@ -311,23 +295,28 @@ public class AnonymousObjectTransformer extends ObjectTransformer", constructorDescriptor, null, ArrayUtil.EMPTY_STRING_ARRAY); + MethodNode intermediateMethodNode = + new MethodNode(AsmUtil.NO_FLAG_PACKAGE_PRIVATE, "", constructorDescriptor, null, ArrayUtil.EMPTY_STRING_ARRAY); inlineMethodAndUpdateGlobalResult(parentRemapper, intermediateMethodNode, constructor, constructorInlineBuilder, true); AbstractInsnNode first = intermediateMethodNode.instructions.getFirst(); final Label oldStartLabel = first instanceof LabelNode ? ((LabelNode) first).getLabel() : null; intermediateMethodNode.accept(new MethodBodyVisitor(capturedFieldInitializer) { @Override - public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { + public void visitLocalVariable( + @NotNull String name, @NotNull String desc, String signature, @NotNull Label start, @NotNull Label end, int index + ) { if (oldStartLabel == start) { start = newBodyStartLabel;//patch for jack&jill } @@ -335,14 +324,13 @@ public class AnonymousObjectTransformer extends ObjectTransformer() { @Override public MethodVisitor invoke() { return 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) + ); } - }); + } + ); } + @NotNull private List extractParametersMappingAndPatchConstructor( @NotNull MethodNode constructor, @NotNull ParametersBuilder capturedParamBuilder, @@ -380,8 +365,8 @@ public class AnonymousObjectTransformer extends ObjectTransformer capturedLambdasToInline = new HashMap(); //captured var of inlined parameter List allRecapturedParameters = new ArrayList(); - boolean addCapturedNotAddOuter = parentFieldRemapper.isRoot() || (parentFieldRemapper instanceof InlinedLambdaRemapper && parentFieldRemapper.getParent().isRoot()); + boolean addCapturedNotAddOuter = + parentFieldRemapper.isRoot() || + (parentFieldRemapper instanceof InlinedLambdaRemapper && parentFieldRemapper.getParent().isRoot()); Map alreadyAdded = new HashMap(); for (LambdaInfo info : capturedLambdas) { if (addCapturedNotAddOuter) { @@ -466,16 +458,20 @@ public class AnonymousObjectTransformer extends ObjectTransformer values) { + private static boolean shouldRenameThis0(@NotNull FieldRemapper parentFieldRemapper, @NotNull Collection values) { if (isFirstDeclSiteLambdaFieldRemapper(parentFieldRemapper)) { for (LambdaInfo value : values) { for (CapturedParamDesc desc : value.getCapturedVars()) { @@ -528,11 +526,12 @@ public class AnonymousObjectTransformer extends ObjectTransformer = IntervalMetaInfo() - val localVarsMetaInfo: IntervalMetaInfo = IntervalMetaInfo() var nextFreeLocalIndex: Int = parameterSize @@ -70,11 +64,11 @@ abstract class CoveringTryCatchNodeProcessor(parameterSize: Int) { result } - Collections.sort(intervals, comp) + Collections.sort(intervals, comp) return intervals } - protected fun substituteTryBlockNodes(node: MethodNode) { + fun substituteTryBlockNodes(node: MethodNode) { node.tryCatchBlocks.clear() sortTryCatchBlocks(tryBlocksMetaInfo.allIntervals) for (info in tryBlocksMetaInfo.getMeaningfulIntervals()) { @@ -82,7 +76,6 @@ abstract class CoveringTryCatchNodeProcessor(parameterSize: Int) { } } - fun substituteLocalVarTable(node: MethodNode) { node.localVariables.clear() for (info in localVarsMetaInfo.getMeaningfulIntervals()) { @@ -92,13 +85,9 @@ abstract class CoveringTryCatchNodeProcessor(parameterSize: Int) { } class IntervalMetaInfo> { - val intervalStarts = LinkedListMultimap.create() - val intervalEnds = LinkedListMultimap.create() - val allIntervals: ArrayList = arrayListOf() - val currentIntervals: MutableSet = linkedSetOf() fun addNewInterval(newInfo: T) { @@ -117,17 +106,10 @@ class IntervalMetaInfo> { intervalEnds.put(remapped.endLabel, remapped) } - fun splitCurrentIntervals(by : Interval, keepStart: Boolean): List> { + fun splitCurrentIntervals(by: Interval, keepStart: Boolean): List> { return currentIntervals.map { split(it, by, keepStart) } } - fun splitAndRemoveIntervalsFromCurrents(by : Interval) { - val copies = ArrayList(currentIntervals) - copies.forEach { - splitAndRemoveInterval(it, by, true) - } - } - fun processCurrent(curIns: LabelNode, directOrder: Boolean) { getInterval(curIns, directOrder).forEach { val added = currentIntervals.add(it) @@ -140,25 +122,27 @@ class IntervalMetaInfo> { } } - fun split(interval: T, by : Interval, keepStart: Boolean): SplitPair { + fun split(interval: T, by: Interval, keepStart: Boolean): SplitPair { 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) return split } - fun splitAndRemoveInterval(interval: T, by : Interval, keepStart: Boolean): SplitPair { + fun splitAndRemoveInterval(interval: T, by: Interval, keepStart: Boolean): SplitPair { val splitPair = split(interval, by, keepStart) val removed = currentIntervals.remove(splitPair.patchedPart) - assert(removed, {"Wrong interval structure: $splitPair"}) + assert(removed) { "Wrong interval structure: $splitPair" } return splitPair } - fun getInterval(curIns: LabelNode, isOpen: Boolean) = if (isOpen) intervalStarts.get(curIns) else intervalEnds.get(curIns) + fun getInterval(curIns: LabelNode, isOpen: Boolean) = + if (isOpen) intervalStarts.get(curIns) else intervalEnds.get(curIns) } private fun Interval.isMeaningless(): Boolean { @@ -175,23 +159,16 @@ fun > IntervalMetaInfo.getMeaningfulIntervals(): Li } class DefaultProcessor(val node: MethodNode, parameterSize: Int) : CoveringTryCatchNodeProcessor(parameterSize) { - init { - node.tryCatchBlocks.forEach { addTryNode(it) } - node.localVariables.forEach { addLocalVarNode(it) } + node.tryCatchBlocks.forEach { + tryBlocksMetaInfo.addNewInterval(TryCatchBlockNodeInfo(it, false)) + } + node.localVariables.forEach { + localVarsMetaInfo.addNewInterval(LocalVarNodeWrapper(it)) + } } - fun addLocalVarNode(it: LocalVariableNode) { - localVarsMetaInfo.addNewInterval(LocalVarNodeWrapper(it)) - } - - fun addTryNode(node: TryCatchBlockNode) { - tryBlocksMetaInfo.addNewInterval(TryCatchBlockNodeInfo(node, false)) - } - - override fun instructionIndex(inst: AbstractInsnNode): Int { - return node.instructions.indexOf(inst) - } + override fun instructionIndex(inst: AbstractInsnNode): Int = node.instructions.indexOf(inst) } class LocalVarNodeWrapper(val node: LocalVariableNode) : Interval, SplittableInterval { @@ -216,5 +193,4 @@ class LocalVarNodeWrapper(val node: LocalVariableNode) : Interval, SplittableInt LocalVariableNode(node.name, node.desc, node.signature, newPartInterval.first, newPartInterval.second, node.index) )) } - -} \ No newline at end of file +} diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/FieldRemapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/FieldRemapper.java index 886a0acc111..f9055cb5255 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/FieldRemapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/FieldRemapper.java @@ -20,7 +20,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.codegen.StackValue; import org.jetbrains.org.objectweb.asm.Opcodes; -import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode; import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode; import org.jetbrains.org.objectweb.asm.tree.MethodNode; @@ -29,30 +28,24 @@ import java.util.Collection; import java.util.List; public class FieldRemapper { - - private final String lambdaInternalName; - protected FieldRemapper parent; - + private final String lambdaInternalName; private final Parameters params; public FieldRemapper(@Nullable String lambdaInternalName, @Nullable FieldRemapper parent, @NotNull Parameters methodParams) { this.lambdaInternalName = lambdaInternalName; this.parent = parent; - params = methodParams; + this.params = methodParams; } - protected boolean canProcess(@NotNull String fieldOwner, String fieldName, boolean isFolding) { + protected boolean canProcess(@NotNull String fieldOwner, @NotNull String fieldName, boolean isFolding) { return fieldOwner.equals(getLambdaInternalName()) && //don't process general field of anonymous objects InlineCodegenUtil.isCapturedFieldName(fieldName); } @Nullable - public AbstractInsnNode foldFieldAccessChainIfNeeded( - @NotNull List capturedFieldAccess, - @NotNull MethodNode node - ) { + public AbstractInsnNode foldFieldAccessChainIfNeeded(@NotNull List capturedFieldAccess, @NotNull MethodNode node) { if (capturedFieldAccess.size() == 1) { //just aload return null; @@ -72,33 +65,33 @@ public class FieldRemapper { int currentInstruction, @NotNull MethodNode node ) { - AbstractInsnNode transformed = null; boolean checkParent = !isRoot() && currentInstruction < capturedFieldAccess.size() - 1; if (checkParent) { - transformed = parent.foldFieldAccessChainIfNeeded(capturedFieldAccess, currentInstruction + 1, node); - } - - if (transformed == null) { - //if parent couldn't transform - FieldInsnNode insnNode = (FieldInsnNode) capturedFieldAccess.get(currentInstruction); - if (canProcess(insnNode.owner, insnNode.name, true)) { - insnNode.name = "$$$" + insnNode.name; - insnNode.setOpcode(Opcodes.GETSTATIC); - - AbstractInsnNode next = capturedFieldAccess.get(0); - while (next != insnNode) { - AbstractInsnNode toDelete = next; - next = next.getNext(); - node.instructions.remove(toDelete); - } - - transformed = capturedFieldAccess.get(capturedFieldAccess.size() - 1); + AbstractInsnNode transformed = parent.foldFieldAccessChainIfNeeded(capturedFieldAccess, currentInstruction + 1, node); + if (transformed != null) { + return transformed; } } - return transformed; + FieldInsnNode insnNode = (FieldInsnNode) capturedFieldAccess.get(currentInstruction); + if (canProcess(insnNode.owner, insnNode.name, true)) { + insnNode.name = "$$$" + insnNode.name; + insnNode.setOpcode(Opcodes.GETSTATIC); + + AbstractInsnNode next = capturedFieldAccess.get(0); + while (next != insnNode) { + AbstractInsnNode toDelete = next; + next = next.getNext(); + node.instructions.remove(toDelete); + } + + return capturedFieldAccess.get(capturedFieldAccess.size() - 1); + } + + return null; } + @Nullable public CapturedParamInfo findField(@NotNull FieldInsnNode fieldInsnNode) { return findField(fieldInsnNode, params.getCaptured()); } @@ -106,13 +99,15 @@ public class FieldRemapper { @Nullable protected CapturedParamInfo findField(@NotNull FieldInsnNode fieldInsnNode, @NotNull Collection captured) { for (CapturedParamInfo valueDescriptor : captured) { - if (valueDescriptor.getOriginalFieldName().equals(fieldInsnNode.name) && fieldInsnNode.owner.equals(valueDescriptor.getContainingLambdaName())) { + if (valueDescriptor.getOriginalFieldName().equals(fieldInsnNode.name) && + valueDescriptor.getContainingLambdaName().equals(fieldInsnNode.owner)) { return valueDescriptor; } } return null; } + @NotNull public FieldRemapper getParent() { return parent; } @@ -131,8 +126,7 @@ public class FieldRemapper { @Nullable public StackValue getFieldForInline(@NotNull FieldInsnNode node, @Nullable StackValue prefix) { - CapturedParamInfo field = MethodInliner.findCapturedField(node, this); - return field.getRemapValue(); + return MethodInliner.findCapturedField(node, this).getRemapValue(); } public boolean isInsideInliningLambda() { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineAdapter.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineAdapter.java index acb316fae48..a0963a05620 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineAdapter.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineAdapter.java @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.codegen.inline; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.org.objectweb.asm.Label; import org.jetbrains.org.objectweb.asm.MethodVisitor; import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; @@ -27,19 +28,16 @@ import java.util.List; import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.getLoadStoreArgSize; public class InlineAdapter extends InstructionAdapter { - - private int nextLocalIndex = 0; private final SourceMapper sourceMapper; - - private boolean isLambdaInlining = false; - private final List blocks = new ArrayList(); + private boolean isLambdaInlining = false; + private int nextLocalIndex = 0; private int nextLocalIndexBeforeInline = -1; - public InlineAdapter(MethodVisitor mv, int localsSize, @NotNull SourceMapper sourceMapper) { + public InlineAdapter(@NotNull MethodVisitor mv, int localsSize, @NotNull SourceMapper sourceMapper) { super(InlineCodegenUtil.API, mv); - nextLocalIndex = localsSize; + this.nextLocalIndex = localsSize; this.sourceMapper = sourceMapper; } @@ -70,15 +68,15 @@ public class InlineAdapter extends InstructionAdapter { this.isLambdaInlining = isInlining; if (isInlining) { nextLocalIndexBeforeInline = nextLocalIndex; - } else { + } + else { nextLocalIndex = nextLocalIndexBeforeInline; } } @Override - public void visitTryCatchBlock(Label start, - Label end, Label handler, String type) { - if(!isLambdaInlining) { + public void visitTryCatchBlock(@NotNull Label start, @NotNull Label end, @NotNull Label handler, @Nullable String type) { + if (!isLambdaInlining) { blocks.add(new CatchBlock(start, end, handler, type)); } else { @@ -87,7 +85,7 @@ public class InlineAdapter extends InstructionAdapter { } @Override - public void visitLineNumber(int line, Label start) { + public void visitLineNumber(int line, @NotNull Label start) { if (InlineCodegenUtil.GENERATE_SMAP) { line = sourceMapper.mapLineNumber(line); } @@ -111,7 +109,7 @@ public class InlineAdapter extends InstructionAdapter { private final Label handler; private final String type; - public CatchBlock(Label start, Label end, Label handler, String type) { + public CatchBlock(@NotNull Label start, @NotNull Label end, @NotNull Label handler, @Nullable String type) { this.start = start; this.end = end; this.handler = handler; 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 92d669d44b2..48f495800b7 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCache.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCache.kt @@ -34,7 +34,8 @@ 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.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java index 6a55a9eca07..cf878a92e25 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java @@ -35,7 +35,6 @@ import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache; import org.jetbrains.kotlin.name.ClassId; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.psi.*; -import org.jetbrains.kotlin.renderer.DescriptorRenderer; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; import org.jetbrains.kotlin.resolve.DescriptorUtils; @@ -85,7 +84,9 @@ public class InlineCodegen extends CallGenerator { private final Map expressionMap = new HashMap(); private final ReifiedTypeInliner reifiedTypeInliner; - @Nullable private final TypeParameterMappings typeParameterMappings; + + @Nullable + private final TypeParameterMappings typeParameterMappings; private LambdaInfo activeLambda; @@ -131,35 +132,53 @@ public class InlineCodegen extends CallGenerator { } @Override - public void genCallInner(@NotNull Callable callableMethod, @Nullable ResolvedCall resolvedCall, boolean callDefault, @NotNull ExpressionCodegen codegen) { - SMAPAndMethodNode nodeAndSmap = null; + public void genCallInner( + @NotNull Callable callableMethod, + @Nullable ResolvedCall resolvedCall, + boolean callDefault, + @NotNull ExpressionCodegen codegen + ) { if (!state.getInlineCycleReporter().enterIntoInlining(resolvedCall)) { generateStub(resolvedCall, codegen); return; } + SMAPAndMethodNode nodeAndSmap = null; try { - nodeAndSmap = createMethodNode(callDefault); + nodeAndSmap = createMethodNode(functionDescriptor, jvmSignature, codegen, context, callDefault); endCall(inlineCall(nodeAndSmap)); } catch (CompilationException e) { throw e; } + catch (InlineException e) { + throw throwCompilationException(nodeAndSmap, e, false); + } catch (Exception e) { - boolean generateNodeText = !(e instanceof InlineException); - PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(this.codegen.getContext().getContextDescriptor()); - throw new CompilationException("Couldn't inline method call '" + - functionDescriptor.getName() + - "' into \n" + (element != null ? element.getText() : "null psi element " + this.codegen.getContext().getContextDescriptor()) + - (generateNodeText ? ("\ncause: " + InlineCodegenUtil.getNodeText(nodeAndSmap != null ? nodeAndSmap.getNode(): null)) : ""), - e, callElement); + throw throwCompilationException(nodeAndSmap, e, true); } finally { state.getInlineCycleReporter().exitFromInliningOf(resolvedCall); } } - protected void generateStub(@Nullable ResolvedCall resolvedCall, @NotNull ExpressionCodegen codegen) { + @NotNull + private CompilationException throwCompilationException( + @Nullable SMAPAndMethodNode nodeAndSmap, @NotNull Exception e, boolean generateNodeText + ) { + CallableMemberDescriptor contextDescriptor = codegen.getContext().getContextDescriptor(); + PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(contextDescriptor); + MethodNode node = nodeAndSmap != null ? nodeAndSmap.getNode() : null; + throw new CompilationException( + "Couldn't inline method call '" + functionDescriptor.getName() + "' into\n" + + contextDescriptor + "\n" + + (element != null ? element.getText() : "") + + (generateNodeText ? ("\nCause: " + InlineCodegenUtil.getNodeText(node)) : ""), + e, callElement + ); + } + + private void generateStub(@Nullable ResolvedCall resolvedCall, @NotNull ExpressionCodegen codegen) { leaveTemps(); assert resolvedCall != null; String message = "Call is part of inline cycle: " + resolvedCall.getCall().getCallElement().getText(); @@ -176,25 +195,19 @@ public class InlineCodegen extends CallGenerator { codegen.markLineNumberAfterInlineIfNeeded(); } - @NotNull - private SMAPAndMethodNode createMethodNode(boolean callDefault) throws IOException { - return createMethodNode(functionDescriptor, jvmSignature, codegen, context, callDefault, state); - } - @NotNull static SMAPAndMethodNode createMethodNode( @NotNull final FunctionDescriptor functionDescriptor, @NotNull JvmMethodSignature jvmSignature, @NotNull ExpressionCodegen codegen, @NotNull CodegenContext context, - boolean callDefault, - @NotNull final GenerationState state + boolean callDefault ) { - - KotlinTypeMapper typeMapper = state.getTypeMapper(); - final Method asmMethod = callDefault - ? typeMapper.mapDefaultMethod(functionDescriptor, context.getContextKind()) - : jvmSignature.getAsmMethod(); + final GenerationState state = codegen.getState(); + final Method asmMethod = + callDefault + ? state.getTypeMapper().mapDefaultMethod(functionDescriptor, context.getContextKind()) + : jvmSignature.getAsmMethod(); MethodId methodId = new MethodId(DescriptorUtils.getFqNameSafe(functionDescriptor.getContainingDeclaration()), asmMethod); @@ -202,15 +215,18 @@ public class InlineCodegen extends CallGenerator { return doCreateMethodNodeFromSource(functionDescriptor, jvmSignature, codegen, context, callDefault, state, asmMethod); } - SMAPAndMethodNode resultInCache = - InlineCacheKt - .getOrPut(state.getInlineCache().getMethodNodeById(), methodId, new Function0() { - @Override - public SMAPAndMethodNode invoke() { - return doCreateMethodNodeFromCompiled(functionDescriptor, - state, asmMethod); - } - }); + SMAPAndMethodNode resultInCache = InlineCacheKt.getOrPut( + state.getInlineCache().getMethodNodeById(), methodId, new Function0() { + @Override + public SMAPAndMethodNode invoke() { + SMAPAndMethodNode result = doCreateMethodNodeFromCompiled(functionDescriptor, state, asmMethod); + if (result == null) { + throw new IllegalStateException("Couldn't obtain compiled function body for " + functionDescriptor); + } + return result; + } + } + ); return resultInCache.copyWithNewNode(cloneMethodNode(resultInCache.getNode())); } @@ -220,12 +236,13 @@ public class InlineCodegen extends CallGenerator { methodNode.instructions.resetLabels(); MethodNode result = new MethodNode( API, methodNode.access, methodNode.name, methodNode.desc, methodNode.signature, - methodNode.exceptions.toArray(ArrayUtil.EMPTY_STRING_ARRAY)); + ArrayUtil.toStringArray(methodNode.exceptions) + ); methodNode.accept(result); return result; } - @NotNull + @Nullable private static SMAPAndMethodNode doCreateMethodNodeFromCompiled( @NotNull FunctionDescriptor functionDescriptor, @NotNull final GenerationState state, @@ -233,7 +250,6 @@ public class InlineCodegen extends CallGenerator { ) { KotlinTypeMapper typeMapper = state.getTypeMapper(); - SMAPAndMethodNode nodeAndSMAP; if (isBuiltInArrayIntrinsic(functionDescriptor)) { ClassId classId = IntrinsicArrayConstructorsKt.getClassId(); byte[] bytes = InlineCacheKt.getOrPut(state.getInlineCache().getClassBytes(), classId, new Function0() { @@ -243,24 +259,13 @@ public class InlineCodegen extends CallGenerator { } }); - nodeAndSMAP = InlineCodegenUtil.getMethodNode( - bytes, - asmMethod.getName(), - asmMethod.getDescriptor(), - classId - ); - - if (nodeAndSMAP == null) { - throw new IllegalStateException("Couldn't obtain array constructor body for " + descriptorName(functionDescriptor)); - } - - return nodeAndSMAP; + return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), classId); } - assert functionDescriptor instanceof DeserializedSimpleFunctionDescriptor; + assert functionDescriptor instanceof DeserializedSimpleFunctionDescriptor : "Not a deserialized function: " + functionDescriptor; - KotlinTypeMapper.ContainingClassesInfo containingClasses = typeMapper.getContainingClassesForDeserializedCallable( - (DeserializedSimpleFunctionDescriptor) functionDescriptor); + KotlinTypeMapper.ContainingClassesInfo containingClasses = + typeMapper.getContainingClassesForDeserializedCallable((DeserializedSimpleFunctionDescriptor) functionDescriptor); final ClassId containerId = containingClasses.getImplClassId(); @@ -280,15 +285,7 @@ public class InlineCodegen extends CallGenerator { } }); - nodeAndSMAP = InlineCodegenUtil.getMethodNode( - bytes, asmMethod.getName(), asmMethod.getDescriptor(), containerId - ); - - if (nodeAndSMAP == null) { - throw new IllegalStateException("Couldn't obtain compiled function body for " + descriptorName(functionDescriptor)); - } - - return nodeAndSMAP; + return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), containerId); } @NotNull @@ -304,27 +301,31 @@ public class InlineCodegen extends CallGenerator { PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor); if (!(element instanceof KtNamedFunction)) { - throw new IllegalStateException("Couldn't find declaration for function " + descriptorName(functionDescriptor)); + throw new IllegalStateException("Couldn't find declaration for function " + functionDescriptor); } KtNamedFunction inliningFunction = (KtNamedFunction) element; - MethodNode node = new MethodNode(InlineCodegenUtil.API, - getMethodAsmFlags(functionDescriptor, context.getContextKind()) | (callDefault ? Opcodes.ACC_STATIC : 0), - asmMethod.getName(), - asmMethod.getDescriptor(), - null, - null); + MethodNode node = new MethodNode( + InlineCodegenUtil.API, + getMethodAsmFlags(functionDescriptor, context.getContextKind()) | (callDefault ? Opcodes.ACC_STATIC : 0), + asmMethod.getName(), + asmMethod.getDescriptor(), + null, null + ); //for maxLocals calculation MethodVisitor maxCalcAdapter = InlineCodegenUtil.wrapWithMaxLocalCalc(node); - MethodContext methodContext = context.getParentContext().intoFunction(functionDescriptor); + CodegenContext parentContext = context.getParentContext(); + assert parentContext != null : "Context has no parent: " + context; + MethodContext methodContext = parentContext.intoFunction(functionDescriptor); SMAP smap; if (callDefault) { Type implementationOwner = state.getTypeMapper().mapImplementationOwner(functionDescriptor); - FakeMemberCodegen parentCodegen = new FakeMemberCodegen(codegen.getParentCodegen(), inliningFunction, - (FieldOwnerContext) methodContext.getParentContext(), - implementationOwner.getInternalName()); + FakeMemberCodegen parentCodegen = new FakeMemberCodegen( + codegen.getParentCodegen(), inliningFunction, (FieldOwnerContext) methodContext.getParentContext(), + implementationOwner.getInternalName() + ); FunctionCodegen.generateDefaultImplBody( methodContext, functionDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT, inliningFunction, parentCodegen, asmMethod @@ -332,7 +333,7 @@ public class InlineCodegen extends CallGenerator { smap = createSMAPWithDefaultMapping(inliningFunction, parentCodegen.getOrCreateSourceMapper().getResultMappings()); } else { - smap = generateMethodBody(maxCalcAdapter, functionDescriptor, methodContext, inliningFunction, jvmSignature, false, codegen, state); + smap = generateMethodBody(maxCalcAdapter, functionDescriptor, methodContext, inliningFunction, jvmSignature, false, codegen); } maxCalcAdapter.visitMaxs(-1, -1); maxCalcAdapter.visitEnd(); @@ -347,7 +348,8 @@ public class InlineCodegen extends CallGenerator { functionDescriptor.getContainingDeclaration() instanceof BuiltInsPackageFragment; } - private InlineResult inlineCall(SMAPAndMethodNode nodeAndSmap) { + @NotNull + private InlineResult inlineCall(@NotNull SMAPAndMethodNode nodeAndSmap) { DefaultSourceMapper defaultSourceMapper = codegen.getParentCodegen().getOrCreateSourceMapper(); defaultSourceMapper.setCallSiteMarker(new CallSiteMarker(codegen.getLastLineNumber())); MethodNode node = nodeAndSmap.getNode(); @@ -363,7 +365,8 @@ public class InlineCodegen extends CallGenerator { InliningContext info = new RootInliningContext( expressionMap, state, codegen.getInlineNameGenerator().subGenerator(jvmSignature.getAsmMethod().getName()), - codegen.getContext(), callElement, getInlineCallSiteInfo(), reifiedTypeInliner, typeParameterMappings); + callElement, getInlineCallSiteInfo(), reifiedTypeInliner, typeParameterMappings + ); MethodInliner inliner = new MethodInliner( node, parameters, info, new FieldRemapper(null, null, parameters), isSameModule, @@ -374,7 +377,6 @@ public class InlineCodegen extends CallGenerator { LocalVarRemapper remapper = new LocalVarRemapper(parameters, initialFrameSize); - MethodNode adapter = InlineCodegenUtil.createEmptyMethodNode(); //hack to keep linenumber info, otherwise jdi will skip begin of linenumber chain adapter.visitInsn(Opcodes.NOP); @@ -392,7 +394,9 @@ public class InlineCodegen extends CallGenerator { }; List infos = MethodInliner.processReturns(adapter, labelOwner, true, null); - generateAndInsertFinallyBlocks(adapter, infos, ((StackValue.Local)remapper.remap(parameters.getArgsSizeOnStack() + 1).value).index); + generateAndInsertFinallyBlocks( + adapter, infos, ((StackValue.Local) remapper.remap(parameters.getArgsSizeOnStack() + 1).value).index + ); removeStaticInitializationTrigger(adapter); removeFinallyMarkers(adapter); @@ -405,7 +409,7 @@ public class InlineCodegen extends CallGenerator { return result; } - private static void removeStaticInitializationTrigger(MethodNode methodNode) { + private static void removeStaticInitializationTrigger(@NotNull MethodNode methodNode) { InsnList insnList = methodNode.instructions; AbstractInsnNode insn = insnList.getFirst(); while (insn != null) { @@ -420,6 +424,7 @@ public class InlineCodegen extends CallGenerator { } } + @NotNull private InlineCallSiteInfo getInlineCallSiteInfo() { MethodContext context = codegen.getContext(); MemberCodegen parentCodegen = codegen.getParentCodegen(); @@ -433,7 +438,9 @@ public class InlineCodegen extends CallGenerator { } JvmMethodSignature signature = typeMapper.mapSignatureSkipGeneric(context.getFunctionDescriptor(), context.getContextKind()); - return new InlineCallSiteInfo(parentCodegen.getClassName(), signature.getAsmMethod().getName(), signature.getAsmMethod().getDescriptor()); + return new InlineCallSiteInfo( + parentCodegen.getClassName(), signature.getAsmMethod().getName(), signature.getAsmMethod().getDescriptor() + ); } private void generateClosuresBodies() { @@ -442,25 +449,29 @@ public class InlineCodegen extends CallGenerator { } } - private SMAPAndMethodNode generateLambdaBody(LambdaInfo info) { + @NotNull + private SMAPAndMethodNode generateLambdaBody(@NotNull LambdaInfo info) { KtExpression declaration = info.getFunctionWithBodyOrCallableReference(); FunctionDescriptor descriptor = info.getFunctionDescriptor(); - MethodContext parentContext = codegen.getContext(); - - MethodContext context = parentContext.intoClosure(descriptor, codegen, typeMapper).intoInlinedLambda(descriptor, info.isCrossInline); + MethodContext context = + codegen.getContext().intoClosure(descriptor, codegen, typeMapper).intoInlinedLambda(descriptor, info.isCrossInline); JvmMethodSignature jvmMethodSignature = typeMapper.mapSignatureSkipGeneric(descriptor); Method asmMethod = jvmMethodSignature.getAsmMethod(); - MethodNode methodNode = new MethodNode(InlineCodegenUtil.API, getMethodAsmFlags(descriptor, context.getContextKind()), asmMethod.getName(), asmMethod.getDescriptor(), null, null); + MethodNode methodNode = new MethodNode( + InlineCodegenUtil.API, getMethodAsmFlags(descriptor, context.getContextKind()), + asmMethod.getName(), asmMethod.getDescriptor(), null, null + ); MethodVisitor adapter = InlineCodegenUtil.wrapWithMaxLocalCalc(methodNode); - SMAP smap = generateMethodBody(adapter, descriptor, context, declaration, jvmMethodSignature, true, codegen, state); + SMAP smap = generateMethodBody(adapter, descriptor, context, declaration, jvmMethodSignature, true, codegen); adapter.visitMaxs(-1, -1); return new SMAPAndMethodNode(methodNode, smap); } + @NotNull private static SMAP generateMethodBody( @NotNull MethodVisitor adapter, @NotNull FunctionDescriptor descriptor, @@ -468,32 +479,29 @@ public class InlineCodegen extends CallGenerator { @NotNull KtExpression expression, @NotNull JvmMethodSignature jvmMethodSignature, boolean isLambda, - @NotNull ExpressionCodegen codegen, - @NotNull GenerationState state - + @NotNull ExpressionCodegen codegen ) { - FakeMemberCodegen parentCodegen = - new FakeMemberCodegen(codegen.getParentCodegen(), expression, - (FieldOwnerContext) context.getParentContext(), - isLambda ? codegen.getParentCodegen().getClassName() - : state.getTypeMapper().mapImplementationOwner(descriptor).getInternalName()); + GenerationState state = codegen.getState(); + + // Wrapping for preventing marking actual parent codegen as containing reified markers + FakeMemberCodegen parentCodegen = new FakeMemberCodegen( + codegen.getParentCodegen(), expression, (FieldOwnerContext) context.getParentContext(), + isLambda ? codegen.getParentCodegen().getClassName() + : state.getTypeMapper().mapImplementationOwner(descriptor).getInternalName() + ); FunctionGenerationStrategy strategy = expression instanceof KtCallableReferenceExpression ? new FunctionReferenceGenerationStrategy( state, descriptor, - CallUtilKt.getResolvedCallWithAssert(((KtCallableReferenceExpression) expression).getCallableReference(), - codegen.getBindingContext() - )) : + CallUtilKt.getResolvedCallWithAssert( + ((KtCallableReferenceExpression) expression).getCallableReference(), codegen.getBindingContext() + ) + ) : new FunctionGenerationStrategy.FunctionDefault(state, descriptor, (KtDeclarationWithBody) expression); - FunctionCodegen.generateMethodBody( - adapter, descriptor, context, jvmMethodSignature, - strategy, - // Wrapping for preventing marking actual parent codegen as containing reifier markers - parentCodegen - ); + FunctionCodegen.generateMethodBody(adapter, descriptor, context, jvmMethodSignature, strategy, parentCodegen); if (isLambda) { codegen.propagateChildReifiedTypeParametersUsages(parentCodegen.getReifiedTypeParametersUsages()); @@ -514,13 +522,18 @@ public class InlineCodegen extends CallGenerator { } private static class FakeMemberCodegen extends MemberCodegen { + private final MemberCodegen delegate; + private final String className; - @NotNull final MemberCodegen delegate; - @NotNull private final String className; - - public FakeMemberCodegen(@NotNull MemberCodegen wrapped, @NotNull KtElement declaration, @NotNull FieldOwnerContext codegenContext, @NotNull String className) { + @SuppressWarnings("unchecked") + public FakeMemberCodegen( + @NotNull MemberCodegen wrapped, + @NotNull KtElement declaration, + @NotNull FieldOwnerContext codegenContext, + @NotNull String className + ) { super(wrapped, declaration, codegenContext); - delegate = wrapped; + this.delegate = wrapped; this.className = className; } @@ -554,11 +567,7 @@ public class InlineCodegen extends CallGenerator { } @Override - public void afterParameterPut( - @NotNull Type type, - @Nullable StackValue stackValue, - int parameterIndex - ) { + public void afterParameterPut(@NotNull Type type, @Nullable StackValue stackValue, int parameterIndex) { putArgumentOrCapturedToLocalVal(type, stackValue, -1, parameterIndex); } @@ -588,11 +597,7 @@ public class InlineCodegen extends CallGenerator { } /*descriptor is null for captured vars*/ - public static boolean shouldPutValue( - @NotNull Type type, - @Nullable StackValue stackValue - ) { - + private static boolean shouldPutValue(@NotNull Type type, @Nullable StackValue stackValue) { if (stackValue == null) { //default or vararg return true; @@ -626,7 +631,7 @@ public class InlineCodegen extends CallGenerator { return true; } - private void recordParameterValueInLocalVal(ParameterInfo... infos) { + private void recordParameterValueInLocalVal(@NotNull ParameterInfo... infos) { int[] index = new int[infos.length]; for (int i = 0; i < infos.length; i++) { ParameterInfo info = infos[i]; @@ -650,34 +655,33 @@ public class InlineCodegen extends CallGenerator { @Override public void putHiddenParams() { if ((getMethodAsmFlags(functionDescriptor, context.getContextKind()) & Opcodes.ACC_STATIC) == 0) { - invocationParamBuilder.addNextParameter(AsmTypes.OBJECT_TYPE, false, null); + invocationParamBuilder.addNextParameter(AsmTypes.OBJECT_TYPE, false); } for (JvmMethodParameterSignature param : jvmSignature.getValueParameters()) { if (param.getKind() == JvmMethodParameterKind.VALUE) { break; } - invocationParamBuilder.addNextParameter(param.getAsmType(), false, null); + invocationParamBuilder.addNextParameter(param.getAsmType(), false); } - invocationParamBuilder.markValueParametesStart(); + invocationParamBuilder.markValueParametersStart(); List hiddenParameters = invocationParamBuilder.buildParameters().getReal(); recordParameterValueInLocalVal(hiddenParameters.toArray(new ParameterInfo[hiddenParameters.size()])); } - public void leaveTemps() { - FrameMap frameMap = codegen.getFrameMap(); + private void leaveTemps() { List infos = invocationParamBuilder.listAllParams(); for (ListIterator iterator = infos.listIterator(infos.size()); iterator.hasPrevious(); ) { ParameterInfo param = iterator.previous(); if (!param.isSkippedOrRemapped()) { - frameMap.leaveTemp(param.type); + codegen.getFrameMap().leaveTemp(param.type); } } } /*lambda or callable reference*/ - public boolean isInliningParameter(KtExpression expression, ValueParameterDescriptor valueParameterDescriptor) { + private boolean isInliningParameter(@NotNull KtExpression expression, @NotNull ValueParameterDescriptor valueParameterDescriptor) { //TODO deparenthisise typed KtExpression deparenthesized = KtPsiUtil.deparenthesize(expression); @@ -691,17 +695,16 @@ public class InlineCodegen extends CallGenerator { isInlinableParameterExpression(deparenthesized); } - protected static boolean isInlinableParameterExpression(KtExpression deparenthesized) { + private static boolean isInlinableParameterExpression(@Nullable KtExpression deparenthesized) { return deparenthesized instanceof KtLambdaExpression || deparenthesized instanceof KtNamedFunction || deparenthesized instanceof KtCallableReferenceExpression; } - public void rememberClosure(KtExpression expression, Type type, ValueParameterDescriptor parameter) { + private void rememberClosure(@NotNull KtExpression expression, @NotNull Type type, @NotNull ValueParameterDescriptor parameter) { KtExpression lambda = KtPsiUtil.deparenthesize(expression); assert isInlinableParameterExpression(lambda) : "Couldn't find inline expression in " + expression.getText(); - LambdaInfo info = new LambdaInfo(lambda, typeMapper, parameter.isCrossinline()); ParameterInfo closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameter.getIndex()); @@ -710,7 +713,7 @@ public class InlineCodegen extends CallGenerator { } @NotNull - protected static Set getDeclarationLabels(@Nullable PsiElement lambdaOrFun, @NotNull DeclarationDescriptor descriptor) { + public static Set getDeclarationLabels(@Nullable PsiElement lambdaOrFun, @NotNull DeclarationDescriptor descriptor) { Set result = new HashSet(); if (lambdaOrFun != null) { @@ -737,18 +740,25 @@ public class InlineCodegen extends CallGenerator { activeLambda = null; } - public static CodegenContext getContext(@NotNull DeclarationDescriptor descriptor, @NotNull GenerationState state, @Nullable KtFile sourceFile) { + @NotNull + public static CodegenContext getContext( + @NotNull DeclarationDescriptor descriptor, @NotNull GenerationState state, @Nullable KtFile sourceFile + ) { if (descriptor instanceof PackageFragmentDescriptor) { return new PackageContext((PackageFragmentDescriptor) descriptor, state.getRootContext(), null, sourceFile); } - CodegenContext parent = getContext(descriptor.getContainingDeclaration(), state, sourceFile); + DeclarationDescriptor container = descriptor.getContainingDeclaration(); + assert container != null : "No container for descriptor: " + descriptor; + CodegenContext parent = getContext(container, state, sourceFile); if (descriptor instanceof ScriptDescriptor) { List earlierScripts = state.getReplSpecific().getEarlierScriptsForReplInterpreter(); - return parent.intoScript((ScriptDescriptor) descriptor, - earlierScripts == null ? Collections.emptyList() : earlierScripts, - (ClassDescriptor) descriptor, state.getTypeMapper()); + return parent.intoScript( + (ScriptDescriptor) descriptor, + earlierScripts == null ? Collections.emptyList() : earlierScripts, + (ClassDescriptor) descriptor, state.getTypeMapper() + ); } else if (descriptor instanceof ClassDescriptor) { OwnerKind kind = DescriptorUtils.isInterface(descriptor) ? OwnerKind.DEFAULT_IMPLS : OwnerKind.IMPLEMENTATION; @@ -758,11 +768,7 @@ public class InlineCodegen extends CallGenerator { return parent.intoFunction((FunctionDescriptor) descriptor); } - throw new IllegalStateException("Couldn't build context for " + descriptorName(descriptor)); - } - - private static String descriptorName(DeclarationDescriptor descriptor) { - return DescriptorRenderer.SHORT_NAMES_IN_TYPES.render(descriptor); + throw new IllegalStateException("Couldn't build context for " + descriptor); } @Override @@ -782,18 +788,11 @@ public class InlineCodegen extends CallGenerator { } @Override - public void putValueIfNeeded( - @NotNull Type parameterType, - @NotNull StackValue value - ) { + public void putValueIfNeeded(@NotNull Type parameterType, @NotNull StackValue value) { putValueIfNeeded(parameterType, value, -1); } - private void putValueIfNeeded( - @NotNull Type parameterType, - @NotNull StackValue value, - int index - ) { + private void putValueIfNeeded(@NotNull Type parameterType, @NotNull StackValue value, int index) { if (shouldPutValue(parameterType, value)) { value.put(parameterType, codegen.v); } @@ -801,17 +800,14 @@ public class InlineCodegen extends CallGenerator { } @Override - public void putCapturedValueOnStack( - @NotNull StackValue stackValue, @NotNull Type valueType, int paramIndex - ) { + public void putCapturedValueOnStack(@NotNull StackValue stackValue, @NotNull Type valueType, int paramIndex) { if (shouldPutValue(stackValue.type, stackValue)) { stackValue.put(stackValue.type, codegen.v); } putArgumentOrCapturedToLocalVal(stackValue.type, stackValue, paramIndex, paramIndex); } - - public void generateAndInsertFinallyBlocks( + private void generateAndInsertFinallyBlocks( @NotNull MethodNode intoNode, @NotNull List insertPoints, int offsetForFinallyLocalVar @@ -879,7 +875,7 @@ public class InlineCodegen extends CallGenerator { //processor.substituteLocalVarTable(intoNode); } - public void removeFinallyMarkers(@NotNull MethodNode intoNode) { + private void removeFinallyMarkers(@NotNull MethodNode intoNode) { if (InlineCodegenUtil.isFinallyMarkerRequired(codegen.getContext())) return; InsnList instructions = intoNode.instructions; @@ -898,6 +894,7 @@ public class InlineCodegen extends CallGenerator { } } + @NotNull public static SourceMapper createNestedSourceMapper(@NotNull SMAPAndMethodNode nodeAndSmap, @NotNull SourceMapper parent) { return new NestedSourceMapper(parent, nodeAndSmap.getSortedRanges(), nodeAndSmap.getClassSMAP().getSourceInfo()); } @@ -912,7 +909,8 @@ public class InlineCodegen extends CallGenerator { if (incrementalCache == null) return; String classFilePath = InlineCodegenUtilsKt.getClassFilePath(sourceDescriptor, state.getTypeMapper(), incrementalCache); String sourceFilePath = InlineCodegenUtilsKt.getSourceFilePath(targetDescriptor); - incrementalCache.registerInline(classFilePath, jvmSignature.toString(), sourceFilePath); + Method method = jvmSignature.getAsmMethod(); + incrementalCache.registerInline(classFilePath, method.getName() + method.getDescriptor(), sourceFilePath); } @Override diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt index 72694078215..1835d00e9ae 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt @@ -65,7 +65,7 @@ class InlineCodegenForDefaultBody( } override fun genCallInner(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen) { - val nodeAndSmap = InlineCodegen.createMethodNode(functionDescriptor, jvmSignature, codegen, context, callDefault, state) + val nodeAndSmap = InlineCodegen.createMethodNode(functionDescriptor, jvmSignature, codegen, context, callDefault) val childSourceMapper = InlineCodegen.createNestedSourceMapper(nodeAndSmap, sourceMapper) val node = nodeAndSmap.node @@ -111,4 +111,4 @@ class InlineCodegenForDefaultBody( override fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: List, valueParameterTypes: List) { throw UnsupportedOperationException("Shouldn't be called") } -} \ No newline at end of file +} diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java index 8b6e60ec850..8097189a178 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java @@ -17,12 +17,10 @@ package org.jetbrains.kotlin.codegen.inline; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import kotlin.text.StringsKt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.TestOnly; import org.jetbrains.kotlin.backend.common.output.OutputFile; import org.jetbrains.kotlin.codegen.MemberCodegen; import org.jetbrains.kotlin.codegen.binding.CodegenBinding; @@ -31,7 +29,6 @@ import org.jetbrains.kotlin.codegen.context.CodegenContextUtil; import org.jetbrains.kotlin.codegen.context.InlineLambdaContext; import org.jetbrains.kotlin.codegen.context.MethodContext; import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructorsKt; -import org.jetbrains.kotlin.codegen.optimization.common.UtilKt; import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper; import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping; @@ -63,19 +60,19 @@ public class InlineCodegenUtil { public static final boolean GENERATE_SMAP = true; public static final int API = Opcodes.ASM5; - public static final String CAPTURED_FIELD_PREFIX = "$"; - public static final String NON_CAPTURED_FIELD_PREFIX = "$$"; + private static final String CAPTURED_FIELD_PREFIX = "$"; + private static final String NON_CAPTURED_FIELD_PREFIX = "$$"; public static final String THIS$0 = "this$0"; public static final String THIS = "this"; - public static final String RECEIVER$0 = "receiver$0"; - public static final String NON_LOCAL_RETURN = "$$$$$NON_LOCAL_RETURN$$$$$"; + private static final String RECEIVER$0 = "receiver$0"; + private static final String NON_LOCAL_RETURN = "$$$$$NON_LOCAL_RETURN$$$$$"; public static final String FIRST_FUN_LABEL = "$$$$$ROOT$$$$$"; public static final String NUMBERED_FUNCTION_PREFIX = "kotlin/jvm/functions/Function"; - public static final String INLINE_MARKER_CLASS_NAME = "kotlin/jvm/internal/InlineMarker"; - public static final String INLINE_MARKER_BEFORE_METHOD_NAME = "beforeInlineCall"; - public static final String INLINE_MARKER_AFTER_METHOD_NAME = "afterInlineCall"; - public static final String INLINE_MARKER_FINALLY_START = "finallyStart"; - public static final String INLINE_MARKER_FINALLY_END = "finallyEnd"; + private static final String INLINE_MARKER_CLASS_NAME = "kotlin/jvm/internal/InlineMarker"; + private static final String INLINE_MARKER_BEFORE_METHOD_NAME = "beforeInlineCall"; + private static final String INLINE_MARKER_AFTER_METHOD_NAME = "afterInlineCall"; + private static final String INLINE_MARKER_FINALLY_START = "finallyStart"; + private static final String INLINE_MARKER_FINALLY_END = "finallyEnd"; public static final String INLINE_TRANSFORMATION_SUFFIX = "$inlined"; public static final String INLINE_FUN_THIS_0_SUFFIX = "$inline_fun"; public static final String INLINE_FUN_VAR_SUFFIX = "$iv"; @@ -93,6 +90,7 @@ public class InlineCodegenUtil { final int[] lines = new int[2]; lines[0] = Integer.MAX_VALUE; lines[1] = Integer.MIN_VALUE; + //noinspection PointlessBitwiseExpression cr.accept(new ClassVisitor(API) { @Override public void visit(int version, int access, @NotNull String name, String signature, String superName, String[] interfaces) { @@ -174,7 +172,7 @@ public class InlineCodegenUtil { } @Nullable - public static VirtualFile findVirtualFileImprecise(@NotNull GenerationState state, @NotNull String internalClassName) { + private static VirtualFile findVirtualFileImprecise(@NotNull GenerationState state, @NotNull String internalClassName) { FqName packageFqName = JvmClassName.byInternalName(internalClassName).getPackageFqName(); String classNameWithDollars = StringsKt.substringAfterLast(internalClassName, "/", internalClassName); //TODO: we cannot construct proper classId at this point, we need to read InnerClasses info from class file @@ -182,6 +180,7 @@ public class InlineCodegenUtil { return findVirtualFile(state, new ClassId(packageFqName, Name.identifier(classNameWithDollars))); } + @NotNull public static String getInlineName( @NotNull CodegenContext codegenContext, @NotNull KotlinTypeMapper typeMapper, @@ -190,6 +189,7 @@ public class InlineCodegenUtil { return getInlineName(codegenContext, codegenContext.getContextDescriptor(), typeMapper, fileClassesManager); } + @NotNull private static String getInlineName( @NotNull CodegenContext codegenContext, @NotNull DeclarationDescriptor currentDescriptor, @@ -197,21 +197,24 @@ public class InlineCodegenUtil { @NotNull JvmFileClassesProvider fileClassesProvider ) { if (currentDescriptor instanceof PackageFragmentDescriptor) { - PsiFile file = getContainingFile(codegenContext); + PsiFile file = DescriptorToSourceUtils.getContainingFile(codegenContext.getContextDescriptor()); Type implementationOwnerType; if (file == null) { implementationOwnerType = CodegenContextUtil.getImplementationOwnerClassType(codegenContext); - } else { + } + else { implementationOwnerType = FileClasses.getFileClassType(fileClassesProvider, (KtFile) file); } if (implementationOwnerType == null) { DeclarationDescriptor contextDescriptor = codegenContext.getContextDescriptor(); //noinspection ConstantConditions - throw new RuntimeException("Couldn't find declaration for " + - contextDescriptor.getContainingDeclaration().getName() + "." + contextDescriptor.getName() + - "; context: " + codegenContext); + throw new RuntimeException( + "Couldn't find declaration for " + + contextDescriptor.getContainingDeclaration().getName() + "." + contextDescriptor.getName() + + "; context: " + codegenContext + ); } return implementationOwnerType.getInternalName(); @@ -219,12 +222,12 @@ public class InlineCodegenUtil { else if (currentDescriptor instanceof ClassifierDescriptor) { Type type = typeMapper.mapType((ClassifierDescriptor) currentDescriptor); return type.getInternalName(); - } else if (currentDescriptor instanceof FunctionDescriptor) { + } + else if (currentDescriptor instanceof FunctionDescriptor) { ClassDescriptor descriptor = typeMapper.getBindingContext().get(CodegenBinding.CLASS_FOR_CALLABLE, (FunctionDescriptor) currentDescriptor); if (descriptor != null) { - Type type = typeMapper.mapType(descriptor); - return type.getInternalName(); + return typeMapper.mapType(descriptor).getInternalName(); } } @@ -246,14 +249,15 @@ public class InlineCodegenUtil { } public static boolean isWhenMappingAccess(@NotNull String internalName, @NotNull String fieldName) { - return fieldName.startsWith(WhenByEnumsMapping.MAPPING_ARRAY_FIELD_PREFIX) && internalName.endsWith(WhenByEnumsMapping.MAPPINGS_CLASS_NAME_POSTFIX); + return fieldName.startsWith(WhenByEnumsMapping.MAPPING_ARRAY_FIELD_PREFIX) && + internalName.endsWith(WhenByEnumsMapping.MAPPINGS_CLASS_NAME_POSTFIX); } public static boolean isAnonymousSingletonLoad(@NotNull String internalName, @NotNull String fieldName) { return JvmAbi.INSTANCE_FIELD.equals(fieldName) && isAnonymousClass(internalName); } - public static boolean isAnonymousClass(String internalName) { + public static boolean isAnonymousClass(@NotNull String internalName) { String shortName = getLastNamePart(internalName); int index = shortName.lastIndexOf("$"); @@ -271,16 +275,6 @@ public class InlineCodegenUtil { return index < 0 ? internalName : internalName.substring(index + 1); } - @Nullable - public static PsiFile getContainingFile(CodegenContext codegenContext) { - DeclarationDescriptor contextDescriptor = codegenContext.getContextDescriptor(); - PsiElement psiElement = DescriptorToSourceUtils.descriptorToDeclaration(contextDescriptor); - if (psiElement != null) { - return psiElement.getContainingFile(); - } - return null; - } - @NotNull public static MethodVisitor wrapWithMaxLocalCalc(@NotNull MethodNode methodNode) { return new MaxStackFrameSizeAndLocalsCalculator(API, methodNode.access, methodNode.desc, methodNode); @@ -317,7 +311,8 @@ public class InlineCodegenUtil { return getMarkedReturnLabelOrNull(returnIns) != null; } - public static @Nullable String getMarkedReturnLabelOrNull(@NotNull AbstractInsnNode returnInsn) { + @Nullable + public static String getMarkedReturnLabelOrNull(@NotNull AbstractInsnNode returnInsn) { if (!isReturnOpcode(returnInsn.getOpcode())) { return null; } @@ -335,30 +330,33 @@ public class InlineCodegenUtil { iv.invokestatic(NON_LOCAL_RETURN, labelName, "()V", false); } + @NotNull public static Type getReturnType(int opcode) { switch (opcode) { - case Opcodes.RETURN: return Type.VOID_TYPE; - case Opcodes.IRETURN: return Type.INT_TYPE; - case Opcodes.DRETURN: return Type.DOUBLE_TYPE; - case Opcodes.FRETURN: return Type.FLOAT_TYPE; - case Opcodes.LRETURN: return Type.LONG_TYPE; - default: return AsmTypes.OBJECT_TYPE; - } - } - - public static void insertNodeBefore(@NotNull MethodNode from, @NotNull InsnList instructions, @NotNull AbstractInsnNode beforeNode) { - ListIterator iterator = from.instructions.iterator(); - while (iterator.hasNext()) { - AbstractInsnNode next = iterator.next(); - instructions.insertBefore(beforeNode, next); + case Opcodes.RETURN: + return Type.VOID_TYPE; + case Opcodes.IRETURN: + return Type.INT_TYPE; + case Opcodes.DRETURN: + return Type.DOUBLE_TYPE; + case Opcodes.FRETURN: + return Type.FLOAT_TYPE; + case Opcodes.LRETURN: + return Type.LONG_TYPE; + default: + return AsmTypes.OBJECT_TYPE; } } public static void insertNodeBefore(@NotNull MethodNode from, @NotNull MethodNode to, @NotNull AbstractInsnNode beforeNode) { - insertNodeBefore(from, to.instructions, beforeNode); + ListIterator iterator = from.instructions.iterator(); + while (iterator.hasNext()) { + AbstractInsnNode next = iterator.next(); + to.instructions.insertBefore(beforeNode, next); + } } - + @NotNull public static MethodNode createEmptyMethodNode() { return new MethodNode(API, 0, "fake", "()V", null, null); } @@ -374,11 +372,7 @@ public class InlineCodegenUtil { @NotNull public static String getNodeText(@Nullable MethodNode node) { - return getNodeText(node, new Textifier()); - } - - @NotNull - public static String getNodeText(@Nullable MethodNode node, @NotNull Textifier textifier) { + Textifier textifier = new Textifier(); if (node == null) { return "Not generated"; } @@ -386,7 +380,7 @@ public class InlineCodegenUtil { StringWriter sw = new StringWriter(); textifier.print(new PrintWriter(sw)); sw.flush(); - return node.name + " " + node.desc + ": \n " + sw.getBuffer().toString(); + return node.name + " " + node.desc + ":\n" + sw.getBuffer().toString(); } @NotNull @@ -397,13 +391,11 @@ public class InlineCodegenUtil { if (outputFile != null) { return new ClassReader(outputFile.asByteArray()); } - else { - VirtualFile file = findVirtualFileImprecise(state, internalName); - if (file == null) { - throw new RuntimeException("Couldn't find virtual file for " + internalName); - } + VirtualFile file = findVirtualFileImprecise(state, internalName); + if (file != null) { return new ClassReader(file.contentsToByteArray()); } + throw new RuntimeException("Couldn't find virtual file for " + internalName); } catch (IOException e) { throw new RuntimeException(e); @@ -424,10 +416,10 @@ public class InlineCodegenUtil { } public static boolean isFinallyMarker(@Nullable AbstractInsnNode node) { - return isFinallyMarker(node, INLINE_MARKER_FINALLY_END) || isFinallyMarker(node, INLINE_MARKER_FINALLY_START); + return node != null && (isFinallyStart(node) || isFinallyEnd(node)); } - public static boolean isFinallyMarker(@Nullable AbstractInsnNode node, String name) { + private static boolean isFinallyMarker(@NotNull AbstractInsnNode node, String name) { if (!(node instanceof MethodInsnNode)) return false; MethodInsnNode method = (MethodInsnNode) node; return INLINE_MARKER_CLASS_NAME.equals(method.owner) && name.equals(method.name); @@ -437,69 +429,51 @@ public class InlineCodegenUtil { return context.isInlineMethodContext() || context instanceof InlineLambdaContext; } - public static int getConstant(AbstractInsnNode ins) { + public static int getConstant(@NotNull AbstractInsnNode ins) { int opcode = ins.getOpcode(); Integer value; if (opcode >= Opcodes.ICONST_0 && opcode <= Opcodes.ICONST_5) { - value = opcode - Opcodes.ICONST_0; + return opcode - Opcodes.ICONST_0; } else if (opcode == Opcodes.BIPUSH || opcode == Opcodes.SIPUSH) { - IntInsnNode index = (IntInsnNode) ins; - value = index.operand; + return ((IntInsnNode) ins).operand; } else { LdcInsnNode index = (LdcInsnNode) ins; - value = (Integer) index.cst; - } - return value; - } - - public static class LabelTextifier extends Textifier { - - public LabelTextifier() { - super(API); - } - - @Nullable - @TestOnly - @SuppressWarnings("UnusedDeclaration") - public String getLabelNameIfExists(@NotNull Label l) { - return labelNames == null ? null : labelNames.get(l); + return (Integer) index.cst; } } - public static void addInlineMarker( - @NotNull InstructionAdapter v, - boolean isStartNotEnd - ) { - v.visitMethodInsn(Opcodes.INVOKESTATIC, INLINE_MARKER_CLASS_NAME, - (isStartNotEnd ? INLINE_MARKER_BEFORE_METHOD_NAME : INLINE_MARKER_AFTER_METHOD_NAME), - "()V", false); + public static void addInlineMarker(@NotNull InstructionAdapter v, boolean isStartNotEnd) { + v.visitMethodInsn( + Opcodes.INVOKESTATIC, INLINE_MARKER_CLASS_NAME, + isStartNotEnd ? INLINE_MARKER_BEFORE_METHOD_NAME : INLINE_MARKER_AFTER_METHOD_NAME, + "()V", false + ); } - public static boolean isInlineMarker(AbstractInsnNode insn) { + public static boolean isInlineMarker(@NotNull AbstractInsnNode insn) { return isInlineMarker(insn, null); } - public static boolean isInlineMarker(AbstractInsnNode insn, String name) { - if (insn instanceof MethodInsnNode) { - MethodInsnNode methodInsnNode = (MethodInsnNode) insn; - return insn.getOpcode() == Opcodes.INVOKESTATIC && - methodInsnNode.owner.equals(INLINE_MARKER_CLASS_NAME) && - (name != null ? methodInsnNode.name.equals(name) - : methodInsnNode.name.equals(INLINE_MARKER_BEFORE_METHOD_NAME) || - methodInsnNode.name.equals(INLINE_MARKER_AFTER_METHOD_NAME)); - } - else { + private static boolean isInlineMarker(@NotNull AbstractInsnNode insn, @Nullable String name) { + if (!(insn instanceof MethodInsnNode)) { return false; } + + MethodInsnNode methodInsnNode = (MethodInsnNode) insn; + return insn.getOpcode() == Opcodes.INVOKESTATIC && + methodInsnNode.owner.equals(INLINE_MARKER_CLASS_NAME) && + (name != null ? methodInsnNode.name.equals(name) + : methodInsnNode.name.equals(INLINE_MARKER_BEFORE_METHOD_NAME) || + methodInsnNode.name.equals(INLINE_MARKER_AFTER_METHOD_NAME)); } - public static boolean isBeforeInlineMarker(AbstractInsnNode insn) { + public static boolean isBeforeInlineMarker(@NotNull AbstractInsnNode insn) { return isInlineMarker(insn, INLINE_MARKER_BEFORE_METHOD_NAME); } - public static boolean isAfterInlineMarker(AbstractInsnNode insn) { + public static boolean isAfterInlineMarker(@NotNull AbstractInsnNode insn) { return isInlineMarker(insn, INLINE_MARKER_AFTER_METHOD_NAME); } @@ -511,44 +485,27 @@ public class InlineCodegenUtil { return opcode >= Opcodes.ISTORE && opcode <= Opcodes.ASTORE; } - public static int calcMarkerShift(Parameters parameters, MethodNode node) { + public static int calcMarkerShift(@NotNull Parameters parameters, @NotNull MethodNode node) { int markerShiftTemp = getIndexAfterLastMarker(node); return markerShiftTemp - parameters.getRealArgsSizeOnStack() + parameters.getArgsSizeOnStack(); } - protected static int getIndexAfterLastMarker(MethodNode node) { - int markerShiftTemp = -1; + private static int getIndexAfterLastMarker(@NotNull MethodNode node) { + int result = -1; for (LocalVariableNode variable : node.localVariables) { if (isFakeLocalVariableForInline(variable.name)) { - markerShiftTemp = Math.max(markerShiftTemp, variable.index + 1); + result = Math.max(result, variable.index + 1); } } - return markerShiftTemp; - } - - public static boolean isFakeLocalVariableForInline(@NotNull String name) { - return name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION) || name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT); - } - - public static boolean isThis0(String name) { - return THIS$0.equals(name); - } - - @Nullable - public static AbstractInsnNode getPrevMeaningful(@NotNull AbstractInsnNode node) { - AbstractInsnNode result = node.getPrevious(); - while (result != null && !UtilKt.isMeaningful(result)) { - result = result.getPrevious(); - } return result; } - public static void removeInterval(@NotNull MethodNode node, @NotNull AbstractInsnNode startInc, @NotNull AbstractInsnNode endInc) { - while (startInc != endInc) { - AbstractInsnNode next = startInc.getNext(); - node.instructions.remove(startInc); - startInc = next; - } - node.instructions.remove(startInc); + public static boolean isFakeLocalVariableForInline(@NotNull String name) { + return name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION) || + name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT); + } + + public static boolean isThis0(@NotNull String name) { + return THIS$0.equals(name); } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlinedLambdaRemapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlinedLambdaRemapper.java index 2c9df346d98..1319f89d0a9 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlinedLambdaRemapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlinedLambdaRemapper.java @@ -24,7 +24,6 @@ import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode; import java.util.Collection; public class InlinedLambdaRemapper extends FieldRemapper { - public InlinedLambdaRemapper( @NotNull String lambdaInternalName, @NotNull FieldRemapper parent, @@ -34,16 +33,13 @@ public class InlinedLambdaRemapper extends FieldRemapper { } @Override - public boolean canProcess(@NotNull String fieldOwner, String fieldName, boolean isFolding) { - return isFolding && super.canProcess(fieldOwner, fieldName, isFolding); + public boolean canProcess(@NotNull String fieldOwner, @NotNull String fieldName, boolean isFolding) { + return isFolding && super.canProcess(fieldOwner, fieldName, true); } @Override @Nullable - public CapturedParamInfo findField( - @NotNull FieldInsnNode fieldInsnNode, - @NotNull Collection captured - ) { + public CapturedParamInfo findField(@NotNull FieldInsnNode fieldInsnNode, @NotNull Collection captured) { return parent.findField(fieldInsnNode, captured); } @@ -52,14 +48,12 @@ public class InlinedLambdaRemapper extends FieldRemapper { return true; } - @Nullable @Override public StackValue getFieldForInline(@NotNull FieldInsnNode node, @Nullable StackValue prefix) { if (parent.isRoot()) { return super.getFieldForInline(node, prefix); - } else { - return parent.getFieldForInline(node, prefix); } + return parent.getFieldForInline(node, prefix); } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InliningContext.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InliningContext.java index 391ed54a734..6103b062b7c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InliningContext.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InliningContext.java @@ -25,87 +25,76 @@ import java.util.HashMap; import java.util.Map; public class InliningContext { - @Nullable private final InliningContext parent; - public final Map expressionMap; - + private final Map expressionMap; public final GenerationState state; - public final NameGenerator nameGenerator; - public final TypeRemapper typeRemapper; - - public final ReifiedTypeInliner reifedTypeInliner; - + public final ReifiedTypeInliner reifiedTypeInliner; public final boolean isInliningLambda; - public final boolean classRegeneration; - protected InliningContext( + public InliningContext( @Nullable InliningContext parent, - @NotNull Map map, + @NotNull Map expressionMap, @NotNull GenerationState state, @NotNull NameGenerator nameGenerator, @NotNull TypeRemapper typeRemapper, - @NotNull ReifiedTypeInliner reifedTypeInliner, + @NotNull ReifiedTypeInliner reifiedTypeInliner, boolean isInliningLambda, boolean classRegeneration ) { this.parent = parent; - expressionMap = map; + this.expressionMap = expressionMap; this.state = state; this.nameGenerator = nameGenerator; this.typeRemapper = typeRemapper; - this.reifedTypeInliner = reifedTypeInliner; + this.reifiedTypeInliner = reifiedTypeInliner; this.isInliningLambda = isInliningLambda; this.classRegeneration = classRegeneration; } - public InliningContext subInline(NameGenerator generator) { - return subInline(generator, Collections.emptyMap()); + @NotNull + public InliningContext subInline(@NotNull NameGenerator generator) { + return subInline(generator, Collections.emptyMap(), isInliningLambda); } - public InliningContext subInlineLambda(LambdaInfo lambdaInfo) { + @NotNull + public InliningContext subInlineLambda(@NotNull LambdaInfo lambdaInfo) { Map map = new HashMap(); map.put(lambdaInfo.getLambdaClassType().getInternalName(), null); //mark lambda inlined return subInline(nameGenerator.subGenerator("lambda"), map, true); } - private InliningContext subInline(NameGenerator generator, Map additionalTypeMappings) { - return subInline(generator, additionalTypeMappings, isInliningLambda); - } - + @NotNull public InliningContext subInlineWithClassRegeneration( @NotNull NameGenerator generator, @NotNull Map newTypeMappings, @NotNull InlineCallSiteInfo callSiteInfo ) { - return new RegeneratedClassContext(this, expressionMap, state, generator, - TypeRemapper.createFrom(typeRemapper, newTypeMappings), - reifedTypeInliner, isInliningLambda, callSiteInfo); - } - - public InliningContext subInline(NameGenerator generator, Map additionalTypeMappings, boolean isInliningLambda) { - return subInline(generator, additionalTypeMappings, isInliningLambda, classRegeneration); + return new RegeneratedClassContext( + this, expressionMap, state, generator, TypeRemapper.createFrom(typeRemapper, newTypeMappings), + reifiedTypeInliner, isInliningLambda, callSiteInfo + ); } + @NotNull private InliningContext subInline( - NameGenerator generator, - Map additionalTypeMappings, - boolean isInliningLambda, - boolean isRegeneration + @NotNull NameGenerator generator, @NotNull Map additionalTypeMappings, boolean isInliningLambda ) { //isInliningLambda && !this.isInliningLambda for root inline lambda - return new InliningContext(this, expressionMap, state, generator, - TypeRemapper.createFrom( - typeRemapper, - additionalTypeMappings, - //root inline lambda - isInliningLambda && !this.isInliningLambda - ), - reifedTypeInliner, isInliningLambda, isRegeneration); + return new InliningContext( + this, expressionMap, state, generator, + TypeRemapper.createFrom( + typeRemapper, + additionalTypeMappings, + //root inline lambda + isInliningLambda && !this.isInliningLambda + ), + reifiedTypeInliner, isInliningLambda, classRegeneration + ); } public boolean isRoot() { @@ -114,12 +103,8 @@ public class InliningContext { @NotNull public RootInliningContext getRoot() { - if (isRoot()) { - return (RootInliningContext) this; - } - else { - return parent.getRoot(); - } + //noinspection ConstantConditions + return isRoot() ? (RootInliningContext) this : parent.getRoot(); } @Nullable @@ -127,11 +112,7 @@ public class InliningContext { return parent; } - public boolean isInliningLambdaRootContext() { - //noinspection ConstantConditions - return isInliningLambda && !getParent().isInliningLambda; - } - + @NotNull public InlineCallSiteInfo getCallSiteInfo() { assert parent != null : "At least root context should return proper value"; return parent.getCallSiteInfo(); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.java index 0b65515e9b7..10cf9e4f4d8 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.java @@ -40,36 +40,26 @@ import java.util.Set; import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*; public class LambdaInfo implements CapturedParamOwner, LabelOwner { - public final KtExpression expression; - private final KotlinTypeMapper typeMapper; - - @NotNull public final Set labels; - private final CalculatedClosure closure; - public final boolean isCrossInline; - - private SMAPAndMethodNode node; - - private List capturedVars; - private final FunctionDescriptor functionDescriptor; - private final ClassDescriptor classDescriptor; - private final Type closureClassType; - LambdaInfo(@NotNull KtExpression expr, @NotNull KotlinTypeMapper typeMapper, boolean isCrossInline) { + private SMAPAndMethodNode node; + private List capturedVars; + + public LambdaInfo(@NotNull KtExpression expression, @NotNull KotlinTypeMapper typeMapper, boolean isCrossInline) { this.isCrossInline = isCrossInline; - this.expression = expr instanceof KtLambdaExpression ? - ((KtLambdaExpression) expr).getFunctionLiteral() : expr; + this.expression = expression instanceof KtLambdaExpression ? + ((KtLambdaExpression) expression).getFunctionLiteral() : expression; this.typeMapper = typeMapper; BindingContext bindingContext = typeMapper.getBindingContext(); - functionDescriptor = bindingContext.get(BindingContext.FUNCTION, expression); + functionDescriptor = bindingContext.get(BindingContext.FUNCTION, this.expression); assert functionDescriptor != null : "Function is not resolved to descriptor: " + expression.getText(); classDescriptor = anonymousClassForCallable(bindingContext, functionDescriptor); @@ -78,34 +68,39 @@ public class LambdaInfo implements CapturedParamOwner, LabelOwner { closure = bindingContext.get(CLOSURE, classDescriptor); assert closure != null : "Closure for lambda should be not null " + expression.getText(); - - labels = InlineCodegen.getDeclarationLabels(expr, functionDescriptor); + labels = InlineCodegen.getDeclarationLabels(expression, functionDescriptor); } + @NotNull public SMAPAndMethodNode getNode() { return node; } - public void setNode(SMAPAndMethodNode node) { + public void setNode(@NotNull SMAPAndMethodNode node) { this.node = node; } + @NotNull public FunctionDescriptor getFunctionDescriptor() { return functionDescriptor; } + @NotNull public KtExpression getFunctionWithBodyOrCallableReference() { return expression; } + @NotNull public ClassDescriptor getClassDescriptor() { return classDescriptor; } + @NotNull public Type getLambdaClassType() { return closureClassType; } + @NotNull public List getCapturedVars() { //lazy initialization cause it would be calculated after object creation if (capturedVars == null) { @@ -114,11 +109,12 @@ public class LambdaInfo implements CapturedParamOwner, LabelOwner { if (closure.getCaptureThis() != null) { Type type = typeMapper.mapType(closure.getCaptureThis()); EnclosedValueDescriptor descriptor = - new EnclosedValueDescriptor(AsmUtil.CAPTURED_THIS_FIELD, - null, - StackValue.field(type, closureClassType, AsmUtil.CAPTURED_THIS_FIELD, false, - StackValue.LOCAL_0), - type); + new EnclosedValueDescriptor( + AsmUtil.CAPTURED_THIS_FIELD, + /* descriptor = */ null, + StackValue.field(type, closureClassType, AsmUtil.CAPTURED_THIS_FIELD, false, StackValue.LOCAL_0), + type + ); capturedVars.add(getCapturedParamInfo(descriptor)); } @@ -127,10 +123,10 @@ public class LambdaInfo implements CapturedParamOwner, LabelOwner { EnclosedValueDescriptor descriptor = new EnclosedValueDescriptor( AsmUtil.CAPTURED_RECEIVER_FIELD, - null, - StackValue.field(type, closureClassType, AsmUtil.CAPTURED_RECEIVER_FIELD, false, - StackValue.LOCAL_0), - type); + /* descriptor = */ null, + StackValue.field(type, closureClassType, AsmUtil.CAPTURED_RECEIVER_FIELD, false, StackValue.LOCAL_0), + type + ); capturedVars.add(getCapturedParamInfo(descriptor)); } @@ -143,29 +139,29 @@ public class LambdaInfo implements CapturedParamOwner, LabelOwner { @NotNull private CapturedParamDesc getCapturedParamInfo(@NotNull EnclosedValueDescriptor descriptor) { - return CapturedParamDesc.createDesc(this, descriptor.getFieldName(), descriptor.getType()); + return new CapturedParamDesc(this, descriptor.getFieldName(), descriptor.getType()); } @NotNull public List getInvokeParamsWithoutCaptured() { - Type[] types = typeMapper.mapAsmMethod(functionDescriptor).getArgumentTypes(); - return Arrays.asList(types); + return Arrays.asList(typeMapper.mapAsmMethod(functionDescriptor).getArgumentTypes()); } @NotNull - public Parameters addAllParameters(FieldRemapper remapper) { + public Parameters addAllParameters(@NotNull FieldRemapper remapper) { Method asmMethod = typeMapper.mapAsmMethod(getFunctionDescriptor()); - ParametersBuilder builder = - ParametersBuilder.initializeBuilderFrom(AsmTypes.OBJECT_TYPE, asmMethod.getDescriptor(), this); + ParametersBuilder builder = ParametersBuilder.initializeBuilderFrom(AsmTypes.OBJECT_TYPE, asmMethod.getDescriptor(), this); for (CapturedParamDesc info : getCapturedVars()) { CapturedParamInfo field = remapper.findField(new FieldInsnNode(0, info.getContainingLambdaName(), info.getFieldName(), "")); + assert field != null : "Captured field not found: " + info.getContainingLambdaName() + "." + info.getFieldName(); builder.addCapturedParam(field, info.getFieldName()); } return builder.buildParameters(); } + @NotNull @Override public Type getType() { return closureClassType; @@ -175,6 +171,4 @@ public class LambdaInfo implements CapturedParamOwner, LabelOwner { public boolean isMyLabel(@NotNull String name) { return labels.contains(name); } - } - diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LocalVarRemapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LocalVarRemapper.java index e69c30cfa30..df748dfb990 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LocalVarRemapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LocalVarRemapper.java @@ -28,18 +28,16 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; import static org.jetbrains.kotlin.codegen.inline.LocalVarRemapper.RemapStatus.*; public class LocalVarRemapper { - private final Parameters params; private final int actualParamsSize; - private final StackValue[] remapValues; private final int additionalShift; - public LocalVarRemapper(Parameters params, int additionalShift) { + public LocalVarRemapper(@NotNull Parameters params, int additionalShift) { this.additionalShift = additionalShift; this.params = params; - remapValues = new StackValue [params.getArgsSizeOnStack()]; + remapValues = new StackValue[params.getArgsSizeOnStack()]; int realSize = 0; for (ParameterInfo info : params) { @@ -56,7 +54,8 @@ public class LocalVarRemapper { actualParamsSize = realSize; } - public RemapInfo doRemap(int index) { + @NotNull + private RemapInfo doRemap(int index) { int remappedIndex; if (index < params.getArgsSizeOnStack()) { @@ -67,16 +66,20 @@ public class LocalVarRemapper { } if (info.isRemapped()) { return new RemapInfo(remapped, info, REMAPPED); - } else { - remappedIndex = ((StackValue.Local)remapped).index; } - } else { - remappedIndex = actualParamsSize - params.getArgsSizeOnStack() + index; //captured params not used directly in this inlined method, they used in closure + else { + remappedIndex = ((StackValue.Local) remapped).index; + } + } + else { + //captured params are not used directly in this inlined method, they are used in closure + remappedIndex = actualParamsSize - params.getArgsSizeOnStack() + index; } return new RemapInfo(StackValue.local(remappedIndex + additionalShift, AsmTypes.OBJECT_TYPE), null, SHIFT); } + @NotNull public RemapInfo remap(int index) { RemapInfo info = doRemap(index); if (FAIL == info.status) { @@ -86,23 +89,29 @@ public class LocalVarRemapper { return info; } - public void visitIincInsn(int var, int increment, MethodVisitor mv) { + public void visitIincInsn(int var, int increment, @NotNull MethodVisitor mv) { RemapInfo remap = remap(var); - assert remap.value instanceof StackValue.Local; + assert remap.value instanceof StackValue.Local : "Remapped value should be a local: " + remap.value; mv.visitIincInsn(((StackValue.Local) remap.value).index, increment); } - public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index, MethodVisitor mv) { + public void visitLocalVariable( + @NotNull String name, + @NotNull String desc, + @Nullable String signature, + @NotNull Label start, + @NotNull Label end, + int index, + MethodVisitor mv + ) { RemapInfo info = doRemap(index); //add entries only for shifted vars if (SHIFT == info.status) { - int newIndex = ((StackValue.Local) info.value).index; - mv.visitLocalVariable(name, desc, signature, start, end, newIndex); + mv.visitLocalVariable(name, desc, signature, start, end, ((StackValue.Local) info.value).index); } } - - public void visitVarInsn(int opcode, int var, InstructionAdapter mv) { + public void visitVarInsn(int opcode, int var, @NotNull InstructionAdapter mv) { RemapInfo remapInfo = remap(var); StackValue value = remapInfo.value; if (value instanceof StackValue.Local) { @@ -117,7 +126,8 @@ public class LocalVarRemapper { if (remapInfo.parameterInfo != null) { 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); } @@ -134,15 +144,15 @@ public class LocalVarRemapper { public final ParameterInfo parameterInfo; public final RemapStatus status; - public RemapInfo(@NotNull StackValue value, @Nullable ParameterInfo info, RemapStatus remapStatus) { + public RemapInfo(@NotNull StackValue value, @Nullable ParameterInfo parameterInfo, @NotNull RemapStatus remapStatus) { this.value = value; - parameterInfo = info; + this.parameterInfo = parameterInfo; this.status = remapStatus; } - public RemapInfo(@NotNull ParameterInfo info) { + public RemapInfo(@NotNull ParameterInfo parameterInfo) { this.value = null; - parameterInfo = info; + this.parameterInfo = parameterInfo; this.status = FAIL; } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodBodyVisitor.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodBodyVisitor.java index 6d85ae0f52c..c9c11bcf753 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodBodyVisitor.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodBodyVisitor.java @@ -54,7 +54,7 @@ public class MethodBodyVisitor extends InstructionAdapter { } @Override - public void visitAttribute(Attribute attr) { + public void visitAttribute(@NotNull Attribute attr) { } @Override diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java index 0f9be2c5a64..92b0d9024f8 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java @@ -43,45 +43,24 @@ import java.util.*; import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.*; public class MethodInliner { - private final MethodNode node; - private final Parameters parameters; - private final InliningContext inliningContext; - private final FieldRemapper nodeRemapper; - private final boolean isSameModule; - private final String errorPrefix; - private final SourceMapper sourceMapper; - private final InlineCallSiteInfo inlineCallSiteInfo; - private final KotlinTypeMapper typeMapper; - private final List invokeCalls = new ArrayList(); - //keeps order private final List transformations = new ArrayList(); //current state private final Map currentTypeMapping = new HashMap(); - private final InlineResult result; - private int lambdasFinallyBlocks; - private final InlineOnlySmapSkipper inlineOnlySmapSkipper; - /* - * - * @param node - * @param parameters - * @param inliningContext - * @param lambdaType - in case on lambda 'invoke' inlining - */ public MethodInliner( @NotNull MethodNode node, @NotNull Parameters parameters, @@ -106,6 +85,7 @@ public class MethodInliner { this.inlineOnlySmapSkipper = smapSkipper; } + @NotNull public InlineResult doInline( @NotNull MethodVisitor adapter, @NotNull LocalVarRemapper remapper, @@ -115,6 +95,7 @@ public class MethodInliner { return doInline(adapter, remapper, remapReturn, labelOwner, 0); } + @NotNull private InlineResult doInline( @NotNull MethodVisitor adapter, @NotNull LocalVarRemapper remapper, @@ -129,11 +110,12 @@ public class MethodInliner { Label end = new Label(); transformedNode = doInline(transformedNode); removeClosureAssertions(transformedNode); - InsnList instructions = transformedNode.instructions; - instructions.resetLabels(); + transformedNode.instructions.resetLabels(); - MethodNode resultNode = new MethodNode(InlineCodegenUtil.API, transformedNode.access, transformedNode.name, transformedNode.desc, - transformedNode.signature, ArrayUtil.toStringArray(transformedNode.exceptions)); + MethodNode resultNode = new MethodNode( + InlineCodegenUtil.API, transformedNode.access, transformedNode.name, transformedNode.desc, + transformedNode.signature, ArrayUtil.toStringArray(transformedNode.exceptions) + ); RemapVisitor visitor = new RemapVisitor(resultNode, remapper, nodeRemapper); try { transformedNode.accept(visitor); @@ -145,7 +127,10 @@ public class MethodInliner { resultNode.visitLabel(end); if (inliningContext.isRoot()) { - InternalFinallyBlockInliner.processInlineFunFinallyBlocks(resultNode, lambdasFinallyBlocks, ((StackValue.Local)remapper.remap(parameters.getArgsSizeOnStack() + 1).value).index); + StackValue remapValue = remapper.remap(parameters.getArgsSizeOnStack() + 1).value; + InternalFinallyBlockInliner.processInlineFunFinallyBlocks( + resultNode, lambdasFinallyBlocks, ((StackValue.Local) remapValue).index + ); } processReturns(resultNode, labelOwner, remapReturn, end); @@ -156,8 +141,8 @@ public class MethodInliner { return result; } - private MethodNode doInline(final MethodNode node) { - + @NotNull + private MethodNode doInline(@NotNull MethodNode node) { final Deque currentInvokes = new LinkedList(invokeCalls); final MethodNode resultNode = new MethodNode(node.access, node.name, node.desc, node.signature, null); @@ -174,8 +159,8 @@ public class MethodInliner { final int markerShift = InlineCodegenUtil.calcMarkerShift(parameters, node); InlineAdapter lambdaInliner = new InlineAdapter(remappingMethodAdapter, parameters.getArgsSizeOnStack(), sourceMapper) { - private TransformationInfo transformationInfo; + private void handleAnonymousObjectRegeneration() { transformationInfo = iterator.next(); @@ -190,10 +175,7 @@ public class MethodInliner { currentTypeMapping, inlineCallSiteInfo ); - ObjectTransformer transformer = transformationInfo.createTransformer( - childInliningContext, - isSameModule - ); + ObjectTransformer transformer = transformationInfo.createTransformer(childInliningContext, isSameModule); InlineResult transformResult = transformer.doTransform(nodeRemapper); result.addAllClassesToRemove(transformResult); @@ -213,7 +195,7 @@ public class MethodInliner { @Override public void anew(@NotNull Type type) { - if (isAnonymousConstructorCall(type.getInternalName(), "")) { + if (isAnonymousClass(type.getInternalName())) { handleAnonymousObjectRegeneration(); } @@ -245,23 +227,25 @@ public class MethodInliner { setLambdaInlining(true); SMAP lambdaSMAP = info.getNode().getClassSMAP(); + //noinspection ConstantConditions SourceMapper mapper = - inliningContext.classRegeneration && !inliningContext.isInliningLambda ? - new NestedSourceMapper(sourceMapper, lambdaSMAP.getIntervals(), lambdaSMAP.getSourceInfo()) + inliningContext.classRegeneration && !inliningContext.isInliningLambda + ? new NestedSourceMapper(sourceMapper, lambdaSMAP.getIntervals(), lambdaSMAP.getSourceInfo()) : new InlineLambdaSourceMapper(sourceMapper.getParent(), info.getNode()); - MethodInliner inliner = new MethodInliner(info.getNode().getNode(), lambdaParameters, - inliningContext.subInlineLambda(info), - newCapturedRemapper, true /*cause all calls in same module as lambda*/, - "Lambda inlining " + info.getLambdaClassType().getInternalName(), - mapper, inlineCallSiteInfo, null); + MethodInliner inliner = new MethodInliner( + info.getNode().getNode(), lambdaParameters, inliningContext.subInlineLambda(info), + newCapturedRemapper, true /*cause all calls in same module as lambda*/, + "Lambda inlining " + info.getLambdaClassType().getInternalName(), + mapper, inlineCallSiteInfo, null + ); LocalVarRemapper remapper = new LocalVarRemapper(lambdaParameters, valueParamShift); - InlineResult lambdaResult = inliner.doInline(this.mv, remapper, true, info, invokeCall.finallyDepthShift);//TODO add skipped this and receiver + //TODO add skipped this and receiver + InlineResult lambdaResult = inliner.doInline(this.mv, remapper, true, info, invokeCall.finallyDepthShift); result.addAllClassesToRemove(lambdaResult); //return value boxing/unboxing - Method bridge = - typeMapper.mapAsmMethod(ClosureCodegen.getErasedInvokeFunction(info.getFunctionDescriptor())); + Method bridge = typeMapper.mapAsmMethod(ClosureCodegen.getErasedInvokeFunction(info.getFunctionDescriptor())); Method delegate = typeMapper.mapAsmMethod(info.getFunctionDescriptor()); StackValue.onStack(delegate.getReturnType()).put(bridge.getReturnType(), this); setLambdaInlining(false); @@ -274,31 +258,38 @@ public class MethodInliner { else if (isAnonymousConstructorCall(owner, name)) { //TODO add method //TODO add proper message assert transformationInfo instanceof AnonymousObjectTransformationInfo : - " call doesn't correspond to object transformation info: " + owner + "." + name + ", info " + transformationInfo; + " call doesn't correspond to object transformation info: " + + owner + "." + name + ", info " + transformationInfo; if (transformationInfo.shouldRegenerate(isSameModule)) { //put additional captured parameters on stack - for (CapturedParamDesc capturedParamDesc : ((AnonymousObjectTransformationInfo) transformationInfo).getAllRecapturedParameters()) { - visitFieldInsn(Opcodes.GETSTATIC, capturedParamDesc.getContainingLambdaName(), - "$$$" + capturedParamDesc.getFieldName(), capturedParamDesc.getType().getDescriptor()); + AnonymousObjectTransformationInfo info = (AnonymousObjectTransformationInfo) transformationInfo; + for (CapturedParamDesc capturedParamDesc : info.getAllRecapturedParameters()) { + visitFieldInsn( + Opcodes.GETSTATIC, capturedParamDesc.getContainingLambdaName(), + "$$$" + capturedParamDesc.getFieldName(), capturedParamDesc.getType().getDescriptor() + ); } - super.visitMethodInsn(opcode, transformationInfo.getNewClassName(), name, - ((AnonymousObjectTransformationInfo) transformationInfo).getNewConstructorDescriptor(), itf); + super.visitMethodInsn(opcode, transformationInfo.getNewClassName(), name, info.getNewConstructorDescriptor(), itf); //TODO: add new inner class also for other contexts if (inliningContext.getParent() instanceof RegeneratedClassContext) { - inliningContext.getParent().typeRemapper.addAdditionalMappings(transformationInfo.getOldClassName(), transformationInfo.getNewClassName()); + inliningContext.getParent().typeRemapper.addAdditionalMappings( + transformationInfo.getOldClassName(), transformationInfo.getNewClassName() + ); } transformationInfo = null; - } else { - super.visitMethodInsn(opcode, changeOwnerForExternalPackage(owner, opcode), name, desc, itf); + } + else { + super.visitMethodInsn(opcode, owner, name, desc, itf); } } - else if (!inliningContext.isInliningLambda && ReifiedTypeInliner.isNeedClassReificationMarker(new MethodInsnNode(opcode, owner, name, desc, false))) { + else if (!inliningContext.isInliningLambda && + ReifiedTypeInliner.isNeedClassReificationMarker(new MethodInsnNode(opcode, owner, name, desc, false))) { //we shouldn't process here content of inlining lambda it should be reified at external level } else { - super.visitMethodInsn(opcode, changeOwnerForExternalPackage(owner, opcode), name, desc, itf); + super.visitMethodInsn(opcode, owner, name, desc, itf); } } @@ -315,7 +306,6 @@ public class MethodInliner { lambdasFinallyBlocks = resultNode.tryCatchBlocks.size(); super.visitMaxs(stack, locals); } - }; node.accept(lambdaInliner); @@ -324,18 +314,20 @@ public class MethodInliner { } @NotNull - public static CapturedParamInfo findCapturedField(FieldInsnNode node, FieldRemapper fieldRemapper) { + public static CapturedParamInfo findCapturedField(@NotNull FieldInsnNode node, @NotNull FieldRemapper fieldRemapper) { assert node.name.startsWith("$$$") : "Captured field template should start with $$$ prefix"; FieldInsnNode fin = new FieldInsnNode(node.getOpcode(), node.owner, node.name.substring(3), node.desc); CapturedParamInfo field = fieldRemapper.findField(fin); if (field == null) { - throw new IllegalStateException("Couldn't find captured field " + node.owner + "." + node.name + " in " + fieldRemapper.getLambdaInternalName()); + throw new IllegalStateException( + "Couldn't find captured field " + node.owner + "." + node.name + " in " + fieldRemapper.getLambdaInternalName() + ); } return field; } @NotNull - public MethodNode prepareNode(@NotNull MethodNode node, int finallyDeepShift) { + private MethodNode prepareNode(@NotNull MethodNode node, int finallyDeepShift) { final int capturedParamsSize = parameters.getCapturedArgsSizeOnStack(); final int realParametersSize = parameters.getRealArgsSizeOnStack(); Type[] types = Type.getArgumentTypes(node.desc); @@ -345,8 +337,10 @@ public class MethodInliner { Type[] allTypes = ArrayUtil.mergeArrays(types, capturedTypes.toArray(new Type[capturedTypes.size()])); node.instructions.resetLabels(); - MethodNode transformedNode = new MethodNode(InlineCodegenUtil.API, node.access, node.name, Type.getMethodDescriptor(returnType, allTypes), node.signature, null) { - + MethodNode transformedNode = new MethodNode( + InlineCodegenUtil.API, node.access, node.name, Type.getMethodDescriptor(returnType, allTypes), node.signature, null + ) { + @SuppressWarnings("ConstantConditions") private final boolean GENERATE_DEBUG_INFO = InlineCodegenUtil.GENERATE_SMAP && inlineOnlySmapSkipper == null; private final boolean isInliningLambda = nodeRemapper.isInsideInliningLambda(); @@ -372,7 +366,7 @@ public class MethodInliner { @Override public void visitLineNumber(int line, @NotNull Label start) { - if(isInliningLambda || GENERATE_DEBUG_INFO) { + if (isInliningLambda || GENERATE_DEBUG_INFO) { super.visitLineNumber(line, start); } } @@ -382,9 +376,8 @@ public class MethodInliner { @NotNull String name, @NotNull String desc, String signature, @NotNull Label start, @NotNull Label end, int index ) { if (isInliningLambda || GENERATE_DEBUG_INFO) { - String varSuffix = inliningContext.isRoot() && - !InlineCodegenUtil.isFakeLocalVariableForInline(name) ? - INLINE_FUN_VAR_SUFFIX : ""; + String varSuffix = + inliningContext.isRoot() && !InlineCodegenUtil.isFakeLocalVariableForInline(name) ? INLINE_FUN_VAR_SUFFIX : ""; String varName = !varSuffix.isEmpty() && name.equals("this") ? name + "_" : name; super.visitLocalVariable(varName + varSuffix, desc, signature, start, end, getNewIndex(index)); } @@ -400,7 +393,9 @@ public class MethodInliner { } @NotNull - protected MethodNode markPlacesForInlineAndRemoveInlinable(@NotNull MethodNode node, @NotNull LabelOwner labelOwner, int finallyDeepShift) { + private MethodNode markPlacesForInlineAndRemoveInlinable( + @NotNull MethodNode node, @NotNull LabelOwner labelOwner, int finallyDeepShift + ) { node = prepareNode(node, finallyDeepShift); Frame[] sources = analyzeMethodNodeBeforeInline(node); @@ -460,9 +455,7 @@ public class MethodInliner { } transformations.add( - buildConstructorInvocation( - owner, desc, lambdaMapping, awaitClassReification - ) + buildConstructorInvocation(owner, desc, lambdaMapping, awaitClassReification) ); awaitClassReification = false; } @@ -482,7 +475,8 @@ public class MethodInliner { else if (isWhenMappingAccess(className, fieldInsnNode.name)) { transformations.add( new WhenMappingTransformationInfo( - className, inliningContext.nameGenerator, isAlreadyRegenerated(className), fieldInsnNode) + className, inliningContext.nameGenerator, isAlreadyRegenerated(className), fieldInsnNode + ) ); } @@ -498,7 +492,8 @@ public class MethodInliner { //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(prevNode); } } @@ -522,6 +517,7 @@ public class MethodInliner { return node; } + @NotNull private Frame[] analyzeMethodNodeBeforeInline(@NotNull MethodNode node) { try { new MandatoryMethodTransformer().transform("fake", node); @@ -545,14 +541,12 @@ public class MethodInliner { } }; - Frame[] sources; try { - sources = analyzer.analyze("fake", node); + return analyzer.analyze("fake", node); } catch (AnalyzerException e) { throw wrapException(e, node, "couldn't inline method call"); } - return sources; } private static boolean isEmptyTryInterval(@NotNull TryCatchBlockNode tryCatchBlockNode) { @@ -595,7 +589,8 @@ public class MethodInliner { int varIndex = ((VarInsnNode) insnNode).var; return getLambdaIfExists(varIndex); } - else if (insnNode instanceof FieldInsnNode) { + + if (insnNode instanceof FieldInsnNode) { FieldInsnNode fieldInsnNode = (FieldInsnNode) insnNode; if (fieldInsnNode.name.startsWith("$$$")) { return findCapturedField(fieldInsnNode, nodeRemapper).getLambda(); @@ -605,6 +600,7 @@ public class MethodInliner { return null; } + @Nullable private LambdaInfo getLambdaIfExists(int varIndex) { if (varIndex < parameters.getArgsSizeOnStack()) { return parameters.getParameterByDeclarationSlot(varIndex).getLambda(); @@ -612,13 +608,14 @@ public class MethodInliner { return null; } - private static void removeClosureAssertions(MethodNode node) { + private static void removeClosureAssertions(@NotNull MethodNode node) { AbstractInsnNode cur = node.instructions.getFirst(); while (cur != null && cur.getNext() != null) { AbstractInsnNode next = cur.getNext(); if (next.getType() == AbstractInsnNode.METHOD_INSN) { MethodInsnNode methodInsnNode = (MethodInsnNode) next; - if (methodInsnNode.name.equals("checkParameterIsNotNull") && methodInsnNode.owner.equals(IntrinsicMethods.INTRINSICS_CLASS_NAME)) { + if (methodInsnNode.name.equals("checkParameterIsNotNull") && + methodInsnNode.owner.equals(IntrinsicMethods.INTRINSICS_CLASS_NAME)) { AbstractInsnNode prev = cur.getPrevious(); assert cur.getOpcode() == Opcodes.LDC : "checkParameterIsNotNull should go after LDC but " + cur; @@ -676,7 +673,7 @@ public class MethodInliner { } @NotNull - public static List getCapturedFieldAccessChain(@NotNull VarInsnNode aload0) { + private static List getCapturedFieldAccessChain(@NotNull VarInsnNode aload0) { List fieldAccessChain = new ArrayList(); fieldAccessChain.add(aload0); AbstractInsnNode next = aload0.getNext(); @@ -697,7 +694,9 @@ public class MethodInliner { return fieldAccessChain; } - public static void putStackValuesIntoLocals(List directOrder, int shift, InstructionAdapter iv, String descriptor) { + private static void putStackValuesIntoLocals( + @NotNull List directOrder, int shift, @NotNull InstructionAdapter iv, @NotNull String descriptor + ) { Type[] actualParams = Type.getArgumentTypes(descriptor); assert actualParams.length == directOrder.size() : "Number of expected and actual params should be equals!"; @@ -719,42 +718,21 @@ public class MethodInliner { } } - //TODO: check it's external module - //TODO?: assert method exists in facade? - public String changeOwnerForExternalPackage(String type, int opcode) { - //if (isSameModule || (opcode & Opcodes.INVOKESTATIC) == 0) { - // return type; - //} - - //JvmClassName name = JvmClassName.byInternalName(type); - //String packageClassInternalName = PackageClassUtils.getPackageClassInternalName(name.getPackageFqName()); - //if (type.startsWith(packageClassInternalName + '$')) { - // VirtualFile virtualFile = InlineCodegenUtil.findVirtualFile(inliningContext.state.getProject(), type); - // if (virtualFile != null) { - // KotlinJvmBinaryClass klass = KotlinBinaryClassCache.getKotlinBinaryClass(virtualFile); - // if (klass != null && klass.getClassHeader().getSyntheticClassKind() == KotlinSyntheticClass.Kind.PACKAGE_PART) { - // return packageClassInternalName; - // } - // } - //} - - return type; - } - @NotNull - public RuntimeException wrapException(@NotNull Throwable originalException, @NotNull MethodNode node, @NotNull String errorSuffix) { + private RuntimeException wrapException(@NotNull Throwable originalException, @NotNull MethodNode node, @NotNull String errorSuffix) { if (originalException instanceof InlineException) { return new InlineException(errorPrefix + ": " + errorSuffix, originalException); } else { - return new InlineException(errorPrefix + ": " + errorSuffix + "\ncause: " + - getNodeText(node), originalException); + return new InlineException(errorPrefix + ": " + errorSuffix + "\nCause: " + getNodeText(node), originalException); } } @NotNull //process local and global returns (local substituted with goto end-label global kept unchanged) - public static List processReturns(@NotNull MethodNode node, @NotNull LabelOwner labelOwner, boolean remapReturn, Label endLabel) { + public static List processReturns( + @NotNull MethodNode node, @NotNull LabelOwner labelOwner, boolean remapReturn, @Nullable Label endLabel + ) { if (!remapReturn) { return Collections.emptyList(); } @@ -785,9 +763,9 @@ public class MethodInliner { //generate finally block before nonLocalReturn flag/return/goto LabelNode label = new LabelNode(); instructions.insert(insnNode, label); - result.add(new PointForExternalFinallyBlocks(getInstructionToInsertFinallyBefore(insnNode, isLocalReturn), - getReturnType(insnNode.getOpcode()), - label)); + result.add(new PointForExternalFinallyBlocks( + getInstructionToInsertFinallyBefore(insnNode, isLocalReturn), getReturnType(insnNode.getOpcode()), label + )); } insnNode = insnNode.getNext(); } @@ -860,7 +838,7 @@ public class MethodInliner { } } - public void transform(MethodNode methodNode) { + public void transform(@NotNull MethodNode methodNode) { int returnVariableIndex = -1; if (needsReturnVariable) { returnVariableIndex = methodNode.maxLocals; @@ -872,6 +850,7 @@ public class MethodInliner { } } + @NotNull public static LocalReturnsNormalizer createFor( @NotNull MethodNode methodNode, @NotNull LabelOwner owner, @@ -905,21 +884,16 @@ public class MethodInliner { } } - - @NotNull - private static AbstractInsnNode getInstructionToInsertFinallyBefore(@NotNull AbstractInsnNode nonLocalReturnOrJump, boolean isLocal) { + private static AbstractInsnNode getInstructionToInsertFinallyBefore(@NotNull AbstractInsnNode nonLocalReturnOrJump, boolean isLocal) { return isLocal ? nonLocalReturnOrJump : nonLocalReturnOrJump.getPrevious(); } //Place to insert finally blocks from try blocks that wraps inline fun call public static class PointForExternalFinallyBlocks { - - final AbstractInsnNode beforeIns; - - final Type returnType; - - final LabelNode finallyIntervalEnd; + public final AbstractInsnNode beforeIns; + public final Type returnType; + public final LabelNode finallyIntervalEnd; public PointForExternalFinallyBlocks( @NotNull AbstractInsnNode beforeIns, @@ -930,6 +904,5 @@ public class MethodInliner { this.returnType = returnType; this.finallyIntervalEnd = finallyIntervalEnd; } - } } 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 8a1cad1249a..a00a975ddbc 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInlinerUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInlinerUtil.kt @@ -16,7 +16,6 @@ package org.jetbrains.kotlin.codegen.inline -import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence import org.jetbrains.kotlin.codegen.optimization.fixStack.top import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode @@ -25,7 +24,6 @@ import org.jetbrains.org.objectweb.asm.tree.VarInsnNode import org.jetbrains.org.objectweb.asm.tree.analysis.Frame import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue - fun MethodInliner.getLambdaIfExistsAndMarkInstructions( insnNode: AbstractInsnNode?, processSwap: Boolean, diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ObjectTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ObjectTransformer.kt index 9a41840c122..1d5f8633f71 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ObjectTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ObjectTransformer.kt @@ -42,14 +42,13 @@ abstract class ObjectTransformer(@JvmField val trans return RemappingClassBuilder( classBuilder, - AsmTypeRemapper(inliningContext.typeRemapper, inliningContext.root.typeParameterMappings == null, transformationResult)) + AsmTypeRemapper(inliningContext.typeRemapper, inliningContext.root.typeParameterMappings == null, transformationResult) + ) } - fun createClassReader(): ClassReader { return InlineCodegenUtil.buildClassReaderByInternalName(state, transformationInfo.oldClassName) } - } class WhenMappingTransformer( @@ -72,7 +71,7 @@ class WhenMappingTransformer( } override fun visitField(access: Int, name: String, desc: String, signature: String?, value: Any?): FieldVisitor? { - return if (name.equals(fieldNode.name)) { + return if (name == fieldNode.name) { classBuilder.newField(JvmDeclarationOrigin.NO_ORIGIN, access, name, desc, signature, value) } else { @@ -80,18 +79,22 @@ class WhenMappingTransformer( } } - override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array?): MethodVisitor? { - val methodNode = MethodNode(access, name, desc, signature, exceptions) - methodNodes.add(methodNode) - return methodNode + override fun visitMethod( + access: Int, name: String, desc: String, signature: String?, exceptions: Array? + ): MethodVisitor? { + return MethodNode(access, name, desc, signature, exceptions).apply { + methodNodes.add(this) + } } }, ClassReader.SKIP_FRAMES) - assert(methodNodes.size == 1, { "When mapping ${fieldNode.owner} class should contain only one method but: " + methodNodes.joinToString { it.name } }) + assert(methodNodes.size == 1) { + "When mapping ${fieldNode.owner} class should contain only one method but: " + methodNodes.joinToString { it.name } + } val clinit = methodNodes.first() assert(clinit.name == "", { "When mapping should contains only method, but contains '${clinit.name}'" }) - var transformedClinit = cutOtherMappings(clinit) + val transformedClinit = cutOtherMappings(clinit) val result = classBuilder.newMethod( JvmDeclarationOrigin.NO_ORIGIN, transformedClinit.access, transformedClinit.name, transformedClinit.desc, transformedClinit.signature, transformedClinit.exceptions.toTypedArray() @@ -102,7 +105,6 @@ class WhenMappingTransformer( return transformationResult } - private fun cutOtherMappings(node: MethodNode): MethodNode { val myArrayAccess = InsnSequence(node.instructions).first { it is FieldInsnNode && it.name.equals(transformationInfo.fieldNode.name) @@ -123,9 +125,9 @@ class WhenMappingTransformer( return result } - private fun isValues(node: AbstractInsnNode) = node is MethodInsnNode && - node.opcode == Opcodes.INVOKESTATIC && - node.name == "values" && - node.desc == "()[" + Type.getObjectType(node.owner).descriptor + private fun isValues(node: AbstractInsnNode) = + node is MethodInsnNode && + node.opcode == Opcodes.INVOKESTATIC && + node.name == "values" && + node.desc == "()[" + Type.getObjectType(node.owner).descriptor } - diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ParameterInfo.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ParameterInfo.java index 2a548334e40..dd48bd9e97b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ParameterInfo.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ParameterInfo.java @@ -22,28 +22,22 @@ import org.jetbrains.kotlin.codegen.StackValue; import org.jetbrains.org.objectweb.asm.Type; class ParameterInfo { - - protected final int index; - - protected final int declarationIndex; + private final int index; + public final int declarationIndex; + public final Type type; + //for skipped parameter: e.g. inlined lambda + public final boolean isSkipped; private boolean isCaptured; - - public final Type type; - - //for skipped parameter: e.g. inlined lambda - public boolean isSkipped; - + private LambdaInfo lambda; //in case when parameter could be extracted from outer context (e.g. from local var) private StackValue remapValue; - public LambdaInfo lambda; - - ParameterInfo(Type type, boolean skipped, int index, int remapValue, int declarationIndex) { + public ParameterInfo(@NotNull Type type, boolean skipped, int index, int remapValue, int declarationIndex) { this(type, skipped, index, remapValue == -1 ? null : StackValue.local(remapValue, type), declarationIndex); } - ParameterInfo(@NotNull Type type, boolean skipped, int index, @Nullable StackValue remapValue, int declarationIndex) { + public ParameterInfo(@NotNull Type type, boolean skipped, int index, @Nullable StackValue remapValue, int declarationIndex) { this.type = type; this.isSkipped = skipped; this.remapValue = remapValue; @@ -52,7 +46,7 @@ class ParameterInfo { } public boolean isSkippedOrRemapped() { - return isSkipped || remapValue != null; + return isSkipped || isRemapped(); } public boolean isRemapped() { @@ -68,10 +62,6 @@ class ParameterInfo { return index; } - public boolean isSkipped() { - return isSkipped; - } - @NotNull public Type getType() { return type; @@ -82,12 +72,14 @@ class ParameterInfo { return lambda; } + @NotNull public ParameterInfo setLambda(@Nullable LambdaInfo lambda) { this.lambda = lambda; return this; } - public ParameterInfo setRemapValue(StackValue remapValue) { + @NotNull + public ParameterInfo setRemapValue(@Nullable StackValue remapValue) { this.remapValue = remapValue; return this; } @@ -96,13 +88,7 @@ class ParameterInfo { return isCaptured; } - public ParameterInfo setSkipped(boolean skipped) { - isSkipped = skipped; - return this; - } - public void setCaptured(boolean isCaptured) { this.isCaptured = isCaptured; } - } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/Parameters.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/Parameters.kt index 21aeea9c2da..c45874e7b54 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/Parameters.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/Parameters.kt @@ -45,7 +45,7 @@ internal class Parameters(val real: List, val captured: List, val captured: List { @@ -71,7 +68,7 @@ internal class Parameters(val real: List, val captured: List, realSize: Int): List { - return capturedParams.withIndex().map { it.value.newIndex(it.index+ realSize) } + return capturedParams.withIndex().map { it.value.newIndex(it.index + realSize) } } } } 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 976b4f371e2..fa212f283b0 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ParametersBuilder.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ParametersBuilder.kt @@ -18,13 +18,9 @@ package org.jetbrains.kotlin.codegen.inline import org.jetbrains.kotlin.codegen.StackValue import org.jetbrains.org.objectweb.asm.Type -import java.lang.Deprecated - -import java.util.ArrayList -import java.util.Collections - -internal class ParametersBuilder private constructor(){ +import java.util.* +internal class ParametersBuilder private constructor() { private val valueAndHiddenParams = arrayListOf() private val capturedParams = arrayListOf() private var valueParamStart = 0 @@ -40,38 +36,31 @@ internal class ParametersBuilder private constructor(){ return info } - fun addNextParameter(type: Type, skipped: Boolean, remapValue: StackValue?): ParameterInfo { - return addParameter(ParameterInfo(type, skipped, nextValueParameterIndex, remapValue, valueAndHiddenParams.size)) + fun addNextParameter(type: Type, skipped: Boolean): ParameterInfo { + return addParameter(ParameterInfo(type, skipped, nextValueParameterIndex, null, valueAndHiddenParams.size)) } fun addNextValueParameter(type: Type, skipped: Boolean, remapValue: StackValue?, parameterIndex: Int): ParameterInfo { - return addParameter(ParameterInfo(type, skipped, nextValueParameterIndex, remapValue, - if (parameterIndex == -1) valueAndHiddenParams.size else { parameterIndex + valueParamStart })) + return addParameter(ParameterInfo( + type, skipped, nextValueParameterIndex, remapValue, + if (parameterIndex == -1) valueAndHiddenParams.size else parameterIndex + valueParamStart + )) } - fun addCapturedParam( - original: CapturedParamInfo, - newFieldName: String): CapturedParamInfo { - val info = CapturedParamInfo(original.desc, newFieldName, original.isSkipped, nextCapturedIndex(), original.getIndex()) - info.setLambda(original.getLambda()) + fun addCapturedParam(original: CapturedParamInfo, newFieldName: String): CapturedParamInfo { + val info = CapturedParamInfo(original.desc, newFieldName, original.isSkipped, nextCapturedIndex(), original.index) + info.lambda = original.lambda return addCapturedParameter(info) } - private fun nextCapturedIndex(): Int { - return nextCaptured + private fun nextCapturedIndex(): Int = nextCaptured + + fun addCapturedParam(desc: CapturedParamDesc, newFieldName: String): CapturedParamInfo { + return addCapturedParameter(CapturedParamInfo(desc, newFieldName, false, nextCapturedIndex(), null)) } - fun addCapturedParam( - desc: CapturedParamDesc, - newFieldName: String): CapturedParamInfo { - val info = CapturedParamInfo(desc, newFieldName, false, nextCapturedIndex(), null) - return addCapturedParameter(info) - } - - fun addCapturedParamCopy( - copyFrom: CapturedParamInfo): CapturedParamInfo { - val info = copyFrom.newIndex(nextCapturedIndex()) - return addCapturedParameter(info) + fun addCapturedParamCopy(copyFrom: CapturedParamInfo): CapturedParamInfo { + return addCapturedParameter(copyFrom.newIndex(nextCapturedIndex())) } fun addCapturedParam( @@ -80,11 +69,13 @@ internal class ParametersBuilder private constructor(){ newFieldName: String, type: Type, skipped: Boolean, - original: ParameterInfo?): CapturedParamInfo { - val info = CapturedParamInfo(CapturedParamDesc.createDesc(containingLambda, fieldName, type), newFieldName, skipped, nextCapturedIndex(), - if (original != null) original.getIndex() else -1) + original: ParameterInfo? + ): CapturedParamInfo { + val info = CapturedParamInfo( + CapturedParamDesc(containingLambda, fieldName, type), newFieldName, skipped, nextCapturedIndex(), original?.index ?: -1 + ) if (original != null) { - info.setLambda(original.getLambda()) + info.lambda = original.lambda } return addCapturedParameter(info) } @@ -101,7 +92,7 @@ internal class ParametersBuilder private constructor(){ return info } - fun markValueParametesStart(){ + fun markValueParametersStart() { this.valueParamStart = valueAndHiddenParams.size } @@ -119,23 +110,24 @@ internal class ParametersBuilder private constructor(){ } companion object { - @JvmStatic fun newBuilder(): ParametersBuilder { return ParametersBuilder() } - @JvmOverloads @JvmStatic - fun initializeBuilderFrom(objectType: Type, descriptor: String, inlineLambda: LambdaInfo? = null, addThis: Boolean = true): ParametersBuilder { + @JvmOverloads + @JvmStatic + fun initializeBuilderFrom( + objectType: Type, descriptor: String, inlineLambda: LambdaInfo? = null, addThis: Boolean = true + ): ParametersBuilder { val builder = newBuilder() if (addThis) { //skipped this for inlined lambda cause it will be removed - builder.addThis(objectType, inlineLambda != null).setLambda(inlineLambda) + builder.addThis(objectType, inlineLambda != null).lambda = inlineLambda } - val types = Type.getArgumentTypes(descriptor) - for (type in types) { - builder.addNextParameter(type, false, null) + for (type in Type.getArgumentTypes(descriptor)) { + builder.addNextParameter(type, false) } return builder } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RegeneratedClassContext.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RegeneratedClassContext.java index 27b39044efb..af1e175643d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RegeneratedClassContext.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RegeneratedClassContext.java @@ -23,7 +23,7 @@ import org.jetbrains.kotlin.codegen.state.GenerationState; import java.util.Map; public class RegeneratedClassContext extends InliningContext { - private InlineCallSiteInfo callSiteInfo; + private final InlineCallSiteInfo callSiteInfo; public RegeneratedClassContext( @Nullable InliningContext parent, @@ -39,6 +39,8 @@ public class RegeneratedClassContext extends InliningContext { this.callSiteInfo = callSiteInfo; } + @NotNull + @Override public InlineCallSiteInfo getCallSiteInfo() { return callSiteInfo; } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RegeneratedLambdaFieldRemapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RegeneratedLambdaFieldRemapper.java index 23466f3c71b..cbc37154f5c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RegeneratedLambdaFieldRemapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RegeneratedLambdaFieldRemapper.java @@ -34,11 +34,11 @@ public class RegeneratedLambdaFieldRemapper extends FieldRemapper { private final boolean isConstructor; public RegeneratedLambdaFieldRemapper( - String oldOwnerType, - String newOwnerType, - Parameters parameters, - Map recapturedLambdas, - FieldRemapper remapper, + @NotNull String oldOwnerType, + @NotNull String newOwnerType, + @NotNull Parameters parameters, + @NotNull Map recapturedLambdas, + @NotNull FieldRemapper remapper, boolean isConstructor ) { super(oldOwnerType, remapper, parameters); @@ -50,12 +50,12 @@ public class RegeneratedLambdaFieldRemapper extends FieldRemapper { } @Override - public boolean canProcess(@NotNull String fieldOwner, String fieldName, boolean isFolding) { + public boolean canProcess(@NotNull String fieldOwner, @NotNull String fieldName, boolean isFolding) { return super.canProcess(fieldOwner, fieldName, isFolding) || isRecapturedLambdaType(fieldOwner, isFolding); } - private boolean isRecapturedLambdaType(String owner, boolean isFolding) { - return recapturedLambdas.containsKey(owner) && (isFolding || false == parent instanceof InlinedLambdaRemapper); + private boolean isRecapturedLambdaType(@NotNull String owner, boolean isFolding) { + return recapturedLambdas.containsKey(owner) && (isFolding || !(parent instanceof InlinedLambdaRemapper)); } @Nullable @@ -64,9 +64,8 @@ public class RegeneratedLambdaFieldRemapper extends FieldRemapper { boolean searchInParent = !canProcess(fieldInsnNode.owner, fieldInsnNode.name, false); if (searchInParent) { return parent.findField(fieldInsnNode); - } else { - return findFieldInMyCaptured(fieldInsnNode); } + return findFieldInMyCaptured(fieldInsnNode); } @Override @@ -75,10 +74,11 @@ public class RegeneratedLambdaFieldRemapper extends FieldRemapper { } @Nullable - public CapturedParamInfo findFieldInMyCaptured(@NotNull FieldInsnNode fieldInsnNode) { + private CapturedParamInfo findFieldInMyCaptured(@NotNull FieldInsnNode fieldInsnNode) { return super.findField(fieldInsnNode, parameters.getCaptured()); } + @NotNull @Override public String getNewLambdaInternalName() { return newOwnerType; @@ -98,18 +98,23 @@ public class RegeneratedLambdaFieldRemapper extends FieldRemapper { boolean searchInParent = false; if (field == null) { - field = findFieldInMyCaptured(new FieldInsnNode(Opcodes.GETSTATIC, oldOwnerType, "this$0", Type.getObjectType(parent.getLambdaInternalName()).getDescriptor())); + field = findFieldInMyCaptured(new FieldInsnNode( + Opcodes.GETSTATIC, oldOwnerType, InlineCodegenUtil.THIS$0, + Type.getObjectType(parent.getLambdaInternalName()).getDescriptor() + )); searchInParent = true; if (field == null) { throw new IllegalStateException("Couldn't find captured this " + getLambdaInternalName() + " for " + node.name); } } - StackValue result = StackValue.field(field.isSkipped ? - Type.getObjectType(parent.parent.getNewLambdaInternalName()) : field.getType(), - Type.getObjectType(getNewLambdaInternalName()), /*TODO owner type*/ - field.getNewFieldName(), false, - prefix == null ? StackValue.LOCAL_0 : prefix); + StackValue result = StackValue.field( + field.isSkipped ? + Type.getObjectType(parent.parent.getNewLambdaInternalName()) : field.getType(), + Type.getObjectType(getNewLambdaInternalName()), /*TODO owner type*/ + field.getNewFieldName(), false, + prefix == null ? StackValue.LOCAL_0 : prefix + ); return searchInParent ? parent.getFieldForInline(node, result) : 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 a623c4e93fa..82092757b6b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt @@ -39,7 +39,8 @@ class ReificationArgument( ReificationArgument( replacement.parameterName, this.nullable || (replacement.nullable && this.arrayDepth == 0), - this.arrayDepth + replacement.arrayDepth) + this.arrayDepth + replacement.arrayDepth + ) fun reify(replacementAsmType: Type, kotlinType: KotlinType) = Pair(Type.getType("[".repeat(arrayDepth) + replacementAsmType), kotlinType.arrayOf(arrayDepth).makeNullableIfNeeded(nullable)) @@ -57,7 +58,6 @@ class ReificationArgument( } class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?) { - enum class OperationKind { NEW_ARRAY, AS, SAFE_AS, IS, JAVA_CLASS; @@ -65,8 +65,8 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?) } companion object { - @JvmField val REIFIED_OPERATION_MARKER_METHOD_NAME = "reifiedOperationMarker" - @JvmField val NEED_CLASS_REIFICATION_MARKER_METHOD_NAME = "needClassReification" + const val REIFIED_OPERATION_MARKER_METHOD_NAME = "reifiedOperationMarker" + const val NEED_CLASS_REIFICATION_MARKER_METHOD_NAME = "needClassReification" private fun isOperationReifiedMarker(insn: AbstractInsnNode) = isReifiedMarker(insn) { it == REIFIED_OPERATION_MARKER_METHOD_NAME } @@ -76,10 +76,12 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?) return insn.owner == IntrinsicMethods.INTRINSICS_CLASS_NAME && namePredicate(insn.name) } - @JvmStatic fun isNeedClassReificationMarker(insn: AbstractInsnNode): Boolean = + @JvmStatic + fun isNeedClassReificationMarker(insn: AbstractInsnNode): Boolean = isReifiedMarker(insn) { s -> s == NEED_CLASS_REIFICATION_MARKER_METHOD_NAME } - @JvmStatic fun putNeedClassReificationMarker(v: MethodVisitor) { + @JvmStatic + fun putNeedClassReificationMarker(v: MethodVisitor) { v.visitMethodInsn( Opcodes.INVOKESTATIC, IntrinsicMethods.INTRINSICS_CLASS_NAME, NEED_CLASS_REIFICATION_MARKER_METHOD_NAME, @@ -102,7 +104,7 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?) val instructions = node.instructions maxStackSize = 0 - var result = ReifiedTypeParametersUsages() + val result = ReifiedTypeParametersUsages() for (insn in instructions.toArray()) { if (isOperationReifiedMarker(insn)) { val newName: String? = processReifyMarker(insn as MethodInsnNode, instructions) @@ -144,7 +146,8 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?) } return null - } else { + } + else { val newReificationArgument = reificationArgument.combine(mapping.reificationArgument!!) instructions.set(insn.previous!!, LdcInsnNode(newReificationArgument.asString())) return mapping.reificationArgument.parameterName @@ -154,43 +157,45 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?) private fun processNewArray(insn: MethodInsnNode, parameter: Type) = processNextTypeInsn(insn, parameter, Opcodes.ANEWARRAY) - private fun processAs(insn: MethodInsnNode, - instructions: InsnList, - kotlinType: KotlinType, - asmType: Type, - safe: Boolean) = - rewriteNextTypeInsn(insn, Opcodes.CHECKCAST) { stubCheckcast: AbstractInsnNode -> - if (stubCheckcast !is TypeInsnNode) return false + private fun processAs( + insn: MethodInsnNode, + instructions: InsnList, + kotlinType: KotlinType, + asmType: Type, + safe: Boolean + ) = rewriteNextTypeInsn(insn, Opcodes.CHECKCAST) { stubCheckcast: AbstractInsnNode -> + if (stubCheckcast !is TypeInsnNode) return false - val newMethodNode = MethodNode(InlineCodegenUtil.API) - generateAsCast(InstructionAdapter(newMethodNode), kotlinType, asmType, safe) + val newMethodNode = MethodNode(InlineCodegenUtil.API) + generateAsCast(InstructionAdapter(newMethodNode), kotlinType, asmType, safe) - instructions.insert(insn, newMethodNode.instructions) - instructions.remove(stubCheckcast) + instructions.insert(insn, newMethodNode.instructions) + instructions.remove(stubCheckcast) - // TODO: refine max stack calculation (it's not always as big as +4) - maxStackSize = Math.max(maxStackSize, 4) + // TODO: refine max stack calculation (it's not always as big as +4) + maxStackSize = Math.max(maxStackSize, 4) - return true - } + return true + } - private fun processIs(insn: MethodInsnNode, - instructions: InsnList, - kotlinType: KotlinType, - asmType: Type) = - rewriteNextTypeInsn(insn, Opcodes.INSTANCEOF) { stubInstanceOf: AbstractInsnNode -> - if (stubInstanceOf !is TypeInsnNode) return false + private fun processIs( + insn: MethodInsnNode, + instructions: InsnList, + kotlinType: KotlinType, + asmType: Type + ) = rewriteNextTypeInsn(insn, Opcodes.INSTANCEOF) { stubInstanceOf: AbstractInsnNode -> + if (stubInstanceOf !is TypeInsnNode) return false - val newMethodNode = MethodNode(InlineCodegenUtil.API) - generateIsCheck(InstructionAdapter(newMethodNode), kotlinType, asmType) + val newMethodNode = MethodNode(InlineCodegenUtil.API) + generateIsCheck(InstructionAdapter(newMethodNode), kotlinType, asmType) - instructions.insert(insn, newMethodNode.instructions) - instructions.remove(stubInstanceOf) + instructions.insert(insn, newMethodNode.instructions) + instructions.remove(stubInstanceOf) - // TODO: refine max stack calculation (it's not always as big as +2) - maxStackSize = Math.max(maxStackSize, 2) - return true - } + // TODO: refine max stack calculation (it's not always as big as +2) + maxStackSize = Math.max(maxStackSize, 2) + return true + } inline private fun rewriteNextTypeInsn( marker: MethodInsnNode, @@ -214,7 +219,6 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?) next.cst = parameter return true } - } private val MethodInsnNode.reificationArgument: ReificationArgument? @@ -242,16 +246,18 @@ 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) + mappingsByName[name] = TypeParameterMapping( + name, type, asmType, reificationArgument = null, signature = signature, isReified = isReified + ) } fun addParameterMappingForFurtherReification(name: String, type: KotlinType, reificationArgument: ReificationArgument, isReified: Boolean) { - mappingsByName[name] = TypeParameterMapping(name, type, asmType = null, reificationArgument = reificationArgument, signature = null, isReified = isReified) + mappingsByName[name] = TypeParameterMapping( + name, type, asmType = null, reificationArgument = reificationArgument, signature = null, isReified = isReified + ) } - operator fun get(name: String): TypeParameterMapping? { - return mappingsByName[name] - } + operator fun get(name: String): TypeParameterMapping? = mappingsByName[name] fun hasReifiedParameters() = mappingsByName.values.any { it.isReified } @@ -261,7 +267,8 @@ class TypeParameterMappings() { } class TypeParameterMapping( - val name: String, val type: KotlinType, + val name: String, + val type: KotlinType, val asmType: Type?, val reificationArgument: ReificationArgument?, val signature: String?, diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RemapVisitor.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RemapVisitor.java index e439471805e..848ed23d999 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RemapVisitor.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RemapVisitor.java @@ -28,14 +28,14 @@ public class RemapVisitor extends MethodBodyVisitor { private final FieldRemapper nodeRemapper; private final InstructionAdapter instructionAdapter; - protected RemapVisitor( - MethodVisitor mv, - LocalVarRemapper localVarRemapper, - FieldRemapper nodeRemapper + public RemapVisitor( + @NotNull MethodVisitor mv, + @NotNull LocalVarRemapper remapper, + @NotNull FieldRemapper nodeRemapper ) { super(mv); this.instructionAdapter = new InstructionAdapter(mv); - this.remapper = localVarRemapper; + this.remapper = remapper; this.nodeRemapper = nodeRemapper; } @@ -58,19 +58,13 @@ public class RemapVisitor extends MethodBodyVisitor { @Override public void visitFieldInsn(int opcode, @NotNull String owner, @NotNull String name, @NotNull String desc) { - if (name.startsWith("$$$")) { - if (nodeRemapper instanceof RegeneratedLambdaFieldRemapper || nodeRemapper.isRoot()) { - FieldInsnNode fin = new FieldInsnNode(opcode, owner, name, desc); - StackValue inline = nodeRemapper.getFieldForInline(fin, null); - assert inline != null : "Captured field should have not null stackValue " + fin; - inline.put(inline.type, this); - } - else { - super.visitFieldInsn(opcode, owner, name, desc); - } - } - else { - super.visitFieldInsn(opcode, owner, name, desc); + if (name.startsWith("$$$") && (nodeRemapper instanceof RegeneratedLambdaFieldRemapper || nodeRemapper.isRoot())) { + FieldInsnNode fin = new FieldInsnNode(opcode, owner, name, desc); + StackValue inline = nodeRemapper.getFieldForInline(fin, null); + assert inline != null : "Captured field should have not null stackValue " + fin; + inline.put(inline.type, this); + return; } + super.visitFieldInsn(opcode, owner, name, desc); } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RootInliningContext.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RootInliningContext.java index 194a787ee4e..31f71b3f54e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RootInliningContext.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RootInliningContext.java @@ -25,7 +25,6 @@ import org.jetbrains.kotlin.psi.KtElement; import java.util.Map; public class RootInliningContext extends InliningContext { - public final CodegenContext startContext; private final InlineCallSiteInfo inlineCallSiteInfo; public final TypeParameterMappings typeParameterMappings; public final KtElement callElement; @@ -34,7 +33,6 @@ public class RootInliningContext extends InliningContext { @NotNull Map map, @NotNull GenerationState state, @NotNull NameGenerator nameGenerator, - @NotNull CodegenContext startContext, @NotNull KtElement callElement, @NotNull InlineCallSiteInfo classNameToInline, @NotNull ReifiedTypeInliner inliner, @@ -42,11 +40,11 @@ public class RootInliningContext extends InliningContext { ) { super(null, map, state, nameGenerator, TypeRemapper.createRoot(typeParameterMappings), inliner, false, false); this.callElement = callElement; - this.startContext = startContext; this.inlineCallSiteInfo = classNameToInline; this.typeParameterMappings = typeParameterMappings; } + @NotNull @Override public InlineCallSiteInfo getCallSiteInfo() { return inlineCallSiteInfo; 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 cfea1fb6c99..f9b1fd2e5b5 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAP.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAP.kt @@ -55,7 +55,9 @@ class SMAPBuilder( val combinedMapping = FileMapping(source, path) realMappings.forEach { fileMapping -> fileMapping.lineMappings.filter { it.callSiteMarker != null }.forEach { rangeMapping -> - combinedMapping.addRangeMapping(RangeMapping(rangeMapping.callSiteMarker!!.lineNumber, rangeMapping.dest, rangeMapping.range)) + combinedMapping.addRangeMapping(RangeMapping( + rangeMapping.callSiteMarker!!.lineNumber, rangeMapping.dest, rangeMapping.range + )) } } @@ -95,9 +97,11 @@ open class NestedSourceMapper( if (mappedLineNumber > 0) { return mappedLineNumber - } else { - val rangeForMapping = (if (lastVisitedRange?.contains(lineNumber) ?: false) lastVisitedRange!! else findMappingIfExists(lineNumber)) - ?: error("Can't find range to map line $lineNumber in ${sourceInfo.source}:${sourceInfo.pathOrCleanFQN}") + } + else { + val rangeForMapping = + (if (lastVisitedRange?.contains(lineNumber) ?: false) lastVisitedRange!! else findMappingIfExists(lineNumber)) + ?: 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) { @@ -132,9 +136,7 @@ open class InlineLambdaSourceMapper( //don't remap origin lambda line numbers return lineNumber } - else { - return super.mapLineNumber(lineNumber) - } + return super.mapLineNumber(lineNumber) } } @@ -152,7 +154,6 @@ interface SourceMapper { } fun endMapping() { - } companion object { @@ -179,11 +180,8 @@ object IdenticalSourceMapper : SourceMapper { class CallSiteMarker(val lineNumber: Int) open class DefaultSourceMapper(val sourceInfo: SourceInfo) : SourceMapper { - private var maxUsedValue: Int = sourceInfo.linesInFile - private var lastMappedWithChanges: RawFileMapping? = null - private var fileMappings: LinkedHashMap = linkedMapOf() protected val origin: RawFileMapping @@ -197,7 +195,6 @@ open class DefaultSourceMapper(val sourceInfo: SourceInfo) : SourceMapper { override val resultMappings: List get() = fileMappings.values.map { it.toFileMapping() } - init { val name = sourceInfo.source val path = sourceInfo.pathOrCleanFQN @@ -206,8 +203,8 @@ open class DefaultSourceMapper(val sourceInfo: SourceInfo) : SourceMapper { fileMappings.put(createKey(name, path), origin) } - constructor(sourceInfo: SourceInfo, fileMappings: List): this(sourceInfo) { - fileMappings.asSequence().drop(1) + constructor(sourceInfo: SourceInfo, fileMappings: List) : this(sourceInfo) { + fileMappings.asSequence().drop(1) //default one mapped through sourceInfo .forEach { fileMapping -> val newFileMapping = getOrRegisterNewSource(fileMapping.name, fileMapping.path) @@ -227,7 +224,7 @@ open class DefaultSourceMapper(val sourceInfo: SourceInfo) : SourceMapper { override fun mapLineNumber(lineNumber: Int): Int { if (lineNumber < 0) { //no source information, so just skip this linenumber - return - 1 + return -1 } //TODO maybe add assertion that linenumber contained in fileMappings return lineNumber @@ -238,8 +235,7 @@ open class DefaultSourceMapper(val sourceInfo: SourceInfo) : SourceMapper { //no source information, so just skip this linenumber return -1 } - val mappedLineIndex = createMapping(getOrRegisterNewSource(sourceName, sourcePath), source) - return mappedLineIndex + return createMapping(getOrRegisterNewSource(sourceName, sourcePath), source) } private fun createMapping(fileMapping: RawFileMapping, lineNumber: Int): Int { @@ -263,6 +259,7 @@ class SMAP(val fileMappings: List) { val intervals = fileMappings.flatMap { it.lineMappings }.sortedWith(RangeMapping.Comparator) val sourceInfo: SourceInfo + init { val defaultMapping = default.lineMappings.first() sourceInfo = SourceInfo(default.name, default.path, defaultMapping.source + defaultMapping.range - 1) @@ -349,7 +346,7 @@ data class RangeMapping(val source: Int, val dest: Int, var range: Int = 1, var get() = dest + range - 1 operator fun contains(destLine: Int): Boolean { - return if (skip) true else dest <= destLine && destLine < dest + range + return skip || (dest <= destLine && destLine < dest + range) } fun mapDestToSource(destLine: Int): Int { @@ -365,12 +362,7 @@ data class RangeMapping(val source: Int, val dest: Int, var range: Int = 1, var if (o1 == o2) return 0 val res = o1.dest - o2.dest - if (res == 0) { - return o1.range - o2.range - } - else { - return res - } + return if (res == 0) o1.range - o2.range else res } } 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 2d2c7168fa3..fd8f4f0b0d6 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPParser.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPParser.kt @@ -64,7 +64,7 @@ object SMAPParser { /*only simple mapping now*/ val targetSplit = lineMapping.indexOf(':') val originalPart = lineMapping.substring(0, targetSplit) - var rangeSeparator = originalPart.indexOf(',').let { if (it < 0) targetSplit else it } + val rangeSeparator = originalPart.indexOf(',').let { if (it < 0) targetSplit else it } val fileSeparator = lineMapping.indexOf('#') val originalIndex = originalPart.substring(0, fileSeparator).toInt() 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 9c39f481f86..b2d27a7340c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TransformationInfo.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TransformationInfo.kt @@ -17,10 +17,8 @@ package org.jetbrains.kotlin.codegen.inline import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode -import java.util.* interface TransformationInfo { - val oldClassName: String val newClassName: String @@ -29,10 +27,7 @@ interface TransformationInfo { fun canRemoveAfterTransformation(): Boolean - fun createTransformer( - inliningContext: InliningContext, - sameModule: Boolean - ): ObjectTransformer<*> + fun createTransformer(inliningContext: InliningContext, sameModule: Boolean): ObjectTransformer<*> } class WhenMappingTransformationInfo( @@ -41,22 +36,17 @@ class WhenMappingTransformationInfo( val alreadyRegenerated: Boolean, val fieldNode: FieldInsnNode ) : TransformationInfo { - override val newClassName by lazy { - nameGenerator.genWhenClassNamePrefix() + TRANSFORMED_WHEN_MAPPING_MARKER + oldClassName.substringAfterLast("/").substringAfterLast(TRANSFORMED_WHEN_MAPPING_MARKER) + nameGenerator.genWhenClassNamePrefix() + TRANSFORMED_WHEN_MAPPING_MARKER + + oldClassName.substringAfterLast("/").substringAfterLast(TRANSFORMED_WHEN_MAPPING_MARKER) } - override fun shouldRegenerate(sameModule: Boolean): Boolean { - return !alreadyRegenerated && !sameModule - } + override fun shouldRegenerate(sameModule: Boolean): Boolean = !alreadyRegenerated && !sameModule - override fun canRemoveAfterTransformation(): Boolean { - return true - } + override fun canRemoveAfterTransformation(): Boolean = true - override fun createTransformer(inliningContext: InliningContext, sameModule: Boolean): ObjectTransformer<*> { - return WhenMappingTransformer(this, inliningContext) - } + override fun createTransformer(inliningContext: InliningContext, sameModule: Boolean): ObjectTransformer<*> = + WhenMappingTransformer(this, inliningContext) companion object { const val TRANSFORMED_WHEN_MAPPING_MARKER = "\$wm$" @@ -71,8 +61,8 @@ class AnonymousObjectTransformationInfo internal constructor( private val alreadyRegenerated: Boolean, val constructorDesc: String?, private val isStaticOrigin: Boolean, - nameGenerator: NameGenerator) : TransformationInfo { - + nameGenerator: NameGenerator +) : TransformationInfo { override val newClassName: String by lazy { nameGenerator.genLambdaClassName() } @@ -89,14 +79,10 @@ class AnonymousObjectTransformationInfo internal constructor( alreadyRegenerated: Boolean, isStaticOrigin: Boolean, nameGenerator: NameGenerator - ) : this( - ownerInternalName, needReification, - HashMap(), false, alreadyRegenerated, null, isStaticOrigin, nameGenerator) { - } + ) : this(ownerInternalName, needReification, hashMapOf(), false, alreadyRegenerated, null, isStaticOrigin, nameGenerator) - override fun shouldRegenerate(sameModule: Boolean): Boolean { - return !alreadyRegenerated && (!lambdasToInline.isEmpty() || !sameModule || capturedOuterRegenerated || needReification) - } + override fun shouldRegenerate(sameModule: Boolean): Boolean = + !alreadyRegenerated && (!lambdasToInline.isEmpty() || !sameModule || capturedOuterRegenerated || needReification) override fun canRemoveAfterTransformation(): Boolean { // Note: It is unsafe to remove anonymous class that is referenced by GETSTATIC within lambda @@ -104,7 +90,6 @@ class AnonymousObjectTransformationInfo internal constructor( return !isStaticOrigin } - override fun createTransformer(inliningContext: InliningContext, sameModule: Boolean): ObjectTransformer<*> { - return AnonymousObjectTransformer(this, inliningContext, sameModule) - } + override fun createTransformer(inliningContext: InliningContext, sameModule: Boolean): ObjectTransformer<*> = + AnonymousObjectTransformer(this, inliningContext, sameModule) } 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 4373f15e0f7..0d7dace4642 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TryBlockClustering.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TryBlockClustering.kt @@ -16,9 +16,9 @@ package org.jetbrains.kotlin.codegen.inline -import org.jetbrains.org.objectweb.asm.tree.TryCatchBlockNode +import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.firstLabelInChain import org.jetbrains.org.objectweb.asm.tree.LabelNode -import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.* +import org.jetbrains.org.objectweb.asm.tree.TryCatchBlockNode enum class TryCatchPosition { START, @@ -26,9 +26,9 @@ enum class TryCatchPosition { INNER } -class SplitPair(val patchedPart: T, val newPart: T) +class SplitPair(val patchedPart: T, val newPart: T) -class SimpleInterval(override val startLabel: LabelNode, override val endLabel: LabelNode ) : Interval +class SimpleInterval(override val startLabel: LabelNode, override val endLabel: LabelNode) : Interval interface Interval { val startLabel: LabelNode @@ -36,20 +36,21 @@ interface Interval { /*note that some intervals are mutable */ fun isEmpty(): Boolean = startLabel == endLabel - } -interface SplittableInterval : Interval { +interface SplittableInterval : Interval { fun split(splitBy: Interval, keepStart: Boolean): SplitPair } - interface IntervalWithHandler : Interval { val handler: LabelNode val type: String? } -class TryCatchBlockNodeInfo(val node: TryCatchBlockNode, val onlyCopyNotProcess: Boolean) : IntervalWithHandler, SplittableInterval { +class TryCatchBlockNodeInfo( + val node: TryCatchBlockNode, + val onlyCopyNotProcess: Boolean +) : IntervalWithHandler, SplittableInterval { override val startLabel: LabelNode get() = node.start override val endLabel: LabelNode @@ -77,16 +78,16 @@ class TryCatchBlockNodeInfo(val node: TryCatchBlockNode, val onlyCopyNotProcess: } } -class TryCatchBlockNodePosition(val nodeInfo: TryCatchBlockNodeInfo, var position: TryCatchPosition) : IntervalWithHandler by nodeInfo { - -} +class TryCatchBlockNodePosition( + val nodeInfo: TryCatchBlockNodeInfo, + var position: TryCatchPosition +) : IntervalWithHandler by nodeInfo class TryBlockCluster(val blocks: MutableList) { val defaultHandler: T? get() = blocks.firstOrNull() { it.type == null } } - fun doClustering(blocks: List): List> { data class TryBlockInterval(val startLabel: LabelNode, val endLabel: LabelNode) 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 35f4160b670..9fa246c82f4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TypeRemapper.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TypeRemapper.kt @@ -16,16 +16,17 @@ package org.jetbrains.kotlin.codegen.inline -import java.util.HashMap +import java.util.* -class TypeParameter(val oldName: String, val newName: String?, val isReified: Boolean, val signature: String?) +class TypeParameter(val oldName: String, val newName: String?, val isReified: Boolean, val signature: String?) //typeMapping data could be changed outside through method processing -class TypeRemapper private constructor(private val typeMapping: MutableMap, val parent: TypeRemapper?, val isInlineLambda: Boolean = false) { - +class TypeRemapper private constructor( + private val typeMapping: MutableMap, + val parent: TypeRemapper?, + val isInlineLambda: Boolean = false +) { private var additionalMappings: MutableMap = hashMapOf() - - private val typeParametersMapping: MutableMap = hashMapOf() fun addMapping(type: String, newType: String) { @@ -37,11 +38,11 @@ class TypeRemapper private constructor(private val typeMapping: MutableMap(), null) - formalTypeParameters?.forEach { - typeRemapper.registerTypeParameter(it) + return TypeRemapper(HashMap(), null).apply { + formalTypeParameters?.forEach { + registerTypeParameter(it) + } } - return typeRemapper } @JvmStatic @@ -82,9 +84,9 @@ class TypeRemapper private constructor(private val typeMapping: MutableMap): MutableMap { - val map = HashMap(remapper.typeMapping) - map += additionalTypeMappings - return map + return HashMap(remapper.typeMapping).apply { + this += additionalTypeMappings + } } } }