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.JvmSerializerExtension
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.descriptors.*
@@ -512,7 +513,8 @@ class CoroutineCodegenForLambda private constructor(
containingClassInternalName = v.thisName,
isForNamedFunction = false,
languageVersionSettings = languageVersionSettings,
disableTailCallOptimizationForFunctionReturningUnit = false
disableTailCallOptimizationForFunctionReturningUnit = false,
useOldSpilledVarTypeAnalysis = state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS)
)
val maybeWithForInline = if (forInline)
SuspendForInlineCopyingMethodVisitor(stateMachineBuilder, access, name, desc, functionCodegen::newMethod)
@@ -5,14 +5,10 @@
package org.jetbrains.kotlin.codegen.coroutines
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.ClassBuilder
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.inline.*
import org.jetbrains.kotlin.codegen.optimization.common.*
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.isReleaseCoroutines
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
@@ -65,7 +61,9 @@ class CoroutineTransformerMethodVisitor(
// May differ from containingClassInternalName in case of DefaultImpls
private val internalNameForDispatchReceiver: String? = null,
// 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) {
private val classBuilderForCoroutineState: ClassBuilder by lazy(obtainClassBuilderForCoroutineState)
@@ -594,7 +592,10 @@ class CoroutineTransformerMethodVisitor(
private fun spillVariables(suspensionPoints: List<SuspensionPoint>, methodNode: MethodNode): List<List<SpilledVariableDescriptor>> {
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)
// 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.Type
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.Interpreter
import org.jetbrains.org.objectweb.asm.tree.analysis.Value
@@ -358,4 +359,11 @@ internal fun performSpilledVariableFieldTypesAnalysis(
methodNode: MethodNode,
thisName: String
): 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.preprocessSuspendMarkers
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.JVMConstructorCallNormalizationMode
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.languageVersionSettings
@@ -95,7 +96,8 @@ class SuspendFunctionGenerationStrategy(
languageVersionSettings = languageVersionSettings,
disableTailCallOptimizationForFunctionReturningUnit = originalSuspendDescriptor.returnType?.isUnit() == true &&
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.optimization.common.asSequence
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
@@ -95,7 +96,8 @@ class CoroutineTransformer(
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
containingClassInternalName = classBuilder.thisName,
isForNamedFunction = false,
disableTailCallOptimizationForFunctionReturningUnit = false
disableTailCallOptimizationForFunctionReturningUnit = false,
useOldSpilledVarTypeAnalysis = state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS)
)
if (generateForInline)
@@ -131,7 +133,8 @@ class CoroutineTransformer(
needDispatchReceiver = true,
internalNameForDispatchReceiver = classBuilder.thisName,
disableTailCallOptimizationForFunctionReturningUnit = disableTailCallOptimization,
putContinuationParameterToLvt = !state.isIrBackend
putContinuationParameterToLvt = !state.isIrBackend,
useOldSpilledVarTypeAnalysis = state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS)
)
if (generateForInline)
@@ -369,6 +369,12 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
)
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> {
val result = super.configureAnalysisFlags(collector)
result[JvmAnalysisFlags.strictMetadataVersionSemantics] = strictMetadataVersionSemantics
@@ -198,6 +198,7 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr
put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, arguments.allowKotlinPackage)
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) }
}
@@ -122,4 +122,7 @@ public class JVMConfigurationKeys {
public static final CompilerConfigurationKey<Boolean> NO_KOTLIN_NOTHING_VALUE_EXCEPTION =
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.reportSuspensionPointInsideMonitor
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.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
@@ -64,7 +65,8 @@ internal fun MethodNode.acceptWithStateMachine(
putContinuationParameterToLvt = false,
disableTailCallOptimizationForFunctionReturningUnit = irFunction.isSuspend && irFunction.suspendFunctionOriginal().let {
it.returnType.isUnit() && it.anyOfOverriddenFunctionsReturnsNonUnit()
}
},
useOldSpilledVarTypeAnalysis = state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS)
)
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-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
-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
-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