diff options
author | jfrijters <jfrijters> | 2015-06-29 13:15:15 +0300 |
---|---|---|
committer | jfrijters <jfrijters> | 2015-06-29 13:15:15 +0300 |
commit | 8bfa5867bc07c64da2bd9441d9d35409357e6da5 (patch) | |
tree | 0330bb12e6e10b564735599c880f35572a0cbce4 | |
parent | 7aaec377650ec7eae81fa536b69e9b335fb250e3 (diff) |
Cleaned up static initializer optimization to use FieldWrapper.IsSerialVersionUID.
-rw-r--r-- | runtime/ClassFile.cs | 9 | ||||
-rw-r--r-- | runtime/DynamicTypeWrapper.cs | 35 | ||||
-rw-r--r-- | runtime/MemberWrapper.cs | 22 |
3 files changed, 33 insertions, 33 deletions
diff --git a/runtime/ClassFile.cs b/runtime/ClassFile.cs index 8eeb2e85..89e66874 100644 --- a/runtime/ClassFile.cs +++ b/runtime/ClassFile.cs @@ -3864,14 +3864,5 @@ namespace IKVM.Internal } return null; } - - internal bool HasSerialVersionUID - { - get - { - Field field = GetField("serialVersionUID", "J"); - return field != null && field.IsStatic && field.IsFinal; - } - } } } diff --git a/runtime/DynamicTypeWrapper.cs b/runtime/DynamicTypeWrapper.cs index 15d7759b..194d62f3 100644 --- a/runtime/DynamicTypeWrapper.cs +++ b/runtime/DynamicTypeWrapper.cs @@ -497,12 +497,13 @@ namespace IKVM.Internal internal void CreateStep1() { - // process all methods + // process all methods (needs to be done first, because property fields depend on being able to lookup the accessor methods) bool hasclinit = wrapper.BaseTypeWrapper == null ? false : wrapper.BaseTypeWrapper.HasStaticInitializer; methods = new MethodWrapper[classFile.Methods.Length]; baseMethods = new MethodWrapper[classFile.Methods.Length][]; for (int i = 0; i < methods.Length; i++) { + MemberFlags flags = MemberFlags.None; ClassFile.Method m = classFile.Methods[i]; if (m.IsClassInitializer) { @@ -510,12 +511,9 @@ namespace IKVM.Internal bool noop; if (IsSideEffectFreeStaticInitializerOrNoop(m, out noop)) { - // because we cannot affect serialVersionUID computation (which is the only way the presence of a <clinit> can surface) - // we cannot do this optimization if the class is serializable but doesn't have a serialVersionUID - if (noop && (!wrapper.IsSerializable || classFile.HasSerialVersionUID)) + if (noop) { - methods[i] = new DummyMethodWrapper(wrapper); - continue; + flags |= MemberFlags.NoOp; } } else @@ -526,7 +524,6 @@ namespace IKVM.Internal hasclinit = true; #endif } - MemberFlags flags = MemberFlags.None; if (m.IsInternal) { flags |= MemberFlags.InternalAccess; @@ -2912,6 +2909,7 @@ namespace IKVM.Internal internal override MethodBase LinkMethod(MethodWrapper mw) { + Debug.Assert(mw != null); if (mw is DelegateConstructorMethodWrapper) { ((DelegateConstructorMethodWrapper)mw).DoLink(typeBuilder); @@ -2921,7 +2919,13 @@ namespace IKVM.Internal { return ((DelegateInvokeStubMethodWrapper)mw).DoLink(typeBuilder); } - Debug.Assert(mw != null); + if (mw.IsClassInitializer && mw.IsNoOp && (!wrapper.IsSerializable || HasSerialVersionUID)) + { + // we don't need to emit the <clinit>, because it is empty and we're not serializable or have an explicit serialVersionUID + // (because we cannot affect serialVersionUID computation (which is the only way the presence of a <clinit> can surface) + // we cannot do this optimization if the class is serializable but doesn't have a serialVersionUID) + return null; + } int index = GetMethodIndex(mw); if (baseMethods[index] != null) { @@ -3077,6 +3081,21 @@ namespace IKVM.Internal } } + private bool HasSerialVersionUID + { + get + { + foreach (FieldWrapper field in fields) + { + if (field.IsSerialVersionUID) + { + return true; + } + } + return false; + } + } + private MethodBuilder GenerateConstructor(MethodWrapper mw) { MethodBuilder cb = mw.GetDefineMethodHelper().DefineConstructor(wrapper, typeBuilder, GetMethodAccess(mw) | MethodAttributes.HideBySig); diff --git a/runtime/MemberWrapper.cs b/runtime/MemberWrapper.cs index 09941d31..58f04110 100644 --- a/runtime/MemberWrapper.cs +++ b/runtime/MemberWrapper.cs @@ -53,6 +53,7 @@ namespace IKVM.Internal NonPublicTypeInSignature = 512, // this flag is only available after linking and is not set for access stubs DelegateInvokeWithByRefParameter = 1024, Type2FinalField = 2048, + NoOp = 4096, // empty static initializer } abstract class MemberWrapper @@ -296,6 +297,11 @@ namespace IKVM.Internal get { return (flags & MemberFlags.DelegateInvokeWithByRefParameter) != 0; } } + internal bool IsNoOp + { + get { return (flags & MemberFlags.NoOp) != 0; } + } + internal Modifiers Modifiers { get @@ -878,22 +884,6 @@ namespace IKVM.Internal } } - // placeholder for <clinit> method that exist in ClassFile but not in TypeWrapper - // (because it is optimized away) - sealed class DummyMethodWrapper : MethodWrapper - { - internal DummyMethodWrapper(TypeWrapper tw) - : base(tw, StringConstants.CLINIT, StringConstants.SIG_VOID, null, PrimitiveTypeWrapper.VOID, TypeWrapper.EmptyArray, Modifiers.Static, MemberFlags.None) - { - } - - protected override void DoLinkMethod() - { - // we're pre-linked (because we pass the signature types to the base constructor) - throw new InvalidOperationException(); - } - } - abstract class SmartMethodWrapper : MethodWrapper { internal SmartMethodWrapper(TypeWrapper declaringType, string name, string sig, MethodBase method, TypeWrapper returnType, TypeWrapper[] parameterTypes, Modifiers modifiers, MemberFlags flags) |