JVM: Fix usage of ClassBuilder API in AnonymousObjectTransformer

This commit is contained in:
Steven Schäfer
2021-03-23 15:22:21 +01:00
committed by Alexander Udalov
parent c156613141
commit 1b5214a2dc
10 changed files with 72 additions and 14 deletions
@@ -81,7 +81,7 @@ class AnonymousObjectTransformer(
debugMetadataAnnotation = AnnotationNode(desc)
return debugMetadataAnnotation
}
return super.visitAnnotation(desc, visible)
return classBuilder.newAnnotation(desc, visible)
}
override fun visitMethod(
@@ -197,9 +197,8 @@ class AnonymousObjectTransformer(
classBuilder.visitSource(sourceInfo!!, debugInfo)
}
val visitor = classBuilder.visitor
innerClassNodes.forEach { node ->
visitor.visitInnerClass(node.name, node.outerName, node.innerName, node.access)
classBuilder.visitInnerClass(node.name, node.outerName, node.innerName, node.access)
}
if (header != null) {
@@ -208,12 +207,12 @@ class AnonymousObjectTransformer(
// debugMetadataAnnotation can be null in LV < 1.3
if (putDebugMetadata && debugMetadataAnnotation != null) {
visitor.visitAnnotation(debugMetadataAnnotation!!.desc, true).also {
classBuilder.newAnnotation(debugMetadataAnnotation!!.desc, true).also {
debugMetadataAnnotation!!.accept(it)
}
}
writeOuterInfo(visitor)
writeOuterInfo(classBuilder)
if (inliningContext.generateAssertField && fieldNames.none { it.key == ASSERTIONS_DISABLED_FIELD_NAME }) {
val clInitBuilder = classBuilder.newMethod(NO_ORIGIN, Opcodes.ACC_STATIC, "<clinit>", "()V", null, null)
@@ -234,7 +233,13 @@ class AnonymousObjectTransformer(
private fun writeTransformedMetadata(header: KotlinClassHeader, classBuilder: ClassBuilder) {
// The transformed anonymous object becomes part of the public ABI if it is inside of a public inline function.
val publicAbi = inliningContext.callSiteInfo.isInPublicInlineScope
writeKotlinMetadata(classBuilder, state, header.kind, publicAbi, header.extraInt and JvmAnnotationNames.METADATA_PUBLIC_ABI_FLAG.inv()) action@{ av ->
writeKotlinMetadata(
classBuilder,
state,
header.kind,
publicAbi,
header.extraInt and JvmAnnotationNames.METADATA_PUBLIC_ABI_FLAG.inv()
) action@{ av ->
val (newProto, newStringTable) = transformMetadata(header) ?: run {
val data = header.data
val strings = header.strings
@@ -277,12 +282,12 @@ class AnonymousObjectTransformer(
}
}
private fun writeOuterInfo(visitor: ClassVisitor) {
private fun writeOuterInfo(classBuilder: ClassBuilder) {
val info = inliningContext.callSiteInfo
// Since $$forInline functions are not generated if retransformation is the last one (i.e. call site is not inline)
// link to the function in OUTERCLASS field becomes invalid. However, since $$forInline function always has no-inline
// companion without the suffix, use it.
visitor.visitOuterClass(info.ownerClassName, info.method.name.removeSuffix(FOR_INLINE_SUFFIX), info.method.descriptor)
classBuilder.visitOuterClass(info.ownerClassName, info.method.name.removeSuffix(FOR_INLINE_SUFFIX), info.method.descriptor)
}
private fun inlineMethodAndUpdateGlobalResult(
@@ -93,7 +93,7 @@ open class InliningContext(
newTypeMappings: MutableMap<String, String?>,
callSiteInfo: InlineCallSiteInfo,
transformationInfo: TransformationInfo
): InliningContext = RegeneratedClassContext(
): RegeneratedClassContext = RegeneratedClassContext(
this, state, generator, TypeRemapper.createFrom(typeRemapper, newTypeMappings),
lambdaInfo, callSiteInfo, transformationInfo
)
@@ -193,6 +193,10 @@ class MethodInliner(
ReifiedTypeInliner.putNeedClassReificationMarker(mv)
result.reifiedTypeParametersUsages.mergeAll(transformResult.reifiedTypeParametersUsages)
}
for (classBuilder in childInliningContext.continuationBuilders.values) {
classBuilder.done()
}
} else {
result.addNotChangedClass(oldClassName)
}
@@ -11,10 +11,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.ClassBuilder;
import org.jetbrains.kotlin.codegen.DelegatingClassBuilder;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
import org.jetbrains.org.objectweb.asm.ClassVisitor;
import org.jetbrains.org.objectweb.asm.FieldVisitor;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.*;
import org.jetbrains.org.objectweb.asm.commons.*;
import org.jetbrains.org.objectweb.asm.commons.FieldRemapper;
@@ -25,6 +22,7 @@ public class RemappingClassBuilder extends DelegatingClassBuilder {
private final ClassBuilder builder;
private final Remapper remapper;
private final Map<String, FieldVisitor> spilledCoroutineVariables = new HashMap<>();
private ClassVisitor visitor = null;
public RemappingClassBuilder(@NotNull ClassBuilder builder, @NotNull Remapper remapper) {
this.builder = builder;
@@ -125,9 +123,28 @@ public class RemappingClassBuilder extends DelegatingClassBuilder {
return new AnnotationRemapper(builder.newAnnotation(remapper.mapDesc(desc), visible), remapper);
}
@Override
public void visitInnerClass(@NotNull String name, @Nullable String outerName, @Nullable String innerName, int access) {
getVisitor().visitInnerClass(name, outerName, innerName, access);
}
@Override
public void visitOuterClass(@NotNull String owner, @Nullable String name, @Nullable String desc) {
getVisitor().visitOuterClass(owner, name, desc);
}
@NotNull
@Override
public RecordComponentVisitor newRecordComponent(@NotNull String name, @NotNull String desc, @Nullable String signature) {
return getVisitor().visitRecordComponent(name, desc, signature);
}
@Override
@NotNull
public ClassVisitor getVisitor() {
return new ClassRemapper(builder.getVisitor(), remapper);
if (visitor == null) {
visitor = new ClassRemapper(builder.getVisitor(), remapper);
}
return visitor;
}
}