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(
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?,
@@ -2492,7 +2492,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> 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
@@ -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());
}
@@ -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);
}
@@ -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
//assertion.2.kt
//Kotlin
//*S Kotlin
//*F
//+ 1 assertion.2.kt
//test/Assertion_2Kt
//*L
//1#1,34:1
//*E
//SMAP ABSENT