Introduce BaseExpressionCodegen and SourceCompilerForInline,
switch CallGenerator and InlineCodegen to them ~base
This commit is contained in:
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 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
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.codegen.inline.NameGenerator
|
||||||
|
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeParametersUsages
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
|
interface BaseExpressionCodegen {
|
||||||
|
|
||||||
|
val frameMap: FrameMap
|
||||||
|
|
||||||
|
val visitor: InstructionAdapter
|
||||||
|
|
||||||
|
val inlineNameGenerator: NameGenerator
|
||||||
|
|
||||||
|
val lastLineNumber: Int
|
||||||
|
|
||||||
|
fun consumeReifiedOperationMarker(typeParameterDescriptor: TypeParameterDescriptor)
|
||||||
|
|
||||||
|
fun propagateChildReifiedTypeParametersUsages(reifiedTypeParametersUsages: ReifiedTypeParametersUsages)
|
||||||
|
|
||||||
|
fun pushClosureOnStack(
|
||||||
|
classDescriptor: ClassDescriptor,
|
||||||
|
putThis: Boolean,
|
||||||
|
callGenerator: CallGenerator,
|
||||||
|
functionReferenceReceiver: StackValue?
|
||||||
|
)
|
||||||
|
|
||||||
|
fun markLineNumberAfterInlineIfNeeded()
|
||||||
|
}
|
||||||
@@ -118,7 +118,7 @@ import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFun
|
|||||||
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral;
|
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral;
|
||||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||||
|
|
||||||
public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> implements LocalLookup {
|
public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> implements LocalLookup, BaseExpressionCodegen {
|
||||||
private final GenerationState state;
|
private final GenerationState state;
|
||||||
final KotlinTypeMapper typeMapper;
|
final KotlinTypeMapper typeMapper;
|
||||||
private final BindingContext bindingContext;
|
private final BindingContext bindingContext;
|
||||||
@@ -1352,6 +1352,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
//we should generate additional linenumber info after inline call only if it used as argument
|
//we should generate additional linenumber info after inline call only if it used as argument
|
||||||
|
@Override
|
||||||
public void markLineNumberAfterInlineIfNeeded() {
|
public void markLineNumberAfterInlineIfNeeded() {
|
||||||
if (!shouldMarkLineNumbers) {
|
if (!shouldMarkLineNumbers) {
|
||||||
//if it used as general argument
|
//if it used as general argument
|
||||||
@@ -1366,6 +1367,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getLastLineNumber() {
|
public int getLastLineNumber() {
|
||||||
return myLastLineNumber;
|
return myLastLineNumber;
|
||||||
}
|
}
|
||||||
@@ -2286,10 +2288,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
FunctionDescriptor original =
|
FunctionDescriptor original =
|
||||||
unwrapInitialSignatureDescriptor(DescriptorUtils.unwrapFakeOverride((FunctionDescriptor) descriptor.getOriginal()));
|
unwrapInitialSignatureDescriptor(DescriptorUtils.unwrapFakeOverride((FunctionDescriptor) descriptor.getOriginal()));
|
||||||
if (isDefaultCompilation) {
|
if (isDefaultCompilation) {
|
||||||
return new InlineCodegenForDefaultBody(original, this, state);
|
return new InlineCodegenForDefaultBody(original, this, state, new SourceCompilerForInline(this));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new InlineCodegen(this, state, original, callElement, typeParameterMappings);
|
return new InlineCodegen(this, state, original, callElement, typeParameterMappings, new SourceCompilerForInline(this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4060,19 +4062,17 @@ The "returned" value of try expression with no finally is either the last expres
|
|||||||
public void putReifiedOperationMarkerIfTypeIsReifiedParameter(
|
public void putReifiedOperationMarkerIfTypeIsReifiedParameter(
|
||||||
@NotNull KotlinType type, @NotNull ReifiedTypeInliner.OperationKind operationKind
|
@NotNull KotlinType type, @NotNull ReifiedTypeInliner.OperationKind operationKind
|
||||||
) {
|
) {
|
||||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(type, operationKind, v);
|
putReifiedOperationMarkerIfTypeIsReifiedParameter(type, operationKind, v, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putReifiedOperationMarkerIfTypeIsReifiedParameter(
|
public static void putReifiedOperationMarkerIfTypeIsReifiedParameter(
|
||||||
@NotNull KotlinType type, @NotNull ReifiedTypeInliner.OperationKind operationKind, @NotNull InstructionAdapter v
|
@NotNull KotlinType type, @NotNull ReifiedTypeInliner.OperationKind operationKind, @NotNull InstructionAdapter v,
|
||||||
|
@NotNull BaseExpressionCodegen codegen
|
||||||
) {
|
) {
|
||||||
Pair<TypeParameterDescriptor, ReificationArgument> typeParameterAndReificationArgument = extractReificationArgument(type);
|
Pair<TypeParameterDescriptor, ReificationArgument> typeParameterAndReificationArgument = extractReificationArgument(type);
|
||||||
if (typeParameterAndReificationArgument != null && typeParameterAndReificationArgument.getFirst().isReified()) {
|
if (typeParameterAndReificationArgument != null && typeParameterAndReificationArgument.getFirst().isReified()) {
|
||||||
TypeParameterDescriptor typeParameterDescriptor = typeParameterAndReificationArgument.getFirst();
|
TypeParameterDescriptor typeParameterDescriptor = typeParameterAndReificationArgument.getFirst();
|
||||||
if (typeParameterDescriptor.getContainingDeclaration() != context.getContextDescriptor()) {
|
codegen.consumeReifiedOperationMarker(typeParameterDescriptor);
|
||||||
parentCodegen.getReifiedTypeParametersUsages().
|
|
||||||
addUsedReifiedParameter(typeParameterDescriptor.getName().asString());
|
|
||||||
}
|
|
||||||
v.iconst(operationKind.getId());
|
v.iconst(operationKind.getId());
|
||||||
v.visitLdcInsn(typeParameterAndReificationArgument.getSecond().asString());
|
v.visitLdcInsn(typeParameterAndReificationArgument.getSecond().asString());
|
||||||
v.invokestatic(
|
v.invokestatic(
|
||||||
@@ -4082,6 +4082,7 @@ The "returned" value of try expression with no finally is either the last expres
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void propagateChildReifiedTypeParametersUsages(@NotNull ReifiedTypeParametersUsages usages) {
|
public void propagateChildReifiedTypeParametersUsages(@NotNull ReifiedTypeParametersUsages usages) {
|
||||||
parentCodegen.getReifiedTypeParametersUsages().propagateChildUsagesWithinContext(usages, context);
|
parentCodegen.getReifiedTypeParametersUsages().propagateChildUsagesWithinContext(usages, context);
|
||||||
}
|
}
|
||||||
@@ -4203,6 +4204,7 @@ The "returned" value of try expression with no finally is either the last expres
|
|||||||
return context.getContextDescriptor().toString();
|
return context.getContextDescriptor().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public FrameMap getFrameMap() {
|
public FrameMap getFrameMap() {
|
||||||
return myFrameMap;
|
return myFrameMap;
|
||||||
@@ -4213,6 +4215,7 @@ The "returned" value of try expression with no finally is either the last expres
|
|||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public NameGenerator getInlineNameGenerator() {
|
public NameGenerator getInlineNameGenerator() {
|
||||||
NameGenerator nameGenerator = getParentCodegen().getInlineNameGenerator();
|
NameGenerator nameGenerator = getParentCodegen().getInlineNameGenerator();
|
||||||
@@ -4255,4 +4258,18 @@ The "returned" value of try expression with no finally is either the last expres
|
|||||||
) {
|
) {
|
||||||
return StackValue.delegate(typeMapper.mapType(variableDescriptor.getType()), delegateValue, metadataValue, variableDescriptor, this);
|
return StackValue.delegate(typeMapper.mapType(variableDescriptor.getType()), delegateValue, metadataValue, variableDescriptor, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public InstructionAdapter getVisitor() {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void consumeReifiedOperationMarker(@NotNull TypeParameterDescriptor typeParameterDescriptor) {
|
||||||
|
if (typeParameterDescriptor.getContainingDeclaration() != context.getContextDescriptor()) {
|
||||||
|
parentCodegen.getReifiedTypeParametersUsages().
|
||||||
|
addUsedReifiedParameter(typeParameterDescriptor.getName().asString());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,10 @@ package org.jetbrains.kotlin.codegen.inline
|
|||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.util.ArrayUtil
|
import com.intellij.util.ArrayUtil
|
||||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
|
||||||
import org.jetbrains.kotlin.builtins.BuiltInsPackageFragment
|
import org.jetbrains.kotlin.builtins.BuiltInsPackageFragment
|
||||||
import org.jetbrains.kotlin.codegen.*
|
import org.jetbrains.kotlin.codegen.*
|
||||||
import org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags
|
import org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags
|
||||||
import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive
|
import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive
|
||||||
import org.jetbrains.kotlin.codegen.context.*
|
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.createMethodNodeForSuspendCoroutineOrReturn
|
import org.jetbrains.kotlin.codegen.coroutines.createMethodNodeForSuspendCoroutineOrReturn
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.isBuiltInSuspendCoroutineOrReturnInJvm
|
import org.jetbrains.kotlin.codegen.coroutines.isBuiltInSuspendCoroutineOrReturnInJvm
|
||||||
import org.jetbrains.kotlin.codegen.intrinsics.bytecode
|
import org.jetbrains.kotlin.codegen.intrinsics.bytecode
|
||||||
@@ -39,11 +37,11 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor
|
import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil.isInlinableParameterExpression
|
import org.jetbrains.kotlin.resolve.inline.InlineUtil.isInlinableParameterExpression
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
@@ -51,22 +49,21 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
|
|||||||
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS
|
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral
|
||||||
import org.jetbrains.kotlin.types.expressions.LabelResolver
|
import org.jetbrains.kotlin.types.expressions.LabelResolver
|
||||||
import org.jetbrains.org.objectweb.asm.Label
|
|
||||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
||||||
import org.jetbrains.org.objectweb.asm.tree.LabelNode
|
|
||||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class InlineCodegen(
|
class InlineCodegen(
|
||||||
private val codegen: ExpressionCodegen,
|
private val codegen: BaseExpressionCodegen,
|
||||||
private val state: GenerationState,
|
private val state: GenerationState,
|
||||||
function: FunctionDescriptor,
|
function: FunctionDescriptor,
|
||||||
private val callElement: KtElement,
|
private val callElement: KtElement,
|
||||||
private val typeParameterMappings: TypeParameterMappings
|
private val typeParameterMappings: TypeParameterMappings,
|
||||||
|
private val sourceCompiler: SourceCompilerForInline
|
||||||
) : CallGenerator() {
|
) : CallGenerator() {
|
||||||
init {
|
init {
|
||||||
assert(InlineUtil.isInline(function) || InlineUtil.isArrayConstructorWithLambda(function)) {
|
assert(InlineUtil.isInline(function) || InlineUtil.isArrayConstructorWithLambda(function)) {
|
||||||
@@ -89,15 +86,9 @@ class InlineCodegen(
|
|||||||
else
|
else
|
||||||
function.original
|
function.original
|
||||||
|
|
||||||
private val context =
|
private val jvmSignature: JvmMethodGenericSignature
|
||||||
getContext(
|
|
||||||
functionDescriptor, state,
|
|
||||||
DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)?.containingFile as? KtFile
|
|
||||||
) as MethodContext
|
|
||||||
|
|
||||||
private val jvmSignature = typeMapper.mapSignatureWithGeneric(functionDescriptor, context.contextKind)
|
private val isSameModule: Boolean
|
||||||
|
|
||||||
private val isSameModule = JvmCodegenUtil.isCallInsideSameModuleAsDeclared(functionDescriptor, codegen.getContext(), state.outDirectory)
|
|
||||||
|
|
||||||
private val invocationParamBuilder = ParametersBuilder.newBuilder()
|
private val invocationParamBuilder = ParametersBuilder.newBuilder()
|
||||||
|
|
||||||
@@ -105,7 +96,7 @@ class InlineCodegen(
|
|||||||
|
|
||||||
private var activeLambda: LambdaInfo? = null
|
private var activeLambda: LambdaInfo? = null
|
||||||
|
|
||||||
private val sourceMapper = codegen.parentCodegen.orCreateSourceMapper
|
private val sourceMapper = sourceCompiler.lazySourceMapper
|
||||||
|
|
||||||
private var delayedHiddenWriting: Function0<Unit>? = null
|
private var delayedHiddenWriting: Function0<Unit>? = null
|
||||||
|
|
||||||
@@ -114,8 +105,12 @@ class InlineCodegen(
|
|||||||
private var methodHandleInDefaultMethodIndex = -1
|
private var methodHandleInDefaultMethodIndex = -1
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
sourceCompiler.initializeInlineFunctionContext(functionDescriptor)
|
||||||
|
jvmSignature = typeMapper.mapSignatureWithGeneric(functionDescriptor, sourceCompiler.contextKind)
|
||||||
|
isSameModule = sourceCompiler.isCallInsideSameModuleAsDeclared(functionDescriptor)
|
||||||
|
|
||||||
if (functionDescriptor !is FictitiousArrayConstructor) {
|
if (functionDescriptor !is FictitiousArrayConstructor) {
|
||||||
reportIncrementalInfo(functionDescriptor, codegen.getContext().functionDescriptor.original, jvmSignature, state)
|
reportIncrementalInfo(functionDescriptor, sourceCompiler.compilationContextFunctionDescriptor.original, jvmSignature, state)
|
||||||
val functionOrAccessorName = typeMapper.mapAsmMethod(function).name
|
val functionOrAccessorName = typeMapper.mapAsmMethod(function).name
|
||||||
//track changes for property accessor and @JvmName inline functions/property accessors
|
//track changes for property accessor and @JvmName inline functions/property accessors
|
||||||
if (functionOrAccessorName != functionDescriptor.name.asString()) {
|
if (functionOrAccessorName != functionDescriptor.name.asString()) {
|
||||||
@@ -130,7 +125,7 @@ class InlineCodegen(
|
|||||||
callableMethod: Callable,
|
callableMethod: Callable,
|
||||||
resolvedCall: ResolvedCall<*>?,
|
resolvedCall: ResolvedCall<*>?,
|
||||||
callDefault: Boolean,
|
callDefault: Boolean,
|
||||||
codegen: ExpressionCodegen
|
codegen: BaseExpressionCodegen
|
||||||
) {
|
) {
|
||||||
if (!state.inlineCycleReporter.enterIntoInlining(resolvedCall)) {
|
if (!state.inlineCycleReporter.enterIntoInlining(resolvedCall)) {
|
||||||
generateStub(resolvedCall, codegen)
|
generateStub(resolvedCall, codegen)
|
||||||
@@ -139,7 +134,7 @@ class InlineCodegen(
|
|||||||
|
|
||||||
var nodeAndSmap: SMAPAndMethodNode? = null
|
var nodeAndSmap: SMAPAndMethodNode? = null
|
||||||
try {
|
try {
|
||||||
nodeAndSmap = createMethodNode(functionDescriptor, jvmSignature, codegen, context, callDefault, resolvedCall)
|
nodeAndSmap = createInlineMethodNode(functionDescriptor, jvmSignature, codegen, callDefault, resolvedCall, state, sourceCompiler)
|
||||||
endCall(inlineCall(nodeAndSmap, callDefault))
|
endCall(inlineCall(nodeAndSmap, callDefault))
|
||||||
}
|
}
|
||||||
catch (e: CompilationException) {
|
catch (e: CompilationException) {
|
||||||
@@ -159,7 +154,7 @@ class InlineCodegen(
|
|||||||
private fun throwCompilationException(
|
private fun throwCompilationException(
|
||||||
nodeAndSmap: SMAPAndMethodNode?, e: Exception, generateNodeText: Boolean
|
nodeAndSmap: SMAPAndMethodNode?, e: Exception, generateNodeText: Boolean
|
||||||
): CompilationException {
|
): CompilationException {
|
||||||
val contextDescriptor = codegen.getContext().contextDescriptor
|
val contextDescriptor = sourceCompiler.compilationContextDescriptor
|
||||||
val element = DescriptorToSourceUtils.descriptorToDeclaration(contextDescriptor)
|
val element = DescriptorToSourceUtils.descriptorToDeclaration(contextDescriptor)
|
||||||
val node = nodeAndSmap?.node
|
val node = nodeAndSmap?.node
|
||||||
throw CompilationException(
|
throw CompilationException(
|
||||||
@@ -171,7 +166,7 @@ class InlineCodegen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateStub(resolvedCall: ResolvedCall<*>?, codegen: ExpressionCodegen) {
|
private fun generateStub(resolvedCall: ResolvedCall<*>?, codegen: BaseExpressionCodegen) {
|
||||||
leaveTemps()
|
leaveTemps()
|
||||||
assert(resolvedCall != null)
|
assert(resolvedCall != null)
|
||||||
val message = "Call is part of inline cycle: " + resolvedCall!!.call.callElement.text
|
val message = "Call is part of inline cycle: " + resolvedCall!!.call.callElement.text
|
||||||
@@ -190,7 +185,7 @@ class InlineCodegen(
|
|||||||
|
|
||||||
private fun inlineCall(nodeAndSmap: SMAPAndMethodNode, callDefault: Boolean): InlineResult {
|
private fun inlineCall(nodeAndSmap: SMAPAndMethodNode, callDefault: Boolean): InlineResult {
|
||||||
assert(delayedHiddenWriting == null) { "'putHiddenParamsIntoLocals' should be called after 'processAndPutHiddenParameters(true)'" }
|
assert(delayedHiddenWriting == null) { "'putHiddenParamsIntoLocals' should be called after 'processAndPutHiddenParameters(true)'" }
|
||||||
val defaultSourceMapper = codegen.parentCodegen.orCreateSourceMapper
|
val defaultSourceMapper = sourceMapper
|
||||||
defaultSourceMapper.callSiteMarker = CallSiteMarker(codegen.lastLineNumber)
|
defaultSourceMapper.callSiteMarker = CallSiteMarker(codegen.lastLineNumber)
|
||||||
val node = nodeAndSmap.node
|
val node = nodeAndSmap.node
|
||||||
if (callDefault) {
|
if (callDefault) {
|
||||||
@@ -216,7 +211,7 @@ class InlineCodegen(
|
|||||||
|
|
||||||
val info = RootInliningContext(
|
val info = RootInliningContext(
|
||||||
expressionMap, state, codegen.inlineNameGenerator.subGenerator(jvmSignature.asmMethod.name),
|
expressionMap, state, codegen.inlineNameGenerator.subGenerator(jvmSignature.asmMethod.name),
|
||||||
callElement, inlineCallSiteInfo, reifiedTypeInliner, typeParameterMappings
|
callElement, sourceCompiler.inlineCallSiteInfo, reifiedTypeInliner, typeParameterMappings
|
||||||
)
|
)
|
||||||
|
|
||||||
val inliner = MethodInliner(
|
val inliner = MethodInliner(
|
||||||
@@ -235,15 +230,15 @@ class InlineCodegen(
|
|||||||
val result = inliner.doInline(adapter, remapper, true, LabelOwner.SKIP_ALL)
|
val result = inliner.doInline(adapter, remapper, true, LabelOwner.SKIP_ALL)
|
||||||
result.reifiedTypeParametersUsages.mergeAll(reificationResult)
|
result.reifiedTypeParametersUsages.mergeAll(reificationResult)
|
||||||
|
|
||||||
val descriptor = getLabelOwnerDescriptor(codegen.getContext())
|
val descriptor = sourceCompiler.getLabelOwnerDescriptor()
|
||||||
val labels = getDeclarationLabels(DescriptorToSourceUtils.descriptorToDeclaration(descriptor), descriptor)
|
val labels = getDeclarationLabels(DescriptorToSourceUtils.descriptorToDeclaration(descriptor), descriptor)
|
||||||
|
|
||||||
val infos = MethodInliner.processReturns(adapter, LabelOwner { labels.contains(it) }, true, null)
|
val infos = MethodInliner.processReturns(adapter, LabelOwner { labels.contains(it) }, true, null)
|
||||||
generateAndInsertFinallyBlocks(
|
sourceCompiler.generateAndInsertFinallyBlocks(
|
||||||
adapter, infos, (remapper.remap(parameters.argsSizeOnStack + 1).value as StackValue.Local).index
|
adapter, infos, (remapper.remap(parameters.argsSizeOnStack + 1).value as StackValue.Local).index
|
||||||
)
|
)
|
||||||
removeStaticInitializationTrigger(adapter)
|
removeStaticInitializationTrigger(adapter)
|
||||||
if (!isFinallyMarkerRequired(codegen.getContext())) {
|
if (!sourceCompiler.isFinallyMarkerRequired()) {
|
||||||
removeFinallyMarkers(adapter)
|
removeFinallyMarkers(adapter)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,57 +251,9 @@ class InlineCodegen(
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private val inlineCallSiteInfo: InlineCallSiteInfo
|
|
||||||
get() {
|
|
||||||
var context = codegen.getContext()
|
|
||||||
var parentCodegen = codegen.parentCodegen
|
|
||||||
while (context is InlineLambdaContext) {
|
|
||||||
val closureContext = context.getParentContext()
|
|
||||||
assert(closureContext is ClosureContext) { "Parent context of inline lambda should be closure context" }
|
|
||||||
assert(closureContext.parentContext is MethodContext) { "Closure context should appear in method context" }
|
|
||||||
context = closureContext.parentContext as MethodContext
|
|
||||||
assert(parentCodegen is FakeMemberCodegen) { "Parent codegen of inlined lambda should be FakeMemberCodegen" }
|
|
||||||
parentCodegen = (parentCodegen as FakeMemberCodegen).delegate
|
|
||||||
}
|
|
||||||
|
|
||||||
val signature = typeMapper.mapSignatureSkipGeneric(context.functionDescriptor, context.contextKind)
|
|
||||||
return InlineCallSiteInfo(
|
|
||||||
parentCodegen.className, signature.asmMethod.name, signature.asmMethod.descriptor
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateClosuresBodies() {
|
private fun generateClosuresBodies() {
|
||||||
for (info in expressionMap.values) {
|
for (info in expressionMap.values) {
|
||||||
info.generateLambdaBody(codegen, reifiedTypeInliner)
|
info.generateLambdaBody(sourceCompiler, reifiedTypeInliner)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class FakeMemberCodegen(
|
|
||||||
internal val delegate: MemberCodegen<*>,
|
|
||||||
declaration: KtElement,
|
|
||||||
codegenContext: FieldOwnerContext<*>,
|
|
||||||
private val className: String
|
|
||||||
) : MemberCodegen<KtPureElement>(delegate as MemberCodegen<KtPureElement>, declaration, codegenContext) {
|
|
||||||
|
|
||||||
override fun generateDeclaration() {
|
|
||||||
throw IllegalStateException()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun generateBody() {
|
|
||||||
throw IllegalStateException()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun generateKotlinMetadataAnnotation() {
|
|
||||||
throw IllegalStateException()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getInlineNameGenerator(): NameGenerator {
|
|
||||||
return delegate.inlineNameGenerator
|
|
||||||
}
|
|
||||||
|
|
||||||
override //TODO: obtain name from context
|
|
||||||
fun getClassName(): String {
|
|
||||||
return className
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,7 +323,7 @@ class InlineCodegen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun processAndPutHiddenParameters(justProcess: Boolean) {
|
override fun processAndPutHiddenParameters(justProcess: Boolean) {
|
||||||
if (getMethodAsmFlags(functionDescriptor, context.contextKind, state) and Opcodes.ACC_STATIC == 0) {
|
if (getMethodAsmFlags(functionDescriptor, sourceCompiler.contextKind, state) and Opcodes.ACC_STATIC == 0) {
|
||||||
invocationParamBuilder.addNextParameter(AsmTypes.OBJECT_TYPE, false)
|
invocationParamBuilder.addNextParameter(AsmTypes.OBJECT_TYPE, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -519,69 +466,6 @@ class InlineCodegen(
|
|||||||
putArgumentOrCapturedToLocalVal(stackValue.type, stackValue, paramIndex, paramIndex, ValueKind.CAPTURED)
|
putArgumentOrCapturedToLocalVal(stackValue.type, stackValue, paramIndex, paramIndex, ValueKind.CAPTURED)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateAndInsertFinallyBlocks(
|
|
||||||
intoNode: MethodNode,
|
|
||||||
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
|
|
||||||
offsetForFinallyLocalVar: Int
|
|
||||||
) {
|
|
||||||
if (!codegen.hasFinallyBlocks()) return
|
|
||||||
|
|
||||||
val extensionPoints = HashMap<AbstractInsnNode, MethodInliner.PointForExternalFinallyBlocks>()
|
|
||||||
for (insertPoint in insertPoints) {
|
|
||||||
extensionPoints.put(insertPoint.beforeIns, insertPoint)
|
|
||||||
}
|
|
||||||
|
|
||||||
val processor = DefaultProcessor(intoNode, offsetForFinallyLocalVar)
|
|
||||||
|
|
||||||
var curFinallyDepth = 0
|
|
||||||
var curInstr: AbstractInsnNode? = intoNode.instructions.first
|
|
||||||
while (curInstr != null) {
|
|
||||||
processor.processInstruction(curInstr, true)
|
|
||||||
if (isFinallyStart(curInstr)) {
|
|
||||||
//TODO depth index calc could be more precise
|
|
||||||
curFinallyDepth = getConstant(curInstr.previous)
|
|
||||||
}
|
|
||||||
|
|
||||||
val extension = extensionPoints[curInstr]
|
|
||||||
if (extension != null) {
|
|
||||||
val start = Label()
|
|
||||||
|
|
||||||
val finallyNode = createEmptyMethodNode()
|
|
||||||
finallyNode.visitLabel(start)
|
|
||||||
|
|
||||||
val finallyCodegen = ExpressionCodegen(finallyNode, codegen.frameMap, codegen.returnType,
|
|
||||||
codegen.getContext(), codegen.state, codegen.parentCodegen)
|
|
||||||
finallyCodegen.addBlockStackElementsForNonLocalReturns(codegen.blockStackElements, curFinallyDepth)
|
|
||||||
|
|
||||||
val frameMap = finallyCodegen.frameMap
|
|
||||||
val mark = frameMap.mark()
|
|
||||||
val marker = processor.localVarsMetaInfo.currentIntervals.maxBy { it.node.index }?.node?.index?.plus(1) ?: -1
|
|
||||||
|
|
||||||
while (frameMap.currentSize < Math.max(processor.nextFreeLocalIndex, offsetForFinallyLocalVar + marker)) {
|
|
||||||
frameMap.enterTemp(Type.INT_TYPE)
|
|
||||||
}
|
|
||||||
|
|
||||||
finallyCodegen.generateFinallyBlocksIfNeeded(extension.returnType, extension.finallyIntervalEnd.label)
|
|
||||||
|
|
||||||
//Exception table for external try/catch/finally blocks will be generated in original codegen after exiting this method
|
|
||||||
insertNodeBefore(finallyNode, intoNode, curInstr)
|
|
||||||
|
|
||||||
val splitBy = SimpleInterval(start.info as LabelNode, extension.finallyIntervalEnd)
|
|
||||||
processor.tryBlocksMetaInfo.splitCurrentIntervals(splitBy, true)
|
|
||||||
|
|
||||||
//processor.getLocalVarsMetaInfo().splitAndRemoveIntervalsFromCurrents(splitBy);
|
|
||||||
|
|
||||||
mark.dropTo()
|
|
||||||
}
|
|
||||||
|
|
||||||
curInstr = curInstr.next
|
|
||||||
}
|
|
||||||
|
|
||||||
processor.substituteTryBlockNodes(intoNode)
|
|
||||||
|
|
||||||
//processor.substituteLocalVarTable(intoNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun reorderArgumentsIfNeeded(
|
override fun reorderArgumentsIfNeeded(
|
||||||
actualArgsWithDeclIndex: List<ArgumentAndDeclIndex>, valueParameterTypes: List<Type>
|
actualArgsWithDeclIndex: List<ArgumentAndDeclIndex>, valueParameterTypes: List<Type>
|
||||||
) {
|
) {
|
||||||
@@ -605,13 +489,14 @@ class InlineCodegen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun createMethodNode(
|
internal fun createInlineMethodNode(
|
||||||
functionDescriptor: FunctionDescriptor,
|
functionDescriptor: FunctionDescriptor,
|
||||||
jvmSignature: JvmMethodSignature,
|
jvmSignature: JvmMethodSignature,
|
||||||
codegen: ExpressionCodegen,
|
codegen: BaseExpressionCodegen,
|
||||||
context: CodegenContext<*>,
|
|
||||||
callDefault: Boolean,
|
callDefault: Boolean,
|
||||||
resolvedCall: ResolvedCall<*>?
|
resolvedCall: ResolvedCall<*>?,
|
||||||
|
state: GenerationState,
|
||||||
|
sourceCompilerForInline: SourceCompilerForInline
|
||||||
): SMAPAndMethodNode {
|
): SMAPAndMethodNode {
|
||||||
if (isSpecialEnumMethod(functionDescriptor)) {
|
if (isSpecialEnumMethod(functionDescriptor)) {
|
||||||
val arguments = resolvedCall!!.typeArguments
|
val arguments = resolvedCall!!.typeArguments
|
||||||
@@ -620,29 +505,28 @@ class InlineCodegen(
|
|||||||
codegen,
|
codegen,
|
||||||
functionDescriptor.name.asString(),
|
functionDescriptor.name.asString(),
|
||||||
arguments.keys.single().defaultType,
|
arguments.keys.single().defaultType,
|
||||||
codegen.state.typeMapper
|
state.typeMapper
|
||||||
)
|
)
|
||||||
return SMAPAndMethodNode(node, SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1))
|
return SMAPAndMethodNode(node, SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1))
|
||||||
}
|
}
|
||||||
else if (functionDescriptor.isBuiltInSuspendCoroutineOrReturnInJvm()) {
|
else if (functionDescriptor.isBuiltInSuspendCoroutineOrReturnInJvm()) {
|
||||||
return SMAPAndMethodNode(
|
return SMAPAndMethodNode(
|
||||||
createMethodNodeForSuspendCoroutineOrReturn(
|
createMethodNodeForSuspendCoroutineOrReturn(
|
||||||
functionDescriptor, codegen.state.typeMapper
|
functionDescriptor, state.typeMapper
|
||||||
),
|
),
|
||||||
SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1)
|
SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val state = codegen.state
|
|
||||||
val asmMethod = if (callDefault)
|
val asmMethod = if (callDefault)
|
||||||
state.typeMapper.mapDefaultMethod(functionDescriptor, context.contextKind)
|
state.typeMapper.mapDefaultMethod(functionDescriptor, sourceCompilerForInline.contextKind)
|
||||||
else
|
else
|
||||||
jvmSignature.asmMethod
|
jvmSignature.asmMethod
|
||||||
|
|
||||||
val methodId = MethodId(DescriptorUtils.getFqNameSafe(functionDescriptor.containingDeclaration), asmMethod)
|
val methodId = MethodId(DescriptorUtils.getFqNameSafe(functionDescriptor.containingDeclaration), asmMethod)
|
||||||
val directMember = getDirectMemberAndCallableFromObject(functionDescriptor)
|
val directMember = getDirectMemberAndCallableFromObject(functionDescriptor)
|
||||||
if (!isBuiltInArrayIntrinsic(functionDescriptor) && directMember !is DeserializedCallableMemberDescriptor) {
|
if (!isBuiltInArrayIntrinsic(functionDescriptor) && directMember !is DeserializedCallableMemberDescriptor) {
|
||||||
return doCreateMethodNodeFromSource(functionDescriptor, jvmSignature, codegen, context, callDefault, state, asmMethod)
|
return sourceCompilerForInline.doCreateMethodNodeFromSource(functionDescriptor, jvmSignature, callDefault, asmMethod)
|
||||||
}
|
}
|
||||||
|
|
||||||
val resultInCache = state.inlineCache.methodNodeById.getOrPut(methodId
|
val resultInCache = state.inlineCache.methodNodeById.getOrPut(methodId
|
||||||
@@ -692,58 +576,7 @@ class InlineCodegen(
|
|||||||
return getMethodNode(bytes, asmMethod.name, asmMethod.descriptor, containerId.asString())
|
return getMethodNode(bytes, asmMethod.name, asmMethod.descriptor, containerId.asString())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun doCreateMethodNodeFromSource(
|
|
||||||
callableDescriptor: FunctionDescriptor,
|
|
||||||
jvmSignature: JvmMethodSignature,
|
|
||||||
codegen: ExpressionCodegen,
|
|
||||||
context: CodegenContext<*>,
|
|
||||||
callDefault: Boolean,
|
|
||||||
state: GenerationState,
|
|
||||||
asmMethod: Method
|
|
||||||
): SMAPAndMethodNode {
|
|
||||||
val element = DescriptorToSourceUtils.descriptorToDeclaration(callableDescriptor)
|
|
||||||
|
|
||||||
if (!(element is KtNamedFunction || element is KtPropertyAccessor)) {
|
|
||||||
throw IllegalStateException("Couldn't find declaration for function " + callableDescriptor)
|
|
||||||
}
|
|
||||||
val inliningFunction = element as KtDeclarationWithBody?
|
|
||||||
|
|
||||||
val node = MethodNode(
|
|
||||||
API,
|
|
||||||
getMethodAsmFlags(callableDescriptor, context.contextKind, state) or if (callDefault) Opcodes.ACC_STATIC else 0,
|
|
||||||
asmMethod.name,
|
|
||||||
asmMethod.descriptor, null, null
|
|
||||||
)
|
|
||||||
|
|
||||||
//for maxLocals calculation
|
|
||||||
val maxCalcAdapter = wrapWithMaxLocalCalc(node)
|
|
||||||
val parentContext = context.parentContext ?: error("Context has no parent: " + context)
|
|
||||||
val methodContext = parentContext.intoFunction(callableDescriptor)
|
|
||||||
|
|
||||||
val smap: SMAP
|
|
||||||
if (callDefault) {
|
|
||||||
val implementationOwner = state.typeMapper.mapImplementationOwner(callableDescriptor)
|
|
||||||
val parentCodegen = FakeMemberCodegen(
|
|
||||||
codegen.parentCodegen, inliningFunction!!, methodContext.parentContext as FieldOwnerContext<*>,
|
|
||||||
implementationOwner.internalName
|
|
||||||
)
|
|
||||||
if (element !is KtNamedFunction) {
|
|
||||||
throw IllegalStateException("Property accessors with default parameters not supported " + callableDescriptor)
|
|
||||||
}
|
|
||||||
FunctionCodegen.generateDefaultImplBody(
|
|
||||||
methodContext, callableDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT,
|
|
||||||
inliningFunction as KtNamedFunction?, parentCodegen, asmMethod
|
|
||||||
)
|
|
||||||
smap = createSMAPWithDefaultMapping(inliningFunction, parentCodegen.orCreateSourceMapper.resultMappings)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
smap = generateMethodBody(maxCalcAdapter, callableDescriptor, methodContext, inliningFunction!!, jvmSignature, codegen, null)
|
|
||||||
}
|
|
||||||
maxCalcAdapter.visitMaxs(-1, -1)
|
|
||||||
maxCalcAdapter.visitEnd()
|
|
||||||
|
|
||||||
return SMAPAndMethodNode(node, smap)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isBuiltInArrayIntrinsic(callableDescriptor: CallableMemberDescriptor): Boolean {
|
private fun isBuiltInArrayIntrinsic(callableDescriptor: CallableMemberDescriptor): Boolean {
|
||||||
if (callableDescriptor is FictitiousArrayConstructor) return true
|
if (callableDescriptor is FictitiousArrayConstructor) return true
|
||||||
@@ -751,14 +584,6 @@ class InlineCodegen(
|
|||||||
return (name == "arrayOf" || name == "emptyArray") && callableDescriptor.containingDeclaration is BuiltInsPackageFragment
|
return (name == "arrayOf" || name == "emptyArray") && callableDescriptor.containingDeclaration is BuiltInsPackageFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getLabelOwnerDescriptor(context: MethodContext): CallableMemberDescriptor {
|
|
||||||
val parentContext = context.parentContext
|
|
||||||
if (parentContext is ClosureContext && parentContext.originalSuspendLambdaDescriptor != null) {
|
|
||||||
return parentContext.originalSuspendLambdaDescriptor!!
|
|
||||||
}
|
|
||||||
return context.contextDescriptor
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun removeStaticInitializationTrigger(methodNode: MethodNode) {
|
private fun removeStaticInitializationTrigger(methodNode: MethodNode) {
|
||||||
val insnList = methodNode.instructions
|
val insnList = methodNode.instructions
|
||||||
var insn: AbstractInsnNode? = insnList.first
|
var insn: AbstractInsnNode? = insnList.first
|
||||||
@@ -774,79 +599,6 @@ class InlineCodegen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateMethodBody(
|
|
||||||
adapter: MethodVisitor,
|
|
||||||
descriptor: FunctionDescriptor,
|
|
||||||
context: MethodContext,
|
|
||||||
expression: KtExpression,
|
|
||||||
jvmMethodSignature: JvmMethodSignature,
|
|
||||||
codegen: ExpressionCodegen,
|
|
||||||
lambdaInfo: ExpressionLambda?
|
|
||||||
): SMAP {
|
|
||||||
val isLambda = lambdaInfo != null
|
|
||||||
val state = codegen.state
|
|
||||||
|
|
||||||
// Wrapping for preventing marking actual parent codegen as containing reified markers
|
|
||||||
val parentCodegen = FakeMemberCodegen(
|
|
||||||
codegen.parentCodegen, expression, context.parentContext as FieldOwnerContext<*>,
|
|
||||||
if (isLambda)
|
|
||||||
codegen.parentCodegen.className
|
|
||||||
else
|
|
||||||
state.typeMapper.mapImplementationOwner(descriptor).internalName
|
|
||||||
)
|
|
||||||
|
|
||||||
val strategy: FunctionGenerationStrategy
|
|
||||||
if (expression is KtCallableReferenceExpression) {
|
|
||||||
val callableReferenceExpression = expression
|
|
||||||
val receiverExpression = callableReferenceExpression.receiverExpression
|
|
||||||
val receiverType = if (receiverExpression != null && codegen.bindingContext.getType(receiverExpression) != null)
|
|
||||||
codegen.state.typeMapper.mapType(codegen.bindingContext.getType(receiverExpression)!!)
|
|
||||||
else
|
|
||||||
null
|
|
||||||
|
|
||||||
if (isLambda && lambdaInfo!!.isPropertyReference) {
|
|
||||||
val asmType = state.typeMapper.mapClass(lambdaInfo.classDescriptor)
|
|
||||||
val info = lambdaInfo.propertyReferenceInfo
|
|
||||||
strategy = PropertyReferenceCodegen.PropertyReferenceGenerationStrategy(
|
|
||||||
true, info!!.getFunction, info.target, asmType, receiverType,
|
|
||||||
lambdaInfo.functionWithBodyOrCallableReference, state, true)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
strategy = FunctionReferenceGenerationStrategy(
|
|
||||||
state,
|
|
||||||
descriptor,
|
|
||||||
callableReferenceExpression.callableReference
|
|
||||||
.getResolvedCallWithAssert(codegen.bindingContext),
|
|
||||||
receiverType, null,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (expression is KtFunctionLiteral) {
|
|
||||||
strategy = ClosureGenerationStrategy(state, expression as KtDeclarationWithBody)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
strategy = FunctionGenerationStrategy.FunctionDefault(state, expression as KtDeclarationWithBody)
|
|
||||||
}
|
|
||||||
|
|
||||||
FunctionCodegen.generateMethodBody(adapter, descriptor, context, jvmMethodSignature, strategy, parentCodegen)
|
|
||||||
|
|
||||||
if (isLambda) {
|
|
||||||
codegen.propagateChildReifiedTypeParametersUsages(parentCodegen.reifiedTypeParametersUsages)
|
|
||||||
}
|
|
||||||
|
|
||||||
return createSMAPWithDefaultMapping(expression, parentCodegen.orCreateSourceMapper.resultMappings)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createSMAPWithDefaultMapping(
|
|
||||||
declaration: KtExpression,
|
|
||||||
mappings: List<FileMapping>
|
|
||||||
): SMAP {
|
|
||||||
val containingFile = declaration.containingFile
|
|
||||||
CodegenUtil.getLineNumberForElement(containingFile, true) ?: error("Couldn't extract line count in " + containingFile)
|
|
||||||
|
|
||||||
return SMAP(mappings)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*descriptor is null for captured vars*/
|
/*descriptor is null for captured vars*/
|
||||||
private fun shouldPutGeneralValue(type: Type, stackValue: StackValue): Boolean {
|
private fun shouldPutGeneralValue(type: Type, stackValue: StackValue): Boolean {
|
||||||
@@ -905,38 +657,7 @@ class InlineCodegen(
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getContext(
|
|
||||||
descriptor: DeclarationDescriptor, state: GenerationState, sourceFile: KtFile?
|
|
||||||
): CodegenContext<*> {
|
|
||||||
if (descriptor is PackageFragmentDescriptor) {
|
|
||||||
return PackageContext(descriptor, state.rootContext, null, sourceFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
val container = descriptor.containingDeclaration ?: error("No container for descriptor: " + descriptor)
|
|
||||||
val parent = getContext(
|
|
||||||
container,
|
|
||||||
state,
|
|
||||||
sourceFile
|
|
||||||
)
|
|
||||||
|
|
||||||
if (descriptor is ScriptDescriptor) {
|
|
||||||
val earlierScripts = state.replSpecific.earlierScriptsForReplInterpreter
|
|
||||||
return parent.intoScript(
|
|
||||||
descriptor,
|
|
||||||
earlierScripts ?: emptyList(),
|
|
||||||
descriptor as ClassDescriptor, state.typeMapper
|
|
||||||
)
|
|
||||||
}
|
|
||||||
else if (descriptor is ClassDescriptor) {
|
|
||||||
val kind = if (DescriptorUtils.isInterface(descriptor)) OwnerKind.DEFAULT_IMPLS else OwnerKind.IMPLEMENTATION
|
|
||||||
return parent.intoClass(descriptor, kind, state)
|
|
||||||
}
|
|
||||||
else if (descriptor is FunctionDescriptor) {
|
|
||||||
return parent.intoFunction(descriptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
throw IllegalStateException("Couldn't build context for " + descriptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createNestedSourceMapper(nodeAndSmap: SMAPAndMethodNode, parent: SourceMapper): SourceMapper {
|
fun createNestedSourceMapper(nodeAndSmap: SMAPAndMethodNode, parent: SourceMapper): SourceMapper {
|
||||||
return NestedSourceMapper(parent, nodeAndSmap.sortedRanges, nodeAndSmap.classSMAP.sourceInfo)
|
return NestedSourceMapper(parent, nodeAndSmap.sortedRanges, nodeAndSmap.classSMAP.sourceInfo)
|
||||||
@@ -956,3 +677,6 @@ class InlineCodegen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val BaseExpressionCodegen.v: InstructionAdapter
|
||||||
|
get() = visitor
|
||||||
+13
-10
@@ -22,10 +22,9 @@ import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
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.calls.model.ResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||||
import org.jetbrains.org.objectweb.asm.Label
|
import org.jetbrains.org.objectweb.asm.Label
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||||
@@ -33,7 +32,8 @@ import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
|||||||
class InlineCodegenForDefaultBody(
|
class InlineCodegenForDefaultBody(
|
||||||
function: FunctionDescriptor,
|
function: FunctionDescriptor,
|
||||||
codegen: ExpressionCodegen,
|
codegen: ExpressionCodegen,
|
||||||
val state: GenerationState
|
val state: GenerationState,
|
||||||
|
private val sourceCompilerForInline: SourceCompilerForInline
|
||||||
) : CallGenerator() {
|
) : CallGenerator() {
|
||||||
|
|
||||||
private val sourceMapper: SourceMapper = codegen.parentCodegen.orCreateSourceMapper
|
private val sourceMapper: SourceMapper = codegen.parentCodegen.orCreateSourceMapper
|
||||||
@@ -45,12 +45,12 @@ class InlineCodegenForDefaultBody(
|
|||||||
function.original
|
function.original
|
||||||
|
|
||||||
|
|
||||||
private val context = InlineCodegen.getContext(
|
init {
|
||||||
functionDescriptor, state,
|
sourceCompilerForInline.initializeInlineFunctionContext(functionDescriptor)
|
||||||
DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)?.containingFile as? KtFile
|
}
|
||||||
)
|
|
||||||
|
|
||||||
private val jvmSignature = state.typeMapper.mapSignatureWithGeneric(functionDescriptor, context.contextKind)
|
|
||||||
|
private val jvmSignature: JvmMethodGenericSignature
|
||||||
|
|
||||||
private val methodStartLabel = Label()
|
private val methodStartLabel = Label()
|
||||||
|
|
||||||
@@ -58,6 +58,9 @@ class InlineCodegenForDefaultBody(
|
|||||||
assert(InlineUtil.isInline(function)) {
|
assert(InlineUtil.isInline(function)) {
|
||||||
"InlineCodegen can inline only inline functions and array constructors: " + function
|
"InlineCodegen can inline only inline functions and array constructors: " + function
|
||||||
}
|
}
|
||||||
|
sourceCompilerForInline.initializeInlineFunctionContext(functionDescriptor)
|
||||||
|
jvmSignature = state.typeMapper.mapSignatureWithGeneric(functionDescriptor, sourceCompilerForInline.contextKind)
|
||||||
|
|
||||||
InlineCodegen.reportIncrementalInfo(functionDescriptor, codegen.context.functionDescriptor.original, jvmSignature, state)
|
InlineCodegen.reportIncrementalInfo(functionDescriptor, codegen.context.functionDescriptor.original, jvmSignature, state)
|
||||||
|
|
||||||
//InlineCodegenForDefaultBody created just after visitCode call
|
//InlineCodegenForDefaultBody created just after visitCode call
|
||||||
@@ -65,7 +68,7 @@ class InlineCodegenForDefaultBody(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun genCallInner(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen) {
|
override fun genCallInner(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen) {
|
||||||
val nodeAndSmap = InlineCodegen.createMethodNode(functionDescriptor, jvmSignature, codegen, context, callDefault, null)
|
val nodeAndSmap = InlineCodegen.createInlineMethodNode(functionDescriptor, jvmSignature, codegen, callDefault, null, state, sourceCompilerForInline)
|
||||||
val childSourceMapper = InlineCodegen.createNestedSourceMapper(nodeAndSmap, sourceMapper)
|
val childSourceMapper = InlineCodegen.createNestedSourceMapper(nodeAndSmap, sourceMapper)
|
||||||
|
|
||||||
val node = nodeAndSmap.node
|
val node = nodeAndSmap.node
|
||||||
@@ -84,7 +87,7 @@ class InlineCodegenForDefaultBody(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
transformedMethod.accept(MethodBodyVisitor(codegen.v))
|
transformedMethod.accept(MethodBodyVisitor(codegen.visitor))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun genValueAndPut(valueParameterDescriptor: ValueParameterDescriptor, argumentExpression: KtExpression, parameterType: Type, parameterIndex: Int) {
|
override fun genValueAndPut(valueParameterDescriptor: ValueParameterDescriptor, argumentExpression: KtExpression, parameterType: Type, parameterIndex: Int) {
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : LabelOwner {
|
|||||||
|
|
||||||
lateinit var node: SMAPAndMethodNode
|
lateinit var node: SMAPAndMethodNode
|
||||||
|
|
||||||
abstract fun generateLambdaBody(codegen: ExpressionCodegen, reifiedTypeInliner: ReifiedTypeInliner)
|
abstract fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner)
|
||||||
|
|
||||||
fun addAllParameters(remapper: FieldRemapper): Parameters {
|
fun addAllParameters(remapper: FieldRemapper): Parameters {
|
||||||
val builder = ParametersBuilder.initializeBuilderFrom(AsmTypes.OBJECT_TYPE, invokeMethod.descriptor, this)
|
val builder = ParametersBuilder.initializeBuilderFrom(AsmTypes.OBJECT_TYPE, invokeMethod.descriptor, this)
|
||||||
@@ -105,8 +105,8 @@ class DefaultLambda(
|
|||||||
|
|
||||||
override fun isMyLabel(name: String): Boolean = false
|
override fun isMyLabel(name: String): Boolean = false
|
||||||
|
|
||||||
override fun generateLambdaBody(codegen: ExpressionCodegen, reifiedTypeInliner: ReifiedTypeInliner) {
|
override fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner) {
|
||||||
val classReader = buildClassReaderByInternalName(codegen.state, lambdaClassType.internalName)
|
val classReader = buildClassReaderByInternalName(sourceCompiler.state, lambdaClassType.internalName)
|
||||||
var isPropertyReference = false
|
var isPropertyReference = false
|
||||||
var isFunctionReference = false
|
var isFunctionReference = false
|
||||||
classReader.accept(object: ClassVisitor(API){
|
classReader.accept(object: ClassVisitor(API){
|
||||||
@@ -153,7 +153,7 @@ class DefaultLambda(
|
|||||||
|
|
||||||
invokeMethod = Method(
|
invokeMethod = Method(
|
||||||
(if (isPropertyReference) OperatorNameConventions.GET else OperatorNameConventions.INVOKE).asString(),
|
(if (isPropertyReference) OperatorNameConventions.GET else OperatorNameConventions.INVOKE).asString(),
|
||||||
codegen.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod.descriptor
|
sourceCompiler.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod.descriptor
|
||||||
)
|
)
|
||||||
|
|
||||||
node = getMethodNode(
|
node = getMethodNode(
|
||||||
@@ -260,24 +260,17 @@ class ExpressionLambda(
|
|||||||
val isPropertyReference: Boolean
|
val isPropertyReference: Boolean
|
||||||
get() = propertyReferenceInfo != null
|
get() = propertyReferenceInfo != null
|
||||||
|
|
||||||
override fun generateLambdaBody(codegen: ExpressionCodegen, reifiedTypeInliner: ReifiedTypeInliner) {
|
override fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner) {
|
||||||
val closureContext =
|
|
||||||
if (isPropertyReference)
|
|
||||||
codegen.getContext().intoAnonymousClass(classDescriptor, codegen, OwnerKind.IMPLEMENTATION)
|
|
||||||
else
|
|
||||||
codegen.getContext().intoClosure(invokeMethodDescriptor, codegen, typeMapper)
|
|
||||||
val context = closureContext.intoInlinedLambda(invokeMethodDescriptor, isCrossInline, isPropertyReference)
|
|
||||||
|
|
||||||
val jvmMethodSignature = typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor)
|
val jvmMethodSignature = typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor)
|
||||||
val asmMethod = jvmMethodSignature.asmMethod
|
val asmMethod = jvmMethodSignature.asmMethod
|
||||||
val methodNode = MethodNode(
|
val methodNode = MethodNode(
|
||||||
API, AsmUtil.getMethodAsmFlags(invokeMethodDescriptor, context.contextKind, codegen.state),
|
API, AsmUtil.getMethodAsmFlags(invokeMethodDescriptor, OwnerKind.IMPLEMENTATION, sourceCompiler.state),
|
||||||
asmMethod.name, asmMethod.descriptor, null, null
|
asmMethod.name, asmMethod.descriptor, null, null
|
||||||
)
|
)
|
||||||
|
|
||||||
node = wrapWithMaxLocalCalc(methodNode).let { adapter ->
|
node = wrapWithMaxLocalCalc(methodNode).let { adapter ->
|
||||||
val smap = InlineCodegen.generateMethodBody(
|
val smap = sourceCompiler.generateLambdaBody(
|
||||||
adapter, invokeMethodDescriptor, context, functionWithBodyOrCallableReference, jvmMethodSignature, codegen, this
|
adapter, jvmMethodSignature, this
|
||||||
)
|
)
|
||||||
adapter.visitMaxs(-1, -1)
|
adapter.visitMaxs(-1, -1)
|
||||||
SMAPAndMethodNode(methodNode, smap)
|
SMAPAndMethodNode(methodNode, smap)
|
||||||
|
|||||||
@@ -0,0 +1,365 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 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.backend.common.CodegenUtil
|
||||||
|
import org.jetbrains.kotlin.codegen.*
|
||||||
|
import org.jetbrains.kotlin.codegen.context.*
|
||||||
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
|
import org.jetbrains.org.objectweb.asm.Label
|
||||||
|
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||||
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||||
|
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
||||||
|
import org.jetbrains.org.objectweb.asm.tree.LabelNode
|
||||||
|
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||||
|
import java.util.HashMap
|
||||||
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
|
class SourceCompilerForInline(private val codegen: ExpressionCodegen) {
|
||||||
|
|
||||||
|
val state = codegen.state
|
||||||
|
|
||||||
|
private var context by Delegates.notNull<CodegenContext<*>>()
|
||||||
|
|
||||||
|
val contextKind
|
||||||
|
get () = context.contextKind
|
||||||
|
|
||||||
|
val inlineCallSiteInfo: InlineCallSiteInfo
|
||||||
|
get() {
|
||||||
|
var context = codegen.getContext()
|
||||||
|
var parentCodegen = codegen.parentCodegen
|
||||||
|
while (context is InlineLambdaContext) {
|
||||||
|
val closureContext = context.getParentContext()
|
||||||
|
assert(closureContext is ClosureContext) { "Parent context of inline lambda should be closure context" }
|
||||||
|
assert(closureContext.parentContext is MethodContext) { "Closure context should appear in method context" }
|
||||||
|
context = closureContext.parentContext as MethodContext
|
||||||
|
assert(parentCodegen is FakeMemberCodegen) { "Parent codegen of inlined lambda should be FakeMemberCodegen" }
|
||||||
|
parentCodegen = (parentCodegen as FakeMemberCodegen).delegate
|
||||||
|
}
|
||||||
|
|
||||||
|
val signature = codegen.state.typeMapper.mapSignatureSkipGeneric(context.functionDescriptor, context.contextKind)
|
||||||
|
return InlineCallSiteInfo(
|
||||||
|
parentCodegen.className, signature.asmMethod.name, signature.asmMethod.descriptor
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val lazySourceMapper
|
||||||
|
get() = codegen.parentCodegen.orCreateSourceMapper
|
||||||
|
|
||||||
|
fun generateLambdaBody(adapter: MethodVisitor,
|
||||||
|
jvmMethodSignature: JvmMethodSignature,
|
||||||
|
lambdaInfo: ExpressionLambda): SMAP {
|
||||||
|
val invokeMethodDescriptor = lambdaInfo.invokeMethodDescriptor
|
||||||
|
val closureContext =
|
||||||
|
if (lambdaInfo.isPropertyReference)
|
||||||
|
codegen.getContext().intoAnonymousClass(lambdaInfo.classDescriptor, codegen, OwnerKind.IMPLEMENTATION)
|
||||||
|
else
|
||||||
|
codegen.getContext().intoClosure(invokeMethodDescriptor, codegen, state.typeMapper)
|
||||||
|
val context = closureContext.intoInlinedLambda(invokeMethodDescriptor, lambdaInfo.isCrossInline, lambdaInfo.isPropertyReference)
|
||||||
|
|
||||||
|
return generateMethodBody(
|
||||||
|
adapter, invokeMethodDescriptor, context,
|
||||||
|
lambdaInfo.functionWithBodyOrCallableReference,
|
||||||
|
jvmMethodSignature, lambdaInfo
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateMethodBody(
|
||||||
|
adapter: MethodVisitor,
|
||||||
|
descriptor: FunctionDescriptor,
|
||||||
|
context: MethodContext,
|
||||||
|
expression: KtExpression,
|
||||||
|
jvmMethodSignature: JvmMethodSignature,
|
||||||
|
lambdaInfo: ExpressionLambda?
|
||||||
|
): SMAP {
|
||||||
|
val isLambda = lambdaInfo != null
|
||||||
|
|
||||||
|
// Wrapping for preventing marking actual parent codegen as containing reified markers
|
||||||
|
val parentCodegen = FakeMemberCodegen(
|
||||||
|
codegen.parentCodegen, expression, context.parentContext as FieldOwnerContext<*>,
|
||||||
|
if (isLambda)
|
||||||
|
codegen.parentCodegen.className
|
||||||
|
else
|
||||||
|
state.typeMapper.mapImplementationOwner(descriptor).internalName
|
||||||
|
)
|
||||||
|
|
||||||
|
val strategy = when (expression) {
|
||||||
|
is KtCallableReferenceExpression -> {
|
||||||
|
val callableReferenceExpression = expression
|
||||||
|
val receiverExpression = callableReferenceExpression.receiverExpression
|
||||||
|
val receiverType = if (receiverExpression != null && state.bindingContext.getType(receiverExpression) != null)
|
||||||
|
state.typeMapper.mapType(state.bindingContext.getType(receiverExpression)!!)
|
||||||
|
else
|
||||||
|
null
|
||||||
|
|
||||||
|
if (isLambda && lambdaInfo!!.isPropertyReference) {
|
||||||
|
val asmType = state.typeMapper.mapClass(lambdaInfo.classDescriptor)
|
||||||
|
val info = lambdaInfo.propertyReferenceInfo
|
||||||
|
PropertyReferenceCodegen.PropertyReferenceGenerationStrategy(
|
||||||
|
true, info!!.getFunction, info.target, asmType, receiverType,
|
||||||
|
lambdaInfo.functionWithBodyOrCallableReference, state, true)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
FunctionReferenceGenerationStrategy(
|
||||||
|
state,
|
||||||
|
descriptor,
|
||||||
|
callableReferenceExpression.callableReference
|
||||||
|
.getResolvedCallWithAssert(state.bindingContext),
|
||||||
|
receiverType, null,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is KtFunctionLiteral -> ClosureGenerationStrategy(state, expression as KtDeclarationWithBody)
|
||||||
|
else -> FunctionGenerationStrategy.FunctionDefault(state, expression as KtDeclarationWithBody)
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionCodegen.generateMethodBody(adapter, descriptor, context, jvmMethodSignature, strategy, parentCodegen)
|
||||||
|
|
||||||
|
if (isLambda) {
|
||||||
|
codegen.propagateChildReifiedTypeParametersUsages(parentCodegen.reifiedTypeParametersUsages)
|
||||||
|
}
|
||||||
|
|
||||||
|
return createSMAPWithDefaultMapping(expression, parentCodegen.orCreateSourceMapper.resultMappings)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun createSMAPWithDefaultMapping(
|
||||||
|
declaration: KtExpression,
|
||||||
|
mappings: List<FileMapping>
|
||||||
|
): SMAP {
|
||||||
|
val containingFile = declaration.containingFile
|
||||||
|
CodegenUtil.getLineNumberForElement(containingFile, true) ?: error("Couldn't extract line count in " + containingFile)
|
||||||
|
|
||||||
|
return SMAP(mappings)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
private class FakeMemberCodegen(
|
||||||
|
internal val delegate: MemberCodegen<*>,
|
||||||
|
declaration: KtElement,
|
||||||
|
codegenContext: FieldOwnerContext<*>,
|
||||||
|
private val className: String
|
||||||
|
) : MemberCodegen<KtPureElement>(delegate as MemberCodegen<KtPureElement>, declaration, codegenContext) {
|
||||||
|
|
||||||
|
override fun generateDeclaration() {
|
||||||
|
throw IllegalStateException()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun generateBody() {
|
||||||
|
throw IllegalStateException()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun generateKotlinMetadataAnnotation() {
|
||||||
|
throw IllegalStateException()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getInlineNameGenerator(): NameGenerator {
|
||||||
|
return delegate.inlineNameGenerator
|
||||||
|
}
|
||||||
|
override //TODO: obtain name from context
|
||||||
|
fun getClassName(): String {
|
||||||
|
return className
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun doCreateMethodNodeFromSource(
|
||||||
|
callableDescriptor: FunctionDescriptor,
|
||||||
|
jvmSignature: JvmMethodSignature,
|
||||||
|
callDefault: Boolean,
|
||||||
|
asmMethod: Method
|
||||||
|
): SMAPAndMethodNode {
|
||||||
|
val element = DescriptorToSourceUtils.descriptorToDeclaration(callableDescriptor)
|
||||||
|
|
||||||
|
if (!(element is KtNamedFunction || element is KtPropertyAccessor)) {
|
||||||
|
throw IllegalStateException("Couldn't find declaration for function " + callableDescriptor)
|
||||||
|
}
|
||||||
|
val inliningFunction = element as KtDeclarationWithBody?
|
||||||
|
|
||||||
|
val node = MethodNode(
|
||||||
|
API,
|
||||||
|
AsmUtil.getMethodAsmFlags(callableDescriptor, context.contextKind, state) or if (callDefault) Opcodes.ACC_STATIC else 0,
|
||||||
|
asmMethod.name,
|
||||||
|
asmMethod.descriptor, null, null
|
||||||
|
)
|
||||||
|
|
||||||
|
//for maxLocals calculation
|
||||||
|
val maxCalcAdapter = wrapWithMaxLocalCalc(node)
|
||||||
|
val parentContext = context.parentContext ?: error("Context has no parent: " + context)
|
||||||
|
val methodContext = parentContext.intoFunction(callableDescriptor)
|
||||||
|
|
||||||
|
val smap: SMAP
|
||||||
|
if (callDefault) {
|
||||||
|
val implementationOwner = state.typeMapper.mapImplementationOwner(callableDescriptor)
|
||||||
|
val parentCodegen = FakeMemberCodegen(
|
||||||
|
codegen.parentCodegen, inliningFunction!!, methodContext.parentContext as FieldOwnerContext<*>,
|
||||||
|
implementationOwner.internalName
|
||||||
|
)
|
||||||
|
if (element !is KtNamedFunction) {
|
||||||
|
throw IllegalStateException("Property accessors with default parameters not supported " + callableDescriptor)
|
||||||
|
}
|
||||||
|
FunctionCodegen.generateDefaultImplBody(
|
||||||
|
methodContext, callableDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT,
|
||||||
|
inliningFunction as KtNamedFunction?, parentCodegen, asmMethod
|
||||||
|
)
|
||||||
|
smap = createSMAPWithDefaultMapping(inliningFunction, parentCodegen.orCreateSourceMapper.resultMappings)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
smap = generateMethodBody(maxCalcAdapter, callableDescriptor, methodContext, inliningFunction!!, jvmSignature, null)
|
||||||
|
}
|
||||||
|
maxCalcAdapter.visitMaxs(-1, -1)
|
||||||
|
maxCalcAdapter.visitEnd()
|
||||||
|
|
||||||
|
return SMAPAndMethodNode(node, smap)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun generateAndInsertFinallyBlocks(
|
||||||
|
intoNode: MethodNode,
|
||||||
|
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
|
||||||
|
offsetForFinallyLocalVar: Int
|
||||||
|
) {
|
||||||
|
if (!codegen.hasFinallyBlocks()) return
|
||||||
|
|
||||||
|
val extensionPoints = HashMap<AbstractInsnNode, MethodInliner.PointForExternalFinallyBlocks>()
|
||||||
|
for (insertPoint in insertPoints) {
|
||||||
|
extensionPoints.put(insertPoint.beforeIns, insertPoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
val processor = DefaultProcessor(intoNode, offsetForFinallyLocalVar)
|
||||||
|
|
||||||
|
var curFinallyDepth = 0
|
||||||
|
var curInstr: AbstractInsnNode? = intoNode.instructions.first
|
||||||
|
while (curInstr != null) {
|
||||||
|
processor.processInstruction(curInstr, true)
|
||||||
|
if (isFinallyStart(curInstr)) {
|
||||||
|
//TODO depth index calc could be more precise
|
||||||
|
curFinallyDepth = getConstant(curInstr.previous)
|
||||||
|
}
|
||||||
|
|
||||||
|
val extension = extensionPoints[curInstr]
|
||||||
|
if (extension != null) {
|
||||||
|
val start = Label()
|
||||||
|
|
||||||
|
val finallyNode = createEmptyMethodNode()
|
||||||
|
finallyNode.visitLabel(start)
|
||||||
|
|
||||||
|
val finallyCodegen = ExpressionCodegen(finallyNode, codegen.frameMap, codegen.returnType,
|
||||||
|
codegen.getContext(), codegen.state, codegen.parentCodegen)
|
||||||
|
finallyCodegen.addBlockStackElementsForNonLocalReturns(codegen.blockStackElements, curFinallyDepth)
|
||||||
|
|
||||||
|
val frameMap = finallyCodegen.frameMap
|
||||||
|
val mark = frameMap.mark()
|
||||||
|
var marker = -1
|
||||||
|
val intervals = processor.localVarsMetaInfo.currentIntervals
|
||||||
|
for (interval in intervals) {
|
||||||
|
marker = Math.max(interval.node.index + 1, marker)
|
||||||
|
}
|
||||||
|
while (frameMap.currentSize < Math.max(processor.nextFreeLocalIndex, offsetForFinallyLocalVar + marker)) {
|
||||||
|
frameMap.enterTemp(Type.INT_TYPE)
|
||||||
|
}
|
||||||
|
|
||||||
|
finallyCodegen.generateFinallyBlocksIfNeeded(extension.returnType, extension.finallyIntervalEnd.label)
|
||||||
|
|
||||||
|
//Exception table for external try/catch/finally blocks will be generated in original codegen after exiting this method
|
||||||
|
insertNodeBefore(finallyNode, intoNode, curInstr)
|
||||||
|
|
||||||
|
val splitBy = SimpleInterval(start.info as LabelNode, extension.finallyIntervalEnd)
|
||||||
|
processor.tryBlocksMetaInfo.splitCurrentIntervals(splitBy, true)
|
||||||
|
|
||||||
|
//processor.getLocalVarsMetaInfo().splitAndRemoveIntervalsFromCurrents(splitBy);
|
||||||
|
|
||||||
|
mark.dropTo()
|
||||||
|
}
|
||||||
|
|
||||||
|
curInstr = curInstr.next
|
||||||
|
}
|
||||||
|
|
||||||
|
processor.substituteTryBlockNodes(intoNode)
|
||||||
|
|
||||||
|
//processor.substituteLocalVarTable(intoNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isCallInsideSameModuleAsDeclared(functionDescriptor: FunctionDescriptor) : Boolean {
|
||||||
|
return JvmCodegenUtil.isCallInsideSameModuleAsDeclared(functionDescriptor, codegen.getContext(), codegen.state.outDirectory)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isFinallyMarkerRequired(): Boolean = isFinallyMarkerRequired(codegen.getContext())
|
||||||
|
|
||||||
|
|
||||||
|
val compilationContextDescriptor
|
||||||
|
get() = codegen.getContext().contextDescriptor
|
||||||
|
|
||||||
|
val compilationContextFunctionDescriptor
|
||||||
|
get() = codegen.getContext().functionDescriptor
|
||||||
|
|
||||||
|
fun getLabelOwnerDescriptor(): CallableMemberDescriptor {
|
||||||
|
val context = codegen.getContext()
|
||||||
|
val parentContext = context.parentContext
|
||||||
|
if (parentContext is ClosureContext && parentContext.originalSuspendLambdaDescriptor != null) {
|
||||||
|
return parentContext.originalSuspendLambdaDescriptor!!
|
||||||
|
}
|
||||||
|
return context.contextDescriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
fun initializeInlineFunctionContext(functionDescriptor: FunctionDescriptor) {
|
||||||
|
context = getContext(functionDescriptor, state, DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)?.containingFile as? KtFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun getContext(
|
||||||
|
descriptor: DeclarationDescriptor, state: GenerationState, sourceFile: KtFile?
|
||||||
|
): CodegenContext<*> {
|
||||||
|
if (descriptor is PackageFragmentDescriptor) {
|
||||||
|
return PackageContext(descriptor, state.rootContext, null, sourceFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
val container = descriptor.containingDeclaration ?: error("No container for descriptor: " + descriptor)
|
||||||
|
val parent = getContext(
|
||||||
|
container,
|
||||||
|
state,
|
||||||
|
sourceFile
|
||||||
|
)
|
||||||
|
|
||||||
|
if (descriptor is ScriptDescriptor) {
|
||||||
|
val earlierScripts = state.replSpecific.earlierScriptsForReplInterpreter
|
||||||
|
return parent.intoScript(
|
||||||
|
descriptor,
|
||||||
|
earlierScripts ?: emptyList(),
|
||||||
|
descriptor as ClassDescriptor, state.typeMapper
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else if (descriptor is ClassDescriptor) {
|
||||||
|
val kind = if (DescriptorUtils.isInterface(descriptor)) OwnerKind.DEFAULT_IMPLS else OwnerKind.IMPLEMENTATION
|
||||||
|
return parent.intoClass(descriptor, kind, state)
|
||||||
|
}
|
||||||
|
else if (descriptor is FunctionDescriptor) {
|
||||||
|
return parent.intoFunction(descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
throw IllegalStateException("Couldn't build context for " + descriptor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen.inline
|
|||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||||
|
import org.jetbrains.kotlin.codegen.BaseExpressionCodegen
|
||||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||||
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
|
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
|
||||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||||
@@ -502,7 +503,7 @@ internal fun isSpecialEnumMethod(functionDescriptor: FunctionDescriptor): Boolea
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun createSpecialEnumMethodBody(
|
internal fun createSpecialEnumMethodBody(
|
||||||
codegen: ExpressionCodegen,
|
codegen: BaseExpressionCodegen,
|
||||||
name: String,
|
name: String,
|
||||||
type: KotlinType,
|
type: KotlinType,
|
||||||
typeMapper: KotlinTypeMapper
|
typeMapper: KotlinTypeMapper
|
||||||
@@ -511,7 +512,7 @@ internal fun createSpecialEnumMethodBody(
|
|||||||
val invokeType = typeMapper.mapType(type)
|
val invokeType = typeMapper.mapType(type)
|
||||||
val desc = getSpecialEnumFunDescriptor(invokeType, isValueOf)
|
val desc = getSpecialEnumFunDescriptor(invokeType, isValueOf)
|
||||||
val node = MethodNode(API, Opcodes.ACC_STATIC, "fake", desc, null, null)
|
val node = MethodNode(API, Opcodes.ACC_STATIC, "fake", desc, null, null)
|
||||||
codegen.putReifiedOperationMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.OperationKind.ENUM_REIFIED, InstructionAdapter(node))
|
ExpressionCodegen.putReifiedOperationMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.OperationKind.ENUM_REIFIED, InstructionAdapter(node), codegen)
|
||||||
if (isValueOf) {
|
if (isValueOf) {
|
||||||
node.visitInsn(Opcodes.ACONST_NULL)
|
node.visitInsn(Opcodes.ACONST_NULL)
|
||||||
node.visitVarInsn(Opcodes.ALOAD, 0)
|
node.visitVarInsn(Opcodes.ALOAD, 0)
|
||||||
@@ -569,7 +570,7 @@ fun FunctionDescriptor.getClassFilePath(typeMapper: KotlinTypeMapper, cache: Inc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class InlineOnlySmapSkipper(codegen: ExpressionCodegen) {
|
class InlineOnlySmapSkipper(codegen: BaseExpressionCodegen) {
|
||||||
|
|
||||||
private val callLineNumber = codegen.lastLineNumber
|
private val callLineNumber = codegen.lastLineNumber
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user