Introduce BaseExpressionCodegen and SourceCompilerForInline,

switch CallGenerator and InlineCodegen to them

~base
This commit is contained in:
Mikhael Bogdanov
2017-06-12 15:20:20 +02:00
parent 3ae214b97a
commit 8dc1b8f95f
7 changed files with 501 additions and 350 deletions
@@ -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.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;
final KotlinTypeMapper typeMapper;
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
@Override
public void markLineNumberAfterInlineIfNeeded() {
if (!shouldMarkLineNumbers) {
//if it used as general argument
@@ -1366,6 +1367,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
}
@Override
public int getLastLineNumber() {
return myLastLineNumber;
}
@@ -2286,10 +2288,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
FunctionDescriptor original =
unwrapInitialSignatureDescriptor(DescriptorUtils.unwrapFakeOverride((FunctionDescriptor) descriptor.getOriginal()));
if (isDefaultCompilation) {
return new InlineCodegenForDefaultBody(original, this, state);
return new InlineCodegenForDefaultBody(original, this, state, new SourceCompilerForInline(this));
}
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(
@NotNull KotlinType type, @NotNull ReifiedTypeInliner.OperationKind operationKind
) {
putReifiedOperationMarkerIfTypeIsReifiedParameter(type, operationKind, v);
putReifiedOperationMarkerIfTypeIsReifiedParameter(type, operationKind, v, this);
}
public void putReifiedOperationMarkerIfTypeIsReifiedParameter(
@NotNull KotlinType type, @NotNull ReifiedTypeInliner.OperationKind operationKind, @NotNull InstructionAdapter v
public static void putReifiedOperationMarkerIfTypeIsReifiedParameter(
@NotNull KotlinType type, @NotNull ReifiedTypeInliner.OperationKind operationKind, @NotNull InstructionAdapter v,
@NotNull BaseExpressionCodegen codegen
) {
Pair<TypeParameterDescriptor, ReificationArgument> typeParameterAndReificationArgument = extractReificationArgument(type);
if (typeParameterAndReificationArgument != null && typeParameterAndReificationArgument.getFirst().isReified()) {
TypeParameterDescriptor typeParameterDescriptor = typeParameterAndReificationArgument.getFirst();
if (typeParameterDescriptor.getContainingDeclaration() != context.getContextDescriptor()) {
parentCodegen.getReifiedTypeParametersUsages().
addUsedReifiedParameter(typeParameterDescriptor.getName().asString());
}
codegen.consumeReifiedOperationMarker(typeParameterDescriptor);
v.iconst(operationKind.getId());
v.visitLdcInsn(typeParameterAndReificationArgument.getSecond().asString());
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) {
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();
}
@Override
@NotNull
public FrameMap getFrameMap() {
return myFrameMap;
@@ -4213,6 +4215,7 @@ The "returned" value of try expression with no finally is either the last expres
return context;
}
@Override
@NotNull
public NameGenerator 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);
}
@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.util.ArrayUtil
import org.jetbrains.kotlin.backend.common.CodegenUtil
import org.jetbrains.kotlin.builtins.BuiltInsPackageFragment
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags
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.isBuiltInSuspendCoroutineOrReturnInJvm
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.DescriptorUtils
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.inline.InlineUtil
import org.jetbrains.kotlin.resolve.inline.InlineUtil.isInlinableParameterExpression
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.JvmMethodSignature
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.ExpressionTypingUtils.isFunctionLiteral
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.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
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.*
class InlineCodegen(
private val codegen: ExpressionCodegen,
private val codegen: BaseExpressionCodegen,
private val state: GenerationState,
function: FunctionDescriptor,
private val callElement: KtElement,
private val typeParameterMappings: TypeParameterMappings
private val typeParameterMappings: TypeParameterMappings,
private val sourceCompiler: SourceCompilerForInline
) : CallGenerator() {
init {
assert(InlineUtil.isInline(function) || InlineUtil.isArrayConstructorWithLambda(function)) {
@@ -89,15 +86,9 @@ class InlineCodegen(
else
function.original
private val context =
getContext(
functionDescriptor, state,
DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)?.containingFile as? KtFile
) as MethodContext
private val jvmSignature: JvmMethodGenericSignature
private val jvmSignature = typeMapper.mapSignatureWithGeneric(functionDescriptor, context.contextKind)
private val isSameModule = JvmCodegenUtil.isCallInsideSameModuleAsDeclared(functionDescriptor, codegen.getContext(), state.outDirectory)
private val isSameModule: Boolean
private val invocationParamBuilder = ParametersBuilder.newBuilder()
@@ -105,7 +96,7 @@ class InlineCodegen(
private var activeLambda: LambdaInfo? = null
private val sourceMapper = codegen.parentCodegen.orCreateSourceMapper
private val sourceMapper = sourceCompiler.lazySourceMapper
private var delayedHiddenWriting: Function0<Unit>? = null
@@ -114,8 +105,12 @@ class InlineCodegen(
private var methodHandleInDefaultMethodIndex = -1
init {
sourceCompiler.initializeInlineFunctionContext(functionDescriptor)
jvmSignature = typeMapper.mapSignatureWithGeneric(functionDescriptor, sourceCompiler.contextKind)
isSameModule = sourceCompiler.isCallInsideSameModuleAsDeclared(functionDescriptor)
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
//track changes for property accessor and @JvmName inline functions/property accessors
if (functionOrAccessorName != functionDescriptor.name.asString()) {
@@ -130,7 +125,7 @@ class InlineCodegen(
callableMethod: Callable,
resolvedCall: ResolvedCall<*>?,
callDefault: Boolean,
codegen: ExpressionCodegen
codegen: BaseExpressionCodegen
) {
if (!state.inlineCycleReporter.enterIntoInlining(resolvedCall)) {
generateStub(resolvedCall, codegen)
@@ -139,7 +134,7 @@ class InlineCodegen(
var nodeAndSmap: SMAPAndMethodNode? = null
try {
nodeAndSmap = createMethodNode(functionDescriptor, jvmSignature, codegen, context, callDefault, resolvedCall)
nodeAndSmap = createInlineMethodNode(functionDescriptor, jvmSignature, codegen, callDefault, resolvedCall, state, sourceCompiler)
endCall(inlineCall(nodeAndSmap, callDefault))
}
catch (e: CompilationException) {
@@ -159,7 +154,7 @@ class InlineCodegen(
private fun throwCompilationException(
nodeAndSmap: SMAPAndMethodNode?, e: Exception, generateNodeText: Boolean
): CompilationException {
val contextDescriptor = codegen.getContext().contextDescriptor
val contextDescriptor = sourceCompiler.compilationContextDescriptor
val element = DescriptorToSourceUtils.descriptorToDeclaration(contextDescriptor)
val node = nodeAndSmap?.node
throw CompilationException(
@@ -171,7 +166,7 @@ class InlineCodegen(
)
}
private fun generateStub(resolvedCall: ResolvedCall<*>?, codegen: ExpressionCodegen) {
private fun generateStub(resolvedCall: ResolvedCall<*>?, codegen: BaseExpressionCodegen) {
leaveTemps()
assert(resolvedCall != null)
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 {
assert(delayedHiddenWriting == null) { "'putHiddenParamsIntoLocals' should be called after 'processAndPutHiddenParameters(true)'" }
val defaultSourceMapper = codegen.parentCodegen.orCreateSourceMapper
val defaultSourceMapper = sourceMapper
defaultSourceMapper.callSiteMarker = CallSiteMarker(codegen.lastLineNumber)
val node = nodeAndSmap.node
if (callDefault) {
@@ -216,7 +211,7 @@ class InlineCodegen(
val info = RootInliningContext(
expressionMap, state, codegen.inlineNameGenerator.subGenerator(jvmSignature.asmMethod.name),
callElement, inlineCallSiteInfo, reifiedTypeInliner, typeParameterMappings
callElement, sourceCompiler.inlineCallSiteInfo, reifiedTypeInliner, typeParameterMappings
)
val inliner = MethodInliner(
@@ -235,15 +230,15 @@ class InlineCodegen(
val result = inliner.doInline(adapter, remapper, true, LabelOwner.SKIP_ALL)
result.reifiedTypeParametersUsages.mergeAll(reificationResult)
val descriptor = getLabelOwnerDescriptor(codegen.getContext())
val descriptor = sourceCompiler.getLabelOwnerDescriptor()
val labels = getDeclarationLabels(DescriptorToSourceUtils.descriptorToDeclaration(descriptor), descriptor)
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
)
removeStaticInitializationTrigger(adapter)
if (!isFinallyMarkerRequired(codegen.getContext())) {
if (!sourceCompiler.isFinallyMarkerRequired()) {
removeFinallyMarkers(adapter)
}
@@ -256,57 +251,9 @@ class InlineCodegen(
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() {
for (info in expressionMap.values) {
info.generateLambdaBody(codegen, 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
info.generateLambdaBody(sourceCompiler, reifiedTypeInliner)
}
}
@@ -376,7 +323,7 @@ class InlineCodegen(
}
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)
}
@@ -519,69 +466,6 @@ class InlineCodegen(
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(
actualArgsWithDeclIndex: List<ArgumentAndDeclIndex>, valueParameterTypes: List<Type>
) {
@@ -605,13 +489,14 @@ class InlineCodegen(
}
}
internal fun createMethodNode(
internal fun createInlineMethodNode(
functionDescriptor: FunctionDescriptor,
jvmSignature: JvmMethodSignature,
codegen: ExpressionCodegen,
context: CodegenContext<*>,
codegen: BaseExpressionCodegen,
callDefault: Boolean,
resolvedCall: ResolvedCall<*>?
resolvedCall: ResolvedCall<*>?,
state: GenerationState,
sourceCompilerForInline: SourceCompilerForInline
): SMAPAndMethodNode {
if (isSpecialEnumMethod(functionDescriptor)) {
val arguments = resolvedCall!!.typeArguments
@@ -620,29 +505,28 @@ class InlineCodegen(
codegen,
functionDescriptor.name.asString(),
arguments.keys.single().defaultType,
codegen.state.typeMapper
state.typeMapper
)
return SMAPAndMethodNode(node, SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1))
}
else if (functionDescriptor.isBuiltInSuspendCoroutineOrReturnInJvm()) {
return SMAPAndMethodNode(
createMethodNodeForSuspendCoroutineOrReturn(
functionDescriptor, codegen.state.typeMapper
functionDescriptor, state.typeMapper
),
SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1)
)
}
val state = codegen.state
val asmMethod = if (callDefault)
state.typeMapper.mapDefaultMethod(functionDescriptor, context.contextKind)
state.typeMapper.mapDefaultMethod(functionDescriptor, sourceCompilerForInline.contextKind)
else
jvmSignature.asmMethod
val methodId = MethodId(DescriptorUtils.getFqNameSafe(functionDescriptor.containingDeclaration), asmMethod)
val directMember = getDirectMemberAndCallableFromObject(functionDescriptor)
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
@@ -692,58 +576,7 @@ class InlineCodegen(
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 {
if (callableDescriptor is FictitiousArrayConstructor) return true
@@ -751,14 +584,6 @@ class InlineCodegen(
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) {
val insnList = methodNode.instructions
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*/
private fun shouldPutGeneralValue(type: Type, stackValue: StackValue): Boolean {
@@ -905,38 +657,7 @@ class InlineCodegen(
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 {
return NestedSourceMapper(parent, nodeAndSmap.sortedRanges, nodeAndSmap.classSMAP.sourceInfo)
@@ -956,3 +677,6 @@ class InlineCodegen(
}
}
}
val BaseExpressionCodegen.v: InstructionAdapter
get() = visitor
@@ -22,10 +22,9 @@ 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.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.MethodNode
@@ -33,7 +32,8 @@ import org.jetbrains.org.objectweb.asm.tree.MethodNode
class InlineCodegenForDefaultBody(
function: FunctionDescriptor,
codegen: ExpressionCodegen,
val state: GenerationState
val state: GenerationState,
private val sourceCompilerForInline: SourceCompilerForInline
) : CallGenerator() {
private val sourceMapper: SourceMapper = codegen.parentCodegen.orCreateSourceMapper
@@ -45,12 +45,12 @@ class InlineCodegenForDefaultBody(
function.original
private val context = InlineCodegen.getContext(
functionDescriptor, state,
DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)?.containingFile as? KtFile
)
init {
sourceCompilerForInline.initializeInlineFunctionContext(functionDescriptor)
}
private val jvmSignature = state.typeMapper.mapSignatureWithGeneric(functionDescriptor, context.contextKind)
private val jvmSignature: JvmMethodGenericSignature
private val methodStartLabel = Label()
@@ -58,6 +58,9 @@ class InlineCodegenForDefaultBody(
assert(InlineUtil.isInline(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)
//InlineCodegenForDefaultBody created just after visitCode call
@@ -65,7 +68,7 @@ class InlineCodegenForDefaultBody(
}
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 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) {
@@ -55,7 +55,7 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : LabelOwner {
lateinit var node: SMAPAndMethodNode
abstract fun generateLambdaBody(codegen: ExpressionCodegen, reifiedTypeInliner: ReifiedTypeInliner)
abstract fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner)
fun addAllParameters(remapper: FieldRemapper): Parameters {
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 generateLambdaBody(codegen: ExpressionCodegen, reifiedTypeInliner: ReifiedTypeInliner) {
val classReader = buildClassReaderByInternalName(codegen.state, lambdaClassType.internalName)
override fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner) {
val classReader = buildClassReaderByInternalName(sourceCompiler.state, lambdaClassType.internalName)
var isPropertyReference = false
var isFunctionReference = false
classReader.accept(object: ClassVisitor(API){
@@ -153,7 +153,7 @@ class DefaultLambda(
invokeMethod = Method(
(if (isPropertyReference) OperatorNameConventions.GET else OperatorNameConventions.INVOKE).asString(),
codegen.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod.descriptor
sourceCompiler.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod.descriptor
)
node = getMethodNode(
@@ -260,24 +260,17 @@ class ExpressionLambda(
val isPropertyReference: Boolean
get() = propertyReferenceInfo != null
override fun generateLambdaBody(codegen: ExpressionCodegen, 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)
override fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner) {
val jvmMethodSignature = typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor)
val asmMethod = jvmMethodSignature.asmMethod
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
)
node = wrapWithMaxLocalCalc(methodNode).let { adapter ->
val smap = InlineCodegen.generateMethodBody(
adapter, invokeMethodDescriptor, context, functionWithBodyOrCallableReference, jvmMethodSignature, codegen, this
val smap = sourceCompiler.generateLambdaBody(
adapter, jvmMethodSignature, this
)
adapter.visitMaxs(-1, -1)
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 org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.BaseExpressionCodegen
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
@@ -502,7 +503,7 @@ internal fun isSpecialEnumMethod(functionDescriptor: FunctionDescriptor): Boolea
}
internal fun createSpecialEnumMethodBody(
codegen: ExpressionCodegen,
codegen: BaseExpressionCodegen,
name: String,
type: KotlinType,
typeMapper: KotlinTypeMapper
@@ -511,7 +512,7 @@ internal fun createSpecialEnumMethodBody(
val invokeType = typeMapper.mapType(type)
val desc = getSpecialEnumFunDescriptor(invokeType, isValueOf)
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) {
node.visitInsn(Opcodes.ACONST_NULL)
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