JVM: split inline intrinsics into "needed by JVM_IR" and "not"
or, alternatively, "suspend" and "not".
This commit is contained in:
@@ -20,8 +20,6 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|||||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||||
import org.jetbrains.kotlin.resolve.inline.isInlineOnly
|
import org.jetbrains.kotlin.resolve.inline.isInlineOnly
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
|
||||||
import org.jetbrains.kotlin.types.model.TypeParameterMarker
|
|
||||||
import org.jetbrains.org.objectweb.asm.Label
|
import org.jetbrains.org.objectweb.asm.Label
|
||||||
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
|
||||||
@@ -83,31 +81,17 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
|||||||
AsmUtil.genThrow(codegen.visitor, "java/lang/UnsupportedOperationException", "Call is part of inline cycle: $text")
|
AsmUtil.genThrow(codegen.visitor, "java/lang/UnsupportedOperationException", "Call is part of inline cycle: $text")
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun endCall(result: InlineResult, registerLineNumberAfterwards: Boolean) {
|
fun performInline(inlineDefaultLambdas: Boolean, registerLineNumberAfterwards: Boolean) {
|
||||||
leaveTemps()
|
|
||||||
|
|
||||||
codegen.propagateChildReifiedTypeParametersUsages(result.reifiedTypeParametersUsages)
|
|
||||||
|
|
||||||
state.factory.removeClasses(result.calcClassesToRemove())
|
|
||||||
|
|
||||||
codegen.markLineNumberAfterInlineIfNeeded(registerLineNumberAfterwards)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun performInline(
|
|
||||||
typeArguments: List<TypeParameterMarker>?,
|
|
||||||
inlineDefaultLambdas: Boolean,
|
|
||||||
typeSystem: TypeSystemCommonBackendContext,
|
|
||||||
registerLineNumberAfterwards: Boolean,
|
|
||||||
) {
|
|
||||||
var nodeAndSmap: SMAPAndMethodNode? = null
|
var nodeAndSmap: SMAPAndMethodNode? = null
|
||||||
try {
|
try {
|
||||||
nodeAndSmap =
|
nodeAndSmap = sourceCompiler.compileInlineFunction(jvmSignature).apply {
|
||||||
generateInlineIntrinsic(state, functionDescriptor, jvmSignature.asmMethod, typeArguments, typeSystem)?.let {
|
node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false)
|
||||||
SMAPAndMethodNode(it, SMAP(listOf()))
|
}
|
||||||
} ?: sourceCompiler.compileInlineFunction(jvmSignature).apply {
|
val result = inlineCall(nodeAndSmap, inlineDefaultLambdas)
|
||||||
node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false)
|
leaveTemps()
|
||||||
}
|
codegen.propagateChildReifiedTypeParametersUsages(result.reifiedTypeParametersUsages)
|
||||||
endCall(inlineCall(nodeAndSmap, inlineDefaultLambdas), registerLineNumberAfterwards)
|
codegen.markLineNumberAfterInlineIfNeeded(registerLineNumberAfterwards)
|
||||||
|
state.factory.removeClasses(result.calcClassesToRemove())
|
||||||
} catch (e: CompilationException) {
|
} catch (e: CompilationException) {
|
||||||
throw e
|
throw e
|
||||||
} catch (e: InlineException) {
|
} catch (e: InlineException) {
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ class PsiInlineCodegen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
performInline(resolvedCall?.typeArguments?.keys?.toList(), callDefault, codegen.typeSystem, registerLineNumber)
|
performInline(callDefault, registerLineNumber)
|
||||||
} finally {
|
} finally {
|
||||||
state.globalInlineContext.exitFromInlining()
|
state.globalInlineContext.exitFromInlining()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -241,6 +241,10 @@ class PsiSourceCompilerForInline(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun compileInlineFunction(jvmSignature: JvmMethodSignature): SMAPAndMethodNode {
|
override fun compileInlineFunction(jvmSignature: JvmMethodSignature): SMAPAndMethodNode {
|
||||||
|
generateInlineIntrinsic(state.languageVersionSettings, functionDescriptor, jvmSignature.asmMethod, codegen.typeSystem)?.let {
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
|
||||||
val asmMethod = if (callDefault) mapDefault() else jvmSignature.asmMethod
|
val asmMethod = if (callDefault) mapDefault() else jvmSignature.asmMethod
|
||||||
|
|
||||||
val directMember = getDirectMemberAndCallableFromObject()
|
val directMember = getDirectMemberAndCallableFromObject()
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import org.jetbrains.kotlin.codegen.coroutines.createMethodNodeForSuspendCorouti
|
|||||||
import org.jetbrains.kotlin.codegen.createMethodNodeForAlwaysEnabledAssert
|
import org.jetbrains.kotlin.codegen.createMethodNodeForAlwaysEnabledAssert
|
||||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructors
|
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructors
|
||||||
import org.jetbrains.kotlin.codegen.isBuiltinAlwaysEnabledAssert
|
import org.jetbrains.kotlin.codegen.isBuiltinAlwaysEnabledAssert
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.calls.checkers.TypeOfChecker
|
import org.jetbrains.kotlin.resolve.calls.checkers.TypeOfChecker
|
||||||
@@ -30,26 +30,29 @@ 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.MethodNode
|
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||||
|
|
||||||
internal fun generateInlineIntrinsic(
|
fun generateInlineIntrinsicForIr(languageVersionSettings: LanguageVersionSettings, descriptor: FunctionDescriptor): SMAPAndMethodNode? =
|
||||||
state: GenerationState,
|
when {
|
||||||
descriptor: FunctionDescriptor,
|
// TODO: implement these as codegen intrinsics (see IrIntrinsicMethods)
|
||||||
asmMethod: Method,
|
|
||||||
typeParameters: List<TypeParameterMarker>?,
|
|
||||||
typeSystem: TypeSystemCommonBackendContext
|
|
||||||
): MethodNode? {
|
|
||||||
val languageVersionSettings = state.languageVersionSettings
|
|
||||||
|
|
||||||
return when {
|
|
||||||
isSpecialEnumMethod(descriptor) ->
|
|
||||||
createSpecialEnumMethodBody(descriptor.name.asString(), typeParameters!!.single(), typeSystem)
|
|
||||||
TypeOfChecker.isTypeOf(descriptor) ->
|
|
||||||
typeSystem.createTypeOfMethodBody(typeParameters!!.single())
|
|
||||||
descriptor.isBuiltInIntercepted(languageVersionSettings) ->
|
descriptor.isBuiltInIntercepted(languageVersionSettings) ->
|
||||||
createMethodNodeForIntercepted(languageVersionSettings)
|
createMethodNodeForIntercepted(languageVersionSettings)
|
||||||
descriptor.isBuiltInCoroutineContext(languageVersionSettings) ->
|
descriptor.isBuiltInCoroutineContext(languageVersionSettings) ->
|
||||||
createMethodNodeForCoroutineContext(descriptor, languageVersionSettings)
|
createMethodNodeForCoroutineContext(descriptor, languageVersionSettings)
|
||||||
descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(languageVersionSettings) ->
|
descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(languageVersionSettings) ->
|
||||||
createMethodNodeForSuspendCoroutineUninterceptedOrReturn(languageVersionSettings)
|
createMethodNodeForSuspendCoroutineUninterceptedOrReturn(languageVersionSettings)
|
||||||
|
else -> null
|
||||||
|
}?.let { SMAPAndMethodNode(it, SMAP(listOf())) }
|
||||||
|
|
||||||
|
internal fun generateInlineIntrinsic(
|
||||||
|
languageVersionSettings: LanguageVersionSettings,
|
||||||
|
descriptor: FunctionDescriptor,
|
||||||
|
asmMethod: Method,
|
||||||
|
typeSystem: TypeSystemCommonBackendContext
|
||||||
|
): SMAPAndMethodNode? {
|
||||||
|
return generateInlineIntrinsicForIr(languageVersionSettings, descriptor) ?: when {
|
||||||
|
isSpecialEnumMethod(descriptor) ->
|
||||||
|
createSpecialEnumMethodBody(descriptor.name.asString(), descriptor.original.typeParameters.single(), typeSystem)
|
||||||
|
TypeOfChecker.isTypeOf(descriptor) ->
|
||||||
|
typeSystem.createTypeOfMethodBody(descriptor.original.typeParameters.single())
|
||||||
descriptor.isBuiltinAlwaysEnabledAssert() ->
|
descriptor.isBuiltinAlwaysEnabledAssert() ->
|
||||||
createMethodNodeForAlwaysEnabledAssert(descriptor)
|
createMethodNodeForAlwaysEnabledAssert(descriptor)
|
||||||
descriptor is FictitiousArrayConstructor ->
|
descriptor is FictitiousArrayConstructor ->
|
||||||
@@ -59,7 +62,7 @@ internal fun generateInlineIntrinsic(
|
|||||||
IntrinsicArrayConstructors.isEmptyArray(descriptor) ->
|
IntrinsicArrayConstructors.isEmptyArray(descriptor) ->
|
||||||
IntrinsicArrayConstructors.generateEmptyArrayBody(asmMethod)
|
IntrinsicArrayConstructors.generateEmptyArrayBody(asmMethod)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}?.let { SMAPAndMethodNode(it, SMAP(listOf())) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isSpecialEnumMethod(descriptor: FunctionDescriptor): Boolean {
|
private fun isSpecialEnumMethod(descriptor: FunctionDescriptor): Boolean {
|
||||||
|
|||||||
+2
-7
@@ -126,13 +126,8 @@ class IrInlineCodegen(
|
|||||||
expression: IrFunctionAccessExpression,
|
expression: IrFunctionAccessExpression,
|
||||||
isInsideIfCondition: Boolean,
|
isInsideIfCondition: Boolean,
|
||||||
) {
|
) {
|
||||||
performInline(
|
// Always look for default lambdas to allow custom default argument handling in compiler plugins.
|
||||||
expression.symbol.owner.typeParameters.map { it.symbol },
|
performInline(inlineDefaultLambdas = true, registerLineNumberAfterwards = isInsideIfCondition)
|
||||||
// Always look for default lambdas to allow custom default argument handling in compiler plugins.
|
|
||||||
inlineDefaultLambdas = true,
|
|
||||||
codegen.typeMapper.typeSystem,
|
|
||||||
registerLineNumberAfterwards = isInsideIfCondition,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun genCycleStub(text: String, codegen: ExpressionCodegen) {
|
override fun genCycleStub(text: String, codegen: ExpressionCodegen) {
|
||||||
|
|||||||
+9
-4
@@ -104,10 +104,15 @@ class IrSourceCompilerForInline(
|
|||||||
return FunctionCodegen(lambdaInfo.function, codegen.classCodegen).generate(codegen, reifiedTypeParameters)
|
return FunctionCodegen(lambdaInfo.function, codegen.classCodegen).generate(codegen, reifiedTypeParameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun compileInlineFunction(jvmSignature: JvmMethodSignature): SMAPAndMethodNode =
|
override fun compileInlineFunction(jvmSignature: JvmMethodSignature): SMAPAndMethodNode {
|
||||||
callee.parentClassId?.let { containerId ->
|
generateInlineIntrinsicForIr(state.languageVersionSettings, callee.toIrBasedDescriptor())?.let {
|
||||||
loadCompiledInlineFunction(containerId, jvmSignature.asmMethod, callee.isSuspend, callee.hasMangledReturnType, state)
|
return it
|
||||||
} ?: ClassCodegen.getOrCreate(callee.parentAsClass, codegen.context).generateMethodNode(callee)
|
}
|
||||||
|
callee.parentClassId?.let {
|
||||||
|
return loadCompiledInlineFunction(it, jvmSignature.asmMethod, callee.isSuspend, callee.hasMangledReturnType, state)
|
||||||
|
}
|
||||||
|
return ClassCodegen.getOrCreate(callee.parentAsClass, codegen.context).generateMethodNode(callee)
|
||||||
|
}
|
||||||
|
|
||||||
override fun hasFinallyBlocks() = data.hasFinallyBlocks()
|
override fun hasFinallyBlocks() = data.hasFinallyBlocks()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user