From c48633571a0bd24ae0cb3184490defe67a91a192 Mon Sep 17 00:00:00 2001 From: jfrijters Date: Fri, 26 Jun 2015 11:22:19 +0000 Subject: Moved unused field removal optimization to a later stage in the compilation. Also made the check more strict to only remove final fields and not remove fields that have annotations. --- ikvmc/Compiler.cs | 2 +- ikvmc/CompilerClassLoader.cs | 5 ----- runtime/ClassFile.cs | 20 +------------------- runtime/ClassLoaderWrapper.cs | 9 +++++++++ runtime/DynamicTypeWrapper.cs | 12 ++++++++++++ 5 files changed, 23 insertions(+), 25 deletions(-) diff --git a/ikvmc/Compiler.cs b/ikvmc/Compiler.cs index 659d4751..159052cd 100644 --- a/ikvmc/Compiler.cs +++ b/ikvmc/Compiler.cs @@ -838,7 +838,7 @@ sealed class IkvmcCompiler } else if(s == "-opt:fields") { - options.removeUnusedFields = true; + options.codegenoptions |= CodeGenOptions.RemoveUnusedFields; } else if(s == "-compressresources") { diff --git a/ikvmc/CompilerClassLoader.cs b/ikvmc/CompilerClassLoader.cs index 8bae21a2..1d6e66a3 100644 --- a/ikvmc/CompilerClassLoader.cs +++ b/ikvmc/CompilerClassLoader.cs @@ -294,10 +294,6 @@ namespace IKVM.Internal StaticCompiler.IssueMessage(options, Message.WrongClassName, name, f.Name); return null; } - if(options.removeUnusedFields) - { - f.RemoveUnusedFields(); - } if(f.IsPublic && options.privatePackages != null) { foreach(string p in options.privatePackages) @@ -3475,7 +3471,6 @@ namespace IKVM.Internal internal Dictionary props; internal bool noglobbing; internal CodeGenOptions codegenoptions; - internal bool removeUnusedFields; internal bool compressedResources; internal string[] privatePackages; internal string[] publicPackages; diff --git a/runtime/ClassFile.cs b/runtime/ClassFile.cs index 9dfa170f..8eeb2e85 100644 --- a/runtime/ClassFile.cs +++ b/runtime/ClassFile.cs @@ -1037,25 +1037,7 @@ namespace IKVM.Internal } } - internal void RemoveUnusedFields() - { - List list = new List(); - foreach(Field f in fields) - { - if(f.IsPrivate && f.IsStatic && f.Name != "serialVersionUID" && !IsReferenced(f)) - { - // unused, so we skip it - Tracer.Info(Tracer.Compiler, "Unused field {0}::{1}", this.Name, f.Name); - } - else - { - list.Add(f); - } - } - fields = list.ToArray(); - } - - private bool IsReferenced(Field fld) + internal bool IsReferenced(Field fld) { foreach(ConstantPoolItem cpi in constantpool) { diff --git a/runtime/ClassLoaderWrapper.cs b/runtime/ClassLoaderWrapper.cs index a7907db2..48a60068 100644 --- a/runtime/ClassLoaderWrapper.cs +++ b/runtime/ClassLoaderWrapper.cs @@ -53,6 +53,7 @@ namespace IKVM.Internal NoAutomagicSerialization = 32, DisableDynamicBinding = 64, NoRefEmitHelpers = 128, + RemoveUnusedFields = 256, } [Flags] @@ -329,6 +330,14 @@ namespace IKVM.Internal } } + internal bool RemoveUnusedFields + { + get + { + return (codegenoptions & CodeGenOptions.RemoveUnusedFields) != 0; + } + } + internal bool WorkaroundAbstractMethodWidening { get diff --git a/runtime/DynamicTypeWrapper.cs b/runtime/DynamicTypeWrapper.cs index a1d89318..ca89df7f 100644 --- a/runtime/DynamicTypeWrapper.cs +++ b/runtime/DynamicTypeWrapper.cs @@ -1520,6 +1520,18 @@ namespace IKVM.Internal } int fieldIndex = GetFieldIndex(fw); #if STATIC_COMPILER + if (wrapper.GetClassLoader().RemoveUnusedFields + && fw.IsPrivate + && fw.IsStatic + && fw.IsFinal + && fw.Name != "serialVersionUID" + && classFile.Fields[fieldIndex].Annotations == null + && !classFile.IsReferenced(classFile.Fields[fieldIndex])) + { + // unused, so we skip it + Tracer.Info(Tracer.Compiler, "Unused field {0}::{1}", wrapper.Name, fw.Name); + return null; + } // for compatibility with broken Java code that assumes that reflection returns the fields in class declaration // order, we emit the fields in class declaration order in the .NET metadata (and then when we retrieve them // using .NET reflection, we sort on metadata token.) -- cgit v1.2.3