From 1735a7976aa87bab6a0a0ea5a18e5bfb049f50f1 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 9 Feb 2014 14:58:47 -0700 Subject: [PATCH] do not omit calls to empty methods which may trigger class initialization There's a small optimization in compileDirectInvoke which tries to avoid generating calls to empty methods. However, this causes problems for code which uses such a call to ensure a class is initialized -- if we omit that call, the class may not be initialized and any side effects of that initialization may not happen when the program expects them to. This commit ensures that the compiler only omits empty method calls when the target class does not need initialization. It also removes commented-out code in classpath-openjdk.cpp which was responsible for loading libmawt proactively; that was a hack to get JogAmp to work before we understood what the real problem was. --- src/classpath-openjdk.cpp | 9 --------- src/compile.cpp | 6 +++++- test/Misc.java | 14 ++++++++++++++ 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index f802abd347..4478159ef3 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -698,15 +698,6 @@ class MyClasspath : public Classpath { #else // not AVIAN_OPENJDK_SRC expect(t, loadLibrary(t, libraryPath, "verify", true, true)); expect(t, loadLibrary(t, libraryPath, "java", true, true)); -# ifndef PLATFORM_WINDOWS - // at one point, loading libmawt ahead of time was necessary to - // make AWT work, but recent versions of OpenJDK seem to take care - // of this from Java code, in which case loading it ahead of time - // actually causes trouble, so we comment it out for now until we - // know exactly when it's needed: - - //loadLibrary(t, libraryPath, "mawt", true, true, false); -# endif #endif // not AVIAN_OPENJDK_SRC { object assertionLock = resolveField diff --git a/src/compile.cpp b/src/compile.cpp index 7a968e176b..2d1703b7f4 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -3234,7 +3234,11 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target, bool tailCall) Compiler::Operand* result = 0; - if (emptyMethod(t, target)) { + // don't bother calling an empty method unless calling it might + // cause the class to be initialized, which may have side effects + if (emptyMethod(t, target) + and (not classNeedsInit(t, methodClass(t, target)))) + { tailCall = false; } else { BootContext* bc = frame->context->bootContext; diff --git a/test/Misc.java b/test/Misc.java index 276fb56c21..22f7806b9e 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -23,6 +23,16 @@ public class Misc { } } + private static class Static { + static { + staticRan = true; + } + + public static void run() { } + } + + private static boolean staticRan; + private static int alpha; private static int beta; private static byte byte1, byte2, byte3; @@ -299,6 +309,10 @@ public class Misc { } catch (java.net.UnknownHostException e) { // cool } + + expect(! staticRan); + Static.run(); + expect(staticRan); } protected class Protected { }