Describe the issue
Static boolean fields of classes initialized at build time are effective for code removal when used in if statements while static methods returning the very same field are not.
Steps to reproduce the issue
Consider this simple class (initialized at build time) used to detect if the code is running as a native image or not:
public abstract class NativeImageDetector {
public static final boolean IN_NATIVE_IMAGE = (System.getProperty("org.graalvm.nativeimage.imagecode") != null);
public static boolean inNativeImage() {
return IN_NATIVE_IMAGE;
}
}
If the static field is used in an if statement:
public class AppWithStaticField {
public static void main(String[] args) {
if (!NativeImageDetector.IN_NATIVE_IMAGE) {
System.out.println("Should not be printed in native images" + new Foo().foo());
}
}
}
As expected the message is not printed on the console and com.sample.Foo is not referenced in the used classes visible in the report generated via -H:+PrintAnalysisCallTree.
But if we do the same with the static method:
public class AppWithStaticMethod {
public static void main(String[] args) {
if (!NativeImageDetector.inNativeImage()) {
System.out.println("Should not be printed in native images" + new Foo().foo());
}
}
}
As expected the message is not printed on the console.
But com.sample.Foo is referenced in the used classes visible in the report generated via `-H:+PrintAnalysisCallTree. Such class should be not be referenced here nor part of the static image, the static method and static field variants should be equivalent for such trivial level of indirection.
Check https://github.com/sdeleuze/graalvm-native-issues/tree/master/static-method-code-removal-regression and run ./build.sh to reproduce the issue.
Describe GraalVM and your environment:
The static analysis currently is not context sensitive and also does not do any inlining. Therefore, even tiny helper methods like inNativeImage are not inlined and constant folded.
We have a research project that tries to address this limitation. However, the solution is not as trivial as it sounds ("just always inline this method"), because we really need to guarantee that inlining happens in all places, which requires a bit of implementation.
@eginez I am not sure to understand why this issue is closed, despite being non trivial to fix isn't it a real open issue?
See for example https://tomcat.apache.org/tomcat-9.0-doc/api/org/apache/tomcat/util/compat/JreCompat.html#isGraalAvailable-- that shows that Tomcat team and likely many others have the same expectation than us.
Is there a root issue to track progresses on you research project?
@sdeleuze I think it makes sense to keep this open to track future development on this issue, for now, however nothing is planned
@vjovanov @christianwimmer As discussed recently, could we move this issue to 20.3 since it seems the potential fix for #2500 will fix this one as well?
@vjovanov @christianwimmer As discussed recently, could we move this issue to 20.3 since it seems the potential fix for #2500 will fix this one as well?
We have a research project that looks at method inlining before static analysis https://github.com/oracle/graal/pull/2860. In https://github.com/oracle/graal/pull/2860#issue-489679740 you'll find examples for fixing https://github.com/oracle/graal/issues/2500.
This should be addressed by the following commit: https://github.com/oracle/graal/commit/17f1de43c1aa31df22e5a62ea2d9cb1318413c5d
Feel free to try this out by using -H:+InlineBeforeAnalysis.