Default body compilation for inline fun extracted from InlineCodegen to separate one

This commit is contained in:
Michael Bogdanov
2016-02-24 12:47:42 +03:00
parent f149f16882
commit b20f49a2c4
6 changed files with 123 additions and 49 deletions
@@ -38,11 +38,6 @@ abstract class CallGenerator {
} }
} }
override fun genCallWithoutAssertions(
callableMethod: CallableMethod, codegen: ExpressionCodegen) {
callableMethod.genInvokeInstruction(codegen.v)
}
override fun afterParameterPut( override fun afterParameterPut(
type: Type, type: Type,
stackValue: StackValue?, stackValue: StackValue?,
@@ -107,8 +102,6 @@ abstract class CallGenerator {
abstract fun genCallInner(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen) abstract fun genCallInner(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen)
abstract fun genCallWithoutAssertions(callableMethod: CallableMethod, codegen: ExpressionCodegen)
abstract fun afterParameterPut( abstract fun afterParameterPut(
type: Type, type: Type,
stackValue: StackValue?, stackValue: StackValue?,
@@ -2492,7 +2492,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
if (!isInline) return defaultCallGenerator; if (!isInline) return defaultCallGenerator;
FunctionDescriptor original = DescriptorUtils.unwrapFakeOverride((FunctionDescriptor) descriptor.getOriginal()); 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 @NotNull
@@ -756,7 +756,7 @@ public class FunctionCodegen {
CallableMethod method = state.getTypeMapper().mapToCallableMethod(functionDescriptor, false); CallableMethod method = state.getTypeMapper().mapToCallableMethod(functionDescriptor, false);
generator.genCallWithoutAssertions(method, codegen); generator.genCall(method, null, false, codegen);
iv.areturn(signature.getReturnType()); iv.areturn(signature.getReturnType());
} }
@@ -86,7 +86,6 @@ public class InlineCodegen extends CallGenerator {
private final ReifiedTypeInliner reifiedTypeInliner; private final ReifiedTypeInliner reifiedTypeInliner;
@Nullable private final TypeParameterMappings typeParameterMappings; @Nullable private final TypeParameterMappings typeParameterMappings;
private final boolean isDefaultMethodCompilation;
private LambdaInfo activeLambda; private LambdaInfo activeLambda;
@@ -97,12 +96,10 @@ public class InlineCodegen extends CallGenerator {
@NotNull GenerationState state, @NotNull GenerationState state,
@NotNull FunctionDescriptor function, @NotNull FunctionDescriptor function,
@NotNull KtElement callElement, @NotNull KtElement callElement,
@Nullable TypeParameterMappings typeParameterMappings, @Nullable TypeParameterMappings typeParameterMappings
boolean isDefaultMethodCompilation
) { ) {
assert InlineUtil.isInline(function) || InlineUtil.isArrayConstructorWithLambda(function) : assert InlineUtil.isInline(function) || InlineUtil.isArrayConstructorWithLambda(function) :
"InlineCodegen can inline only inline functions and array constructors: " + function; "InlineCodegen can inline only inline functions and array constructors: " + function;
this.isDefaultMethodCompilation = isDefaultMethodCompilation;
this.state = state; this.state = state;
this.typeMapper = state.getTypeMapper(); this.typeMapper = state.getTypeMapper();
this.codegen = codegen; this.codegen = codegen;
@@ -129,15 +126,10 @@ public class InlineCodegen extends CallGenerator {
sourceMapper = codegen.getParentCodegen().getOrCreateSourceMapper(); sourceMapper = codegen.getParentCodegen().getOrCreateSourceMapper();
if (!(functionDescriptor instanceof FictitiousArrayConstructor)) { 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 @Override
public void genCallInner(@NotNull Callable callableMethod, @Nullable ResolvedCall<?> resolvedCall, boolean callDefault, @NotNull ExpressionCodegen codegen) { public void genCallInner(@NotNull Callable callableMethod, @Nullable ResolvedCall<?> resolvedCall, boolean callDefault, @NotNull ExpressionCodegen codegen) {
SMAPAndMethodNode nodeAndSmap = null; SMAPAndMethodNode nodeAndSmap = null;
@@ -148,11 +140,7 @@ public class InlineCodegen extends CallGenerator {
try { try {
nodeAndSmap = createMethodNode(callDefault); nodeAndSmap = createMethodNode(callDefault);
if (isDefaultMethodCompilation) { endCall(inlineCall(nodeAndSmap));
nodeAndSmap.getNode().accept(new MethodBodyVisitor(codegen.v));
} else {
endCall(inlineCall(nodeAndSmap));
}
} }
catch (CompilationException e) { catch (CompilationException e) {
throw e; throw e;
@@ -190,6 +178,18 @@ public class InlineCodegen extends CallGenerator {
@NotNull @NotNull
private SMAPAndMethodNode createMethodNode(boolean callDefault) throws IOException { 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 Method asmMethod = callDefault
? typeMapper.mapDefaultMethod(functionDescriptor, context.getContextKind()) ? typeMapper.mapDefaultMethod(functionDescriptor, context.getContextKind())
: jvmSignature.getAsmMethod(); : jvmSignature.getAsmMethod();
@@ -257,7 +257,7 @@ public class InlineCodegen extends CallGenerator {
smap = createSMAPWithDefaultMapping(inliningFunction, parentCodegen.getOrCreateSourceMapper().getResultMappings()); smap = createSMAPWithDefaultMapping(inliningFunction, parentCodegen.getOrCreateSourceMapper().getResultMappings());
} }
else { else {
smap = generateMethodBody(maxCalcAdapter, functionDescriptor, methodContext, inliningFunction, jvmSignature, false); smap = generateMethodBody(maxCalcAdapter, functionDescriptor, methodContext, inliningFunction, jvmSignature, false, codegen, state);
} }
nodeAndSMAP = new SMAPAndMethodNode(node, smap); nodeAndSMAP = new SMAPAndMethodNode(node, smap);
@@ -355,24 +355,27 @@ public class InlineCodegen extends CallGenerator {
MethodVisitor adapter = InlineCodegenUtil.wrapWithMaxLocalCalc(methodNode); 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); adapter.visitMaxs(-1, -1);
return new SMAPAndMethodNode(methodNode, smap); return new SMAPAndMethodNode(methodNode, smap);
} }
private SMAP generateMethodBody( private static SMAP generateMethodBody(
@NotNull MethodVisitor adapter, @NotNull MethodVisitor adapter,
@NotNull FunctionDescriptor descriptor, @NotNull FunctionDescriptor descriptor,
@NotNull MethodContext context, @NotNull MethodContext context,
@NotNull KtExpression expression, @NotNull KtExpression expression,
@NotNull JvmMethodSignature jvmMethodSignature, @NotNull JvmMethodSignature jvmMethodSignature,
boolean isLambda boolean isLambda,
@NotNull ExpressionCodegen codegen,
@NotNull GenerationState state
) { ) {
FakeMemberCodegen parentCodegen = FakeMemberCodegen parentCodegen =
new FakeMemberCodegen(codegen.getParentCodegen(), expression, new FakeMemberCodegen(codegen.getParentCodegen(), expression,
(FieldOwnerContext) context.getParentContext(), (FieldOwnerContext) context.getParentContext(),
isLambda ? codegen.getParentCodegen().getClassName() isLambda ? codegen.getParentCodegen().getClassName()
: typeMapper.mapImplementationOwner(descriptor).getInternalName()); : state.getTypeMapper().mapImplementationOwner(descriptor).getInternalName());
FunctionGenerationStrategy strategy = FunctionGenerationStrategy strategy =
expression instanceof KtCallableReferenceExpression ? expression instanceof KtCallableReferenceExpression ?
@@ -682,11 +685,6 @@ public class InlineCodegen extends CallGenerator {
@NotNull Type parameterType, @NotNull Type parameterType,
@NotNull StackValue value @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); putValueIfNeeded(parameterType, value, -1);
} }
@@ -803,9 +801,11 @@ public class InlineCodegen extends CallGenerator {
return new NestedSourceMapper(sourceMapper, nodeAndSmap.getRanges(), nodeAndSmap.getClassSMAP().getSourceInfo()); return new NestedSourceMapper(sourceMapper, nodeAndSmap.getRanges(), nodeAndSmap.getClassSMAP().getSourceInfo());
} }
private void reportIncrementalInfo( static void reportIncrementalInfo(
@NotNull FunctionDescriptor sourceDescriptor, @NotNull FunctionDescriptor sourceDescriptor,
@NotNull FunctionDescriptor targetDescriptor @NotNull FunctionDescriptor targetDescriptor,
@NotNull JvmMethodSignature jvmSignature,
@NotNull GenerationState state
) { ) {
IncrementalCompilationComponents incrementalCompilationComponents = state.getIncrementalCompilationComponents(); IncrementalCompilationComponents incrementalCompilationComponents = state.getIncrementalCompilationComponents();
TargetId targetId = state.getTargetId(); TargetId targetId = state.getTargetId();
@@ -813,7 +813,7 @@ public class InlineCodegen extends CallGenerator {
if (incrementalCompilationComponents == null || targetId == null) return; if (incrementalCompilationComponents == null || targetId == null) return;
IncrementalCache incrementalCache = incrementalCompilationComponents.getIncrementalCache(targetId); 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); String sourceFilePath = InlineCodegenUtilsKt.getSourceFilePath(targetDescriptor);
incrementalCache.registerInline(classFilePath, jvmSignature.toString(), sourceFilePath); incrementalCache.registerInline(classFilePath, jvmSignature.toString(), sourceFilePath);
} }
@@ -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<ArgumentAndDeclIndex>, valueParameterTypes: List<Type>) {
throw UnsupportedOperationException("Shouldn't be called")
}
}
+1 -12
View File
@@ -20,15 +20,4 @@ public inline fun massert(value: Boolean, message: Any = "Assertion failed") {
} }
} }
//TODO SHOULD BE ABSENT //SMAP ABSENT
//SMAP
//assertion.2.kt
//Kotlin
//*S Kotlin
//*F
//+ 1 assertion.2.kt
//test/Assertion_2Kt
//*L
//1#1,34:1
//*E