jvm-abi-gen: Strip inline functions in private classes

Inline functions in private classes can only be accessed from Java and
we do not need to preserve their bodies for the abi.
This commit is contained in:
Steven Schäfer
2021-08-06 10:27:13 +02:00
committed by Alexander Udalov
parent 3ffe495346
commit 5059513106
12 changed files with 111 additions and 12 deletions
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.codegen.DelegatingClassBuilder
import org.jetbrains.kotlin.codegen.DelegatingClassBuilderFactory
import org.jetbrains.kotlin.codegen.extensions.ClassBuilderInterceptorExtension
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.MemberDescriptor
@@ -65,11 +66,17 @@ class JvmAbiClassBuilderInterceptor : ClassBuilderInterceptorExtension {
override fun interceptClassBuilderFactory(interceptedFactory: ClassBuilderFactory, bindingContext: BindingContext, diagnostics: DiagnosticSink): ClassBuilderFactory =
object : DelegatingClassBuilderFactory(interceptedFactory) {
override fun newClassBuilder(origin: JvmDeclarationOrigin): DelegatingClassBuilder =
AbiInfoClassBuilder(interceptedFactory.newClassBuilder(origin))
override fun newClassBuilder(origin: JvmDeclarationOrigin): DelegatingClassBuilder {
val descriptor = origin.descriptor as? ClassDescriptor
val isPrivate = descriptor?.visibility?.let(DescriptorVisibilities::isPrivate) ?: false
return AbiInfoClassBuilder(interceptedFactory.newClassBuilder(origin), isPrivate)
}
}
private inner class AbiInfoClassBuilder(private val delegate: ClassBuilder) : DelegatingClassBuilder() {
private inner class AbiInfoClassBuilder(
private val delegate: ClassBuilder,
private val isPrivateClass: Boolean
) : DelegatingClassBuilder() {
lateinit var internalName: String
var localOrAnonymousClass = false
var publicAbi = false
@@ -104,7 +111,7 @@ class JvmAbiClassBuilderInterceptor : ClassBuilderInterceptorExtension {
// metadata to indicate this (the inliner simply first checks for a method such as `f$$forInline`
// and then checks for `f` if this method doesn't exist) so we have to remember to strip the
// original methods if there was a $$forInline version.
if (name.endsWith(FOR_INLINE_SUFFIX)) {
if (name.endsWith(FOR_INLINE_SUFFIX) && !isPrivateClass) {
// Note that origin.descriptor is null on the JVM BE in this case.
methodInfos[Method(name, desc)] = AbiMethodInfo.KEEP
maskedMethods += Method(name.removeSuffix(FOR_INLINE_SUFFIX), desc)
@@ -119,7 +126,7 @@ class JvmAbiClassBuilderInterceptor : ClassBuilderInterceptorExtension {
}
// Copy inline functions verbatim
if (origin.descriptor?.safeAs<FunctionDescriptor>()?.isInline == true) {
if (origin.descriptor?.safeAs<FunctionDescriptor>()?.isInline == true && !isPrivateClass) {
methodInfos[Method(name, desc)] = AbiMethodInfo.KEEP
} else {
methodInfos[Method(name, desc)] = AbiMethodInfo.STRIP
@@ -85,6 +85,16 @@ public class CompareJvmAbiTestGenerated extends AbstractCompareJvmAbiTest {
runTest("plugins/jvm-abi-gen/testData/compare/functionBody/");
}
@TestMetadata("inlineFunInPrivateClass")
public void testInlineFunInPrivateClass() throws Exception {
runTest("plugins/jvm-abi-gen/testData/compare/inlineFunInPrivateClass/");
}
@TestMetadata("inlineFunInPrivateNestedClass")
public void testInlineFunInPrivateNestedClass() throws Exception {
runTest("plugins/jvm-abi-gen/testData/compare/inlineFunInPrivateNestedClass/");
}
@TestMetadata("inlineFunctionBody")
public void testInlineFunctionBody() throws Exception {
runTest("plugins/jvm-abi-gen/testData/compare/inlineFunctionBody/");
@@ -85,6 +85,16 @@ public class IrCompareJvmAbiTestGenerated extends AbstractIrCompareJvmAbiTest {
runTest("plugins/jvm-abi-gen/testData/compare/functionBody/");
}
@TestMetadata("inlineFunInPrivateClass")
public void testInlineFunInPrivateClass() throws Exception {
runTest("plugins/jvm-abi-gen/testData/compare/inlineFunInPrivateClass/");
}
@TestMetadata("inlineFunInPrivateNestedClass")
public void testInlineFunInPrivateNestedClass() throws Exception {
runTest("plugins/jvm-abi-gen/testData/compare/inlineFunInPrivateNestedClass/");
}
@TestMetadata("inlineFunctionBody")
public void testInlineFunctionBody() throws Exception {
runTest("plugins/jvm-abi-gen/testData/compare/inlineFunctionBody/");
@@ -85,6 +85,16 @@ public class LegacyCompareJvmAbiTestGenerated extends AbstractLegacyCompareJvmAb
runTest("plugins/jvm-abi-gen/testData/compare/functionBody/");
}
@TestMetadata("inlineFunInPrivateClass")
public void testInlineFunInPrivateClass() throws Exception {
runTest("plugins/jvm-abi-gen/testData/compare/inlineFunInPrivateClass/");
}
@TestMetadata("inlineFunInPrivateNestedClass")
public void testInlineFunInPrivateNestedClass() throws Exception {
runTest("plugins/jvm-abi-gen/testData/compare/inlineFunInPrivateNestedClass/");
}
@TestMetadata("inlineFunctionBody")
public void testInlineFunctionBody() throws Exception {
runTest("plugins/jvm-abi-gen/testData/compare/inlineFunctionBody/");
@@ -0,0 +1,9 @@
private class A {
inline fun test(crossinline s: () -> Unit) {
object {
fun run() {
s()
}
}.run()
}
}
@@ -0,0 +1 @@
// IGNORE_BACKEND_LEGACY: JVM
@@ -0,0 +1,9 @@
private class A {
inline fun test(crossinline s: () -> Unit) {
object {
fun run() {
//s()
}
}.run()
}
}
@@ -0,0 +1,11 @@
class A {
private class B {
inline fun test(crossinline s: () -> Unit) {
object {
fun run() {
s()
}
}.run()
}
}
}
@@ -0,0 +1 @@
// IGNORE_BACKEND_LEGACY: JVM
@@ -0,0 +1,11 @@
class A {
private class B {
inline fun test(crossinline s: () -> Unit) {
object {
fun run() {
//s()
}
}.run()
}
}
}