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-07-02 10:21:17 +0300
committerjfrijters <jfrijters>2015-07-02 10:21:17 +0300
commit2299e0e8f388e3a77944eeb1b40935975026fccd (patch)
tree3d8f075f0c7bbc9a4745e912792049151ef4bd58
parent5120f4f902f00b49e64e44ee6d4a617a2b8e6145 (diff)
Improved -removeassertions ikvmc optimization to remove more code (esp. allow otherwise empty <clinit> methods to be optimized away).
-rw-r--r--openjdk/response.txt46
-rw-r--r--runtime/ClassFile.cs137
-rw-r--r--runtime/ClassLoaderWrapper.cs4
-rw-r--r--runtime/DynamicTypeWrapper.cs15
-rw-r--r--runtime/verifier.cs24
5 files changed, 184 insertions, 42 deletions
diff --git a/openjdk/response.txt b/openjdk/response.txt
index 37e32097..9bc69a05 100644
--- a/openjdk/response.txt
+++ b/openjdk/response.txt
@@ -193,7 +193,7 @@
}
{
-out:IKVM.OpenJDK.Corba.dll
- -baseaddress:0x57350000
+ -baseaddress:0x57320000
-recurse:resources.zip/com/sun/corba/*
-recurse:resources.zip/com/sun/jndi/cosnaming/jndiprovider.properties
-resource:com/sun/corba/se/impl/logging/LogStrings.properties=@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/classes/com/sun/corba/se/impl/logging/LogStrings.properties
@@ -314,7 +314,7 @@
}
{
-out:IKVM.OpenJDK.XML.API.dll
- -baseaddress:0x57980000
+ -baseaddress:0x57950000
-resource:META-INF/services/sun.util.spi.XmlPropertiesProvider=@OPENJDK@/jdk/src/share/classes/sun/util/xml/META-INF/services/sun.util.spi.XmlPropertiesProvider
@OPENJDK@/jaxp/src/javax/xml/*.class
@OPENJDK@/jaxp/src/javax/xml/datatype/*.class
@@ -349,7 +349,7 @@
}
{
-out:IKVM.OpenJDK.XML.XPath.dll
- -baseaddress:0x57A40000
+ -baseaddress:0x57A10000
-recurse:resources.zip/com/sun/org/apache/xalan/internal/res/*
@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/extensions/*.class
@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/res/*.class
@@ -374,7 +374,7 @@
}
{
-out:IKVM.OpenJDK.XML.Parse.dll
- -baseaddress:0x57DA0000
+ -baseaddress:0x57D70000
-recurse:resources.zip/com/sun/org/apache/xerces/*
-recurse:resources.zip/com/sun/org/apache/xml/internal/*
-recurse:resources.zip/com/sun/xml/internal/stream/*
@@ -437,7 +437,7 @@
}
{
-out:IKVM.OpenJDK.XML.Transform.dll
- -baseaddress:0x58580000
+ -baseaddress:0x58550000
@OPENJDK@/jaxp/src/com/sun/java_cup/internal/runtime/*.class
@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/*.class
@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/classfile/*.class
@@ -461,7 +461,7 @@
}
{
-out:IKVM.OpenJDK.XML.Bind.dll
- -baseaddress:0x589D0000
+ -baseaddress:0x589A0000
-recurse:resources.zip/javax/xml/bind/*
-recurse:resources.zip/com/sun/xml/internal/bind/*
-recurse:resources.zip/com/sun/xml/internal/fastinfoset/*
@@ -520,7 +520,7 @@
}
{
-out:IKVM.OpenJDK.XML.WebServices.dll
- -baseaddress:0x58DF0000
+ -baseaddress:0x58DC0000
-recurse:resources.zip/com/sun/xml/internal/messaging/*
-recurse:resources.zip/com/sun/xml/internal/ws/*
@OPENJDK@/jaxws/src/share/jaxws_classes/com/oracle/webservices/internal/api/*.class
@@ -661,7 +661,7 @@
}
{
-out:IKVM.OpenJDK.XML.Crypto.dll
- -baseaddress:0x59600000
+ -baseaddress:0x595D0000
@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/*.class
@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/*.class
@OPENJDK@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/*.class
@@ -697,7 +697,7 @@
}
{
-out:IKVM.OpenJDK.SwingAWT.dll
- -baseaddress:0x59780000
+ -baseaddress:0x59750000
-remap:swingawt.xml
-resource:META-INF/services/sun.java2d.pipe.RenderingEngine=resources/META-INF/services/sun.java2d.pipe.RenderingEngine
-resource:META-INF/services/sun.java2d.cmm.CMMServiceProvider=@OPENJDK@/jdk/src/share/classes/sun/java2d/cmm/lcms/META-INF/services/sun.java2d.cmm.CMMServiceProvider
@@ -797,14 +797,14 @@
}
{
-out:IKVM.OpenJDK.Charsets.dll
- -baseaddress:0x5A9B0000
+ -baseaddress:0x5A980000
-resource:sun/nio/cs/ext/sjis0213.dat=@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/sjis0213.dat
@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/ext/*.class
@OPENJDK@/jdk/src/share/classes/sun/nio/cs/ext/*.class
}
{
-out:IKVM.OpenJDK.Util.dll
- -baseaddress:0x5AEC0000
+ -baseaddress:0x5AE90000
-recurse:resources.zip/com/sun/java/util/jar/pack/intrinsic.properties
-recurse:resources.zip/sun/launcher/resources/*
-resource:META-INF/services/java.nio.file.spi.FileSystemProvider=@OPENJDK@/jdk/src/share/demo/nio/zipfs/src/META-INF/services/java.nio.file.spi.FileSystemProvider
@@ -830,7 +830,7 @@
}
{
-out:IKVM.OpenJDK.Text.dll
- -baseaddress:0x5B190000
+ -baseaddress:0x5B160000
-recurse:resources.zip/sun/text/resources/*
@OPENJDK@/jdk/src/share/classes/java/text/*.class
@OPENJDK@/jdk/src/share/classes/java/text/spi/*.class
@@ -842,7 +842,7 @@
}
{
-out:IKVM.OpenJDK.Security.dll
- -baseaddress:0x5B340000
+ -baseaddress:0x5B310000
-remap:security.xml
sun/security/jgss/wrapper/*.class
@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/security/util/*.class
@@ -916,7 +916,7 @@
}
{
-out:IKVM.OpenJDK.Management.dll
- -baseaddress:0x5BB80000
+ -baseaddress:0x5BB50000
java/lang/management/*.class
sun/management/*.class
rmistubs/org/omg/stub/javax/management/remote/rmi/*.class
@@ -950,7 +950,7 @@
}
{
-out:IKVM.OpenJDK.Misc.dll
- -baseaddress:0x5BF10000
+ -baseaddress:0x5BEE0000
@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/misc/resources/*.class
@OPENJDK@/corba/src/share/classes/javax/activity/*.class
@OPENJDK@/jaxws/src/share/jaxws_classes/javax/annotation/*.class
@@ -981,7 +981,7 @@
}
{
-out:IKVM.OpenJDK.Naming.dll
- -baseaddress:0x5BFD0000
+ -baseaddress:0x5BFA0000
-recurse:resources.zip/com/sun/jndi/ldap/jndiprovider.properties
-resource:META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor=@OPENJDK@/jdk/src/share/classes/sun/net/spi/nameservice/dns/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
sun/net/dns/*.class
@@ -1007,7 +1007,7 @@
}
{
-out:IKVM.OpenJDK.Jdbc.dll
- -baseaddress:0x5C150000
+ -baseaddress:0x5C120000
-resource:META-INF/services/java.sql.Driver=resources/META-INF/services/java.sql.Driver
-recurse:resources.zip/com/sun/rowset/*
-recurse:resources.zip/javax/sql/*
@@ -1024,7 +1024,7 @@
}
{
-out:IKVM.OpenJDK.Remoting.dll
- -baseaddress:0x5C2D0000
+ -baseaddress:0x5C2A0000
-recurse:resources.zip/sun/rmi/*
rmistubs/com/sun/jndi/rmi/registry/*.class
rmistubs/java/rmi/activation/*.class
@@ -1050,7 +1050,7 @@
}
{
-out:IKVM.OpenJDK.Beans.dll
- -baseaddress:0x5C420000
+ -baseaddress:0x5C3F0000
-resource:META-INF/mailcap.default=@OPENJDK@/jaxws/src/share/jaf_classes/META-INF/mailcap.default
-resource:META-INF/mimetypes.default=@OPENJDK@/jaxws/src/share/jaf_classes/META-INF/mimetypes.default
@OPENJDK@/jaxws/src/share/jaf_classes/com/sun/activation/registries/*.class
@@ -1066,7 +1066,7 @@
}
{
-out:IKVM.OpenJDK.Media.dll
- -baseaddress:0x5C510000
+ -baseaddress:0x5C4E0000
-resource:META-INF/services/javax.print.PrintServiceLookup=@OPENJDK@/jdk/src/windows/classes/sun/print/services/javax.print.PrintServiceLookup
-resource:META-INF/services/javax.print.StreamPrintServiceFactory=@OPENJDK@/jdk/src/windows/classes/sun/print/services/javax.print.StreamPrintServiceFactory
-resource:META-INF/services/javax.sound.midi.spi.MidiDeviceProvider=@OPENJDK@/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.MidiDeviceProvider
@@ -1113,7 +1113,7 @@
}
{
-out:IKVM.OpenJDK.Nashorn.dll
- -baseaddress:0x5C780000
+ -baseaddress:0x5C750000
-resource:META-INF/services/javax.script.ScriptEngineFactory=@OPENJDK@/nashorn/src/META-INF/services/javax.script.ScriptEngineFactory
-resource:jdk/nashorn/internal/runtime/resources/version.properties=resources/nashorn/version.properties
-recurse:@OPENJDK@/nashorn/src/*.js
@@ -1151,7 +1151,7 @@
}
{
-out:IKVM.OpenJDK.Localedata.dll
- -baseaddress:0x5CCF0000
+ -baseaddress:0x5CCC0000
@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/*.class
@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ar/*.class
@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/be/*.class
@@ -1252,7 +1252,7 @@
}
{
-out:IKVM.OpenJDK.Cldrdata.dll
- -baseaddress:0x5D1D0000
+ -baseaddress:0x5D1A0000
@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/*.class
@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/aa/*.class
@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/af/*.class
diff --git a/runtime/ClassFile.cs b/runtime/ClassFile.cs
index 89e66874..9752fe83 100644
--- a/runtime/ClassFile.cs
+++ b/runtime/ClassFile.cs
@@ -51,6 +51,7 @@ namespace IKVM.Internal
LineNumberTable = 2,
RelaxedClassNameValidation = 4,
TrustedAnnotations = 8,
+ RemoveAssertions = 16,
}
sealed class ClassFile
@@ -68,6 +69,7 @@ namespace IKVM.Internal
private const ushort FLAG_LAMBDAFORM_COMPILED = 0x800;
private const ushort FLAG_LAMBDAFORM_HIDDEN = 0x1000;
private const ushort FLAG_FORCEINLINE = 0x2000;
+ private const ushort FLAG_HAS_ASSERTIONS = 0x4000;
private ConstantPoolItemClass[] interfaces;
private Field[] fields;
private Method[] methods;
@@ -346,6 +348,10 @@ namespace IKVM.Internal
{
throw new ClassFormatError("{0} (Method \"{1}\" has illegal signature \"{2}\")", Name, name, sig);
}
+ if((options & ClassFileParseOptions.RemoveAssertions) != 0 && methods[i].IsClassInitializer)
+ {
+ RemoveAssertionInit(methods[i]);
+ }
}
}
CheckDuplicates<FieldOrMethod>(methods, "Repetitive method name/signature");
@@ -1311,6 +1317,14 @@ namespace IKVM.Internal
flags |= FLAG_MASK_INTERNAL;
}
+ internal bool HasAssertions
+ {
+ get
+ {
+ return (flags & FLAG_HAS_ASSERTIONS) != 0;
+ }
+ }
+
internal bool HasInitializedFields
{
get
@@ -2706,6 +2720,11 @@ namespace IKVM.Internal
}
}
+ internal void PatchConstantValue(object value)
+ {
+ constantValue = value;
+ }
+
internal bool IsStaticFinalConstant
{
get { return (access_flags & (Modifiers.Final | Modifiers.Static)) == (Modifiers.Final | Modifiers.Static) && constantValue != null; }
@@ -3864,5 +3883,123 @@ namespace IKVM.Internal
}
return null;
}
+
+ private void RemoveAssertionInit(Method m)
+ {
+ /* We match the following code sequence:
+ * 0 ldc <class X>
+ * 2 invokevirtual <Method java/lang/Class desiredAssertionStatus()Z>
+ * 5 ifne 12
+ * 8 iconst_1
+ * 9 goto 13
+ * 12 iconst_0
+ * 13 putstatic <Field <this class> boolean <static final field>>
+ */
+ ConstantPoolItemFieldref fieldref;
+ Field field;
+ if (m.Instructions[0].NormalizedOpCode == NormalizedByteCode.__ldc && SafeIsConstantPoolClass(m.Instructions[0].Arg1)
+ && m.Instructions[1].NormalizedOpCode == NormalizedByteCode.__invokevirtual && IsDesiredAssertionStatusMethodref(m.Instructions[1].Arg1)
+ && m.Instructions[2].NormalizedOpCode == NormalizedByteCode.__ifne && m.Instructions[2].TargetIndex == 5
+ && m.Instructions[3].NormalizedOpCode == NormalizedByteCode.__iconst && m.Instructions[3].Arg1 == 1
+ && m.Instructions[4].NormalizedOpCode == NormalizedByteCode.__goto && m.Instructions[4].TargetIndex == 6
+ && m.Instructions[5].NormalizedOpCode == NormalizedByteCode.__iconst && m.Instructions[5].Arg1 == 0
+ && m.Instructions[6].NormalizedOpCode == NormalizedByteCode.__putstatic && (fieldref = SafeGetFieldref(m.Instructions[6].Arg1)) != null
+ && fieldref.Class == Name && fieldref.Signature == "Z"
+ && (field = GetField(fieldref.Name, fieldref.Signature)) != null
+ && field.IsStatic && field.IsFinal
+ && !HasBranchIntoRegion(m.Instructions, 7, m.Instructions.Length, 0, 7)
+ && !HasStaticFieldWrite(m.Instructions, 7, m.Instructions.Length, field)
+ && !HasExceptionHandlerInRegion(m.ExceptionTable, 0, 7))
+ {
+ field.PatchConstantValue(true);
+ m.Instructions[0].PatchOpCode(NormalizedByteCode.__goto, 7);
+ flags |= FLAG_HAS_ASSERTIONS;
+ }
+ }
+
+ private bool IsDesiredAssertionStatusMethodref(int cpi)
+ {
+ ConstantPoolItemMethodref method = SafeGetMethodref(cpi) as ConstantPoolItemMethodref;
+ return method != null
+ && method.Class == "java.lang.Class"
+ && method.Name == "desiredAssertionStatus"
+ && method.Signature == "()Z";
+ }
+
+ private static bool HasBranchIntoRegion(Method.Instruction[] instructions, int checkStart, int checkEnd, int regionStart, int regionEnd)
+ {
+ for (int i = checkStart; i < checkEnd; i++)
+ {
+ switch (instructions[i].NormalizedOpCode)
+ {
+ case NormalizedByteCode.__ifeq:
+ case NormalizedByteCode.__ifne:
+ case NormalizedByteCode.__iflt:
+ case NormalizedByteCode.__ifge:
+ case NormalizedByteCode.__ifgt:
+ case NormalizedByteCode.__ifle:
+ case NormalizedByteCode.__if_icmpeq:
+ case NormalizedByteCode.__if_icmpne:
+ case NormalizedByteCode.__if_icmplt:
+ case NormalizedByteCode.__if_icmpge:
+ case NormalizedByteCode.__if_icmpgt:
+ case NormalizedByteCode.__if_icmple:
+ case NormalizedByteCode.__if_acmpeq:
+ case NormalizedByteCode.__if_acmpne:
+ case NormalizedByteCode.__ifnull:
+ case NormalizedByteCode.__ifnonnull:
+ case NormalizedByteCode.__goto:
+ case NormalizedByteCode.__jsr:
+ if (instructions[i].TargetIndex > regionStart && instructions[i].TargetIndex < regionEnd)
+ {
+ return true;
+ }
+ break;
+ case NormalizedByteCode.__tableswitch:
+ case NormalizedByteCode.__lookupswitch:
+ if (instructions[i].DefaultTarget > regionStart && instructions[i].DefaultTarget < regionEnd)
+ {
+ return true;
+ }
+ for (int j = 0; j < instructions[i].SwitchEntryCount; j++)
+ {
+ if (instructions[i].GetSwitchTargetIndex(j) > regionStart && instructions[i].GetSwitchTargetIndex(j) < regionEnd)
+ {
+ return true;
+ }
+ }
+ break;
+ }
+ }
+ return false;
+ }
+
+ private bool HasStaticFieldWrite(Method.Instruction[] instructions, int checkStart, int checkEnd, Field field)
+ {
+ for (int i = checkStart; i < checkEnd; i++)
+ {
+ if (instructions[i].NormalizedOpCode == NormalizedByteCode.__putstatic)
+ {
+ ConstantPoolItemFieldref fieldref = SafeGetFieldref(instructions[i].Arg1);
+ if (fieldref != null && fieldref.Class == Name && fieldref.Name == field.Name && fieldref.Signature == field.Signature)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private static bool HasExceptionHandlerInRegion(Method.ExceptionTableEntry[] entries, int regionStart, int regionEnd)
+ {
+ for (int i = 0; i < entries.Length; i++)
+ {
+ if (entries[i].handlerIndex > regionStart && entries[i].handlerIndex < regionEnd)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
}
}
diff --git a/runtime/ClassLoaderWrapper.cs b/runtime/ClassLoaderWrapper.cs
index 48a60068..d04d05dd 100644
--- a/runtime/ClassLoaderWrapper.cs
+++ b/runtime/ClassLoaderWrapper.cs
@@ -1495,6 +1495,10 @@ namespace IKVM.Internal
{
cfp |= ClassFileParseOptions.TrustedAnnotations;
}
+ if (RemoveAsserts)
+ {
+ cfp |= ClassFileParseOptions.RemoveAssertions;
+ }
return cfp;
#else
ClassFileParseOptions cfp = ClassFileParseOptions.LineNumberTable;
diff --git a/runtime/DynamicTypeWrapper.cs b/runtime/DynamicTypeWrapper.cs
index 6b1f19c0..72685c14 100644
--- a/runtime/DynamicTypeWrapper.cs
+++ b/runtime/DynamicTypeWrapper.cs
@@ -1147,7 +1147,20 @@ namespace IKVM.Internal
noop = true;
for (int i = 0; i < m.Instructions.Length; i++)
{
- NormalizedByteCode bc = m.Instructions[i].NormalizedOpCode;
+ NormalizedByteCode bc;
+ while ((bc = m.Instructions[i].NormalizedOpCode) == NormalizedByteCode.__goto)
+ {
+ int target = m.Instructions[i].TargetIndex;
+ if (target <= i)
+ {
+ // backward branch means we can't do anything
+ noop = false;
+ return false;
+ }
+ // we must skip the unused instructions because the "remove assertions" optimization
+ // uses a goto to remove the (now unused) code
+ i = target;
+ }
if (bc == NormalizedByteCode.__getstatic || bc == NormalizedByteCode.__putstatic)
{
ClassFile.ConstantPoolItemFieldref fld = classFile.SafeGetFieldref(m.Instructions[i].Arg1);
diff --git a/runtime/verifier.cs b/runtime/verifier.cs
index b9c5991a..fdeb809d 100644
--- a/runtime/verifier.cs
+++ b/runtime/verifier.cs
@@ -2572,19 +2572,9 @@ sealed class MethodAnalyzer
// Optimization pass
if (classLoader.RemoveAsserts)
{
- FieldWrapper assertionsDisabled = null;
- foreach (FieldWrapper fw in wrapper.GetFields())
- {
- // HACK we assume that all compilers use the same name for this field (ecj and javac do)
- if (fw.Name == "$assertionsDisabled" && fw.Signature == "Z"
- && (fw.Modifiers & (IKVM.Attributes.Modifiers.AccessMask | IKVM.Attributes.Modifiers.Final | IKVM.Attributes.Modifiers.Static | IKVM.Attributes.Modifiers.Synthetic))
- == (IKVM.Attributes.Modifiers.Static | IKVM.Attributes.Modifiers.Final | IKVM.Attributes.Modifiers.Synthetic))
- {
- assertionsDisabled = fw;
- break;
- }
- }
- if (assertionsDisabled != null)
+ // While the optimization is general, in practice it never happens that a getstatic is used on a final field,
+ // so we only look for this if assert initialization has been optimized out.
+ if (classFile.HasAssertions)
{
// compute branch targets
InstructionFlags[] flags = MethodAnalyzer.ComputePartialReachability(codeInfo, method.Instructions, exceptions, 0, false);
@@ -2596,12 +2586,10 @@ sealed class MethodAnalyzer
&& instructions[i + 1].TargetIndex > i
&& (flags[i + 1] & InstructionFlags.BranchTarget) == 0)
{
- ClassFile.ConstantPoolItemFieldref cpi = classFile.GetFieldref(instructions[i].Arg1);
- if (cpi.GetField() == assertionsDisabled)
+ ConstantFieldWrapper field = classFile.GetFieldref(instructions[i].Arg1).GetField() as ConstantFieldWrapper;
+ if (field != null && field.FieldTypeWrapper == PrimitiveTypeWrapper.BOOLEAN && (bool)field.GetConstantValue())
{
- // We've found an assertion. We patch the instruction to branch around it so that
- // the assertion code will be unreachable (and hence optimized away).
- // Note that the goto will be optimized away later by the code generator (which removes unnecessary branches).
+ // We know the branch will always be taken, so we replace the getstatic/ifne by a goto.
instructions[i].PatchOpCode(NormalizedByteCode.__goto, instructions[i + 1].TargetIndex);
}
}