Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/ikvm-fork.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjfrijters <jfrijters>2015-06-29 13:15:15 +0300
committerjfrijters <jfrijters>2015-06-29 13:15:15 +0300
commit8bfa5867bc07c64da2bd9441d9d35409357e6da5 (patch)
tree0330bb12e6e10b564735599c880f35572a0cbce4
parent7aaec377650ec7eae81fa536b69e9b335fb250e3 (diff)
Cleaned up static initializer optimization to use FieldWrapper.IsSerialVersionUID.
-rw-r--r--runtime/ClassFile.cs9
-rw-r--r--runtime/DynamicTypeWrapper.cs35
-rw-r--r--runtime/MemberWrapper.cs22
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)