Get rid of class builder factory for coroutines

Initially it was a sort of hack: introducing another
interception class builder factory that will process all functions.

To differentiate suspend functions from the common ones
the fake annotation class has been used.

The problem is that now we should inject the different
class builder into the CoroutineTransformerMethodVisitor:
we need class builder for anonymous class representing state
for named function while currently it will be the one for the class
where the named function is defined
This commit is contained in:
Denis Zharkov
2017-04-19 11:21:03 +03:00
parent 7271ca0b72
commit 0cd80d8b0e
6 changed files with 25 additions and 34 deletions
@@ -200,12 +200,18 @@ public class FunctionCodegen {
// Native methods are only defined in facades and do not need package part implementations // Native methods are only defined in facades and do not need package part implementations
return; return;
} }
MethodVisitor mv = v.newMethod(origin, MethodVisitor mv =
flags, strategy.wrapMethodVisitor(
asmMethod.getName(), v.newMethod(origin,
asmMethod.getDescriptor(), flags,
jvmSignature.getGenericsSignature(), asmMethod.getName(),
getThrownExceptions(functionDescriptor, typeMapper)); asmMethod.getDescriptor(),
jvmSignature.getGenericsSignature(),
getThrownExceptions(functionDescriptor, typeMapper)
),
flags, asmMethod.getName(),
asmMethod.getDescriptor()
);
if (CodegenContextUtil.isImplClassOwner(owner)) { if (CodegenContextUtil.isImplClassOwner(owner)) {
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, CodegenUtilKt.unwrapFrontendVersion(functionDescriptor), asmMethod); v.getSerializationBindings().put(METHOD_FOR_FUNCTION, CodegenUtilKt.unwrapFrontendVersion(functionDescriptor), asmMethod);
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.codegen;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.codegen.context.MethodContext; import org.jetbrains.kotlin.codegen.context.MethodContext;
import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
import org.jetbrains.kotlin.psi.KtDeclarationWithBody; import org.jetbrains.kotlin.psi.KtDeclarationWithBody;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature; import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
import org.jetbrains.org.objectweb.asm.MethodVisitor; import org.jetbrains.org.objectweb.asm.MethodVisitor;
@@ -33,6 +32,10 @@ public abstract class FunctionGenerationStrategy {
@NotNull MemberCodegen<?> parentCodegen @NotNull MemberCodegen<?> parentCodegen
); );
public MethodVisitor wrapMethodVisitor(@NotNull MethodVisitor mv, int access, @NotNull String name, @NotNull String desc) {
return mv;
}
public static class FunctionDefault extends CodegenBased { public static class FunctionDefault extends CodegenBased {
private final KtDeclarationWithBody declaration; private final KtDeclarationWithBody declaration;
@@ -306,8 +306,12 @@ class CoroutineCodegen private constructor(
OtherOrigin(element), OtherOrigin(element),
doResumeDescriptor, doResumeDescriptor,
object : FunctionGenerationStrategy.FunctionDefault(state, element as KtDeclarationWithBody) { object : FunctionGenerationStrategy.FunctionDefault(state, element as KtDeclarationWithBody) {
override fun wrapMethodVisitor(mv: MethodVisitor, access: Int, name: String, desc: String): MethodVisitor {
return CoroutineTransformerMethodVisitor(mv, access, name, desc, null, null, v)
}
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) { override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
codegen.v.visitAnnotation(CONTINUATION_METHOD_ANNOTATION_DESC, true).visitEnd()
codegen.initializeCoroutineParameters() codegen.initializeCoroutineParameters()
super.doGenerateBody(codegen, signature) super.doGenerateBody(codegen, signature)
} }
@@ -17,7 +17,10 @@
package org.jetbrains.kotlin.codegen.coroutines package org.jetbrains.kotlin.codegen.coroutines
import com.intellij.util.containers.Stack import com.intellij.util.containers.Stack
import org.jetbrains.kotlin.codegen.* 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.optimization.DeadCodeEliminationMethodTransformer import org.jetbrains.kotlin.codegen.optimization.DeadCodeEliminationMethodTransformer
import org.jetbrains.kotlin.codegen.optimization.FixStackWithLabelNormalizationMethodTransformer import org.jetbrains.kotlin.codegen.optimization.FixStackWithLabelNormalizationMethodTransformer
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
@@ -34,24 +37,6 @@ import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.tree.* import org.jetbrains.org.objectweb.asm.tree.*
class CoroutineTransformationClassBuilder(private val delegate: ClassBuilder) : DelegatingClassBuilder() {
override fun getDelegate() = delegate
override fun newMethod(
origin: JvmDeclarationOrigin,
access: Int, name: String,
desc: String, signature:
String?,
exceptions: Array<out String>?
) = CoroutineTransformerMethodVisitor(
delegate.newMethod(origin, access, name, desc, signature, exceptions),
access, name, desc, signature, exceptions, this)
}
class CoroutineTransformerClassBuilderFactory(delegate: ClassBuilderFactory) : DelegatingClassBuilderFactory(delegate) {
override fun newClassBuilder(origin: JvmDeclarationOrigin) = CoroutineTransformationClassBuilder(delegate.newClassBuilder(origin))
}
class CoroutineTransformerMethodVisitor( class CoroutineTransformerMethodVisitor(
delegate: MethodVisitor, delegate: MethodVisitor,
access: Int, access: Int,
@@ -62,9 +47,6 @@ class CoroutineTransformerMethodVisitor(
private val classBuilder: ClassBuilder private val classBuilder: ClassBuilder
) : TransformationMethodVisitor(delegate, access, name, desc, signature, exceptions) { ) : TransformationMethodVisitor(delegate, access, name, desc, signature, exceptions) {
override fun performTransformations(methodNode: MethodNode) { override fun performTransformations(methodNode: MethodNode) {
if (methodNode.visibleAnnotations?.none { it.desc == CONTINUATION_METHOD_ANNOTATION_DESC } != false) return
methodNode.visibleAnnotations.removeAll { it.desc == CONTINUATION_METHOD_ANNOTATION_DESC }
val customCoroutineStartMarker = methodNode.instructions.toArray().filterIsInstance<MethodInsnNode>().firstOrNull { val customCoroutineStartMarker = methodNode.instructions.toArray().filterIsInstance<MethodInsnNode>().firstOrNull {
it.owner == COROUTINE_MARKER_OWNER && it.name == ACTUAL_COROUTINE_START_MARKER_NAME it.owner == COROUTINE_MARKER_OWNER && it.name == ACTUAL_COROUTINE_START_MARKER_NAME
} }
@@ -53,8 +53,6 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.tree.MethodNode import org.jetbrains.org.objectweb.asm.tree.MethodNode
// These classes do not actually exist at runtime // These classes do not actually exist at runtime
val CONTINUATION_METHOD_ANNOTATION_DESC = "Lkotlin/ContinuationMethod;"
const val COROUTINE_MARKER_OWNER = "kotlin/coroutines/Markers" const val COROUTINE_MARKER_OWNER = "kotlin/coroutines/Markers"
const val BEFORE_SUSPENSION_POINT_MARKER_NAME = "beforeSuspensionPoint" const val BEFORE_SUSPENSION_POINT_MARKER_NAME = "beforeSuspensionPoint"
const val AFTER_SUSPENSION_POINT_MARKER_NAME = "afterSuspensionPoint" const val AFTER_SUSPENSION_POINT_MARKER_NAME = "afterSuspensionPoint"
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.codegen.`when`.MappingsClassesForWhenByEnum
import org.jetbrains.kotlin.codegen.binding.CodegenBinding import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.context.CodegenContext import org.jetbrains.kotlin.codegen.context.CodegenContext
import org.jetbrains.kotlin.codegen.context.RootContext import org.jetbrains.kotlin.codegen.context.RootContext
import org.jetbrains.kotlin.codegen.coroutines.CoroutineTransformerClassBuilderFactory
import org.jetbrains.kotlin.codegen.extensions.ClassBuilderInterceptorExtension import org.jetbrains.kotlin.codegen.extensions.ClassBuilderInterceptorExtension
import org.jetbrains.kotlin.codegen.inline.InlineCache import org.jetbrains.kotlin.codegen.inline.InlineCache
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
@@ -177,7 +176,6 @@ class GenerationState @JvmOverloads constructor(
this.interceptedBuilderFactory = builderFactory this.interceptedBuilderFactory = builderFactory
.wrapWith( .wrapWith(
{ OptimizationClassBuilderFactory(it, configuration.get(JVMConfigurationKeys.DISABLE_OPTIMIZATION, false)) }, { OptimizationClassBuilderFactory(it, configuration.get(JVMConfigurationKeys.DISABLE_OPTIMIZATION, false)) },
::CoroutineTransformerClassBuilderFactory,
{ BuilderFactoryForDuplicateSignatureDiagnostics( { BuilderFactoryForDuplicateSignatureDiagnostics(
it, this.bindingContext, diagnostics, it, this.bindingContext, diagnostics,
fileClassesProvider, this.moduleName, fileClassesProvider, this.moduleName,