Add flag to disable new spilled variable type analysis

This commit is contained in:
Ilmir Usmanov
2020-06-25 21:13:11 +02:00
parent d7df6e1e0c
commit f127a0f593
10 changed files with 43 additions and 13 deletions
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.codegen.context.MethodContext
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION
import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.isReleaseCoroutines import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
@@ -512,7 +513,8 @@ class CoroutineCodegenForLambda private constructor(
containingClassInternalName = v.thisName, containingClassInternalName = v.thisName,
isForNamedFunction = false, isForNamedFunction = false,
languageVersionSettings = languageVersionSettings, languageVersionSettings = languageVersionSettings,
disableTailCallOptimizationForFunctionReturningUnit = false disableTailCallOptimizationForFunctionReturningUnit = false,
useOldSpilledVarTypeAnalysis = state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS)
) )
val maybeWithForInline = if (forInline) val maybeWithForInline = if (forInline)
SuspendForInlineCopyingMethodVisitor(stateMachineBuilder, access, name, desc, functionCodegen::newMethod) SuspendForInlineCopyingMethodVisitor(stateMachineBuilder, access, name, desc, functionCodegen::newMethod)
@@ -5,14 +5,10 @@
package org.jetbrains.kotlin.codegen.coroutines package org.jetbrains.kotlin.codegen.coroutines
import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.ClassBuilder
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
import org.jetbrains.kotlin.codegen.inline.* import org.jetbrains.kotlin.codegen.inline.*
import org.jetbrains.kotlin.codegen.optimization.common.* import org.jetbrains.kotlin.codegen.optimization.common.*
import org.jetbrains.kotlin.codegen.optimization.fixStack.FixStackMethodTransformer import org.jetbrains.kotlin.codegen.optimization.fixStack.FixStackMethodTransformer
import org.jetbrains.kotlin.codegen.linkWithLabel
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.isReleaseCoroutines import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.resolve.jvm.AsmTypes
@@ -65,7 +61,9 @@ class CoroutineTransformerMethodVisitor(
// May differ from containingClassInternalName in case of DefaultImpls // May differ from containingClassInternalName in case of DefaultImpls
private val internalNameForDispatchReceiver: String? = null, private val internalNameForDispatchReceiver: String? = null,
// JVM_IR backend generates $completion, while old backend does not // JVM_IR backend generates $completion, while old backend does not
private val putContinuationParameterToLvt: Boolean = true private val putContinuationParameterToLvt: Boolean = true,
// New SourceInterpreter-less analyser can be somewhat unstable, disable it
private val useOldSpilledVarTypeAnalysis: Boolean = false
) : TransformationMethodVisitor(delegate, access, name, desc, signature, exceptions) { ) : TransformationMethodVisitor(delegate, access, name, desc, signature, exceptions) {
private val classBuilderForCoroutineState: ClassBuilder by lazy(obtainClassBuilderForCoroutineState) private val classBuilderForCoroutineState: ClassBuilder by lazy(obtainClassBuilderForCoroutineState)
@@ -594,7 +592,10 @@ class CoroutineTransformerMethodVisitor(
private fun spillVariables(suspensionPoints: List<SuspensionPoint>, methodNode: MethodNode): List<List<SpilledVariableDescriptor>> { private fun spillVariables(suspensionPoints: List<SuspensionPoint>, methodNode: MethodNode): List<List<SpilledVariableDescriptor>> {
val instructions = methodNode.instructions val instructions = methodNode.instructions
val frames = performSpilledVariableFieldTypesAnalysis(methodNode, containingClassInternalName) val frames =
if (useOldSpilledVarTypeAnalysis) performRefinedTypeAnalysis(methodNode, containingClassInternalName)
else performSpilledVariableFieldTypesAnalysis(methodNode, containingClassInternalName)
fun AbstractInsnNode.index() = instructions.indexOf(this) fun AbstractInsnNode.index() = instructions.indexOf(this)
// We postpone these actions because they change instruction indices that we use when obtaining frames // We postpone these actions because they change instruction indices that we use when obtaining frames
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.resolve.jvm.AsmTypes
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.tree.* import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
import org.jetbrains.org.objectweb.asm.tree.analysis.Value import org.jetbrains.org.objectweb.asm.tree.analysis.Value
@@ -358,4 +359,11 @@ internal fun performSpilledVariableFieldTypesAnalysis(
methodNode: MethodNode, methodNode: MethodNode,
thisName: String thisName: String
): Array<out Frame<SpilledVariableFieldTypeValue>?> = ): Array<out Frame<SpilledVariableFieldTypeValue>?> =
MethodAnalyzer(thisName, methodNode, SpilledVariableFieldTypesInterpreter(methodNode)).analyze() MethodAnalyzer(thisName, methodNode, SpilledVariableFieldTypesInterpreter(methodNode)).analyze()
internal val Value.type: Type?
get() = when (this) {
is BasicValue -> type
is SpilledVariableFieldTypeValue -> type
else -> error("Unexpected type of $this")
}
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.codegen.inline.addFakeContinuationConstructorCallMar
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
import org.jetbrains.kotlin.codegen.inline.preprocessSuspendMarkers import org.jetbrains.kotlin.codegen.inline.preprocessSuspendMarkers
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.JVMConstructorCallNormalizationMode import org.jetbrains.kotlin.config.JVMConstructorCallNormalizationMode
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.config.languageVersionSettings
@@ -95,7 +96,8 @@ class SuspendFunctionGenerationStrategy(
languageVersionSettings = languageVersionSettings, languageVersionSettings = languageVersionSettings,
disableTailCallOptimizationForFunctionReturningUnit = originalSuspendDescriptor.returnType?.isUnit() == true && disableTailCallOptimizationForFunctionReturningUnit = originalSuspendDescriptor.returnType?.isUnit() == true &&
originalSuspendDescriptor.overriddenDescriptors.isNotEmpty() && originalSuspendDescriptor.overriddenDescriptors.isNotEmpty() &&
!originalSuspendDescriptor.allOverriddenFunctionsReturnUnit() !originalSuspendDescriptor.allOverriddenFunctionsReturnUnit(),
useOldSpilledVarTypeAnalysis = state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS)
) )
} }
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.codegen.coroutines.*
import org.jetbrains.kotlin.codegen.inline.* import org.jetbrains.kotlin.codegen.inline.*
import org.jetbrains.kotlin.codegen.optimization.common.asSequence import org.jetbrains.kotlin.codegen.optimization.common.asSequence
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.isReleaseCoroutines import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
@@ -95,7 +96,8 @@ class CoroutineTransformer(
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization, shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
containingClassInternalName = classBuilder.thisName, containingClassInternalName = classBuilder.thisName,
isForNamedFunction = false, isForNamedFunction = false,
disableTailCallOptimizationForFunctionReturningUnit = false disableTailCallOptimizationForFunctionReturningUnit = false,
useOldSpilledVarTypeAnalysis = state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS)
) )
if (generateForInline) if (generateForInline)
@@ -131,7 +133,8 @@ class CoroutineTransformer(
needDispatchReceiver = true, needDispatchReceiver = true,
internalNameForDispatchReceiver = classBuilder.thisName, internalNameForDispatchReceiver = classBuilder.thisName,
disableTailCallOptimizationForFunctionReturningUnit = disableTailCallOptimization, disableTailCallOptimizationForFunctionReturningUnit = disableTailCallOptimization,
putContinuationParameterToLvt = !state.isIrBackend putContinuationParameterToLvt = !state.isIrBackend,
useOldSpilledVarTypeAnalysis = state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS)
) )
if (generateForInline) if (generateForInline)
@@ -369,6 +369,12 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
) )
var repeatCompileModules: String? by NullableStringFreezableVar(null) var repeatCompileModules: String? by NullableStringFreezableVar(null)
@Argument(
value = "-Xuse-old-spilled-var-type-analysis",
description = "Use old, SourceInterpreter-based analysis for fields, used for spilled variables in coroutines"
)
var useOldSpilledVarTypeAnalysis: Boolean by FreezableVar(false)
override fun configureAnalysisFlags(collector: MessageCollector): MutableMap<AnalysisFlag<*>, Any> { override fun configureAnalysisFlags(collector: MessageCollector): MutableMap<AnalysisFlag<*>, Any> {
val result = super.configureAnalysisFlags(collector) val result = super.configureAnalysisFlags(collector)
result[JvmAnalysisFlags.strictMetadataVersionSemantics] = strictMetadataVersionSemantics result[JvmAnalysisFlags.strictMetadataVersionSemantics] = strictMetadataVersionSemantics
@@ -198,6 +198,7 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr
put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, arguments.allowKotlinPackage) put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, arguments.allowKotlinPackage)
put(JVMConfigurationKeys.USE_SINGLE_MODULE, arguments.singleModule) put(JVMConfigurationKeys.USE_SINGLE_MODULE, arguments.singleModule)
put(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS, arguments.useOldSpilledVarTypeAnalysis)
arguments.declarationsOutputPath?.let { put(JVMConfigurationKeys.DECLARATIONS_JSON_PATH, it) } arguments.declarationsOutputPath?.let { put(JVMConfigurationKeys.DECLARATIONS_JSON_PATH, it) }
} }
@@ -122,4 +122,7 @@ public class JVMConfigurationKeys {
public static final CompilerConfigurationKey<Boolean> NO_KOTLIN_NOTHING_VALUE_EXCEPTION = public static final CompilerConfigurationKey<Boolean> NO_KOTLIN_NOTHING_VALUE_EXCEPTION =
CompilerConfigurationKey.create("Do not use KotlinNothingValueException available since 1.4"); CompilerConfigurationKey.create("Do not use KotlinNothingValueException available since 1.4");
public static final CompilerConfigurationKey<Boolean> USE_OLD_SPILLED_VAR_TYPE_ANALYSIS =
CompilerConfigurationKey.create("Use old, SourceInterpreter-based analysis for fields, used for spilled variables in coroutines");
} }
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.codegen.coroutines.INVOKE_SUSPEND_METHOD_NAME
import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_IMPL_NAME_SUFFIX import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_IMPL_NAME_SUFFIX
import org.jetbrains.kotlin.codegen.coroutines.reportSuspensionPointInsideMonitor import org.jetbrains.kotlin.codegen.coroutines.reportSuspensionPointInsideMonitor
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.isReleaseCoroutines import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
@@ -64,7 +65,8 @@ internal fun MethodNode.acceptWithStateMachine(
putContinuationParameterToLvt = false, putContinuationParameterToLvt = false,
disableTailCallOptimizationForFunctionReturningUnit = irFunction.isSuspend && irFunction.suspendFunctionOriginal().let { disableTailCallOptimizationForFunctionReturningUnit = irFunction.isSuspend && irFunction.suspendFunctionOriginal().let {
it.returnType.isUnit() && it.anyOfOverriddenFunctionsReturnsNonUnit() it.returnType.isUnit() && it.anyOfOverriddenFunctionsReturnsNonUnit()
} },
useOldSpilledVarTypeAnalysis = state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS)
) )
accept(visitor) accept(visitor)
} }
+2
View File
@@ -100,6 +100,8 @@ where advanced options include:
-Xuse-javac Use javac for Java source and class files analysis -Xuse-javac Use javac for Java source and class files analysis
-Xuse-old-class-files-reading Use old class files reading implementation. This may slow down the build and cause problems with Groovy interop. -Xuse-old-class-files-reading Use old class files reading implementation. This may slow down the build and cause problems with Groovy interop.
Should be used in case of problems with the new implementation Should be used in case of problems with the new implementation
-Xuse-old-spilled-var-type-analysis
Use old, SourceInterpreter-based analysis for fields, used for spilled variables in coroutines
-Xuse-type-table Use type table in metadata serialization -Xuse-type-table Use type table in metadata serialization
-Xallow-kotlin-package Allow compiling code in package 'kotlin' and allow not requiring kotlin.stdlib in module-info -Xallow-kotlin-package Allow compiling code in package 'kotlin' and allow not requiring kotlin.stdlib in module-info
-Xallow-result-return-type Allow compiling code when `kotlin.Result` is used as a return type -Xallow-result-return-type Allow compiling code when `kotlin.Result` is used as a return type