diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/CallGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/CallGenerator.kt index 3024bbb0d27..59bcce2277e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/CallGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/CallGenerator.kt @@ -38,11 +38,6 @@ abstract class CallGenerator { } } - override fun genCallWithoutAssertions( - callableMethod: CallableMethod, codegen: ExpressionCodegen) { - callableMethod.genInvokeInstruction(codegen.v) - } - override fun afterParameterPut( type: Type, stackValue: StackValue?, @@ -107,8 +102,6 @@ abstract class CallGenerator { abstract fun genCallInner(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen) - abstract fun genCallWithoutAssertions(callableMethod: CallableMethod, codegen: ExpressionCodegen) - abstract fun afterParameterPut( type: Type, stackValue: StackValue?, diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index dbc558016be..e2c671d6166 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -2492,7 +2492,12 @@ public class ExpressionCodegen extends KtVisitor impleme if (!isInline) return defaultCallGenerator; FunctionDescriptor original = DescriptorUtils.unwrapFakeOverride((FunctionDescriptor) descriptor.getOriginal()); - return new InlineCodegen(this, state, original, callElement, typeParameterMappings, isDefaultCompilation); + if (isDefaultCompilation) { + return new InlineCodegenForDefaultBody(original, this, state); + } + else { + return new InlineCodegen(this, state, original, callElement, typeParameterMappings); + } } @NotNull diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index cfb44e11331..4ea91e8f02e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -756,7 +756,7 @@ public class FunctionCodegen { CallableMethod method = state.getTypeMapper().mapToCallableMethod(functionDescriptor, false); - generator.genCallWithoutAssertions(method, codegen); + generator.genCall(method, null, false, codegen); iv.areturn(signature.getReturnType()); } 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 69fd32faf55..16bf5546e29 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java @@ -86,7 +86,6 @@ public class InlineCodegen extends CallGenerator { private final ReifiedTypeInliner reifiedTypeInliner; @Nullable private final TypeParameterMappings typeParameterMappings; - private final boolean isDefaultMethodCompilation; private LambdaInfo activeLambda; @@ -97,12 +96,10 @@ public class InlineCodegen extends CallGenerator { @NotNull GenerationState state, @NotNull FunctionDescriptor function, @NotNull KtElement callElement, - @Nullable TypeParameterMappings typeParameterMappings, - boolean isDefaultMethodCompilation + @Nullable TypeParameterMappings typeParameterMappings ) { assert InlineUtil.isInline(function) || InlineUtil.isArrayConstructorWithLambda(function) : "InlineCodegen can inline only inline functions and array constructors: " + function; - this.isDefaultMethodCompilation = isDefaultMethodCompilation; this.state = state; this.typeMapper = state.getTypeMapper(); this.codegen = codegen; @@ -129,15 +126,10 @@ public class InlineCodegen extends CallGenerator { sourceMapper = codegen.getParentCodegen().getOrCreateSourceMapper(); if (!(functionDescriptor instanceof FictitiousArrayConstructor)) { - reportIncrementalInfo(functionDescriptor, codegen.getContext().getFunctionDescriptor().getOriginal()); + reportIncrementalInfo(functionDescriptor, codegen.getContext().getFunctionDescriptor().getOriginal(), jvmSignature, state); } } - @Override - public void genCallWithoutAssertions(@NotNull CallableMethod callableMethod, @NotNull ExpressionCodegen codegen) { - genCall(callableMethod, null, false, codegen); - } - @Override public void genCallInner(@NotNull Callable callableMethod, @Nullable ResolvedCall resolvedCall, boolean callDefault, @NotNull ExpressionCodegen codegen) { SMAPAndMethodNode nodeAndSmap = null; @@ -148,11 +140,7 @@ public class InlineCodegen extends CallGenerator { try { nodeAndSmap = createMethodNode(callDefault); - if (isDefaultMethodCompilation) { - nodeAndSmap.getNode().accept(new MethodBodyVisitor(codegen.v)); - } else { - endCall(inlineCall(nodeAndSmap)); - } + endCall(inlineCall(nodeAndSmap)); } catch (CompilationException e) { throw e; @@ -190,6 +178,18 @@ public class InlineCodegen extends CallGenerator { @NotNull private SMAPAndMethodNode createMethodNode(boolean callDefault) throws IOException { + return createMethodNode(functionDescriptor, jvmSignature, codegen, context, callDefault, state); + } + + @NotNull + static SMAPAndMethodNode createMethodNode( + @NotNull FunctionDescriptor functionDescriptor, + @NotNull JvmMethodSignature jvmSignature, + @NotNull ExpressionCodegen codegen, + @NotNull CodegenContext context, + boolean callDefault, + @NotNull GenerationState state) throws IOException { + JetTypeMapper typeMapper = state.getTypeMapper(); Method asmMethod = callDefault ? typeMapper.mapDefaultMethod(functionDescriptor, context.getContextKind()) : jvmSignature.getAsmMethod(); @@ -257,7 +257,7 @@ public class InlineCodegen extends CallGenerator { smap = createSMAPWithDefaultMapping(inliningFunction, parentCodegen.getOrCreateSourceMapper().getResultMappings()); } else { - smap = generateMethodBody(maxCalcAdapter, functionDescriptor, methodContext, inliningFunction, jvmSignature, false); + smap = generateMethodBody(maxCalcAdapter, functionDescriptor, methodContext, inliningFunction, jvmSignature, false, codegen, state); } nodeAndSMAP = new SMAPAndMethodNode(node, smap); @@ -355,24 +355,27 @@ public class InlineCodegen extends CallGenerator { MethodVisitor adapter = InlineCodegenUtil.wrapWithMaxLocalCalc(methodNode); - SMAP smap = generateMethodBody(adapter, descriptor, context, declaration, jvmMethodSignature, true); + SMAP smap = generateMethodBody(adapter, descriptor, context, declaration, jvmMethodSignature, true, codegen, state); adapter.visitMaxs(-1, -1); return new SMAPAndMethodNode(methodNode, smap); } - private SMAP generateMethodBody( + private static SMAP generateMethodBody( @NotNull MethodVisitor adapter, @NotNull FunctionDescriptor descriptor, @NotNull MethodContext context, @NotNull KtExpression expression, @NotNull JvmMethodSignature jvmMethodSignature, - boolean isLambda + boolean isLambda, + @NotNull ExpressionCodegen codegen, + @NotNull GenerationState state + ) { FakeMemberCodegen parentCodegen = new FakeMemberCodegen(codegen.getParentCodegen(), expression, (FieldOwnerContext) context.getParentContext(), isLambda ? codegen.getParentCodegen().getClassName() - : typeMapper.mapImplementationOwner(descriptor).getInternalName()); + : state.getTypeMapper().mapImplementationOwner(descriptor).getInternalName()); FunctionGenerationStrategy strategy = expression instanceof KtCallableReferenceExpression ? @@ -682,11 +685,6 @@ public class InlineCodegen extends CallGenerator { @NotNull Type parameterType, @NotNull StackValue value ) { - if (isDefaultMethodCompilation) { - //original method would be inlined directly into default impl body without any inline magic - //so we no need to load variables on stack to further method call - return; - } putValueIfNeeded(parameterType, value, -1); } @@ -803,9 +801,11 @@ public class InlineCodegen extends CallGenerator { return new NestedSourceMapper(sourceMapper, nodeAndSmap.getRanges(), nodeAndSmap.getClassSMAP().getSourceInfo()); } - private void reportIncrementalInfo( + static void reportIncrementalInfo( @NotNull FunctionDescriptor sourceDescriptor, - @NotNull FunctionDescriptor targetDescriptor + @NotNull FunctionDescriptor targetDescriptor, + @NotNull JvmMethodSignature jvmSignature, + @NotNull GenerationState state ) { IncrementalCompilationComponents incrementalCompilationComponents = state.getIncrementalCompilationComponents(); TargetId targetId = state.getTargetId(); @@ -813,7 +813,7 @@ public class InlineCodegen extends CallGenerator { if (incrementalCompilationComponents == null || targetId == null) return; IncrementalCache incrementalCache = incrementalCompilationComponents.getIncrementalCache(targetId); - String classFilePath = InlineCodegenUtilsKt.getClassFilePath(sourceDescriptor, typeMapper, incrementalCache); + String classFilePath = InlineCodegenUtilsKt.getClassFilePath(sourceDescriptor, state.getTypeMapper(), incrementalCache); String sourceFilePath = InlineCodegenUtilsKt.getSourceFilePath(targetDescriptor); incrementalCache.registerInline(classFilePath, jvmSignature.toString(), sourceFilePath); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt new file mode 100644 index 00000000000..c64361e1d05 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt @@ -0,0 +1,87 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.codegen.inline + +import org.jetbrains.kotlin.codegen.* +import org.jetbrains.kotlin.codegen.state.GenerationState +import org.jetbrains.kotlin.descriptors.ConstructorDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.inline.InlineUtil +import org.jetbrains.org.objectweb.asm.Type + +class InlineCodegenForDefaultBody( + function: FunctionDescriptor, + codegen: ExpressionCodegen, + val state: GenerationState +) : CallGenerator() { + + private val functionDescriptor = + if (InlineUtil.isArrayConstructorWithLambda(function)) + FictitiousArrayConstructor.create(function as ConstructorDescriptor) + else + function.original + + + private val context = InlineCodegen.getContext( + functionDescriptor, state, + DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)?.containingFile as? KtFile + ) + + private val jvmSignature = state.typeMapper.mapSignature(functionDescriptor, context.contextKind) + + init { + assert(InlineUtil.isInline(function)) { + "InlineCodegen can inline only inline functions and array constructors: " + function + } + InlineCodegen.reportIncrementalInfo(functionDescriptor, codegen.context.functionDescriptor.original, jvmSignature, state) + } + + override fun genCallInner(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen) { + val nodeAndSmap = InlineCodegen.createMethodNode(functionDescriptor, jvmSignature, codegen, context, callDefault, state) + nodeAndSmap.node.accept(MethodBodyVisitor(codegen.v)) + } + + override fun afterParameterPut(type: Type, stackValue: StackValue?, parameterIndex: Int) { + throw UnsupportedOperationException("Shouldn't be called") + } + + override fun genValueAndPut(valueParameterDescriptor: ValueParameterDescriptor, argumentExpression: KtExpression, parameterType: Type, parameterIndex: Int) { + throw UnsupportedOperationException("Shouldn't be called") + } + + override fun putValueIfNeeded(parameterType: Type, value: StackValue) { + //original method would be inlined directly into default impl body without any inline magic + //so we no need to load variables on stack to further method call + } + + override fun putCapturedValueOnStack(stackValue: StackValue, valueType: Type, paramIndex: Int) { + throw UnsupportedOperationException("Shouldn't be called") + } + + override fun putHiddenParams() { + throw UnsupportedOperationException("Shouldn't be called") + } + + override fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: List, valueParameterTypes: List) { + throw UnsupportedOperationException("Shouldn't be called") + } +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/smap/assertion.2.kt b/compiler/testData/codegen/boxInline/smap/assertion.2.kt index 4b7e300724c..2bec83a1ecf 100644 --- a/compiler/testData/codegen/boxInline/smap/assertion.2.kt +++ b/compiler/testData/codegen/boxInline/smap/assertion.2.kt @@ -20,15 +20,4 @@ public inline fun massert(value: Boolean, message: Any = "Assertion failed") { } } -//TODO SHOULD BE ABSENT - -//SMAP -//assertion.2.kt -//Kotlin -//*S Kotlin -//*F -//+ 1 assertion.2.kt -//test/Assertion_2Kt -//*L -//1#1,34:1 -//*E \ No newline at end of file +//SMAP ABSENT