Do not inline methods from interfaces

This commit is contained in:
Thomas Vochten
2023-09-20 11:28:19 +02:00
committed by Dimitrios Anyfantakis
parent 9a7a97d1ca
commit 8bb7cc0c4b
3 changed files with 63 additions and 0 deletions

View File

@@ -652,6 +652,14 @@ implements AttributeVisitor,
AccessConstants.STATIC |
AccessConstants.FINAL)) != 0 &&
DEBUG("Interface?") &&
// Methods in interfaces should not be inlined since this can potentially
// lead to other methods in the interface needing broadened visibility,
// which can lead to either compilation errors during output writing
// or various issues at runtime.
(programClass.getAccessFlags() & AccessConstants.INTERFACE) == 0 &&
DEBUG("Synchronized?") &&
// Only inline the method if it is not synchronized, etc.

View File

@@ -282,6 +282,60 @@ class MethodInlinerTest : FreeSpec({
}
}
}
"Given a method calling another method in an interface" - {
val (programClassPool, _) = ClassPoolBuilder.fromSource(
JavaSource(
"Foo.java",
"""interface Foo {
default void f1() {
f2();
}
static void f2() {
StringBuilder sb = new StringBuilder();
sb.append(System.currentTimeMillis());
System.out.println(sb.toString());
}
}"""
)
)
val clazz = programClassPool.getClass("Foo") as ProgramClass
val method = clazz.findMethod("f1", "()V") as ProgramMethod
val codeAttr = method.attributes.filterIsInstance<CodeAttribute>()[0]
val lengthBefore = codeAttr.u4codeLength
// Initialize optimization info (used when inlining).
val optimizationInfoInitializer: ClassVisitor = MultiClassVisitor(
ProgramClassOptimizationInfoSetter(),
AllMethodVisitor(
ProgramMemberOptimizationInfoSetter()
)
)
programClassPool.classesAccept(optimizationInfoInitializer)
// Create a mock method inliner which always returns true.
val methodInliner = object : MethodInliner(false, true, true) {
override fun shouldInline(clazz: Clazz?, method: Method?, codeAttribute: CodeAttribute?): Boolean = true
}
"Then the interface method is not inlined" {
programClassPool.classesAccept(
AllMethodVisitor(
AllAttributeVisitor(
methodInliner
)
)
)
val lengthAfter = codeAttr.u4codeLength
lengthAfter shouldBeExactly lengthBefore
}
}
})
private fun printProgramMethodInstructions(

View File

@@ -13,6 +13,7 @@
- Fix "NoClassDefFoundError: Failed resolution of: Lorg/apache/logging/log4j/LogManager" when using GSON optimization or `-addconfigurationdebugging`. (#326)
- Don't drop Record attribute for records with no components. (proguard-core#118)
- Fix potential duplication class when name obfuscating Kotlin multi-file facades.
- Do not inline interface methods to avoid compilation errors during output writing due to an interface method being made package visible.
## Version 7.3.2