diff --git a/src/IKVM.Java/map.xml b/src/IKVM.Java/map.xml index 2b7f194e3b..a970136c01 100644 --- a/src/IKVM.Java/map.xml +++ b/src/IKVM.Java/map.xml @@ -958,7 +958,7 @@ - + @@ -994,7 +994,7 @@ - + @@ -1005,7 +1005,7 @@ - + @@ -1016,7 +1016,7 @@ - + @@ -1025,7 +1025,7 @@ - + @@ -1071,7 +1071,7 @@ - + @@ -1106,7 +1106,7 @@ - + @@ -1144,7 +1144,7 @@ - + @@ -1189,7 +1189,7 @@ - + @@ -1249,7 +1249,7 @@ - + @@ -1290,7 +1290,7 @@ - + @@ -1306,7 +1306,7 @@ - + @@ -1327,7 +1327,7 @@ - + @@ -1335,7 +1335,7 @@ - + @@ -1347,21 +1347,21 @@ - + - + - + - + @@ -1395,23 +1395,23 @@ - + - + - + - + - + @@ -1437,12 +1437,12 @@ - + - + diff --git a/src/IKVM.Runtime/AccessStubConstructorMethodWrapper.cs b/src/IKVM.Runtime/AccessStubConstructorMethodWrapper.cs index a459f93fcc..a12bdcdb50 100644 --- a/src/IKVM.Runtime/AccessStubConstructorMethodWrapper.cs +++ b/src/IKVM.Runtime/AccessStubConstructorMethodWrapper.cs @@ -33,7 +33,7 @@ Jeroen Frijters using System.Reflection.Emit; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { sealed class AccessStubConstructorMethodWrapper : SmartMethodWrapper diff --git a/src/IKVM.Runtime/AccessStubMethodWrapper.cs b/src/IKVM.Runtime/AccessStubMethodWrapper.cs index 6f2370b033..f3b0c1e01a 100644 --- a/src/IKVM.Runtime/AccessStubMethodWrapper.cs +++ b/src/IKVM.Runtime/AccessStubMethodWrapper.cs @@ -33,7 +33,7 @@ Jeroen Frijters using System.Reflection.Emit; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { sealed class AccessStubMethodWrapper : SmartMethodWrapper diff --git a/src/IKVM.Runtime/Accessors/FieldAccessor.cs b/src/IKVM.Runtime/Accessors/FieldAccessor.cs index 846734ef9d..ae6de18a0d 100644 --- a/src/IKVM.Runtime/Accessors/FieldAccessor.cs +++ b/src/IKVM.Runtime/Accessors/FieldAccessor.cs @@ -4,8 +4,6 @@ using System.Reflection.Emit; using System.Threading; -using IKVM.Internal; - namespace IKVM.Runtime.Accessors { diff --git a/src/IKVM.Runtime/Accessors/MethodAccessor.cs b/src/IKVM.Runtime/Accessors/MethodAccessor.cs index 938437443e..e4adcdf015 100644 --- a/src/IKVM.Runtime/Accessors/MethodAccessor.cs +++ b/src/IKVM.Runtime/Accessors/MethodAccessor.cs @@ -3,8 +3,6 @@ using System.Reflection; using System.Reflection.Emit; -using IKVM.Internal; - namespace IKVM.Runtime.Accessors { diff --git a/src/IKVM.Runtime/Accessors/PropertyAccessor.cs b/src/IKVM.Runtime/Accessors/PropertyAccessor.cs index 5cc554b8bb..43aa1c0cc3 100644 --- a/src/IKVM.Runtime/Accessors/PropertyAccessor.cs +++ b/src/IKVM.Runtime/Accessors/PropertyAccessor.cs @@ -2,8 +2,6 @@ using System.Reflection; using System.Reflection.Emit; -using IKVM.Internal; - namespace IKVM.Runtime.Accessors { diff --git a/src/IKVM.Runtime/Annotation.cs b/src/IKVM.Runtime/Annotation.cs index b95a73ffef..d9767a64bd 100644 --- a/src/IKVM.Runtime/Annotation.cs +++ b/src/IKVM.Runtime/Annotation.cs @@ -41,7 +41,7 @@ Jeroen Frijters using IKVM.Tools.Importer; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { abstract class Annotation diff --git a/src/IKVM.Runtime/AnonymousTypeWrapper.cs b/src/IKVM.Runtime/AnonymousTypeWrapper.cs index 64026ff51c..30805adb9e 100644 --- a/src/IKVM.Runtime/AnonymousTypeWrapper.cs +++ b/src/IKVM.Runtime/AnonymousTypeWrapper.cs @@ -39,7 +39,7 @@ Jeroen Frijters using IKVM.Tools.Importer; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { #if !IMPORTER && !EXPORTER diff --git a/src/IKVM.Runtime/ArrayTypeWrapper.cs b/src/IKVM.Runtime/ArrayTypeWrapper.cs index 7b5a7032d0..c3de24514a 100644 --- a/src/IKVM.Runtime/ArrayTypeWrapper.cs +++ b/src/IKVM.Runtime/ArrayTypeWrapper.cs @@ -39,7 +39,7 @@ Jeroen Frijters using IKVM.Tools.Importer; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { sealed class ArrayTypeWrapper : TypeWrapper { diff --git a/src/IKVM.Runtime/ArrayUtil.cs b/src/IKVM.Runtime/ArrayUtil.cs index 546436720b..f684e22d60 100644 --- a/src/IKVM.Runtime/ArrayUtil.cs +++ b/src/IKVM.Runtime/ArrayUtil.cs @@ -23,7 +23,7 @@ Jeroen Frijters */ using System; -namespace IKVM.Internal +namespace IKVM.Runtime { static class ArrayUtil diff --git a/src/IKVM.Runtime/AssemblyClassLoader.cs b/src/IKVM.Runtime/AssemblyClassLoader.cs index fbd581ac16..e5360edf6e 100644 --- a/src/IKVM.Runtime/AssemblyClassLoader.cs +++ b/src/IKVM.Runtime/AssemblyClassLoader.cs @@ -47,7 +47,7 @@ Jeroen Frijters using IKVM.Tools.Importer; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { internal class AssemblyClassLoader : ClassLoaderWrapper diff --git a/src/IKVM.Runtime/Assertions.cs b/src/IKVM.Runtime/Assertions.cs index 02ba076e2d..9c50d0bb29 100644 --- a/src/IKVM.Runtime/Assertions.cs +++ b/src/IKVM.Runtime/Assertions.cs @@ -24,7 +24,7 @@ Jeroen Frijters using System; using System.Globalization; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Runtime { diff --git a/src/IKVM.Runtime/AttributeHelper.cs b/src/IKVM.Runtime/AttributeHelper.cs index 476120b10f..2391daa94f 100644 --- a/src/IKVM.Runtime/AttributeHelper.cs +++ b/src/IKVM.Runtime/AttributeHelper.cs @@ -48,7 +48,7 @@ Jeroen Frijters using IKVM.Tools.Importer; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { static class AttributeHelper diff --git a/src/IKVM.Runtime/Attributes/AnnotationAttributeAttribute.cs b/src/IKVM.Runtime/Attributes/AnnotationAttributeAttribute.cs index fab68f8bef..87d7423de2 100644 --- a/src/IKVM.Runtime/Attributes/AnnotationAttributeAttribute.cs +++ b/src/IKVM.Runtime/Attributes/AnnotationAttributeAttribute.cs @@ -23,7 +23,7 @@ Jeroen Frijters */ using System; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Attributes { diff --git a/src/IKVM.Runtime/Attributes/AnnotationDefaultAttribute.cs b/src/IKVM.Runtime/Attributes/AnnotationDefaultAttribute.cs index ed432367c9..633652b30e 100644 --- a/src/IKVM.Runtime/Attributes/AnnotationDefaultAttribute.cs +++ b/src/IKVM.Runtime/Attributes/AnnotationDefaultAttribute.cs @@ -23,17 +23,15 @@ Jeroen Frijters */ using System; -using IKVM.Internal; - -#if IMPORTER || EXPORTER -using Type = IKVM.Reflection.Type; -#endif +using IKVM.Runtime; namespace IKVM.Attributes { + [AttributeUsage(AttributeTargets.Method)] public sealed class AnnotationDefaultAttribute : Attribute { + public const byte TAG_ENUM = (byte)'e'; public const byte TAG_CLASS = (byte)'c'; public const byte TAG_ANNOTATION = (byte)'@'; diff --git a/src/IKVM.Runtime/Attributes/ConstantPoolAttribute.cs b/src/IKVM.Runtime/Attributes/ConstantPoolAttribute.cs index 2b43038bf8..d1c26a115b 100644 --- a/src/IKVM.Runtime/Attributes/ConstantPoolAttribute.cs +++ b/src/IKVM.Runtime/Attributes/ConstantPoolAttribute.cs @@ -24,17 +24,15 @@ Jeroen Frijters using System; using System.Collections.Generic; -using IKVM.Internal; - -#if IMPORTER || EXPORTER -using Type = IKVM.Reflection.Type; -#endif +using IKVM.Runtime; namespace IKVM.Attributes { + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] public sealed class ConstantPoolAttribute : Attribute { + internal readonly object[] constantPool; public ConstantPoolAttribute(object[] constantPool) @@ -112,5 +110,7 @@ private static object Escape(object obj) } return obj; } + } + } diff --git a/src/IKVM.Runtime/Attributes/DynamicAnnotationAttribute.cs b/src/IKVM.Runtime/Attributes/DynamicAnnotationAttribute.cs index f984fdf32a..d8913c6655 100644 --- a/src/IKVM.Runtime/Attributes/DynamicAnnotationAttribute.cs +++ b/src/IKVM.Runtime/Attributes/DynamicAnnotationAttribute.cs @@ -23,15 +23,13 @@ Jeroen Frijters */ using System; -#if IMPORTER || EXPORTER -using Type = IKVM.Reflection.Type; -#endif - namespace IKVM.Attributes { + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Parameter, AllowMultiple = false)] public sealed class DynamicAnnotationAttribute : Attribute { + private readonly object[] definition; public DynamicAnnotationAttribute(object[] definition) @@ -43,5 +41,7 @@ public object[] Definition { get { return definition; } } + } + } diff --git a/src/IKVM.Runtime/Attributes/EnclosingMethodAttribute.cs b/src/IKVM.Runtime/Attributes/EnclosingMethodAttribute.cs index d45ba2363b..07c02a3674 100644 --- a/src/IKVM.Runtime/Attributes/EnclosingMethodAttribute.cs +++ b/src/IKVM.Runtime/Attributes/EnclosingMethodAttribute.cs @@ -23,7 +23,7 @@ Jeroen Frijters */ using System; -using IKVM.Internal; +using IKVM.Runtime; #if IMPORTER || EXPORTER using Type = IKVM.Reflection.Type; @@ -31,9 +31,11 @@ Jeroen Frijters namespace IKVM.Attributes { + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] public sealed class EnclosingMethodAttribute : Attribute { + private string className; private string methodName; private string methodSig; @@ -48,34 +50,17 @@ public EnclosingMethodAttribute(string className, string methodName, string meth internal EnclosingMethodAttribute SetClassName(Type type) { if (className == null) - { - className = IKVM.Internal.ClassLoaderWrapper.GetWrapperFromType(type.DeclaringType).Name; - } + className = IKVM.Runtime.ClassLoaderWrapper.GetWrapperFromType(type.DeclaringType).Name; + return this; } - public string ClassName - { - get - { - return className; - } - } + public string ClassName => className; - public string MethodName - { - get - { - return methodName; - } - } + public string MethodName => methodName; + + public string MethodSignature => methodSig; + + } - public string MethodSignature - { - get - { - return methodSig; - } - } - } } diff --git a/src/IKVM.Runtime/Attributes/ExceptionIsUnsafeForMappingAttribute.cs b/src/IKVM.Runtime/Attributes/ExceptionIsUnsafeForMappingAttribute.cs index 66c0fa11d6..51ca7a45a9 100644 --- a/src/IKVM.Runtime/Attributes/ExceptionIsUnsafeForMappingAttribute.cs +++ b/src/IKVM.Runtime/Attributes/ExceptionIsUnsafeForMappingAttribute.cs @@ -23,14 +23,13 @@ Jeroen Frijters */ using System; -#if IMPORTER || EXPORTER -using Type = IKVM.Reflection.Type; -#endif - namespace IKVM.Attributes { + [AttributeUsage(AttributeTargets.Class)] public sealed class ExceptionIsUnsafeForMappingAttribute : Attribute { + } + } diff --git a/src/IKVM.Runtime/Attributes/GhostInterfaceAttribute.cs b/src/IKVM.Runtime/Attributes/GhostInterfaceAttribute.cs index 974a972609..432066719e 100644 --- a/src/IKVM.Runtime/Attributes/GhostInterfaceAttribute.cs +++ b/src/IKVM.Runtime/Attributes/GhostInterfaceAttribute.cs @@ -23,14 +23,13 @@ Jeroen Frijters */ using System; -#if IMPORTER || EXPORTER -using Type = IKVM.Reflection.Type; -#endif - namespace IKVM.Attributes { + [AttributeUsage(AttributeTargets.Struct)] public sealed class GhostInterfaceAttribute : Attribute { + } + } diff --git a/src/IKVM.Runtime/Attributes/HideFromJavaAttribute.cs b/src/IKVM.Runtime/Attributes/HideFromJavaAttribute.cs index e999de0ed6..d9d6e47b62 100644 --- a/src/IKVM.Runtime/Attributes/HideFromJavaAttribute.cs +++ b/src/IKVM.Runtime/Attributes/HideFromJavaAttribute.cs @@ -23,10 +23,6 @@ Jeroen Frijters */ using System; -#if IMPORTER || EXPORTER -using Type = IKVM.Reflection.Type; -#endif - namespace IKVM.Attributes { diff --git a/src/IKVM.Runtime/Attributes/HideFromJavaFlags.cs b/src/IKVM.Runtime/Attributes/HideFromJavaFlags.cs index d9e5fabfd4..9101d2ef92 100644 --- a/src/IKVM.Runtime/Attributes/HideFromJavaFlags.cs +++ b/src/IKVM.Runtime/Attributes/HideFromJavaFlags.cs @@ -23,10 +23,6 @@ Jeroen Frijters */ using System; -#if IMPORTER || EXPORTER -using Type = IKVM.Reflection.Type; -#endif - namespace IKVM.Attributes { diff --git a/src/IKVM.Runtime/Attributes/ImplementsAttribute.cs b/src/IKVM.Runtime/Attributes/ImplementsAttribute.cs index e83822a2c4..4bd1bb3fec 100644 --- a/src/IKVM.Runtime/Attributes/ImplementsAttribute.cs +++ b/src/IKVM.Runtime/Attributes/ImplementsAttribute.cs @@ -23,17 +23,15 @@ Jeroen Frijters */ using System; -using IKVM.Internal; - -#if IMPORTER || EXPORTER -using Type = IKVM.Reflection.Type; -#endif +using IKVM.Runtime; namespace IKVM.Attributes { + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] public sealed class ImplementsAttribute : Attribute { + private string[] interfaces; // NOTE this is not CLS compliant, so maybe we should have a couple of overloads @@ -42,12 +40,8 @@ public ImplementsAttribute(string[] interfaces) this.interfaces = UnicodeUtil.UnescapeInvalidSurrogates(interfaces); } - public string[] Interfaces - { - get - { - return interfaces; - } - } - } + public string[] Interfaces => interfaces; + + } + } diff --git a/src/IKVM.Runtime/Attributes/InnerClassAttribute.cs b/src/IKVM.Runtime/Attributes/InnerClassAttribute.cs index d87c44d9ea..08c36ff3f9 100644 --- a/src/IKVM.Runtime/Attributes/InnerClassAttribute.cs +++ b/src/IKVM.Runtime/Attributes/InnerClassAttribute.cs @@ -23,7 +23,7 @@ Jeroen Frijters */ using System; -using IKVM.Internal; +using IKVM.Runtime; #if IMPORTER || EXPORTER using Type = IKVM.Reflection.Type; diff --git a/src/IKVM.Runtime/Attributes/JavaModuleAttribute.cs b/src/IKVM.Runtime/Attributes/JavaModuleAttribute.cs index d004336a58..ff6ab346d4 100644 --- a/src/IKVM.Runtime/Attributes/JavaModuleAttribute.cs +++ b/src/IKVM.Runtime/Attributes/JavaModuleAttribute.cs @@ -23,11 +23,7 @@ Jeroen Frijters */ using System; -using IKVM.Internal; - -#if IMPORTER || EXPORTER -using Type = IKVM.Reflection.Type; -#endif +using IKVM.Runtime; namespace IKVM.Attributes { diff --git a/src/IKVM.Runtime/Attributes/JavaResourceAttribute.cs b/src/IKVM.Runtime/Attributes/JavaResourceAttribute.cs index e4e0207513..c4c3d317a4 100644 --- a/src/IKVM.Runtime/Attributes/JavaResourceAttribute.cs +++ b/src/IKVM.Runtime/Attributes/JavaResourceAttribute.cs @@ -23,16 +23,13 @@ Jeroen Frijters */ using System; -#if IMPORTER || EXPORTER -using Type = IKVM.Reflection.Type; -#endif - namespace IKVM.Attributes { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] public sealed class JavaResourceAttribute : Attribute { + private readonly string javaName; private readonly string resourceName; @@ -42,14 +39,10 @@ public JavaResourceAttribute(string javaName, string resourceName) this.resourceName = resourceName; } - public string JavaName - { - get { return javaName; } - } + public string JavaName => javaName; + + public string ResourceName => resourceName; + + } - public string ResourceName - { - get { return resourceName; } - } - } } diff --git a/src/IKVM.Runtime/Attributes/LineNumberTableAttribute.cs b/src/IKVM.Runtime/Attributes/LineNumberTableAttribute.cs index b5355db5eb..2ce05c73c9 100644 --- a/src/IKVM.Runtime/Attributes/LineNumberTableAttribute.cs +++ b/src/IKVM.Runtime/Attributes/LineNumberTableAttribute.cs @@ -23,15 +23,13 @@ Jeroen Frijters */ using System; -#if IMPORTER || EXPORTER -using Type = IKVM.Reflection.Type; -#endif - namespace IKVM.Attributes { + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor)] public sealed class LineNumberTableAttribute : Attribute { + private byte[] table; public LineNumberTableAttribute(ushort lineno) @@ -249,5 +247,7 @@ public int GetLineNumber(int ilOffset) } return line; } + } + } diff --git a/src/IKVM.Runtime/Attributes/MethodParametersAttribute.cs b/src/IKVM.Runtime/Attributes/MethodParametersAttribute.cs index 2b513a44b9..c592ecafc4 100644 --- a/src/IKVM.Runtime/Attributes/MethodParametersAttribute.cs +++ b/src/IKVM.Runtime/Attributes/MethodParametersAttribute.cs @@ -23,15 +23,13 @@ Jeroen Frijters */ using System; -#if IMPORTER || EXPORTER -using Type = IKVM.Reflection.Type; -#endif - namespace IKVM.Attributes { + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor)] public sealed class MethodParametersAttribute : Attribute { + private readonly Modifiers[] modifiers; public MethodParametersAttribute(Modifiers[] modifiers) @@ -39,14 +37,10 @@ public MethodParametersAttribute(Modifiers[] modifiers) this.modifiers = modifiers; } - public Modifiers[] Modifiers - { - get { return modifiers; } - } + public Modifiers[] Modifiers => modifiers; + + public bool IsMalformed => modifiers == null; + + } - public bool IsMalformed - { - get { return modifiers == null; } - } - } } diff --git a/src/IKVM.Runtime/Attributes/ModifiersAttribute.cs b/src/IKVM.Runtime/Attributes/ModifiersAttribute.cs index 9460ab3308..10b252ffcc 100644 --- a/src/IKVM.Runtime/Attributes/ModifiersAttribute.cs +++ b/src/IKVM.Runtime/Attributes/ModifiersAttribute.cs @@ -23,14 +23,10 @@ Jeroen Frijters */ using System; -#if IMPORTER || EXPORTER -using Type = IKVM.Reflection.Type; -#endif - namespace IKVM.Attributes { - [AttributeUsage(AttributeTargets.All)] + [AttributeUsage(AttributeTargets.All)] public sealed class ModifiersAttribute : Attribute { diff --git a/src/IKVM.Runtime/Attributes/NameSigAttribute.cs b/src/IKVM.Runtime/Attributes/NameSigAttribute.cs index 7a995c9ba3..c4aa2b5cbe 100644 --- a/src/IKVM.Runtime/Attributes/NameSigAttribute.cs +++ b/src/IKVM.Runtime/Attributes/NameSigAttribute.cs @@ -23,17 +23,15 @@ Jeroen Frijters */ using System; -using IKVM.Internal; - -#if IMPORTER || EXPORTER -using Type = IKVM.Reflection.Type; -#endif +using IKVM.Runtime; namespace IKVM.Attributes { + [AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Field)] public sealed class NameSigAttribute : Attribute { + private string name; private string sig; @@ -43,20 +41,10 @@ public NameSigAttribute(string name, string sig) this.sig = UnicodeUtil.UnescapeInvalidSurrogates(sig); } - public string Name - { - get - { - return name; - } - } + public string Name => name; + + public string Sig => sig; + + } - public string Sig - { - get - { - return sig; - } - } - } } diff --git a/src/IKVM.Runtime/Attributes/NoPackagePrefixAttribute.cs b/src/IKVM.Runtime/Attributes/NoPackagePrefixAttribute.cs index 13b6115c4b..d8dccb92fa 100644 --- a/src/IKVM.Runtime/Attributes/NoPackagePrefixAttribute.cs +++ b/src/IKVM.Runtime/Attributes/NoPackagePrefixAttribute.cs @@ -23,14 +23,13 @@ Jeroen Frijters */ using System; -#if IMPORTER || EXPORTER -using Type = IKVM.Reflection.Type; -#endif - namespace IKVM.Attributes { + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Assembly)] public sealed class NoPackagePrefixAttribute : Attribute { + } + } diff --git a/src/IKVM.Runtime/Attributes/NonNestedInnerClassAttribute.cs b/src/IKVM.Runtime/Attributes/NonNestedInnerClassAttribute.cs index 1a4b41201a..3094e86e6b 100644 --- a/src/IKVM.Runtime/Attributes/NonNestedInnerClassAttribute.cs +++ b/src/IKVM.Runtime/Attributes/NonNestedInnerClassAttribute.cs @@ -23,17 +23,15 @@ Jeroen Frijters */ using System; -using IKVM.Internal; - -#if IMPORTER || EXPORTER -using Type = IKVM.Reflection.Type; -#endif +using IKVM.Runtime; namespace IKVM.Attributes { + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true)] public sealed class NonNestedInnerClassAttribute : Attribute { + private string innerClassName; public NonNestedInnerClassAttribute(string innerClassName) @@ -41,12 +39,8 @@ public NonNestedInnerClassAttribute(string innerClassName) this.innerClassName = UnicodeUtil.UnescapeInvalidSurrogates(innerClassName); } - public string InnerClassName - { - get - { - return innerClassName; - } - } + public string InnerClassName => innerClassName; + } + } diff --git a/src/IKVM.Runtime/Attributes/NonNestedOuterClassAttribute.cs b/src/IKVM.Runtime/Attributes/NonNestedOuterClassAttribute.cs index 92cfca60fc..614970a8ed 100644 --- a/src/IKVM.Runtime/Attributes/NonNestedOuterClassAttribute.cs +++ b/src/IKVM.Runtime/Attributes/NonNestedOuterClassAttribute.cs @@ -23,17 +23,15 @@ Jeroen Frijters */ using System; -using IKVM.Internal; - -#if IMPORTER || EXPORTER -using Type = IKVM.Reflection.Type; -#endif +using IKVM.Runtime; namespace IKVM.Attributes { + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] public sealed class NonNestedOuterClassAttribute : Attribute { + private string outerClassName; public NonNestedOuterClassAttribute(string outerClassName) @@ -41,12 +39,8 @@ public NonNestedOuterClassAttribute(string outerClassName) this.outerClassName = UnicodeUtil.UnescapeInvalidSurrogates(outerClassName); } - public string OuterClassName - { - get - { - return outerClassName; - } - } - } + public string OuterClassName => outerClassName; + + } + } diff --git a/src/IKVM.Runtime/Attributes/PackageListAttribute.cs b/src/IKVM.Runtime/Attributes/PackageListAttribute.cs index fab144d1d0..f2dcf32f43 100644 --- a/src/IKVM.Runtime/Attributes/PackageListAttribute.cs +++ b/src/IKVM.Runtime/Attributes/PackageListAttribute.cs @@ -23,17 +23,15 @@ Jeroen Frijters */ using System; -using IKVM.Internal; - -#if IMPORTER || EXPORTER -using Type = IKVM.Reflection.Type; -#endif +using IKVM.Runtime; namespace IKVM.Attributes { + [AttributeUsage(AttributeTargets.Module, AllowMultiple = true)] public sealed class PackageListAttribute : Attribute { + internal string jar; internal string[] packages; @@ -43,9 +41,8 @@ public PackageListAttribute(string jar, string[] packages) this.packages = UnicodeUtil.UnescapeInvalidSurrogates(packages); } - public string[] GetPackages() - { - return packages; - } - } + public string[] GetPackages() => packages; + + } + } diff --git a/src/IKVM.Runtime/Attributes/RemappedClassAttribute.cs b/src/IKVM.Runtime/Attributes/RemappedClassAttribute.cs index 7df7b78b3a..522bb201a5 100644 --- a/src/IKVM.Runtime/Attributes/RemappedClassAttribute.cs +++ b/src/IKVM.Runtime/Attributes/RemappedClassAttribute.cs @@ -38,10 +38,12 @@ public sealed class RemappedClassAttribute : Attribute private Type remappedType; #if EXPORTER + public RemappedClassAttribute(string name, System.Type remappedType) { } + #endif public RemappedClassAttribute(string name, Type remappedType) @@ -50,22 +52,10 @@ public RemappedClassAttribute(string name, Type remappedType) this.remappedType = remappedType; } - public string Name - { - get - { - return name; - } - } + public string Name => name; - public Type RemappedType - { - get - { - return remappedType; - } - } + public Type RemappedType => remappedType; - } + } } diff --git a/src/IKVM.Runtime/Attributes/RemappedInterfaceMethodAttribute.cs b/src/IKVM.Runtime/Attributes/RemappedInterfaceMethodAttribute.cs index 322ca38ded..5528b32880 100644 --- a/src/IKVM.Runtime/Attributes/RemappedInterfaceMethodAttribute.cs +++ b/src/IKVM.Runtime/Attributes/RemappedInterfaceMethodAttribute.cs @@ -23,15 +23,13 @@ Jeroen Frijters */ using System; -#if IMPORTER || EXPORTER -using Type = IKVM.Reflection.Type; -#endif - namespace IKVM.Attributes { + [AttributeUsage(AttributeTargets.Interface)] public sealed class RemappedInterfaceMethodAttribute : Attribute { + private string name; private string mappedTo; private string[] throws; @@ -43,28 +41,12 @@ public RemappedInterfaceMethodAttribute(string name, string mappedTo, string[] t this.throws = throws; } - public string Name - { - get - { - return name; - } - } + public string Name => name; - public string MappedTo - { - get - { - return mappedTo; - } - } + public string MappedTo => mappedTo; + + public string[] Throws => throws; + + } - public string[] Throws - { - get - { - return throws; - } - } - } } diff --git a/src/IKVM.Runtime/Attributes/RemappedTypeAttribute.cs b/src/IKVM.Runtime/Attributes/RemappedTypeAttribute.cs index ea7802a026..da10979780 100644 --- a/src/IKVM.Runtime/Attributes/RemappedTypeAttribute.cs +++ b/src/IKVM.Runtime/Attributes/RemappedTypeAttribute.cs @@ -29,28 +29,29 @@ Jeroen Frijters namespace IKVM.Attributes { + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] - public sealed class RemappedTypeAttribute : Attribute - { - private Type type; + public sealed class RemappedTypeAttribute : Attribute + { + + private Type type; #if EXPORTER + public RemappedTypeAttribute(System.Type type) { + } + #endif - public RemappedTypeAttribute(Type type) - { - this.type = type; - } + public RemappedTypeAttribute(Type type) + { + this.type = type; + } + + public Type Type => type; + + } - public Type Type - { - get - { - return type; - } - } - } } diff --git a/src/IKVM.Runtime/Attributes/RuntimeVisibleTypeAnnotationsAttribute.cs b/src/IKVM.Runtime/Attributes/RuntimeVisibleTypeAnnotationsAttribute.cs index ba32d02572..fb0ae54312 100644 --- a/src/IKVM.Runtime/Attributes/RuntimeVisibleTypeAnnotationsAttribute.cs +++ b/src/IKVM.Runtime/Attributes/RuntimeVisibleTypeAnnotationsAttribute.cs @@ -23,10 +23,6 @@ Jeroen Frijters */ using System; -#if IMPORTER || EXPORTER -using Type = IKVM.Reflection.Type; -#endif - namespace IKVM.Attributes { diff --git a/src/IKVM.Runtime/Attributes/SignatureAttribute.cs b/src/IKVM.Runtime/Attributes/SignatureAttribute.cs index d4bb76e89d..7e70976523 100644 --- a/src/IKVM.Runtime/Attributes/SignatureAttribute.cs +++ b/src/IKVM.Runtime/Attributes/SignatureAttribute.cs @@ -23,13 +23,15 @@ Jeroen Frijters */ using System; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Attributes { + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Field)] public sealed class SignatureAttribute : Attribute { + private string signature; public SignatureAttribute(string signature) @@ -37,12 +39,8 @@ public SignatureAttribute(string signature) this.signature = UnicodeUtil.UnescapeInvalidSurrogates(signature); } - public string Signature - { - get - { - return signature; - } - } - } + public string Signature => signature; + + } + } diff --git a/src/IKVM.Runtime/Attributes/ThrowsAttribute.cs b/src/IKVM.Runtime/Attributes/ThrowsAttribute.cs index d77f4efd81..94a481223b 100644 --- a/src/IKVM.Runtime/Attributes/ThrowsAttribute.cs +++ b/src/IKVM.Runtime/Attributes/ThrowsAttribute.cs @@ -23,7 +23,7 @@ Jeroen Frijters */ using System; -using IKVM.Internal; +using IKVM.Runtime; #if IMPORTER || EXPORTER using Type = IKVM.Reflection.Type; @@ -31,9 +31,11 @@ Jeroen Frijters namespace IKVM.Attributes { + [AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method)] public sealed class ThrowsAttribute : Attribute { + internal string[] classes; internal Type[] types; @@ -53,14 +55,10 @@ public ThrowsAttribute(params Type[] types) this.types = types; } - // dotted Java class names (e.g. java.lang.Throwable) - [Obsolete] - public string[] Classes - { - get - { - return classes; - } - } - } + // dotted Java class names (e.g. java.lang.Throwable) + [Obsolete] + public string[] Classes => classes; + + } + } diff --git a/src/IKVM.Runtime/BigEndianBinaryReader.cs b/src/IKVM.Runtime/BigEndianBinaryReader.cs index 587c0b0770..826c4e215c 100644 --- a/src/IKVM.Runtime/BigEndianBinaryReader.cs +++ b/src/IKVM.Runtime/BigEndianBinaryReader.cs @@ -24,215 +24,220 @@ Jeroen Frijters using System; using System.Text; -sealed class BigEndianBinaryReader +namespace IKVM.Runtime { - readonly ReadOnlyMemory buf; + sealed class BigEndianBinaryReader + { - int pos; + readonly ReadOnlyMemory buf; - /// - /// Initializes a new instance. - /// - /// - /// - internal BigEndianBinaryReader(ReadOnlyMemory buf) - { - this.buf = buf; - this.pos = 0; - } + int pos; - internal BigEndianBinaryReader Section(uint length) - { - var br = new BigEndianBinaryReader(buf.Slice(pos, checked((int)length))); - Skip(length); - return br; - } + /// + /// Initializes a new instance. + /// + /// + /// + internal BigEndianBinaryReader(ReadOnlyMemory buf) + { + this.buf = buf; + this.pos = 0; + } - internal bool IsAtEnd => pos == buf.Length; + internal BigEndianBinaryReader Section(uint length) + { + var br = new BigEndianBinaryReader(buf.Slice(pos, checked((int)length))); + Skip(length); + return br; + } - internal int Position => pos; + internal bool IsAtEnd => pos == buf.Length; - internal void Skip(uint count) - { - if (buf.Length - pos < count) - throw new ClassFormatError("Truncated class file"); + internal int Position => pos; - checked + internal void Skip(uint count) { - pos += (int)count; - } - } + if (buf.Length - pos < count) + throw new ClassFormatError("Truncated class file"); - internal byte ReadByte() - { - if (pos == buf.Length) - throw new ClassFormatError("Truncated class file"); + checked + { + pos += (int)count; + } + } - return buf.Span[pos++]; - } + internal byte ReadByte() + { + if (pos == buf.Length) + throw new ClassFormatError("Truncated class file"); - internal sbyte ReadSByte() - { - if (pos == buf.Length) - throw new ClassFormatError("Truncated class file"); + return buf.Span[pos++]; + } - return (sbyte)buf.Span[pos++]; - } + internal sbyte ReadSByte() + { + if (pos == buf.Length) + throw new ClassFormatError("Truncated class file"); - internal double ReadDouble() - { - return BitConverter.Int64BitsToDouble(ReadInt64()); - } + return (sbyte)buf.Span[pos++]; + } - internal short ReadInt16() - { - if (buf.Length - pos < 2) - throw new ClassFormatError("Truncated class file"); + internal double ReadDouble() + { + return BitConverter.Int64BitsToDouble(ReadInt64()); + } - var s = (short)((buf.Span[pos] << 8) + buf.Span[pos + 1]); - pos += 2; + internal short ReadInt16() + { + if (buf.Length - pos < 2) + throw new ClassFormatError("Truncated class file"); - return s; - } + var s = (short)((buf.Span[pos] << 8) + buf.Span[pos + 1]); + pos += 2; - internal int ReadInt32() - { - if (buf.Length - pos < 4) - throw new ClassFormatError("Truncated class file"); + return s; + } - var i = (int)((buf.Span[pos] << 24) + (buf.Span[pos + 1] << 16) + (buf.Span[pos + 2] << 8) + buf.Span[pos + 3]); - pos += 4; - return i; - } + internal int ReadInt32() + { + if (buf.Length - pos < 4) + throw new ClassFormatError("Truncated class file"); - internal long ReadInt64() - { - if (buf.Length - pos < 8) - throw new ClassFormatError("Truncated class file"); - - var i1 = (uint)((buf.Span[pos] << 24) + (buf.Span[pos + 1] << 16) + (buf.Span[pos + 2] << 8) + buf.Span[pos + 3]); - var i2 = (uint)((buf.Span[pos + 4] << 24) + (buf.Span[pos + 5] << 16) + (buf.Span[pos + 6] << 8) + buf.Span[pos + 7]); - var l = (((long)i1) << 32) + i2; - pos += 8; - return l; - } + var i = (int)((buf.Span[pos] << 24) + (buf.Span[pos + 1] << 16) + (buf.Span[pos + 2] << 8) + buf.Span[pos + 3]); + pos += 4; + return i; + } - internal float ReadSingle() - { - return BitConverter.ToSingle(BitConverter.GetBytes(ReadInt32()), 0); - } + internal long ReadInt64() + { + if (buf.Length - pos < 8) + throw new ClassFormatError("Truncated class file"); + + var i1 = (uint)((buf.Span[pos] << 24) + (buf.Span[pos + 1] << 16) + (buf.Span[pos + 2] << 8) + buf.Span[pos + 3]); + var i2 = (uint)((buf.Span[pos + 4] << 24) + (buf.Span[pos + 5] << 16) + (buf.Span[pos + 6] << 8) + buf.Span[pos + 7]); + var l = (((long)i1) << 32) + i2; + pos += 8; + return l; + } - internal unsafe string ReadString(string classFile, int majorVersion) - { - int len = ReadUInt16(); - if (buf.Length - pos < len) - throw new ClassFormatError("{0} (Truncated class file)", classFile); + internal float ReadSingle() + { + return BitConverter.ToSingle(BitConverter.GetBytes(ReadInt32()), 0); + } - // special code path for ASCII strings (which occur *very* frequently) - for (int j = 0; j < len; j++) + internal unsafe string ReadString(string classFile, int majorVersion) { - if (buf.Span[pos + j] == 0 || buf.Span[pos + j] >= 128) + int len = ReadUInt16(); + if (buf.Length - pos < len) + throw new ClassFormatError("{0} (Truncated class file)", classFile); + + // special code path for ASCII strings (which occur *very* frequently) + for (int j = 0; j < len; j++) { - // NOTE we *cannot* use System.Text.UTF8Encoding, because this is *not* compatible - // (esp. for embedded nulls) - char[] ch = new char[len]; - int l = 0; - for (int i = 0; i < len; i++) + if (buf.Span[pos + j] == 0 || buf.Span[pos + j] >= 128) { - int c = buf.Span[pos + i]; - int char2, char3; - switch (c >> 4) + // NOTE we *cannot* use System.Text.UTF8Encoding, because this is *not* compatible + // (esp. for embedded nulls) + char[] ch = new char[len]; + int l = 0; + for (int i = 0; i < len; i++) { - case 0: - if (c == 0) - { - goto default; - } - break; - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - // 0xxxxxxx - break; - case 12: - case 13: - // 110x xxxx 10xx xxxx - char2 = buf.Span[pos + ++i]; - if ((char2 & 0xc0) != 0x80 || i >= len) - { - goto default; - } - c = (((c & 0x1F) << 6) | (char2 & 0x3F)); - if (c < 0x80 && c != 0 && majorVersion >= 48) - { - goto default; - } - break; - case 14: - // 1110 xxxx 10xx xxxx 10xx xxxx - char2 = buf.Span[pos + ++i]; - char3 = buf.Span[pos + ++i]; - if ((char2 & 0xc0) != 0x80 || (char3 & 0xc0) != 0x80 || i >= len) - { - goto default; - } - c = (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); - if (c < 0x800 && majorVersion >= 48) - { - goto default; - } - break; - default: - throw new ClassFormatError("Illegal UTF8 string in constant pool in class file {0}", classFile ?? ""); + int c = buf.Span[pos + i]; + int char2, char3; + switch (c >> 4) + { + case 0: + if (c == 0) + { + goto default; + } + break; + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + // 0xxxxxxx + break; + case 12: + case 13: + // 110x xxxx 10xx xxxx + char2 = buf.Span[pos + ++i]; + if ((char2 & 0xc0) != 0x80 || i >= len) + { + goto default; + } + c = (((c & 0x1F) << 6) | (char2 & 0x3F)); + if (c < 0x80 && c != 0 && majorVersion >= 48) + { + goto default; + } + break; + case 14: + // 1110 xxxx 10xx xxxx 10xx xxxx + char2 = buf.Span[pos + ++i]; + char3 = buf.Span[pos + ++i]; + if ((char2 & 0xc0) != 0x80 || (char3 & 0xc0) != 0x80 || i >= len) + { + goto default; + } + c = (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); + if (c < 0x800 && majorVersion >= 48) + { + goto default; + } + break; + default: + throw new ClassFormatError("Illegal UTF8 string in constant pool in class file {0}", classFile ?? ""); + } + ch[l++] = (char)c; } - ch[l++] = (char)c; + pos += len; + return new string(ch, 0, l); } - pos += len; - return new string(ch, 0, l); } - } #if NETFRAMEWORK - string s; - fixed (byte* p = buf.Slice(pos, len).Span) - s = Encoding.ASCII.GetString(p, buf.Length); + string s; + fixed (byte* p = buf.Slice(pos, len).Span) + s = Encoding.ASCII.GetString(p, buf.Length); #else var s = Encoding.ASCII.GetString(buf.Slice(pos, len).Span); #endif - pos += len; - return s; - } + pos += len; + return s; + } - internal ushort ReadUInt16() - { - if (buf.Length - pos < 2) - throw new ClassFormatError("Truncated class file"); + internal ushort ReadUInt16() + { + if (buf.Length - pos < 2) + throw new ClassFormatError("Truncated class file"); - var s = (ushort)((buf.Span[pos] << 8) + buf.Span[pos + 1]); - pos += 2; - return s; - } + var s = (ushort)((buf.Span[pos] << 8) + buf.Span[pos + 1]); + pos += 2; + return s; + } - internal uint ReadUInt32() - { - if (buf.Length - pos < 4) - throw new ClassFormatError("Truncated class file"); + internal uint ReadUInt32() + { + if (buf.Length - pos < 4) + throw new ClassFormatError("Truncated class file"); - uint i = (uint)((buf.Span[pos] << 24) + (buf.Span[pos + 1] << 16) + (buf.Span[pos + 2] << 8) + buf.Span[pos + 3]); - pos += 4; - return i; - } + uint i = (uint)((buf.Span[pos] << 24) + (buf.Span[pos + 1] << 16) + (buf.Span[pos + 2] << 8) + buf.Span[pos + 3]); + pos += 4; + return i; + } + + internal byte[] ToArray() + { + var res = new byte[buf.Length - pos]; + buf.Slice(pos, res.Length).CopyTo(res); + return res; + } - internal byte[] ToArray() - { - var res = new byte[buf.Length - pos]; - buf.Slice(pos, res.Length).CopyTo(res); - return res; } } diff --git a/src/IKVM.Runtime/Boxer.cs b/src/IKVM.Runtime/Boxer.cs index 932756b103..3439dfb7bb 100644 --- a/src/IKVM.Runtime/Boxer.cs +++ b/src/IKVM.Runtime/Boxer.cs @@ -23,8 +23,9 @@ Jeroen Frijters */ using System; -namespace IKVM.Internal +namespace IKVM.Runtime { + static class Boxer { diff --git a/src/IKVM.Runtime/ByteCode.cs b/src/IKVM.Runtime/ByteCode.cs new file mode 100644 index 0000000000..5670aba9a7 --- /dev/null +++ b/src/IKVM.Runtime/ByteCode.cs @@ -0,0 +1,236 @@ +/* + Copyright (C) 2002, 2004, 2005, 2006 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +namespace IKVM.Runtime +{ + + enum ByteCode : byte + { + + __nop = 0, + __aconst_null = 1, + __iconst_m1 = 2, + __iconst_0 = 3, + __iconst_1 = 4, + __iconst_2 = 5, + __iconst_3 = 6, + __iconst_4 = 7, + __iconst_5 = 8, + __lconst_0 = 9, + __lconst_1 = 10, + __fconst_0 = 11, + __fconst_1 = 12, + __fconst_2 = 13, + __dconst_0 = 14, + __dconst_1 = 15, + __bipush = 16, + __sipush = 17, + __ldc = 18, + __ldc_w = 19, + __ldc2_w = 20, + __iload = 21, + __lload = 22, + __fload = 23, + __dload = 24, + __aload = 25, + __iload_0 = 26, + __iload_1 = 27, + __iload_2 = 28, + __iload_3 = 29, + __lload_0 = 30, + __lload_1 = 31, + __lload_2 = 32, + __lload_3 = 33, + __fload_0 = 34, + __fload_1 = 35, + __fload_2 = 36, + __fload_3 = 37, + __dload_0 = 38, + __dload_1 = 39, + __dload_2 = 40, + __dload_3 = 41, + __aload_0 = 42, + __aload_1 = 43, + __aload_2 = 44, + __aload_3 = 45, + __iaload = 46, + __laload = 47, + __faload = 48, + __daload = 49, + __aaload = 50, + __baload = 51, + __caload = 52, + __saload = 53, + __istore = 54, + __lstore = 55, + __fstore = 56, + __dstore = 57, + __astore = 58, + __istore_0 = 59, + __istore_1 = 60, + __istore_2 = 61, + __istore_3 = 62, + __lstore_0 = 63, + __lstore_1 = 64, + __lstore_2 = 65, + __lstore_3 = 66, + __fstore_0 = 67, + __fstore_1 = 68, + __fstore_2 = 69, + __fstore_3 = 70, + __dstore_0 = 71, + __dstore_1 = 72, + __dstore_2 = 73, + __dstore_3 = 74, + __astore_0 = 75, + __astore_1 = 76, + __astore_2 = 77, + __astore_3 = 78, + __iastore = 79, + __lastore = 80, + __fastore = 81, + __dastore = 82, + __aastore = 83, + __bastore = 84, + __castore = 85, + __sastore = 86, + __pop = 87, + __pop2 = 88, + __dup = 89, + __dup_x1 = 90, + __dup_x2 = 91, + __dup2 = 92, + __dup2_x1 = 93, + __dup2_x2 = 94, + __swap = 95, + __iadd = 96, + __ladd = 97, + __fadd = 98, + __dadd = 99, + __isub = 100, + __lsub = 101, + __fsub = 102, + __dsub = 103, + __imul = 104, + __lmul = 105, + __fmul = 106, + __dmul = 107, + __idiv = 108, + __ldiv = 109, + __fdiv = 110, + __ddiv = 111, + __irem = 112, + __lrem = 113, + __frem = 114, + __drem = 115, + __ineg = 116, + __lneg = 117, + __fneg = 118, + __dneg = 119, + __ishl = 120, + __lshl = 121, + __ishr = 122, + __lshr = 123, + __iushr = 124, + __lushr = 125, + __iand = 126, + __land = 127, + __ior = 128, + __lor = 129, + __ixor = 130, + __lxor = 131, + __iinc = 132, + __i2l = 133, + __i2f = 134, + __i2d = 135, + __l2i = 136, + __l2f = 137, + __l2d = 138, + __f2i = 139, + __f2l = 140, + __f2d = 141, + __d2i = 142, + __d2l = 143, + __d2f = 144, + __i2b = 145, + __i2c = 146, + __i2s = 147, + __lcmp = 148, + __fcmpl = 149, + __fcmpg = 150, + __dcmpl = 151, + __dcmpg = 152, + __ifeq = 153, + __ifne = 154, + __iflt = 155, + __ifge = 156, + __ifgt = 157, + __ifle = 158, + __if_icmpeq = 159, + __if_icmpne = 160, + __if_icmplt = 161, + __if_icmpge = 162, + __if_icmpgt = 163, + __if_icmple = 164, + __if_acmpeq = 165, + __if_acmpne = 166, + __goto = 167, + __jsr = 168, + __ret = 169, + __tableswitch = 170, + __lookupswitch = 171, + __ireturn = 172, + __lreturn = 173, + __freturn = 174, + __dreturn = 175, + __areturn = 176, + __return = 177, + __getstatic = 178, + __putstatic = 179, + __getfield = 180, + __putfield = 181, + __invokevirtual = 182, + __invokespecial = 183, + __invokestatic = 184, + __invokeinterface = 185, + __invokedynamic = 186, + __new = 187, + __newarray = 188, + __anewarray = 189, + __arraylength = 190, + __athrow = 191, + __checkcast = 192, + __instanceof = 193, + __monitorenter = 194, + __monitorexit = 195, + __wide = 196, + __multianewarray = 197, + __ifnull = 198, + __ifnonnull = 199, + __goto_w = 200, + __jsr_w = 201 + + } + +} diff --git a/src/IKVM.Runtime/ByteCodeFlags.cs b/src/IKVM.Runtime/ByteCodeFlags.cs index 629bdac36e..618565e945 100644 --- a/src/IKVM.Runtime/ByteCodeFlags.cs +++ b/src/IKVM.Runtime/ByteCodeFlags.cs @@ -23,12 +23,17 @@ Jeroen Frijters */ using System; -[Flags] -enum ByteCodeFlags : byte +namespace IKVM.Runtime { - None = 0, - FixedArg = 1, - CannotThrow = 2 + [Flags] + enum ByteCodeFlags : byte + { + + None = 0, + FixedArg = 1, + CannotThrow = 2 + + } } diff --git a/src/IKVM.Runtime/ByteCodeFlowControl.cs b/src/IKVM.Runtime/ByteCodeFlowControl.cs index 11252d7b9a..2a5eace55d 100644 --- a/src/IKVM.Runtime/ByteCodeFlowControl.cs +++ b/src/IKVM.Runtime/ByteCodeFlowControl.cs @@ -22,12 +22,17 @@ Jeroen Frijters */ -enum ByteCodeFlowControl : byte +namespace IKVM.Runtime { - Next, - Branch, - CondBranch, - Return, - Throw, - Switch, + + enum ByteCodeFlowControl : byte + { + Next, + Branch, + CondBranch, + Return, + Throw, + Switch, + } + } diff --git a/src/IKVM.Runtime/ByteCodeHelper.cs b/src/IKVM.Runtime/ByteCodeHelper.cs index 95f99ff5a7..70af395a14 100644 --- a/src/IKVM.Runtime/ByteCodeHelper.cs +++ b/src/IKVM.Runtime/ByteCodeHelper.cs @@ -29,7 +29,6 @@ Jeroen Frijters using IKVM.Attributes; using IKVM.ByteCode; -using IKVM.Internal; #if IMPORTER || EXPORTER using IKVM.Reflection; diff --git a/src/IKVM.Runtime/ByteCodeHelperMethods.cs b/src/IKVM.Runtime/ByteCodeHelperMethods.cs index 83ea5cf229..e2468faa89 100644 --- a/src/IKVM.Runtime/ByteCodeHelperMethods.cs +++ b/src/IKVM.Runtime/ByteCodeHelperMethods.cs @@ -23,7 +23,7 @@ Jeroen Frijters */ using System; -using IKVM.Internal; +using IKVM.Runtime; #if IMPORTER using IKVM.Reflection; diff --git a/src/IKVM.Runtime/ByteCodeMetaData.cs b/src/IKVM.Runtime/ByteCodeMetaData.cs new file mode 100644 index 0000000000..4705c03510 --- /dev/null +++ b/src/IKVM.Runtime/ByteCodeMetaData.cs @@ -0,0 +1,399 @@ +/* + Copyright (C) 2002, 2004, 2005, 2006 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +namespace IKVM.Runtime +{ + + struct ByteCodeMetaData + { + + private static ByteCodeMetaData[] data = new ByteCodeMetaData[256]; + private ByteCodeMode reg; + private ByteCodeModeWide wide; + private NormalizedByteCode normbc; + private ByteCodeFlags flags; + private int arg; + + private ByteCodeMetaData(ByteCode bc, ByteCodeMode reg, ByteCodeModeWide wide, bool cannotThrow) + { + this.reg = reg; + this.wide = wide; + this.normbc = (NormalizedByteCode)bc; + this.arg = 0; + this.flags = ByteCodeFlags.None; + if (cannotThrow) + { + this.flags |= ByteCodeFlags.CannotThrow; + } + data[(int)bc] = this; + } + + private ByteCodeMetaData(ByteCode bc, NormalizedByteCode normbc, ByteCodeMode reg, ByteCodeModeWide wide, bool cannotThrow) + { + this.reg = reg; + this.wide = wide; + this.normbc = normbc; + this.arg = 0; + this.flags = ByteCodeFlags.None; + if (cannotThrow) + { + this.flags |= ByteCodeFlags.CannotThrow; + } + data[(int)bc] = this; + } + + private ByteCodeMetaData(ByteCode bc, NormalizedByteCode normbc, int arg, ByteCodeMode reg, ByteCodeModeWide wide, bool cannotThrow) + { + this.reg = reg; + this.wide = wide; + this.normbc = normbc; + this.arg = arg; + this.flags = ByteCodeFlags.FixedArg; + if (cannotThrow) + { + this.flags |= ByteCodeFlags.CannotThrow; + } + data[(int)bc] = this; + } + + internal static NormalizedByteCode GetNormalizedByteCode(ByteCode bc) + { + return data[(int)bc].normbc; + } + + internal static int GetArg(ByteCode bc, int arg) + { + if ((data[(int)bc].flags & ByteCodeFlags.FixedArg) != 0) + { + return data[(int)bc].arg; + } + return arg; + } + + internal static ByteCodeMode GetMode(ByteCode bc) + { + return data[(int)bc].reg; + } + + internal static ByteCodeModeWide GetWideMode(ByteCode bc) + { + return data[(int)bc].wide; + } + + internal static ByteCodeFlowControl GetFlowControl(NormalizedByteCode bc) + { + switch (bc) + { + case NormalizedByteCode.__tableswitch: + case NormalizedByteCode.__lookupswitch: + return ByteCodeFlowControl.Switch; + + case NormalizedByteCode.__goto: + case NormalizedByteCode.__goto_finally: + return ByteCodeFlowControl.Branch; + + 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: + return ByteCodeFlowControl.CondBranch; + + case NormalizedByteCode.__ireturn: + case NormalizedByteCode.__lreturn: + case NormalizedByteCode.__freturn: + case NormalizedByteCode.__dreturn: + case NormalizedByteCode.__areturn: + case NormalizedByteCode.__return: + return ByteCodeFlowControl.Return; + + case NormalizedByteCode.__athrow: + case NormalizedByteCode.__athrow_no_unmap: + case NormalizedByteCode.__static_error: + return ByteCodeFlowControl.Throw; + + default: + return ByteCodeFlowControl.Next; + } + } + + internal static bool CanThrowException(NormalizedByteCode bc) + { + switch (bc) + { + case NormalizedByteCode.__dynamic_invokeinterface: + case NormalizedByteCode.__dynamic_invokestatic: + case NormalizedByteCode.__dynamic_invokevirtual: + case NormalizedByteCode.__dynamic_getstatic: + case NormalizedByteCode.__dynamic_putstatic: + case NormalizedByteCode.__dynamic_getfield: + case NormalizedByteCode.__dynamic_putfield: + case NormalizedByteCode.__clone_array: + case NormalizedByteCode.__static_error: + case NormalizedByteCode.__methodhandle_invoke: + case NormalizedByteCode.__methodhandle_link: + return true; + case NormalizedByteCode.__iconst: + case NormalizedByteCode.__ldc_nothrow: + return false; + default: + return (data[(int)bc].flags & ByteCodeFlags.CannotThrow) == 0; + } + } + + internal static bool IsBranch(NormalizedByteCode bc) + { + switch (data[(int)bc].reg) + { + case ByteCodeMode.Branch_2: + case ByteCodeMode.Branch_4: + case ByteCodeMode.Lookupswitch: + case ByteCodeMode.Tableswitch: + return true; + default: + return false; + } + } + + static ByteCodeMetaData() + { + new ByteCodeMetaData(ByteCode.__nop, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__aconst_null, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iconst_m1, NormalizedByteCode.__iconst, -1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iconst_0, NormalizedByteCode.__iconst, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iconst_1, NormalizedByteCode.__iconst, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iconst_2, NormalizedByteCode.__iconst, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iconst_3, NormalizedByteCode.__iconst, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iconst_4, NormalizedByteCode.__iconst, 4, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iconst_5, NormalizedByteCode.__iconst, 5, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lconst_0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lconst_1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fconst_0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fconst_1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fconst_2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dconst_0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dconst_1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__bipush, NormalizedByteCode.__iconst, ByteCodeMode.Immediate_1, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__sipush, NormalizedByteCode.__iconst, ByteCodeMode.Immediate_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ldc, ByteCodeMode.Constant_1, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__ldc_w, NormalizedByteCode.__ldc, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__ldc2_w, NormalizedByteCode.__ldc, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__iload, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__lload, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__fload, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__dload, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__aload, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__iload_0, NormalizedByteCode.__iload, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iload_1, NormalizedByteCode.__iload, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iload_2, NormalizedByteCode.__iload, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iload_3, NormalizedByteCode.__iload, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lload_0, NormalizedByteCode.__lload, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lload_1, NormalizedByteCode.__lload, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lload_2, NormalizedByteCode.__lload, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lload_3, NormalizedByteCode.__lload, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fload_0, NormalizedByteCode.__fload, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fload_1, NormalizedByteCode.__fload, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fload_2, NormalizedByteCode.__fload, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fload_3, NormalizedByteCode.__fload, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dload_0, NormalizedByteCode.__dload, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dload_1, NormalizedByteCode.__dload, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dload_2, NormalizedByteCode.__dload, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dload_3, NormalizedByteCode.__dload, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__aload_0, NormalizedByteCode.__aload, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__aload_1, NormalizedByteCode.__aload, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__aload_2, NormalizedByteCode.__aload, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__aload_3, NormalizedByteCode.__aload, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iaload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__laload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__faload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__daload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__aaload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__baload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__caload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__saload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__istore, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__lstore, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__fstore, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__dstore, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__astore, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__istore_0, NormalizedByteCode.__istore, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__istore_1, NormalizedByteCode.__istore, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__istore_2, NormalizedByteCode.__istore, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__istore_3, NormalizedByteCode.__istore, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lstore_0, NormalizedByteCode.__lstore, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lstore_1, NormalizedByteCode.__lstore, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lstore_2, NormalizedByteCode.__lstore, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lstore_3, NormalizedByteCode.__lstore, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fstore_0, NormalizedByteCode.__fstore, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fstore_1, NormalizedByteCode.__fstore, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fstore_2, NormalizedByteCode.__fstore, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fstore_3, NormalizedByteCode.__fstore, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dstore_0, NormalizedByteCode.__dstore, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dstore_1, NormalizedByteCode.__dstore, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dstore_2, NormalizedByteCode.__dstore, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dstore_3, NormalizedByteCode.__dstore, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__astore_0, NormalizedByteCode.__astore, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__astore_1, NormalizedByteCode.__astore, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__astore_2, NormalizedByteCode.__astore, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__astore_3, NormalizedByteCode.__astore, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__lastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__fastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__dastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__aastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__bastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__castore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__sastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__pop, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__pop2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dup, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dup_x1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dup_x2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dup2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dup2_x1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dup2_x2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__swap, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iadd, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ladd, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fadd, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dadd, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__isub, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lsub, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fsub, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dsub, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__imul, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lmul, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fmul, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dmul, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__idiv, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__ldiv, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__fdiv, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ddiv, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__irem, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__lrem, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__frem, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__drem, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ineg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lneg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fneg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dneg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ishl, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lshl, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ishr, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lshr, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iushr, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lushr, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iand, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__land, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ior, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lor, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ixor, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lxor, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iinc, ByteCodeMode.Local_1_Immediate_1, ByteCodeModeWide.Local_2_Immediate_2, true); + new ByteCodeMetaData(ByteCode.__i2l, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__i2f, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__i2d, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__l2i, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__l2f, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__l2d, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__f2i, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__f2l, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__f2d, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__d2i, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__d2l, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__d2f, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__i2b, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__i2c, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__i2s, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lcmp, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fcmpl, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__fcmpg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dcmpl, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dcmpg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ifeq, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ifne, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__iflt, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ifge, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ifgt, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ifle, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_icmpeq, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_icmpne, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_icmplt, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_icmpge, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_icmpgt, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_icmple, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_acmpeq, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__if_acmpne, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__goto, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__jsr, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ret, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); + new ByteCodeMetaData(ByteCode.__tableswitch, ByteCodeMode.Tableswitch, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lookupswitch, ByteCodeMode.Lookupswitch, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ireturn, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__lreturn, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__freturn, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__dreturn, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__areturn, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__return, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__getstatic, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__putstatic, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__getfield, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__putfield, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__invokevirtual, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__invokespecial, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__invokestatic, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__invokeinterface, ByteCodeMode.Constant_2_1_1, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__invokedynamic, ByteCodeMode.Constant_2_1_1, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__new, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__newarray, ByteCodeMode.Immediate_1, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__anewarray, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__arraylength, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__athrow, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__checkcast, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__instanceof, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__monitorenter, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__monitorexit, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__wide, NormalizedByteCode.__nop, ByteCodeMode.WidePrefix, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__multianewarray, ByteCodeMode.Constant_2_Immediate_1, ByteCodeModeWide.Unused, false); + new ByteCodeMetaData(ByteCode.__ifnull, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__ifnonnull, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__goto_w, NormalizedByteCode.__goto, ByteCodeMode.Branch_4, ByteCodeModeWide.Unused, true); + new ByteCodeMetaData(ByteCode.__jsr_w, NormalizedByteCode.__jsr, ByteCodeMode.Branch_4, ByteCodeModeWide.Unused, true); + + } + + } + +} diff --git a/src/IKVM.Runtime/ClassFile/ByteCodeMode.cs b/src/IKVM.Runtime/ByteCodeMode.cs similarity index 77% rename from src/IKVM.Runtime/ClassFile/ByteCodeMode.cs rename to src/IKVM.Runtime/ByteCodeMode.cs index 3cb75daba8..98e989e9b8 100644 --- a/src/IKVM.Runtime/ClassFile/ByteCodeMode.cs +++ b/src/IKVM.Runtime/ByteCodeMode.cs @@ -22,21 +22,28 @@ Jeroen Frijters */ -enum ByteCodeMode : byte +namespace IKVM.Runtime { - Unused, - Simple, - Constant_1, - Constant_2, - Branch_2, - Local_1, - Constant_2_1_1, - Immediate_1, - Immediate_2, - Local_1_Immediate_1, - Tableswitch, - Lookupswitch, - Constant_2_Immediate_1, - Branch_4, - WidePrefix -} + + enum ByteCodeMode : byte + { + + Unused, + Simple, + Constant_1, + Constant_2, + Branch_2, + Local_1, + Constant_2_1_1, + Immediate_1, + Immediate_2, + Local_1_Immediate_1, + Tableswitch, + Lookupswitch, + Constant_2_Immediate_1, + Branch_4, + WidePrefix + + } + +} \ No newline at end of file diff --git a/src/IKVM.Runtime/ByteCodeModeWide.cs b/src/IKVM.Runtime/ByteCodeModeWide.cs index e6a309fc8b..4fb5b52de2 100644 --- a/src/IKVM.Runtime/ByteCodeModeWide.cs +++ b/src/IKVM.Runtime/ByteCodeModeWide.cs @@ -22,9 +22,14 @@ Jeroen Frijters */ -enum ByteCodeModeWide : byte +namespace IKVM.Runtime { - Unused, - Local_2, - Local_2_Immediate_2 + + enum ByteCodeModeWide : byte + { + Unused, + Local_2, + Local_2_Immediate_2 + } + } diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.BootstrapMethod.cs b/src/IKVM.Runtime/ClassFile.BootstrapMethod.cs similarity index 98% rename from src/IKVM.Runtime/ClassFile/ClassFile.BootstrapMethod.cs rename to src/IKVM.Runtime/ClassFile.BootstrapMethod.cs index cc76bb6d7c..9820107791 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.BootstrapMethod.cs +++ b/src/IKVM.Runtime/ClassFile.BootstrapMethod.cs @@ -22,13 +22,14 @@ Jeroen Frijters */ -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile { internal struct BootstrapMethod { + private ushort bsm_index; private ushort[] args; @@ -52,7 +53,9 @@ internal int GetArgument(int index) { return args[index]; } + } + } } diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.Constant.cs b/src/IKVM.Runtime/ClassFile.Constant.cs similarity index 98% rename from src/IKVM.Runtime/ClassFile/ClassFile.Constant.cs rename to src/IKVM.Runtime/ClassFile.Constant.cs index dee3c30377..24b31f28eb 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.Constant.cs +++ b/src/IKVM.Runtime/ClassFile.Constant.cs @@ -22,11 +22,12 @@ Jeroen Frijters */ -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile { + internal enum Constant { Utf8 = 1, @@ -44,6 +45,7 @@ internal enum Constant MethodType = 16, InvokeDynamic = 18, } + } } diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItem.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItem.cs similarity index 98% rename from src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItem.cs rename to src/IKVM.Runtime/ClassFile.ConstantPoolItem.cs index d63c7e087a..8506018232 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItem.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItem.cs @@ -23,19 +23,23 @@ Jeroen Frijters */ using System; -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile { + internal abstract class ConstantPoolItem { + internal virtual void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options) { + } internal virtual void Link(TypeWrapper thisType, LoadMode mode) { + } internal virtual ConstantType GetConstantType() @@ -45,6 +49,7 @@ internal virtual ConstantType GetConstantType() internal virtual void MarkLinkRequired() { + } // this is used for sun.reflect.ConstantPool @@ -53,7 +58,9 @@ internal virtual object GetRuntimeValue() { return null; } + } + } } diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemClass.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemClass.cs similarity index 99% rename from src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemClass.cs rename to src/IKVM.Runtime/ClassFile.ConstantPoolItemClass.cs index 0a825a685a..ea5e4e7c3f 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemClass.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemClass.cs @@ -25,7 +25,7 @@ Jeroen Frijters using IKVM.ByteCode.Reading; -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemDouble.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemDouble.cs similarity index 98% rename from src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemDouble.cs rename to src/IKVM.Runtime/ClassFile.ConstantPoolItemDouble.cs index c7d67c49b9..ab1420eaa5 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemDouble.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemDouble.cs @@ -24,7 +24,7 @@ Jeroen Frijters using IKVM.ByteCode.Reading; -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemFMI.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemFMI.cs similarity index 99% rename from src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemFMI.cs rename to src/IKVM.Runtime/ClassFile.ConstantPoolItemFMI.cs index 2d5d5811f1..3842596b8e 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemFMI.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemFMI.cs @@ -23,7 +23,7 @@ Jeroen Frijters */ using System; -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemFieldref.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemFieldref.cs similarity index 99% rename from src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemFieldref.cs rename to src/IKVM.Runtime/ClassFile.ConstantPoolItemFieldref.cs index 0063137d53..04917d5f94 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemFieldref.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemFieldref.cs @@ -24,7 +24,7 @@ Jeroen Frijters using IKVM.ByteCode.Reading; -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemFloat.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemFloat.cs similarity index 98% rename from src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemFloat.cs rename to src/IKVM.Runtime/ClassFile.ConstantPoolItemFloat.cs index 04e882106a..1bfd77bf01 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemFloat.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemFloat.cs @@ -24,7 +24,7 @@ Jeroen Frijters using IKVM.ByteCode.Reading; -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemInteger.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemInteger.cs similarity index 98% rename from src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemInteger.cs rename to src/IKVM.Runtime/ClassFile.ConstantPoolItemInteger.cs index e156ce7f02..2ba0f74924 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemInteger.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemInteger.cs @@ -24,7 +24,7 @@ Jeroen Frijters using IKVM.ByteCode.Reading; -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemInterfaceMethodref.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemInterfaceMethodref.cs similarity index 98% rename from src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemInterfaceMethodref.cs rename to src/IKVM.Runtime/ClassFile.ConstantPoolItemInterfaceMethodref.cs index a693495349..4828405534 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemInterfaceMethodref.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemInterfaceMethodref.cs @@ -24,7 +24,7 @@ Jeroen Frijters using IKVM.ByteCode.Reading; -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemInvokeDynamic.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemInvokeDynamic.cs similarity index 99% rename from src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemInvokeDynamic.cs rename to src/IKVM.Runtime/ClassFile.ConstantPoolItemInvokeDynamic.cs index b108241312..439a55c005 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemInvokeDynamic.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemInvokeDynamic.cs @@ -23,7 +23,7 @@ Jeroen Frijters */ using IKVM.ByteCode.Reading; -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemLiveObject.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemLiveObject.cs similarity index 98% rename from src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemLiveObject.cs rename to src/IKVM.Runtime/ClassFile.ConstantPoolItemLiveObject.cs index 9289d14bed..48b5a547a6 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemLiveObject.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemLiveObject.cs @@ -22,7 +22,7 @@ Jeroen Frijters */ -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemLong.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemLong.cs similarity index 98% rename from src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemLong.cs rename to src/IKVM.Runtime/ClassFile.ConstantPoolItemLong.cs index 13f2bf3ce0..a5f1517416 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemLong.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemLong.cs @@ -24,7 +24,7 @@ Jeroen Frijters using IKVM.ByteCode.Reading; -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemMI.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemMI.cs similarity index 99% rename from src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemMI.cs rename to src/IKVM.Runtime/ClassFile.ConstantPoolItemMI.cs index 86dea52bd5..16b6f6a57b 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemMI.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemMI.cs @@ -22,7 +22,7 @@ Jeroen Frijters */ -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemMethodHandle.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemMethodHandle.cs similarity index 99% rename from src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemMethodHandle.cs rename to src/IKVM.Runtime/ClassFile.ConstantPoolItemMethodHandle.cs index 37b4f67c34..6c206bc2bf 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemMethodHandle.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemMethodHandle.cs @@ -27,7 +27,7 @@ Jeroen Frijters using IKVM.ByteCode; using IKVM.ByteCode.Reading; -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemMethodType.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemMethodType.cs similarity index 99% rename from src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemMethodType.cs rename to src/IKVM.Runtime/ClassFile.ConstantPoolItemMethodType.cs index a280438258..333b80e90d 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemMethodType.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemMethodType.cs @@ -23,7 +23,7 @@ Jeroen Frijters */ using IKVM.ByteCode.Reading; -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemMethodref.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemMethodref.cs similarity index 99% rename from src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemMethodref.cs rename to src/IKVM.Runtime/ClassFile.ConstantPoolItemMethodref.cs index adf6ed1767..cb499501e9 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemMethodref.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemMethodref.cs @@ -25,7 +25,7 @@ Jeroen Frijters using IKVM.ByteCode.Reading; using IKVM.Runtime; -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemNameAndType.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemNameAndType.cs similarity index 98% rename from src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemNameAndType.cs rename to src/IKVM.Runtime/ClassFile.ConstantPoolItemNameAndType.cs index 9a2c381bd0..42243da418 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemNameAndType.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemNameAndType.cs @@ -24,7 +24,7 @@ Jeroen Frijters using IKVM.ByteCode.Reading; -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemString.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemString.cs similarity index 98% rename from src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemString.cs rename to src/IKVM.Runtime/ClassFile.ConstantPoolItemString.cs index c870bc53ba..3c0fd1694d 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemString.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemString.cs @@ -24,7 +24,7 @@ Jeroen Frijters using IKVM.ByteCode.Reading; -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemUtf8.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemUtf8.cs similarity index 98% rename from src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemUtf8.cs rename to src/IKVM.Runtime/ClassFile.ConstantPoolItemUtf8.cs index a9c19ffbe4..52d09d83e9 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantPoolItemUtf8.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemUtf8.cs @@ -22,7 +22,7 @@ Jeroen Frijters */ -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantType.cs b/src/IKVM.Runtime/ClassFile.ConstantType.cs similarity index 98% rename from src/IKVM.Runtime/ClassFile/ClassFile.ConstantType.cs rename to src/IKVM.Runtime/ClassFile.ConstantType.cs index 2db6705f23..3fd0bee94f 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.ConstantType.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantType.cs @@ -22,7 +22,7 @@ Jeroen Frijters */ -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.Field.cs b/src/IKVM.Runtime/ClassFile.Field.cs similarity index 99% rename from src/IKVM.Runtime/ClassFile/ClassFile.Field.cs rename to src/IKVM.Runtime/ClassFile.Field.cs index 3b70595d04..ea90842c34 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.Field.cs +++ b/src/IKVM.Runtime/ClassFile.Field.cs @@ -27,7 +27,7 @@ Jeroen Frijters using IKVM.ByteCode; using IKVM.ByteCode.Reading; -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.FieldOrMethod.cs b/src/IKVM.Runtime/ClassFile.FieldOrMethod.cs similarity index 99% rename from src/IKVM.Runtime/ClassFile/ClassFile.FieldOrMethod.cs rename to src/IKVM.Runtime/ClassFile.FieldOrMethod.cs index ff47745968..718ab0a715 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.FieldOrMethod.cs +++ b/src/IKVM.Runtime/ClassFile.FieldOrMethod.cs @@ -28,7 +28,7 @@ Jeroen Frijters using IKVM.ByteCode; using IKVM.ByteCode.Reading; -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.InnerClass.cs b/src/IKVM.Runtime/ClassFile.InnerClass.cs similarity index 98% rename from src/IKVM.Runtime/ClassFile/ClassFile.InnerClass.cs rename to src/IKVM.Runtime/ClassFile.InnerClass.cs index 7edde4f238..49e71db614 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.InnerClass.cs +++ b/src/IKVM.Runtime/ClassFile.InnerClass.cs @@ -23,7 +23,7 @@ Jeroen Frijters */ using IKVM.Attributes; -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.Method.Code.cs b/src/IKVM.Runtime/ClassFile.Method.Code.cs similarity index 99% rename from src/IKVM.Runtime/ClassFile/ClassFile.Method.Code.cs rename to src/IKVM.Runtime/ClassFile.Method.Code.cs index baa0a1ea41..f23d43c82e 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.Method.Code.cs +++ b/src/IKVM.Runtime/ClassFile.Method.Code.cs @@ -26,7 +26,7 @@ Jeroen Frijters using IKVM.ByteCode.Reading; -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.Method.ExceptionTableEntry.cs b/src/IKVM.Runtime/ClassFile.Method.ExceptionTableEntry.cs similarity index 98% rename from src/IKVM.Runtime/ClassFile/ClassFile.Method.ExceptionTableEntry.cs rename to src/IKVM.Runtime/ClassFile.Method.ExceptionTableEntry.cs index 9614c51e19..25e5008420 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.Method.ExceptionTableEntry.cs +++ b/src/IKVM.Runtime/ClassFile.Method.ExceptionTableEntry.cs @@ -22,7 +22,7 @@ Jeroen Frijters */ -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.Method.Instruction.cs b/src/IKVM.Runtime/ClassFile.Method.Instruction.cs similarity index 98% rename from src/IKVM.Runtime/ClassFile/ClassFile.Method.Instruction.cs rename to src/IKVM.Runtime/ClassFile.Method.Instruction.cs index 35b45e72e5..50ab0955d0 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.Method.Instruction.cs +++ b/src/IKVM.Runtime/ClassFile.Method.Instruction.cs @@ -22,7 +22,7 @@ Jeroen Frijters */ -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile @@ -118,7 +118,7 @@ internal void MapSwitchTargets(int[] pcIndexMap) internal void Read(ushort pc, BigEndianBinaryReader br, ClassFile classFile) { this.pc = pc; - var bc = (global::ByteCode)br.ReadByte(); + var bc = (ByteCode)br.ReadByte(); switch (ByteCodeMetaData.GetMode(bc)) { case ByteCodeMode.Simple: @@ -213,7 +213,7 @@ internal void Read(ushort pc, BigEndianBinaryReader br, ClassFile classFile) break; } case ByteCodeMode.WidePrefix: - bc = (global::ByteCode)br.ReadByte(); + bc = (ByteCode)br.ReadByte(); // NOTE the PC of a wide instruction is actually the PC of the // wide prefix, not the following instruction (vmspec 4.9.2) switch (ByteCodeMetaData.GetWideMode(bc)) diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.Method.InstructionFlags.cs b/src/IKVM.Runtime/ClassFile.Method.InstructionFlags.cs similarity index 98% rename from src/IKVM.Runtime/ClassFile/ClassFile.Method.InstructionFlags.cs rename to src/IKVM.Runtime/ClassFile.Method.InstructionFlags.cs index 6074d9a0dd..b8b8afca9a 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.Method.InstructionFlags.cs +++ b/src/IKVM.Runtime/ClassFile.Method.InstructionFlags.cs @@ -23,7 +23,7 @@ Jeroen Frijters */ using System; -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.Method.LineNumberTableEntry.cs b/src/IKVM.Runtime/ClassFile.Method.LineNumberTableEntry.cs similarity index 98% rename from src/IKVM.Runtime/ClassFile/ClassFile.Method.LineNumberTableEntry.cs rename to src/IKVM.Runtime/ClassFile.Method.LineNumberTableEntry.cs index 6d08be72b9..e754acda71 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.Method.LineNumberTableEntry.cs +++ b/src/IKVM.Runtime/ClassFile.Method.LineNumberTableEntry.cs @@ -22,7 +22,7 @@ Jeroen Frijters */ -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.Method.LocalVariableTableEntry.cs b/src/IKVM.Runtime/ClassFile.Method.LocalVariableTableEntry.cs similarity index 98% rename from src/IKVM.Runtime/ClassFile/ClassFile.Method.LocalVariableTableEntry.cs rename to src/IKVM.Runtime/ClassFile.Method.LocalVariableTableEntry.cs index 495753d7eb..1f948a6896 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.Method.LocalVariableTableEntry.cs +++ b/src/IKVM.Runtime/ClassFile.Method.LocalVariableTableEntry.cs @@ -22,7 +22,7 @@ Jeroen Frijters */ -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.Method.LowFreqData.cs b/src/IKVM.Runtime/ClassFile.Method.LowFreqData.cs similarity index 98% rename from src/IKVM.Runtime/ClassFile/ClassFile.Method.LowFreqData.cs rename to src/IKVM.Runtime/ClassFile.Method.LowFreqData.cs index 3ec561f09c..45a02e0f09 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.Method.LowFreqData.cs +++ b/src/IKVM.Runtime/ClassFile.Method.LowFreqData.cs @@ -22,7 +22,7 @@ Jeroen Frijters */ -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.Method.cs b/src/IKVM.Runtime/ClassFile.Method.cs similarity index 99% rename from src/IKVM.Runtime/ClassFile/ClassFile.Method.cs rename to src/IKVM.Runtime/ClassFile.Method.cs index 4675b982fc..c14509b42c 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.Method.cs +++ b/src/IKVM.Runtime/ClassFile.Method.cs @@ -22,7 +22,6 @@ Jeroen Frijters */ using System.Collections.Generic; -using System.Linq; using IKVM.Attributes; using IKVM.ByteCode.Reading; @@ -31,7 +30,7 @@ Jeroen Frijters using IKVM.Tools.Importer; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.SupportedVersions.cs b/src/IKVM.Runtime/ClassFile.SupportedVersions.cs similarity index 97% rename from src/IKVM.Runtime/ClassFile/ClassFile.SupportedVersions.cs rename to src/IKVM.Runtime/ClassFile.SupportedVersions.cs index ec19979d2d..9802c287e3 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.SupportedVersions.cs +++ b/src/IKVM.Runtime/ClassFile.SupportedVersions.cs @@ -22,7 +22,7 @@ Jeroen Frijters */ -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile diff --git a/src/IKVM.Runtime/ClassFile/ClassFile.cs b/src/IKVM.Runtime/ClassFile.cs similarity index 99% rename from src/IKVM.Runtime/ClassFile/ClassFile.cs rename to src/IKVM.Runtime/ClassFile.cs index d573c7ae7e..9cf39608f7 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFile.cs +++ b/src/IKVM.Runtime/ClassFile.cs @@ -30,7 +30,7 @@ Jeroen Frijters using IKVM.ByteCode; using IKVM.ByteCode.Reading; -namespace IKVM.Internal +namespace IKVM.Runtime { sealed partial class ClassFile @@ -639,23 +639,23 @@ static object ReadAnnotationElementValue(ElementValueReader reader, ClassFile cl { switch (reader) { - case ElementValueConstantReader r when r.Tag == ByteCode.Parsing.ElementValueTag.Boolean: + case ElementValueConstantReader r when r.Tag == IKVM.ByteCode.Parsing.ElementValueTag.Boolean: return classFile.GetConstantPoolConstantInteger(r.Value.Index) != 0; - case ElementValueConstantReader r when r.Tag == ByteCode.Parsing.ElementValueTag.Byte: + case ElementValueConstantReader r when r.Tag == IKVM.ByteCode.Parsing.ElementValueTag.Byte: return (byte)classFile.GetConstantPoolConstantInteger(r.Value.Index); - case ElementValueConstantReader r when r.Tag == ByteCode.Parsing.ElementValueTag.Char: + case ElementValueConstantReader r when r.Tag == IKVM.ByteCode.Parsing.ElementValueTag.Char: return (char)classFile.GetConstantPoolConstantInteger(r.Value.Index); - case ElementValueConstantReader r when r.Tag == ByteCode.Parsing.ElementValueTag.Short: + case ElementValueConstantReader r when r.Tag == IKVM.ByteCode.Parsing.ElementValueTag.Short: return (short)classFile.GetConstantPoolConstantInteger(r.Value.Index); - case ElementValueConstantReader r when r.Tag == ByteCode.Parsing.ElementValueTag.Integer: + case ElementValueConstantReader r when r.Tag == IKVM.ByteCode.Parsing.ElementValueTag.Integer: return classFile.GetConstantPoolConstantInteger(r.Value.Index); - case ElementValueConstantReader r when r.Tag == ByteCode.Parsing.ElementValueTag.Float: + case ElementValueConstantReader r when r.Tag == IKVM.ByteCode.Parsing.ElementValueTag.Float: return classFile.GetConstantPoolConstantFloat(r.Value.Index); - case ElementValueConstantReader r when r.Tag == ByteCode.Parsing.ElementValueTag.Long: + case ElementValueConstantReader r when r.Tag == IKVM.ByteCode.Parsing.ElementValueTag.Long: return classFile.GetConstantPoolConstantLong(r.Value.Index); - case ElementValueConstantReader r when r.Tag == ByteCode.Parsing.ElementValueTag.Double: + case ElementValueConstantReader r when r.Tag == IKVM.ByteCode.Parsing.ElementValueTag.Double: return classFile.GetConstantPoolConstantDouble(r.Value.Index); - case ElementValueConstantReader r when r.Tag == ByteCode.Parsing.ElementValueTag.String: + case ElementValueConstantReader r when r.Tag == IKVM.ByteCode.Parsing.ElementValueTag.String: return classFile.GetConstantPoolUtf8String(utf8_cp, r.Value.Index); case ElementValueEnumConstantReader r: return new object[] { diff --git a/src/IKVM.Runtime/ClassFile/ByteCode.cs b/src/IKVM.Runtime/ClassFile/ByteCode.cs deleted file mode 100644 index bd8358bd2d..0000000000 --- a/src/IKVM.Runtime/ClassFile/ByteCode.cs +++ /dev/null @@ -1,231 +0,0 @@ -/* - Copyright (C) 2002, 2004, 2005, 2006 Jeroen Frijters - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jeroen Frijters - jeroen@frijters.net - -*/ - -enum ByteCode : byte -{ - - __nop = 0, - __aconst_null = 1, - __iconst_m1 = 2, - __iconst_0 = 3, - __iconst_1 = 4, - __iconst_2 = 5, - __iconst_3 = 6, - __iconst_4 = 7, - __iconst_5 = 8, - __lconst_0 = 9, - __lconst_1 = 10, - __fconst_0 = 11, - __fconst_1 = 12, - __fconst_2 = 13, - __dconst_0 = 14, - __dconst_1 = 15, - __bipush = 16, - __sipush = 17, - __ldc = 18, - __ldc_w = 19, - __ldc2_w = 20, - __iload = 21, - __lload = 22, - __fload = 23, - __dload = 24, - __aload = 25, - __iload_0 = 26, - __iload_1 = 27, - __iload_2 = 28, - __iload_3 = 29, - __lload_0 = 30, - __lload_1 = 31, - __lload_2 = 32, - __lload_3 = 33, - __fload_0 = 34, - __fload_1 = 35, - __fload_2 = 36, - __fload_3 = 37, - __dload_0 = 38, - __dload_1 = 39, - __dload_2 = 40, - __dload_3 = 41, - __aload_0 = 42, - __aload_1 = 43, - __aload_2 = 44, - __aload_3 = 45, - __iaload = 46, - __laload = 47, - __faload = 48, - __daload = 49, - __aaload = 50, - __baload = 51, - __caload = 52, - __saload = 53, - __istore = 54, - __lstore = 55, - __fstore = 56, - __dstore = 57, - __astore = 58, - __istore_0 = 59, - __istore_1 = 60, - __istore_2 = 61, - __istore_3 = 62, - __lstore_0 = 63, - __lstore_1 = 64, - __lstore_2 = 65, - __lstore_3 = 66, - __fstore_0 = 67, - __fstore_1 = 68, - __fstore_2 = 69, - __fstore_3 = 70, - __dstore_0 = 71, - __dstore_1 = 72, - __dstore_2 = 73, - __dstore_3 = 74, - __astore_0 = 75, - __astore_1 = 76, - __astore_2 = 77, - __astore_3 = 78, - __iastore = 79, - __lastore = 80, - __fastore = 81, - __dastore = 82, - __aastore = 83, - __bastore = 84, - __castore = 85, - __sastore = 86, - __pop = 87, - __pop2 = 88, - __dup = 89, - __dup_x1 = 90, - __dup_x2 = 91, - __dup2 = 92, - __dup2_x1 = 93, - __dup2_x2 = 94, - __swap = 95, - __iadd = 96, - __ladd = 97, - __fadd = 98, - __dadd = 99, - __isub = 100, - __lsub = 101, - __fsub = 102, - __dsub = 103, - __imul = 104, - __lmul = 105, - __fmul = 106, - __dmul = 107, - __idiv = 108, - __ldiv = 109, - __fdiv = 110, - __ddiv = 111, - __irem = 112, - __lrem = 113, - __frem = 114, - __drem = 115, - __ineg = 116, - __lneg = 117, - __fneg = 118, - __dneg = 119, - __ishl = 120, - __lshl = 121, - __ishr = 122, - __lshr = 123, - __iushr = 124, - __lushr = 125, - __iand = 126, - __land = 127, - __ior = 128, - __lor = 129, - __ixor = 130, - __lxor = 131, - __iinc = 132, - __i2l = 133, - __i2f = 134, - __i2d = 135, - __l2i = 136, - __l2f = 137, - __l2d = 138, - __f2i = 139, - __f2l = 140, - __f2d = 141, - __d2i = 142, - __d2l = 143, - __d2f = 144, - __i2b = 145, - __i2c = 146, - __i2s = 147, - __lcmp = 148, - __fcmpl = 149, - __fcmpg = 150, - __dcmpl = 151, - __dcmpg = 152, - __ifeq = 153, - __ifne = 154, - __iflt = 155, - __ifge = 156, - __ifgt = 157, - __ifle = 158, - __if_icmpeq = 159, - __if_icmpne = 160, - __if_icmplt = 161, - __if_icmpge = 162, - __if_icmpgt = 163, - __if_icmple = 164, - __if_acmpeq = 165, - __if_acmpne = 166, - __goto = 167, - __jsr = 168, - __ret = 169, - __tableswitch = 170, - __lookupswitch = 171, - __ireturn = 172, - __lreturn = 173, - __freturn = 174, - __dreturn = 175, - __areturn = 176, - __return = 177, - __getstatic = 178, - __putstatic = 179, - __getfield = 180, - __putfield = 181, - __invokevirtual = 182, - __invokespecial = 183, - __invokestatic = 184, - __invokeinterface = 185, - __invokedynamic = 186, - __new = 187, - __newarray = 188, - __anewarray = 189, - __arraylength = 190, - __athrow = 191, - __checkcast = 192, - __instanceof = 193, - __monitorenter = 194, - __monitorexit = 195, - __wide = 196, - __multianewarray = 197, - __ifnull = 198, - __ifnonnull = 199, - __goto_w = 200, - __jsr_w = 201 - -} diff --git a/src/IKVM.Runtime/ClassFile/ByteCodeMetaData.cs b/src/IKVM.Runtime/ClassFile/ByteCodeMetaData.cs deleted file mode 100644 index 042fef9362..0000000000 --- a/src/IKVM.Runtime/ClassFile/ByteCodeMetaData.cs +++ /dev/null @@ -1,394 +0,0 @@ -/* - Copyright (C) 2002, 2004, 2005, 2006 Jeroen Frijters - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jeroen Frijters - jeroen@frijters.net - -*/ - -struct ByteCodeMetaData -{ - - private static ByteCodeMetaData[] data = new ByteCodeMetaData[256]; - private ByteCodeMode reg; - private ByteCodeModeWide wide; - private NormalizedByteCode normbc; - private ByteCodeFlags flags; - private int arg; - - private ByteCodeMetaData(ByteCode bc, ByteCodeMode reg, ByteCodeModeWide wide, bool cannotThrow) - { - this.reg = reg; - this.wide = wide; - this.normbc = (NormalizedByteCode)bc; - this.arg = 0; - this.flags = ByteCodeFlags.None; - if (cannotThrow) - { - this.flags |= ByteCodeFlags.CannotThrow; - } - data[(int)bc] = this; - } - - private ByteCodeMetaData(ByteCode bc, NormalizedByteCode normbc, ByteCodeMode reg, ByteCodeModeWide wide, bool cannotThrow) - { - this.reg = reg; - this.wide = wide; - this.normbc = normbc; - this.arg = 0; - this.flags = ByteCodeFlags.None; - if (cannotThrow) - { - this.flags |= ByteCodeFlags.CannotThrow; - } - data[(int)bc] = this; - } - - private ByteCodeMetaData(ByteCode bc, NormalizedByteCode normbc, int arg, ByteCodeMode reg, ByteCodeModeWide wide, bool cannotThrow) - { - this.reg = reg; - this.wide = wide; - this.normbc = normbc; - this.arg = arg; - this.flags = ByteCodeFlags.FixedArg; - if (cannotThrow) - { - this.flags |= ByteCodeFlags.CannotThrow; - } - data[(int)bc] = this; - } - - internal static NormalizedByteCode GetNormalizedByteCode(ByteCode bc) - { - return data[(int)bc].normbc; - } - - internal static int GetArg(ByteCode bc, int arg) - { - if ((data[(int)bc].flags & ByteCodeFlags.FixedArg) != 0) - { - return data[(int)bc].arg; - } - return arg; - } - - internal static ByteCodeMode GetMode(ByteCode bc) - { - return data[(int)bc].reg; - } - - internal static ByteCodeModeWide GetWideMode(ByteCode bc) - { - return data[(int)bc].wide; - } - - internal static ByteCodeFlowControl GetFlowControl(NormalizedByteCode bc) - { - switch (bc) - { - case NormalizedByteCode.__tableswitch: - case NormalizedByteCode.__lookupswitch: - return ByteCodeFlowControl.Switch; - - case NormalizedByteCode.__goto: - case NormalizedByteCode.__goto_finally: - return ByteCodeFlowControl.Branch; - - 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: - return ByteCodeFlowControl.CondBranch; - - case NormalizedByteCode.__ireturn: - case NormalizedByteCode.__lreturn: - case NormalizedByteCode.__freturn: - case NormalizedByteCode.__dreturn: - case NormalizedByteCode.__areturn: - case NormalizedByteCode.__return: - return ByteCodeFlowControl.Return; - - case NormalizedByteCode.__athrow: - case NormalizedByteCode.__athrow_no_unmap: - case NormalizedByteCode.__static_error: - return ByteCodeFlowControl.Throw; - - default: - return ByteCodeFlowControl.Next; - } - } - - internal static bool CanThrowException(NormalizedByteCode bc) - { - switch (bc) - { - case NormalizedByteCode.__dynamic_invokeinterface: - case NormalizedByteCode.__dynamic_invokestatic: - case NormalizedByteCode.__dynamic_invokevirtual: - case NormalizedByteCode.__dynamic_getstatic: - case NormalizedByteCode.__dynamic_putstatic: - case NormalizedByteCode.__dynamic_getfield: - case NormalizedByteCode.__dynamic_putfield: - case NormalizedByteCode.__clone_array: - case NormalizedByteCode.__static_error: - case NormalizedByteCode.__methodhandle_invoke: - case NormalizedByteCode.__methodhandle_link: - return true; - case NormalizedByteCode.__iconst: - case NormalizedByteCode.__ldc_nothrow: - return false; - default: - return (data[(int)bc].flags & ByteCodeFlags.CannotThrow) == 0; - } - } - - internal static bool IsBranch(NormalizedByteCode bc) - { - switch (data[(int)bc].reg) - { - case ByteCodeMode.Branch_2: - case ByteCodeMode.Branch_4: - case ByteCodeMode.Lookupswitch: - case ByteCodeMode.Tableswitch: - return true; - default: - return false; - } - } - - static ByteCodeMetaData() - { - new ByteCodeMetaData(ByteCode.__nop, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__aconst_null, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__iconst_m1, NormalizedByteCode.__iconst, -1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__iconst_0, NormalizedByteCode.__iconst, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__iconst_1, NormalizedByteCode.__iconst, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__iconst_2, NormalizedByteCode.__iconst, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__iconst_3, NormalizedByteCode.__iconst, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__iconst_4, NormalizedByteCode.__iconst, 4, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__iconst_5, NormalizedByteCode.__iconst, 5, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__lconst_0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__lconst_1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__fconst_0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__fconst_1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__fconst_2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__dconst_0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__dconst_1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__bipush, NormalizedByteCode.__iconst, ByteCodeMode.Immediate_1, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__sipush, NormalizedByteCode.__iconst, ByteCodeMode.Immediate_2, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__ldc, ByteCodeMode.Constant_1, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__ldc_w, NormalizedByteCode.__ldc, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__ldc2_w, NormalizedByteCode.__ldc, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__iload, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); - new ByteCodeMetaData(ByteCode.__lload, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); - new ByteCodeMetaData(ByteCode.__fload, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); - new ByteCodeMetaData(ByteCode.__dload, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); - new ByteCodeMetaData(ByteCode.__aload, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); - new ByteCodeMetaData(ByteCode.__iload_0, NormalizedByteCode.__iload, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__iload_1, NormalizedByteCode.__iload, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__iload_2, NormalizedByteCode.__iload, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__iload_3, NormalizedByteCode.__iload, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__lload_0, NormalizedByteCode.__lload, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__lload_1, NormalizedByteCode.__lload, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__lload_2, NormalizedByteCode.__lload, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__lload_3, NormalizedByteCode.__lload, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__fload_0, NormalizedByteCode.__fload, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__fload_1, NormalizedByteCode.__fload, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__fload_2, NormalizedByteCode.__fload, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__fload_3, NormalizedByteCode.__fload, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__dload_0, NormalizedByteCode.__dload, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__dload_1, NormalizedByteCode.__dload, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__dload_2, NormalizedByteCode.__dload, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__dload_3, NormalizedByteCode.__dload, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__aload_0, NormalizedByteCode.__aload, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__aload_1, NormalizedByteCode.__aload, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__aload_2, NormalizedByteCode.__aload, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__aload_3, NormalizedByteCode.__aload, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__iaload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__laload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__faload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__daload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__aaload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__baload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__caload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__saload, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__istore, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); - new ByteCodeMetaData(ByteCode.__lstore, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); - new ByteCodeMetaData(ByteCode.__fstore, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); - new ByteCodeMetaData(ByteCode.__dstore, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); - new ByteCodeMetaData(ByteCode.__astore, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); - new ByteCodeMetaData(ByteCode.__istore_0, NormalizedByteCode.__istore, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__istore_1, NormalizedByteCode.__istore, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__istore_2, NormalizedByteCode.__istore, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__istore_3, NormalizedByteCode.__istore, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__lstore_0, NormalizedByteCode.__lstore, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__lstore_1, NormalizedByteCode.__lstore, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__lstore_2, NormalizedByteCode.__lstore, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__lstore_3, NormalizedByteCode.__lstore, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__fstore_0, NormalizedByteCode.__fstore, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__fstore_1, NormalizedByteCode.__fstore, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__fstore_2, NormalizedByteCode.__fstore, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__fstore_3, NormalizedByteCode.__fstore, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__dstore_0, NormalizedByteCode.__dstore, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__dstore_1, NormalizedByteCode.__dstore, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__dstore_2, NormalizedByteCode.__dstore, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__dstore_3, NormalizedByteCode.__dstore, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__astore_0, NormalizedByteCode.__astore, 0, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__astore_1, NormalizedByteCode.__astore, 1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__astore_2, NormalizedByteCode.__astore, 2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__astore_3, NormalizedByteCode.__astore, 3, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__iastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__lastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__fastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__dastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__aastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__bastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__castore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__sastore, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__pop, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__pop2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__dup, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__dup_x1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__dup_x2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__dup2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__dup2_x1, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__dup2_x2, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__swap, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__iadd, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__ladd, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__fadd, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__dadd, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__isub, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__lsub, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__fsub, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__dsub, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__imul, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__lmul, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__fmul, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__dmul, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__idiv, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__ldiv, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__fdiv, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__ddiv, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__irem, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__lrem, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__frem, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__drem, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__ineg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__lneg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__fneg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__dneg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__ishl, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__lshl, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__ishr, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__lshr, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__iushr, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__lushr, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__iand, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__land, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__ior, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__lor, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__ixor, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__lxor, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__iinc, ByteCodeMode.Local_1_Immediate_1, ByteCodeModeWide.Local_2_Immediate_2, true); - new ByteCodeMetaData(ByteCode.__i2l, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__i2f, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__i2d, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__l2i, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__l2f, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__l2d, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__f2i, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__f2l, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__f2d, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__d2i, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__d2l, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__d2f, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__i2b, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__i2c, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__i2s, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__lcmp, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__fcmpl, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__fcmpg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__dcmpl, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__dcmpg, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__ifeq, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__ifne, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__iflt, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__ifge, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__ifgt, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__ifle, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__if_icmpeq, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__if_icmpne, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__if_icmplt, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__if_icmpge, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__if_icmpgt, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__if_icmple, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__if_acmpeq, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__if_acmpne, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__goto, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__jsr, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__ret, ByteCodeMode.Local_1, ByteCodeModeWide.Local_2, true); - new ByteCodeMetaData(ByteCode.__tableswitch, ByteCodeMode.Tableswitch, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__lookupswitch, ByteCodeMode.Lookupswitch, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__ireturn, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__lreturn, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__freturn, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__dreturn, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__areturn, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__return, ByteCodeMode.Simple, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__getstatic, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__putstatic, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__getfield, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__putfield, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__invokevirtual, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__invokespecial, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__invokestatic, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__invokeinterface, ByteCodeMode.Constant_2_1_1, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__invokedynamic, ByteCodeMode.Constant_2_1_1, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__new, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__newarray, ByteCodeMode.Immediate_1, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__anewarray, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__arraylength, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__athrow, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__checkcast, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__instanceof, ByteCodeMode.Constant_2, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__monitorenter, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__monitorexit, ByteCodeMode.Simple, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__wide, NormalizedByteCode.__nop, ByteCodeMode.WidePrefix, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__multianewarray, ByteCodeMode.Constant_2_Immediate_1, ByteCodeModeWide.Unused, false); - new ByteCodeMetaData(ByteCode.__ifnull, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__ifnonnull, ByteCodeMode.Branch_2, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__goto_w, NormalizedByteCode.__goto, ByteCodeMode.Branch_4, ByteCodeModeWide.Unused, true); - new ByteCodeMetaData(ByteCode.__jsr_w, NormalizedByteCode.__jsr, ByteCodeMode.Branch_4, ByteCodeModeWide.Unused, true); - - } - -} diff --git a/src/IKVM.Runtime/ClassFile/ClassFileParseOptions.cs b/src/IKVM.Runtime/ClassFileParseOptions.cs similarity index 98% rename from src/IKVM.Runtime/ClassFile/ClassFileParseOptions.cs rename to src/IKVM.Runtime/ClassFileParseOptions.cs index f4491e3d7f..a7fc6c9a95 100644 --- a/src/IKVM.Runtime/ClassFile/ClassFileParseOptions.cs +++ b/src/IKVM.Runtime/ClassFileParseOptions.cs @@ -23,7 +23,7 @@ Jeroen Frijters */ using System; -namespace IKVM.Internal +namespace IKVM.Runtime { [Flags] diff --git a/src/IKVM.Runtime/ClassLoaderWrapper.cs b/src/IKVM.Runtime/ClassLoaderWrapper.cs index a880d38be8..0614c38cbe 100644 --- a/src/IKVM.Runtime/ClassLoaderWrapper.cs +++ b/src/IKVM.Runtime/ClassLoaderWrapper.cs @@ -53,7 +53,7 @@ Jeroen Frijters using IKVM.Tools.Importer; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { class ClassLoaderWrapper diff --git a/src/IKVM.Runtime/CodeEmitter.cs b/src/IKVM.Runtime/CodeEmitter.cs index a476672f0c..fd7cb3fcf6 100644 --- a/src/IKVM.Runtime/CodeEmitter.cs +++ b/src/IKVM.Runtime/CodeEmitter.cs @@ -39,7 +39,7 @@ Jeroen Frijters using System.Reflection.Emit; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { sealed class CodeEmitter @@ -2878,7 +2878,7 @@ internal void CheckLabels() foreach(System.Diagnostics.StackFrame frame in labels.Values) { string name = frame.GetFileName() + ":" + frame.GetFileLineNumber(); - IKVM.Internal.JVM.CriticalFailure("Label failure: " + name, null); + IKVM.Runtime.JVM.CriticalFailure("Label failure: " + name, null); } #endif } diff --git a/src/IKVM.Runtime/CodeEmitterLabel.cs b/src/IKVM.Runtime/CodeEmitterLabel.cs index 3f1c3f8d3c..07232aa41d 100644 --- a/src/IKVM.Runtime/CodeEmitterLabel.cs +++ b/src/IKVM.Runtime/CodeEmitterLabel.cs @@ -29,7 +29,7 @@ Jeroen Frijters using System.Reflection.Emit; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { sealed class CodeEmitterLabel diff --git a/src/IKVM.Runtime/CodeEmitterLocal.cs b/src/IKVM.Runtime/CodeEmitterLocal.cs index 01f0a9885a..3005afa572 100644 --- a/src/IKVM.Runtime/CodeEmitterLocal.cs +++ b/src/IKVM.Runtime/CodeEmitterLocal.cs @@ -31,7 +31,7 @@ Jeroen Frijters using System.Reflection.Emit; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { sealed class CodeEmitterLocal diff --git a/src/IKVM.Runtime/CodeGenOptions.cs b/src/IKVM.Runtime/CodeGenOptions.cs index f9f1e5779d..b7bb5967dc 100644 --- a/src/IKVM.Runtime/CodeGenOptions.cs +++ b/src/IKVM.Runtime/CodeGenOptions.cs @@ -26,17 +26,20 @@ Jeroen Frijters #if IMPORTER || EXPORTER using IKVM.Reflection; using IKVM.Reflection.Emit; + using Type = IKVM.Reflection.Type; using ProtectionDomain = System.Object; #else #endif -namespace IKVM.Internal +namespace IKVM.Runtime { + [Flags] enum CodeGenOptions { + None = 0, Debug = 1, NoStackTraceInfo = 2, @@ -47,5 +50,7 @@ enum CodeGenOptions DisableDynamicBinding = 64, NoRefEmitHelpers = 128, RemoveUnusedFields = 256, + } + } diff --git a/src/IKVM.Runtime/CodeInfo.cs b/src/IKVM.Runtime/CodeInfo.cs new file mode 100644 index 0000000000..b26a196a75 --- /dev/null +++ b/src/IKVM.Runtime/CodeInfo.cs @@ -0,0 +1,75 @@ +/* + Copyright (C) 2002-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +namespace IKVM.Runtime +{ + + readonly struct CodeInfo + { + + private readonly InstructionState[] state; + + internal CodeInfo(InstructionState[] state) + { + this.state = state; + } + + internal bool HasState(int index) + { + return state[index] != null; + } + + internal int GetStackHeight(int index) + { + return state[index].GetStackHeight(); + } + + internal TypeWrapper GetStackTypeWrapper(int index, int pos) + { + TypeWrapper type = state[index].GetStackSlot(pos); + if (VerifierTypeWrapper.IsThis(type)) + { + type = ((VerifierTypeWrapper)type).UnderlyingType; + } + return type; + } + + internal TypeWrapper GetRawStackTypeWrapper(int index, int pos) + { + return state[index].GetStackSlot(pos); + } + + internal bool IsStackTypeExtendedDouble(int index, int pos) + { + return state[index].GetStackSlotEx(pos) == VerifierTypeWrapper.ExtendedDouble; + } + + internal TypeWrapper GetLocalTypeWrapper(int index, int local) + { + return state[index].GetLocalTypeEx(local); + } + + } + +} diff --git a/src/IKVM.Runtime/CompiledAccessStubFieldWrapper.cs b/src/IKVM.Runtime/CompiledAccessStubFieldWrapper.cs index ff8c43eacc..9446025100 100644 --- a/src/IKVM.Runtime/CompiledAccessStubFieldWrapper.cs +++ b/src/IKVM.Runtime/CompiledAccessStubFieldWrapper.cs @@ -33,11 +33,7 @@ Jeroen Frijters using System.Reflection.Emit; #endif -#if IMPORTER -using IKVM.Tools.Importer; -#endif - -namespace IKVM.Internal +namespace IKVM.Runtime { sealed class CompiledAccessStubFieldWrapper : FieldWrapper diff --git a/src/IKVM.Runtime/CompiledPropertyFieldWrapper.cs b/src/IKVM.Runtime/CompiledPropertyFieldWrapper.cs index bc7e26a78b..b24da5024e 100644 --- a/src/IKVM.Runtime/CompiledPropertyFieldWrapper.cs +++ b/src/IKVM.Runtime/CompiledPropertyFieldWrapper.cs @@ -32,11 +32,7 @@ Jeroen Frijters using System.Reflection.Emit; #endif -#if IMPORTER -using IKVM.Tools.Importer; -#endif - -namespace IKVM.Internal +namespace IKVM.Runtime { /// diff --git a/src/IKVM.Runtime/CompiledTypeWrapper.cs b/src/IKVM.Runtime/CompiledTypeWrapper.cs index ffe612c3c8..a7516325c3 100644 --- a/src/IKVM.Runtime/CompiledTypeWrapper.cs +++ b/src/IKVM.Runtime/CompiledTypeWrapper.cs @@ -26,7 +26,6 @@ Jeroen Frijters using System.Diagnostics; using IKVM.Attributes; -using IKVM.Runtime; using IKVM.Runtime.Syntax; using IKVM.ByteCode; @@ -44,7 +43,7 @@ Jeroen Frijters using IKVM.Tools.Importer; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { class CompiledTypeWrapper : TypeWrapper diff --git a/src/IKVM.Runtime/ConstantFieldWrapper.cs b/src/IKVM.Runtime/ConstantFieldWrapper.cs index ff12655d96..33609694c1 100644 --- a/src/IKVM.Runtime/ConstantFieldWrapper.cs +++ b/src/IKVM.Runtime/ConstantFieldWrapper.cs @@ -25,7 +25,6 @@ Jeroen Frijters using System.Diagnostics; using IKVM.Attributes; -using IKVM.Runtime; #if IMPORTER || EXPORTER using IKVM.Reflection; @@ -37,11 +36,7 @@ Jeroen Frijters using System.Reflection.Emit; #endif -#if IMPORTER -using IKVM.Tools.Importer; -#endif - -namespace IKVM.Internal +namespace IKVM.Runtime { /// diff --git a/src/IKVM.Runtime/CoreClasses.cs b/src/IKVM.Runtime/CoreClasses.cs index fa7f736c94..d185ffb838 100644 --- a/src/IKVM.Runtime/CoreClasses.cs +++ b/src/IKVM.Runtime/CoreClasses.cs @@ -22,9 +22,9 @@ Jeroen Frijters */ -namespace IKVM.Internal +namespace IKVM.Runtime { - internal static class CoreClasses + internal static class CoreClasses { internal static class cli diff --git a/src/IKVM.Runtime/DefaultInterfaceMethodWrapper.cs b/src/IKVM.Runtime/DefaultInterfaceMethodWrapper.cs index f4b65d185b..016840f258 100644 --- a/src/IKVM.Runtime/DefaultInterfaceMethodWrapper.cs +++ b/src/IKVM.Runtime/DefaultInterfaceMethodWrapper.cs @@ -33,7 +33,7 @@ Jeroen Frijters using System.Reflection.Emit; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { sealed class DefaultInterfaceMethodWrapper : SmartMethodWrapper diff --git a/src/IKVM.Runtime/DefineMethodHelper.cs b/src/IKVM.Runtime/DefineMethodHelper.cs index 4766d415de..cde1c007c3 100644 --- a/src/IKVM.Runtime/DefineMethodHelper.cs +++ b/src/IKVM.Runtime/DefineMethodHelper.cs @@ -36,7 +36,7 @@ Jeroen Frijters using System.Reflection.Emit; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { sealed class DefineMethodHelper diff --git a/src/IKVM.Runtime/DotNetTypeWrapper.cs b/src/IKVM.Runtime/DotNetTypeWrapper.cs index 4a7fdd819c..fc2d437909 100644 --- a/src/IKVM.Runtime/DotNetTypeWrapper.cs +++ b/src/IKVM.Runtime/DotNetTypeWrapper.cs @@ -26,7 +26,6 @@ Jeroen Frijters using System.Diagnostics; using IKVM.Attributes; -using IKVM.Runtime; #if IMPORTER || EXPORTER using IKVM.Reflection; @@ -42,7 +41,7 @@ Jeroen Frijters using IKVM.Tools.Importer; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { sealed class DotNetTypeWrapper : TypeWrapper diff --git a/src/IKVM.Runtime/DynamicCallerIDProvider.cs b/src/IKVM.Runtime/DynamicCallerIDProvider.cs index 3c81fb635e..9cad095b5f 100644 --- a/src/IKVM.Runtime/DynamicCallerIDProvider.cs +++ b/src/IKVM.Runtime/DynamicCallerIDProvider.cs @@ -22,21 +22,11 @@ Jeroen Frijters */ using System.Diagnostics; - -#if IMPORTER -using IKVM.Reflection; -using IKVM.Reflection.Emit; -using IKVM.Tools.Importer; - -using Type = IKVM.Reflection.Type; -using DynamicOrAotTypeWrapper = IKVM.Tools.Importer.AotTypeWrapper; -using ProtectionDomain = System.Object; -#else using System.Reflection; -#endif -namespace IKVM.Internal +namespace IKVM.Runtime { + #if !IMPORTER sealed class DynamicCallerIDProvider diff --git a/src/IKVM.Runtime/DynamicClassLoader.cs b/src/IKVM.Runtime/DynamicClassLoader.cs index 0f625c3ab9..f68f5d731e 100644 --- a/src/IKVM.Runtime/DynamicClassLoader.cs +++ b/src/IKVM.Runtime/DynamicClassLoader.cs @@ -27,8 +27,6 @@ Jeroen Frijters using System.Runtime.CompilerServices; using System.Runtime.Serialization; -using IKVM.Runtime; - #if IMPORTER using IKVM.Reflection; using IKVM.Reflection.Emit; @@ -43,7 +41,7 @@ Jeroen Frijters using ProtectionDomain = java.security.ProtectionDomain; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { /// diff --git a/src/IKVM.Runtime/DynamicMethodUtil.cs b/src/IKVM.Runtime/DynamicMethodUtil.cs index b7792438fa..81cde41b18 100644 --- a/src/IKVM.Runtime/DynamicMethodUtil.cs +++ b/src/IKVM.Runtime/DynamicMethodUtil.cs @@ -3,8 +3,6 @@ using System.Reflection.Emit; using System.Security; -using IKVM.Internal; - namespace IKVM.Runtime { diff --git a/src/IKVM.Runtime/DynamicPropertyFieldWrapper.cs b/src/IKVM.Runtime/DynamicPropertyFieldWrapper.cs index 6543bdd696..36b846e510 100644 --- a/src/IKVM.Runtime/DynamicPropertyFieldWrapper.cs +++ b/src/IKVM.Runtime/DynamicPropertyFieldWrapper.cs @@ -37,7 +37,7 @@ Jeroen Frijters using IKVM.Tools.Importer; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { #if EXPORTER == false diff --git a/src/IKVM.Runtime/DynamicTypeWrapper.DynamicImpl.cs b/src/IKVM.Runtime/DynamicTypeWrapper.DynamicImpl.cs index fe06ee2a48..040648a981 100644 --- a/src/IKVM.Runtime/DynamicTypeWrapper.DynamicImpl.cs +++ b/src/IKVM.Runtime/DynamicTypeWrapper.DynamicImpl.cs @@ -27,17 +27,13 @@ Jeroen Frijters #if IMPORTER using IKVM.Reflection; -using IKVM.Reflection.Emit; -using IKVM.Tools.Importer; using Type = IKVM.Reflection.Type; -using DynamicOrAotTypeWrapper = IKVM.Tools.Importer.AotTypeWrapper; -using ProtectionDomain = System.Object; #else using System.Reflection; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { #if IMPORTER @@ -47,8 +43,10 @@ abstract partial class DynamicTypeWrapper : TypeWrapper sealed partial class DynamicTypeWrapper #endif { + private abstract class DynamicImpl { + internal abstract Type Type { get; } internal abstract TypeWrapper[] InnerClasses { get; } internal abstract TypeWrapper DeclaringTypeWrapper { get; } @@ -73,7 +71,9 @@ private abstract class DynamicImpl internal abstract byte[] GetMethodRawTypeAnnotations(int index); internal abstract byte[] GetFieldRawTypeAnnotations(int index); internal abstract TypeWrapper Host { get; } + } + } } \ No newline at end of file diff --git a/src/IKVM.Runtime/DynamicTypeWrapper.FinishContext.cs b/src/IKVM.Runtime/DynamicTypeWrapper.FinishContext.cs index a1e4cb9a70..62a77e90b6 100644 --- a/src/IKVM.Runtime/DynamicTypeWrapper.FinishContext.cs +++ b/src/IKVM.Runtime/DynamicTypeWrapper.FinishContext.cs @@ -27,7 +27,6 @@ Jeroen Frijters using IKVM.ByteCode.Reading; using IKVM.Attributes; -using IKVM.Runtime; #if IMPORTER using IKVM.Reflection; @@ -36,15 +35,14 @@ Jeroen Frijters using Type = IKVM.Reflection.Type; using DynamicOrAotTypeWrapper = IKVM.Tools.Importer.AotTypeWrapper; -using ProtectionDomain = System.Object; #else using System.Reflection; using System.Reflection.Emit; -using DynamicOrAotTypeWrapper = IKVM.Internal.DynamicTypeWrapper; +using DynamicOrAotTypeWrapper = IKVM.Runtime.DynamicTypeWrapper; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { #if IMPORTER @@ -54,8 +52,10 @@ abstract partial class DynamicTypeWrapper : TypeWrapper sealed partial class DynamicTypeWrapper #endif { + internal sealed class FinishContext { + private readonly TypeWrapper host; private readonly ClassFile classFile; private readonly DynamicOrAotTypeWrapper wrapper; diff --git a/src/IKVM.Runtime/DynamicTypeWrapper.FinishedTypeImpl.cs b/src/IKVM.Runtime/DynamicTypeWrapper.FinishedTypeImpl.cs index 37e159c689..d9887dfdc5 100644 --- a/src/IKVM.Runtime/DynamicTypeWrapper.FinishedTypeImpl.cs +++ b/src/IKVM.Runtime/DynamicTypeWrapper.FinishedTypeImpl.cs @@ -32,14 +32,12 @@ Jeroen Frijters using IKVM.Tools.Importer; using Type = IKVM.Reflection.Type; -using DynamicOrAotTypeWrapper = IKVM.Tools.Importer.AotTypeWrapper; -using ProtectionDomain = System.Object; #else using System.Reflection; using System.Reflection.Emit; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { #if IMPORTER @@ -49,6 +47,7 @@ abstract partial class DynamicTypeWrapper : TypeWrapper sealed partial class DynamicTypeWrapper #endif { + sealed class FinishedTypeImpl : DynamicImpl { diff --git a/src/IKVM.Runtime/DynamicTypeWrapper.JavaTypeImpl.cs b/src/IKVM.Runtime/DynamicTypeWrapper.JavaTypeImpl.cs index a336fd28e9..941a6085ee 100644 --- a/src/IKVM.Runtime/DynamicTypeWrapper.JavaTypeImpl.cs +++ b/src/IKVM.Runtime/DynamicTypeWrapper.JavaTypeImpl.cs @@ -26,7 +26,6 @@ Jeroen Frijters using System.Diagnostics; using IKVM.Attributes; -using IKVM.Runtime; #if IMPORTER using IKVM.Reflection; @@ -35,15 +34,14 @@ Jeroen Frijters using Type = IKVM.Reflection.Type; using DynamicOrAotTypeWrapper = IKVM.Tools.Importer.AotTypeWrapper; -using ProtectionDomain = System.Object; #else using System.Reflection; using System.Reflection.Emit; -using DynamicOrAotTypeWrapper = IKVM.Internal.DynamicTypeWrapper; +using DynamicOrAotTypeWrapper = IKVM.Runtime.DynamicTypeWrapper; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { #if IMPORTER @@ -53,6 +51,7 @@ abstract partial class DynamicTypeWrapper : TypeWrapper sealed partial class DynamicTypeWrapper #endif { + private sealed class JavaTypeImpl : DynamicImpl { private readonly TypeWrapper host; diff --git a/src/IKVM.Runtime/DynamicTypeWrapper.Metadata.cs b/src/IKVM.Runtime/DynamicTypeWrapper.Metadata.cs index a9354ec210..62d2c2fc08 100644 --- a/src/IKVM.Runtime/DynamicTypeWrapper.Metadata.cs +++ b/src/IKVM.Runtime/DynamicTypeWrapper.Metadata.cs @@ -22,24 +22,12 @@ Jeroen Frijters */ using System.Collections.Generic; - -using IKVM.Runtime; -using IKVM.ByteCode.Reading; -using IKVM.ByteCode.Parsing; - using System.Linq; -#if IMPORTER -using IKVM.Reflection; -using IKVM.Reflection.Emit; -using IKVM.Tools.Importer; - -using Type = IKVM.Reflection.Type; -using DynamicOrAotTypeWrapper = IKVM.Tools.Importer.AotTypeWrapper; -using ProtectionDomain = System.Object; -#endif +using IKVM.ByteCode.Parsing; +using IKVM.ByteCode.Reading; -namespace IKVM.Internal +namespace IKVM.Runtime { #if IMPORTER @@ -49,6 +37,7 @@ abstract partial class DynamicTypeWrapper : TypeWrapper sealed partial class DynamicTypeWrapper #endif { + sealed class Metadata { diff --git a/src/IKVM.Runtime/DynamicTypeWrapper.cs b/src/IKVM.Runtime/DynamicTypeWrapper.cs index 8304866631..ce7e0c6b95 100644 --- a/src/IKVM.Runtime/DynamicTypeWrapper.cs +++ b/src/IKVM.Runtime/DynamicTypeWrapper.cs @@ -26,7 +26,6 @@ Jeroen Frijters using System.Diagnostics; using IKVM.Attributes; -using IKVM.Runtime; #if IMPORTER using IKVM.Reflection; @@ -40,11 +39,11 @@ Jeroen Frijters using System.Reflection; using System.Reflection.Emit; -using DynamicOrAotTypeWrapper = IKVM.Internal.DynamicTypeWrapper; +using DynamicOrAotTypeWrapper = IKVM.Runtime.DynamicTypeWrapper; using ProtectionDomain = java.security.ProtectionDomain; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { #if IMPORTER diff --git a/src/IKVM.Runtime/EmitIntrinsicContext.cs b/src/IKVM.Runtime/EmitIntrinsicContext.cs new file mode 100644 index 0000000000..0ff3644aaa --- /dev/null +++ b/src/IKVM.Runtime/EmitIntrinsicContext.cs @@ -0,0 +1,121 @@ +/* + Copyright (C) 2008-2013 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +using Instruction = IKVM.Runtime.ClassFile.Method.Instruction; +using InstructionFlags = IKVM.Runtime.ClassFile.Method.InstructionFlags; + +namespace IKVM.Runtime +{ + + sealed class EmitIntrinsicContext + { + + internal readonly MethodWrapper Method; + internal readonly DynamicTypeWrapper.FinishContext Context; + internal readonly CodeEmitter Emitter; + readonly CodeInfo ma; + internal readonly int OpcodeIndex; + internal readonly MethodWrapper Caller; + internal readonly ClassFile ClassFile; + internal readonly Instruction[] Code; + internal readonly InstructionFlags[] Flags; + internal bool NonLeaf = true; + + internal EmitIntrinsicContext(MethodWrapper method, DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, CodeInfo ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) + { + this.Method = method; + this.Context = context; + this.Emitter = ilgen; + this.ma = ma; + this.OpcodeIndex = opcodeIndex; + this.Caller = caller; + this.ClassFile = classFile; + this.Code = code; + this.Flags = flags; + } + + internal bool MatchRange(int offset, int length) + { + if (OpcodeIndex + offset < 0) + return false; + + if (OpcodeIndex + offset + length > Code.Length) + return false; + + // we check for branches *into* the range, the start of the range may be a branch target + for (int i = OpcodeIndex + offset + 1, end = OpcodeIndex + offset + length; i < end; i++) + if ((Flags[i] & InstructionFlags.BranchTarget) != 0) + return false; + + return true; + } + + internal bool Match(int offset, NormalizedByteCode opcode) + { + return Code[OpcodeIndex + offset].NormalizedOpCode == opcode; + } + + internal bool Match(int offset, NormalizedByteCode opcode, int arg) + { + return Code[OpcodeIndex + offset].NormalizedOpCode == opcode && Code[OpcodeIndex + offset].Arg1 == arg; + } + + internal TypeWrapper GetStackTypeWrapper(int offset, int pos) + { + return ma.GetStackTypeWrapper(OpcodeIndex + offset, pos); + } + + internal ClassFile.ConstantPoolItemMI GetMethodref(int offset) + { + return ClassFile.GetMethodref(Code[OpcodeIndex + offset].Arg1); + } + + internal ClassFile.ConstantPoolItemFieldref GetFieldref(int offset) + { + return ClassFile.GetFieldref(Code[OpcodeIndex + offset].Arg1); + } + + internal TypeWrapper GetClassLiteral(int offset) + { + return ClassFile.GetConstantPoolClassType(Code[OpcodeIndex + offset].Arg1); + } + + internal string GetStringLiteral(int offset) + { + return ClassFile.GetConstantPoolConstantString(Code[OpcodeIndex + offset].Arg1); + } + + internal ClassFile.ConstantType GetConstantType(int offset) + { + return ClassFile.GetConstantPoolConstantType(Code[OpcodeIndex + offset].Arg1); + } + + internal void PatchOpCode(int offset, NormalizedByteCode opc) + { + Code[OpcodeIndex + offset].PatchOpCode(opc); + } + + } + +} diff --git a/src/IKVM.Runtime/EnumHelper.cs b/src/IKVM.Runtime/EnumHelper.cs index 2e6550984f..93a0537608 100644 --- a/src/IKVM.Runtime/EnumHelper.cs +++ b/src/IKVM.Runtime/EnumHelper.cs @@ -24,26 +24,21 @@ Jeroen Frijters using System; using System.Diagnostics; -using IKVM.Runtime; - #if IMPORTER || EXPORTER using IKVM.Reflection; -using IKVM.Reflection.Emit; using Type = IKVM.Reflection.Type; -#else -#endif - -#if IMPORTER -using IKVM.Tools.Importer; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { + static class EnumHelper { + internal static Type GetUnderlyingType(Type enumType) { + #if IMPORTER || EXPORTER return enumType.GetEnumUnderlyingType(); #else @@ -52,6 +47,7 @@ internal static Type GetUnderlyingType(Type enumType) } #if IMPORTER + internal static object Parse(Type type, string value) { object retval = null; @@ -147,6 +143,7 @@ internal static object GetPrimitiveValue(Type underlyingType, object obj) throw new InvalidOperationException(); } } + } } diff --git a/src/IKVM.Runtime/ExModifiers.cs b/src/IKVM.Runtime/ExModifiers.cs index bd6187098e..ce7a3d86eb 100644 --- a/src/IKVM.Runtime/ExModifiers.cs +++ b/src/IKVM.Runtime/ExModifiers.cs @@ -23,8 +23,9 @@ Jeroen Frijters */ using IKVM.Attributes; -namespace IKVM.Internal +namespace IKVM.Runtime { + struct ExModifiers { diff --git a/src/IKVM.Runtime/ExceptionHelper.cs b/src/IKVM.Runtime/ExceptionHelper.cs index d45e0e60a9..2cb495fdea 100644 --- a/src/IKVM.Runtime/ExceptionHelper.cs +++ b/src/IKVM.Runtime/ExceptionHelper.cs @@ -29,7 +29,6 @@ Jeroen Frijters using System.Security; using IKVM.Attributes; -using IKVM.Runtime; using IDictionary = System.Collections.IDictionary; using Interlocked = System.Threading.Interlocked; @@ -43,7 +42,7 @@ Jeroen Frijters using Throwable = java.lang.Throwable; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { static class ExceptionHelper diff --git a/src/IKVM.Runtime/ExceptionSorter.cs b/src/IKVM.Runtime/ExceptionSorter.cs new file mode 100644 index 0000000000..35d1932bfd --- /dev/null +++ b/src/IKVM.Runtime/ExceptionSorter.cs @@ -0,0 +1,64 @@ +/* + Copyright (C) 2002-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System.Collections.Generic; + +using ExceptionTableEntry = IKVM.Runtime.ClassFile.Method.ExceptionTableEntry; + +namespace IKVM.Runtime +{ + + sealed class ExceptionSorter : IComparer + { + + public int Compare(ExceptionTableEntry e1, ExceptionTableEntry e2) + { + if (e1.startIndex < e2.startIndex) + { + return -1; + } + if (e1.startIndex == e2.startIndex) + { + if (e1.endIndex == e2.endIndex) + { + if (e1.ordinal > e2.ordinal) + { + return -1; + } + if (e1.ordinal == e2.ordinal) + { + return 0; + } + return 1; + } + if (e1.endIndex > e2.endIndex) + { + return -1; + } + } + return 1; + } + + } + +} diff --git a/src/IKVM.Runtime/FieldWrapper.cs b/src/IKVM.Runtime/FieldWrapper.cs index 5d13982080..cfa6e3d38b 100644 --- a/src/IKVM.Runtime/FieldWrapper.cs +++ b/src/IKVM.Runtime/FieldWrapper.cs @@ -27,9 +27,6 @@ Jeroen Frijters using IKVM.Attributes; using System.Threading; -using System.CodeDom; -using System.Linq; -using IKVM.Runtime; #if IMPORTER || EXPORTER using IKVM.Reflection; @@ -41,7 +38,7 @@ Jeroen Frijters using System.Reflection.Emit; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { abstract class FieldWrapper : MemberWrapper diff --git a/src/IKVM.Runtime/GenericClassLoaderWrapper.cs b/src/IKVM.Runtime/GenericClassLoaderWrapper.cs index 81e4e9f366..5e56b16421 100644 --- a/src/IKVM.Runtime/GenericClassLoaderWrapper.cs +++ b/src/IKVM.Runtime/GenericClassLoaderWrapper.cs @@ -23,18 +23,7 @@ Jeroen Frijters */ using System; -#if NETCOREAPP -using System.Runtime.Loader; -#endif - -#if IMPORTER || EXPORTER -using IKVM.Reflection; -using IKVM.Reflection.Emit; -using Type = IKVM.Reflection.Type; -using ProtectionDomain = System.Object; -#endif - -namespace IKVM.Internal +namespace IKVM.Runtime { sealed class GenericClassLoaderWrapper : ClassLoaderWrapper diff --git a/src/IKVM.Runtime/GhostMethodWrapper.cs b/src/IKVM.Runtime/GhostMethodWrapper.cs index 15beff69d1..6760702a5e 100644 --- a/src/IKVM.Runtime/GhostMethodWrapper.cs +++ b/src/IKVM.Runtime/GhostMethodWrapper.cs @@ -28,14 +28,12 @@ Jeroen Frijters #if IMPORTER || EXPORTER using IKVM.Reflection; using IKVM.Reflection.Emit; - -using Type = IKVM.Reflection.Type; #else using System.Reflection; using System.Reflection.Emit; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { sealed class GhostMethodWrapper : SmartMethodWrapper diff --git a/src/IKVM.Runtime/GhostTag.cs b/src/IKVM.Runtime/GhostTag.cs index 1e60bd338f..f172051933 100644 --- a/src/IKVM.Runtime/GhostTag.cs +++ b/src/IKVM.Runtime/GhostTag.cs @@ -26,15 +26,6 @@ Jeroen Frijters using System.Threading; using IKVM.Attributes; -using IKVM.Internal; - -#if IMPORTER || EXPORTER -using IKVM.Reflection; -using IKVM.Reflection.Emit; - -using Type = IKVM.Reflection.Type; -#else -#endif namespace IKVM.Runtime { @@ -103,6 +94,7 @@ internal static void ThrowClassCastException(object obj, RuntimeTypeHandle typeH throw new global::java.lang.ClassCastException(sb.ToString()); #endif } + } } diff --git a/src/IKVM.Runtime/ClassFile/HardError.cs b/src/IKVM.Runtime/HardError.cs similarity index 98% rename from src/IKVM.Runtime/ClassFile/HardError.cs rename to src/IKVM.Runtime/HardError.cs index c24be17987..b6021c1e07 100644 --- a/src/IKVM.Runtime/ClassFile/HardError.cs +++ b/src/IKVM.Runtime/HardError.cs @@ -22,7 +22,7 @@ Jeroen Frijters */ -namespace IKVM.Internal +namespace IKVM.Runtime { enum HardError : short diff --git a/src/IKVM.Runtime/IKVM.Runtime.csproj b/src/IKVM.Runtime/IKVM.Runtime.csproj index 2ad4359872..0631d33f93 100644 --- a/src/IKVM.Runtime/IKVM.Runtime.csproj +++ b/src/IKVM.Runtime/IKVM.Runtime.csproj @@ -69,15 +69,15 @@ - - - - - - - - - + + + + + + + + + diff --git a/src/IKVM.Runtime/InstructionState.cs b/src/IKVM.Runtime/InstructionState.cs new file mode 100644 index 0000000000..e7bbe84fec --- /dev/null +++ b/src/IKVM.Runtime/InstructionState.cs @@ -0,0 +1,943 @@ +/* + Copyright (C) 2002-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; + +#if IMPORTER +using IKVM.Tools.Importer; +#endif + +namespace IKVM.Runtime +{ + + sealed class InstructionState + { + + private struct LocalStoreSites + { + + private int[] data; + private int count; + private bool shared; + + internal LocalStoreSites Copy() + { + LocalStoreSites n = new LocalStoreSites(); + n.data = data; + n.count = count; + n.shared = true; + return n; + } + + internal static LocalStoreSites Alloc() + { + LocalStoreSites n = new LocalStoreSites(); + n.data = new int[4]; + return n; + } + + internal void Add(int store) + { + for (int i = 0; i < count; i++) + { + if (data[i] == store) + { + return; + } + } + if (count == data.Length) + { + int[] newarray = new int[data.Length * 2]; + Buffer.BlockCopy(data, 0, newarray, 0, data.Length * 4); + data = newarray; + shared = false; + } + if (shared) + { + shared = false; + data = (int[])data.Clone(); + } + data[count++] = store; + } + + internal int this[int index] + { + get + { + return data[index]; + } + } + + internal int Count + { + get + { + return count; + } + } + + internal static void MarkShared(LocalStoreSites[] localStoreSites) + { + for (int i = 0; i < localStoreSites.Length; i++) + { + localStoreSites[i].shared = true; + } + } + } + + TypeWrapper[] stack; + int stackSize; + int stackEnd; + TypeWrapper[] locals; + bool unitializedThis; + internal bool changed = true; + + private enum ShareFlags : byte + { + None = 0, + Stack = 1, + Locals = 2, + All = Stack | Locals + } + private ShareFlags flags; + + private InstructionState(TypeWrapper[] stack, int stackSize, int stackEnd, TypeWrapper[] locals, bool unitializedThis) + { + this.flags = ShareFlags.All; + this.stack = stack; + this.stackSize = stackSize; + this.stackEnd = stackEnd; + this.locals = locals; + this.unitializedThis = unitializedThis; + } + + internal InstructionState(int maxLocals, int maxStack) + { + this.flags = ShareFlags.None; + this.stack = new TypeWrapper[maxStack]; + this.stackEnd = maxStack; + this.locals = new TypeWrapper[maxLocals]; + } + + internal InstructionState Copy() + { + return new InstructionState(stack, stackSize, stackEnd, locals, unitializedThis); + } + + internal void CopyTo(InstructionState target) + { + target.flags = ShareFlags.All; + target.stack = stack; + target.stackSize = stackSize; + target.stackEnd = stackEnd; + target.locals = locals; + target.unitializedThis = unitializedThis; + target.changed = true; + } + + internal InstructionState CopyLocals() + { + InstructionState copy = new InstructionState(new TypeWrapper[stack.Length], 0, stack.Length, locals, unitializedThis); + copy.flags &= ~ShareFlags.Stack; + return copy; + } + + public static InstructionState operator +(InstructionState s1, InstructionState s2) + { + if (s1 == null) + { + return s2.Copy(); + } + if (s1.stackSize != s2.stackSize || s1.stackEnd != s2.stackEnd) + { + throw new VerifyError(string.Format("Inconsistent stack height: {0} != {1}", + s1.stackSize + s1.stack.Length - s1.stackEnd, + s2.stackSize + s2.stack.Length - s2.stackEnd)); + } + InstructionState s = s1.Copy(); + s.changed = s1.changed; + for (int i = 0; i < s.stackSize; i++) + { + TypeWrapper type = s.stack[i]; + TypeWrapper type2 = s2.stack[i]; + if (type == type2) + { + // perfect match, nothing to do + } + else if ((type == VerifierTypeWrapper.ExtendedDouble && type2 == PrimitiveTypeWrapper.DOUBLE) + || (type2 == VerifierTypeWrapper.ExtendedDouble && type == PrimitiveTypeWrapper.DOUBLE)) + { + if (type != VerifierTypeWrapper.ExtendedDouble) + { + s.StackCopyOnWrite(); + s.stack[i] = VerifierTypeWrapper.ExtendedDouble; + s.changed = true; + } + } + else if ((type == VerifierTypeWrapper.ExtendedFloat && type2 == PrimitiveTypeWrapper.FLOAT) + || (type2 == VerifierTypeWrapper.ExtendedFloat && type == PrimitiveTypeWrapper.FLOAT)) + { + if (type != VerifierTypeWrapper.ExtendedFloat) + { + s.StackCopyOnWrite(); + s.stack[i] = VerifierTypeWrapper.ExtendedFloat; + s.changed = true; + } + } + else if (!type.IsPrimitive) + { + TypeWrapper baseType = InstructionState.FindCommonBaseType(type, type2); + if (baseType == VerifierTypeWrapper.Invalid) + { + throw new VerifyError(string.Format("cannot merge {0} and {1}", type.Name, type2.Name)); + } + if (type != baseType) + { + s.StackCopyOnWrite(); + s.stack[i] = baseType; + s.changed = true; + } + } + else + { + throw new VerifyError(string.Format("cannot merge {0} and {1}", type.Name, type2.Name)); + } + } + for (int i = 0; i < s.locals.Length; i++) + { + TypeWrapper type = s.locals[i]; + TypeWrapper type2 = s2.locals[i]; + TypeWrapper baseType = InstructionState.FindCommonBaseType(type, type2); + if (type != baseType) + { + s.LocalsCopyOnWrite(); + s.locals[i] = baseType; + s.changed = true; + } + } + if (!s.unitializedThis && s2.unitializedThis) + { + s.unitializedThis = true; + s.changed = true; + } + return s; + } + + private static LocalStoreSites MergeStoreSites(LocalStoreSites h1, LocalStoreSites h2) + { + if (h1.Count == 0) + { + return h2.Copy(); + } + if (h2.Count == 0) + { + return h1.Copy(); + } + LocalStoreSites h = h1.Copy(); + for (int i = 0; i < h2.Count; i++) + { + h.Add(h2[i]); + } + return h; + } + + internal void SetUnitializedThis(bool state) + { + unitializedThis = state; + } + + internal void CheckUninitializedThis() + { + if (unitializedThis) + { + throw new VerifyError("Base class constructor wasn't called"); + } + } + + internal static TypeWrapper FindCommonBaseType(TypeWrapper type1, TypeWrapper type2) + { + if (type1 == type2) + { + return type1; + } + if (type1 == VerifierTypeWrapper.Null) + { + return type2; + } + if (type2 == VerifierTypeWrapper.Null) + { + return type1; + } + if (type1 == VerifierTypeWrapper.Invalid || type2 == VerifierTypeWrapper.Invalid) + { + return VerifierTypeWrapper.Invalid; + } + if (VerifierTypeWrapper.IsFaultBlockException(type1)) + { + VerifierTypeWrapper.ClearFaultBlockException(type1); + return FindCommonBaseType(CoreClasses.java.lang.Throwable.Wrapper, type2); + } + if (VerifierTypeWrapper.IsFaultBlockException(type2)) + { + VerifierTypeWrapper.ClearFaultBlockException(type2); + return FindCommonBaseType(type1, CoreClasses.java.lang.Throwable.Wrapper); + } + if (type1.IsPrimitive || type2.IsPrimitive) + { + return VerifierTypeWrapper.Invalid; + } + if (type1 == VerifierTypeWrapper.UninitializedThis || type2 == VerifierTypeWrapper.UninitializedThis) + { + return VerifierTypeWrapper.Invalid; + } + if (VerifierTypeWrapper.IsNew(type1) || VerifierTypeWrapper.IsNew(type2)) + { + return VerifierTypeWrapper.Invalid; + } + if (VerifierTypeWrapper.IsThis(type1)) + { + type1 = ((VerifierTypeWrapper)type1).UnderlyingType; + } + if (VerifierTypeWrapper.IsThis(type2)) + { + type2 = ((VerifierTypeWrapper)type2).UnderlyingType; + } + if (type1.IsUnloadable || type2.IsUnloadable) + { + return VerifierTypeWrapper.Unloadable; + } + if (type1.ArrayRank > 0 && type2.ArrayRank > 0) + { + int rank = 1; + int rank1 = type1.ArrayRank - 1; + int rank2 = type2.ArrayRank - 1; + TypeWrapper elem1 = type1.ElementTypeWrapper; + TypeWrapper elem2 = type2.ElementTypeWrapper; + while (rank1 != 0 && rank2 != 0) + { + elem1 = elem1.ElementTypeWrapper; + elem2 = elem2.ElementTypeWrapper; + rank++; + rank1--; + rank2--; + } + // NOTE arrays of value types have special merging semantics! + // NOTE we don't have to test for the case where the element types are the same, because that + // is only relevant if the ranks are the same, but if that is the case the types are completely + // identical, in which case the identity test at the top of this method already returned. + TypeWrapper baseType; + if (elem1.IsPrimitive || elem2.IsPrimitive || elem1.IsNonPrimitiveValueType || elem2.IsNonPrimitiveValueType) + { + baseType = CoreClasses.java.lang.Object.Wrapper; + rank--; + if (rank == 0) + { + return baseType; + } + } + else + { + baseType = FindCommonBaseTypeHelper(elem1, elem2); + } + return baseType.MakeArrayType(rank); + } + return FindCommonBaseTypeHelper(type1, type2); + } + + private static TypeWrapper FindCommonBaseTypeHelper(TypeWrapper t1, TypeWrapper t2) + { + if (t1 == t2) + { + return t1; + } + if (t1.IsInterface || t2.IsInterface) + { + // NOTE according to a paper by Alessandro Coglio & Allen Goldberg titled + // "Type Safety in the JVM: Some Problems in Java 2 SDK 1.2 and Proposed Solutions" + // the common base of two interfaces is java.lang.Object, and there is special + // treatment for java.lang.Object types that allow it to be assigned to any interface + // type, the JVM's typesafety then depends on the invokeinterface instruction to make + // sure that the reference actually implements the interface. + // NOTE the ECMA CLI spec also specifies this interface merging algorithm, so we can't + // really do anything more clever than this. + return CoreClasses.java.lang.Object.Wrapper; + } + Stack st1 = new Stack(); + Stack st2 = new Stack(); + while (t1 != null) + { + st1.Push(t1); + t1 = t1.BaseTypeWrapper; + } + while (t2 != null) + { + st2.Push(t2); + t2 = t2.BaseTypeWrapper; + } + if (HasMissingBaseType(st1) || HasMissingBaseType(st2)) + { + return VerifierTypeWrapper.Unloadable; + } + TypeWrapper type = CoreClasses.java.lang.Object.Wrapper; + for (; ; ) + { + t1 = st1.Count > 0 ? st1.Pop() : null; + t2 = st2.Count > 0 ? st2.Pop() : null; + if (t1 != t2) + { + return type; + } + type = t1; + } + } + + private static bool HasMissingBaseType(Stack st) + { +#if IMPORTER + if (st.Pop().IsUnloadable) + { + // we have a missing type in base class hierarchy + StaticCompiler.IssueMissingTypeMessage(st.Pop().TypeAsBaseType.BaseType); + return true; + } +#endif + return false; + } + + private void SetLocal1(int index, TypeWrapper type) + { + try + { + LocalsCopyOnWrite(); + if (index > 0 && locals[index - 1] != VerifierTypeWrapper.Invalid && locals[index - 1].IsWidePrimitive) + { + locals[index - 1] = VerifierTypeWrapper.Invalid; + } + locals[index] = type; + } + catch (IndexOutOfRangeException) + { + throw new VerifyError("Illegal local variable number"); + } + } + + private void SetLocal2(int index, TypeWrapper type) + { + try + { + LocalsCopyOnWrite(); + if (index > 0 && locals[index - 1] != VerifierTypeWrapper.Invalid && locals[index - 1].IsWidePrimitive) + { + locals[index - 1] = VerifierTypeWrapper.Invalid; + } + locals[index] = type; + locals[index + 1] = VerifierTypeWrapper.Invalid; + } + catch (IndexOutOfRangeException) + { + throw new VerifyError("Illegal local variable number"); + } + } + + internal void GetLocalInt(int index) + { + if (GetLocalType(index) != PrimitiveTypeWrapper.INT) + { + throw new VerifyError("Invalid local type"); + } + } + + internal void SetLocalInt(int index, int instructionIndex) + { + SetLocal1(index, PrimitiveTypeWrapper.INT); + } + + internal void GetLocalLong(int index) + { + if (GetLocalType(index) != PrimitiveTypeWrapper.LONG) + { + throw new VerifyError("incorrect local type, not long"); + } + } + + internal void SetLocalLong(int index, int instructionIndex) + { + SetLocal2(index, PrimitiveTypeWrapper.LONG); + } + + internal void GetLocalFloat(int index) + { + if (GetLocalType(index) != PrimitiveTypeWrapper.FLOAT) + { + throw new VerifyError("incorrect local type, not float"); + } + } + + internal void SetLocalFloat(int index, int instructionIndex) + { + SetLocal1(index, PrimitiveTypeWrapper.FLOAT); + } + + internal void GetLocalDouble(int index) + { + if (GetLocalType(index) != PrimitiveTypeWrapper.DOUBLE) + { + throw new VerifyError("incorrect local type, not double"); + } + } + + internal void SetLocalDouble(int index, int instructionIndex) + { + SetLocal2(index, PrimitiveTypeWrapper.DOUBLE); + } + + internal TypeWrapper GetLocalType(int index) + { + try + { + return locals[index]; + } + catch (IndexOutOfRangeException) + { + throw new VerifyError("Illegal local variable number"); + } + } + + // this is used by the compiler (indirectly, through MethodAnalyzer.GetLocalTypeWrapper), + // we've already verified the code so we know we won't run outside the array boundary, + // and we don't need to record the fact that we're reading the local. + internal TypeWrapper GetLocalTypeEx(int index) + { + return locals[index]; + } + + internal void SetLocalType(int index, TypeWrapper type, int instructionIndex) + { + if (type.IsWidePrimitive) + { + SetLocal2(index, type); + } + else + { + SetLocal1(index, type); + } + } + + internal void PushType(TypeWrapper type) + { + if (type.IsIntOnStackPrimitive) + { + type = PrimitiveTypeWrapper.INT; + } + PushHelper(type); + } + + internal void PushInt() + { + PushHelper(PrimitiveTypeWrapper.INT); + } + + internal void PushLong() + { + PushHelper(PrimitiveTypeWrapper.LONG); + } + + internal void PushFloat() + { + PushHelper(PrimitiveTypeWrapper.FLOAT); + } + + internal void PushExtendedFloat() + { + PushHelper(VerifierTypeWrapper.ExtendedFloat); + } + + internal void PushDouble() + { + PushHelper(PrimitiveTypeWrapper.DOUBLE); + } + + internal void PushExtendedDouble() + { + PushHelper(VerifierTypeWrapper.ExtendedDouble); + } + + internal void PopInt() + { + PopIntImpl(PopAnyType()); + } + + internal static void PopIntImpl(TypeWrapper type) + { + if (type != PrimitiveTypeWrapper.INT) + { + throw new VerifyError("Int expected on stack"); + } + } + + internal bool PopFloat() + { + TypeWrapper tw = PopAnyType(); + PopFloatImpl(tw); + return tw == VerifierTypeWrapper.ExtendedFloat; + } + + internal static void PopFloatImpl(TypeWrapper tw) + { + if (tw != PrimitiveTypeWrapper.FLOAT && tw != VerifierTypeWrapper.ExtendedFloat) + { + throw new VerifyError("Float expected on stack"); + } + } + + internal bool PopDouble() + { + TypeWrapper tw = PopAnyType(); + PopDoubleImpl(tw); + return tw == VerifierTypeWrapper.ExtendedDouble; + } + + internal static void PopDoubleImpl(TypeWrapper tw) + { + if (tw != PrimitiveTypeWrapper.DOUBLE && tw != VerifierTypeWrapper.ExtendedDouble) + { + throw new VerifyError("Double expected on stack"); + } + } + + internal void PopLong() + { + PopLongImpl(PopAnyType()); + } + + internal static void PopLongImpl(TypeWrapper tw) + { + if (tw != PrimitiveTypeWrapper.LONG) + { + throw new VerifyError("Long expected on stack"); + } + } + + internal TypeWrapper PopArrayType() + { + return PopArrayTypeImpl(PopAnyType()); + } + + internal static TypeWrapper PopArrayTypeImpl(TypeWrapper type) + { + if (!VerifierTypeWrapper.IsNullOrUnloadable(type) && type.ArrayRank == 0) + { + throw new VerifyError("Array reference expected on stack"); + } + return type; + } + + // null or an initialized object reference + internal TypeWrapper PopObjectType() + { + return PopObjectTypeImpl(PopType()); + } + + internal static TypeWrapper PopObjectTypeImpl(TypeWrapper type) + { + if (type.IsPrimitive || VerifierTypeWrapper.IsNew(type) || type == VerifierTypeWrapper.UninitializedThis) + { + throw new VerifyError("Expected object reference on stack"); + } + return type; + } + + // null or an initialized object reference derived from baseType (or baseType) + internal TypeWrapper PopObjectType(TypeWrapper baseType) + { + return PopObjectTypeImpl(baseType, PopObjectType()); + } + + internal static TypeWrapper PopObjectTypeImpl(TypeWrapper baseType, TypeWrapper type) + { + // HACK because of the way interfaces references works, if baseType + // is an interface or array of interfaces, any reference will be accepted + if (!baseType.IsUnloadable && !baseType.IsInterfaceOrInterfaceArray && !(type.IsUnloadable || type.IsAssignableTo(baseType))) + { + throw new VerifyError("Unexpected type " + type.Name + " where " + baseType.Name + " was expected"); + } + return type; + } + + internal TypeWrapper PeekType() + { + if (stackSize == 0) + { + throw new VerifyError("Unable to pop operand off an empty stack"); + } + return stack[stackSize - 1]; + } + + internal void MultiPopAnyType(int count) + { + while (count-- != 0) + { + PopAnyType(); + } + } + + internal TypeWrapper PopFaultBlockException() + { + return stack[--stackSize]; + } + + internal TypeWrapper PopAnyType() + { + if (stackSize == 0) + { + throw new VerifyError("Unable to pop operand off an empty stack"); + } + TypeWrapper type = stack[--stackSize]; + if (type.IsWidePrimitive || type == VerifierTypeWrapper.ExtendedDouble) + { + stackEnd++; + } + if (VerifierTypeWrapper.IsThis(type)) + { + type = ((VerifierTypeWrapper)type).UnderlyingType; + } + if (VerifierTypeWrapper.IsFaultBlockException(type)) + { + VerifierTypeWrapper.ClearFaultBlockException(type); + type = CoreClasses.java.lang.Throwable.Wrapper; + } + return type; + } + + // NOTE this can *not* be used to pop double or long + internal TypeWrapper PopType() + { + return PopTypeImpl(PopAnyType()); + } + + internal static TypeWrapper PopTypeImpl(TypeWrapper type) + { + if (type.IsWidePrimitive || type == VerifierTypeWrapper.ExtendedDouble) + { + throw new VerifyError("Attempt to split long or double on the stack"); + } + return type; + } + + // this will accept null, a primitive type of the specified type or an initialized reference of the + // specified type or derived from it + // NOTE this can also be used to pop double or long + internal TypeWrapper PopType(TypeWrapper baseType) + { + return PopTypeImpl(baseType, PopAnyType()); + } + + internal static TypeWrapper PopTypeImpl(TypeWrapper baseType, TypeWrapper type) + { + if (baseType.IsIntOnStackPrimitive) + { + baseType = PrimitiveTypeWrapper.INT; + } + if (VerifierTypeWrapper.IsNew(type) || type == VerifierTypeWrapper.UninitializedThis) + { + throw new VerifyError("Expecting to find object/array on stack"); + } + if (type == baseType) + { + return type; + } + else if (type == VerifierTypeWrapper.ExtendedDouble && baseType == PrimitiveTypeWrapper.DOUBLE) + { + return type; + } + else if (type == VerifierTypeWrapper.ExtendedFloat && baseType == PrimitiveTypeWrapper.FLOAT) + { + return type; + } + else if (type.IsPrimitive || baseType.IsPrimitive) + { + // throw at the end of the method + } + else if (baseType == CoreClasses.java.lang.Object.Wrapper) + { + return type; + } + else if (type.IsUnloadable || baseType.IsUnloadable) + { + return type; + } + else if (baseType.IsInterfaceOrInterfaceArray) + { + // because of the way interfaces references works, if baseType + // is an interface or array of interfaces, any reference will be accepted + return type; + } + else if (type.IsAssignableTo(baseType)) + { + return type; + } + else if (HasMissingBaseType(type) || HasMissingBaseType(baseType)) + { + return type; + } + throw new VerifyError("Unexpected type " + type.Name + " where " + baseType.Name + " was expected"); + } + + private static bool HasMissingBaseType(TypeWrapper tw) + { +#if IMPORTER + for (TypeWrapper baseTypeWrapper; (baseTypeWrapper = tw.BaseTypeWrapper) != null; tw = baseTypeWrapper) + { + if (baseTypeWrapper.IsUnloadable) + { + StaticCompiler.IssueMissingTypeMessage(tw.TypeAsBaseType.BaseType); + return true; + } + } +#endif + return false; + } + + internal int GetStackHeight() + { + return stackSize; + } + + internal TypeWrapper GetStackSlot(int pos) + { + TypeWrapper tw = stack[stackSize - 1 - pos]; + if (tw == VerifierTypeWrapper.ExtendedDouble) + { + tw = PrimitiveTypeWrapper.DOUBLE; + } + else if (tw == VerifierTypeWrapper.ExtendedFloat) + { + tw = PrimitiveTypeWrapper.FLOAT; + } + return tw; + } + + internal TypeWrapper GetStackSlotEx(int pos) + { + return stack[stackSize - 1 - pos]; + } + + internal TypeWrapper GetStackByIndex(int index) + { + return stack[index]; + } + + private void PushHelper(TypeWrapper type) + { + if (type.IsWidePrimitive || type == VerifierTypeWrapper.ExtendedDouble) + { + stackEnd--; + } + if (stackSize >= stackEnd) + { + throw new VerifyError("Stack overflow"); + } + StackCopyOnWrite(); + stack[stackSize++] = type; + } + + internal void MarkInitialized(TypeWrapper type, TypeWrapper initType, int instructionIndex) + { + System.Diagnostics.Debug.Assert(type != null && initType != null); + + for (int i = 0; i < locals.Length; i++) + { + if (locals[i] == type) + { + LocalsCopyOnWrite(); + locals[i] = initType; + } + } + for (int i = 0; i < stackSize; i++) + { + if (stack[i] == type) + { + StackCopyOnWrite(); + stack[i] = initType; + } + } + } + + private void StackCopyOnWrite() + { + if ((flags & ShareFlags.Stack) != 0) + { + flags &= ~ShareFlags.Stack; + stack = (TypeWrapper[])stack.Clone(); + } + } + + private void LocalsCopyOnWrite() + { + if ((flags & ShareFlags.Locals) != 0) + { + flags &= ~ShareFlags.Locals; + locals = (TypeWrapper[])locals.Clone(); + } + } + + internal void DumpLocals() + { + Console.Write("// "); + string sep = ""; + for (int i = 0; i < locals.Length; i++) + { + Console.Write(sep); + Console.Write(locals[i]); + sep = ", "; + } + Console.WriteLine(); + } + + internal void DumpStack() + { + Console.Write("// "); + string sep = ""; + for (int i = 0; i < stackSize; i++) + { + Console.Write(sep); + Console.Write(stack[i]); + sep = ", "; + } + Console.WriteLine(); + } + + internal void ClearFaultBlockException() + { + if (VerifierTypeWrapper.IsFaultBlockException(stack[0])) + { + StackCopyOnWrite(); + changed = true; + stack[0] = CoreClasses.java.lang.Throwable.Wrapper; + } + } + + } + +} diff --git a/src/IKVM.Runtime/JNI/JNIEnv.cs b/src/IKVM.Runtime/JNI/JNIEnv.cs index 49eeeabe52..57ab6e7c8f 100644 --- a/src/IKVM.Runtime/JNI/JNIEnv.cs +++ b/src/IKVM.Runtime/JNI/JNIEnv.cs @@ -29,7 +29,7 @@ Jeroen Frijters using System.Runtime.InteropServices; using IKVM.ByteCode.Text; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Runtime.JNI { diff --git a/src/IKVM.Runtime/JNI/JNIFrame.cs b/src/IKVM.Runtime/JNI/JNIFrame.cs index efedfb7bc9..da8e8917c6 100644 --- a/src/IKVM.Runtime/JNI/JNIFrame.cs +++ b/src/IKVM.Runtime/JNI/JNIFrame.cs @@ -25,7 +25,7 @@ Jeroen Frijters using System.Diagnostics; using System.Text; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Runtime.JNI { diff --git a/src/IKVM.Runtime/JNI/JNINativeLoader.cs b/src/IKVM.Runtime/JNI/JNINativeLoader.cs index 6fa610bb11..e8c5be14b4 100644 --- a/src/IKVM.Runtime/JNI/JNINativeLoader.cs +++ b/src/IKVM.Runtime/JNI/JNINativeLoader.cs @@ -26,7 +26,7 @@ Jeroen Frijters using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Runtime.JNI { diff --git a/src/IKVM.Runtime/Java/Externs/ikvm/internal/CallerID.cs b/src/IKVM.Runtime/Java/Externs/ikvm/internal/CallerID.cs index 25787ade5d..d35fd31e39 100644 --- a/src/IKVM.Runtime/Java/Externs/ikvm/internal/CallerID.cs +++ b/src/IKVM.Runtime/Java/Externs/ikvm/internal/CallerID.cs @@ -23,7 +23,7 @@ Jeroen Frijters */ using System.Reflection; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Java.Externs.ikvm.@internal { diff --git a/src/IKVM.Runtime/Java/Externs/ikvm/runtime/AppDomainAssemblyClassLoader.cs b/src/IKVM.Runtime/Java/Externs/ikvm/runtime/AppDomainAssemblyClassLoader.cs index f43411b02b..a410f915d7 100644 --- a/src/IKVM.Runtime/Java/Externs/ikvm/runtime/AppDomainAssemblyClassLoader.cs +++ b/src/IKVM.Runtime/Java/Externs/ikvm/runtime/AppDomainAssemblyClassLoader.cs @@ -39,7 +39,7 @@ static class AppDomainAssemblyClassLoader /// static object LoadClassFromAssembly(Assembly assembly, string className) { - return assembly.IsDynamic == false ? (Internal.AssemblyClassLoader.FromAssembly(assembly).DoLoad(className)?.ClassObject) : null; + return assembly.IsDynamic == false ? (IKVM.Runtime.AssemblyClassLoader.FromAssembly(assembly).DoLoad(className)?.ClassObject) : null; } /// @@ -68,14 +68,14 @@ static object LoadClassFromAssembly(Assembly assembly, string className) /// static IEnumerable FindResources(string name) { - var done = new HashSet(); + var done = new HashSet(); foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) { if (asm.IsDynamic) continue; - var acl = Internal.AssemblyClassLoader.FromAssembly(asm); + var acl = IKVM.Runtime.AssemblyClassLoader.FromAssembly(asm); if (done.Add(acl)) foreach (var url in acl.FindResources(name)) yield return url; diff --git a/src/IKVM.Runtime/Java/Externs/ikvm/runtime/AssemblyClassLoader.cs b/src/IKVM.Runtime/Java/Externs/ikvm/runtime/AssemblyClassLoader.cs index 97484049a0..91c588de59 100644 --- a/src/IKVM.Runtime/Java/Externs/ikvm/runtime/AssemblyClassLoader.cs +++ b/src/IKVM.Runtime/Java/Externs/ikvm/runtime/AssemblyClassLoader.cs @@ -24,11 +24,11 @@ Jeroen Frijters using System; using System.Reflection; -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Runtime; using IKVM.Runtime.Accessors.Java.Lang; -using AssemblyClassLoader_ = IKVM.Internal.AssemblyClassLoader; +using AssemblyClassLoader_ = IKVM.Runtime.AssemblyClassLoader; namespace IKVM.Java.Externs.ikvm.runtime { diff --git a/src/IKVM.Runtime/Java/Externs/ikvm/runtime/GenericClassLoader.cs b/src/IKVM.Runtime/Java/Externs/ikvm/runtime/GenericClassLoader.cs index cbc9d2ed5d..63b2688df2 100644 --- a/src/IKVM.Runtime/Java/Externs/ikvm/runtime/GenericClassLoader.cs +++ b/src/IKVM.Runtime/Java/Externs/ikvm/runtime/GenericClassLoader.cs @@ -21,7 +21,7 @@ Jeroen Frijters jeroen@frijters.net */ -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Java.Externs.ikvm.runtime { diff --git a/src/IKVM.Runtime/Java/Externs/ikvm/runtime/Launcher.cs b/src/IKVM.Runtime/Java/Externs/ikvm/runtime/Launcher.cs index 3de245b6f7..0c74746789 100644 --- a/src/IKVM.Runtime/Java/Externs/ikvm/runtime/Launcher.cs +++ b/src/IKVM.Runtime/Java/Externs/ikvm/runtime/Launcher.cs @@ -2,7 +2,7 @@ using System.Collections; using System.Collections.Generic; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Java.Externs.ikvm.runtime { @@ -32,7 +32,7 @@ public static int run(Type main, string[] args, string jvmArgPrefix, global::jav // statically compiled entry points need to be explicitly added to the classpath // this is sort of a hack and should be removed with a better class loader hierarchy if (main != null && main.Assembly.IsDynamic == false) - ClassLoaderWrapper.GetBootstrapClassLoader().AddDelegate(IKVM.Internal.AssemblyClassLoader.FromAssembly(main.Assembly)); + ClassLoaderWrapper.GetBootstrapClassLoader().AddDelegate(IKVM.Runtime.AssemblyClassLoader.FromAssembly(main.Assembly)); // copy properties to a CLR type var p = new Dictionary(); diff --git a/src/IKVM.Runtime/Java/Externs/ikvm/runtime/Startup.cs b/src/IKVM.Runtime/Java/Externs/ikvm/runtime/Startup.cs index 1af2fabbad..7971d0a24c 100644 --- a/src/IKVM.Runtime/Java/Externs/ikvm/runtime/Startup.cs +++ b/src/IKVM.Runtime/Java/Externs/ikvm/runtime/Startup.cs @@ -1,6 +1,6 @@ using System.Reflection; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Java.Externs.ikvm.runtime { @@ -13,7 +13,7 @@ static class Startup public static void addBootClassPathAssembly(Assembly asm) { - ClassLoaderWrapper.GetBootstrapClassLoader().AddDelegate(IKVM.Internal.AssemblyClassLoader.FromAssembly(asm)); + ClassLoaderWrapper.GetBootstrapClassLoader().AddDelegate(IKVM.Runtime.AssemblyClassLoader.FromAssembly(asm)); } } diff --git a/src/IKVM.Runtime/Java/Externs/ikvm/runtime/Util.cs b/src/IKVM.Runtime/Java/Externs/ikvm/runtime/Util.cs index 2484f89224..eb2eae7ba9 100644 --- a/src/IKVM.Runtime/Java/Externs/ikvm/runtime/Util.cs +++ b/src/IKVM.Runtime/Java/Externs/ikvm/runtime/Util.cs @@ -25,7 +25,7 @@ Jeroen Frijters using System.Reflection.Emit; using IKVM.Attributes; -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Runtime; diff --git a/src/IKVM.Runtime/Java/Externs/java/io/FileDescriptor.cs b/src/IKVM.Runtime/Java/Externs/java/io/FileDescriptor.cs index b9492ced03..bf991ab0d1 100644 --- a/src/IKVM.Runtime/Java/Externs/java/io/FileDescriptor.cs +++ b/src/IKVM.Runtime/Java/Externs/java/io/FileDescriptor.cs @@ -2,7 +2,7 @@ using System.IO; using System.Runtime.InteropServices; -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Runtime; using IKVM.Runtime.Accessors.Java.Io; diff --git a/src/IKVM.Runtime/Java/Externs/java/io/ObjectStreamClass.cs b/src/IKVM.Runtime/Java/Externs/java/io/ObjectStreamClass.cs index bbfe169003..8a109a27ee 100644 --- a/src/IKVM.Runtime/Java/Externs/java/io/ObjectStreamClass.cs +++ b/src/IKVM.Runtime/Java/Externs/java/io/ObjectStreamClass.cs @@ -26,7 +26,7 @@ Jeroen Frijters #if !NO_REF_EMIT using System.Reflection.Emit; #endif -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Runtime; namespace IKVM.Java.Externs.java.io diff --git a/src/IKVM.Runtime/Java/Externs/java/lang/Class.cs b/src/IKVM.Runtime/Java/Externs/java/lang/Class.cs index 0ab3acb4c4..2c37d0fca1 100644 --- a/src/IKVM.Runtime/Java/Externs/java/lang/Class.cs +++ b/src/IKVM.Runtime/Java/Externs/java/lang/Class.cs @@ -24,7 +24,7 @@ Jeroen Frijters using System; using System.Collections.Generic; -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Runtime; using IKVM.Runtime.Accessors.Java.Lang; diff --git a/src/IKVM.Runtime/Java/Externs/java/lang/ClassLoader.NativeLibrary.cs b/src/IKVM.Runtime/Java/Externs/java/lang/ClassLoader.NativeLibrary.cs index df31015381..046276891b 100644 --- a/src/IKVM.Runtime/Java/Externs/java/lang/ClassLoader.NativeLibrary.cs +++ b/src/IKVM.Runtime/Java/Externs/java/lang/ClassLoader.NativeLibrary.cs @@ -28,7 +28,7 @@ Jeroen Frijters using System.Security; using System.Threading; -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Runtime.JNI; namespace IKVM.Java.Externs.java.lang diff --git a/src/IKVM.Runtime/Java/Externs/java/lang/ClassLoader.cs b/src/IKVM.Runtime/Java/Externs/java/lang/ClassLoader.cs index 6e015d5948..5fe038934d 100644 --- a/src/IKVM.Runtime/Java/Externs/java/lang/ClassLoader.cs +++ b/src/IKVM.Runtime/Java/Externs/java/lang/ClassLoader.cs @@ -25,7 +25,7 @@ Jeroen Frijters using System.Linq; using IKVM.ByteCode.Reading; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Java.Externs.java.lang { diff --git a/src/IKVM.Runtime/Java/Externs/java/lang/Package.cs b/src/IKVM.Runtime/Java/Externs/java/lang/Package.cs index f6c6927df5..f540ef183d 100644 --- a/src/IKVM.Runtime/Java/Externs/java/lang/Package.cs +++ b/src/IKVM.Runtime/Java/Externs/java/lang/Package.cs @@ -25,7 +25,7 @@ Jeroen Frijters using System.IO; using System.Threading; -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Runtime; using IKVM.Runtime.Vfs; diff --git a/src/IKVM.Runtime/Java/Externs/java/lang/SecurityManager.cs b/src/IKVM.Runtime/Java/Externs/java/lang/SecurityManager.cs index bd1ffa5d6a..6a1e42df13 100644 --- a/src/IKVM.Runtime/Java/Externs/java/lang/SecurityManager.cs +++ b/src/IKVM.Runtime/Java/Externs/java/lang/SecurityManager.cs @@ -27,7 +27,7 @@ Jeroen Frijters using System.Diagnostics; using System.Reflection; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Java.Externs.java.lang { diff --git a/src/IKVM.Runtime/Java/Externs/java/lang/Thread.cs b/src/IKVM.Runtime/Java/Externs/java/lang/Thread.cs index 4915057859..3460cb8a6f 100644 --- a/src/IKVM.Runtime/Java/Externs/java/lang/Thread.cs +++ b/src/IKVM.Runtime/Java/Externs/java/lang/Thread.cs @@ -27,7 +27,7 @@ Jeroen Frijters using System.Diagnostics; using System.Threading; -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Runtime; using IKVM.Runtime.Accessors.Java.Lang; using IKVM.Runtime.Util.Java.Security; diff --git a/src/IKVM.Runtime/Java/Externs/java/lang/invoke/DirectMethodHandle.cs b/src/IKVM.Runtime/Java/Externs/java/lang/invoke/DirectMethodHandle.cs index 887cbcb46c..686952683f 100644 --- a/src/IKVM.Runtime/Java/Externs/java/lang/invoke/DirectMethodHandle.cs +++ b/src/IKVM.Runtime/Java/Externs/java/lang/invoke/DirectMethodHandle.cs @@ -21,7 +21,7 @@ Jeroen Frijters jeroen@frijters.net */ -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Java.Externs.java.lang.invoke { diff --git a/src/IKVM.Runtime/Java/Externs/java/lang/invoke/MethodHandleNatives.cs b/src/IKVM.Runtime/Java/Externs/java/lang/invoke/MethodHandleNatives.cs index ad387a8476..c4e3f4f7ef 100644 --- a/src/IKVM.Runtime/Java/Externs/java/lang/invoke/MethodHandleNatives.cs +++ b/src/IKVM.Runtime/Java/Externs/java/lang/invoke/MethodHandleNatives.cs @@ -25,7 +25,7 @@ Jeroen Frijters using System.Reflection; using System.Threading; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Java.Externs.java.lang.invoke { diff --git a/src/IKVM.Runtime/Java/Externs/java/lang/ref/Reference.cs b/src/IKVM.Runtime/Java/Externs/java/lang/ref/Reference.cs index 1727d62954..c8abd2d2cd 100644 --- a/src/IKVM.Runtime/Java/Externs/java/lang/ref/Reference.cs +++ b/src/IKVM.Runtime/Java/Externs/java/lang/ref/Reference.cs @@ -22,7 +22,7 @@ Jeroen Frijters jeroen@frijters.net */ -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Java.Externs.java.lang.@ref { diff --git a/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Array.cs b/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Array.cs index 615de07b7b..1184c4bcc1 100644 --- a/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Array.cs +++ b/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Array.cs @@ -23,7 +23,7 @@ Jeroen Frijters */ using System; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Java.Externs.java.lang.reflect { diff --git a/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Executable.cs b/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Executable.cs index bf45b93b4d..fe4ffd720f 100644 --- a/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Executable.cs +++ b/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Executable.cs @@ -23,7 +23,7 @@ Jeroen Frijters */ using System.Collections.Generic; -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Runtime; namespace IKVM.Java.Externs.java.lang.reflect diff --git a/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Field.cs b/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Field.cs index f142fd9236..04685ebff4 100644 --- a/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Field.cs +++ b/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Field.cs @@ -21,7 +21,7 @@ Jeroen Frijters jeroen@frijters.net */ -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Java.Externs.java.lang.reflect { diff --git a/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Method.cs b/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Method.cs index 40c49a19df..78cd4152b9 100644 --- a/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Method.cs +++ b/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Method.cs @@ -21,7 +21,7 @@ Jeroen Frijters jeroen@frijters.net */ -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Java.Externs.java.lang.reflect { diff --git a/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Proxy.cs b/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Proxy.cs index 2f3f9038fa..587c44e168 100644 --- a/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Proxy.cs +++ b/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Proxy.cs @@ -23,7 +23,7 @@ Jeroen Frijters */ using System; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Java.Externs.java.lang.reflect { diff --git a/src/IKVM.Runtime/Java/Externs/java/net/PlainDatagramSocketImpl.cs b/src/IKVM.Runtime/Java/Externs/java/net/PlainDatagramSocketImpl.cs index a040a044d5..5e852b5d9c 100644 --- a/src/IKVM.Runtime/Java/Externs/java/net/PlainDatagramSocketImpl.cs +++ b/src/IKVM.Runtime/Java/Externs/java/net/PlainDatagramSocketImpl.cs @@ -8,7 +8,7 @@ using System.Reflection; using System.Runtime.InteropServices; -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Runtime; using IKVM.Runtime.Accessors.Java.Io; using IKVM.Runtime.Util.Java.Net; diff --git a/src/IKVM.Runtime/Java/Externs/java/net/PlainSocketImpl.cs b/src/IKVM.Runtime/Java/Externs/java/net/PlainSocketImpl.cs index 400fe4f31e..bcf5154541 100644 --- a/src/IKVM.Runtime/Java/Externs/java/net/PlainSocketImpl.cs +++ b/src/IKVM.Runtime/Java/Externs/java/net/PlainSocketImpl.cs @@ -7,7 +7,7 @@ using System.Reflection; using System.Runtime.InteropServices; -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Runtime; using IKVM.Runtime.Accessors.Java.Io; using IKVM.Runtime.Util.Java.Net; diff --git a/src/IKVM.Runtime/Java/Externs/java/security/AccessController.cs b/src/IKVM.Runtime/Java/Externs/java/security/AccessController.cs index 6607cd01a0..5860b942c1 100644 --- a/src/IKVM.Runtime/Java/Externs/java/security/AccessController.cs +++ b/src/IKVM.Runtime/Java/Externs/java/security/AccessController.cs @@ -25,7 +25,7 @@ Jeroen Frijters using System.Collections.Generic; using System.Diagnostics; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Java.Externs.java.security { diff --git a/src/IKVM.Runtime/Java/Externs/sun/invoke/util/VerifyAccess.cs b/src/IKVM.Runtime/Java/Externs/sun/invoke/util/VerifyAccess.cs index 8808763f83..0a024e109a 100644 --- a/src/IKVM.Runtime/Java/Externs/sun/invoke/util/VerifyAccess.cs +++ b/src/IKVM.Runtime/Java/Externs/sun/invoke/util/VerifyAccess.cs @@ -22,7 +22,7 @@ Jeroen Frijters jeroen@frijters.net */ -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Java.Externs.sun.invoke.util { diff --git a/src/IKVM.Runtime/Java/Externs/sun/misc/MiscHelper.cs b/src/IKVM.Runtime/Java/Externs/sun/misc/MiscHelper.cs index 52fd97a0c9..f4e76e8e2c 100644 --- a/src/IKVM.Runtime/Java/Externs/sun/misc/MiscHelper.cs +++ b/src/IKVM.Runtime/Java/Externs/sun/misc/MiscHelper.cs @@ -24,7 +24,7 @@ Jeroen Frijters */ using System.Reflection; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Java.Externs.sun.misc { diff --git a/src/IKVM.Runtime/Java/Externs/sun/misc/Unsafe.cs b/src/IKVM.Runtime/Java/Externs/sun/misc/Unsafe.cs index 665c7795f0..5d0ce6d5a5 100644 --- a/src/IKVM.Runtime/Java/Externs/sun/misc/Unsafe.cs +++ b/src/IKVM.Runtime/Java/Externs/sun/misc/Unsafe.cs @@ -9,7 +9,7 @@ using System.Threading; using IKVM.ByteCode.Reading; -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Runtime; namespace IKVM.Java.Externs.sun.misc diff --git a/src/IKVM.Runtime/Java/Externs/sun/misc/VM.cs b/src/IKVM.Runtime/Java/Externs/sun/misc/VM.cs index 2d0473d327..cd70ad3984 100644 --- a/src/IKVM.Runtime/Java/Externs/sun/misc/VM.cs +++ b/src/IKVM.Runtime/Java/Externs/sun/misc/VM.cs @@ -25,7 +25,7 @@ Jeroen Frijters using System; using System.Diagnostics; -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Runtime; namespace IKVM.Java.Externs.sun.misc diff --git a/src/IKVM.Runtime/Java/Externs/sun/net/www/protocol/ikvmres/Handler.cs b/src/IKVM.Runtime/Java/Externs/sun/net/www/protocol/ikvmres/Handler.cs index 7f32edadad..a91005362c 100644 --- a/src/IKVM.Runtime/Java/Externs/sun/net/www/protocol/ikvmres/Handler.cs +++ b/src/IKVM.Runtime/Java/Externs/sun/net/www/protocol/ikvmres/Handler.cs @@ -24,7 +24,7 @@ Jeroen Frijters using System.IO; using System.Reflection; -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Runtime; #if NETCOREAPP diff --git a/src/IKVM.Runtime/Java/Externs/sun/nio/ch/Net.cs b/src/IKVM.Runtime/Java/Externs/sun/nio/ch/Net.cs index 11f2832e4a..24a7ae3615 100644 --- a/src/IKVM.Runtime/Java/Externs/sun/nio/ch/Net.cs +++ b/src/IKVM.Runtime/Java/Externs/sun/nio/ch/Net.cs @@ -6,7 +6,7 @@ using System.Runtime.InteropServices; using System.Threading.Tasks; -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Runtime; using IKVM.Runtime.Accessors.Java.Io; using IKVM.Runtime.Util.Java.Net; diff --git a/src/IKVM.Runtime/Java/Externs/sun/reflect/IReflectionException.cs b/src/IKVM.Runtime/Java/Externs/sun/reflect/IReflectionException.cs index 67510beb59..7c874fd747 100644 --- a/src/IKVM.Runtime/Java/Externs/sun/reflect/IReflectionException.cs +++ b/src/IKVM.Runtime/Java/Externs/sun/reflect/IReflectionException.cs @@ -21,7 +21,7 @@ Jeroen Frijters jeroen@frijters.net */ -namespace IKVM.Internal +namespace IKVM.Runtime { #if !FIRST_PASS diff --git a/src/IKVM.Runtime/Java/Externs/sun/reflect/Reflection.cs b/src/IKVM.Runtime/Java/Externs/sun/reflect/Reflection.cs index a91f57a5f0..c5e3b63389 100644 --- a/src/IKVM.Runtime/Java/Externs/sun/reflect/Reflection.cs +++ b/src/IKVM.Runtime/Java/Externs/sun/reflect/Reflection.cs @@ -28,7 +28,7 @@ Jeroen Frijters using System.Runtime.CompilerServices; using IKVM.Attributes; -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Runtime; namespace IKVM.Java.Externs.sun.reflect diff --git a/src/IKVM.Runtime/Java/Externs/sun/reflect/ReflectionFactory.cs b/src/IKVM.Runtime/Java/Externs/sun/reflect/ReflectionFactory.cs index ce8aaf7aab..857d822bd7 100644 --- a/src/IKVM.Runtime/Java/Externs/sun/reflect/ReflectionFactory.cs +++ b/src/IKVM.Runtime/Java/Externs/sun/reflect/ReflectionFactory.cs @@ -31,7 +31,7 @@ Jeroen Frijters using System.Runtime.Serialization; using System.Security; -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Runtime; using IKVM.Runtime.Accessors.Java.Io; using IKVM.Runtime.Accessors.Java.Lang; diff --git a/src/IKVM.Runtime/Java/Externs/sun/util/locale/provider/JRELocaleProviderAdapter.cs b/src/IKVM.Runtime/Java/Externs/sun/util/locale/provider/JRELocaleProviderAdapter.cs index 61336cbcf0..f378403ac8 100644 --- a/src/IKVM.Runtime/Java/Externs/sun/util/locale/provider/JRELocaleProviderAdapter.cs +++ b/src/IKVM.Runtime/Java/Externs/sun/util/locale/provider/JRELocaleProviderAdapter.cs @@ -28,7 +28,7 @@ static class JRELocaleProviderAdapter // the Java implementation is redirected via map.xml internal static bool isNonENLangSupported() { - return IKVM.Internal.ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedNameFast("sun.text.resources.nl.FormatData_nl") != null; + return IKVM.Runtime.ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedNameFast("sun.text.resources.nl.FormatData_nl") != null; } } diff --git a/src/IKVM.Runtime/JsrInliner.cs b/src/IKVM.Runtime/JsrInliner.cs index cea7484ae2..314f1fdbbd 100644 --- a/src/IKVM.Runtime/JsrInliner.cs +++ b/src/IKVM.Runtime/JsrInliner.cs @@ -23,13 +23,15 @@ Jeroen Frijters */ using System; using System.Collections.Generic; -using System.Diagnostics; -using InstructionFlags = IKVM.Internal.ClassFile.Method.InstructionFlags; -namespace IKVM.Internal +using InstructionFlags = IKVM.Runtime.ClassFile.Method.InstructionFlags; + +namespace IKVM.Runtime { - sealed class JsrInliner + + sealed class JsrInliner { + private ClassFile.Method.Instruction[] codeCopy; private int codeLength; private InstructionFlags[] flags; diff --git a/src/IKVM.Runtime/LambdaMetafactory.cs b/src/IKVM.Runtime/LambdaMetafactory.cs index 8f3dc0b674..e942e23cdb 100644 --- a/src/IKVM.Runtime/LambdaMetafactory.cs +++ b/src/IKVM.Runtime/LambdaMetafactory.cs @@ -25,9 +25,7 @@ Jeroen Frijters using System.Collections.Generic; using System.Diagnostics; -using IKVM.Attributes; using IKVM.ByteCode; -using IKVM.Runtime; #if IMPORTER using IKVM.Reflection; @@ -41,7 +39,7 @@ Jeroen Frijters #endif -namespace IKVM.Internal +namespace IKVM.Runtime { sealed class LambdaMetafactory @@ -1075,4 +1073,5 @@ private static bool HasUnloadable(TypeWrapper[] wrappers) return false; } } + } diff --git a/src/IKVM.Runtime/Launcher.cs b/src/IKVM.Runtime/Launcher.cs index 6f5836624e..01d0058a01 100644 --- a/src/IKVM.Runtime/Launcher.cs +++ b/src/IKVM.Runtime/Launcher.cs @@ -13,7 +13,7 @@ using System.Threading; using IKVM.Attributes; -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Runtime.Accessors.Ikvm.Internal; using IKVM.Runtime.Accessors.Java.Lang; using IKVM.Runtime.Accessors.Java.Lang.Reflect; diff --git a/src/IKVM.Runtime/LoadMode.cs b/src/IKVM.Runtime/LoadMode.cs index a9efa34006..582b3b1f35 100644 --- a/src/IKVM.Runtime/LoadMode.cs +++ b/src/IKVM.Runtime/LoadMode.cs @@ -23,16 +23,7 @@ Jeroen Frijters */ using System; -#if IMPORTER || EXPORTER -using IKVM.Reflection; -using IKVM.Reflection.Emit; -using Type = IKVM.Reflection.Type; -using ProtectionDomain = System.Object; -#else -#endif - - -namespace IKVM.Internal +namespace IKVM.Runtime { [Flags] diff --git a/src/IKVM.Runtime/LocalVar.cs b/src/IKVM.Runtime/LocalVar.cs new file mode 100644 index 0000000000..c68834affe --- /dev/null +++ b/src/IKVM.Runtime/LocalVar.cs @@ -0,0 +1,42 @@ +/* + Copyright (C) 2002-2010 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +namespace IKVM.Runtime +{ + + sealed class LocalVar + { + + internal bool isArg; + internal int local; + internal TypeWrapper type; + internal CodeEmitterLocal builder; + // used to emit debugging info, only available if ClassLoaderWrapper.EmitDebugInfo is true + internal string name; + internal int start_pc; + internal int end_pc; + + } + +} diff --git a/src/IKVM.Runtime/LocalVarInfo.cs b/src/IKVM.Runtime/LocalVarInfo.cs new file mode 100644 index 0000000000..308183e257 --- /dev/null +++ b/src/IKVM.Runtime/LocalVarInfo.cs @@ -0,0 +1,627 @@ +/* + Copyright (C) 2002-2010 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Diagnostics; + +using InstructionFlags = IKVM.Runtime.ClassFile.Method.InstructionFlags; +using ExceptionTableEntry = IKVM.Runtime.ClassFile.Method.ExceptionTableEntry; + +namespace IKVM.Runtime +{ + + struct LocalVarInfo + { + + private readonly LocalVar[/*instructionIndex*/] localVars; + private readonly LocalVar[/*instructionIndex*/][/*localIndex*/] invokespecialLocalVars; + private readonly LocalVar[/*index*/] allLocalVars; + + internal LocalVarInfo(CodeInfo ma, ClassFile classFile, ClassFile.Method method, UntangledExceptionTable exceptions, MethodWrapper mw, ClassLoaderWrapper classLoader) + { + Dictionary[] localStoreReaders = FindLocalVariables(ma, mw, classFile, method); + + // now that we've done the code flow analysis, we can do a liveness analysis on the local variables + ClassFile.Method.Instruction[] instructions = method.Instructions; + Dictionary localByStoreSite = new Dictionary(); + List locals = new List(); + for (int i = 0; i < localStoreReaders.Length; i++) + { + if (localStoreReaders[i] != null) + { + VisitLocalLoads(ma, method, locals, localByStoreSite, localStoreReaders[i], i, classLoader.EmitDebugInfo); + } + } + Dictionary forwarders = new Dictionary(); + if (classLoader.EmitDebugInfo) + { + InstructionFlags[] flags = MethodAnalyzer.ComputePartialReachability(ma, method.Instructions, exceptions, 0, false); + // if we're emitting debug info, we need to keep dead stores as well... + for (int i = 0; i < instructions.Length; i++) + { + if ((flags[i] & InstructionFlags.Reachable) != 0 + && IsStoreLocal(instructions[i].NormalizedOpCode)) + { + if (!localByStoreSite.ContainsKey(MakeKey(i, instructions[i].NormalizedArg1))) + { + LocalVar v = new LocalVar(); + v.local = instructions[i].NormalizedArg1; + v.type = ma.GetStackTypeWrapper(i, 0); + FindLvtEntry(v, method, i); + locals.Add(v); + localByStoreSite.Add(MakeKey(i, v.local), v); + } + } + } + // to make the debugging experience better, we have to trust the + // LocalVariableTable (unless it's clearly bogus) and merge locals + // together that are the same according to the LVT + for (int i = 0; i < locals.Count - 1; i++) + { + for (int j = i + 1; j < locals.Count; j++) + { + LocalVar v1 = (LocalVar)locals[i]; + LocalVar v2 = (LocalVar)locals[j]; + if (v1.name != null && v1.name == v2.name && v1.start_pc == v2.start_pc && v1.end_pc == v2.end_pc) + { + // we can only merge if the resulting type is valid (this protects against incorrect + // LVT data, but is also needed for constructors, where the uninitialized this is a different + // type from the initialized this) + TypeWrapper tw = InstructionState.FindCommonBaseType(v1.type, v2.type); + if (tw != VerifierTypeWrapper.Invalid) + { + v1.isArg |= v2.isArg; + v1.type = tw; + forwarders.Add(v2, v1); + locals.RemoveAt(j); + j--; + } + } + } + } + } + else + { + for (int i = 0; i < locals.Count - 1; i++) + { + for (int j = i + 1; j < locals.Count; j++) + { + LocalVar v1 = (LocalVar)locals[i]; + LocalVar v2 = (LocalVar)locals[j]; + // if the two locals are the same, we merge them, this is a small + // optimization, it should *not* be required for correctness. + if (v1.local == v2.local && v1.type == v2.type) + { + v1.isArg |= v2.isArg; + forwarders.Add(v2, v1); + locals.RemoveAt(j); + j--; + } + } + } + } + invokespecialLocalVars = new LocalVar[instructions.Length][]; + localVars = new LocalVar[instructions.Length]; + for (int i = 0; i < localVars.Length; i++) + { + LocalVar v = null; + if (localStoreReaders[i] != null) + { + Debug.Assert(IsLoadLocal(instructions[i].NormalizedOpCode)); + // lame way to look up the local variable for a load + // (by indirecting through a corresponding store) + foreach (int store in localStoreReaders[i].Keys) + { + v = localByStoreSite[MakeKey(store, instructions[i].NormalizedArg1)]; + break; + } + } + else + { + if (instructions[i].NormalizedOpCode == NormalizedByteCode.__invokespecial || instructions[i].NormalizedOpCode == NormalizedByteCode.__dynamic_invokespecial) + { + invokespecialLocalVars[i] = new LocalVar[method.MaxLocals]; + for (int j = 0; j < invokespecialLocalVars[i].Length; j++) + { + localByStoreSite.TryGetValue(MakeKey(i, j), out invokespecialLocalVars[i][j]); + } + } + else + { + localByStoreSite.TryGetValue(MakeKey(i, instructions[i].NormalizedArg1), out v); + } + } + if (v != null) + { + LocalVar fwd; + if (forwarders.TryGetValue(v, out fwd)) + { + v = fwd; + } + localVars[i] = v; + } + } + this.allLocalVars = locals.ToArray(); + } + + private static void FindLvtEntry(LocalVar lv, ClassFile.Method method, int instructionIndex) + { + ClassFile.Method.LocalVariableTableEntry[] lvt = method.LocalVariableTableAttribute; + if (lvt != null) + { + int pc = method.Instructions[instructionIndex].PC; + int nextPC = method.Instructions[instructionIndex + 1].PC; + bool isStore = IsStoreLocal(method.Instructions[instructionIndex].NormalizedOpCode); + foreach (ClassFile.Method.LocalVariableTableEntry e in lvt) + { + // TODO validate the contents of the LVT entry + if (e.index == lv.local && + (e.start_pc <= pc || (e.start_pc == nextPC && isStore)) && + e.start_pc + e.length > pc) + { + lv.name = e.name; + lv.start_pc = e.start_pc; + lv.end_pc = e.start_pc + e.length; + break; + } + } + } + } + + // NOTE for dead stores, this returns null + internal LocalVar GetLocalVar(int instructionIndex) + { + return localVars[instructionIndex]; + } + + internal LocalVar[] GetLocalVarsForInvokeSpecial(int instructionIndex) + { + return invokespecialLocalVars[instructionIndex]; + } + + internal LocalVar[] GetAllLocalVars() + { + return allLocalVars; + } + + private static bool IsLoadLocal(NormalizedByteCode bc) + { + return bc == NormalizedByteCode.__aload || + bc == NormalizedByteCode.__iload || + bc == NormalizedByteCode.__lload || + bc == NormalizedByteCode.__fload || + bc == NormalizedByteCode.__dload || + bc == NormalizedByteCode.__iinc || + bc == NormalizedByteCode.__ret; + } + + private static bool IsStoreLocal(NormalizedByteCode bc) + { + return bc == NormalizedByteCode.__astore || + bc == NormalizedByteCode.__istore || + bc == NormalizedByteCode.__lstore || + bc == NormalizedByteCode.__fstore || + bc == NormalizedByteCode.__dstore; + } + + struct FindLocalVarState + { + internal bool changed; + internal FindLocalVarStoreSite[] sites; + + internal void Store(int instructionIndex, int localIndex) + { + if (sites[localIndex].Count == 1 && sites[localIndex][0] == instructionIndex) + { + return; + } + sites = (FindLocalVarStoreSite[])sites.Clone(); + sites[localIndex] = new FindLocalVarStoreSite(); + sites[localIndex].Add(instructionIndex); + } + + internal void Merge(FindLocalVarState state) + { + if (sites == null) + { + sites = state.sites; + changed = true; + } + else + { + bool dirty = true; + for (int i = 0; i < sites.Length; i++) + { + for (int j = 0; j < state.sites[i].Count; j++) + { + if (!sites[i].Contains(state.sites[i][j])) + { + if (dirty) + { + dirty = false; + sites = (FindLocalVarStoreSite[])sites.Clone(); + } + sites[i].Add(state.sites[i][j]); + changed = true; + } + } + } + } + } + + internal FindLocalVarState Copy() + { + FindLocalVarState copy = new FindLocalVarState(); + copy.sites = sites; + return copy; + } + + public override string ToString() + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + if (sites != null) + { + foreach (FindLocalVarStoreSite site in sites) + { + sb.Append('['); + for (int i = 0; i < site.Count; i++) + { + sb.AppendFormat("{0}, ", site[i]); + } + sb.Append(']'); + } + } + return sb.ToString(); + } + } + + struct FindLocalVarStoreSite + { + private int[] data; + + internal bool Contains(int instructionIndex) + { + if (data != null) + { + for (int i = 0; i < data.Length; i++) + { + if (data[i] == instructionIndex) + { + return true; + } + } + } + return false; + } + + internal void Add(int instructionIndex) + { + if (data == null) + { + data = new int[] { instructionIndex }; + } + else + { + data = ArrayUtil.Concat(data, instructionIndex); + } + } + + internal int this[int index] + { + get { return data[index]; } + } + + internal int Count + { + get { return data == null ? 0 : data.Length; } + } + } + + private static Dictionary[] FindLocalVariables(CodeInfo codeInfo, MethodWrapper mw, ClassFile classFile, ClassFile.Method method) + { + FindLocalVarState[] state = new FindLocalVarState[method.Instructions.Length]; + state[0].changed = true; + state[0].sites = new FindLocalVarStoreSite[method.MaxLocals]; + TypeWrapper[] parameters = mw.GetParameters(); + int argpos = 0; + if (!mw.IsStatic) + { + state[0].sites[argpos++].Add(-1); + } + for (int i = 0; i < parameters.Length; i++) + { + state[0].sites[argpos++].Add(-1); + if (parameters[i].IsWidePrimitive) + { + argpos++; + } + } + return FindLocalVariablesImpl(codeInfo, classFile, method, state); + } + + private static Dictionary[] FindLocalVariablesImpl(CodeInfo codeInfo, ClassFile classFile, ClassFile.Method method, FindLocalVarState[] state) + { + ClassFile.Method.Instruction[] instructions = method.Instructions; + ExceptionTableEntry[] exceptions = method.ExceptionTable; + int maxLocals = method.MaxLocals; + Dictionary[] localStoreReaders = new Dictionary[instructions.Length]; + bool done = false; + + while (!done) + { + done = true; + for (int i = 0; i < instructions.Length; i++) + { + if (state[i].changed) + { + done = false; + state[i].changed = false; + + FindLocalVarState curr = state[i].Copy(); + + for (int j = 0; j < exceptions.Length; j++) + { + if (exceptions[j].startIndex <= i && i < exceptions[j].endIndex) + { + state[exceptions[j].handlerIndex].Merge(curr); + } + } + + if (IsLoadLocal(instructions[i].NormalizedOpCode) + && (instructions[i].NormalizedOpCode != NormalizedByteCode.__aload || !VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(i + 1, 0)))) + { + if (localStoreReaders[i] == null) + { + localStoreReaders[i] = new Dictionary(); + } + for (int j = 0; j < curr.sites[instructions[i].NormalizedArg1].Count; j++) + { + localStoreReaders[i][curr.sites[instructions[i].NormalizedArg1][j]] = ""; + } + } + + if (IsStoreLocal(instructions[i].NormalizedOpCode) + && (instructions[i].NormalizedOpCode != NormalizedByteCode.__astore || !VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(i, 0)))) + { + curr.Store(i, instructions[i].NormalizedArg1); + // if this is a store at the end of an exception block, + // we need to propagate the new state to the exception handler + for (int j = 0; j < exceptions.Length; j++) + { + if (exceptions[j].endIndex == i + 1) + { + state[exceptions[j].handlerIndex].Merge(curr); + } + } + } + + if (instructions[i].NormalizedOpCode == NormalizedByteCode.__invokespecial) + { + ClassFile.ConstantPoolItemMI cpi = classFile.GetMethodref(instructions[i].Arg1); + if (ReferenceEquals(cpi.Name, StringConstants.INIT)) + { + TypeWrapper type = codeInfo.GetRawStackTypeWrapper(i, cpi.GetArgTypes().Length); + // after we've invoked the constructor, the uninitialized references + // are now initialized + if (type == VerifierTypeWrapper.UninitializedThis + || VerifierTypeWrapper.IsNew(type)) + { + for (int j = 0; j < maxLocals; j++) + { + if (codeInfo.GetLocalTypeWrapper(i, j) == type) + { + curr.Store(i, j); + } + } + } + } + } + else if (instructions[i].NormalizedOpCode == NormalizedByteCode.__goto_finally) + { + int handler = instructions[i].HandlerIndex; + + // Normally a store at the end of a try block doesn't affect the handler block, + // but in the case of a finally handler it does, so we need to make sure that + // we merge here in case the try block ended with a store. + state[handler].Merge(curr); + + // Now we recursively analyse the handler and afterwards merge the endfault locations back to us + FindLocalVarState[] handlerState = new FindLocalVarState[instructions.Length]; + handlerState[handler].Merge(curr); + curr = new FindLocalVarState(); + FindLocalVariablesImpl(codeInfo, classFile, method, handlerState); + + // Merge back to the target of our __goto_finally + for (int j = 0; j < handlerState.Length; j++) + { + if (instructions[j].NormalizedOpCode == NormalizedByteCode.__athrow + && codeInfo.HasState(j) + && VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(j, 0)) + && ((VerifierTypeWrapper)codeInfo.GetRawStackTypeWrapper(j, 0)).Index == handler) + { + curr.Merge(handlerState[j]); + } + } + } + + switch (ByteCodeMetaData.GetFlowControl(instructions[i].NormalizedOpCode)) + { + case ByteCodeFlowControl.Switch: + { + for (int j = 0; j < instructions[i].SwitchEntryCount; j++) + { + state[instructions[i].GetSwitchTargetIndex(j)].Merge(curr); + } + state[instructions[i].DefaultTarget].Merge(curr); + break; + } + case ByteCodeFlowControl.Branch: + state[instructions[i].TargetIndex].Merge(curr); + break; + case ByteCodeFlowControl.CondBranch: + state[instructions[i].TargetIndex].Merge(curr); + state[i + 1].Merge(curr); + break; + case ByteCodeFlowControl.Return: + case ByteCodeFlowControl.Throw: + break; + case ByteCodeFlowControl.Next: + state[i + 1].Merge(curr); + break; + default: + throw new InvalidOperationException(); + } + } + } + } + return localStoreReaders; + } + + private static void VisitLocalLoads(CodeInfo codeInfo, ClassFile.Method method, List locals, Dictionary localByStoreSite, Dictionary storeSites, int instructionIndex, bool debug) + { + Debug.Assert(IsLoadLocal(method.Instructions[instructionIndex].NormalizedOpCode)); + LocalVar local = null; + TypeWrapper type = VerifierTypeWrapper.Null; + int localIndex = method.Instructions[instructionIndex].NormalizedArg1; + bool isArg = false; + foreach (int store in storeSites.Keys) + { + if (store == -1) + { + // it's a method argument, it has no initial store, but the type is simply the parameter type + type = InstructionState.FindCommonBaseType(type, codeInfo.GetLocalTypeWrapper(0, localIndex)); + isArg = true; + } + else + { + if (method.Instructions[store].NormalizedOpCode == NormalizedByteCode.__invokespecial) + { + type = InstructionState.FindCommonBaseType(type, codeInfo.GetLocalTypeWrapper(store + 1, localIndex)); + } + else if (method.Instructions[store].NormalizedOpCode == NormalizedByteCode.__static_error) + { + // it's an __invokespecial that turned into a __static_error + // (since a __static_error doesn't continue, we don't need to set type) + } + else + { + Debug.Assert(IsStoreLocal(method.Instructions[store].NormalizedOpCode)); + type = InstructionState.FindCommonBaseType(type, codeInfo.GetStackTypeWrapper(store, 0)); + } + } + // we can't have an invalid type, because that would have failed verification earlier + Debug.Assert(type != VerifierTypeWrapper.Invalid); + + LocalVar l; + if (localByStoreSite.TryGetValue(MakeKey(store, localIndex), out l)) + { + if (local == null) + { + local = l; + } + else if (local != l) + { + // If we've already defined a LocalVar and we find another one, then we merge them + // together. + // This happens for the following code fragment: + // + // int i = -1; + // try { i = 0; for(; ; ) System.out.println(i); } catch(Exception x) {} + // try { i = 0; for(; ; ) System.out.println(i); } catch(Exception x) {} + // System.out.println(i); + // + local = MergeLocals(locals, localByStoreSite, local, l); + } + } + } + if (local == null) + { + local = new LocalVar(); + local.local = localIndex; + if (VerifierTypeWrapper.IsThis(type)) + { + local.type = ((VerifierTypeWrapper)type).UnderlyingType; + } + else + { + local.type = type; + } + local.isArg = isArg; + if (debug) + { + FindLvtEntry(local, method, instructionIndex); + } + locals.Add(local); + } + else + { + local.isArg |= isArg; + local.type = InstructionState.FindCommonBaseType(local.type, type); + Debug.Assert(local.type != VerifierTypeWrapper.Invalid); + } + foreach (int store in storeSites.Keys) + { + LocalVar v; + if (!localByStoreSite.TryGetValue(MakeKey(store, localIndex), out v)) + { + localByStoreSite[MakeKey(store, localIndex)] = local; + } + else if (v != local) + { + local = MergeLocals(locals, localByStoreSite, local, v); + } + } + } + + private static long MakeKey(int i, int j) + { + return (((long)(uint)i) << 32) + (uint)j; + } + + private static LocalVar MergeLocals(List locals, Dictionary localByStoreSite, LocalVar l1, LocalVar l2) + { + Debug.Assert(l1 != l2); + Debug.Assert(l1.local == l2.local); + for (int i = 0; i < locals.Count; i++) + { + if (locals[i] == l2) + { + locals.RemoveAt(i); + i--; + } + } + Dictionary temp = new Dictionary(localByStoreSite); + localByStoreSite.Clear(); + foreach (KeyValuePair kv in temp) + { + localByStoreSite[kv.Key] = kv.Value == l2 ? l1 : kv.Value; + } + l1.isArg |= l2.isArg; + l1.type = InstructionState.FindCommonBaseType(l1.type, l2.type); + Debug.Assert(l1.type != VerifierTypeWrapper.Invalid); + return l1; + } + } + +} diff --git a/src/IKVM.Runtime/LocalVars.cs b/src/IKVM.Runtime/LocalVars.cs deleted file mode 100644 index 8294d5b04c..0000000000 --- a/src/IKVM.Runtime/LocalVars.cs +++ /dev/null @@ -1,642 +0,0 @@ -/* - Copyright (C) 2002-2010 Jeroen Frijters - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jeroen Frijters - jeroen@frijters.net - -*/ -using System; -using System.Collections.Generic; -using System.Diagnostics; - -using IKVM.Internal; - -#if IMPORTER -using IKVM.Reflection.Emit; -using Type = IKVM.Reflection.Type; -#else -using System.Reflection.Emit; -#endif - -using InstructionFlags = IKVM.Internal.ClassFile.Method.InstructionFlags; -using ExceptionTableEntry = IKVM.Internal.ClassFile.Method.ExceptionTableEntry; - -sealed class LocalVar -{ - internal bool isArg; - internal int local; - internal TypeWrapper type; - internal CodeEmitterLocal builder; - // used to emit debugging info, only available if ClassLoaderWrapper.EmitDebugInfo is true - internal string name; - internal int start_pc; - internal int end_pc; -} - -struct LocalVarInfo -{ - private readonly LocalVar[/*instructionIndex*/] localVars; - private readonly LocalVar[/*instructionIndex*/][/*localIndex*/] invokespecialLocalVars; - private readonly LocalVar[/*index*/] allLocalVars; - - internal LocalVarInfo(CodeInfo ma, ClassFile classFile, ClassFile.Method method, UntangledExceptionTable exceptions, MethodWrapper mw, ClassLoaderWrapper classLoader) - { - Dictionary[] localStoreReaders = FindLocalVariables(ma, mw, classFile, method); - - // now that we've done the code flow analysis, we can do a liveness analysis on the local variables - ClassFile.Method.Instruction[] instructions = method.Instructions; - Dictionary localByStoreSite = new Dictionary(); - List locals = new List(); - for (int i = 0; i < localStoreReaders.Length; i++) - { - if (localStoreReaders[i] != null) - { - VisitLocalLoads(ma, method, locals, localByStoreSite, localStoreReaders[i], i, classLoader.EmitDebugInfo); - } - } - Dictionary forwarders = new Dictionary(); - if (classLoader.EmitDebugInfo) - { - InstructionFlags[] flags = MethodAnalyzer.ComputePartialReachability(ma, method.Instructions, exceptions, 0, false); - // if we're emitting debug info, we need to keep dead stores as well... - for (int i = 0; i < instructions.Length; i++) - { - if ((flags[i] & InstructionFlags.Reachable) != 0 - && IsStoreLocal(instructions[i].NormalizedOpCode)) - { - if (!localByStoreSite.ContainsKey(MakeKey(i, instructions[i].NormalizedArg1))) - { - LocalVar v = new LocalVar(); - v.local = instructions[i].NormalizedArg1; - v.type = ma.GetStackTypeWrapper(i, 0); - FindLvtEntry(v, method, i); - locals.Add(v); - localByStoreSite.Add(MakeKey(i, v.local), v); - } - } - } - // to make the debugging experience better, we have to trust the - // LocalVariableTable (unless it's clearly bogus) and merge locals - // together that are the same according to the LVT - for (int i = 0; i < locals.Count - 1; i++) - { - for (int j = i + 1; j < locals.Count; j++) - { - LocalVar v1 = (LocalVar)locals[i]; - LocalVar v2 = (LocalVar)locals[j]; - if (v1.name != null && v1.name == v2.name && v1.start_pc == v2.start_pc && v1.end_pc == v2.end_pc) - { - // we can only merge if the resulting type is valid (this protects against incorrect - // LVT data, but is also needed for constructors, where the uninitialized this is a different - // type from the initialized this) - TypeWrapper tw = InstructionState.FindCommonBaseType(v1.type, v2.type); - if (tw != VerifierTypeWrapper.Invalid) - { - v1.isArg |= v2.isArg; - v1.type = tw; - forwarders.Add(v2, v1); - locals.RemoveAt(j); - j--; - } - } - } - } - } - else - { - for (int i = 0; i < locals.Count - 1; i++) - { - for (int j = i + 1; j < locals.Count; j++) - { - LocalVar v1 = (LocalVar)locals[i]; - LocalVar v2 = (LocalVar)locals[j]; - // if the two locals are the same, we merge them, this is a small - // optimization, it should *not* be required for correctness. - if (v1.local == v2.local && v1.type == v2.type) - { - v1.isArg |= v2.isArg; - forwarders.Add(v2, v1); - locals.RemoveAt(j); - j--; - } - } - } - } - invokespecialLocalVars = new LocalVar[instructions.Length][]; - localVars = new LocalVar[instructions.Length]; - for (int i = 0; i < localVars.Length; i++) - { - LocalVar v = null; - if (localStoreReaders[i] != null) - { - Debug.Assert(IsLoadLocal(instructions[i].NormalizedOpCode)); - // lame way to look up the local variable for a load - // (by indirecting through a corresponding store) - foreach (int store in localStoreReaders[i].Keys) - { - v = localByStoreSite[MakeKey(store, instructions[i].NormalizedArg1)]; - break; - } - } - else - { - if (instructions[i].NormalizedOpCode == NormalizedByteCode.__invokespecial || instructions[i].NormalizedOpCode == NormalizedByteCode.__dynamic_invokespecial) - { - invokespecialLocalVars[i] = new LocalVar[method.MaxLocals]; - for (int j = 0; j < invokespecialLocalVars[i].Length; j++) - { - localByStoreSite.TryGetValue(MakeKey(i, j), out invokespecialLocalVars[i][j]); - } - } - else - { - localByStoreSite.TryGetValue(MakeKey(i, instructions[i].NormalizedArg1), out v); - } - } - if (v != null) - { - LocalVar fwd; - if (forwarders.TryGetValue(v, out fwd)) - { - v = fwd; - } - localVars[i] = v; - } - } - this.allLocalVars = locals.ToArray(); - } - - private static void FindLvtEntry(LocalVar lv, ClassFile.Method method, int instructionIndex) - { - ClassFile.Method.LocalVariableTableEntry[] lvt = method.LocalVariableTableAttribute; - if (lvt != null) - { - int pc = method.Instructions[instructionIndex].PC; - int nextPC = method.Instructions[instructionIndex + 1].PC; - bool isStore = IsStoreLocal(method.Instructions[instructionIndex].NormalizedOpCode); - foreach (ClassFile.Method.LocalVariableTableEntry e in lvt) - { - // TODO validate the contents of the LVT entry - if (e.index == lv.local && - (e.start_pc <= pc || (e.start_pc == nextPC && isStore)) && - e.start_pc + e.length > pc) - { - lv.name = e.name; - lv.start_pc = e.start_pc; - lv.end_pc = e.start_pc + e.length; - break; - } - } - } - } - - // NOTE for dead stores, this returns null - internal LocalVar GetLocalVar(int instructionIndex) - { - return localVars[instructionIndex]; - } - - internal LocalVar[] GetLocalVarsForInvokeSpecial(int instructionIndex) - { - return invokespecialLocalVars[instructionIndex]; - } - - internal LocalVar[] GetAllLocalVars() - { - return allLocalVars; - } - - private static bool IsLoadLocal(NormalizedByteCode bc) - { - return bc == NormalizedByteCode.__aload || - bc == NormalizedByteCode.__iload || - bc == NormalizedByteCode.__lload || - bc == NormalizedByteCode.__fload || - bc == NormalizedByteCode.__dload || - bc == NormalizedByteCode.__iinc || - bc == NormalizedByteCode.__ret; - } - - private static bool IsStoreLocal(NormalizedByteCode bc) - { - return bc == NormalizedByteCode.__astore || - bc == NormalizedByteCode.__istore || - bc == NormalizedByteCode.__lstore || - bc == NormalizedByteCode.__fstore || - bc == NormalizedByteCode.__dstore; - } - - struct FindLocalVarState - { - internal bool changed; - internal FindLocalVarStoreSite[] sites; - - internal void Store(int instructionIndex, int localIndex) - { - if (sites[localIndex].Count == 1 && sites[localIndex][0] == instructionIndex) - { - return; - } - sites = (FindLocalVarStoreSite[])sites.Clone(); - sites[localIndex] = new FindLocalVarStoreSite(); - sites[localIndex].Add(instructionIndex); - } - - internal void Merge(FindLocalVarState state) - { - if (sites == null) - { - sites = state.sites; - changed = true; - } - else - { - bool dirty = true; - for (int i = 0; i < sites.Length; i++) - { - for (int j = 0; j < state.sites[i].Count; j++) - { - if (!sites[i].Contains(state.sites[i][j])) - { - if (dirty) - { - dirty = false; - sites = (FindLocalVarStoreSite[])sites.Clone(); - } - sites[i].Add(state.sites[i][j]); - changed = true; - } - } - } - } - } - - internal FindLocalVarState Copy() - { - FindLocalVarState copy = new FindLocalVarState(); - copy.sites = sites; - return copy; - } - - public override string ToString() - { - System.Text.StringBuilder sb = new System.Text.StringBuilder(); - if (sites != null) - { - foreach (FindLocalVarStoreSite site in sites) - { - sb.Append('['); - for (int i = 0; i < site.Count; i++) - { - sb.AppendFormat("{0}, ", site[i]); - } - sb.Append(']'); - } - } - return sb.ToString(); - } - } - - struct FindLocalVarStoreSite - { - private int[] data; - - internal bool Contains(int instructionIndex) - { - if (data != null) - { - for (int i = 0; i < data.Length; i++) - { - if (data[i] == instructionIndex) - { - return true; - } - } - } - return false; - } - - internal void Add(int instructionIndex) - { - if (data == null) - { - data = new int[] { instructionIndex }; - } - else - { - data = ArrayUtil.Concat(data, instructionIndex); - } - } - - internal int this[int index] - { - get { return data[index]; } - } - - internal int Count - { - get { return data == null ? 0 : data.Length; } - } - } - - private static Dictionary[] FindLocalVariables(CodeInfo codeInfo, MethodWrapper mw, ClassFile classFile, ClassFile.Method method) - { - FindLocalVarState[] state = new FindLocalVarState[method.Instructions.Length]; - state[0].changed = true; - state[0].sites = new FindLocalVarStoreSite[method.MaxLocals]; - TypeWrapper[] parameters = mw.GetParameters(); - int argpos = 0; - if (!mw.IsStatic) - { - state[0].sites[argpos++].Add(-1); - } - for (int i = 0; i < parameters.Length; i++) - { - state[0].sites[argpos++].Add(-1); - if (parameters[i].IsWidePrimitive) - { - argpos++; - } - } - return FindLocalVariablesImpl(codeInfo, classFile, method, state); - } - - private static Dictionary[] FindLocalVariablesImpl(CodeInfo codeInfo, ClassFile classFile, ClassFile.Method method, FindLocalVarState[] state) - { - ClassFile.Method.Instruction[] instructions = method.Instructions; - ExceptionTableEntry[] exceptions = method.ExceptionTable; - int maxLocals = method.MaxLocals; - Dictionary[] localStoreReaders = new Dictionary[instructions.Length]; - bool done = false; - - while (!done) - { - done = true; - for (int i = 0; i < instructions.Length; i++) - { - if (state[i].changed) - { - done = false; - state[i].changed = false; - - FindLocalVarState curr = state[i].Copy(); - - for (int j = 0; j < exceptions.Length; j++) - { - if (exceptions[j].startIndex <= i && i < exceptions[j].endIndex) - { - state[exceptions[j].handlerIndex].Merge(curr); - } - } - - if (IsLoadLocal(instructions[i].NormalizedOpCode) - && (instructions[i].NormalizedOpCode != NormalizedByteCode.__aload || !VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(i + 1, 0)))) - { - if (localStoreReaders[i] == null) - { - localStoreReaders[i] = new Dictionary(); - } - for (int j = 0; j < curr.sites[instructions[i].NormalizedArg1].Count; j++) - { - localStoreReaders[i][curr.sites[instructions[i].NormalizedArg1][j]] = ""; - } - } - - if (IsStoreLocal(instructions[i].NormalizedOpCode) - && (instructions[i].NormalizedOpCode != NormalizedByteCode.__astore || !VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(i, 0)))) - { - curr.Store(i, instructions[i].NormalizedArg1); - // if this is a store at the end of an exception block, - // we need to propagate the new state to the exception handler - for (int j = 0; j < exceptions.Length; j++) - { - if (exceptions[j].endIndex == i + 1) - { - state[exceptions[j].handlerIndex].Merge(curr); - } - } - } - - if (instructions[i].NormalizedOpCode == NormalizedByteCode.__invokespecial) - { - ClassFile.ConstantPoolItemMI cpi = classFile.GetMethodref(instructions[i].Arg1); - if (ReferenceEquals(cpi.Name, StringConstants.INIT)) - { - TypeWrapper type = codeInfo.GetRawStackTypeWrapper(i, cpi.GetArgTypes().Length); - // after we've invoked the constructor, the uninitialized references - // are now initialized - if (type == VerifierTypeWrapper.UninitializedThis - || VerifierTypeWrapper.IsNew(type)) - { - for (int j = 0; j < maxLocals; j++) - { - if (codeInfo.GetLocalTypeWrapper(i, j) == type) - { - curr.Store(i, j); - } - } - } - } - } - else if (instructions[i].NormalizedOpCode == NormalizedByteCode.__goto_finally) - { - int handler = instructions[i].HandlerIndex; - - // Normally a store at the end of a try block doesn't affect the handler block, - // but in the case of a finally handler it does, so we need to make sure that - // we merge here in case the try block ended with a store. - state[handler].Merge(curr); - - // Now we recursively analyse the handler and afterwards merge the endfault locations back to us - FindLocalVarState[] handlerState = new FindLocalVarState[instructions.Length]; - handlerState[handler].Merge(curr); - curr = new FindLocalVarState(); - FindLocalVariablesImpl(codeInfo, classFile, method, handlerState); - - // Merge back to the target of our __goto_finally - for (int j = 0; j < handlerState.Length; j++) - { - if (instructions[j].NormalizedOpCode == NormalizedByteCode.__athrow - && codeInfo.HasState(j) - && VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(j, 0)) - && ((VerifierTypeWrapper)codeInfo.GetRawStackTypeWrapper(j, 0)).Index == handler) - { - curr.Merge(handlerState[j]); - } - } - } - - switch (ByteCodeMetaData.GetFlowControl(instructions[i].NormalizedOpCode)) - { - case ByteCodeFlowControl.Switch: - { - for (int j = 0; j < instructions[i].SwitchEntryCount; j++) - { - state[instructions[i].GetSwitchTargetIndex(j)].Merge(curr); - } - state[instructions[i].DefaultTarget].Merge(curr); - break; - } - case ByteCodeFlowControl.Branch: - state[instructions[i].TargetIndex].Merge(curr); - break; - case ByteCodeFlowControl.CondBranch: - state[instructions[i].TargetIndex].Merge(curr); - state[i + 1].Merge(curr); - break; - case ByteCodeFlowControl.Return: - case ByteCodeFlowControl.Throw: - break; - case ByteCodeFlowControl.Next: - state[i + 1].Merge(curr); - break; - default: - throw new InvalidOperationException(); - } - } - } - } - return localStoreReaders; - } - - private static void VisitLocalLoads(CodeInfo codeInfo, ClassFile.Method method, List locals, Dictionary localByStoreSite, Dictionary storeSites, int instructionIndex, bool debug) - { - Debug.Assert(IsLoadLocal(method.Instructions[instructionIndex].NormalizedOpCode)); - LocalVar local = null; - TypeWrapper type = VerifierTypeWrapper.Null; - int localIndex = method.Instructions[instructionIndex].NormalizedArg1; - bool isArg = false; - foreach (int store in storeSites.Keys) - { - if (store == -1) - { - // it's a method argument, it has no initial store, but the type is simply the parameter type - type = InstructionState.FindCommonBaseType(type, codeInfo.GetLocalTypeWrapper(0, localIndex)); - isArg = true; - } - else - { - if (method.Instructions[store].NormalizedOpCode == NormalizedByteCode.__invokespecial) - { - type = InstructionState.FindCommonBaseType(type, codeInfo.GetLocalTypeWrapper(store + 1, localIndex)); - } - else if (method.Instructions[store].NormalizedOpCode == NormalizedByteCode.__static_error) - { - // it's an __invokespecial that turned into a __static_error - // (since a __static_error doesn't continue, we don't need to set type) - } - else - { - Debug.Assert(IsStoreLocal(method.Instructions[store].NormalizedOpCode)); - type = InstructionState.FindCommonBaseType(type, codeInfo.GetStackTypeWrapper(store, 0)); - } - } - // we can't have an invalid type, because that would have failed verification earlier - Debug.Assert(type != VerifierTypeWrapper.Invalid); - - LocalVar l; - if (localByStoreSite.TryGetValue(MakeKey(store, localIndex), out l)) - { - if (local == null) - { - local = l; - } - else if (local != l) - { - // If we've already defined a LocalVar and we find another one, then we merge them - // together. - // This happens for the following code fragment: - // - // int i = -1; - // try { i = 0; for(; ; ) System.out.println(i); } catch(Exception x) {} - // try { i = 0; for(; ; ) System.out.println(i); } catch(Exception x) {} - // System.out.println(i); - // - local = MergeLocals(locals, localByStoreSite, local, l); - } - } - } - if (local == null) - { - local = new LocalVar(); - local.local = localIndex; - if (VerifierTypeWrapper.IsThis(type)) - { - local.type = ((VerifierTypeWrapper)type).UnderlyingType; - } - else - { - local.type = type; - } - local.isArg = isArg; - if (debug) - { - FindLvtEntry(local, method, instructionIndex); - } - locals.Add(local); - } - else - { - local.isArg |= isArg; - local.type = InstructionState.FindCommonBaseType(local.type, type); - Debug.Assert(local.type != VerifierTypeWrapper.Invalid); - } - foreach (int store in storeSites.Keys) - { - LocalVar v; - if (!localByStoreSite.TryGetValue(MakeKey(store, localIndex), out v)) - { - localByStoreSite[MakeKey(store, localIndex)] = local; - } - else if (v != local) - { - local = MergeLocals(locals, localByStoreSite, local, v); - } - } - } - - private static long MakeKey(int i, int j) - { - return (((long)(uint)i) << 32) + (uint)j; - } - - private static LocalVar MergeLocals(List locals, Dictionary localByStoreSite, LocalVar l1, LocalVar l2) - { - Debug.Assert(l1 != l2); - Debug.Assert(l1.local == l2.local); - for (int i = 0; i < locals.Count; i++) - { - if (locals[i] == l2) - { - locals.RemoveAt(i); - i--; - } - } - Dictionary temp = new Dictionary(localByStoreSite); - localByStoreSite.Clear(); - foreach (KeyValuePair kv in temp) - { - localByStoreSite[kv.Key] = kv.Value == l2 ? l1 : kv.Value; - } - l1.isArg |= l2.isArg; - l1.type = InstructionState.FindCommonBaseType(l1.type, l2.type); - Debug.Assert(l1.type != VerifierTypeWrapper.Invalid); - return l1; - } -} diff --git a/src/IKVM.Runtime/MemberFlags.cs b/src/IKVM.Runtime/MemberFlags.cs index d3d4269526..77efa0609f 100644 --- a/src/IKVM.Runtime/MemberFlags.cs +++ b/src/IKVM.Runtime/MemberFlags.cs @@ -23,7 +23,7 @@ Jeroen Frijters */ using System; -namespace IKVM.Internal +namespace IKVM.Runtime { [Flags] diff --git a/src/IKVM.Runtime/MemberWrapper.cs b/src/IKVM.Runtime/MemberWrapper.cs index 157052b4f8..bba1b84753 100644 --- a/src/IKVM.Runtime/MemberWrapper.cs +++ b/src/IKVM.Runtime/MemberWrapper.cs @@ -26,7 +26,6 @@ Jeroen Frijters using System.Runtime.InteropServices; using IKVM.Attributes; -using IKVM.Runtime; #if IMPORTER || EXPORTER using IKVM.Reflection; @@ -42,7 +41,7 @@ Jeroen Frijters using IKVM.Tools.Importer; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { abstract class MemberWrapper diff --git a/src/IKVM.Runtime/MethodAnalyzer.cs b/src/IKVM.Runtime/MethodAnalyzer.cs new file mode 100644 index 0000000000..00ef054b68 --- /dev/null +++ b/src/IKVM.Runtime/MethodAnalyzer.cs @@ -0,0 +1,3018 @@ +/* + Copyright (C) 2002-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Diagnostics; + +using IKVM.ByteCode; + +#if IMPORTER +using IKVM.Tools.Importer; +#endif + +using ExceptionTableEntry = IKVM.Runtime.ClassFile.Method.ExceptionTableEntry; +using InstructionFlags = IKVM.Runtime.ClassFile.Method.InstructionFlags; + +namespace IKVM.Runtime +{ + + sealed class MethodAnalyzer + { + private readonly static TypeWrapper ByteArrayType; + private readonly static TypeWrapper BooleanArrayType; + private readonly static TypeWrapper ShortArrayType; + private readonly static TypeWrapper CharArrayType; + private readonly static TypeWrapper IntArrayType; + private readonly static TypeWrapper FloatArrayType; + private readonly static TypeWrapper DoubleArrayType; + private readonly static TypeWrapper LongArrayType; + private readonly static TypeWrapper java_lang_ThreadDeath; + private readonly TypeWrapper host; // used to by Unsafe.defineAnonymousClass() to provide access to private members of the host + private readonly TypeWrapper wrapper; + private readonly MethodWrapper mw; + private readonly ClassFile classFile; + private readonly ClassFile.Method method; + private readonly ClassLoaderWrapper classLoader; + private readonly TypeWrapper thisType; + private readonly InstructionState[] state; + private List errorMessages; + private readonly Dictionary newTypes = new Dictionary(); + private readonly Dictionary faultTypes = new Dictionary(); + + static MethodAnalyzer() + { + ByteArrayType = PrimitiveTypeWrapper.BYTE.MakeArrayType(1); + BooleanArrayType = PrimitiveTypeWrapper.BOOLEAN.MakeArrayType(1); + ShortArrayType = PrimitiveTypeWrapper.SHORT.MakeArrayType(1); + CharArrayType = PrimitiveTypeWrapper.CHAR.MakeArrayType(1); + IntArrayType = PrimitiveTypeWrapper.INT.MakeArrayType(1); + FloatArrayType = PrimitiveTypeWrapper.FLOAT.MakeArrayType(1); + DoubleArrayType = PrimitiveTypeWrapper.DOUBLE.MakeArrayType(1); + LongArrayType = PrimitiveTypeWrapper.LONG.MakeArrayType(1); + java_lang_ThreadDeath = ClassLoaderWrapper.LoadClassCritical("java.lang.ThreadDeath"); + } + + internal MethodAnalyzer(TypeWrapper host, TypeWrapper wrapper, MethodWrapper mw, ClassFile classFile, ClassFile.Method method, ClassLoaderWrapper classLoader) + { + if (method.VerifyError != null) + { + throw new VerifyError(method.VerifyError); + } + + this.host = host; + this.wrapper = wrapper; + this.mw = mw; + this.classFile = classFile; + this.method = method; + this.classLoader = classLoader; + state = new InstructionState[method.Instructions.Length]; + + try + { + // ensure that exception blocks and handlers start and end at instruction boundaries + for (int i = 0; i < method.ExceptionTable.Length; i++) + { + int start = method.ExceptionTable[i].startIndex; + int end = method.ExceptionTable[i].endIndex; + int handler = method.ExceptionTable[i].handlerIndex; + if (start >= end || start == -1 || end == -1 || handler <= 0) + { + throw new IndexOutOfRangeException(); + } + } + } + catch (IndexOutOfRangeException) + { + // TODO figure out if we should throw this during class loading + throw new ClassFormatError(string.Format("Illegal exception table (class: {0}, method: {1}, signature: {2}", classFile.Name, method.Name, method.Signature)); + } + + // start by computing the initial state, the stack is empty and the locals contain the arguments + state[0] = new InstructionState(method.MaxLocals, method.MaxStack); + int firstNonArgLocalIndex = 0; + if (!method.IsStatic) + { + thisType = VerifierTypeWrapper.MakeThis(wrapper); + // this reference. If we're a constructor, the this reference is uninitialized. + if (method.IsConstructor) + { + state[0].SetLocalType(firstNonArgLocalIndex++, VerifierTypeWrapper.UninitializedThis, -1); + state[0].SetUnitializedThis(true); + } + else + { + state[0].SetLocalType(firstNonArgLocalIndex++, thisType, -1); + } + } + else + { + thisType = null; + } + // mw can be null when we're invoked from IsSideEffectFreeStaticInitializer + TypeWrapper[] argTypeWrappers = mw == null ? TypeWrapper.EmptyArray : mw.GetParameters(); + for (int i = 0; i < argTypeWrappers.Length; i++) + { + TypeWrapper type = argTypeWrappers[i]; + if (type.IsIntOnStackPrimitive) + { + type = PrimitiveTypeWrapper.INT; + } + state[0].SetLocalType(firstNonArgLocalIndex++, type, -1); + if (type.IsWidePrimitive) + { + firstNonArgLocalIndex++; + } + } + AnalyzeTypeFlow(); + VerifyPassTwo(); + PatchLoadConstants(); + } + + private void PatchLoadConstants() + { + ClassFile.Method.Instruction[] code = method.Instructions; + for (int i = 0; i < code.Length; i++) + { + if (state[i] != null) + { + switch (code[i].NormalizedOpCode) + { + case NormalizedByteCode.__ldc: + switch (GetConstantPoolConstantType(code[i].Arg1)) + { + case ClassFile.ConstantType.Double: + case ClassFile.ConstantType.Float: + case ClassFile.ConstantType.Integer: + case ClassFile.ConstantType.Long: + case ClassFile.ConstantType.String: + case ClassFile.ConstantType.LiveObject: + code[i].PatchOpCode(NormalizedByteCode.__ldc_nothrow); + break; + } + break; + } + } + } + } + + internal CodeInfo GetCodeInfoAndErrors(UntangledExceptionTable exceptions, out List errors) + { + CodeInfo codeInfo = new CodeInfo(state); + OptimizationPass(codeInfo, classFile, method, exceptions, wrapper, classLoader); + PatchHardErrorsAndDynamicMemberAccess(wrapper, mw); + errors = errorMessages; + if (AnalyzePotentialFaultBlocks(codeInfo, method, exceptions)) + { + AnalyzeTypeFlow(); + } + ConvertFinallyBlocks(codeInfo, method, exceptions); + return codeInfo; + } + + private void AnalyzeTypeFlow() + { + InstructionState s = new InstructionState(method.MaxLocals, method.MaxStack); + bool done = false; + ClassFile.Method.Instruction[] instructions = method.Instructions; + while (!done) + { + done = true; + for (int i = 0; i < instructions.Length; i++) + { + if (state[i] != null && state[i].changed) + { + try + { + //Console.WriteLine(method.Instructions[i].PC + ": " + method.Instructions[i].OpCode.ToString()); + done = false; + state[i].changed = false; + // mark the exception handlers reachable from this instruction + for (int j = 0; j < method.ExceptionTable.Length; j++) + { + if (method.ExceptionTable[j].startIndex <= i && i < method.ExceptionTable[j].endIndex) + { + MergeExceptionHandler(j, state[i]); + } + } + state[i].CopyTo(s); + ClassFile.Method.Instruction instr = instructions[i]; + switch (instr.NormalizedOpCode) + { + case NormalizedByteCode.__aload: + { + TypeWrapper type = s.GetLocalType(instr.NormalizedArg1); + if (type == VerifierTypeWrapper.Invalid || type.IsPrimitive) + { + throw new VerifyError("Object reference expected"); + } + s.PushType(type); + break; + } + case NormalizedByteCode.__astore: + { + if (VerifierTypeWrapper.IsFaultBlockException(s.PeekType())) + { + s.SetLocalType(instr.NormalizedArg1, s.PopFaultBlockException(), i); + break; + } + // NOTE since the reference can be uninitialized, we cannot use PopObjectType + TypeWrapper type = s.PopType(); + if (type.IsPrimitive) + { + throw new VerifyError("Object reference expected"); + } + s.SetLocalType(instr.NormalizedArg1, type, i); + break; + } + case NormalizedByteCode.__aconst_null: + s.PushType(VerifierTypeWrapper.Null); + break; + case NormalizedByteCode.__aaload: + { + s.PopInt(); + TypeWrapper type = s.PopArrayType(); + if (type == VerifierTypeWrapper.Null) + { + // if the array is null, we have use null as the element type, because + // otherwise the rest of the code will not verify correctly + s.PushType(VerifierTypeWrapper.Null); + } + else if (type.IsUnloadable) + { + s.PushType(VerifierTypeWrapper.Unloadable); + } + else + { + type = type.ElementTypeWrapper; + if (type.IsPrimitive) + { + throw new VerifyError("Object array expected"); + } + s.PushType(type); + } + break; + } + case NormalizedByteCode.__aastore: + s.PopObjectType(); + s.PopInt(); + s.PopArrayType(); + // TODO check that elem is assignable to the array + break; + case NormalizedByteCode.__baload: + { + s.PopInt(); + TypeWrapper type = s.PopArrayType(); + if (!VerifierTypeWrapper.IsNullOrUnloadable(type) && + type != ByteArrayType && + type != BooleanArrayType) + { + throw new VerifyError(); + } + s.PushInt(); + break; + } + case NormalizedByteCode.__bastore: + { + s.PopInt(); + s.PopInt(); + TypeWrapper type = s.PopArrayType(); + if (!VerifierTypeWrapper.IsNullOrUnloadable(type) && + type != ByteArrayType && + type != BooleanArrayType) + { + throw new VerifyError(); + } + break; + } + case NormalizedByteCode.__caload: + s.PopInt(); + s.PopObjectType(CharArrayType); + s.PushInt(); + break; + case NormalizedByteCode.__castore: + s.PopInt(); + s.PopInt(); + s.PopObjectType(CharArrayType); + break; + case NormalizedByteCode.__saload: + s.PopInt(); + s.PopObjectType(ShortArrayType); + s.PushInt(); + break; + case NormalizedByteCode.__sastore: + s.PopInt(); + s.PopInt(); + s.PopObjectType(ShortArrayType); + break; + case NormalizedByteCode.__iaload: + s.PopInt(); + s.PopObjectType(IntArrayType); + s.PushInt(); + break; + case NormalizedByteCode.__iastore: + s.PopInt(); + s.PopInt(); + s.PopObjectType(IntArrayType); + break; + case NormalizedByteCode.__laload: + s.PopInt(); + s.PopObjectType(LongArrayType); + s.PushLong(); + break; + case NormalizedByteCode.__lastore: + s.PopLong(); + s.PopInt(); + s.PopObjectType(LongArrayType); + break; + case NormalizedByteCode.__daload: + s.PopInt(); + s.PopObjectType(DoubleArrayType); + s.PushDouble(); + break; + case NormalizedByteCode.__dastore: + s.PopDouble(); + s.PopInt(); + s.PopObjectType(DoubleArrayType); + break; + case NormalizedByteCode.__faload: + s.PopInt(); + s.PopObjectType(FloatArrayType); + s.PushFloat(); + break; + case NormalizedByteCode.__fastore: + s.PopFloat(); + s.PopInt(); + s.PopObjectType(FloatArrayType); + break; + case NormalizedByteCode.__arraylength: + s.PopArrayType(); + s.PushInt(); + break; + case NormalizedByteCode.__iconst: + s.PushInt(); + break; + case NormalizedByteCode.__if_icmpeq: + case NormalizedByteCode.__if_icmpne: + case NormalizedByteCode.__if_icmplt: + case NormalizedByteCode.__if_icmpge: + case NormalizedByteCode.__if_icmpgt: + case NormalizedByteCode.__if_icmple: + s.PopInt(); + s.PopInt(); + break; + case NormalizedByteCode.__ifeq: + case NormalizedByteCode.__ifge: + case NormalizedByteCode.__ifgt: + case NormalizedByteCode.__ifle: + case NormalizedByteCode.__iflt: + case NormalizedByteCode.__ifne: + s.PopInt(); + break; + case NormalizedByteCode.__ifnonnull: + case NormalizedByteCode.__ifnull: + // TODO it might be legal to use an unitialized ref here + s.PopObjectType(); + break; + case NormalizedByteCode.__if_acmpeq: + case NormalizedByteCode.__if_acmpne: + // TODO it might be legal to use an unitialized ref here + s.PopObjectType(); + s.PopObjectType(); + break; + case NormalizedByteCode.__getstatic: + case NormalizedByteCode.__dynamic_getstatic: + // special support for when we're being called from IsSideEffectFreeStaticInitializer + if (mw == null) + { + switch (GetFieldref(instr.Arg1).Signature[0]) + { + case 'B': + case 'Z': + case 'C': + case 'S': + case 'I': + s.PushInt(); + break; + case 'F': + s.PushFloat(); + break; + case 'D': + s.PushDouble(); + break; + case 'J': + s.PushLong(); + break; + case 'L': + case '[': + throw new VerifyError(); + default: + throw new InvalidOperationException(); + } + } + else + { + ClassFile.ConstantPoolItemFieldref cpi = GetFieldref(instr.Arg1); + if (cpi.GetField() != null && cpi.GetField().FieldTypeWrapper.IsUnloadable) + { + s.PushType(cpi.GetField().FieldTypeWrapper); + } + else + { + s.PushType(cpi.GetFieldType()); + } + } + break; + case NormalizedByteCode.__putstatic: + case NormalizedByteCode.__dynamic_putstatic: + // special support for when we're being called from IsSideEffectFreeStaticInitializer + if (mw == null) + { + switch (GetFieldref(instr.Arg1).Signature[0]) + { + case 'B': + case 'Z': + case 'C': + case 'S': + case 'I': + s.PopInt(); + break; + case 'F': + s.PopFloat(); + break; + case 'D': + s.PopDouble(); + break; + case 'J': + s.PopLong(); + break; + case 'L': + case '[': + if (s.PopAnyType() != VerifierTypeWrapper.Null) + { + throw new VerifyError(); + } + break; + default: + throw new InvalidOperationException(); + } + } + else + { + s.PopType(GetFieldref(instr.Arg1).GetFieldType()); + } + break; + case NormalizedByteCode.__getfield: + case NormalizedByteCode.__dynamic_getfield: + { + s.PopObjectType(GetFieldref(instr.Arg1).GetClassType()); + ClassFile.ConstantPoolItemFieldref cpi = GetFieldref(instr.Arg1); + if (cpi.GetField() != null && cpi.GetField().FieldTypeWrapper.IsUnloadable) + { + s.PushType(cpi.GetField().FieldTypeWrapper); + } + else + { + s.PushType(cpi.GetFieldType()); + } + break; + } + case NormalizedByteCode.__putfield: + case NormalizedByteCode.__dynamic_putfield: + s.PopType(GetFieldref(instr.Arg1).GetFieldType()); + // putfield is allowed to access the uninitialized this + if (s.PeekType() == VerifierTypeWrapper.UninitializedThis + && wrapper.IsAssignableTo(GetFieldref(instr.Arg1).GetClassType())) + { + s.PopType(); + } + else + { + s.PopObjectType(GetFieldref(instr.Arg1).GetClassType()); + } + break; + case NormalizedByteCode.__ldc_nothrow: + case NormalizedByteCode.__ldc: + { + switch (GetConstantPoolConstantType(instr.Arg1)) + { + case ClassFile.ConstantType.Double: + s.PushDouble(); + break; + case ClassFile.ConstantType.Float: + s.PushFloat(); + break; + case ClassFile.ConstantType.Integer: + s.PushInt(); + break; + case ClassFile.ConstantType.Long: + s.PushLong(); + break; + case ClassFile.ConstantType.String: + s.PushType(CoreClasses.java.lang.String.Wrapper); + break; + case ClassFile.ConstantType.LiveObject: + s.PushType(CoreClasses.java.lang.Object.Wrapper); + break; + case ClassFile.ConstantType.Class: + if (classFile.MajorVersion < 49) + { + throw new VerifyError("Illegal type in constant pool"); + } + s.PushType(CoreClasses.java.lang.Class.Wrapper); + break; + case ClassFile.ConstantType.MethodHandle: + s.PushType(CoreClasses.java.lang.invoke.MethodHandle.Wrapper); + break; + case ClassFile.ConstantType.MethodType: + s.PushType(CoreClasses.java.lang.invoke.MethodType.Wrapper); + break; + default: + // NOTE this is not a VerifyError, because it cannot happen (unless we have + // a bug in ClassFile.GetConstantPoolConstantType) + throw new InvalidOperationException(); + } + break; + } + case NormalizedByteCode.__clone_array: + case NormalizedByteCode.__invokevirtual: + case NormalizedByteCode.__invokespecial: + case NormalizedByteCode.__invokeinterface: + case NormalizedByteCode.__invokestatic: + case NormalizedByteCode.__dynamic_invokevirtual: + case NormalizedByteCode.__dynamic_invokespecial: + case NormalizedByteCode.__dynamic_invokeinterface: + case NormalizedByteCode.__dynamic_invokestatic: + case NormalizedByteCode.__privileged_invokevirtual: + case NormalizedByteCode.__privileged_invokespecial: + case NormalizedByteCode.__privileged_invokestatic: + case NormalizedByteCode.__methodhandle_invoke: + case NormalizedByteCode.__methodhandle_link: + { + ClassFile.ConstantPoolItemMI cpi = GetMethodref(instr.Arg1); + TypeWrapper retType = cpi.GetRetType(); + // HACK to allow the result of Unsafe.getObjectVolatile() (on an array) + // to be used with Unsafe.putObject() we need to propagate the + // element type here as the return type (instead of object) + if (cpi.GetMethod() != null + && cpi.GetMethod().IsIntrinsic + && cpi.Class == "sun.misc.Unsafe" + && cpi.Name == "getObjectVolatile" + && Intrinsics.IsSupportedArrayTypeForUnsafeOperation(s.GetStackSlot(1))) + { + retType = s.GetStackSlot(1).ElementTypeWrapper; + } + s.MultiPopAnyType(cpi.GetArgTypes().Length); + if (instr.NormalizedOpCode != NormalizedByteCode.__invokestatic + && instr.NormalizedOpCode != NormalizedByteCode.__dynamic_invokestatic) + { + TypeWrapper type = s.PopType(); + if (ReferenceEquals(cpi.Name, StringConstants.INIT)) + { + // after we've invoked the constructor, the uninitialized references + // are now initialized + if (type == VerifierTypeWrapper.UninitializedThis) + { + if (s.GetLocalTypeEx(0) == type) + { + s.SetLocalType(0, thisType, i); + } + s.MarkInitialized(type, wrapper, i); + s.SetUnitializedThis(false); + } + else if (VerifierTypeWrapper.IsNew(type)) + { + s.MarkInitialized(type, ((VerifierTypeWrapper)type).UnderlyingType, i); + } + else + { + // This is a VerifyError, but it will be caught by our second pass + } + } + } + if (retType != PrimitiveTypeWrapper.VOID) + { + if (cpi.GetMethod() != null && cpi.GetMethod().ReturnType.IsUnloadable) + { + s.PushType(cpi.GetMethod().ReturnType); + } + else if (retType == PrimitiveTypeWrapper.DOUBLE) + { + s.PushExtendedDouble(); + } + else if (retType == PrimitiveTypeWrapper.FLOAT) + { + s.PushExtendedFloat(); + } + else + { + s.PushType(retType); + } + } + break; + } + case NormalizedByteCode.__invokedynamic: + { + ClassFile.ConstantPoolItemInvokeDynamic cpi = GetInvokeDynamic(instr.Arg1); + s.MultiPopAnyType(cpi.GetArgTypes().Length); + TypeWrapper retType = cpi.GetRetType(); + if (retType != PrimitiveTypeWrapper.VOID) + { + if (retType == PrimitiveTypeWrapper.DOUBLE) + { + s.PushExtendedDouble(); + } + else if (retType == PrimitiveTypeWrapper.FLOAT) + { + s.PushExtendedFloat(); + } + else + { + s.PushType(retType); + } + } + break; + } + case NormalizedByteCode.__goto: + break; + case NormalizedByteCode.__istore: + s.PopInt(); + s.SetLocalInt(instr.NormalizedArg1, i); + break; + case NormalizedByteCode.__iload: + s.GetLocalInt(instr.NormalizedArg1); + s.PushInt(); + break; + case NormalizedByteCode.__ineg: + s.PopInt(); + s.PushInt(); + break; + case NormalizedByteCode.__iadd: + case NormalizedByteCode.__isub: + case NormalizedByteCode.__imul: + case NormalizedByteCode.__idiv: + case NormalizedByteCode.__irem: + case NormalizedByteCode.__iand: + case NormalizedByteCode.__ior: + case NormalizedByteCode.__ixor: + case NormalizedByteCode.__ishl: + case NormalizedByteCode.__ishr: + case NormalizedByteCode.__iushr: + s.PopInt(); + s.PopInt(); + s.PushInt(); + break; + case NormalizedByteCode.__lneg: + s.PopLong(); + s.PushLong(); + break; + case NormalizedByteCode.__ladd: + case NormalizedByteCode.__lsub: + case NormalizedByteCode.__lmul: + case NormalizedByteCode.__ldiv: + case NormalizedByteCode.__lrem: + case NormalizedByteCode.__land: + case NormalizedByteCode.__lor: + case NormalizedByteCode.__lxor: + s.PopLong(); + s.PopLong(); + s.PushLong(); + break; + case NormalizedByteCode.__lshl: + case NormalizedByteCode.__lshr: + case NormalizedByteCode.__lushr: + s.PopInt(); + s.PopLong(); + s.PushLong(); + break; + case NormalizedByteCode.__fneg: + if (s.PopFloat()) + { + s.PushExtendedFloat(); + } + else + { + s.PushFloat(); + } + break; + case NormalizedByteCode.__fadd: + case NormalizedByteCode.__fsub: + case NormalizedByteCode.__fmul: + case NormalizedByteCode.__fdiv: + case NormalizedByteCode.__frem: + s.PopFloat(); + s.PopFloat(); + s.PushExtendedFloat(); + break; + case NormalizedByteCode.__dneg: + if (s.PopDouble()) + { + s.PushExtendedDouble(); + } + else + { + s.PushDouble(); + } + break; + case NormalizedByteCode.__dadd: + case NormalizedByteCode.__dsub: + case NormalizedByteCode.__dmul: + case NormalizedByteCode.__ddiv: + case NormalizedByteCode.__drem: + s.PopDouble(); + s.PopDouble(); + s.PushExtendedDouble(); + break; + case NormalizedByteCode.__new: + { + // mark the type, so that we can ascertain that it is a "new object" + TypeWrapper type; + if (!newTypes.TryGetValue(i, out type)) + { + type = GetConstantPoolClassType(instr.Arg1); + if (type.IsArray) + { + throw new VerifyError("Illegal use of array type"); + } + type = VerifierTypeWrapper.MakeNew(type, i); + newTypes[i] = type; + } + s.PushType(type); + break; + } + case NormalizedByteCode.__multianewarray: + { + if (instr.Arg2 < 1) + { + throw new VerifyError("Illegal dimension argument"); + } + for (int j = 0; j < instr.Arg2; j++) + { + s.PopInt(); + } + TypeWrapper type = GetConstantPoolClassType(instr.Arg1); + if (type.ArrayRank < instr.Arg2) + { + throw new VerifyError("Illegal dimension argument"); + } + s.PushType(type); + break; + } + case NormalizedByteCode.__anewarray: + { + s.PopInt(); + TypeWrapper type = GetConstantPoolClassType(instr.Arg1); + if (type.IsUnloadable) + { + s.PushType(new UnloadableTypeWrapper("[" + type.SigName)); + } + else + { + s.PushType(type.MakeArrayType(1)); + } + break; + } + case NormalizedByteCode.__newarray: + s.PopInt(); + switch (instr.Arg1) + { + case 4: + s.PushType(BooleanArrayType); + break; + case 5: + s.PushType(CharArrayType); + break; + case 6: + s.PushType(FloatArrayType); + break; + case 7: + s.PushType(DoubleArrayType); + break; + case 8: + s.PushType(ByteArrayType); + break; + case 9: + s.PushType(ShortArrayType); + break; + case 10: + s.PushType(IntArrayType); + break; + case 11: + s.PushType(LongArrayType); + break; + default: + throw new VerifyError("Bad type"); + } + break; + case NormalizedByteCode.__swap: + { + TypeWrapper t1 = s.PopType(); + TypeWrapper t2 = s.PopType(); + s.PushType(t1); + s.PushType(t2); + break; + } + case NormalizedByteCode.__dup: + { + TypeWrapper t = s.PopType(); + s.PushType(t); + s.PushType(t); + break; + } + case NormalizedByteCode.__dup2: + { + TypeWrapper t = s.PopAnyType(); + if (t.IsWidePrimitive || t == VerifierTypeWrapper.ExtendedDouble) + { + s.PushType(t); + s.PushType(t); + } + else + { + TypeWrapper t2 = s.PopType(); + s.PushType(t2); + s.PushType(t); + s.PushType(t2); + s.PushType(t); + } + break; + } + case NormalizedByteCode.__dup_x1: + { + TypeWrapper value1 = s.PopType(); + TypeWrapper value2 = s.PopType(); + s.PushType(value1); + s.PushType(value2); + s.PushType(value1); + break; + } + case NormalizedByteCode.__dup2_x1: + { + TypeWrapper value1 = s.PopAnyType(); + if (value1.IsWidePrimitive || value1 == VerifierTypeWrapper.ExtendedDouble) + { + TypeWrapper value2 = s.PopType(); + s.PushType(value1); + s.PushType(value2); + s.PushType(value1); + } + else + { + TypeWrapper value2 = s.PopType(); + TypeWrapper value3 = s.PopType(); + s.PushType(value2); + s.PushType(value1); + s.PushType(value3); + s.PushType(value2); + s.PushType(value1); + } + break; + } + case NormalizedByteCode.__dup_x2: + { + TypeWrapper value1 = s.PopType(); + TypeWrapper value2 = s.PopAnyType(); + if (value2.IsWidePrimitive || value2 == VerifierTypeWrapper.ExtendedDouble) + { + s.PushType(value1); + s.PushType(value2); + s.PushType(value1); + } + else + { + TypeWrapper value3 = s.PopType(); + s.PushType(value1); + s.PushType(value3); + s.PushType(value2); + s.PushType(value1); + } + break; + } + case NormalizedByteCode.__dup2_x2: + { + TypeWrapper value1 = s.PopAnyType(); + if (value1.IsWidePrimitive || value1 == VerifierTypeWrapper.ExtendedDouble) + { + TypeWrapper value2 = s.PopAnyType(); + if (value2.IsWidePrimitive || value2 == VerifierTypeWrapper.ExtendedDouble) + { + // Form 4 + s.PushType(value1); + s.PushType(value2); + s.PushType(value1); + } + else + { + // Form 2 + TypeWrapper value3 = s.PopType(); + s.PushType(value1); + s.PushType(value3); + s.PushType(value2); + s.PushType(value1); + } + } + else + { + TypeWrapper value2 = s.PopType(); + TypeWrapper value3 = s.PopAnyType(); + if (value3.IsWidePrimitive || value3 == VerifierTypeWrapper.ExtendedDouble) + { + // Form 3 + s.PushType(value2); + s.PushType(value1); + s.PushType(value3); + s.PushType(value2); + s.PushType(value1); + } + else + { + // Form 4 + TypeWrapper value4 = s.PopType(); + s.PushType(value2); + s.PushType(value1); + s.PushType(value4); + s.PushType(value3); + s.PushType(value2); + s.PushType(value1); + } + } + break; + } + case NormalizedByteCode.__pop: + s.PopType(); + break; + case NormalizedByteCode.__pop2: + { + TypeWrapper type = s.PopAnyType(); + if (!type.IsWidePrimitive && type != VerifierTypeWrapper.ExtendedDouble) + { + s.PopType(); + } + break; + } + case NormalizedByteCode.__monitorenter: + case NormalizedByteCode.__monitorexit: + // TODO these bytecodes are allowed on an uninitialized object, but + // we don't support that at the moment... + s.PopObjectType(); + break; + case NormalizedByteCode.__return: + // mw is null if we're called from IsSideEffectFreeStaticInitializer + if (mw != null) + { + if (mw.ReturnType != PrimitiveTypeWrapper.VOID) + { + throw new VerifyError("Wrong return type in function"); + } + // if we're a constructor, make sure we called the base class constructor + s.CheckUninitializedThis(); + } + break; + case NormalizedByteCode.__areturn: + s.PopObjectType(mw.ReturnType); + break; + case NormalizedByteCode.__ireturn: + { + s.PopInt(); + if (!mw.ReturnType.IsIntOnStackPrimitive) + { + throw new VerifyError("Wrong return type in function"); + } + break; + } + case NormalizedByteCode.__lreturn: + s.PopLong(); + if (mw.ReturnType != PrimitiveTypeWrapper.LONG) + { + throw new VerifyError("Wrong return type in function"); + } + break; + case NormalizedByteCode.__freturn: + s.PopFloat(); + if (mw.ReturnType != PrimitiveTypeWrapper.FLOAT) + { + throw new VerifyError("Wrong return type in function"); + } + break; + case NormalizedByteCode.__dreturn: + s.PopDouble(); + if (mw.ReturnType != PrimitiveTypeWrapper.DOUBLE) + { + throw new VerifyError("Wrong return type in function"); + } + break; + case NormalizedByteCode.__fload: + s.GetLocalFloat(instr.NormalizedArg1); + s.PushFloat(); + break; + case NormalizedByteCode.__fstore: + s.PopFloat(); + s.SetLocalFloat(instr.NormalizedArg1, i); + break; + case NormalizedByteCode.__dload: + s.GetLocalDouble(instr.NormalizedArg1); + s.PushDouble(); + break; + case NormalizedByteCode.__dstore: + s.PopDouble(); + s.SetLocalDouble(instr.NormalizedArg1, i); + break; + case NormalizedByteCode.__lload: + s.GetLocalLong(instr.NormalizedArg1); + s.PushLong(); + break; + case NormalizedByteCode.__lstore: + s.PopLong(); + s.SetLocalLong(instr.NormalizedArg1, i); + break; + case NormalizedByteCode.__lconst_0: + case NormalizedByteCode.__lconst_1: + s.PushLong(); + break; + case NormalizedByteCode.__fconst_0: + case NormalizedByteCode.__fconst_1: + case NormalizedByteCode.__fconst_2: + s.PushFloat(); + break; + case NormalizedByteCode.__dconst_0: + case NormalizedByteCode.__dconst_1: + s.PushDouble(); + break; + case NormalizedByteCode.__lcmp: + s.PopLong(); + s.PopLong(); + s.PushInt(); + break; + case NormalizedByteCode.__fcmpl: + case NormalizedByteCode.__fcmpg: + s.PopFloat(); + s.PopFloat(); + s.PushInt(); + break; + case NormalizedByteCode.__dcmpl: + case NormalizedByteCode.__dcmpg: + s.PopDouble(); + s.PopDouble(); + s.PushInt(); + break; + case NormalizedByteCode.__checkcast: + s.PopObjectType(); + s.PushType(GetConstantPoolClassType(instr.Arg1)); + break; + case NormalizedByteCode.__instanceof: + s.PopObjectType(); + s.PushInt(); + break; + case NormalizedByteCode.__iinc: + s.GetLocalInt(instr.Arg1); + break; + case NormalizedByteCode.__athrow: + if (VerifierTypeWrapper.IsFaultBlockException(s.PeekType())) + { + s.PopFaultBlockException(); + } + else + { + s.PopObjectType(CoreClasses.java.lang.Throwable.Wrapper); + } + break; + case NormalizedByteCode.__tableswitch: + case NormalizedByteCode.__lookupswitch: + s.PopInt(); + break; + case NormalizedByteCode.__i2b: + s.PopInt(); + s.PushInt(); + break; + case NormalizedByteCode.__i2c: + s.PopInt(); + s.PushInt(); + break; + case NormalizedByteCode.__i2s: + s.PopInt(); + s.PushInt(); + break; + case NormalizedByteCode.__i2l: + s.PopInt(); + s.PushLong(); + break; + case NormalizedByteCode.__i2f: + s.PopInt(); + s.PushFloat(); + break; + case NormalizedByteCode.__i2d: + s.PopInt(); + s.PushDouble(); + break; + case NormalizedByteCode.__l2i: + s.PopLong(); + s.PushInt(); + break; + case NormalizedByteCode.__l2f: + s.PopLong(); + s.PushFloat(); + break; + case NormalizedByteCode.__l2d: + s.PopLong(); + s.PushDouble(); + break; + case NormalizedByteCode.__f2i: + s.PopFloat(); + s.PushInt(); + break; + case NormalizedByteCode.__f2l: + s.PopFloat(); + s.PushLong(); + break; + case NormalizedByteCode.__f2d: + s.PopFloat(); + s.PushDouble(); + break; + case NormalizedByteCode.__d2i: + s.PopDouble(); + s.PushInt(); + break; + case NormalizedByteCode.__d2f: + s.PopDouble(); + s.PushFloat(); + break; + case NormalizedByteCode.__d2l: + s.PopDouble(); + s.PushLong(); + break; + case NormalizedByteCode.__nop: + if (i + 1 == instructions.Length) + { + throw new VerifyError("Falling off the end of the code"); + } + break; + case NormalizedByteCode.__static_error: + break; + case NormalizedByteCode.__jsr: + case NormalizedByteCode.__ret: + throw new VerifyError("Bad instruction"); + default: + throw new NotImplementedException(instr.NormalizedOpCode.ToString()); + } + if (s.GetStackHeight() > method.MaxStack) + { + throw new VerifyError("Stack size too large"); + } + for (int j = 0; j < method.ExceptionTable.Length; j++) + { + if (method.ExceptionTable[j].endIndex == i + 1) + { + MergeExceptionHandler(j, s); + } + } + try + { + switch (ByteCodeMetaData.GetFlowControl(instr.NormalizedOpCode)) + { + case ByteCodeFlowControl.Switch: + for (int j = 0; j < instr.SwitchEntryCount; j++) + { + state[instr.GetSwitchTargetIndex(j)] += s; + } + state[instr.DefaultTarget] += s; + break; + case ByteCodeFlowControl.CondBranch: + state[i + 1] += s; + state[instr.TargetIndex] += s; + break; + case ByteCodeFlowControl.Branch: + state[instr.TargetIndex] += s; + break; + case ByteCodeFlowControl.Return: + case ByteCodeFlowControl.Throw: + break; + case ByteCodeFlowControl.Next: + state[i + 1] += s; + break; + default: + throw new InvalidOperationException(); + } + } + catch (IndexOutOfRangeException) + { + // we're going to assume that this always means that we have an invalid branch target + // NOTE because PcIndexMap returns -1 for illegal PCs (in the middle of an instruction) and + // we always use that value as an index into the state array, any invalid PC will result + // in an IndexOutOfRangeException + throw new VerifyError("Illegal target of jump or branch"); + } + } + catch (VerifyError x) + { + string opcode = instructions[i].NormalizedOpCode.ToString(); + if (opcode.StartsWith("__")) + { + opcode = opcode.Substring(2); + } + throw new VerifyError(string.Format("{5} (class: {0}, method: {1}, signature: {2}, offset: {3}, instruction: {4})", + classFile.Name, method.Name, method.Signature, instructions[i].PC, opcode, x.Message), x); + } + } + } + } + } + + private void MergeExceptionHandler(int exceptionIndex, InstructionState curr) + { + int idx = method.ExceptionTable[exceptionIndex].handlerIndex; + InstructionState ex = curr.CopyLocals(); + int catch_type = method.ExceptionTable[exceptionIndex].catch_type; + if (catch_type == 0) + { + TypeWrapper tw; + if (!faultTypes.TryGetValue(idx, out tw)) + { + tw = VerifierTypeWrapper.MakeFaultBlockException(this, idx); + faultTypes.Add(idx, tw); + } + ex.PushType(tw); + } + else + { + // TODO if the exception type is unloadable we should consider pushing + // Throwable as the type and recording a loader constraint + ex.PushType(GetConstantPoolClassType(catch_type)); + } + state[idx] += ex; + } + + // this verification pass must run on the unmodified bytecode stream + private void VerifyPassTwo() + { + ClassFile.Method.Instruction[] instructions = method.Instructions; + for (int i = 0; i < instructions.Length; i++) + { + if (state[i] != null) + { + try + { + switch (instructions[i].NormalizedOpCode) + { + case NormalizedByteCode.__invokeinterface: + case NormalizedByteCode.__invokespecial: + case NormalizedByteCode.__invokestatic: + case NormalizedByteCode.__invokevirtual: + VerifyInvokePassTwo(i); + break; + case NormalizedByteCode.__invokedynamic: + VerifyInvokeDynamic(i); + break; + } + } + catch (VerifyError x) + { + string opcode = instructions[i].NormalizedOpCode.ToString(); + if (opcode.StartsWith("__")) + { + opcode = opcode.Substring(2); + } + throw new VerifyError(string.Format("{5} (class: {0}, method: {1}, signature: {2}, offset: {3}, instruction: {4})", + classFile.Name, method.Name, method.Signature, instructions[i].PC, opcode, x.Message), x); + } + } + } + } + + private void VerifyInvokePassTwo(int index) + { + StackState stack = new StackState(state[index]); + NormalizedByteCode invoke = method.Instructions[index].NormalizedOpCode; + ClassFile.ConstantPoolItemMI cpi = GetMethodref(method.Instructions[index].Arg1); + if ((invoke == NormalizedByteCode.__invokestatic || invoke == NormalizedByteCode.__invokespecial) && classFile.MajorVersion >= 52) + { + // invokestatic and invokespecial may be used to invoke interface methods in Java 8 + // but invokespecial can only invoke methods in the current interface or a directly implemented interface + if (invoke == NormalizedByteCode.__invokespecial && cpi is ClassFile.ConstantPoolItemInterfaceMethodref) + { + if (cpi.GetClassType() == host) + { + // ok + } + else if (cpi.GetClassType() != wrapper && Array.IndexOf(wrapper.Interfaces, cpi.GetClassType()) == -1) + { + throw new VerifyError("Bad invokespecial instruction: interface method reference is in an indirect superinterface."); + } + } + } + else if ((cpi is ClassFile.ConstantPoolItemInterfaceMethodref) != (invoke == NormalizedByteCode.__invokeinterface)) + { + throw new VerifyError("Illegal constant pool index"); + } + if (invoke != NormalizedByteCode.__invokespecial && ReferenceEquals(cpi.Name, StringConstants.INIT)) + { + throw new VerifyError("Must call initializers using invokespecial"); + } + if (ReferenceEquals(cpi.Name, StringConstants.CLINIT)) + { + throw new VerifyError("Illegal call to internal method"); + } + TypeWrapper[] args = cpi.GetArgTypes(); + for (int j = args.Length - 1; j >= 0; j--) + { + stack.PopType(args[j]); + } + if (invoke == NormalizedByteCode.__invokeinterface) + { + int argcount = args.Length + 1; + for (int j = 0; j < args.Length; j++) + { + if (args[j].IsWidePrimitive) + { + argcount++; + } + } + if (method.Instructions[index].Arg2 != argcount) + { + throw new VerifyError("Inconsistent args size"); + } + } + bool isnew = false; + TypeWrapper thisType; + if (invoke == NormalizedByteCode.__invokestatic) + { + thisType = null; + } + else + { + thisType = SigTypeToClassName(stack.PeekType(), cpi.GetClassType(), wrapper); + if (ReferenceEquals(cpi.Name, StringConstants.INIT)) + { + TypeWrapper type = stack.PopType(); + isnew = VerifierTypeWrapper.IsNew(type); + if ((isnew && ((VerifierTypeWrapper)type).UnderlyingType != cpi.GetClassType()) || + (type == VerifierTypeWrapper.UninitializedThis && cpi.GetClassType() != wrapper.BaseTypeWrapper && cpi.GetClassType() != wrapper) || + (!isnew && type != VerifierTypeWrapper.UninitializedThis)) + { + // TODO oddly enough, Java fails verification for the class without + // even running the constructor, so maybe constructors are always + // verified... + // NOTE when a constructor isn't verifiable, the static initializer + // doesn't run either + throw new VerifyError("Call to wrong initialization method"); + } + } + else + { + if (invoke != NormalizedByteCode.__invokeinterface) + { + TypeWrapper refType = stack.PopObjectType(); + TypeWrapper targetType = cpi.GetClassType(); + if (!VerifierTypeWrapper.IsNullOrUnloadable(refType) && + !targetType.IsUnloadable && + !refType.IsAssignableTo(targetType)) + { + throw new VerifyError("Incompatible object argument for function call"); + } + // for invokespecial we also need to make sure we're calling ourself or a base class + if (invoke == NormalizedByteCode.__invokespecial) + { + if (VerifierTypeWrapper.IsNullOrUnloadable(refType)) + { + // ok + } + else if (refType.IsSubTypeOf(wrapper)) + { + // ok + } + else if (host != null && refType.IsSubTypeOf(host)) + { + // ok + } + else + { + throw new VerifyError("Incompatible target object for invokespecial"); + } + if (targetType.IsUnloadable) + { + // ok + } + else if (wrapper.IsSubTypeOf(targetType)) + { + // ok + } + else if (host != null && host.IsSubTypeOf(targetType)) + { + // ok + } + else + { + throw new VerifyError("Invokespecial cannot call subclass methods"); + } + } + } + else /* __invokeinterface */ + { + // NOTE unlike in the above case, we also allow *any* interface target type + // regardless of whether it is compatible or not, because if it is not compatible + // we want an IncompatibleClassChangeError at runtime + TypeWrapper refType = stack.PopObjectType(); + TypeWrapper targetType = cpi.GetClassType(); + if (!VerifierTypeWrapper.IsNullOrUnloadable(refType) + && !targetType.IsUnloadable + && !refType.IsAssignableTo(targetType) + && !targetType.IsInterface) + { + throw new VerifyError("Incompatible object argument for function call"); + } + } + } + } + } + + private void VerifyInvokeDynamic(int index) + { + StackState stack = new StackState(state[index]); + ClassFile.ConstantPoolItemInvokeDynamic cpi = GetInvokeDynamic(method.Instructions[index].Arg1); + TypeWrapper[] args = cpi.GetArgTypes(); + for (int j = args.Length - 1; j >= 0; j--) + { + stack.PopType(args[j]); + } + } + + private static void OptimizationPass(CodeInfo codeInfo, ClassFile classFile, ClassFile.Method method, UntangledExceptionTable exceptions, TypeWrapper wrapper, ClassLoaderWrapper classLoader) + { + // Optimization pass + if (classLoader.RemoveAsserts) + { + // 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); + ClassFile.Method.Instruction[] instructions = method.Instructions; + for (int i = 0; i < instructions.Length; i++) + { + if (instructions[i].NormalizedOpCode == NormalizedByteCode.__getstatic + && instructions[i + 1].NormalizedOpCode == NormalizedByteCode.__ifne + && instructions[i + 1].TargetIndex > i + && (flags[i + 1] & InstructionFlags.BranchTarget) == 0) + { + var field = classFile.GetFieldref(instructions[i].Arg1).GetField() as ConstantFieldWrapper; + if (field != null && field.FieldTypeWrapper == PrimitiveTypeWrapper.BOOLEAN && (bool)field.GetConstantValue()) + { + // 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); + } + } + } + } + } + } + + private void PatchHardErrorsAndDynamicMemberAccess(TypeWrapper wrapper, MethodWrapper mw) + { + // Now we do another pass to find "hard error" instructions + if (true) + { + ClassFile.Method.Instruction[] instructions = method.Instructions; + for (int i = 0; i < instructions.Length; i++) + { + if (state[i] != null) + { + StackState stack = new StackState(state[i]); + switch (instructions[i].NormalizedOpCode) + { + case NormalizedByteCode.__invokeinterface: + case NormalizedByteCode.__invokespecial: + case NormalizedByteCode.__invokestatic: + case NormalizedByteCode.__invokevirtual: + PatchInvoke(wrapper, ref instructions[i], stack); + break; + case NormalizedByteCode.__getfield: + case NormalizedByteCode.__putfield: + case NormalizedByteCode.__getstatic: + case NormalizedByteCode.__putstatic: + PatchFieldAccess(wrapper, mw, ref instructions[i], stack); + break; + case NormalizedByteCode.__ldc: + switch (classFile.GetConstantPoolConstantType(instructions[i].Arg1)) + { + case ClassFile.ConstantType.Class: + { + TypeWrapper tw = classFile.GetConstantPoolClassType(instructions[i].Arg1); + if (tw.IsUnloadable) + { + ConditionalPatchNoClassDefFoundError(ref instructions[i], tw); + } + break; + } + case ClassFile.ConstantType.MethodType: + { + ClassFile.ConstantPoolItemMethodType cpi = classFile.GetConstantPoolConstantMethodType(instructions[i].Arg1); + TypeWrapper[] args = cpi.GetArgTypes(); + TypeWrapper tw = cpi.GetRetType(); + for (int j = 0; !tw.IsUnloadable && j < args.Length; j++) + { + tw = args[j]; + } + if (tw.IsUnloadable) + { + ConditionalPatchNoClassDefFoundError(ref instructions[i], tw); + } + break; + } + case ClassFile.ConstantType.MethodHandle: + PatchLdcMethodHandle(ref instructions[i]); + break; + } + break; + case NormalizedByteCode.__new: + { + TypeWrapper tw = classFile.GetConstantPoolClassType(instructions[i].Arg1); + if (tw.IsUnloadable) + { + ConditionalPatchNoClassDefFoundError(ref instructions[i], tw); + } + else if (!tw.IsAccessibleFrom(wrapper)) + { + SetHardError(wrapper.GetClassLoader(), ref instructions[i], HardError.IllegalAccessError, "Try to access class {0} from class {1}", tw.Name, wrapper.Name); + } + else if (tw.IsAbstract) + { + SetHardError(wrapper.GetClassLoader(), ref instructions[i], HardError.InstantiationError, "{0}", tw.Name); + } + break; + } + case NormalizedByteCode.__multianewarray: + case NormalizedByteCode.__anewarray: + { + TypeWrapper tw = classFile.GetConstantPoolClassType(instructions[i].Arg1); + if (tw.IsUnloadable) + { + ConditionalPatchNoClassDefFoundError(ref instructions[i], tw); + } + else if (!tw.IsAccessibleFrom(wrapper)) + { + SetHardError(wrapper.GetClassLoader(), ref instructions[i], HardError.IllegalAccessError, "Try to access class {0} from class {1}", tw.Name, wrapper.Name); + } + break; + } + case NormalizedByteCode.__checkcast: + case NormalizedByteCode.__instanceof: + { + TypeWrapper tw = classFile.GetConstantPoolClassType(instructions[i].Arg1); + if (tw.IsUnloadable) + { + // If the type is unloadable, we always generate the dynamic code + // (regardless of ClassLoaderWrapper.DisableDynamicBinding), because at runtime, + // null references should always pass thru without attempting + // to load the type (for Sun compatibility). + } + else if (!tw.IsAccessibleFrom(wrapper)) + { + SetHardError(wrapper.GetClassLoader(), ref instructions[i], HardError.IllegalAccessError, "Try to access class {0} from class {1}", tw.Name, wrapper.Name); + } + break; + } + case NormalizedByteCode.__aaload: + { + stack.PopInt(); + TypeWrapper tw = stack.PopArrayType(); + if (tw.IsUnloadable) + { + ConditionalPatchNoClassDefFoundError(ref instructions[i], tw); + } + break; + } + case NormalizedByteCode.__aastore: + { + stack.PopObjectType(); + stack.PopInt(); + TypeWrapper tw = stack.PopArrayType(); + if (tw.IsUnloadable) + { + ConditionalPatchNoClassDefFoundError(ref instructions[i], tw); + } + break; + } + default: + break; + } + } + } + } + } + + private void PatchLdcMethodHandle(ref ClassFile.Method.Instruction instr) + { + ClassFile.ConstantPoolItemMethodHandle cpi = classFile.GetConstantPoolConstantMethodHandle(instr.Arg1); + if (cpi.GetClassType().IsUnloadable) + { + ConditionalPatchNoClassDefFoundError(ref instr, cpi.GetClassType()); + } + else if (!cpi.GetClassType().IsAccessibleFrom(wrapper)) + { + SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IllegalAccessError, "tried to access class {0} from class {1}", cpi.Class, wrapper.Name); + } + else if (cpi.Kind == ReferenceKind.InvokeVirtual + && cpi.GetClassType() == CoreClasses.java.lang.invoke.MethodHandle.Wrapper + && (cpi.Name == "invoke" || cpi.Name == "invokeExact")) + { + // it's allowed to use ldc to create a MethodHandle invoker + } + else if (cpi.Member == null || cpi.Member.IsStatic != (cpi.Kind == ReferenceKind.GetStatic || cpi.Kind == ReferenceKind.PutStatic || cpi.Kind == ReferenceKind.InvokeStatic)) + { + HardError err; + string msg; + switch (cpi.Kind) + { + case ReferenceKind.GetField: + case ReferenceKind.GetStatic: + case ReferenceKind.PutField: + case ReferenceKind.PutStatic: + err = HardError.NoSuchFieldError; + msg = cpi.Name; + break; + default: + err = HardError.NoSuchMethodError; + msg = cpi.Class + "." + cpi.Name + cpi.Signature; + break; + } + SetHardError(wrapper.GetClassLoader(), ref instr, err, msg, cpi.Class, cpi.Name, SigToString(cpi.Signature)); + } + else if (!cpi.Member.IsAccessibleFrom(cpi.GetClassType(), wrapper, cpi.GetClassType())) + { + if (cpi.Member.IsProtected && wrapper.IsSubTypeOf(cpi.Member.DeclaringType)) + { + // this is allowed, the receiver will be narrowed to current type + } + else + { + SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IllegalAccessException, "member is private: {0}.{1}/{2}/{3}, from {4}", cpi.Class, cpi.Name, SigToString(cpi.Signature), cpi.Kind, wrapper.Name); + } + } + } + + private static string SigToString(string sig) + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + string sep = ""; + int dims = 0; + for (int i = 0; i < sig.Length; i++) + { + if (sig[i] == '(' || sig[i] == ')') + { + sb.Append(sig[i]); + sep = ""; + continue; + } + else if (sig[i] == '[') + { + dims++; + continue; + } + sb.Append(sep); + sep = ","; + switch (sig[i]) + { + case 'V': + sb.Append("void"); + break; + case 'B': + sb.Append("byte"); + break; + case 'Z': + sb.Append("boolean"); + break; + case 'S': + sb.Append("short"); + break; + case 'C': + sb.Append("char"); + break; + case 'I': + sb.Append("int"); + break; + case 'J': + sb.Append("long"); + break; + case 'F': + sb.Append("float"); + break; + case 'D': + sb.Append("double"); + break; + case 'L': + sb.Append(sig, i + 1, sig.IndexOf(';', i + 1) - (i + 1)); + i = sig.IndexOf(';', i + 1); + break; + } + for (; dims != 0; dims--) + { + sb.Append("[]"); + } + } + return sb.ToString(); + } + + internal static InstructionFlags[] ComputePartialReachability(CodeInfo codeInfo, ClassFile.Method.Instruction[] instructions, UntangledExceptionTable exceptions, int initialInstructionIndex, bool skipFaultBlocks) + { + InstructionFlags[] flags = new InstructionFlags[instructions.Length]; + flags[initialInstructionIndex] |= InstructionFlags.Reachable; + UpdatePartialReachability(flags, codeInfo, instructions, exceptions, skipFaultBlocks); + return flags; + } + + private static void UpdatePartialReachability(InstructionFlags[] flags, CodeInfo codeInfo, ClassFile.Method.Instruction[] instructions, UntangledExceptionTable exceptions, bool skipFaultBlocks) + { + bool done = false; + while (!done) + { + done = true; + for (int i = 0; i < instructions.Length; i++) + { + if ((flags[i] & (InstructionFlags.Reachable | InstructionFlags.Processed)) == InstructionFlags.Reachable) + { + done = false; + flags[i] |= InstructionFlags.Processed; + // mark the exception handlers reachable from this instruction + for (int j = 0; j < exceptions.Length; j++) + { + if (exceptions[j].startIndex <= i && i < exceptions[j].endIndex) + { + int idx = exceptions[j].handlerIndex; + if (!skipFaultBlocks || !VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(idx, 0))) + { + flags[idx] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; + } + } + } + MarkSuccessors(instructions, flags, i); + } + } + } + } + + private static void MarkSuccessors(ClassFile.Method.Instruction[] code, InstructionFlags[] flags, int index) + { + switch (ByteCodeMetaData.GetFlowControl(code[index].NormalizedOpCode)) + { + case ByteCodeFlowControl.Switch: + { + for (int i = 0; i < code[index].SwitchEntryCount; i++) + { + flags[code[index].GetSwitchTargetIndex(i)] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; + } + flags[code[index].DefaultTarget] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; + break; + } + case ByteCodeFlowControl.Branch: + flags[code[index].TargetIndex] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; + break; + case ByteCodeFlowControl.CondBranch: + flags[code[index].TargetIndex] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; + flags[index + 1] |= InstructionFlags.Reachable; + break; + case ByteCodeFlowControl.Return: + case ByteCodeFlowControl.Throw: + break; + case ByteCodeFlowControl.Next: + flags[index + 1] |= InstructionFlags.Reachable; + break; + default: + throw new InvalidOperationException(); + } + } + + internal static UntangledExceptionTable UntangleExceptionBlocks(ClassFile classFile, ClassFile.Method method) + { + ClassFile.Method.Instruction[] instructions = method.Instructions; + ExceptionTableEntry[] exceptionTable = method.ExceptionTable; + List ar = new List(exceptionTable); + + // This optimization removes the recursive exception handlers that Java compiler place around + // the exit of a synchronization block to be "safe" in the face of asynchronous exceptions. + // (see http://weblog.ikvm.net/PermaLink.aspx?guid=3af9548e-4905-4557-8809-65a205ce2cd6) + // We can safely remove them since the code we generate for this construct isn't async safe anyway, + // but there is another reason why this optimization may be slightly controversial. In some + // pathological cases it can cause observable differences, where the Sun JVM would spin in an + // infinite loop, but we will throw an exception. However, the perf benefit is large enough to + // warrant this "incompatibility". + // Note that there is also code in the exception handler handling code that detects these bytecode + // sequences to try to compile them into a fault block, instead of an exception handler. + for (int i = 0; i < ar.Count; i++) + { + ExceptionTableEntry ei = ar[i]; + if (ei.startIndex == ei.handlerIndex && ei.catch_type == 0) + { + int index = ei.startIndex; + if (index + 2 < instructions.Length + && ei.endIndex == index + 2 + && instructions[index].NormalizedOpCode == NormalizedByteCode.__aload + && instructions[index + 1].NormalizedOpCode == NormalizedByteCode.__monitorexit + && instructions[index + 2].NormalizedOpCode == NormalizedByteCode.__athrow) + { + // this is the async exception guard that Jikes and the Eclipse Java Compiler produce + ar.RemoveAt(i); + i--; + } + else if (index + 4 < instructions.Length + && ei.endIndex == index + 3 + && instructions[index].NormalizedOpCode == NormalizedByteCode.__astore + && instructions[index + 1].NormalizedOpCode == NormalizedByteCode.__aload + && instructions[index + 2].NormalizedOpCode == NormalizedByteCode.__monitorexit + && instructions[index + 3].NormalizedOpCode == NormalizedByteCode.__aload + && instructions[index + 4].NormalizedOpCode == NormalizedByteCode.__athrow + && instructions[index].NormalizedArg1 == instructions[index + 3].NormalizedArg1) + { + // this is the async exception guard that javac produces + ar.RemoveAt(i); + i--; + } + else if (index + 1 < instructions.Length + && ei.endIndex == index + 1 + && instructions[index].NormalizedOpCode == NormalizedByteCode.__astore) + { + // this is the finally guard that javac produces + ar.RemoveAt(i); + i--; + } + } + } + + // Modern versions of javac split try blocks when the try block contains a return statement. + // Here we merge these exception blocks again, because it allows us to generate more efficient code. + for (int i = 0; i < ar.Count - 1; i++) + { + if (ar[i].endIndex + 1 == ar[i + 1].startIndex + && ar[i].handlerIndex == ar[i + 1].handlerIndex + && ar[i].catch_type == ar[i + 1].catch_type + && IsReturn(instructions[ar[i].endIndex].NormalizedOpCode)) + { + ar[i] = new ExceptionTableEntry(ar[i].startIndex, ar[i + 1].endIndex, ar[i].handlerIndex, ar[i].catch_type, ar[i].ordinal); + ar.RemoveAt(i + 1); + i--; + } + } + + restart: + for (int i = 0; i < ar.Count; i++) + { + ExceptionTableEntry ei = ar[i]; + for (int j = 0; j < ar.Count; j++) + { + ExceptionTableEntry ej = ar[j]; + if (ei.startIndex <= ej.startIndex && ej.startIndex < ei.endIndex) + { + // 0006/test.j + if (ej.endIndex > ei.endIndex) + { + ExceptionTableEntry emi = new ExceptionTableEntry(ej.startIndex, ei.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); + ExceptionTableEntry emj = new ExceptionTableEntry(ej.startIndex, ei.endIndex, ej.handlerIndex, ej.catch_type, ej.ordinal); + ei = new ExceptionTableEntry(ei.startIndex, emi.startIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); + ej = new ExceptionTableEntry(emj.endIndex, ej.endIndex, ej.handlerIndex, ej.catch_type, ej.ordinal); + ar[i] = ei; + ar[j] = ej; + ar.Insert(j, emj); + ar.Insert(i + 1, emi); + goto restart; + } + // 0007/test.j + else if (j > i && ej.endIndex < ei.endIndex) + { + ExceptionTableEntry emi = new ExceptionTableEntry(ej.startIndex, ej.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); + ExceptionTableEntry eei = new ExceptionTableEntry(ej.endIndex, ei.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); + ei = new ExceptionTableEntry(ei.startIndex, emi.startIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); + ar[i] = ei; + ar.Insert(i + 1, eei); + ar.Insert(i + 1, emi); + goto restart; + } + } + } + } + // Split try blocks at branch targets (branches from outside the try block) + restart_split: + for (int i = 0; i < ar.Count; i++) + { + ExceptionTableEntry ei = ar[i]; + int start = ei.startIndex; + int end = ei.endIndex; + for (int j = 0; j < instructions.Length; j++) + { + if (j < start || j >= end) + { + switch (instructions[j].NormalizedOpCode) + { + case NormalizedByteCode.__tableswitch: + case NormalizedByteCode.__lookupswitch: + // start at -1 to have an opportunity to handle the default offset + for (int k = -1; k < instructions[j].SwitchEntryCount; k++) + { + int targetIndex = (k == -1 ? instructions[j].DefaultTarget : instructions[j].GetSwitchTargetIndex(k)); + if (ei.startIndex < targetIndex && targetIndex < ei.endIndex) + { + ExceptionTableEntry en = new ExceptionTableEntry(targetIndex, ei.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); + ei = new ExceptionTableEntry(ei.startIndex, targetIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); + ar[i] = ei; + ar.Insert(i + 1, en); + goto restart_split; + } + } + break; + 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: + { + int targetIndex = instructions[j].Arg1; + if (ei.startIndex < targetIndex && targetIndex < ei.endIndex) + { + ExceptionTableEntry en = new ExceptionTableEntry(targetIndex, ei.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); + ei = new ExceptionTableEntry(ei.startIndex, targetIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); + ar[i] = ei; + ar.Insert(i + 1, en); + goto restart_split; + } + break; + } + } + } + } + } + // exception handlers are also a kind of jump, so we need to split try blocks around handlers as well + for (int i = 0; i < ar.Count; i++) + { + ExceptionTableEntry ei = ar[i]; + for (int j = 0; j < ar.Count; j++) + { + ExceptionTableEntry ej = ar[j]; + if (ei.startIndex < ej.handlerIndex && ej.handlerIndex < ei.endIndex) + { + ExceptionTableEntry en = new ExceptionTableEntry(ej.handlerIndex, ei.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); + ei = new ExceptionTableEntry(ei.startIndex, ej.handlerIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); + ar[i] = ei; + ar.Insert(i + 1, en); + goto restart_split; + } + } + } + // filter out zero length try blocks + for (int i = 0; i < ar.Count; i++) + { + ExceptionTableEntry ei = ar[i]; + if (ei.startIndex == ei.endIndex) + { + ar.RemoveAt(i); + i--; + } + else + { + // exception blocks that only contain harmless instructions (i.e. instructions that will *never* throw an exception) + // are also filtered out (to improve the quality of the generated code) + TypeWrapper exceptionType = ei.catch_type == 0 ? CoreClasses.java.lang.Throwable.Wrapper : classFile.GetConstantPoolClassType(ei.catch_type); + if (exceptionType.IsUnloadable) + { + // we can't remove handlers for unloadable types + } + else if (java_lang_ThreadDeath.IsAssignableTo(exceptionType)) + { + // We only remove exception handlers that could catch ThreadDeath in limited cases, because it can be thrown + // asynchronously (and thus appear on any instruction). This is particularly important to ensure that + // we run finally blocks when a thread is killed. + // Note that even so, we aren't remotely async exception safe. + int start = ei.startIndex; + int end = ei.endIndex; + for (int j = start; j < end; j++) + { + switch (instructions[j].NormalizedOpCode) + { + case NormalizedByteCode.__aload: + case NormalizedByteCode.__iload: + case NormalizedByteCode.__lload: + case NormalizedByteCode.__fload: + case NormalizedByteCode.__dload: + case NormalizedByteCode.__astore: + case NormalizedByteCode.__istore: + case NormalizedByteCode.__lstore: + case NormalizedByteCode.__fstore: + case NormalizedByteCode.__dstore: + break; + case NormalizedByteCode.__dup: + case NormalizedByteCode.__dup_x1: + case NormalizedByteCode.__dup_x2: + case NormalizedByteCode.__dup2: + case NormalizedByteCode.__dup2_x1: + case NormalizedByteCode.__dup2_x2: + case NormalizedByteCode.__pop: + case NormalizedByteCode.__pop2: + break; + case NormalizedByteCode.__return: + case NormalizedByteCode.__areturn: + case NormalizedByteCode.__ireturn: + case NormalizedByteCode.__lreturn: + case NormalizedByteCode.__freturn: + case NormalizedByteCode.__dreturn: + break; + case NormalizedByteCode.__goto: + // if there is a branch that stays inside the block, we should keep the block + if (start <= instructions[j].TargetIndex && instructions[j].TargetIndex < end) + goto next; + break; + default: + goto next; + } + } + ar.RemoveAt(i); + i--; + } + else + { + int start = ei.startIndex; + int end = ei.endIndex; + for (int j = start; j < end; j++) + { + if (ByteCodeMetaData.CanThrowException(instructions[j].NormalizedOpCode)) + { + goto next; + } + } + ar.RemoveAt(i); + i--; + } + } + next:; + } + + ExceptionTableEntry[] exceptions = ar.ToArray(); + Array.Sort(exceptions, new ExceptionSorter()); + + return new UntangledExceptionTable(exceptions); + } + + private static bool IsReturn(NormalizedByteCode bc) + { + return bc == NormalizedByteCode.__return + || bc == NormalizedByteCode.__areturn + || bc == NormalizedByteCode.__dreturn + || bc == NormalizedByteCode.__ireturn + || bc == NormalizedByteCode.__freturn + || bc == NormalizedByteCode.__lreturn; + } + + private static bool AnalyzePotentialFaultBlocks(CodeInfo codeInfo, ClassFile.Method method, UntangledExceptionTable exceptions) + { + ClassFile.Method.Instruction[] code = method.Instructions; + bool changed = false; + bool done = false; + while (!done) + { + done = true; + Stack stack = new Stack(); + ExceptionTableEntry current = new ExceptionTableEntry(0, code.Length, -1, ushort.MaxValue, -1); + stack.Push(current); + for (int i = 0; i < exceptions.Length; i++) + { + while (exceptions[i].startIndex >= current.endIndex) + { + current = stack.Pop(); + } + Debug.Assert(exceptions[i].startIndex >= current.startIndex && exceptions[i].endIndex <= current.endIndex); + if (exceptions[i].catch_type == 0 + && codeInfo.HasState(exceptions[i].handlerIndex) + && VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(exceptions[i].handlerIndex, 0))) + { + InstructionFlags[] flags = MethodAnalyzer.ComputePartialReachability(codeInfo, method.Instructions, exceptions, exceptions[i].handlerIndex, true); + for (int j = 0; j < code.Length; j++) + { + if ((flags[j] & InstructionFlags.Reachable) != 0) + { + switch (code[j].NormalizedOpCode) + { + case NormalizedByteCode.__return: + case NormalizedByteCode.__areturn: + case NormalizedByteCode.__ireturn: + case NormalizedByteCode.__lreturn: + case NormalizedByteCode.__freturn: + case NormalizedByteCode.__dreturn: + goto not_fault_block; + case NormalizedByteCode.__athrow: + for (int k = i + 1; k < exceptions.Length; k++) + { + if (exceptions[k].startIndex <= j && j < exceptions[k].endIndex) + { + goto not_fault_block; + } + } + if (VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(j, 0)) + && codeInfo.GetRawStackTypeWrapper(j, 0) != codeInfo.GetRawStackTypeWrapper(exceptions[i].handlerIndex, 0)) + { + goto not_fault_block; + } + break; + } + if (j < current.startIndex || j >= current.endIndex) + { + goto not_fault_block; + } + else if (exceptions[i].startIndex <= j && j < exceptions[i].endIndex) + { + goto not_fault_block; + } + else + { + continue; + } + not_fault_block: + VerifierTypeWrapper.ClearFaultBlockException(codeInfo.GetRawStackTypeWrapper(exceptions[i].handlerIndex, 0)); + done = false; + changed = true; + break; + } + } + } + stack.Push(current); + current = exceptions[i]; + } + } + return changed; + } + + private static void ConvertFinallyBlocks(CodeInfo codeInfo, ClassFile.Method method, UntangledExceptionTable exceptions) + { + ClassFile.Method.Instruction[] code = method.Instructions; + InstructionFlags[] flags = ComputePartialReachability(codeInfo, code, exceptions, 0, false); + for (int i = 0; i < exceptions.Length; i++) + { + if (exceptions[i].catch_type == 0 + && codeInfo.HasState(exceptions[i].handlerIndex) + && VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(exceptions[i].handlerIndex, 0))) + { + int exit; + if (IsSynchronizedBlockHandler(code, exceptions[i].handlerIndex) + && exceptions[i].endIndex - 2 >= exceptions[i].startIndex + && TryFindSingleTryBlockExit(code, flags, exceptions, new ExceptionTableEntry(exceptions[i].startIndex, exceptions[i].endIndex - 2, exceptions[i].handlerIndex, 0, exceptions[i].ordinal), i, out exit) + && exit == exceptions[i].endIndex - 2 + && (flags[exit + 1] & InstructionFlags.BranchTarget) == 0 + && MatchInstructions(code, exit, exceptions[i].handlerIndex + 1) + && MatchInstructions(code, exit + 1, exceptions[i].handlerIndex + 2) + && MatchExceptionCoverage(exceptions, i, exceptions[i].handlerIndex + 1, exceptions[i].handlerIndex + 3, exit, exit + 2) + && exceptions[i].handlerIndex <= ushort.MaxValue) + { + code[exit].PatchOpCode(NormalizedByteCode.__goto_finally, exceptions[i].endIndex, (short)exceptions[i].handlerIndex); + exceptions.SetFinally(i); + } + else if (TryFindSingleTryBlockExit(code, flags, exceptions, exceptions[i], i, out exit) + // the stack must be empty + && codeInfo.GetStackHeight(exit) == 0 + // the exit code must not be reachable (except from within the try-block), + // because we're going to patch it to jump around the exit code + && !IsReachableFromOutsideTryBlock(codeInfo, code, exceptions, exceptions[i], exit)) + { + int exitHandlerEnd; + int faultHandlerEnd; + if (MatchFinallyBlock(codeInfo, code, exceptions, exceptions[i].handlerIndex, exit, out exitHandlerEnd, out faultHandlerEnd)) + { + if (exit != exitHandlerEnd + && codeInfo.GetStackHeight(exitHandlerEnd) == 0 + && MatchExceptionCoverage(exceptions, -1, exceptions[i].handlerIndex, faultHandlerEnd, exit, exitHandlerEnd)) + { + // We use Arg2 (which is a short) to store the handler in the __goto_finally pseudo-opcode, + // so we can only do that if handlerIndex fits in a short (note that we can use the sign bit too). + if (exceptions[i].handlerIndex <= ushort.MaxValue) + { + code[exit].PatchOpCode(NormalizedByteCode.__goto_finally, exitHandlerEnd, (short)exceptions[i].handlerIndex); + exceptions.SetFinally(i); + } + } + } + } + } + } + } + + private static bool IsSynchronizedBlockHandler(ClassFile.Method.Instruction[] code, int index) + { + return code[index].NormalizedOpCode == NormalizedByteCode.__astore + && code[index + 1].NormalizedOpCode == NormalizedByteCode.__aload + && code[index + 2].NormalizedOpCode == NormalizedByteCode.__monitorexit + && code[index + 3].NormalizedOpCode == NormalizedByteCode.__aload && code[index + 3].Arg1 == code[index].Arg1 + && code[index + 4].NormalizedOpCode == NormalizedByteCode.__athrow; + } + + private static bool MatchExceptionCoverage(UntangledExceptionTable exceptions, int skipException, int startFault, int endFault, int startExit, int endExit) + { + for (int j = 0; j < exceptions.Length; j++) + { + if (j != skipException && ExceptionCovers(exceptions[j], startFault, endFault) != ExceptionCovers(exceptions[j], startExit, endExit)) + { + return false; + } + } + return true; + } + + private static bool ExceptionCovers(ExceptionTableEntry exception, int start, int end) + { + return exception.startIndex < end && exception.endIndex > start; + } + + private static bool MatchFinallyBlock(CodeInfo codeInfo, ClassFile.Method.Instruction[] code, UntangledExceptionTable exceptions, int faultHandler, int exitHandler, out int exitHandlerEnd, out int faultHandlerEnd) + { + exitHandlerEnd = -1; + faultHandlerEnd = -1; + if (code[faultHandler].NormalizedOpCode != NormalizedByteCode.__astore) + { + return false; + } + int startFault = faultHandler; + int faultLocal = code[faultHandler++].NormalizedArg1; + for (; ; ) + { + if (code[faultHandler].NormalizedOpCode == NormalizedByteCode.__aload + && code[faultHandler].NormalizedArg1 == faultLocal + && code[faultHandler + 1].NormalizedOpCode == NormalizedByteCode.__athrow) + { + // make sure that instructions that we haven't covered aren't reachable + InstructionFlags[] flags = ComputePartialReachability(codeInfo, code, exceptions, startFault, false); + for (int i = 0; i < flags.Length; i++) + { + if ((i < startFault || i > faultHandler + 1) && (flags[i] & InstructionFlags.Reachable) != 0) + { + return false; + } + } + exitHandlerEnd = exitHandler; + faultHandlerEnd = faultHandler; + return true; + } + if (!MatchInstructions(code, faultHandler, exitHandler)) + { + return false; + } + faultHandler++; + exitHandler++; + } + } + + private static bool MatchInstructions(ClassFile.Method.Instruction[] code, int i, int j) + { + if (code[i].NormalizedOpCode != code[j].NormalizedOpCode) + { + return false; + } + switch (ByteCodeMetaData.GetFlowControl(code[i].NormalizedOpCode)) + { + case ByteCodeFlowControl.Branch: + case ByteCodeFlowControl.CondBranch: + if (code[i].Arg1 - i != code[j].Arg1 - j) + { + return false; + } + break; + case ByteCodeFlowControl.Switch: + if (code[i].SwitchEntryCount != code[j].SwitchEntryCount) + { + return false; + } + for (int k = 0; k < code[i].SwitchEntryCount; k++) + { + if (code[i].GetSwitchTargetIndex(k) != code[j].GetSwitchTargetIndex(k)) + { + return false; + } + } + if (code[i].DefaultTarget != code[j].DefaultTarget) + { + return false; + } + break; + default: + if (code[i].Arg1 != code[j].Arg1) + { + return false; + } + if (code[i].Arg2 != code[j].Arg2) + { + return false; + } + break; + } + return true; + } + + private static bool IsReachableFromOutsideTryBlock(CodeInfo codeInfo, ClassFile.Method.Instruction[] code, UntangledExceptionTable exceptions, ExceptionTableEntry tryBlock, int instructionIndex) + { + InstructionFlags[] flags = new InstructionFlags[code.Length]; + flags[0] |= InstructionFlags.Reachable; + // We mark the first instruction of the try-block as already processed, so that UpdatePartialReachability will skip the try-block. + // Note that we can do this, because it is not possible to jump into the middle of a try-block (after the exceptions have been untangled). + flags[tryBlock.startIndex] = InstructionFlags.Processed; + // We mark the successor instructions of the instruction we're examinining as reachable, + // to figure out if the code following the handler somehow branches back to it. + MarkSuccessors(code, flags, instructionIndex); + UpdatePartialReachability(flags, codeInfo, code, exceptions, false); + return (flags[instructionIndex] & InstructionFlags.Reachable) != 0; + } + + private static bool TryFindSingleTryBlockExit(ClassFile.Method.Instruction[] code, InstructionFlags[] flags, UntangledExceptionTable exceptions, ExceptionTableEntry exception, int exceptionIndex, out int exit) + { + exit = -1; + bool fail = false; + bool nextIsReachable = false; + for (int i = exception.startIndex; !fail && i < exception.endIndex; i++) + { + if ((flags[i] & InstructionFlags.Reachable) != 0) + { + nextIsReachable = false; + for (int j = 0; j < exceptions.Length; j++) + { + if (j != exceptionIndex && exceptions[j].startIndex >= exception.startIndex && exception.endIndex <= exceptions[j].endIndex) + { + UpdateTryBlockExit(exception, exceptions[j].handlerIndex, ref exit, ref fail); + } + } + switch (ByteCodeMetaData.GetFlowControl(code[i].NormalizedOpCode)) + { + case ByteCodeFlowControl.Switch: + { + for (int j = 0; j < code[i].SwitchEntryCount; j++) + { + UpdateTryBlockExit(exception, code[i].GetSwitchTargetIndex(j), ref exit, ref fail); + } + UpdateTryBlockExit(exception, code[i].DefaultTarget, ref exit, ref fail); + break; + } + case ByteCodeFlowControl.Branch: + UpdateTryBlockExit(exception, code[i].TargetIndex, ref exit, ref fail); + break; + case ByteCodeFlowControl.CondBranch: + UpdateTryBlockExit(exception, code[i].TargetIndex, ref exit, ref fail); + nextIsReachable = true; + break; + case ByteCodeFlowControl.Return: + fail = true; + break; + case ByteCodeFlowControl.Throw: + break; + case ByteCodeFlowControl.Next: + nextIsReachable = true; + break; + default: + throw new InvalidOperationException(); + } + } + } + if (nextIsReachable) + { + UpdateTryBlockExit(exception, exception.endIndex, ref exit, ref fail); + } + return !fail && exit != -1; + } + + private static void UpdateTryBlockExit(ExceptionTableEntry exception, int targetIndex, ref int exitIndex, ref bool fail) + { + if (exception.startIndex <= targetIndex && targetIndex < exception.endIndex) + { + // branch stays inside try block + } + else if (exitIndex == -1) + { + exitIndex = targetIndex; + } + else if (exitIndex != targetIndex) + { + fail = true; + } + } + + private void ConditionalPatchNoClassDefFoundError(ref ClassFile.Method.Instruction instruction, TypeWrapper tw) + { + ClassLoaderWrapper loader = wrapper.GetClassLoader(); + if (loader.DisableDynamicBinding) + { + SetHardError(loader, ref instruction, HardError.NoClassDefFoundError, "{0}", tw.Name); + } + } + + private void SetHardError(ClassLoaderWrapper classLoader, ref ClassFile.Method.Instruction instruction, HardError hardError, string message, params object[] args) + { + string text = string.Format(message, args); +#if IMPORTER + Message msg; + switch (hardError) + { + case HardError.NoClassDefFoundError: + msg = Message.EmittedNoClassDefFoundError; + break; + case HardError.IllegalAccessError: + msg = Message.EmittedIllegalAccessError; + break; + case HardError.InstantiationError: + msg = Message.EmittedIllegalAccessError; + break; + case HardError.IncompatibleClassChangeError: + case HardError.IllegalAccessException: + msg = Message.EmittedIncompatibleClassChangeError; + break; + case HardError.NoSuchFieldError: + msg = Message.EmittedNoSuchFieldError; + break; + case HardError.AbstractMethodError: + msg = Message.EmittedAbstractMethodError; + break; + case HardError.NoSuchMethodError: + msg = Message.EmittedNoSuchMethodError; + break; + case HardError.LinkageError: + msg = Message.EmittedLinkageError; + break; + default: + throw new InvalidOperationException(); + } + classLoader.IssueMessage(msg, classFile.Name + "." + method.Name + method.Signature, text); +#endif + instruction.SetHardError(hardError, AllocErrorMessage(text)); + } + + private void PatchInvoke(TypeWrapper wrapper, ref ClassFile.Method.Instruction instr, StackState stack) + { + ClassFile.ConstantPoolItemMI cpi = GetMethodref(instr.Arg1); + NormalizedByteCode invoke = instr.NormalizedOpCode; + bool isnew = false; + TypeWrapper thisType; + if (invoke == NormalizedByteCode.__invokevirtual + && cpi.Class == "java.lang.invoke.MethodHandle" + && (cpi.Name == "invoke" || cpi.Name == "invokeExact" || cpi.Name == "invokeBasic")) + { + if (cpi.GetArgTypes().Length > 127 && MethodHandleUtil.SlotCount(cpi.GetArgTypes()) > 254) + { + instr.SetHardError(HardError.LinkageError, AllocErrorMessage("bad parameter count")); + return; + } + instr.PatchOpCode(NormalizedByteCode.__methodhandle_invoke); + return; + } + else if (invoke == NormalizedByteCode.__invokestatic + && cpi.Class == "java.lang.invoke.MethodHandle" + && (cpi.Name == "linkToVirtual" || cpi.Name == "linkToStatic" || cpi.Name == "linkToSpecial" || cpi.Name == "linkToInterface") + && CoreClasses.java.lang.invoke.MethodHandle.Wrapper.IsPackageAccessibleFrom(wrapper)) + { + instr.PatchOpCode(NormalizedByteCode.__methodhandle_link); + return; + } + else if (invoke == NormalizedByteCode.__invokestatic) + { + thisType = null; + } + else + { + TypeWrapper[] args = cpi.GetArgTypes(); + for (int j = args.Length - 1; j >= 0; j--) + { + stack.PopType(args[j]); + } + thisType = SigTypeToClassName(stack.PeekType(), cpi.GetClassType(), wrapper); + if (ReferenceEquals(cpi.Name, StringConstants.INIT)) + { + TypeWrapper type = stack.PopType(); + isnew = VerifierTypeWrapper.IsNew(type); + } + } + + if (cpi.GetClassType().IsUnloadable) + { + if (wrapper.GetClassLoader().DisableDynamicBinding) + { + SetHardError(wrapper.GetClassLoader(), ref instr, HardError.NoClassDefFoundError, "{0}", cpi.GetClassType().Name); + } + else + { + switch (invoke) + { + case NormalizedByteCode.__invokeinterface: + instr.PatchOpCode(NormalizedByteCode.__dynamic_invokeinterface); + break; + case NormalizedByteCode.__invokestatic: + instr.PatchOpCode(NormalizedByteCode.__dynamic_invokestatic); + break; + case NormalizedByteCode.__invokevirtual: + instr.PatchOpCode(NormalizedByteCode.__dynamic_invokevirtual); + break; + case NormalizedByteCode.__invokespecial: + if (isnew) + { + instr.PatchOpCode(NormalizedByteCode.__dynamic_invokespecial); + } + else + { + throw new VerifyError("Invokespecial cannot call subclass methods"); + } + break; + default: + throw new InvalidOperationException(); + } + } + } + else if (invoke == NormalizedByteCode.__invokeinterface && !cpi.GetClassType().IsInterface) + { + SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IncompatibleClassChangeError, "invokeinterface on non-interface"); + } + else if (cpi.GetClassType().IsInterface && invoke != NormalizedByteCode.__invokeinterface && ((invoke != NormalizedByteCode.__invokestatic && invoke != NormalizedByteCode.__invokespecial) || classFile.MajorVersion < 52)) + { + SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IncompatibleClassChangeError, + classFile.MajorVersion < 52 + ? "interface method must be invoked using invokeinterface" + : "interface method must be invoked using invokeinterface, invokespecial or invokestatic"); + } + else + { + MethodWrapper targetMethod = invoke == NormalizedByteCode.__invokespecial ? cpi.GetMethodForInvokespecial() : cpi.GetMethod(); + if (targetMethod != null) + { + string errmsg = CheckLoaderConstraints(cpi, targetMethod); + if (errmsg != null) + { + SetHardError(wrapper.GetClassLoader(), ref instr, HardError.LinkageError, "{0}", errmsg); + } + else if (targetMethod.IsStatic == (invoke == NormalizedByteCode.__invokestatic)) + { + if (targetMethod.IsAbstract && invoke == NormalizedByteCode.__invokespecial && (targetMethod.GetMethod() == null || targetMethod.GetMethod().IsAbstract)) + { + SetHardError(wrapper.GetClassLoader(), ref instr, HardError.AbstractMethodError, "{0}.{1}{2}", cpi.Class, cpi.Name, cpi.Signature); + } + else if (invoke == NormalizedByteCode.__invokeinterface && targetMethod.IsPrivate) + { + SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IncompatibleClassChangeError, "private interface method requires invokespecial, not invokeinterface: method {0}.{1}{2}", cpi.Class, cpi.Name, cpi.Signature); + } + else if (targetMethod.IsAccessibleFrom(cpi.GetClassType(), wrapper, thisType)) + { + return; + } + else if (host != null && targetMethod.IsAccessibleFrom(cpi.GetClassType(), host, thisType)) + { + switch (invoke) + { + case NormalizedByteCode.__invokespecial: + instr.PatchOpCode(NormalizedByteCode.__privileged_invokespecial); + break; + case NormalizedByteCode.__invokestatic: + instr.PatchOpCode(NormalizedByteCode.__privileged_invokestatic); + break; + case NormalizedByteCode.__invokevirtual: + instr.PatchOpCode(NormalizedByteCode.__privileged_invokevirtual); + break; + default: + throw new InvalidOperationException(); + } + return; + } + else + { + // NOTE special case for incorrect invocation of Object.clone(), because this could mean + // we're calling clone() on an array + // (bug in javac, see http://developer.java.sun.com/developer/bugParade/bugs/4329886.html) + if (cpi.GetClassType() == CoreClasses.java.lang.Object.Wrapper + && thisType.IsArray + && ReferenceEquals(cpi.Name, StringConstants.CLONE)) + { + // Patch the instruction, so that the compiler doesn't need to do this test again. + instr.PatchOpCode(NormalizedByteCode.__clone_array); + return; + } + SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IllegalAccessError, "tried to access method {0}.{1}{2} from class {3}", ToSlash(targetMethod.DeclaringType.Name), cpi.Name, ToSlash(cpi.Signature), ToSlash(wrapper.Name)); + } + } + else + { + SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IncompatibleClassChangeError, "static call to non-static method (or v.v.)"); + } + } + else + { + SetHardError(wrapper.GetClassLoader(), ref instr, HardError.NoSuchMethodError, "{0}.{1}{2}", cpi.Class, cpi.Name, cpi.Signature); + } + } + } + + private static string ToSlash(string str) + { + return str.Replace('.', '/'); + } + + private void PatchFieldAccess(TypeWrapper wrapper, MethodWrapper mw, ref ClassFile.Method.Instruction instr, StackState stack) + { + ClassFile.ConstantPoolItemFieldref cpi = classFile.GetFieldref(instr.Arg1); + bool isStatic; + bool write; + TypeWrapper thisType; + switch (instr.NormalizedOpCode) + { + case NormalizedByteCode.__getfield: + isStatic = false; + write = false; + thisType = SigTypeToClassName(stack.PopObjectType(GetFieldref(instr.Arg1).GetClassType()), cpi.GetClassType(), wrapper); + break; + case NormalizedByteCode.__putfield: + stack.PopType(GetFieldref(instr.Arg1).GetFieldType()); + isStatic = false; + write = true; + // putfield is allowed to access the unintialized this + if (stack.PeekType() == VerifierTypeWrapper.UninitializedThis + && wrapper.IsAssignableTo(GetFieldref(instr.Arg1).GetClassType())) + { + thisType = wrapper; + } + else + { + thisType = SigTypeToClassName(stack.PopObjectType(GetFieldref(instr.Arg1).GetClassType()), cpi.GetClassType(), wrapper); + } + break; + case NormalizedByteCode.__getstatic: + isStatic = true; + write = false; + thisType = null; + break; + case NormalizedByteCode.__putstatic: + // special support for when we're being called from IsSideEffectFreeStaticInitializer + if (mw == null) + { + switch (GetFieldref(instr.Arg1).Signature[0]) + { + case 'B': + case 'Z': + case 'C': + case 'S': + case 'I': + stack.PopInt(); + break; + case 'F': + stack.PopFloat(); + break; + case 'D': + stack.PopDouble(); + break; + case 'J': + stack.PopLong(); + break; + case 'L': + case '[': + if (stack.PopAnyType() != VerifierTypeWrapper.Null) + { + throw new VerifyError(); + } + break; + default: + throw new InvalidOperationException(); + } + } + else + { + stack.PopType(GetFieldref(instr.Arg1).GetFieldType()); + } + isStatic = true; + write = true; + thisType = null; + break; + default: + throw new InvalidOperationException(); + } + if (mw == null) + { + // We're being called from IsSideEffectFreeStaticInitializer, + // no further checks are possible (nor needed). + } + else if (cpi.GetClassType().IsUnloadable) + { + if (wrapper.GetClassLoader().DisableDynamicBinding) + { + SetHardError(wrapper.GetClassLoader(), ref instr, HardError.NoClassDefFoundError, "{0}", cpi.GetClassType().Name); + } + else + { + switch (instr.NormalizedOpCode) + { + case NormalizedByteCode.__getstatic: + instr.PatchOpCode(NormalizedByteCode.__dynamic_getstatic); + break; + case NormalizedByteCode.__putstatic: + instr.PatchOpCode(NormalizedByteCode.__dynamic_putstatic); + break; + case NormalizedByteCode.__getfield: + instr.PatchOpCode(NormalizedByteCode.__dynamic_getfield); + break; + case NormalizedByteCode.__putfield: + instr.PatchOpCode(NormalizedByteCode.__dynamic_putfield); + break; + default: + throw new InvalidOperationException(); + } + } + return; + } + else + { + FieldWrapper field = cpi.GetField(); + if (field == null) + { + SetHardError(wrapper.GetClassLoader(), ref instr, HardError.NoSuchFieldError, "{0}.{1}", cpi.Class, cpi.Name); + return; + } + if (false && cpi.GetFieldType() != field.FieldTypeWrapper && !cpi.GetFieldType().IsUnloadable & !field.FieldTypeWrapper.IsUnloadable) + { +#if IMPORTER + StaticCompiler.LinkageError("Field \"{2}.{3}\" is of type \"{0}\" instead of type \"{1}\" as expected by \"{4}\"", field.FieldTypeWrapper, cpi.GetFieldType(), cpi.GetClassType().Name, cpi.Name, wrapper.Name); +#endif + SetHardError(wrapper.GetClassLoader(), ref instr, HardError.LinkageError, "Loader constraints violated: {0}.{1}", field.DeclaringType.Name, field.Name); + return; + } + if (field.IsStatic != isStatic) + { + SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IncompatibleClassChangeError, "Static field access to non-static field (or v.v.)"); + return; + } + if (!field.IsAccessibleFrom(cpi.GetClassType(), wrapper, thisType)) + { + SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IllegalAccessError, "Try to access field {0}.{1} from class {2}", field.DeclaringType.Name, field.Name, wrapper.Name); + return; + } + // are we trying to mutate a final field? (they are read-only from outside of the defining class) + if (write && field.IsFinal + && ((isStatic ? wrapper != cpi.GetClassType() : wrapper != thisType) || (wrapper.GetClassLoader().StrictFinalFieldSemantics && (isStatic ? (mw != null && mw.Name != "") : (mw == null || mw.Name != ""))))) + { + SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IllegalAccessError, "Field {0}.{1} is final", field.DeclaringType.Name, field.Name); + return; + } + } + } + + // TODO this method should have a better name + private TypeWrapper SigTypeToClassName(TypeWrapper type, TypeWrapper nullType, TypeWrapper wrapper) + { + if (type == VerifierTypeWrapper.UninitializedThis) + { + return wrapper; + } + else if (VerifierTypeWrapper.IsNew(type)) + { + return ((VerifierTypeWrapper)type).UnderlyingType; + } + else if (type == VerifierTypeWrapper.Null) + { + return nullType; + } + else + { + return type; + } + } + + private int AllocErrorMessage(string message) + { + if (errorMessages == null) + { + errorMessages = new List(); + } + int index = errorMessages.Count; + errorMessages.Add(message); + return index; + } + + private string CheckLoaderConstraints(ClassFile.ConstantPoolItemMI cpi, MethodWrapper mw) + { +#if NETFRAMEWORK + if (cpi.GetRetType() != mw.ReturnType && !cpi.GetRetType().IsUnloadable && !mw.ReturnType.IsUnloadable) +#else + if (cpi.GetRetType() != mw.ReturnType && cpi.GetRetType().Name != mw.ReturnType.Name && !cpi.GetRetType().IsUnloadable && !mw.ReturnType.IsUnloadable) +#endif + { +#if IMPORTER + StaticCompiler.LinkageError("Method \"{2}.{3}{4}\" has a return type \"{0}\" instead of type \"{1}\" as expected by \"{5}\"", mw.ReturnType, cpi.GetRetType(), cpi.GetClassType().Name, cpi.Name, cpi.Signature, classFile.Name); +#endif + return "Loader constraints violated (return type): " + mw.DeclaringType.Name + "." + mw.Name + mw.Signature; + } + TypeWrapper[] here = cpi.GetArgTypes(); + TypeWrapper[] there = mw.GetParameters(); + for (int i = 0; i < here.Length; i++) + { +#if NETFRAMEWORK + if (here[i] != there[i] && !here[i].IsUnloadable && !there[i].IsUnloadable) +#else + if (here[i] != there[i] && here[i].Name != there[i].Name && !here[i].IsUnloadable && !there[i].IsUnloadable) +#endif + { +#if IMPORTER + StaticCompiler.LinkageError("Method \"{2}.{3}{4}\" has a argument type \"{0}\" instead of type \"{1}\" as expected by \"{5}\"", there[i], here[i], cpi.GetClassType().Name, cpi.Name, cpi.Signature, classFile.Name); +#endif + return "Loader constraints violated (arg " + i + "): " + mw.DeclaringType.Name + "." + mw.Name + mw.Signature; + } + } + return null; + } + + private ClassFile.ConstantPoolItemInvokeDynamic GetInvokeDynamic(int index) + { + try + { + ClassFile.ConstantPoolItemInvokeDynamic item = classFile.GetInvokeDynamic(index); + if (item != null) + { + return item; + } + } + catch (InvalidCastException) + { + } + catch (IndexOutOfRangeException) + { + } + throw new VerifyError("Illegal constant pool index"); + } + + private ClassFile.ConstantPoolItemMI GetMethodref(int index) + { + try + { + ClassFile.ConstantPoolItemMI item = classFile.GetMethodref(index); + if (item != null) + { + return item; + } + } + catch (InvalidCastException) + { + } + catch (IndexOutOfRangeException) + { + } + throw new VerifyError("Illegal constant pool index"); + } + + private ClassFile.ConstantPoolItemFieldref GetFieldref(int index) + { + try + { + ClassFile.ConstantPoolItemFieldref item = classFile.GetFieldref(index); + if (item != null) + { + return item; + } + } + catch (InvalidCastException) + { + } + catch (IndexOutOfRangeException) + { + } + throw new VerifyError("Illegal constant pool index"); + } + + private ClassFile.ConstantType GetConstantPoolConstantType(int index) + { + try + { + return classFile.GetConstantPoolConstantType(index); + } + catch (IndexOutOfRangeException) + { + // constant pool index out of range + } + catch (InvalidOperationException) + { + // specified constant pool entry doesn't contain a constant + } + catch (NullReferenceException) + { + // specified constant pool entry is empty (entry 0 or the filler following a wide entry) + } + throw new VerifyError("Illegal constant pool index"); + } + + private TypeWrapper GetConstantPoolClassType(int index) + { + try + { + return classFile.GetConstantPoolClassType(index); + } + catch (InvalidCastException) + { + } + catch (IndexOutOfRangeException) + { + } + catch (NullReferenceException) + { + } + throw new VerifyError("Illegal constant pool index"); + } + + internal void ClearFaultBlockException(int instructionIndex) + { + Debug.Assert(state[instructionIndex].GetStackHeight() == 1); + state[instructionIndex].ClearFaultBlockException(); + } + + private static void DumpMethod(CodeInfo codeInfo, ClassFile.Method method, UntangledExceptionTable exceptions) + { + ClassFile.Method.Instruction[] code = method.Instructions; + InstructionFlags[] flags = ComputePartialReachability(codeInfo, code, exceptions, 0, false); + for (int i = 0; i < code.Length; i++) + { + bool label = (flags[i] & InstructionFlags.BranchTarget) != 0; + if (!label) + { + for (int j = 0; j < exceptions.Length; j++) + { + if (exceptions[j].startIndex == i + || exceptions[j].endIndex == i + || exceptions[j].handlerIndex == i) + { + label = true; + break; + } + } + } + if (label) + { + Console.WriteLine("label{0}:", i); + } + if ((flags[i] & InstructionFlags.Reachable) != 0) + { + Console.Write(" {1}", i, code[i].NormalizedOpCode.ToString().Substring(2)); + switch (ByteCodeMetaData.GetFlowControl(code[i].NormalizedOpCode)) + { + case ByteCodeFlowControl.Branch: + case ByteCodeFlowControl.CondBranch: + Console.Write(" label{0}", code[i].Arg1); + break; + } + switch (code[i].NormalizedOpCode) + { + case NormalizedByteCode.__iload: + case NormalizedByteCode.__lload: + case NormalizedByteCode.__fload: + case NormalizedByteCode.__dload: + case NormalizedByteCode.__aload: + case NormalizedByteCode.__istore: + case NormalizedByteCode.__lstore: + case NormalizedByteCode.__fstore: + case NormalizedByteCode.__dstore: + case NormalizedByteCode.__astore: + case NormalizedByteCode.__iconst: + Console.Write(" {0}", code[i].Arg1); + break; + case NormalizedByteCode.__ldc: + case NormalizedByteCode.__ldc_nothrow: + case NormalizedByteCode.__getfield: + case NormalizedByteCode.__getstatic: + case NormalizedByteCode.__putfield: + case NormalizedByteCode.__putstatic: + case NormalizedByteCode.__invokeinterface: + case NormalizedByteCode.__invokespecial: + case NormalizedByteCode.__invokestatic: + case NormalizedByteCode.__invokevirtual: + case NormalizedByteCode.__new: + Console.Write(" #{0}", code[i].Arg1); + break; + } + Console.WriteLine(); + } + } + for (int i = 0; i < exceptions.Length; i++) + { + Console.WriteLine(".catch #{0} from label{1} to label{2} using label{3}", exceptions[i].catch_type, exceptions[i].startIndex, exceptions[i].endIndex, exceptions[i].handlerIndex); + } + } + } + +} diff --git a/src/IKVM.Runtime/MethodHandleUtil.compiler.cs b/src/IKVM.Runtime/MethodHandleUtil.compiler.cs index 0545289ae7..09046e0321 100644 --- a/src/IKVM.Runtime/MethodHandleUtil.compiler.cs +++ b/src/IKVM.Runtime/MethodHandleUtil.compiler.cs @@ -3,101 +3,104 @@ #if IMPORTER using IKVM.Reflection; using IKVM.Reflection.Emit; + using Type = IKVM.Reflection.Type; #else using System.Reflection; using System.Reflection.Emit; #endif -using IKVM.Internal; - -static partial class MethodHandleUtil +namespace IKVM.Runtime { - internal static void EmitCallDelegateInvokeMethod(CodeEmitter ilgen, Type delegateType) + static partial class MethodHandleUtil { - if (delegateType.IsGenericType) + + internal static void EmitCallDelegateInvokeMethod(CodeEmitter ilgen, Type delegateType) { - // MONOBUG we don't look at the invoke method directly here, because Mono doesn't support GetParameters() on a builder instantiation - Type[] typeArgs = delegateType.GetGenericArguments(); - if (IsPackedArgsContainer(typeArgs[typeArgs.Length - 1])) - { - WrapArgs(ilgen, typeArgs[typeArgs.Length - 1]); - } - else if (typeArgs.Length > 2 && IsPackedArgsContainer(typeArgs[typeArgs.Length - 2])) + if (delegateType.IsGenericType) { - WrapArgs(ilgen, typeArgs[typeArgs.Length - 2]); + // MONOBUG we don't look at the invoke method directly here, because Mono doesn't support GetParameters() on a builder instantiation + Type[] typeArgs = delegateType.GetGenericArguments(); + if (IsPackedArgsContainer(typeArgs[typeArgs.Length - 1])) + { + WrapArgs(ilgen, typeArgs[typeArgs.Length - 1]); + } + else if (typeArgs.Length > 2 && IsPackedArgsContainer(typeArgs[typeArgs.Length - 2])) + { + WrapArgs(ilgen, typeArgs[typeArgs.Length - 2]); + } } + ilgen.Emit(OpCodes.Callvirt, GetDelegateInvokeMethod(delegateType)); } - ilgen.Emit(OpCodes.Callvirt, GetDelegateInvokeMethod(delegateType)); - } - private static void WrapArgs(CodeEmitter ilgen, Type type) - { - Type last = type.GetGenericArguments()[MaxArity - 1]; - if (IsPackedArgsContainer(last)) + private static void WrapArgs(CodeEmitter ilgen, Type type) { - WrapArgs(ilgen, last); + Type last = type.GetGenericArguments()[MaxArity - 1]; + if (IsPackedArgsContainer(last)) + { + WrapArgs(ilgen, last); + } + ilgen.Emit(OpCodes.Newobj, GetDelegateOrPackedArgsConstructor(type)); } - ilgen.Emit(OpCodes.Newobj, GetDelegateOrPackedArgsConstructor(type)); - } - internal static MethodInfo GetDelegateInvokeMethod(Type delegateType) - { - if (ReflectUtil.ContainsTypeBuilder(delegateType)) - { - return TypeBuilder.GetMethod(delegateType, delegateType.GetGenericTypeDefinition().GetMethod("Invoke")); - } - else + internal static MethodInfo GetDelegateInvokeMethod(Type delegateType) { - return delegateType.GetMethod("Invoke"); + if (ReflectUtil.ContainsTypeBuilder(delegateType)) + { + return TypeBuilder.GetMethod(delegateType, delegateType.GetGenericTypeDefinition().GetMethod("Invoke")); + } + else + { + return delegateType.GetMethod("Invoke"); + } } - } - internal static ConstructorInfo GetDelegateConstructor(Type delegateType) - { - return GetDelegateOrPackedArgsConstructor(delegateType); - } - - private static ConstructorInfo GetDelegateOrPackedArgsConstructor(Type type) - { - if (ReflectUtil.ContainsTypeBuilder(type)) + internal static ConstructorInfo GetDelegateConstructor(Type delegateType) { - return TypeBuilder.GetConstructor(type, type.GetGenericTypeDefinition().GetConstructors()[0]); + return GetDelegateOrPackedArgsConstructor(delegateType); } - else - { - return type.GetConstructors()[0]; - } - } - // for delegate types used for "ldc " we don't want ghost arrays to be erased - internal static Type CreateDelegateTypeForLoadConstant(TypeWrapper[] args, TypeWrapper ret) - { - Type[] typeArgs = new Type[args.Length]; - for (int i = 0; i < args.Length; i++) + private static ConstructorInfo GetDelegateOrPackedArgsConstructor(Type type) { - typeArgs[i] = TypeWrapperToTypeForLoadConstant(args[i]); + if (ReflectUtil.ContainsTypeBuilder(type)) + { + return TypeBuilder.GetConstructor(type, type.GetGenericTypeDefinition().GetConstructors()[0]); + } + else + { + return type.GetConstructors()[0]; + } } - return CreateDelegateType(typeArgs, TypeWrapperToTypeForLoadConstant(ret)); - } - private static Type TypeWrapperToTypeForLoadConstant(TypeWrapper tw) - { - if (tw.IsGhostArray) + // for delegate types used for "ldc " we don't want ghost arrays to be erased + internal static Type CreateDelegateTypeForLoadConstant(TypeWrapper[] args, TypeWrapper ret) { - int dims = tw.ArrayRank; - while (tw.IsArray) + Type[] typeArgs = new Type[args.Length]; + for (int i = 0; i < args.Length; i++) { - tw = tw.ElementTypeWrapper; + typeArgs[i] = TypeWrapperToTypeForLoadConstant(args[i]); } - return ArrayTypeWrapper.MakeArrayType(tw.TypeAsSignatureType, dims); + return CreateDelegateType(typeArgs, TypeWrapperToTypeForLoadConstant(ret)); } - else + + private static Type TypeWrapperToTypeForLoadConstant(TypeWrapper tw) { - return tw.TypeAsSignatureType; + if (tw.IsGhostArray) + { + int dims = tw.ArrayRank; + while (tw.IsArray) + { + tw = tw.ElementTypeWrapper; + } + return ArrayTypeWrapper.MakeArrayType(tw.TypeAsSignatureType, dims); + } + else + { + return tw.TypeAsSignatureType; + } } + } } - diff --git a/src/IKVM.Runtime/MethodHandleUtil.jniexport.cs b/src/IKVM.Runtime/MethodHandleUtil.jniexport.cs index ac172202e3..8eb6f88f29 100644 --- a/src/IKVM.Runtime/MethodHandleUtil.jniexport.cs +++ b/src/IKVM.Runtime/MethodHandleUtil.jniexport.cs @@ -21,320 +21,321 @@ Jeroen Frijters jeroen@frijters.net */ -#if !IMPORTER +#if IMPORTER == false using System; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; -using IKVM.Internal; -using IKVM.Runtime; - -static partial class MethodHandleUtil +namespace IKVM.Runtime { - internal static Type GetMemberWrapperDelegateType(global::java.lang.invoke.MethodType type) + static partial class MethodHandleUtil { + + internal static Type GetMemberWrapperDelegateType(global::java.lang.invoke.MethodType type) + { #if FIRST_PASS - return null; + throw new NotImplementedException(); #else - return GetDelegateTypeForInvokeExact(type.basicType()); + return GetDelegateTypeForInvokeExact(type.basicType()); #endif - } - -#if !FIRST_PASS - private static Type CreateMethodHandleDelegateType(java.lang.invoke.MethodType type) - { - TypeWrapper[] args = new TypeWrapper[type.parameterCount()]; - for (int i = 0; i < args.Length; i++) - { - args[i] = TypeWrapper.FromClass(type.parameterType(i)); - args[i].Finish(); - } - TypeWrapper ret = TypeWrapper.FromClass(type.returnType()); - ret.Finish(); - return CreateMethodHandleDelegateType(args, ret); - } - - private static Type[] GetParameterTypes(MethodBase mb) - { - ParameterInfo[] pi = mb.GetParameters(); - Type[] args = new Type[pi.Length]; - for (int i = 0; i < args.Length; i++) - { - args[i] = pi[i].ParameterType; } - return args; - } - internal static Type[] GetParameterTypes(Type thisType, MethodBase mb) - { - ParameterInfo[] pi = mb.GetParameters(); - Type[] args = new Type[pi.Length + 1]; - args[0] = thisType; - for (int i = 1; i < args.Length; i++) - { - args[i] = pi[i - 1].ParameterType; - } - return args; - } +#if FIRST_PASS == false - internal static java.lang.invoke.MethodType GetDelegateMethodType(Type type) - { - java.lang.Class[] types; - MethodInfo mi = GetDelegateInvokeMethod(type); - ParameterInfo[] pi = mi.GetParameters(); - if (pi.Length > 0 && IsPackedArgsContainer(pi[pi.Length - 1].ParameterType)) + private static Type CreateMethodHandleDelegateType(java.lang.invoke.MethodType type) { - System.Collections.Generic.List list = new System.Collections.Generic.List(); - for (int i = 0; i < pi.Length - 1; i++) - { - list.Add(ClassLoaderWrapper.GetWrapperFromType(pi[i].ParameterType).ClassObject); - } - Type[] args = pi[pi.Length - 1].ParameterType.GetGenericArguments(); - while (IsPackedArgsContainer(args[args.Length - 1])) - { - for (int i = 0; i < args.Length - 1; i++) - { - list.Add(ClassLoaderWrapper.GetWrapperFromType(args[i]).ClassObject); - } - args = args[args.Length - 1].GetGenericArguments(); - } + TypeWrapper[] args = new TypeWrapper[type.parameterCount()]; for (int i = 0; i < args.Length; i++) { - list.Add(ClassLoaderWrapper.GetWrapperFromType(args[i]).ClassObject); + args[i] = TypeWrapper.FromClass(type.parameterType(i)); + args[i].Finish(); } - types = list.ToArray(); + TypeWrapper ret = TypeWrapper.FromClass(type.returnType()); + ret.Finish(); + return CreateMethodHandleDelegateType(args, ret); } - else + + private static Type[] GetParameterTypes(MethodBase mb) { - types = new java.lang.Class[pi.Length]; - for (int i = 0; i < types.Length; i++) + ParameterInfo[] pi = mb.GetParameters(); + Type[] args = new Type[pi.Length]; + for (int i = 0; i < args.Length; i++) { - types[i] = ClassLoaderWrapper.GetWrapperFromType(pi[i].ParameterType).ClassObject; + args[i] = pi[i].ParameterType; } + return args; } - return java.lang.invoke.MethodType.methodType(ClassLoaderWrapper.GetWrapperFromType(mi.ReturnType).ClassObject, types); - } - internal sealed class DynamicMethodBuilder - { - private readonly java.lang.invoke.MethodType type; - private readonly int firstArg; - private readonly Type delegateType; - private readonly object firstBoundValue; - private readonly object secondBoundValue; - private readonly Type container; - private readonly DynamicMethod dm; - private readonly CodeEmitter ilgen; - private readonly Type packedArgType; - private readonly int packedArgPos; - - sealed class Container + internal static Type[] GetParameterTypes(Type thisType, MethodBase mb) { - public T1 target; - public T2 value; - - public Container(T1 target, T2 value) + ParameterInfo[] pi = mb.GetParameters(); + Type[] args = new Type[pi.Length + 1]; + args[0] = thisType; + for (int i = 1; i < args.Length; i++) { - this.target = target; - this.value = value; + args[i] = pi[i - 1].ParameterType; } + return args; } - private DynamicMethodBuilder(string name, java.lang.invoke.MethodType type, Type container, object target, object value, Type owner, bool useBasicTypes) + internal static java.lang.invoke.MethodType GetDelegateMethodType(Type type) { - this.type = type; - this.delegateType = useBasicTypes ? GetMemberWrapperDelegateType(type) : GetDelegateTypeForInvokeExact(type); - this.firstBoundValue = target; - this.secondBoundValue = value; - this.container = container; - MethodInfo mi = GetDelegateInvokeMethod(delegateType); - Type[] paramTypes; - if (container != null) - { - this.firstArg = 1; - paramTypes = GetParameterTypes(container, mi); - } - else if (target != null) - { - this.firstArg = 1; - paramTypes = GetParameterTypes(target.GetType(), mi); - } - else - { - paramTypes = GetParameterTypes(mi); - } - if (!ReflectUtil.CanOwnDynamicMethod(owner)) - { - owner = typeof(DynamicMethodBuilder); - } - this.dm = new DynamicMethod(name, mi.ReturnType, paramTypes, owner, true); - this.ilgen = CodeEmitter.Create(dm); - - if (type.parameterCount() > MaxArity) + java.lang.Class[] types; + MethodInfo mi = GetDelegateInvokeMethod(type); + ParameterInfo[] pi = mi.GetParameters(); + if (pi.Length > 0 && IsPackedArgsContainer(pi[pi.Length - 1].ParameterType)) { - ParameterInfo[] pi = mi.GetParameters(); - this.packedArgType = pi[pi.Length - 1].ParameterType; - this.packedArgPos = pi.Length - 1 + firstArg; + System.Collections.Generic.List list = new System.Collections.Generic.List(); + for (int i = 0; i < pi.Length - 1; i++) + { + list.Add(ClassLoaderWrapper.GetWrapperFromType(pi[i].ParameterType).ClassObject); + } + Type[] args = pi[pi.Length - 1].ParameterType.GetGenericArguments(); + while (IsPackedArgsContainer(args[args.Length - 1])) + { + for (int i = 0; i < args.Length - 1; i++) + { + list.Add(ClassLoaderWrapper.GetWrapperFromType(args[i]).ClassObject); + } + args = args[args.Length - 1].GetGenericArguments(); + } + for (int i = 0; i < args.Length; i++) + { + list.Add(ClassLoaderWrapper.GetWrapperFromType(args[i]).ClassObject); + } + types = list.ToArray(); } else { - this.packedArgPos = Int32.MaxValue; + types = new java.lang.Class[pi.Length]; + for (int i = 0; i < types.Length; i++) + { + types[i] = ClassLoaderWrapper.GetWrapperFromType(pi[i].ParameterType).ClassObject; + } } + return java.lang.invoke.MethodType.methodType(ClassLoaderWrapper.GetWrapperFromType(mi.ReturnType).ClassObject, types); } - internal static Delegate CreateVoidAdapter(global::java.lang.invoke.MethodType type) + internal sealed class DynamicMethodBuilder { - DynamicMethodBuilder dm = new DynamicMethodBuilder("VoidAdapter", type.changeReturnType(global::java.lang.Void.TYPE), null, null, null, null, true); - Type targetDelegateType = GetMemberWrapperDelegateType(type); - dm.Ldarg(0); - dm.EmitCheckcast(CoreClasses.java.lang.invoke.MethodHandle.Wrapper); - dm.ilgen.Emit(OpCodes.Ldfld, typeof(global::java.lang.invoke.MethodHandle).GetField("form", BindingFlags.Instance | BindingFlags.NonPublic)); - dm.ilgen.Emit(OpCodes.Ldfld, typeof(global::java.lang.invoke.LambdaForm).GetField("vmentry", BindingFlags.Instance | BindingFlags.NonPublic)); - dm.ilgen.Emit(OpCodes.Ldfld, typeof(global::java.lang.invoke.MemberName).GetField("vmtarget", BindingFlags.Instance | BindingFlags.NonPublic)); - dm.ilgen.Emit(OpCodes.Castclass, targetDelegateType); - for (int i = 0; i < type.parameterCount(); i++) - { - dm.Ldarg(i); - } - dm.CallDelegate(targetDelegateType); - dm.ilgen.Emit(OpCodes.Pop); - dm.Ret(); - return dm.CreateDelegate(); - } + private readonly java.lang.invoke.MethodType type; + private readonly int firstArg; + private readonly Type delegateType; + private readonly object firstBoundValue; + private readonly object secondBoundValue; + private readonly Type container; + private readonly DynamicMethod dm; + private readonly CodeEmitter ilgen; + private readonly Type packedArgType; + private readonly int packedArgPos; - internal static DynamicMethod CreateInvokeExact(global::java.lang.invoke.MethodType type) - { - FinishTypes(type); - DynamicMethodBuilder dm = new DynamicMethodBuilder("InvokeExact", type, typeof(java.lang.invoke.MethodHandle), null, null, null, false); - Type targetDelegateType = GetMemberWrapperDelegateType(type.insertParameterTypes(0, CoreClasses.java.lang.invoke.MethodHandle.Wrapper.ClassObject)); - dm.ilgen.Emit(OpCodes.Ldarg_0); - dm.ilgen.Emit(OpCodes.Ldfld, typeof(global::java.lang.invoke.MethodHandle).GetField("form", BindingFlags.Instance | BindingFlags.NonPublic)); - dm.ilgen.Emit(OpCodes.Ldfld, typeof(global::java.lang.invoke.LambdaForm).GetField("vmentry", BindingFlags.Instance | BindingFlags.NonPublic)); - if (type.returnType() == java.lang.Void.TYPE) - { - dm.ilgen.Emit(OpCodes.Call, typeof(MethodHandleUtil).GetMethod("GetVoidAdapter", BindingFlags.Static | BindingFlags.NonPublic)); - } - else + sealed class Container { - dm.ilgen.Emit(OpCodes.Ldfld, typeof(java.lang.invoke.MemberName).GetField("vmtarget", BindingFlags.Instance | BindingFlags.NonPublic)); + public T1 target; + public T2 value; + + public Container(T1 target, T2 value) + { + this.target = target; + this.value = value; + } } - dm.ilgen.Emit(OpCodes.Castclass, targetDelegateType); - dm.ilgen.Emit(OpCodes.Ldarg_0); - for (int i = 0; i < type.parameterCount(); i++) + + private DynamicMethodBuilder(string name, java.lang.invoke.MethodType type, Type container, object target, object value, Type owner, bool useBasicTypes) { - dm.Ldarg(i); - TypeWrapper tw = TypeWrapper.FromClass(type.parameterType(i)); - if (tw.IsNonPrimitiveValueType) + this.type = type; + this.delegateType = useBasicTypes ? GetMemberWrapperDelegateType(type) : GetDelegateTypeForInvokeExact(type); + this.firstBoundValue = target; + this.secondBoundValue = value; + this.container = container; + MethodInfo mi = GetDelegateInvokeMethod(delegateType); + Type[] paramTypes; + if (container != null) { - tw.EmitBox(dm.ilgen); + this.firstArg = 1; + paramTypes = GetParameterTypes(container, mi); } - else if (tw.IsGhost) + else if (target != null) { - tw.EmitConvSignatureTypeToStackType(dm.ilgen); + this.firstArg = 1; + paramTypes = GetParameterTypes(target.GetType(), mi); } - else if (tw == PrimitiveTypeWrapper.BYTE) + else { - dm.ilgen.Emit(OpCodes.Conv_I1); + paramTypes = GetParameterTypes(mi); + } + if (!ReflectUtil.CanOwnDynamicMethod(owner)) + { + owner = typeof(DynamicMethodBuilder); + } + this.dm = new DynamicMethod(name, mi.ReturnType, paramTypes, owner, true); + this.ilgen = CodeEmitter.Create(dm); + + if (type.parameterCount() > MaxArity) + { + ParameterInfo[] pi = mi.GetParameters(); + this.packedArgType = pi[pi.Length - 1].ParameterType; + this.packedArgPos = pi.Length - 1 + firstArg; + } + else + { + this.packedArgPos = Int32.MaxValue; } } - dm.CallDelegate(targetDelegateType); - TypeWrapper retType = TypeWrapper.FromClass(type.returnType()); - if (retType.IsNonPrimitiveValueType) - { - retType.EmitUnbox(dm.ilgen); - } - else if (retType.IsGhost) + + internal static Delegate CreateVoidAdapter(global::java.lang.invoke.MethodType type) { - retType.EmitConvStackTypeToSignatureType(dm.ilgen, null); + DynamicMethodBuilder dm = new DynamicMethodBuilder("VoidAdapter", type.changeReturnType(global::java.lang.Void.TYPE), null, null, null, null, true); + Type targetDelegateType = GetMemberWrapperDelegateType(type); + dm.Ldarg(0); + dm.EmitCheckcast(CoreClasses.java.lang.invoke.MethodHandle.Wrapper); + dm.ilgen.Emit(OpCodes.Ldfld, typeof(global::java.lang.invoke.MethodHandle).GetField("form", BindingFlags.Instance | BindingFlags.NonPublic)); + dm.ilgen.Emit(OpCodes.Ldfld, typeof(global::java.lang.invoke.LambdaForm).GetField("vmentry", BindingFlags.Instance | BindingFlags.NonPublic)); + dm.ilgen.Emit(OpCodes.Ldfld, typeof(global::java.lang.invoke.MemberName).GetField("vmtarget", BindingFlags.Instance | BindingFlags.NonPublic)); + dm.ilgen.Emit(OpCodes.Castclass, targetDelegateType); + for (int i = 0; i < type.parameterCount(); i++) + { + dm.Ldarg(i); + } + dm.CallDelegate(targetDelegateType); + dm.ilgen.Emit(OpCodes.Pop); + dm.Ret(); + return dm.CreateDelegate(); } - else if (!retType.IsPrimitive && retType != CoreClasses.java.lang.Object.Wrapper) + + internal static DynamicMethod CreateInvokeExact(global::java.lang.invoke.MethodType type) { - dm.EmitCheckcast(retType); + FinishTypes(type); + DynamicMethodBuilder dm = new DynamicMethodBuilder("InvokeExact", type, typeof(java.lang.invoke.MethodHandle), null, null, null, false); + Type targetDelegateType = GetMemberWrapperDelegateType(type.insertParameterTypes(0, CoreClasses.java.lang.invoke.MethodHandle.Wrapper.ClassObject)); + dm.ilgen.Emit(OpCodes.Ldarg_0); + dm.ilgen.Emit(OpCodes.Ldfld, typeof(global::java.lang.invoke.MethodHandle).GetField("form", BindingFlags.Instance | BindingFlags.NonPublic)); + dm.ilgen.Emit(OpCodes.Ldfld, typeof(global::java.lang.invoke.LambdaForm).GetField("vmentry", BindingFlags.Instance | BindingFlags.NonPublic)); + if (type.returnType() == java.lang.Void.TYPE) + { + dm.ilgen.Emit(OpCodes.Call, typeof(MethodHandleUtil).GetMethod("GetVoidAdapter", BindingFlags.Static | BindingFlags.NonPublic)); + } + else + { + dm.ilgen.Emit(OpCodes.Ldfld, typeof(java.lang.invoke.MemberName).GetField("vmtarget", BindingFlags.Instance | BindingFlags.NonPublic)); + } + dm.ilgen.Emit(OpCodes.Castclass, targetDelegateType); + dm.ilgen.Emit(OpCodes.Ldarg_0); + for (int i = 0; i < type.parameterCount(); i++) + { + dm.Ldarg(i); + TypeWrapper tw = TypeWrapper.FromClass(type.parameterType(i)); + if (tw.IsNonPrimitiveValueType) + { + tw.EmitBox(dm.ilgen); + } + else if (tw.IsGhost) + { + tw.EmitConvSignatureTypeToStackType(dm.ilgen); + } + else if (tw == PrimitiveTypeWrapper.BYTE) + { + dm.ilgen.Emit(OpCodes.Conv_I1); + } + } + dm.CallDelegate(targetDelegateType); + TypeWrapper retType = TypeWrapper.FromClass(type.returnType()); + if (retType.IsNonPrimitiveValueType) + { + retType.EmitUnbox(dm.ilgen); + } + else if (retType.IsGhost) + { + retType.EmitConvStackTypeToSignatureType(dm.ilgen, null); + } + else if (!retType.IsPrimitive && retType != CoreClasses.java.lang.Object.Wrapper) + { + dm.EmitCheckcast(retType); + } + dm.Ret(); + dm.ilgen.DoEmit(); + return dm.dm; } - dm.Ret(); - dm.ilgen.DoEmit(); - return dm.dm; - } - internal static Delegate CreateMethodHandleLinkTo(java.lang.invoke.MemberName mn) - { - java.lang.invoke.MethodType type = mn.getMethodType(); - Type delegateType = MethodHandleUtil.GetMemberWrapperDelegateType(type.dropParameterTypes(type.parameterCount() - 1, type.parameterCount())); - DynamicMethodBuilder dm = new DynamicMethodBuilder("DirectMethodHandle." + mn.getName() + type, type, null, null, null, null, true); - dm.Ldarg(type.parameterCount() - 1); - dm.ilgen.EmitCastclass(typeof(java.lang.invoke.MemberName)); - dm.ilgen.Emit(OpCodes.Ldfld, typeof(java.lang.invoke.MemberName).GetField("vmtarget", BindingFlags.Instance | BindingFlags.NonPublic)); - dm.ilgen.Emit(OpCodes.Castclass, delegateType); - for (int i = 0, count = type.parameterCount() - 1; i < count; i++) - { - dm.Ldarg(i); - } - dm.CallDelegate(delegateType); - dm.Ret(); - return dm.CreateDelegate(); - } - - internal static Delegate CreateMethodHandleInvoke(java.lang.invoke.MemberName mn) - { - java.lang.invoke.MethodType type = mn.getMethodType().insertParameterTypes(0, mn.getDeclaringClass()); - Type targetDelegateType = MethodHandleUtil.GetMemberWrapperDelegateType(type); - DynamicMethodBuilder dm = new DynamicMethodBuilder("DirectMethodHandle." + mn.getName() + type, type, - typeof(Container<,>).MakeGenericType(typeof(object), typeof(IKVM.Runtime.InvokeCache<>).MakeGenericType(targetDelegateType)), null, null, null, true); - dm.Ldarg(0); - dm.EmitCheckcast(CoreClasses.java.lang.invoke.MethodHandle.Wrapper); - switch (mn.getName()) - { - case "invokeExact": - dm.Call(ByteCodeHelperMethods.GetDelegateForInvokeExact.MakeGenericMethod(targetDelegateType)); - break; - case "invoke": - dm.LoadValueAddress(); - dm.Call(ByteCodeHelperMethods.GetDelegateForInvoke.MakeGenericMethod(targetDelegateType)); - break; - case "invokeBasic": - dm.Call(ByteCodeHelperMethods.GetDelegateForInvokeBasic.MakeGenericMethod(targetDelegateType)); - break; - default: - throw new InvalidOperationException(); - } - dm.Ldarg(0); - for (int i = 1, count = type.parameterCount(); i < count; i++) + internal static Delegate CreateMethodHandleLinkTo(java.lang.invoke.MemberName mn) { - dm.Ldarg(i); + java.lang.invoke.MethodType type = mn.getMethodType(); + Type delegateType = MethodHandleUtil.GetMemberWrapperDelegateType(type.dropParameterTypes(type.parameterCount() - 1, type.parameterCount())); + DynamicMethodBuilder dm = new DynamicMethodBuilder("DirectMethodHandle." + mn.getName() + type, type, null, null, null, null, true); + dm.Ldarg(type.parameterCount() - 1); + dm.ilgen.EmitCastclass(typeof(java.lang.invoke.MemberName)); + dm.ilgen.Emit(OpCodes.Ldfld, typeof(java.lang.invoke.MemberName).GetField("vmtarget", BindingFlags.Instance | BindingFlags.NonPublic)); + dm.ilgen.Emit(OpCodes.Castclass, delegateType); + for (int i = 0, count = type.parameterCount() - 1; i < count; i++) + { + dm.Ldarg(i); + } + dm.CallDelegate(delegateType); + dm.Ret(); + return dm.CreateDelegate(); } - dm.CallDelegate(targetDelegateType); - dm.Ret(); - return dm.CreateDelegate(); - } - internal static Delegate CreateDynamicOnly(MethodWrapper mw, java.lang.invoke.MethodType type) - { - FinishTypes(type); - DynamicMethodBuilder dm = new DynamicMethodBuilder("CustomInvoke:" + mw.Name, type, null, mw, null, null, true); - dm.ilgen.Emit(OpCodes.Ldarg_0); - if (mw.IsStatic) + internal static Delegate CreateMethodHandleInvoke(java.lang.invoke.MemberName mn) { - dm.LoadNull(); - dm.BoxArgs(0); + java.lang.invoke.MethodType type = mn.getMethodType().insertParameterTypes(0, mn.getDeclaringClass()); + Type targetDelegateType = MethodHandleUtil.GetMemberWrapperDelegateType(type); + DynamicMethodBuilder dm = new DynamicMethodBuilder("DirectMethodHandle." + mn.getName() + type, type, + typeof(Container<,>).MakeGenericType(typeof(object), typeof(IKVM.Runtime.InvokeCache<>).MakeGenericType(targetDelegateType)), null, null, null, true); + dm.Ldarg(0); + dm.EmitCheckcast(CoreClasses.java.lang.invoke.MethodHandle.Wrapper); + switch (mn.getName()) + { + case "invokeExact": + dm.Call(ByteCodeHelperMethods.GetDelegateForInvokeExact.MakeGenericMethod(targetDelegateType)); + break; + case "invoke": + dm.LoadValueAddress(); + dm.Call(ByteCodeHelperMethods.GetDelegateForInvoke.MakeGenericMethod(targetDelegateType)); + break; + case "invokeBasic": + dm.Call(ByteCodeHelperMethods.GetDelegateForInvokeBasic.MakeGenericMethod(targetDelegateType)); + break; + default: + throw new InvalidOperationException(); + } + dm.Ldarg(0); + for (int i = 1, count = type.parameterCount(); i < count; i++) + { + dm.Ldarg(i); + } + dm.CallDelegate(targetDelegateType); + dm.Ret(); + return dm.CreateDelegate(); } - else + + internal static Delegate CreateDynamicOnly(MethodWrapper mw, java.lang.invoke.MethodType type) { - dm.Ldarg(0); - dm.BoxArgs(1); + FinishTypes(type); + DynamicMethodBuilder dm = new DynamicMethodBuilder("CustomInvoke:" + mw.Name, type, null, mw, null, null, true); + dm.ilgen.Emit(OpCodes.Ldarg_0); + if (mw.IsStatic) + { + dm.LoadNull(); + dm.BoxArgs(0); + } + else + { + dm.Ldarg(0); + dm.BoxArgs(1); + } + dm.Callvirt(typeof(MethodWrapper).GetMethod("Invoke", BindingFlags.Instance | BindingFlags.NonPublic)); + dm.UnboxReturnValue(); + dm.Ret(); + return dm.CreateDelegate(); } - dm.Callvirt(typeof(MethodWrapper).GetMethod("Invoke", BindingFlags.Instance | BindingFlags.NonPublic)); - dm.UnboxReturnValue(); - dm.Ret(); - return dm.CreateDelegate(); - } - internal static Delegate CreateMemberName(MethodWrapper mw, global::java.lang.invoke.MethodType type, bool doDispatch) - { - FinishTypes(type); - TypeWrapper tw = mw.DeclaringType; - Type owner = tw.TypeAsBaseType; + internal static Delegate CreateMemberName(MethodWrapper mw, global::java.lang.invoke.MethodType type, bool doDispatch) + { + FinishTypes(type); + TypeWrapper tw = mw.DeclaringType; + Type owner = tw.TypeAsBaseType; #if NET_4_0 if (!doDispatch && !mw.IsStatic) { @@ -345,360 +346,362 @@ internal static Delegate CreateMemberName(MethodWrapper mw, global::java.lang.in owner = typeof(object); } #endif - DynamicMethodBuilder dm = new DynamicMethodBuilder("MemberName:" + mw.DeclaringType.Name + "::" + mw.Name + mw.Signature, type, null, - mw.HasCallerID ? DynamicCallerIDProvider.Instance : null, null, owner, true); - for (int i = 0, count = type.parameterCount(); i < count; i++) - { - if (i == 0 && !mw.IsStatic && (tw.IsGhost || tw.IsNonPrimitiveValueType || tw.IsRemapped) && (!mw.IsConstructor || tw != CoreClasses.java.lang.String.Wrapper)) + DynamicMethodBuilder dm = new DynamicMethodBuilder("MemberName:" + mw.DeclaringType.Name + "::" + mw.Name + mw.Signature, type, null, + mw.HasCallerID ? DynamicCallerIDProvider.Instance : null, null, owner, true); + for (int i = 0, count = type.parameterCount(); i < count; i++) { - if (tw.IsGhost || tw.IsNonPrimitiveValueType) + if (i == 0 && !mw.IsStatic && (tw.IsGhost || tw.IsNonPrimitiveValueType || tw.IsRemapped) && (!mw.IsConstructor || tw != CoreClasses.java.lang.String.Wrapper)) { - dm.LoadFirstArgAddress(tw); + if (tw.IsGhost || tw.IsNonPrimitiveValueType) + { + dm.LoadFirstArgAddress(tw); + } + else + { + Debug.Assert(tw.IsRemapped); + // TODO this must be checked + dm.Ldarg(0); + if (mw.IsConstructor) + { + dm.EmitCastclass(tw.TypeAsBaseType); + } + else if (tw != CoreClasses.cli.System.Object.Wrapper) + { + dm.EmitCheckcast(tw); + } + } } else { - Debug.Assert(tw.IsRemapped); - // TODO this must be checked - dm.Ldarg(0); - if (mw.IsConstructor) + dm.Ldarg(i); + TypeWrapper argType = TypeWrapper.FromClass(type.parameterType(i)); + if (!argType.IsPrimitive) { - dm.EmitCastclass(tw.TypeAsBaseType); - } - else if (tw != CoreClasses.cli.System.Object.Wrapper) - { - dm.EmitCheckcast(tw); + if (argType.IsUnloadable) + { + } + else if (argType.IsNonPrimitiveValueType) + { + dm.Unbox(argType); + } + else if (argType.IsGhost) + { + dm.UnboxGhost(argType); + } + else + { + dm.EmitCheckcast(argType); + } } } } - else + if (mw.HasCallerID) { - dm.Ldarg(i); - TypeWrapper argType = TypeWrapper.FromClass(type.parameterType(i)); - if (!argType.IsPrimitive) + dm.LoadCallerID(); + } + // special case for Object.clone() and Object.finalize() + if (mw.IsFinalizeOrClone) + { + if (doDispatch) { - if (argType.IsUnloadable) - { - } - else if (argType.IsNonPrimitiveValueType) - { - dm.Unbox(argType); - } - else if (argType.IsGhost) - { - dm.UnboxGhost(argType); - } - else - { - dm.EmitCheckcast(argType); - } + mw.EmitCallvirtReflect(dm.ilgen); + } + else + { + // we can re-use the implementations from cli.System.Object (even though the object may not in-fact extend cli.System.Object) + CoreClasses.cli.System.Object.Wrapper.GetMethodWrapper(mw.Name, mw.Signature, false).EmitCall(dm.ilgen); } } - } - if (mw.HasCallerID) - { - dm.LoadCallerID(); - } - // special case for Object.clone() and Object.finalize() - if (mw.IsFinalizeOrClone) - { - if (doDispatch) + else if (doDispatch && !mw.IsStatic) { - mw.EmitCallvirtReflect(dm.ilgen); + dm.Callvirt(mw); } else { - // we can re-use the implementations from cli.System.Object (even though the object may not in-fact extend cli.System.Object) - CoreClasses.cli.System.Object.Wrapper.GetMethodWrapper(mw.Name, mw.Signature, false).EmitCall(dm.ilgen); + dm.Call(mw); } + TypeWrapper retType = TypeWrapper.FromClass(type.returnType()); + if (retType.IsUnloadable) + { + } + else if (retType.IsNonPrimitiveValueType) + { + dm.Box(retType); + } + else if (retType.IsGhost) + { + dm.BoxGhost(retType); + } + else if (retType == PrimitiveTypeWrapper.BYTE) + { + dm.CastByte(); + } + dm.Ret(); + return dm.CreateDelegate(); } - else if (doDispatch && !mw.IsStatic) + + internal void Call(MethodInfo method) { - dm.Callvirt(mw); + ilgen.Emit(OpCodes.Call, method); } - else + + internal void Callvirt(MethodInfo method) { - dm.Call(mw); + ilgen.Emit(OpCodes.Callvirt, method); } - TypeWrapper retType = TypeWrapper.FromClass(type.returnType()); - if (retType.IsUnloadable) + + internal void Call(MethodWrapper mw) { + mw.EmitCall(ilgen); } - else if (retType.IsNonPrimitiveValueType) + + internal void Callvirt(MethodWrapper mw) { - dm.Box(retType); + mw.EmitCallvirt(ilgen); } - else if (retType.IsGhost) + + internal void CallDelegate(Type delegateType) { - dm.BoxGhost(retType); + EmitCallDelegateInvokeMethod(ilgen, delegateType); } - else if (retType == PrimitiveTypeWrapper.BYTE) + + internal void LoadFirstArgAddress(TypeWrapper tw) { - dm.CastByte(); + ilgen.EmitLdarg(0); + if (tw.IsGhost) + { + tw.EmitConvStackTypeToSignatureType(ilgen, null); + CodeEmitterLocal local = ilgen.DeclareLocal(tw.TypeAsSignatureType); + ilgen.Emit(OpCodes.Stloc, local); + ilgen.Emit(OpCodes.Ldloca, local); + } + else if (tw.IsNonPrimitiveValueType) + { + ilgen.Emit(OpCodes.Unbox, tw.TypeAsSignatureType); + } + else + { + throw new InvalidOperationException(); + } } - dm.Ret(); - return dm.CreateDelegate(); - } - - internal void Call(MethodInfo method) - { - ilgen.Emit(OpCodes.Call, method); - } - - internal void Callvirt(MethodInfo method) - { - ilgen.Emit(OpCodes.Callvirt, method); - } - - internal void Call(MethodWrapper mw) - { - mw.EmitCall(ilgen); - } - - internal void Callvirt(MethodWrapper mw) - { - mw.EmitCallvirt(ilgen); - } - - internal void CallDelegate(Type delegateType) - { - EmitCallDelegateInvokeMethod(ilgen, delegateType); - } - internal void LoadFirstArgAddress(TypeWrapper tw) - { - ilgen.EmitLdarg(0); - if (tw.IsGhost) + internal void Ldarg(int i) { - tw.EmitConvStackTypeToSignatureType(ilgen, null); - CodeEmitterLocal local = ilgen.DeclareLocal(tw.TypeAsSignatureType); - ilgen.Emit(OpCodes.Stloc, local); - ilgen.Emit(OpCodes.Ldloca, local); + LoadPackedArg(ilgen, i, firstArg, packedArgPos, packedArgType); } - else if (tw.IsNonPrimitiveValueType) + + internal void LoadCallerID() { - ilgen.Emit(OpCodes.Unbox, tw.TypeAsSignatureType); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicCallerID); } - else + + internal void LoadValueAddress() { - throw new InvalidOperationException(); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Ldflda, container.GetField("value")); } - } - - internal void Ldarg(int i) - { - LoadPackedArg(ilgen, i, firstArg, packedArgPos, packedArgType); - } - - internal void LoadCallerID() - { - ilgen.Emit(OpCodes.Ldarg_0); - ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicCallerID); - } - - internal void LoadValueAddress() - { - ilgen.Emit(OpCodes.Ldarg_0); - ilgen.Emit(OpCodes.Ldflda, container.GetField("value")); - } - internal void Ret() - { - ilgen.Emit(OpCodes.Ret); - } + internal void Ret() + { + ilgen.Emit(OpCodes.Ret); + } - internal Delegate CreateDelegate() - { - //Console.WriteLine(delegateType); - //ilgen.DumpMethod(); - ilgen.DoEmit(); - return ValidateDelegate(firstArg == 0 - ? dm.CreateDelegate(delegateType) - : dm.CreateDelegate(delegateType, container == null ? firstBoundValue : Activator.CreateInstance(container, firstBoundValue, secondBoundValue))); - } + internal Delegate CreateDelegate() + { + //Console.WriteLine(delegateType); + //ilgen.DumpMethod(); + ilgen.DoEmit(); + return ValidateDelegate(firstArg == 0 + ? dm.CreateDelegate(delegateType) + : dm.CreateDelegate(delegateType, container == null ? firstBoundValue : Activator.CreateInstance(container, firstBoundValue, secondBoundValue))); + } - internal void BoxArgs(int start) - { - int paramCount = type.parameterCount(); - ilgen.EmitLdc_I4(paramCount - start); - ilgen.Emit(OpCodes.Newarr, Types.Object); - for (int i = start; i < paramCount; i++) + internal void BoxArgs(int start) { - ilgen.Emit(OpCodes.Dup); - ilgen.EmitLdc_I4(i - start); - Ldarg(i); - TypeWrapper tw = TypeWrapper.FromClass(type.parameterType(i)); - if (tw.IsPrimitive) + int paramCount = type.parameterCount(); + ilgen.EmitLdc_I4(paramCount - start); + ilgen.Emit(OpCodes.Newarr, Types.Object); + for (int i = start; i < paramCount; i++) { - ilgen.Emit(OpCodes.Box, tw.TypeAsSignatureType); + ilgen.Emit(OpCodes.Dup); + ilgen.EmitLdc_I4(i - start); + Ldarg(i); + TypeWrapper tw = TypeWrapper.FromClass(type.parameterType(i)); + if (tw.IsPrimitive) + { + ilgen.Emit(OpCodes.Box, tw.TypeAsSignatureType); + } + ilgen.Emit(OpCodes.Stelem_Ref); } - ilgen.Emit(OpCodes.Stelem_Ref); } - } - internal void UnboxReturnValue() - { - TypeWrapper tw = TypeWrapper.FromClass(type.returnType()); - if (tw == PrimitiveTypeWrapper.VOID) + internal void UnboxReturnValue() { - ilgen.Emit(OpCodes.Pop); + TypeWrapper tw = TypeWrapper.FromClass(type.returnType()); + if (tw == PrimitiveTypeWrapper.VOID) + { + ilgen.Emit(OpCodes.Pop); + } + else if (tw.IsPrimitive) + { + ilgen.Emit(OpCodes.Unbox, tw.TypeAsSignatureType); + ilgen.Emit(OpCodes.Ldobj, tw.TypeAsSignatureType); + } } - else if (tw.IsPrimitive) + + internal void LoadNull() { - ilgen.Emit(OpCodes.Unbox, tw.TypeAsSignatureType); - ilgen.Emit(OpCodes.Ldobj, tw.TypeAsSignatureType); + ilgen.Emit(OpCodes.Ldnull); } - } - internal void LoadNull() - { - ilgen.Emit(OpCodes.Ldnull); - } - - internal void Unbox(TypeWrapper tw) - { - tw.EmitUnbox(ilgen); - } + internal void Unbox(TypeWrapper tw) + { + tw.EmitUnbox(ilgen); + } - internal void Box(TypeWrapper tw) - { - tw.EmitBox(ilgen); - } + internal void Box(TypeWrapper tw) + { + tw.EmitBox(ilgen); + } - internal void UnboxGhost(TypeWrapper tw) - { - tw.EmitConvStackTypeToSignatureType(ilgen, null); - } + internal void UnboxGhost(TypeWrapper tw) + { + tw.EmitConvStackTypeToSignatureType(ilgen, null); + } - internal void BoxGhost(TypeWrapper tw) - { - tw.EmitConvSignatureTypeToStackType(ilgen); - } + internal void BoxGhost(TypeWrapper tw) + { + tw.EmitConvSignatureTypeToStackType(ilgen); + } - internal void EmitCheckcast(TypeWrapper tw) - { - tw.EmitCheckcast(ilgen); - } + internal void EmitCheckcast(TypeWrapper tw) + { + tw.EmitCheckcast(ilgen); + } - internal void EmitCastclass(Type type) - { - ilgen.EmitCastclass(type); - } + internal void EmitCastclass(Type type) + { + ilgen.EmitCastclass(type); + } - internal void EmitWriteLine() - { - ilgen.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(object) })); - } + internal void EmitWriteLine() + { + ilgen.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(object) })); + } - internal void CastByte() - { - ilgen.Emit(OpCodes.Conv_I1); - } + internal void CastByte() + { + ilgen.Emit(OpCodes.Conv_I1); + } - internal void DumpMethod() - { - Console.WriteLine(dm.Name + ", type = " + delegateType); - ilgen.DumpMethod(); - } + internal void DumpMethod() + { + Console.WriteLine(dm.Name + ", type = " + delegateType); + ilgen.DumpMethod(); + } - private static void FinishTypes(global::java.lang.invoke.MethodType type) - { - // FXBUG(?) DynamicILGenerator doesn't like SymbolType (e.g. an array of a TypeBuilder) - // so we have to finish the signature types - TypeWrapper.FromClass(type.returnType()).Finish(); - for (int i = 0; i < type.parameterCount(); i++) + private static void FinishTypes(global::java.lang.invoke.MethodType type) { - TypeWrapper.FromClass(type.parameterType(i)).Finish(); + // FXBUG(?) DynamicILGenerator doesn't like SymbolType (e.g. an array of a TypeBuilder) + // so we have to finish the signature types + TypeWrapper.FromClass(type.returnType()).Finish(); + for (int i = 0; i < type.parameterCount(); i++) + { + TypeWrapper.FromClass(type.parameterType(i)).Finish(); + } } } - } #if DEBUG - [System.Security.SecuritySafeCritical] + [System.Security.SecuritySafeCritical] #endif - private static Delegate ValidateDelegate(Delegate d) - { -#if DEBUG - try + private static Delegate ValidateDelegate(Delegate d) { - System.Runtime.CompilerServices.RuntimeHelpers.PrepareDelegate(d); - } - catch (Exception x) - { - throw new InternalException("Delegate failed to JIT", x); - } +#if DEBUG + try + { + System.Runtime.CompilerServices.RuntimeHelpers.PrepareDelegate(d); + } + catch (Exception x) + { + throw new InternalException("Delegate failed to JIT", x); + } #endif - return d; - } - - internal static Type GetDelegateTypeForInvokeExact(global::java.lang.invoke.MethodType type) - { - if (type._invokeExactDelegateType == null) - { - type._invokeExactDelegateType = CreateMethodHandleDelegateType(type); + return d; } - return type._invokeExactDelegateType; - } - internal static T GetDelegateForInvokeExact(global::java.lang.invoke.MethodHandle mh) - where T : class - { - global::java.lang.invoke.MethodType type = mh.type(); - if (mh._invokeExactDelegate == null) + internal static Type GetDelegateTypeForInvokeExact(global::java.lang.invoke.MethodType type) { - if (type._invokeExactDynamicMethod == null) - { - type._invokeExactDynamicMethod = DynamicMethodBuilder.CreateInvokeExact(type); - } - mh._invokeExactDelegate = type._invokeExactDynamicMethod.CreateDelegate(GetDelegateTypeForInvokeExact(type), mh); - T del = mh._invokeExactDelegate as T; - if (del != null) + if (type._invokeExactDelegateType == null) { - return del; + type._invokeExactDelegateType = CreateMethodHandleDelegateType(type); } + return type._invokeExactDelegateType; } - throw java.lang.invoke.Invokers.newWrongMethodTypeException(GetDelegateMethodType(typeof(T)), type); - } - // called from InvokeExact DynamicMethod and ByteCodeHelper.GetDelegateForInvokeBasic() - internal static object GetVoidAdapter(java.lang.invoke.MemberName mn) - { - global::java.lang.invoke.MethodType type = mn.getMethodType(); - if (type.voidAdapter == null) + internal static T GetDelegateForInvokeExact(global::java.lang.invoke.MethodHandle mh) + where T : class { - if (type.returnType() == global::java.lang.Void.TYPE) + global::java.lang.invoke.MethodType type = mh.type(); + if (mh._invokeExactDelegate == null) { - return mn.vmtarget; + if (type._invokeExactDynamicMethod == null) + { + type._invokeExactDynamicMethod = DynamicMethodBuilder.CreateInvokeExact(type); + } + mh._invokeExactDelegate = type._invokeExactDynamicMethod.CreateDelegate(GetDelegateTypeForInvokeExact(type), mh); + T del = mh._invokeExactDelegate as T; + if (del != null) + { + return del; + } } - type.voidAdapter = DynamicMethodBuilder.CreateVoidAdapter(type); + throw java.lang.invoke.Invokers.newWrongMethodTypeException(GetDelegateMethodType(typeof(T)), type); } - return type.voidAdapter; - } - internal static void LoadPackedArg(CodeEmitter ilgen, int index, int firstArg, int packedArgPos, Type packedArgType) - { - index += firstArg; - if (index >= packedArgPos) + // called from InvokeExact DynamicMethod and ByteCodeHelper.GetDelegateForInvokeBasic() + internal static object GetVoidAdapter(java.lang.invoke.MemberName mn) { - ilgen.EmitLdarga(packedArgPos); - int fieldPos = index - packedArgPos; - Type type = packedArgType; - while (fieldPos >= MaxArity || (fieldPos == MaxArity - 1 && IsPackedArgsContainer(type.GetField("t8").FieldType))) + global::java.lang.invoke.MethodType type = mn.getMethodType(); + if (type.voidAdapter == null) { - FieldInfo field = type.GetField("t8"); - type = field.FieldType; - ilgen.Emit(OpCodes.Ldflda, field); - fieldPos -= MaxArity - 1; + if (type.returnType() == global::java.lang.Void.TYPE) + { + return mn.vmtarget; + } + type.voidAdapter = DynamicMethodBuilder.CreateVoidAdapter(type); } - ilgen.Emit(OpCodes.Ldfld, type.GetField("t" + (1 + fieldPos))); + return type.voidAdapter; } - else + + internal static void LoadPackedArg(CodeEmitter ilgen, int index, int firstArg, int packedArgPos, Type packedArgType) { - ilgen.EmitLdarg(index); + index += firstArg; + if (index >= packedArgPos) + { + ilgen.EmitLdarga(packedArgPos); + int fieldPos = index - packedArgPos; + Type type = packedArgType; + while (fieldPos >= MaxArity || (fieldPos == MaxArity - 1 && IsPackedArgsContainer(type.GetField("t8").FieldType))) + { + FieldInfo field = type.GetField("t8"); + type = field.FieldType; + ilgen.Emit(OpCodes.Ldflda, field); + fieldPos -= MaxArity - 1; + } + ilgen.Emit(OpCodes.Ldfld, type.GetField("t" + (1 + fieldPos))); + } + else + { + ilgen.EmitLdarg(index); + } } - } #endif + } + } #endif diff --git a/src/IKVM.Runtime/MethodHandleUtil.root.cs b/src/IKVM.Runtime/MethodHandleUtil.root.cs index 5a66a1c6e7..325baf3805 100644 --- a/src/IKVM.Runtime/MethodHandleUtil.root.cs +++ b/src/IKVM.Runtime/MethodHandleUtil.root.cs @@ -23,11 +23,7 @@ Jeroen Frijters */ using System; -using IKVM.Internal; - #if IMPORTER -using IKVM.Reflection; -using IKVM.Reflection.Emit; using IKVM.Tools.Importer; using Type = IKVM.Reflection.Type; @@ -36,17 +32,20 @@ Jeroen Frijters using System.Reflection.Emit; #endif -static partial class MethodHandleUtil +namespace IKVM.Runtime { - internal const int MaxArity = 8; + static partial class MethodHandleUtil + { - static readonly Type typeofMHA; - static readonly Type[] typeofMHV; - static readonly Type[] typeofMH; + internal const int MaxArity = 8; - static MethodHandleUtil() - { + static readonly Type typeofMHA; + static readonly Type[] typeofMHV; + static readonly Type[] typeofMH; + + static MethodHandleUtil() + { #if IMPORTER typeofMHA = StaticCompiler.GetRuntimeType("IKVM.Runtime.MHA`8"); typeofMHV = new Type[] { @@ -73,8 +72,8 @@ static MethodHandleUtil() StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`9"), }; #else - typeofMHA = typeof(IKVM.Runtime.MHA<,,,,,,,>); - typeofMHV = new Type[] { + typeofMHA = typeof(IKVM.Runtime.MHA<,,,,,,,>); + typeofMHV = new Type[] { typeof(IKVM.Runtime.MHV), typeof(IKVM.Runtime.MHV<>), typeof(IKVM.Runtime.MHV<,>), @@ -85,7 +84,7 @@ static MethodHandleUtil() typeof(IKVM.Runtime.MHV<,,,,,,>), typeof(IKVM.Runtime.MHV<,,,,,,,>), }; - typeofMH = new Type[] { + typeofMH = new Type[] { null, typeof(IKVM.Runtime.MH<>), typeof(IKVM.Runtime.MH<,>), @@ -98,117 +97,119 @@ static MethodHandleUtil() typeof(IKVM.Runtime.MH<,,,,,,,,>), }; #endif - } - - internal static bool IsPackedArgsContainer(Type type) - { - return type.IsGenericType && type.GetGenericTypeDefinition() == typeofMHA; - } + } - internal static Type CreateMethodHandleDelegateType(TypeWrapper[] args, TypeWrapper ret) - { - Type[] typeArgs = new Type[args.Length]; - for (int i = 0; i < args.Length; i++) + internal static bool IsPackedArgsContainer(Type type) { - typeArgs[i] = args[i].TypeAsSignatureType; + return type.IsGenericType && type.GetGenericTypeDefinition() == typeofMHA; } - return CreateDelegateType(typeArgs, ret.TypeAsSignatureType); - } - internal static Type CreateMemberWrapperDelegateType(TypeWrapper[] args, TypeWrapper ret) - { - Type[] typeArgs = new Type[args.Length]; - for (int i = 0; i < args.Length; i++) + internal static Type CreateMethodHandleDelegateType(TypeWrapper[] args, TypeWrapper ret) { - typeArgs[i] = AsBasicType(args[i]); + Type[] typeArgs = new Type[args.Length]; + for (int i = 0; i < args.Length; i++) + { + typeArgs[i] = args[i].TypeAsSignatureType; + } + return CreateDelegateType(typeArgs, ret.TypeAsSignatureType); } - return CreateDelegateType(typeArgs, AsBasicType(ret)); - } - static Type CreateDelegateType(Type[] types, Type retType) - { - if (types.Length == 0 && retType == Types.Void) + internal static Type CreateMemberWrapperDelegateType(TypeWrapper[] args, TypeWrapper ret) { - return typeofMHV[0]; + Type[] typeArgs = new Type[args.Length]; + for (int i = 0; i < args.Length; i++) + { + typeArgs[i] = AsBasicType(args[i]); + } + return CreateDelegateType(typeArgs, AsBasicType(ret)); } - else if (types.Length > MaxArity) + + static Type CreateDelegateType(Type[] types, Type retType) { - int arity = types.Length; - int remainder = (arity - 8) % 7; - int count = (arity - 8) / 7; - if (remainder == 0) + if (types.Length == 0 && retType == Types.Void) { - remainder = 7; - count--; + return typeofMHV[0]; } - - var last = typeofMHA.MakeGenericType(SubArray(types, types.Length - 8, 8)); - for (int i = 0; i < count; i++) + else if (types.Length > MaxArity) { - var temp = SubArray(types, types.Length - 8 - 7 * (i + 1), 8); - temp[7] = last; - last = typeofMHA.MakeGenericType(temp); + int arity = types.Length; + int remainder = (arity - 8) % 7; + int count = (arity - 8) / 7; + if (remainder == 0) + { + remainder = 7; + count--; + } + + var last = typeofMHA.MakeGenericType(SubArray(types, types.Length - 8, 8)); + for (int i = 0; i < count; i++) + { + var temp = SubArray(types, types.Length - 8 - 7 * (i + 1), 8); + temp[7] = last; + last = typeofMHA.MakeGenericType(temp); + } + + types = SubArray(types, 0, remainder + 1); + types[remainder] = last; } - types = SubArray(types, 0, remainder + 1); - types[remainder] = last; + if (retType == Types.Void) + { + return typeofMHV[types.Length].MakeGenericType(types); + } + else + { + types = ArrayUtil.Concat(types, retType); + return typeofMH[types.Length].MakeGenericType(types); + } } - if (retType == Types.Void) + static Type[] SubArray(Type[] inArray, int start, int length) { - return typeofMHV[types.Length].MakeGenericType(types); + var outArray = new Type[length]; + Array.Copy(inArray, start, outArray, 0, length); + return outArray; } - else + + internal static Type AsBasicType(TypeWrapper tw) { - types = ArrayUtil.Concat(types, retType); - return typeofMH[types.Length].MakeGenericType(types); + if (tw == PrimitiveTypeWrapper.BOOLEAN || tw == PrimitiveTypeWrapper.BYTE || tw == PrimitiveTypeWrapper.CHAR || tw == PrimitiveTypeWrapper.SHORT || tw == PrimitiveTypeWrapper.INT) + return Types.Int32; + else if (tw == PrimitiveTypeWrapper.LONG || tw == PrimitiveTypeWrapper.FLOAT || tw == PrimitiveTypeWrapper.DOUBLE || tw == PrimitiveTypeWrapper.VOID) + return tw.TypeAsSignatureType; + else + return Types.Object; } - } - static Type[] SubArray(Type[] inArray, int start, int length) - { - var outArray = new Type[length]; - Array.Copy(inArray, start, outArray, 0, length); - return outArray; - } - - internal static Type AsBasicType(TypeWrapper tw) - { - if (tw == PrimitiveTypeWrapper.BOOLEAN || tw == PrimitiveTypeWrapper.BYTE || tw == PrimitiveTypeWrapper.CHAR || tw == PrimitiveTypeWrapper.SHORT || tw == PrimitiveTypeWrapper.INT) - return Types.Int32; - else if (tw == PrimitiveTypeWrapper.LONG || tw == PrimitiveTypeWrapper.FLOAT || tw == PrimitiveTypeWrapper.DOUBLE || tw == PrimitiveTypeWrapper.VOID) - return tw.TypeAsSignatureType; - else - return Types.Object; - } - - internal static bool HasOnlyBasicTypes(TypeWrapper[] args, TypeWrapper ret) - { - foreach (var tw in args) - if (!IsBasicType(tw)) - return false; + internal static bool HasOnlyBasicTypes(TypeWrapper[] args, TypeWrapper ret) + { + foreach (var tw in args) + if (!IsBasicType(tw)) + return false; - return IsBasicType(ret); - } + return IsBasicType(ret); + } - static bool IsBasicType(TypeWrapper tw) - { - return tw == PrimitiveTypeWrapper.INT - || tw == PrimitiveTypeWrapper.LONG - || tw == PrimitiveTypeWrapper.FLOAT - || tw == PrimitiveTypeWrapper.DOUBLE - || tw == PrimitiveTypeWrapper.VOID - || tw == CoreClasses.java.lang.Object.Wrapper; - } + static bool IsBasicType(TypeWrapper tw) + { + return tw == PrimitiveTypeWrapper.INT + || tw == PrimitiveTypeWrapper.LONG + || tw == PrimitiveTypeWrapper.FLOAT + || tw == PrimitiveTypeWrapper.DOUBLE + || tw == PrimitiveTypeWrapper.VOID + || tw == CoreClasses.java.lang.Object.Wrapper; + } - internal static int SlotCount(TypeWrapper[] parameters) - { - int count = 0; - for (int i = 0; i < parameters.Length; i++) + internal static int SlotCount(TypeWrapper[] parameters) { - count += parameters[i].IsWidePrimitive ? 2 : 1; + int count = 0; + for (int i = 0; i < parameters.Length; i++) + { + count += parameters[i].IsWidePrimitive ? 2 : 1; + } + return count; } - return count; + } } diff --git a/src/IKVM.Runtime/MethodParametersEntry.cs b/src/IKVM.Runtime/MethodParametersEntry.cs index b365da095b..96ad7ec0f9 100644 --- a/src/IKVM.Runtime/MethodParametersEntry.cs +++ b/src/IKVM.Runtime/MethodParametersEntry.cs @@ -24,7 +24,7 @@ Jeroen Frijters using IKVM.ByteCode; -namespace IKVM.Internal +namespace IKVM.Runtime { struct MethodParametersEntry diff --git a/src/IKVM.Runtime/MethodWrapper.cs b/src/IKVM.Runtime/MethodWrapper.cs index fffca5da43..e5ef007597 100644 --- a/src/IKVM.Runtime/MethodWrapper.cs +++ b/src/IKVM.Runtime/MethodWrapper.cs @@ -25,8 +25,8 @@ Jeroen Frijters using System.Diagnostics; using IKVM.Attributes; + using System.Linq; -using IKVM.Runtime; #if IMPORTER || EXPORTER using IKVM.Reflection; @@ -38,11 +38,7 @@ Jeroen Frijters using System.Reflection.Emit; #endif -#if IMPORTER -using IKVM.Tools.Importer; -#endif - -namespace IKVM.Internal +namespace IKVM.Runtime { abstract class MethodWrapper : MemberWrapper diff --git a/src/IKVM.Runtime/MirandaMethodWrapper.cs b/src/IKVM.Runtime/MirandaMethodWrapper.cs index 1da17b02ab..b96e036332 100644 --- a/src/IKVM.Runtime/MirandaMethodWrapper.cs +++ b/src/IKVM.Runtime/MirandaMethodWrapper.cs @@ -24,20 +24,14 @@ Jeroen Frijters using IKVM.Attributes; #if IMPORTER || EXPORTER -using IKVM.Reflection; using IKVM.Reflection.Emit; - -using Type = IKVM.Reflection.Type; #else using System.Reflection.Emit; #endif -#if IMPORTER -using IKVM.Tools.Importer; -#endif - -namespace IKVM.Internal +namespace IKVM.Runtime { + abstract class MirandaMethodWrapper : SmartMethodWrapper { diff --git a/src/IKVM.Runtime/NamePrefix.cs b/src/IKVM.Runtime/NamePrefix.cs index 2c9089c1b0..5d1352d0e0 100644 --- a/src/IKVM.Runtime/NamePrefix.cs +++ b/src/IKVM.Runtime/NamePrefix.cs @@ -22,8 +22,9 @@ Jeroen Frijters */ -namespace IKVM.Internal +namespace IKVM.Runtime { + static class NamePrefix { diff --git a/src/IKVM.Runtime/NestedTypeName.cs b/src/IKVM.Runtime/NestedTypeName.cs index 7adabfc099..722066eaa8 100644 --- a/src/IKVM.Runtime/NestedTypeName.cs +++ b/src/IKVM.Runtime/NestedTypeName.cs @@ -22,8 +22,9 @@ Jeroen Frijters */ -namespace IKVM.Internal +namespace IKVM.Runtime { + static class NestedTypeName { diff --git a/src/IKVM.Runtime/NormalizedByteCode.cs b/src/IKVM.Runtime/NormalizedByteCode.cs index 9e4f0b854f..04ce524341 100644 --- a/src/IKVM.Runtime/NormalizedByteCode.cs +++ b/src/IKVM.Runtime/NormalizedByteCode.cs @@ -21,175 +21,183 @@ Jeroen Frijters jeroen@frijters.net */ -enum NormalizedByteCode : byte + +namespace IKVM.Runtime { - __nop = 0, - __aconst_null = 1, - __lconst_0 = 9, - __lconst_1 = 10, - __fconst_0 = 11, - __fconst_1 = 12, - __fconst_2 = 13, - __dconst_0 = 14, - __dconst_1 = 15, - __ldc = 18, - __iload = 21, - __lload = 22, - __fload = 23, - __dload = 24, - __aload = 25, - __iaload = 46, - __laload = 47, - __faload = 48, - __daload = 49, - __aaload = 50, - __baload = 51, - __caload = 52, - __saload = 53, - __istore = 54, - __lstore = 55, - __fstore = 56, - __dstore = 57, - __astore = 58, - __iastore = 79, - __lastore = 80, - __fastore = 81, - __dastore = 82, - __aastore = 83, - __bastore = 84, - __castore = 85, - __sastore = 86, - __pop = 87, - __pop2 = 88, - __dup = 89, - __dup_x1 = 90, - __dup_x2 = 91, - __dup2 = 92, - __dup2_x1 = 93, - __dup2_x2 = 94, - __swap = 95, - __iadd = 96, - __ladd = 97, - __fadd = 98, - __dadd = 99, - __isub = 100, - __lsub = 101, - __fsub = 102, - __dsub = 103, - __imul = 104, - __lmul = 105, - __fmul = 106, - __dmul = 107, - __idiv = 108, - __ldiv = 109, - __fdiv = 110, - __ddiv = 111, - __irem = 112, - __lrem = 113, - __frem = 114, - __drem = 115, - __ineg = 116, - __lneg = 117, - __fneg = 118, - __dneg = 119, - __ishl = 120, - __lshl = 121, - __ishr = 122, - __lshr = 123, - __iushr = 124, - __lushr = 125, - __iand = 126, - __land = 127, - __ior = 128, - __lor = 129, - __ixor = 130, - __lxor = 131, - __iinc = 132, - __i2l = 133, - __i2f = 134, - __i2d = 135, - __l2i = 136, - __l2f = 137, - __l2d = 138, - __f2i = 139, - __f2l = 140, - __f2d = 141, - __d2i = 142, - __d2l = 143, - __d2f = 144, - __i2b = 145, - __i2c = 146, - __i2s = 147, - __lcmp = 148, - __fcmpl = 149, - __fcmpg = 150, - __dcmpl = 151, - __dcmpg = 152, - __ifeq = 153, - __ifne = 154, - __iflt = 155, - __ifge = 156, - __ifgt = 157, - __ifle = 158, - __if_icmpeq = 159, - __if_icmpne = 160, - __if_icmplt = 161, - __if_icmpge = 162, - __if_icmpgt = 163, - __if_icmple = 164, - __if_acmpeq = 165, - __if_acmpne = 166, - __goto = 167, - __jsr = 168, - __ret = 169, - __tableswitch = 170, - __lookupswitch = 171, - __ireturn = 172, - __lreturn = 173, - __freturn = 174, - __dreturn = 175, - __areturn = 176, - __return = 177, - __getstatic = 178, - __putstatic = 179, - __getfield = 180, - __putfield = 181, - __invokevirtual = 182, - __invokespecial = 183, - __invokestatic = 184, - __invokeinterface = 185, - __invokedynamic = 186, - __new = 187, - __newarray = 188, - __anewarray = 189, - __arraylength = 190, - __athrow = 191, - __checkcast = 192, - __instanceof = 193, - __monitorenter = 194, - __monitorexit = 195, - __multianewarray = 197, - __ifnull = 198, - __ifnonnull = 199, - // This is where the pseudo-bytecodes start - __privileged_invokestatic = 235, // the privileged bytecodes are used for accessing host class members - __privileged_invokevirtual = 237, - __privileged_invokespecial = 238, - __ldc_nothrow = 239, - __methodhandle_invoke = 240, - __methodhandle_link = 241, - __goto_finally = 242, - __intrinsic_gettype = 243, - __athrow_no_unmap = 244, - __dynamic_getstatic = 245, - __dynamic_putstatic = 246, - __dynamic_getfield = 247, - __dynamic_putfield = 248, - __dynamic_invokeinterface = 249, - __dynamic_invokestatic = 250, - __dynamic_invokevirtual = 251, - __dynamic_invokespecial = 252, - __clone_array = 253, - __static_error = 254, // not a real instruction, this signals an instruction that is compiled as an exception - __iconst = 255 -} + + enum NormalizedByteCode : byte + { + + __nop = 0, + __aconst_null = 1, + __lconst_0 = 9, + __lconst_1 = 10, + __fconst_0 = 11, + __fconst_1 = 12, + __fconst_2 = 13, + __dconst_0 = 14, + __dconst_1 = 15, + __ldc = 18, + __iload = 21, + __lload = 22, + __fload = 23, + __dload = 24, + __aload = 25, + __iaload = 46, + __laload = 47, + __faload = 48, + __daload = 49, + __aaload = 50, + __baload = 51, + __caload = 52, + __saload = 53, + __istore = 54, + __lstore = 55, + __fstore = 56, + __dstore = 57, + __astore = 58, + __iastore = 79, + __lastore = 80, + __fastore = 81, + __dastore = 82, + __aastore = 83, + __bastore = 84, + __castore = 85, + __sastore = 86, + __pop = 87, + __pop2 = 88, + __dup = 89, + __dup_x1 = 90, + __dup_x2 = 91, + __dup2 = 92, + __dup2_x1 = 93, + __dup2_x2 = 94, + __swap = 95, + __iadd = 96, + __ladd = 97, + __fadd = 98, + __dadd = 99, + __isub = 100, + __lsub = 101, + __fsub = 102, + __dsub = 103, + __imul = 104, + __lmul = 105, + __fmul = 106, + __dmul = 107, + __idiv = 108, + __ldiv = 109, + __fdiv = 110, + __ddiv = 111, + __irem = 112, + __lrem = 113, + __frem = 114, + __drem = 115, + __ineg = 116, + __lneg = 117, + __fneg = 118, + __dneg = 119, + __ishl = 120, + __lshl = 121, + __ishr = 122, + __lshr = 123, + __iushr = 124, + __lushr = 125, + __iand = 126, + __land = 127, + __ior = 128, + __lor = 129, + __ixor = 130, + __lxor = 131, + __iinc = 132, + __i2l = 133, + __i2f = 134, + __i2d = 135, + __l2i = 136, + __l2f = 137, + __l2d = 138, + __f2i = 139, + __f2l = 140, + __f2d = 141, + __d2i = 142, + __d2l = 143, + __d2f = 144, + __i2b = 145, + __i2c = 146, + __i2s = 147, + __lcmp = 148, + __fcmpl = 149, + __fcmpg = 150, + __dcmpl = 151, + __dcmpg = 152, + __ifeq = 153, + __ifne = 154, + __iflt = 155, + __ifge = 156, + __ifgt = 157, + __ifle = 158, + __if_icmpeq = 159, + __if_icmpne = 160, + __if_icmplt = 161, + __if_icmpge = 162, + __if_icmpgt = 163, + __if_icmple = 164, + __if_acmpeq = 165, + __if_acmpne = 166, + __goto = 167, + __jsr = 168, + __ret = 169, + __tableswitch = 170, + __lookupswitch = 171, + __ireturn = 172, + __lreturn = 173, + __freturn = 174, + __dreturn = 175, + __areturn = 176, + __return = 177, + __getstatic = 178, + __putstatic = 179, + __getfield = 180, + __putfield = 181, + __invokevirtual = 182, + __invokespecial = 183, + __invokestatic = 184, + __invokeinterface = 185, + __invokedynamic = 186, + __new = 187, + __newarray = 188, + __anewarray = 189, + __arraylength = 190, + __athrow = 191, + __checkcast = 192, + __instanceof = 193, + __monitorenter = 194, + __monitorexit = 195, + __multianewarray = 197, + __ifnull = 198, + __ifnonnull = 199, + // This is where the pseudo-bytecodes start + __privileged_invokestatic = 235, // the privileged bytecodes are used for accessing host class members + __privileged_invokevirtual = 237, + __privileged_invokespecial = 238, + __ldc_nothrow = 239, + __methodhandle_invoke = 240, + __methodhandle_link = 241, + __goto_finally = 242, + __intrinsic_gettype = 243, + __athrow_no_unmap = 244, + __dynamic_getstatic = 245, + __dynamic_putstatic = 246, + __dynamic_getfield = 247, + __dynamic_putfield = 248, + __dynamic_invokeinterface = 249, + __dynamic_invokestatic = 250, + __dynamic_invokevirtual = 251, + __dynamic_invokespecial = 252, + __clone_array = 253, + __static_error = 254, // not a real instruction, this signals an instruction that is compiled as an exception + __iconst = 255 + + } + +} \ No newline at end of file diff --git a/src/IKVM.Runtime/PrimitiveTypeWrapper.cs b/src/IKVM.Runtime/PrimitiveTypeWrapper.cs index bd6d579d59..4791e53e29 100644 --- a/src/IKVM.Runtime/PrimitiveTypeWrapper.cs +++ b/src/IKVM.Runtime/PrimitiveTypeWrapper.cs @@ -24,7 +24,6 @@ Jeroen Frijters using System; using IKVM.Attributes; -using IKVM.Runtime; #if IMPORTER || EXPORTER using IKVM.Reflection; @@ -36,11 +35,7 @@ Jeroen Frijters using System.Reflection.Emit; #endif -#if IMPORTER -using IKVM.Tools.Importer; -#endif - -namespace IKVM.Internal +namespace IKVM.Runtime { sealed class PrimitiveTypeWrapper : TypeWrapper diff --git a/src/IKVM.Runtime/ReflectUtil.cs b/src/IKVM.Runtime/ReflectUtil.cs index 40576ea1fa..c85b9245b3 100644 --- a/src/IKVM.Runtime/ReflectUtil.cs +++ b/src/IKVM.Runtime/ReflectUtil.cs @@ -32,7 +32,7 @@ Jeroen Frijters using System.Reflection.Emit; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { static class ReflectUtil diff --git a/src/IKVM.Runtime/Serialization.cs b/src/IKVM.Runtime/Serialization.cs index c5f70fa896..00148fc738 100644 --- a/src/IKVM.Runtime/Serialization.cs +++ b/src/IKVM.Runtime/Serialization.cs @@ -25,8 +25,6 @@ Jeroen Frijters using System.Runtime.Serialization; using System.Security; -using IKVM.Runtime; - #if IMPORTER using IKVM.Reflection; using IKVM.Reflection.Emit; @@ -38,7 +36,7 @@ Jeroen Frijters using System.Reflection.Emit; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { static class Serialization diff --git a/src/IKVM.Runtime/SimpleCallMethodWrapper.cs b/src/IKVM.Runtime/SimpleCallMethodWrapper.cs index eadebf62ca..e9fb971dd6 100644 --- a/src/IKVM.Runtime/SimpleCallMethodWrapper.cs +++ b/src/IKVM.Runtime/SimpleCallMethodWrapper.cs @@ -25,19 +25,13 @@ Jeroen Frijters #if IMPORTER || EXPORTER using IKVM.Reflection; -using IKVM.Reflection.Emit; - -using Type = IKVM.Reflection.Type; #else using System.Reflection; #endif -#if IMPORTER -using IKVM.Tools.Importer; -#endif - -namespace IKVM.Internal +namespace IKVM.Runtime { + sealed class SimpleCallMethodWrapper : MethodWrapper { diff --git a/src/IKVM.Runtime/SimpleFieldWrapper.cs b/src/IKVM.Runtime/SimpleFieldWrapper.cs index 30b1ab6b65..73e51fd8bd 100644 --- a/src/IKVM.Runtime/SimpleFieldWrapper.cs +++ b/src/IKVM.Runtime/SimpleFieldWrapper.cs @@ -23,25 +23,20 @@ Jeroen Frijters */ using System.Diagnostics; -using IKVM.Runtime; - #if IMPORTER || EXPORTER using IKVM.Reflection; using IKVM.Reflection.Emit; - -using Type = IKVM.Reflection.Type; #else using System.Reflection; using System.Reflection.Emit; using System.Threading; - #endif #if IMPORTER using IKVM.Tools.Importer; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { /// diff --git a/src/IKVM.Runtime/SimpleOpCode.cs b/src/IKVM.Runtime/SimpleOpCode.cs index fd4eba0789..e01c28878f 100644 --- a/src/IKVM.Runtime/SimpleOpCode.cs +++ b/src/IKVM.Runtime/SimpleOpCode.cs @@ -22,25 +22,16 @@ Jeroen Frijters */ -#if IMPORTER || EXPORTER -using IKVM.Reflection; -using IKVM.Reflection.Emit; - -using Type = IKVM.Reflection.Type; -#else -#endif - -#if IMPORTER -using IKVM.Tools.Importer; -#endif - -namespace IKVM.Internal +namespace IKVM.Runtime { + enum SimpleOpCode : byte { + Call, Callvirt, Newobj + } } diff --git a/src/IKVM.Runtime/SmartMethodWrapper.cs b/src/IKVM.Runtime/SmartMethodWrapper.cs index 74d34cbe33..96399c90b3 100644 --- a/src/IKVM.Runtime/SmartMethodWrapper.cs +++ b/src/IKVM.Runtime/SmartMethodWrapper.cs @@ -27,19 +27,13 @@ Jeroen Frijters #if IMPORTER || EXPORTER using IKVM.Reflection; -using IKVM.Reflection.Emit; - -using Type = IKVM.Reflection.Type; #else using System.Reflection; #endif -#if IMPORTER -using IKVM.Tools.Importer; -#endif - -namespace IKVM.Internal +namespace IKVM.Runtime { + abstract class SmartMethodWrapper : MethodWrapper { diff --git a/src/IKVM.Runtime/StackState.cs b/src/IKVM.Runtime/StackState.cs new file mode 100644 index 0000000000..f0db760331 --- /dev/null +++ b/src/IKVM.Runtime/StackState.cs @@ -0,0 +1,122 @@ +/* + Copyright (C) 2002-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ + +namespace IKVM.Runtime +{ + + struct StackState + { + + private InstructionState state; + private int sp; + + internal StackState(InstructionState state) + { + this.state = state; + sp = state.GetStackHeight(); + } + + internal TypeWrapper PeekType() + { + if (sp == 0) + { + throw new VerifyError("Unable to pop operand off an empty stack"); + } + TypeWrapper type = state.GetStackByIndex(sp - 1); + if (VerifierTypeWrapper.IsThis(type)) + { + type = ((VerifierTypeWrapper)type).UnderlyingType; + } + return type; + } + + internal TypeWrapper PopAnyType() + { + if (sp == 0) + { + throw new VerifyError("Unable to pop operand off an empty stack"); + } + TypeWrapper type = state.GetStackByIndex(--sp); + if (VerifierTypeWrapper.IsThis(type)) + { + type = ((VerifierTypeWrapper)type).UnderlyingType; + } + if (VerifierTypeWrapper.IsFaultBlockException(type)) + { + VerifierTypeWrapper.ClearFaultBlockException(type); + type = CoreClasses.java.lang.Throwable.Wrapper; + } + return type; + } + + internal TypeWrapper PopType(TypeWrapper baseType) + { + return InstructionState.PopTypeImpl(baseType, PopAnyType()); + } + + // NOTE this can *not* be used to pop double or long + internal TypeWrapper PopType() + { + return InstructionState.PopTypeImpl(PopAnyType()); + } + + internal void PopInt() + { + InstructionState.PopIntImpl(PopAnyType()); + } + + internal void PopFloat() + { + InstructionState.PopFloatImpl(PopAnyType()); + } + + internal void PopDouble() + { + InstructionState.PopDoubleImpl(PopAnyType()); + } + + internal void PopLong() + { + InstructionState.PopLongImpl(PopAnyType()); + } + + internal TypeWrapper PopArrayType() + { + return InstructionState.PopArrayTypeImpl(PopAnyType()); + } + + // either null or an initialized object reference + internal TypeWrapper PopObjectType() + { + return InstructionState.PopObjectTypeImpl(PopAnyType()); + } + + // null or an initialized object reference derived from baseType (or baseType) + internal TypeWrapper PopObjectType(TypeWrapper baseType) + { + return InstructionState.PopObjectTypeImpl(baseType, PopObjectType()); + } + } + +} diff --git a/src/IKVM.Runtime/StringConstants.cs b/src/IKVM.Runtime/StringConstants.cs index 1cc5f1f221..6cf5a8e554 100644 --- a/src/IKVM.Runtime/StringConstants.cs +++ b/src/IKVM.Runtime/StringConstants.cs @@ -22,7 +22,7 @@ Jeroen Frijters */ -namespace IKVM.Internal +namespace IKVM.Runtime { static class StringConstants diff --git a/src/IKVM.Runtime/StubGen/AnnotationDefaultClassFileAttribute.cs b/src/IKVM.Runtime/StubGen/AnnotationDefaultClassFileAttribute.cs index b033003c56..46996f0fb1 100644 --- a/src/IKVM.Runtime/StubGen/AnnotationDefaultClassFileAttribute.cs +++ b/src/IKVM.Runtime/StubGen/AnnotationDefaultClassFileAttribute.cs @@ -24,8 +24,10 @@ Jeroen Frijters namespace IKVM.StubGen { + sealed class AnnotationDefaultClassFileAttribute : ClassFileAttribute { + private ClassFileWriter classFile; private byte[] buf; @@ -45,5 +47,7 @@ public override void Write(BigEndianStream bes) bes.WriteByte(b); } } + } + } diff --git a/src/IKVM.Runtime/StubGen/BigEndianStream.cs b/src/IKVM.Runtime/StubGen/BigEndianStream.cs index 6a6ca46b13..3c667aeae4 100644 --- a/src/IKVM.Runtime/StubGen/BigEndianStream.cs +++ b/src/IKVM.Runtime/StubGen/BigEndianStream.cs @@ -26,8 +26,10 @@ Jeroen Frijters namespace IKVM.StubGen { + sealed class BigEndianStream { + private Stream stream; public BigEndianStream(Stream stream) @@ -108,5 +110,7 @@ public void WriteUtf8(string str) WriteUInt16((ushort)j); stream.Write(buf, 0, j); } + } + } diff --git a/src/IKVM.Runtime/StubGen/ClassFileAttribute.cs b/src/IKVM.Runtime/StubGen/ClassFileAttribute.cs index 8ef21b5c5f..ab5e1e2b50 100644 --- a/src/IKVM.Runtime/StubGen/ClassFileAttribute.cs +++ b/src/IKVM.Runtime/StubGen/ClassFileAttribute.cs @@ -24,8 +24,10 @@ Jeroen Frijters namespace IKVM.StubGen { + abstract class ClassFileAttribute { + private ushort name_index; public ClassFileAttribute(ushort name_index) @@ -37,5 +39,7 @@ public virtual void Write(BigEndianStream bes) { bes.WriteUInt16(name_index); } + } + } diff --git a/src/IKVM.Runtime/StubGen/ClassFileWriter.cs b/src/IKVM.Runtime/StubGen/ClassFileWriter.cs index 5c306b2aeb..11ed4748dd 100644 --- a/src/IKVM.Runtime/StubGen/ClassFileWriter.cs +++ b/src/IKVM.Runtime/StubGen/ClassFileWriter.cs @@ -32,6 +32,7 @@ namespace IKVM.StubGen sealed class ClassFileWriter : IAttributeOwner { + private List cplist = new List(); private Dictionary cphashtable = new Dictionary(); private List fields = new List(); @@ -239,6 +240,7 @@ public void Write(Stream stream) attribs[i].Write(bes); } } + } } diff --git a/src/IKVM.Runtime/StubGen/CodeAttribute.cs b/src/IKVM.Runtime/StubGen/CodeAttribute.cs index d41460a81f..a73de1dd3d 100644 --- a/src/IKVM.Runtime/StubGen/CodeAttribute.cs +++ b/src/IKVM.Runtime/StubGen/CodeAttribute.cs @@ -24,8 +24,10 @@ Jeroen Frijters namespace IKVM.StubGen { + sealed class CodeAttribute : ClassFileAttribute { + private ClassFileWriter classFile; private ushort max_stack; private ushort max_locals; @@ -69,5 +71,7 @@ public override void Write(BigEndianStream bes) bes.WriteUInt16(0); // no exceptions bes.WriteUInt16(0); // no attributes } + } + } diff --git a/src/IKVM.Runtime/StubGen/Constant.cs b/src/IKVM.Runtime/StubGen/Constant.cs index 023e4bce59..d45bbb6ec2 100644 --- a/src/IKVM.Runtime/StubGen/Constant.cs +++ b/src/IKVM.Runtime/StubGen/Constant.cs @@ -24,8 +24,10 @@ Jeroen Frijters namespace IKVM.StubGen { + enum Constant { + Utf8 = 1, Integer = 3, Float = 4, @@ -37,5 +39,7 @@ enum Constant Methodref = 10, InterfaceMethodref = 11, NameAndType = 12 + } + } diff --git a/src/IKVM.Runtime/StubGen/ConstantPoolItem.cs b/src/IKVM.Runtime/StubGen/ConstantPoolItem.cs index 36a7c89d09..9a17aea004 100644 --- a/src/IKVM.Runtime/StubGen/ConstantPoolItem.cs +++ b/src/IKVM.Runtime/StubGen/ConstantPoolItem.cs @@ -24,8 +24,11 @@ Jeroen Frijters namespace IKVM.StubGen { + abstract class ConstantPoolItem - { - public abstract void Write(BigEndianStream bes); - } + { + + public abstract void Write(BigEndianStream bes); + } + } diff --git a/src/IKVM.Runtime/StubGen/ConstantPoolItemClass.cs b/src/IKVM.Runtime/StubGen/ConstantPoolItemClass.cs index 92d5a80f3f..6e9ccb6d25 100644 --- a/src/IKVM.Runtime/StubGen/ConstantPoolItemClass.cs +++ b/src/IKVM.Runtime/StubGen/ConstantPoolItemClass.cs @@ -24,8 +24,10 @@ Jeroen Frijters namespace IKVM.StubGen { + sealed class ConstantPoolItemClass : ConstantPoolItem { + private ushort name_index; public ConstantPoolItemClass(ushort name_index) @@ -52,5 +54,7 @@ public override void Write(BigEndianStream bes) bes.WriteByte((byte)Constant.Class); bes.WriteUInt16(name_index); } + } + } diff --git a/src/IKVM.Runtime/StubGen/ConstantPoolItemDouble.cs b/src/IKVM.Runtime/StubGen/ConstantPoolItemDouble.cs index 7553259445..2024f0f95a 100644 --- a/src/IKVM.Runtime/StubGen/ConstantPoolItemDouble.cs +++ b/src/IKVM.Runtime/StubGen/ConstantPoolItemDouble.cs @@ -25,8 +25,10 @@ Jeroen Frijters namespace IKVM.StubGen { + sealed class ConstantPoolItemDouble : ConstantPoolItem { + private double v; public ConstantPoolItemDouble(double v) @@ -54,5 +56,7 @@ public override void Write(BigEndianStream bes) bes.WriteByte((byte)Constant.Double); bes.WriteDouble(v); } + } + } diff --git a/src/IKVM.Runtime/StubGen/ConstantPoolItemFloat.cs b/src/IKVM.Runtime/StubGen/ConstantPoolItemFloat.cs index 043193d6c1..a9e65f7495 100644 --- a/src/IKVM.Runtime/StubGen/ConstantPoolItemFloat.cs +++ b/src/IKVM.Runtime/StubGen/ConstantPoolItemFloat.cs @@ -25,8 +25,10 @@ Jeroen Frijters namespace IKVM.StubGen { + sealed class ConstantPoolItemFloat : ConstantPoolItem { + private float v; public ConstantPoolItemFloat(float v) @@ -53,5 +55,7 @@ public override void Write(BigEndianStream bes) bes.WriteByte((byte)Constant.Float); bes.WriteFloat(v); } + } + } diff --git a/src/IKVM.Runtime/StubGen/ConstantPoolItemInt.cs b/src/IKVM.Runtime/StubGen/ConstantPoolItemInt.cs index 25dbc71fc7..6671a04d76 100644 --- a/src/IKVM.Runtime/StubGen/ConstantPoolItemInt.cs +++ b/src/IKVM.Runtime/StubGen/ConstantPoolItemInt.cs @@ -24,8 +24,10 @@ Jeroen Frijters namespace IKVM.StubGen { + sealed class ConstantPoolItemInt : ConstantPoolItem { + private int v; public ConstantPoolItemInt(int v) @@ -52,5 +54,7 @@ public override void Write(BigEndianStream bes) bes.WriteByte((byte)Constant.Integer); bes.WriteUInt32((uint)v); } + } + } diff --git a/src/IKVM.Runtime/StubGen/ConstantPoolItemLong.cs b/src/IKVM.Runtime/StubGen/ConstantPoolItemLong.cs index 4f044962d3..4ea35e09f8 100644 --- a/src/IKVM.Runtime/StubGen/ConstantPoolItemLong.cs +++ b/src/IKVM.Runtime/StubGen/ConstantPoolItemLong.cs @@ -24,8 +24,10 @@ Jeroen Frijters namespace IKVM.StubGen { + sealed class ConstantPoolItemLong : ConstantPoolItem { + private long v; public ConstantPoolItemLong(long v) @@ -52,5 +54,7 @@ public override void Write(BigEndianStream bes) bes.WriteByte((byte)Constant.Long); bes.WriteInt64(v); } + } + } diff --git a/src/IKVM.Runtime/StubGen/ConstantPoolItemMethodref.cs b/src/IKVM.Runtime/StubGen/ConstantPoolItemMethodref.cs index 3f424d9e1e..a348e5225e 100644 --- a/src/IKVM.Runtime/StubGen/ConstantPoolItemMethodref.cs +++ b/src/IKVM.Runtime/StubGen/ConstantPoolItemMethodref.cs @@ -24,8 +24,10 @@ Jeroen Frijters namespace IKVM.StubGen { + sealed class ConstantPoolItemMethodref : ConstantPoolItem { + private ushort class_index; private ushort name_and_type_index; @@ -56,5 +58,7 @@ public override void Write(BigEndianStream bes) bes.WriteUInt16(class_index); bes.WriteUInt16(name_and_type_index); } + } + } diff --git a/src/IKVM.Runtime/StubGen/ConstantPoolItemNameAndType.cs b/src/IKVM.Runtime/StubGen/ConstantPoolItemNameAndType.cs index 977b5e9dfd..c946e069d0 100644 --- a/src/IKVM.Runtime/StubGen/ConstantPoolItemNameAndType.cs +++ b/src/IKVM.Runtime/StubGen/ConstantPoolItemNameAndType.cs @@ -24,8 +24,10 @@ Jeroen Frijters namespace IKVM.StubGen { + sealed class ConstantPoolItemNameAndType : ConstantPoolItem { + private ushort name_index; private ushort descriptor_index; @@ -56,5 +58,7 @@ public override void Write(BigEndianStream bes) bes.WriteUInt16(name_index); bes.WriteUInt16(descriptor_index); } + } + } diff --git a/src/IKVM.Runtime/StubGen/ConstantPoolItemString.cs b/src/IKVM.Runtime/StubGen/ConstantPoolItemString.cs index 34938d8e27..08a1a0e495 100644 --- a/src/IKVM.Runtime/StubGen/ConstantPoolItemString.cs +++ b/src/IKVM.Runtime/StubGen/ConstantPoolItemString.cs @@ -24,8 +24,10 @@ Jeroen Frijters namespace IKVM.StubGen { + sealed class ConstantPoolItemString : ConstantPoolItem { + private ushort string_index; public ConstantPoolItemString(ushort string_index) @@ -52,5 +54,7 @@ public override void Write(BigEndianStream bes) bes.WriteByte((byte)Constant.String); bes.WriteUInt16(string_index); } + } + } diff --git a/src/IKVM.Runtime/StubGen/ConstantPoolItemUtf8.cs b/src/IKVM.Runtime/StubGen/ConstantPoolItemUtf8.cs index 518c9cd029..bc1fe7cb40 100644 --- a/src/IKVM.Runtime/StubGen/ConstantPoolItemUtf8.cs +++ b/src/IKVM.Runtime/StubGen/ConstantPoolItemUtf8.cs @@ -24,8 +24,10 @@ Jeroen Frijters namespace IKVM.StubGen { + sealed class ConstantPoolItemUtf8 : ConstantPoolItem { + private string str; public ConstantPoolItemUtf8(string str) @@ -52,5 +54,7 @@ public override void Write(BigEndianStream bes) bes.WriteByte((byte)Constant.Utf8); bes.WriteUtf8(str); } + } + } diff --git a/src/IKVM.Runtime/StubGen/ConstantValueAttribute.cs b/src/IKVM.Runtime/StubGen/ConstantValueAttribute.cs index 43a1b026ea..d35d884282 100644 --- a/src/IKVM.Runtime/StubGen/ConstantValueAttribute.cs +++ b/src/IKVM.Runtime/StubGen/ConstantValueAttribute.cs @@ -24,8 +24,10 @@ Jeroen Frijters namespace IKVM.StubGen { + sealed class ConstantValueAttribute : ClassFileAttribute { + private ushort constant_index; public ConstantValueAttribute(ushort name_index, ushort constant_index) @@ -40,5 +42,7 @@ public override void Write(BigEndianStream bes) bes.WriteUInt32(2); bes.WriteUInt16(constant_index); } + } + } diff --git a/src/IKVM.Runtime/StubGen/DeprecatedAttribute.cs b/src/IKVM.Runtime/StubGen/DeprecatedAttribute.cs index 9c94944ce6..15ca9fd5c3 100644 --- a/src/IKVM.Runtime/StubGen/DeprecatedAttribute.cs +++ b/src/IKVM.Runtime/StubGen/DeprecatedAttribute.cs @@ -24,8 +24,10 @@ Jeroen Frijters namespace IKVM.StubGen { + sealed class DeprecatedAttribute : ClassFileAttribute { + internal DeprecatedAttribute(ClassFileWriter classFile) : base(classFile.AddUtf8("Deprecated")) { @@ -36,5 +38,7 @@ public override void Write(BigEndianStream bes) base.Write(bes); bes.WriteUInt32(0); } + } + } diff --git a/src/IKVM.Runtime/StubGen/ExceptionsAttribute.cs b/src/IKVM.Runtime/StubGen/ExceptionsAttribute.cs index da454f3a6d..49caff7318 100644 --- a/src/IKVM.Runtime/StubGen/ExceptionsAttribute.cs +++ b/src/IKVM.Runtime/StubGen/ExceptionsAttribute.cs @@ -25,8 +25,10 @@ Jeroen Frijters namespace IKVM.StubGen { + sealed class ExceptionsAttribute : ClassFileAttribute { + private ClassFileWriter classFile; private List classes = new List(); @@ -51,5 +53,7 @@ public override void Write(BigEndianStream bes) bes.WriteUInt16(idx); } } + } + } diff --git a/src/IKVM.Runtime/StubGen/FieldOrMethod.cs b/src/IKVM.Runtime/StubGen/FieldOrMethod.cs index 6e27f8363f..14699a6f60 100644 --- a/src/IKVM.Runtime/StubGen/FieldOrMethod.cs +++ b/src/IKVM.Runtime/StubGen/FieldOrMethod.cs @@ -27,8 +27,10 @@ Jeroen Frijters namespace IKVM.StubGen { + sealed class FieldOrMethod : IAttributeOwner { + private Modifiers access_flags; private ushort name_index; private ushort descriptor_index; @@ -57,5 +59,7 @@ public void Write(BigEndianStream bes) attribs[i].Write(bes); } } + } + } diff --git a/src/IKVM.Runtime/StubGen/IAttributeOwner.cs b/src/IKVM.Runtime/StubGen/IAttributeOwner.cs index a5c2035340..d1a00616c2 100644 --- a/src/IKVM.Runtime/StubGen/IAttributeOwner.cs +++ b/src/IKVM.Runtime/StubGen/IAttributeOwner.cs @@ -24,8 +24,12 @@ Jeroen Frijters namespace IKVM.StubGen { + interface IAttributeOwner { + void AddAttribute(ClassFileAttribute attrib); + } + } diff --git a/src/IKVM.Runtime/StubGen/InnerClassesAttribute.cs b/src/IKVM.Runtime/StubGen/InnerClassesAttribute.cs index 38a98761a4..ac05c5c2da 100644 --- a/src/IKVM.Runtime/StubGen/InnerClassesAttribute.cs +++ b/src/IKVM.Runtime/StubGen/InnerClassesAttribute.cs @@ -25,8 +25,10 @@ Jeroen Frijters namespace IKVM.StubGen { + sealed class InnerClassesAttribute : ClassFileAttribute { + private ClassFileWriter classFile; private List classes = new List(); @@ -70,5 +72,7 @@ public void Add(string inner, string outer, string name, ushort access) i.inner_class_access_flags = access; classes.Add(i); } + } + } diff --git a/src/IKVM.Runtime/StubGen/MethodParametersAttribute.cs b/src/IKVM.Runtime/StubGen/MethodParametersAttribute.cs index 1f34df3621..5b79728c01 100644 --- a/src/IKVM.Runtime/StubGen/MethodParametersAttribute.cs +++ b/src/IKVM.Runtime/StubGen/MethodParametersAttribute.cs @@ -24,8 +24,10 @@ Jeroen Frijters namespace IKVM.StubGen { + sealed class MethodParametersAttribute : ClassFileAttribute { + private readonly ClassFileWriter classFile; private readonly ushort[] names; private readonly ushort[] flags; @@ -55,5 +57,7 @@ public override void Write(BigEndianStream bes) bes.WriteUInt16(flags[i]); } } + } + } diff --git a/src/IKVM.Runtime/StubGen/RuntimeVisibleAnnotationsAttribute.cs b/src/IKVM.Runtime/StubGen/RuntimeVisibleAnnotationsAttribute.cs index 5674f0f198..c4eea5710d 100644 --- a/src/IKVM.Runtime/StubGen/RuntimeVisibleAnnotationsAttribute.cs +++ b/src/IKVM.Runtime/StubGen/RuntimeVisibleAnnotationsAttribute.cs @@ -27,8 +27,10 @@ Jeroen Frijters namespace IKVM.StubGen { + sealed class RuntimeVisibleAnnotationsAttribute : ClassFileAttribute { + private ClassFileWriter classFile; private MemoryStream mem; private BigEndianStream bes; @@ -176,5 +178,7 @@ internal uint Length { get { return (uint)mem.Length + 2; } } + } + } diff --git a/src/IKVM.Runtime/StubGen/RuntimeVisibleParameterAnnotationsAttribute.cs b/src/IKVM.Runtime/StubGen/RuntimeVisibleParameterAnnotationsAttribute.cs index 718307d1e6..aee6935a78 100644 --- a/src/IKVM.Runtime/StubGen/RuntimeVisibleParameterAnnotationsAttribute.cs +++ b/src/IKVM.Runtime/StubGen/RuntimeVisibleParameterAnnotationsAttribute.cs @@ -25,8 +25,10 @@ Jeroen Frijters namespace IKVM.StubGen { + sealed class RuntimeVisibleParameterAnnotationsAttribute : ClassFileAttribute { + private readonly List parameters = new List(); internal RuntimeVisibleParameterAnnotationsAttribute(ClassFileWriter classFile) @@ -54,5 +56,7 @@ public override void Write(BigEndianStream bes) attr.WriteImpl(bes); } } + } + } diff --git a/src/IKVM.Runtime/StubGen/RuntimeVisibleTypeAnnotationsAttribute.cs b/src/IKVM.Runtime/StubGen/RuntimeVisibleTypeAnnotationsAttribute.cs index 0703a3b510..8256941d79 100644 --- a/src/IKVM.Runtime/StubGen/RuntimeVisibleTypeAnnotationsAttribute.cs +++ b/src/IKVM.Runtime/StubGen/RuntimeVisibleTypeAnnotationsAttribute.cs @@ -24,8 +24,10 @@ Jeroen Frijters namespace IKVM.StubGen { + sealed class RuntimeVisibleTypeAnnotationsAttribute : ClassFileAttribute { + private readonly byte[] data; internal RuntimeVisibleTypeAnnotationsAttribute(ClassFileWriter classFile, byte[] data) @@ -40,5 +42,7 @@ public override void Write(BigEndianStream bes) bes.WriteUInt32((uint)data.Length); bes.WriteBytes(data); } + } + } diff --git a/src/IKVM.Runtime/StubGen/SerialVersionUID.cs b/src/IKVM.Runtime/StubGen/SerialVersionUID.cs index 915dec98d9..147a1a2ea1 100644 --- a/src/IKVM.Runtime/StubGen/SerialVersionUID.cs +++ b/src/IKVM.Runtime/StubGen/SerialVersionUID.cs @@ -26,7 +26,7 @@ Jeroen Frijters using System.Security.Cryptography; using IKVM.Attributes; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.StubGen { @@ -34,6 +34,7 @@ namespace IKVM.StubGen static class SerialVersionUID { + readonly static SHA1 sha1 = SHA1.Create(); internal static long Compute(TypeWrapper tw) diff --git a/src/IKVM.Runtime/StubGen/StringAttribute.cs b/src/IKVM.Runtime/StubGen/StringAttribute.cs index d7e4e1dcb3..79f8377d99 100644 --- a/src/IKVM.Runtime/StubGen/StringAttribute.cs +++ b/src/IKVM.Runtime/StubGen/StringAttribute.cs @@ -24,8 +24,10 @@ Jeroen Frijters namespace IKVM.StubGen { + sealed class StringAttribute : ClassFileAttribute { + private ushort string_index; public StringAttribute(ushort name_index, ushort string_index) @@ -40,5 +42,7 @@ public override void Write(BigEndianStream bes) bes.WriteUInt32(2); bes.WriteUInt16(string_index); } + } + } diff --git a/src/IKVM.Runtime/StubGen/StubGenerator.cs b/src/IKVM.Runtime/StubGen/StubGenerator.cs index 3e08781a38..c04e1389e2 100644 --- a/src/IKVM.Runtime/StubGen/StubGenerator.cs +++ b/src/IKVM.Runtime/StubGen/StubGenerator.cs @@ -26,7 +26,6 @@ Jeroen Frijters using System.Collections.Generic; using IKVM.Attributes; -using IKVM.Internal; using IKVM.Runtime; #if EXPORTER diff --git a/src/IKVM.Runtime/TypeFlags.cs b/src/IKVM.Runtime/TypeFlags.cs index 8d942f5521..73b9ea6f72 100644 --- a/src/IKVM.Runtime/TypeFlags.cs +++ b/src/IKVM.Runtime/TypeFlags.cs @@ -24,7 +24,7 @@ Jeroen Frijters using System; -namespace IKVM.Internal +namespace IKVM.Runtime { [Flags] diff --git a/src/IKVM.Runtime/TypeNameUtil.cs b/src/IKVM.Runtime/TypeNameUtil.cs index ba501098ef..b491902766 100644 --- a/src/IKVM.Runtime/TypeNameUtil.cs +++ b/src/IKVM.Runtime/TypeNameUtil.cs @@ -22,22 +22,12 @@ Jeroen Frijters */ -#if IMPORTER || EXPORTER -using IKVM.Reflection; -using IKVM.Reflection.Emit; - -using Type = IKVM.Reflection.Type; -#else -#endif - -#if IMPORTER -using IKVM.Tools.Importer; -#endif - -namespace IKVM.Internal +namespace IKVM.Runtime { + static class TypeNameUtil { + // note that MangleNestedTypeName() assumes that there are less than 16 special characters private const string specialCharactersString = "\\+,[]*&\u0000"; internal const string ProxiesContainer = "__"; @@ -149,6 +139,7 @@ internal static string GetProxyName(TypeWrapper[] interfaces) { return ProxiesContainer + "+" + GetProxyNestedName(interfaces); } + } } diff --git a/src/IKVM.Runtime/TypeWrapper.cs b/src/IKVM.Runtime/TypeWrapper.cs index 8b5c8343c0..23c6c849fc 100644 --- a/src/IKVM.Runtime/TypeWrapper.cs +++ b/src/IKVM.Runtime/TypeWrapper.cs @@ -26,7 +26,6 @@ Jeroen Frijters using System.Diagnostics; using IKVM.Attributes; -using IKVM.Runtime; #if IMPORTER || EXPORTER using IKVM.Reflection; @@ -42,7 +41,7 @@ Jeroen Frijters using IKVM.Tools.Importer; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { /// diff --git a/src/IKVM.Runtime/TypeWrapperFactory.cs b/src/IKVM.Runtime/TypeWrapperFactory.cs index dba010a90f..dab144844e 100644 --- a/src/IKVM.Runtime/TypeWrapperFactory.cs +++ b/src/IKVM.Runtime/TypeWrapperFactory.cs @@ -25,13 +25,10 @@ Jeroen Frijters using System; using System.Collections.Generic; -#if NETCOREAPP -using System.Runtime.Loader; -#endif - #if IMPORTER || EXPORTER using IKVM.Reflection; using IKVM.Reflection.Emit; + using Type = IKVM.Reflection.Type; using ProtectionDomain = System.Object; #else @@ -41,7 +38,7 @@ Jeroen Frijters using ProtectionDomain = java.security.ProtectionDomain; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { #if !EXPORTER diff --git a/src/IKVM.Runtime/Types.cs b/src/IKVM.Runtime/Types.cs index 7b2718bb11..bafb1525c3 100644 --- a/src/IKVM.Runtime/Types.cs +++ b/src/IKVM.Runtime/Types.cs @@ -23,13 +23,11 @@ Jeroen Frijters */ using System; -using IKVM.Runtime; - #if IMPORTER || EXPORTER using Type = IKVM.Reflection.Type; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { static class Types diff --git a/src/IKVM.Runtime/TypicalMethodWrapper.cs b/src/IKVM.Runtime/TypicalMethodWrapper.cs index d1f96eab13..88ab6530e5 100644 --- a/src/IKVM.Runtime/TypicalMethodWrapper.cs +++ b/src/IKVM.Runtime/TypicalMethodWrapper.cs @@ -33,11 +33,7 @@ Jeroen Frijters using System.Reflection.Emit; #endif -#if IMPORTER -using IKVM.Tools.Importer; -#endif - -namespace IKVM.Internal +namespace IKVM.Runtime { sealed class TypicalMethodWrapper : SmartMethodWrapper { diff --git a/src/IKVM.Runtime/UnicodeUtil.cs b/src/IKVM.Runtime/UnicodeUtil.cs index df47087142..3955f23ab7 100644 --- a/src/IKVM.Runtime/UnicodeUtil.cs +++ b/src/IKVM.Runtime/UnicodeUtil.cs @@ -23,22 +23,12 @@ Jeroen Frijters */ using System; -#if IMPORTER || EXPORTER -using IKVM.Reflection; -using IKVM.Reflection.Emit; - -using Type = IKVM.Reflection.Type; -#else -#endif - -#if IMPORTER -using IKVM.Tools.Importer; -#endif - -namespace IKVM.Internal +namespace IKVM.Runtime { + static class UnicodeUtil { + // We use part of the Supplementary Private Use Area-B to encode // invalid surrogates. If we encounter either of these two // markers, we always encode the surrogate (single or pair) diff --git a/src/IKVM.Runtime/UnloadableTypeWrapper.cs b/src/IKVM.Runtime/UnloadableTypeWrapper.cs index 1e9e7b8399..e484340956 100644 --- a/src/IKVM.Runtime/UnloadableTypeWrapper.cs +++ b/src/IKVM.Runtime/UnloadableTypeWrapper.cs @@ -35,8 +35,9 @@ Jeroen Frijters using IKVM.Tools.Importer; #endif -namespace IKVM.Internal +namespace IKVM.Runtime { + sealed class UnloadableTypeWrapper : TypeWrapper { @@ -66,10 +67,7 @@ internal UnloadableTypeWrapper(string name, Type customModifier) : this.customModifier = customModifier; } - internal override TypeWrapper BaseTypeWrapper - { - get { return null; } - } + internal override TypeWrapper BaseTypeWrapper => null; internal override ClassLoaderWrapper GetClassLoader() { @@ -102,13 +100,7 @@ protected override void LazyPublishMembers() throw new InvalidOperationException("LazyPublishMembers called on UnloadableTypeWrapper: " + Name); } - internal override Type TypeAsTBD - { - get - { - throw new InvalidOperationException("get_Type called on UnloadableTypeWrapper: " + Name); - } - } + internal override Type TypeAsTBD => throw new InvalidOperationException("get_Type called on UnloadableTypeWrapper: " + Name); internal override TypeWrapper[] Interfaces { @@ -126,36 +118,18 @@ internal override TypeWrapper[] Interfaces } } - internal override TypeWrapper[] InnerClasses - { - get - { - throw new InvalidOperationException("get_InnerClasses called on UnloadableTypeWrapper: " + Name); - } - } + internal override TypeWrapper[] InnerClasses => throw new InvalidOperationException("get_InnerClasses called on UnloadableTypeWrapper: " + Name); - internal override TypeWrapper DeclaringTypeWrapper - { - get - { - throw new InvalidOperationException("get_DeclaringTypeWrapper called on UnloadableTypeWrapper: " + Name); - } - } + internal override TypeWrapper DeclaringTypeWrapper => throw new InvalidOperationException("get_DeclaringTypeWrapper called on UnloadableTypeWrapper: " + Name); internal override void Finish() { throw new InvalidOperationException("Finish called on UnloadableTypeWrapper: " + Name); } - internal Type MissingType - { - get { return missingType; } - } + internal Type MissingType => missingType; - internal Type CustomModifier - { - get { return customModifier; } - } + internal Type CustomModifier => customModifier; internal void SetCustomModifier(Type type) { diff --git a/src/IKVM.Runtime/UntangledExceptionTable.cs b/src/IKVM.Runtime/UntangledExceptionTable.cs new file mode 100644 index 0000000000..cf12988fb8 --- /dev/null +++ b/src/IKVM.Runtime/UntangledExceptionTable.cs @@ -0,0 +1,78 @@ +/* + Copyright (C) 2002-2014 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; + +using ExceptionTableEntry = IKVM.Runtime.ClassFile.Method.ExceptionTableEntry; + +namespace IKVM.Runtime +{ + + struct UntangledExceptionTable + { + private readonly ExceptionTableEntry[] exceptions; + + internal UntangledExceptionTable(ExceptionTableEntry[] exceptions) + { +#if DEBUG + for (int i = 0; i < exceptions.Length; i++) + { + for (int j = i + 1; j < exceptions.Length; j++) + { + // check for partially overlapping try blocks (which is legal for the JVM, but not the CLR) + if (exceptions[i].startIndex < exceptions[j].startIndex && + exceptions[j].startIndex < exceptions[i].endIndex && + exceptions[i].endIndex < exceptions[j].endIndex) + { + throw new InvalidOperationException("Partially overlapping try blocks is broken"); + } + // check that we didn't destroy the ordering, when sorting + if (exceptions[i].startIndex <= exceptions[j].startIndex && + exceptions[i].endIndex >= exceptions[j].endIndex && + exceptions[i].ordinal < exceptions[j].ordinal) + { + throw new InvalidOperationException("Non recursive try blocks is broken"); + } + } + } +#endif + this.exceptions = exceptions; + } + + internal ExceptionTableEntry this[int index] + { + get { return exceptions[index]; } + } + + internal int Length + { + get { return exceptions.Length; } + } + + internal void SetFinally(int index) + { + exceptions[index] = new ExceptionTableEntry(exceptions[index].startIndex, exceptions[index].endIndex, exceptions[index].handlerIndex, exceptions[index].catch_type, exceptions[index].ordinal, true); + } + } + +} diff --git a/src/IKVM.Runtime/Util/Java/Lang/Invoke/NativeInvokerBytecodeGenerator.cs b/src/IKVM.Runtime/Util/Java/Lang/Invoke/NativeInvokerBytecodeGenerator.cs index b916d3b281..00c03b8ba4 100644 --- a/src/IKVM.Runtime/Util/Java/Lang/Invoke/NativeInvokerBytecodeGenerator.cs +++ b/src/IKVM.Runtime/Util/Java/Lang/Invoke/NativeInvokerBytecodeGenerator.cs @@ -33,7 +33,7 @@ using System.Reflection.Emit; using IKVM.Attributes; -using IKVM.Internal; +using IKVM.Runtime; using java.lang.invoke; diff --git a/src/IKVM.Runtime/Util/Java/Nio/DirectBufferMemoryManager.cs b/src/IKVM.Runtime/Util/Java/Nio/DirectBufferMemoryManager.cs index 41e48b57ce..a1499920e1 100644 --- a/src/IKVM.Runtime/Util/Java/Nio/DirectBufferMemoryManager.cs +++ b/src/IKVM.Runtime/Util/Java/Nio/DirectBufferMemoryManager.cs @@ -1,7 +1,7 @@ using System; using System.Buffers; -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Runtime.Accessors.Java.Lang; namespace IKVM.Runtime.Util.Java.Nio diff --git a/src/IKVM.Runtime/VerifierTypeWrapper.cs b/src/IKVM.Runtime/VerifierTypeWrapper.cs index 57a57c32ff..f0dec8de74 100644 --- a/src/IKVM.Runtime/VerifierTypeWrapper.cs +++ b/src/IKVM.Runtime/VerifierTypeWrapper.cs @@ -28,15 +28,11 @@ Jeroen Frijters using IKVM.Reflection.Emit; using Type = IKVM.Reflection.Type; -#else #endif -#if IMPORTER -using IKVM.Tools.Importer; -#endif - -namespace IKVM.Internal +namespace IKVM.Runtime { + // this is a container for the special verifier TypeWrappers sealed class VerifierTypeWrapper : TypeWrapper { diff --git a/src/IKVM.Runtime/Vfs/VfsAssemblyClassDirectory.cs b/src/IKVM.Runtime/Vfs/VfsAssemblyClassDirectory.cs index 5cbfb6337b..58a612542a 100644 --- a/src/IKVM.Runtime/Vfs/VfsAssemblyClassDirectory.cs +++ b/src/IKVM.Runtime/Vfs/VfsAssemblyClassDirectory.cs @@ -4,7 +4,7 @@ using System.Linq; using System.Reflection; -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Runtime.Syntax; namespace IKVM.Runtime.Vfs diff --git a/src/IKVM.Runtime/Vfs/VfsAssemblyClassFile.cs b/src/IKVM.Runtime/Vfs/VfsAssemblyClassFile.cs index fae0a0dd20..67ef61a574 100644 --- a/src/IKVM.Runtime/Vfs/VfsAssemblyClassFile.cs +++ b/src/IKVM.Runtime/Vfs/VfsAssemblyClassFile.cs @@ -1,7 +1,7 @@ using System; using System.IO; -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Runtime.Accessors.Java.Lang; namespace IKVM.Runtime.Vfs diff --git a/src/IKVM.Runtime/VolatileLongDoubleFieldWrapper.cs b/src/IKVM.Runtime/VolatileLongDoubleFieldWrapper.cs index db5cdb1228..36800198c1 100644 --- a/src/IKVM.Runtime/VolatileLongDoubleFieldWrapper.cs +++ b/src/IKVM.Runtime/VolatileLongDoubleFieldWrapper.cs @@ -23,23 +23,15 @@ Jeroen Frijters */ using System; -using IKVM.Runtime; - #if IMPORTER || EXPORTER using IKVM.Reflection; using IKVM.Reflection.Emit; - -using Type = IKVM.Reflection.Type; #else using System.Reflection; using System.Reflection.Emit; #endif -#if IMPORTER -using IKVM.Tools.Importer; -#endif - -namespace IKVM.Internal +namespace IKVM.Runtime { /// diff --git a/src/IKVM.Runtime/atomic.cs b/src/IKVM.Runtime/atomic.cs index 5005d7e6e5..07211572d7 100644 --- a/src/IKVM.Runtime/atomic.cs +++ b/src/IKVM.Runtime/atomic.cs @@ -23,22 +23,24 @@ Jeroen Frijters */ using System; -using IKVM.Internal; + using IKVM.Runtime; #if IMPORTER using IKVM.Reflection; using IKVM.Reflection.Emit; + using Type = IKVM.Reflection.Type; #else using System.Reflection; using System.Reflection.Emit; #endif -using InstructionFlags = IKVM.Internal.ClassFile.Method.InstructionFlags; +using InstructionFlags = IKVM.Runtime.ClassFile.Method.InstructionFlags; static class AtomicReferenceFieldUpdaterEmitter { + internal static bool Emit(DynamicTypeWrapper.FinishContext context, TypeWrapper wrapper, CodeEmitter ilgen, ClassFile classFile, int i, ClassFile.Method.Instruction[] code, InstructionFlags[] flags) { if (i >= 3 diff --git a/src/IKVM.Runtime/compiler.cs b/src/IKVM.Runtime/compiler.cs index 100795aeec..a3ea79ff03 100644 --- a/src/IKVM.Runtime/compiler.cs +++ b/src/IKVM.Runtime/compiler.cs @@ -27,7 +27,6 @@ Jeroen Frijters using System.Diagnostics.SymbolStore; using IKVM.Attributes; -using IKVM.Internal; using IKVM.ByteCode; #if IMPORTER @@ -41,10 +40,10 @@ Jeroen Frijters using System.Reflection.Emit; #endif -using ExceptionTableEntry = IKVM.Internal.ClassFile.Method.ExceptionTableEntry; -using LocalVariableTableEntry = IKVM.Internal.ClassFile.Method.LocalVariableTableEntry; -using Instruction = IKVM.Internal.ClassFile.Method.Instruction; -using InstructionFlags = IKVM.Internal.ClassFile.Method.InstructionFlags; +using ExceptionTableEntry = IKVM.Runtime.ClassFile.Method.ExceptionTableEntry; +using LocalVariableTableEntry = IKVM.Runtime.ClassFile.Method.LocalVariableTableEntry; +using Instruction = IKVM.Runtime.ClassFile.Method.Instruction; +using InstructionFlags = IKVM.Runtime.ClassFile.Method.InstructionFlags; namespace IKVM.Runtime { diff --git a/src/IKVM.Runtime/intrinsics.cs b/src/IKVM.Runtime/intrinsics.cs index f012292cd8..a903f1d796 100644 --- a/src/IKVM.Runtime/intrinsics.cs +++ b/src/IKVM.Runtime/intrinsics.cs @@ -25,8 +25,6 @@ Jeroen Frijters using System; using System.Collections.Generic; -using IKVM.Runtime; - #if IMPORTER using IKVM.Reflection; using IKVM.Reflection.Emit; @@ -38,105 +36,17 @@ Jeroen Frijters using System.Reflection.Emit; #endif -using Instruction = IKVM.Internal.ClassFile.Method.Instruction; -using InstructionFlags = IKVM.Internal.ClassFile.Method.InstructionFlags; +using Instruction = IKVM.Runtime.ClassFile.Method.Instruction; +using InstructionFlags = IKVM.Runtime.ClassFile.Method.InstructionFlags; -namespace IKVM.Internal +namespace IKVM.Runtime { - sealed class EmitIntrinsicContext - { - - internal readonly MethodWrapper Method; - internal readonly DynamicTypeWrapper.FinishContext Context; - internal readonly CodeEmitter Emitter; - readonly CodeInfo ma; - internal readonly int OpcodeIndex; - internal readonly MethodWrapper Caller; - internal readonly ClassFile ClassFile; - internal readonly Instruction[] Code; - internal readonly InstructionFlags[] Flags; - internal bool NonLeaf = true; - - internal EmitIntrinsicContext(MethodWrapper method, DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, CodeInfo ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) - { - this.Method = method; - this.Context = context; - this.Emitter = ilgen; - this.ma = ma; - this.OpcodeIndex = opcodeIndex; - this.Caller = caller; - this.ClassFile = classFile; - this.Code = code; - this.Flags = flags; - } - - internal bool MatchRange(int offset, int length) - { - if (OpcodeIndex + offset < 0) - return false; - - if (OpcodeIndex + offset + length > Code.Length) - return false; - - // we check for branches *into* the range, the start of the range may be a branch target - for (int i = OpcodeIndex + offset + 1, end = OpcodeIndex + offset + length; i < end; i++) - if ((Flags[i] & InstructionFlags.BranchTarget) != 0) - return false; - - return true; - } - - internal bool Match(int offset, NormalizedByteCode opcode) - { - return Code[OpcodeIndex + offset].NormalizedOpCode == opcode; - } - - internal bool Match(int offset, NormalizedByteCode opcode, int arg) - { - return Code[OpcodeIndex + offset].NormalizedOpCode == opcode && Code[OpcodeIndex + offset].Arg1 == arg; - } - - internal TypeWrapper GetStackTypeWrapper(int offset, int pos) - { - return ma.GetStackTypeWrapper(OpcodeIndex + offset, pos); - } - - internal ClassFile.ConstantPoolItemMI GetMethodref(int offset) - { - return ClassFile.GetMethodref(Code[OpcodeIndex + offset].Arg1); - } - - internal ClassFile.ConstantPoolItemFieldref GetFieldref(int offset) - { - return ClassFile.GetFieldref(Code[OpcodeIndex + offset].Arg1); - } - - internal TypeWrapper GetClassLiteral(int offset) - { - return ClassFile.GetConstantPoolClassType(Code[OpcodeIndex + offset].Arg1); - } - - internal string GetStringLiteral(int offset) - { - return ClassFile.GetConstantPoolConstantString(Code[OpcodeIndex + offset].Arg1); - } - - internal ClassFile.ConstantType GetConstantType(int offset) - { - return ClassFile.GetConstantPoolConstantType(Code[OpcodeIndex + offset].Arg1); - } - - internal void PatchOpCode(int offset, NormalizedByteCode opc) - { - Code[OpcodeIndex + offset].PatchOpCode(opc); - } - - } - static class Intrinsics { + private delegate bool Emitter(EmitIntrinsicContext eic); + private struct IntrinsicKey : IEquatable { private readonly string className; diff --git a/src/IKVM.Runtime/profiler.cs b/src/IKVM.Runtime/profiler.cs index 45cdfd0279..5c8115895d 100644 --- a/src/IKVM.Runtime/profiler.cs +++ b/src/IKVM.Runtime/profiler.cs @@ -25,97 +25,103 @@ Jeroen Frijters using System.Collections.Generic; using System.Diagnostics; -sealed class Profiler +namespace IKVM.Runtime { - private static Profiler instance = new Profiler(); - private static Dictionary counters = new Dictionary(); - [ThreadStatic] - private static Stack stack; - private sealed class Entry + sealed class Profiler { - internal long Time; - internal long Count; - } - ~Profiler() - { - // get rid off the warning that "instance" is unused - instance.Equals(null); - Console.Error.WriteLine("{0,-40}{1,10}{2,12}", "Event", "Count", "Time (ms)"); - Console.Error.WriteLine("{0,-40}{1,10}{2,12}", "-----", "-----", "---------"); - long totalTime = 0; - foreach(KeyValuePair e in counters) + private static Profiler instance = new Profiler(); + private static Dictionary counters = new Dictionary(); + [ThreadStatic] + private static Stack stack; + + private sealed class Entry { - Entry entry = e.Value; - if(entry.Time == 0) - { - Console.Error.WriteLine("{0,-40}{1,10}", e.Key, entry.Count); - } - else - { - totalTime += entry.Time / 10000; - Console.Error.WriteLine("{0,-40}{1,10}{2,12}", e.Key, entry.Count, entry.Time / 10000); - } + internal long Time; + internal long Count; } - Console.Error.WriteLine("{0,-40}{1,10}{2,12}", "", "", "---------"); - Console.Error.WriteLine("{0,-40}{1,10}{2,12}", "", "", totalTime); - } - [Conditional("PROFILE")] - internal static void Enter(string name) - { - long ticks = DateTime.Now.Ticks; - lock(counters) + ~Profiler() { - if(stack == null) + // get rid off the warning that "instance" is unused + instance.Equals(null); + Console.Error.WriteLine("{0,-40}{1,10}{2,12}", "Event", "Count", "Time (ms)"); + Console.Error.WriteLine("{0,-40}{1,10}{2,12}", "-----", "-----", "---------"); + long totalTime = 0; + foreach (KeyValuePair e in counters) { - stack = new Stack(); + Entry entry = e.Value; + if (entry.Time == 0) + { + Console.Error.WriteLine("{0,-40}{1,10}", e.Key, entry.Count); + } + else + { + totalTime += entry.Time / 10000; + Console.Error.WriteLine("{0,-40}{1,10}{2,12}", e.Key, entry.Count, entry.Time / 10000); + } } - if(stack.Count > 0) - { - stack.Peek().Time += ticks; - } - Entry e; - if(!counters.TryGetValue(name, out e)) + Console.Error.WriteLine("{0,-40}{1,10}{2,12}", "", "", "---------"); + Console.Error.WriteLine("{0,-40}{1,10}{2,12}", "", "", totalTime); + } + + [Conditional("PROFILE")] + internal static void Enter(string name) + { + long ticks = DateTime.Now.Ticks; + lock (counters) { - e = new Entry(); - counters[name] = e; + if (stack == null) + { + stack = new Stack(); + } + if (stack.Count > 0) + { + stack.Peek().Time += ticks; + } + Entry e; + if (!counters.TryGetValue(name, out e)) + { + e = new Entry(); + counters[name] = e; + } + e.Count++; + e.Time -= ticks; + stack.Push(e); } - e.Count++; - e.Time -= ticks; - stack.Push(e); } - } - [Conditional("PROFILE")] - internal static void Leave(string name) - { - long ticks = DateTime.Now.Ticks; - stack.Pop(); - lock(counters) + [Conditional("PROFILE")] + internal static void Leave(string name) { - Entry e = counters[name]; - e.Time += ticks; - if(stack.Count > 0) + long ticks = DateTime.Now.Ticks; + stack.Pop(); + lock (counters) { - ((Entry)stack.Peek()).Time -= ticks; + Entry e = counters[name]; + e.Time += ticks; + if (stack.Count > 0) + { + ((Entry)stack.Peek()).Time -= ticks; + } } } - } - [Conditional("PROFILE")] - internal static void Count(string name) - { - lock(counters) + [Conditional("PROFILE")] + internal static void Count(string name) { - Entry e; - if(!counters.TryGetValue(name, out e)) + lock (counters) { - e = new Entry(); - counters[name] = e; + Entry e; + if (!counters.TryGetValue(name, out e)) + { + e = new Entry(); + counters[name] = e; + } + e.Count++; } - e.Count++; } } + } diff --git a/src/IKVM.Runtime/tracer.cs b/src/IKVM.Runtime/tracer.cs index f55baffabe..8d8270f231 100644 --- a/src/IKVM.Runtime/tracer.cs +++ b/src/IKVM.Runtime/tracer.cs @@ -28,7 +28,7 @@ Jeroen Frijters using System.Text.RegularExpressions; using System.Threading; -namespace IKVM.Internal +namespace IKVM.Runtime { public static class Tracer diff --git a/src/IKVM.Runtime/verifier.cs b/src/IKVM.Runtime/verifier.cs deleted file mode 100644 index c60a838995..0000000000 --- a/src/IKVM.Runtime/verifier.cs +++ /dev/null @@ -1,4138 +0,0 @@ -/* - Copyright (C) 2002-2014 Jeroen Frijters - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jeroen Frijters - jeroen@frijters.net - -*/ -using System; -using System.Collections.Generic; -using System.Diagnostics; - -using IKVM.ByteCode; -using IKVM.Internal; - -#if IMPORTER -using IKVM.Tools.Importer; -#endif - -using ExceptionTableEntry = IKVM.Internal.ClassFile.Method.ExceptionTableEntry; -using InstructionFlags = IKVM.Internal.ClassFile.Method.InstructionFlags; - -sealed class InstructionState -{ - - private struct LocalStoreSites - { - - private int[] data; - private int count; - private bool shared; - - internal LocalStoreSites Copy() - { - LocalStoreSites n = new LocalStoreSites(); - n.data = data; - n.count = count; - n.shared = true; - return n; - } - - internal static LocalStoreSites Alloc() - { - LocalStoreSites n = new LocalStoreSites(); - n.data = new int[4]; - return n; - } - - internal void Add(int store) - { - for (int i = 0; i < count; i++) - { - if (data[i] == store) - { - return; - } - } - if (count == data.Length) - { - int[] newarray = new int[data.Length * 2]; - Buffer.BlockCopy(data, 0, newarray, 0, data.Length * 4); - data = newarray; - shared = false; - } - if (shared) - { - shared = false; - data = (int[])data.Clone(); - } - data[count++] = store; - } - - internal int this[int index] - { - get - { - return data[index]; - } - } - - internal int Count - { - get - { - return count; - } - } - - internal static void MarkShared(LocalStoreSites[] localStoreSites) - { - for (int i = 0; i < localStoreSites.Length; i++) - { - localStoreSites[i].shared = true; - } - } - } - - TypeWrapper[] stack; - int stackSize; - int stackEnd; - TypeWrapper[] locals; - bool unitializedThis; - internal bool changed = true; - - private enum ShareFlags : byte - { - None = 0, - Stack = 1, - Locals = 2, - All = Stack | Locals - } - private ShareFlags flags; - - private InstructionState(TypeWrapper[] stack, int stackSize, int stackEnd, TypeWrapper[] locals, bool unitializedThis) - { - this.flags = ShareFlags.All; - this.stack = stack; - this.stackSize = stackSize; - this.stackEnd = stackEnd; - this.locals = locals; - this.unitializedThis = unitializedThis; - } - - internal InstructionState(int maxLocals, int maxStack) - { - this.flags = ShareFlags.None; - this.stack = new TypeWrapper[maxStack]; - this.stackEnd = maxStack; - this.locals = new TypeWrapper[maxLocals]; - } - - internal InstructionState Copy() - { - return new InstructionState(stack, stackSize, stackEnd, locals, unitializedThis); - } - - internal void CopyTo(InstructionState target) - { - target.flags = ShareFlags.All; - target.stack = stack; - target.stackSize = stackSize; - target.stackEnd = stackEnd; - target.locals = locals; - target.unitializedThis = unitializedThis; - target.changed = true; - } - - internal InstructionState CopyLocals() - { - InstructionState copy = new InstructionState(new TypeWrapper[stack.Length], 0, stack.Length, locals, unitializedThis); - copy.flags &= ~ShareFlags.Stack; - return copy; - } - - public static InstructionState operator +(InstructionState s1, InstructionState s2) - { - if (s1 == null) - { - return s2.Copy(); - } - if (s1.stackSize != s2.stackSize || s1.stackEnd != s2.stackEnd) - { - throw new VerifyError(string.Format("Inconsistent stack height: {0} != {1}", - s1.stackSize + s1.stack.Length - s1.stackEnd, - s2.stackSize + s2.stack.Length - s2.stackEnd)); - } - InstructionState s = s1.Copy(); - s.changed = s1.changed; - for (int i = 0; i < s.stackSize; i++) - { - TypeWrapper type = s.stack[i]; - TypeWrapper type2 = s2.stack[i]; - if (type == type2) - { - // perfect match, nothing to do - } - else if ((type == VerifierTypeWrapper.ExtendedDouble && type2 == PrimitiveTypeWrapper.DOUBLE) - || (type2 == VerifierTypeWrapper.ExtendedDouble && type == PrimitiveTypeWrapper.DOUBLE)) - { - if (type != VerifierTypeWrapper.ExtendedDouble) - { - s.StackCopyOnWrite(); - s.stack[i] = VerifierTypeWrapper.ExtendedDouble; - s.changed = true; - } - } - else if ((type == VerifierTypeWrapper.ExtendedFloat && type2 == PrimitiveTypeWrapper.FLOAT) - || (type2 == VerifierTypeWrapper.ExtendedFloat && type == PrimitiveTypeWrapper.FLOAT)) - { - if (type != VerifierTypeWrapper.ExtendedFloat) - { - s.StackCopyOnWrite(); - s.stack[i] = VerifierTypeWrapper.ExtendedFloat; - s.changed = true; - } - } - else if (!type.IsPrimitive) - { - TypeWrapper baseType = InstructionState.FindCommonBaseType(type, type2); - if (baseType == VerifierTypeWrapper.Invalid) - { - throw new VerifyError(string.Format("cannot merge {0} and {1}", type.Name, type2.Name)); - } - if (type != baseType) - { - s.StackCopyOnWrite(); - s.stack[i] = baseType; - s.changed = true; - } - } - else - { - throw new VerifyError(string.Format("cannot merge {0} and {1}", type.Name, type2.Name)); - } - } - for (int i = 0; i < s.locals.Length; i++) - { - TypeWrapper type = s.locals[i]; - TypeWrapper type2 = s2.locals[i]; - TypeWrapper baseType = InstructionState.FindCommonBaseType(type, type2); - if (type != baseType) - { - s.LocalsCopyOnWrite(); - s.locals[i] = baseType; - s.changed = true; - } - } - if (!s.unitializedThis && s2.unitializedThis) - { - s.unitializedThis = true; - s.changed = true; - } - return s; - } - - private static LocalStoreSites MergeStoreSites(LocalStoreSites h1, LocalStoreSites h2) - { - if (h1.Count == 0) - { - return h2.Copy(); - } - if (h2.Count == 0) - { - return h1.Copy(); - } - LocalStoreSites h = h1.Copy(); - for (int i = 0; i < h2.Count; i++) - { - h.Add(h2[i]); - } - return h; - } - - internal void SetUnitializedThis(bool state) - { - unitializedThis = state; - } - - internal void CheckUninitializedThis() - { - if (unitializedThis) - { - throw new VerifyError("Base class constructor wasn't called"); - } - } - - internal static TypeWrapper FindCommonBaseType(TypeWrapper type1, TypeWrapper type2) - { - if (type1 == type2) - { - return type1; - } - if (type1 == VerifierTypeWrapper.Null) - { - return type2; - } - if (type2 == VerifierTypeWrapper.Null) - { - return type1; - } - if (type1 == VerifierTypeWrapper.Invalid || type2 == VerifierTypeWrapper.Invalid) - { - return VerifierTypeWrapper.Invalid; - } - if (VerifierTypeWrapper.IsFaultBlockException(type1)) - { - VerifierTypeWrapper.ClearFaultBlockException(type1); - return FindCommonBaseType(CoreClasses.java.lang.Throwable.Wrapper, type2); - } - if (VerifierTypeWrapper.IsFaultBlockException(type2)) - { - VerifierTypeWrapper.ClearFaultBlockException(type2); - return FindCommonBaseType(type1, CoreClasses.java.lang.Throwable.Wrapper); - } - if (type1.IsPrimitive || type2.IsPrimitive) - { - return VerifierTypeWrapper.Invalid; - } - if (type1 == VerifierTypeWrapper.UninitializedThis || type2 == VerifierTypeWrapper.UninitializedThis) - { - return VerifierTypeWrapper.Invalid; - } - if (VerifierTypeWrapper.IsNew(type1) || VerifierTypeWrapper.IsNew(type2)) - { - return VerifierTypeWrapper.Invalid; - } - if (VerifierTypeWrapper.IsThis(type1)) - { - type1 = ((VerifierTypeWrapper)type1).UnderlyingType; - } - if (VerifierTypeWrapper.IsThis(type2)) - { - type2 = ((VerifierTypeWrapper)type2).UnderlyingType; - } - if (type1.IsUnloadable || type2.IsUnloadable) - { - return VerifierTypeWrapper.Unloadable; - } - if (type1.ArrayRank > 0 && type2.ArrayRank > 0) - { - int rank = 1; - int rank1 = type1.ArrayRank - 1; - int rank2 = type2.ArrayRank - 1; - TypeWrapper elem1 = type1.ElementTypeWrapper; - TypeWrapper elem2 = type2.ElementTypeWrapper; - while (rank1 != 0 && rank2 != 0) - { - elem1 = elem1.ElementTypeWrapper; - elem2 = elem2.ElementTypeWrapper; - rank++; - rank1--; - rank2--; - } - // NOTE arrays of value types have special merging semantics! - // NOTE we don't have to test for the case where the element types are the same, because that - // is only relevant if the ranks are the same, but if that is the case the types are completely - // identical, in which case the identity test at the top of this method already returned. - TypeWrapper baseType; - if (elem1.IsPrimitive || elem2.IsPrimitive || elem1.IsNonPrimitiveValueType || elem2.IsNonPrimitiveValueType) - { - baseType = CoreClasses.java.lang.Object.Wrapper; - rank--; - if (rank == 0) - { - return baseType; - } - } - else - { - baseType = FindCommonBaseTypeHelper(elem1, elem2); - } - return baseType.MakeArrayType(rank); - } - return FindCommonBaseTypeHelper(type1, type2); - } - - private static TypeWrapper FindCommonBaseTypeHelper(TypeWrapper t1, TypeWrapper t2) - { - if (t1 == t2) - { - return t1; - } - if (t1.IsInterface || t2.IsInterface) - { - // NOTE according to a paper by Alessandro Coglio & Allen Goldberg titled - // "Type Safety in the JVM: Some Problems in Java 2 SDK 1.2 and Proposed Solutions" - // the common base of two interfaces is java.lang.Object, and there is special - // treatment for java.lang.Object types that allow it to be assigned to any interface - // type, the JVM's typesafety then depends on the invokeinterface instruction to make - // sure that the reference actually implements the interface. - // NOTE the ECMA CLI spec also specifies this interface merging algorithm, so we can't - // really do anything more clever than this. - return CoreClasses.java.lang.Object.Wrapper; - } - Stack st1 = new Stack(); - Stack st2 = new Stack(); - while (t1 != null) - { - st1.Push(t1); - t1 = t1.BaseTypeWrapper; - } - while (t2 != null) - { - st2.Push(t2); - t2 = t2.BaseTypeWrapper; - } - if (HasMissingBaseType(st1) || HasMissingBaseType(st2)) - { - return VerifierTypeWrapper.Unloadable; - } - TypeWrapper type = CoreClasses.java.lang.Object.Wrapper; - for (; ; ) - { - t1 = st1.Count > 0 ? st1.Pop() : null; - t2 = st2.Count > 0 ? st2.Pop() : null; - if (t1 != t2) - { - return type; - } - type = t1; - } - } - - private static bool HasMissingBaseType(Stack st) - { -#if IMPORTER - if (st.Pop().IsUnloadable) - { - // we have a missing type in base class hierarchy - StaticCompiler.IssueMissingTypeMessage(st.Pop().TypeAsBaseType.BaseType); - return true; - } -#endif - return false; - } - - private void SetLocal1(int index, TypeWrapper type) - { - try - { - LocalsCopyOnWrite(); - if (index > 0 && locals[index - 1] != VerifierTypeWrapper.Invalid && locals[index - 1].IsWidePrimitive) - { - locals[index - 1] = VerifierTypeWrapper.Invalid; - } - locals[index] = type; - } - catch (IndexOutOfRangeException) - { - throw new VerifyError("Illegal local variable number"); - } - } - - private void SetLocal2(int index, TypeWrapper type) - { - try - { - LocalsCopyOnWrite(); - if (index > 0 && locals[index - 1] != VerifierTypeWrapper.Invalid && locals[index - 1].IsWidePrimitive) - { - locals[index - 1] = VerifierTypeWrapper.Invalid; - } - locals[index] = type; - locals[index + 1] = VerifierTypeWrapper.Invalid; - } - catch (IndexOutOfRangeException) - { - throw new VerifyError("Illegal local variable number"); - } - } - - internal void GetLocalInt(int index) - { - if (GetLocalType(index) != PrimitiveTypeWrapper.INT) - { - throw new VerifyError("Invalid local type"); - } - } - - internal void SetLocalInt(int index, int instructionIndex) - { - SetLocal1(index, PrimitiveTypeWrapper.INT); - } - - internal void GetLocalLong(int index) - { - if (GetLocalType(index) != PrimitiveTypeWrapper.LONG) - { - throw new VerifyError("incorrect local type, not long"); - } - } - - internal void SetLocalLong(int index, int instructionIndex) - { - SetLocal2(index, PrimitiveTypeWrapper.LONG); - } - - internal void GetLocalFloat(int index) - { - if (GetLocalType(index) != PrimitiveTypeWrapper.FLOAT) - { - throw new VerifyError("incorrect local type, not float"); - } - } - - internal void SetLocalFloat(int index, int instructionIndex) - { - SetLocal1(index, PrimitiveTypeWrapper.FLOAT); - } - - internal void GetLocalDouble(int index) - { - if (GetLocalType(index) != PrimitiveTypeWrapper.DOUBLE) - { - throw new VerifyError("incorrect local type, not double"); - } - } - - internal void SetLocalDouble(int index, int instructionIndex) - { - SetLocal2(index, PrimitiveTypeWrapper.DOUBLE); - } - - internal TypeWrapper GetLocalType(int index) - { - try - { - return locals[index]; - } - catch (IndexOutOfRangeException) - { - throw new VerifyError("Illegal local variable number"); - } - } - - // this is used by the compiler (indirectly, through MethodAnalyzer.GetLocalTypeWrapper), - // we've already verified the code so we know we won't run outside the array boundary, - // and we don't need to record the fact that we're reading the local. - internal TypeWrapper GetLocalTypeEx(int index) - { - return locals[index]; - } - - internal void SetLocalType(int index, TypeWrapper type, int instructionIndex) - { - if (type.IsWidePrimitive) - { - SetLocal2(index, type); - } - else - { - SetLocal1(index, type); - } - } - - internal void PushType(TypeWrapper type) - { - if (type.IsIntOnStackPrimitive) - { - type = PrimitiveTypeWrapper.INT; - } - PushHelper(type); - } - - internal void PushInt() - { - PushHelper(PrimitiveTypeWrapper.INT); - } - - internal void PushLong() - { - PushHelper(PrimitiveTypeWrapper.LONG); - } - - internal void PushFloat() - { - PushHelper(PrimitiveTypeWrapper.FLOAT); - } - - internal void PushExtendedFloat() - { - PushHelper(VerifierTypeWrapper.ExtendedFloat); - } - - internal void PushDouble() - { - PushHelper(PrimitiveTypeWrapper.DOUBLE); - } - - internal void PushExtendedDouble() - { - PushHelper(VerifierTypeWrapper.ExtendedDouble); - } - - internal void PopInt() - { - PopIntImpl(PopAnyType()); - } - - internal static void PopIntImpl(TypeWrapper type) - { - if (type != PrimitiveTypeWrapper.INT) - { - throw new VerifyError("Int expected on stack"); - } - } - - internal bool PopFloat() - { - TypeWrapper tw = PopAnyType(); - PopFloatImpl(tw); - return tw == VerifierTypeWrapper.ExtendedFloat; - } - - internal static void PopFloatImpl(TypeWrapper tw) - { - if (tw != PrimitiveTypeWrapper.FLOAT && tw != VerifierTypeWrapper.ExtendedFloat) - { - throw new VerifyError("Float expected on stack"); - } - } - - internal bool PopDouble() - { - TypeWrapper tw = PopAnyType(); - PopDoubleImpl(tw); - return tw == VerifierTypeWrapper.ExtendedDouble; - } - - internal static void PopDoubleImpl(TypeWrapper tw) - { - if (tw != PrimitiveTypeWrapper.DOUBLE && tw != VerifierTypeWrapper.ExtendedDouble) - { - throw new VerifyError("Double expected on stack"); - } - } - - internal void PopLong() - { - PopLongImpl(PopAnyType()); - } - - internal static void PopLongImpl(TypeWrapper tw) - { - if (tw != PrimitiveTypeWrapper.LONG) - { - throw new VerifyError("Long expected on stack"); - } - } - - internal TypeWrapper PopArrayType() - { - return PopArrayTypeImpl(PopAnyType()); - } - - internal static TypeWrapper PopArrayTypeImpl(TypeWrapper type) - { - if (!VerifierTypeWrapper.IsNullOrUnloadable(type) && type.ArrayRank == 0) - { - throw new VerifyError("Array reference expected on stack"); - } - return type; - } - - // null or an initialized object reference - internal TypeWrapper PopObjectType() - { - return PopObjectTypeImpl(PopType()); - } - - internal static TypeWrapper PopObjectTypeImpl(TypeWrapper type) - { - if (type.IsPrimitive || VerifierTypeWrapper.IsNew(type) || type == VerifierTypeWrapper.UninitializedThis) - { - throw new VerifyError("Expected object reference on stack"); - } - return type; - } - - // null or an initialized object reference derived from baseType (or baseType) - internal TypeWrapper PopObjectType(TypeWrapper baseType) - { - return PopObjectTypeImpl(baseType, PopObjectType()); - } - - internal static TypeWrapper PopObjectTypeImpl(TypeWrapper baseType, TypeWrapper type) - { - // HACK because of the way interfaces references works, if baseType - // is an interface or array of interfaces, any reference will be accepted - if (!baseType.IsUnloadable && !baseType.IsInterfaceOrInterfaceArray && !(type.IsUnloadable || type.IsAssignableTo(baseType))) - { - throw new VerifyError("Unexpected type " + type.Name + " where " + baseType.Name + " was expected"); - } - return type; - } - - internal TypeWrapper PeekType() - { - if (stackSize == 0) - { - throw new VerifyError("Unable to pop operand off an empty stack"); - } - return stack[stackSize - 1]; - } - - internal void MultiPopAnyType(int count) - { - while (count-- != 0) - { - PopAnyType(); - } - } - - internal TypeWrapper PopFaultBlockException() - { - return stack[--stackSize]; - } - - internal TypeWrapper PopAnyType() - { - if (stackSize == 0) - { - throw new VerifyError("Unable to pop operand off an empty stack"); - } - TypeWrapper type = stack[--stackSize]; - if (type.IsWidePrimitive || type == VerifierTypeWrapper.ExtendedDouble) - { - stackEnd++; - } - if (VerifierTypeWrapper.IsThis(type)) - { - type = ((VerifierTypeWrapper)type).UnderlyingType; - } - if (VerifierTypeWrapper.IsFaultBlockException(type)) - { - VerifierTypeWrapper.ClearFaultBlockException(type); - type = CoreClasses.java.lang.Throwable.Wrapper; - } - return type; - } - - // NOTE this can *not* be used to pop double or long - internal TypeWrapper PopType() - { - return PopTypeImpl(PopAnyType()); - } - - internal static TypeWrapper PopTypeImpl(TypeWrapper type) - { - if (type.IsWidePrimitive || type == VerifierTypeWrapper.ExtendedDouble) - { - throw new VerifyError("Attempt to split long or double on the stack"); - } - return type; - } - - // this will accept null, a primitive type of the specified type or an initialized reference of the - // specified type or derived from it - // NOTE this can also be used to pop double or long - internal TypeWrapper PopType(TypeWrapper baseType) - { - return PopTypeImpl(baseType, PopAnyType()); - } - - internal static TypeWrapper PopTypeImpl(TypeWrapper baseType, TypeWrapper type) - { - if (baseType.IsIntOnStackPrimitive) - { - baseType = PrimitiveTypeWrapper.INT; - } - if (VerifierTypeWrapper.IsNew(type) || type == VerifierTypeWrapper.UninitializedThis) - { - throw new VerifyError("Expecting to find object/array on stack"); - } - if (type == baseType) - { - return type; - } - else if (type == VerifierTypeWrapper.ExtendedDouble && baseType == PrimitiveTypeWrapper.DOUBLE) - { - return type; - } - else if (type == VerifierTypeWrapper.ExtendedFloat && baseType == PrimitiveTypeWrapper.FLOAT) - { - return type; - } - else if (type.IsPrimitive || baseType.IsPrimitive) - { - // throw at the end of the method - } - else if (baseType == CoreClasses.java.lang.Object.Wrapper) - { - return type; - } - else if (type.IsUnloadable || baseType.IsUnloadable) - { - return type; - } - else if (baseType.IsInterfaceOrInterfaceArray) - { - // because of the way interfaces references works, if baseType - // is an interface or array of interfaces, any reference will be accepted - return type; - } - else if (type.IsAssignableTo(baseType)) - { - return type; - } - else if (HasMissingBaseType(type) || HasMissingBaseType(baseType)) - { - return type; - } - throw new VerifyError("Unexpected type " + type.Name + " where " + baseType.Name + " was expected"); - } - - private static bool HasMissingBaseType(TypeWrapper tw) - { -#if IMPORTER - for (TypeWrapper baseTypeWrapper; (baseTypeWrapper = tw.BaseTypeWrapper) != null; tw = baseTypeWrapper) - { - if (baseTypeWrapper.IsUnloadable) - { - StaticCompiler.IssueMissingTypeMessage(tw.TypeAsBaseType.BaseType); - return true; - } - } -#endif - return false; - } - - internal int GetStackHeight() - { - return stackSize; - } - - internal TypeWrapper GetStackSlot(int pos) - { - TypeWrapper tw = stack[stackSize - 1 - pos]; - if (tw == VerifierTypeWrapper.ExtendedDouble) - { - tw = PrimitiveTypeWrapper.DOUBLE; - } - else if (tw == VerifierTypeWrapper.ExtendedFloat) - { - tw = PrimitiveTypeWrapper.FLOAT; - } - return tw; - } - - internal TypeWrapper GetStackSlotEx(int pos) - { - return stack[stackSize - 1 - pos]; - } - - internal TypeWrapper GetStackByIndex(int index) - { - return stack[index]; - } - - private void PushHelper(TypeWrapper type) - { - if (type.IsWidePrimitive || type == VerifierTypeWrapper.ExtendedDouble) - { - stackEnd--; - } - if (stackSize >= stackEnd) - { - throw new VerifyError("Stack overflow"); - } - StackCopyOnWrite(); - stack[stackSize++] = type; - } - - internal void MarkInitialized(TypeWrapper type, TypeWrapper initType, int instructionIndex) - { - System.Diagnostics.Debug.Assert(type != null && initType != null); - - for (int i = 0; i < locals.Length; i++) - { - if (locals[i] == type) - { - LocalsCopyOnWrite(); - locals[i] = initType; - } - } - for (int i = 0; i < stackSize; i++) - { - if (stack[i] == type) - { - StackCopyOnWrite(); - stack[i] = initType; - } - } - } - - private void StackCopyOnWrite() - { - if ((flags & ShareFlags.Stack) != 0) - { - flags &= ~ShareFlags.Stack; - stack = (TypeWrapper[])stack.Clone(); - } - } - - private void LocalsCopyOnWrite() - { - if ((flags & ShareFlags.Locals) != 0) - { - flags &= ~ShareFlags.Locals; - locals = (TypeWrapper[])locals.Clone(); - } - } - - internal void DumpLocals() - { - Console.Write("// "); - string sep = ""; - for (int i = 0; i < locals.Length; i++) - { - Console.Write(sep); - Console.Write(locals[i]); - sep = ", "; - } - Console.WriteLine(); - } - - internal void DumpStack() - { - Console.Write("// "); - string sep = ""; - for (int i = 0; i < stackSize; i++) - { - Console.Write(sep); - Console.Write(stack[i]); - sep = ", "; - } - Console.WriteLine(); - } - - internal void ClearFaultBlockException() - { - if (VerifierTypeWrapper.IsFaultBlockException(stack[0])) - { - StackCopyOnWrite(); - changed = true; - stack[0] = CoreClasses.java.lang.Throwable.Wrapper; - } - } -} - -struct StackState -{ - private InstructionState state; - private int sp; - - internal StackState(InstructionState state) - { - this.state = state; - sp = state.GetStackHeight(); - } - - internal TypeWrapper PeekType() - { - if (sp == 0) - { - throw new VerifyError("Unable to pop operand off an empty stack"); - } - TypeWrapper type = state.GetStackByIndex(sp - 1); - if (VerifierTypeWrapper.IsThis(type)) - { - type = ((VerifierTypeWrapper)type).UnderlyingType; - } - return type; - } - - internal TypeWrapper PopAnyType() - { - if (sp == 0) - { - throw new VerifyError("Unable to pop operand off an empty stack"); - } - TypeWrapper type = state.GetStackByIndex(--sp); - if (VerifierTypeWrapper.IsThis(type)) - { - type = ((VerifierTypeWrapper)type).UnderlyingType; - } - if (VerifierTypeWrapper.IsFaultBlockException(type)) - { - VerifierTypeWrapper.ClearFaultBlockException(type); - type = CoreClasses.java.lang.Throwable.Wrapper; - } - return type; - } - - internal TypeWrapper PopType(TypeWrapper baseType) - { - return InstructionState.PopTypeImpl(baseType, PopAnyType()); - } - - // NOTE this can *not* be used to pop double or long - internal TypeWrapper PopType() - { - return InstructionState.PopTypeImpl(PopAnyType()); - } - - internal void PopInt() - { - InstructionState.PopIntImpl(PopAnyType()); - } - - internal void PopFloat() - { - InstructionState.PopFloatImpl(PopAnyType()); - } - - internal void PopDouble() - { - InstructionState.PopDoubleImpl(PopAnyType()); - } - - internal void PopLong() - { - InstructionState.PopLongImpl(PopAnyType()); - } - - internal TypeWrapper PopArrayType() - { - return InstructionState.PopArrayTypeImpl(PopAnyType()); - } - - // either null or an initialized object reference - internal TypeWrapper PopObjectType() - { - return InstructionState.PopObjectTypeImpl(PopAnyType()); - } - - // null or an initialized object reference derived from baseType (or baseType) - internal TypeWrapper PopObjectType(TypeWrapper baseType) - { - return InstructionState.PopObjectTypeImpl(baseType, PopObjectType()); - } -} - -sealed class ExceptionSorter : IComparer -{ - public int Compare(ExceptionTableEntry e1, ExceptionTableEntry e2) - { - if (e1.startIndex < e2.startIndex) - { - return -1; - } - if (e1.startIndex == e2.startIndex) - { - if (e1.endIndex == e2.endIndex) - { - if (e1.ordinal > e2.ordinal) - { - return -1; - } - if (e1.ordinal == e2.ordinal) - { - return 0; - } - return 1; - } - if (e1.endIndex > e2.endIndex) - { - return -1; - } - } - return 1; - } -} - -struct UntangledExceptionTable -{ - private readonly ExceptionTableEntry[] exceptions; - - internal UntangledExceptionTable(ExceptionTableEntry[] exceptions) - { -#if DEBUG - for (int i = 0; i < exceptions.Length; i++) - { - for (int j = i + 1; j < exceptions.Length; j++) - { - // check for partially overlapping try blocks (which is legal for the JVM, but not the CLR) - if (exceptions[i].startIndex < exceptions[j].startIndex && - exceptions[j].startIndex < exceptions[i].endIndex && - exceptions[i].endIndex < exceptions[j].endIndex) - { - throw new InvalidOperationException("Partially overlapping try blocks is broken"); - } - // check that we didn't destroy the ordering, when sorting - if (exceptions[i].startIndex <= exceptions[j].startIndex && - exceptions[i].endIndex >= exceptions[j].endIndex && - exceptions[i].ordinal < exceptions[j].ordinal) - { - throw new InvalidOperationException("Non recursive try blocks is broken"); - } - } - } -#endif - this.exceptions = exceptions; - } - - internal ExceptionTableEntry this[int index] - { - get { return exceptions[index]; } - } - - internal int Length - { - get { return exceptions.Length; } - } - - internal void SetFinally(int index) - { - exceptions[index] = new ExceptionTableEntry(exceptions[index].startIndex, exceptions[index].endIndex, exceptions[index].handlerIndex, exceptions[index].catch_type, exceptions[index].ordinal, true); - } -} - -struct CodeInfo -{ - private readonly InstructionState[] state; - - internal CodeInfo(InstructionState[] state) - { - this.state = state; - } - - internal bool HasState(int index) - { - return state[index] != null; - } - - internal int GetStackHeight(int index) - { - return state[index].GetStackHeight(); - } - - internal TypeWrapper GetStackTypeWrapper(int index, int pos) - { - TypeWrapper type = state[index].GetStackSlot(pos); - if (VerifierTypeWrapper.IsThis(type)) - { - type = ((VerifierTypeWrapper)type).UnderlyingType; - } - return type; - } - - internal TypeWrapper GetRawStackTypeWrapper(int index, int pos) - { - return state[index].GetStackSlot(pos); - } - - internal bool IsStackTypeExtendedDouble(int index, int pos) - { - return state[index].GetStackSlotEx(pos) == VerifierTypeWrapper.ExtendedDouble; - } - - internal TypeWrapper GetLocalTypeWrapper(int index, int local) - { - return state[index].GetLocalTypeEx(local); - } -} - -sealed class MethodAnalyzer -{ - private readonly static TypeWrapper ByteArrayType; - private readonly static TypeWrapper BooleanArrayType; - private readonly static TypeWrapper ShortArrayType; - private readonly static TypeWrapper CharArrayType; - private readonly static TypeWrapper IntArrayType; - private readonly static TypeWrapper FloatArrayType; - private readonly static TypeWrapper DoubleArrayType; - private readonly static TypeWrapper LongArrayType; - private readonly static TypeWrapper java_lang_ThreadDeath; - private readonly TypeWrapper host; // used to by Unsafe.defineAnonymousClass() to provide access to private members of the host - private readonly TypeWrapper wrapper; - private readonly MethodWrapper mw; - private readonly ClassFile classFile; - private readonly ClassFile.Method method; - private readonly ClassLoaderWrapper classLoader; - private readonly TypeWrapper thisType; - private readonly InstructionState[] state; - private List errorMessages; - private readonly Dictionary newTypes = new Dictionary(); - private readonly Dictionary faultTypes = new Dictionary(); - - static MethodAnalyzer() - { - ByteArrayType = PrimitiveTypeWrapper.BYTE.MakeArrayType(1); - BooleanArrayType = PrimitiveTypeWrapper.BOOLEAN.MakeArrayType(1); - ShortArrayType = PrimitiveTypeWrapper.SHORT.MakeArrayType(1); - CharArrayType = PrimitiveTypeWrapper.CHAR.MakeArrayType(1); - IntArrayType = PrimitiveTypeWrapper.INT.MakeArrayType(1); - FloatArrayType = PrimitiveTypeWrapper.FLOAT.MakeArrayType(1); - DoubleArrayType = PrimitiveTypeWrapper.DOUBLE.MakeArrayType(1); - LongArrayType = PrimitiveTypeWrapper.LONG.MakeArrayType(1); - java_lang_ThreadDeath = ClassLoaderWrapper.LoadClassCritical("java.lang.ThreadDeath"); - } - - internal MethodAnalyzer(TypeWrapper host, TypeWrapper wrapper, MethodWrapper mw, ClassFile classFile, ClassFile.Method method, ClassLoaderWrapper classLoader) - { - if (method.VerifyError != null) - { - throw new VerifyError(method.VerifyError); - } - - this.host = host; - this.wrapper = wrapper; - this.mw = mw; - this.classFile = classFile; - this.method = method; - this.classLoader = classLoader; - state = new InstructionState[method.Instructions.Length]; - - try - { - // ensure that exception blocks and handlers start and end at instruction boundaries - for (int i = 0; i < method.ExceptionTable.Length; i++) - { - int start = method.ExceptionTable[i].startIndex; - int end = method.ExceptionTable[i].endIndex; - int handler = method.ExceptionTable[i].handlerIndex; - if (start >= end || start == -1 || end == -1 || handler <= 0) - { - throw new IndexOutOfRangeException(); - } - } - } - catch (IndexOutOfRangeException) - { - // TODO figure out if we should throw this during class loading - throw new ClassFormatError(string.Format("Illegal exception table (class: {0}, method: {1}, signature: {2}", classFile.Name, method.Name, method.Signature)); - } - - // start by computing the initial state, the stack is empty and the locals contain the arguments - state[0] = new InstructionState(method.MaxLocals, method.MaxStack); - int firstNonArgLocalIndex = 0; - if (!method.IsStatic) - { - thisType = VerifierTypeWrapper.MakeThis(wrapper); - // this reference. If we're a constructor, the this reference is uninitialized. - if (method.IsConstructor) - { - state[0].SetLocalType(firstNonArgLocalIndex++, VerifierTypeWrapper.UninitializedThis, -1); - state[0].SetUnitializedThis(true); - } - else - { - state[0].SetLocalType(firstNonArgLocalIndex++, thisType, -1); - } - } - else - { - thisType = null; - } - // mw can be null when we're invoked from IsSideEffectFreeStaticInitializer - TypeWrapper[] argTypeWrappers = mw == null ? TypeWrapper.EmptyArray : mw.GetParameters(); - for (int i = 0; i < argTypeWrappers.Length; i++) - { - TypeWrapper type = argTypeWrappers[i]; - if (type.IsIntOnStackPrimitive) - { - type = PrimitiveTypeWrapper.INT; - } - state[0].SetLocalType(firstNonArgLocalIndex++, type, -1); - if (type.IsWidePrimitive) - { - firstNonArgLocalIndex++; - } - } - AnalyzeTypeFlow(); - VerifyPassTwo(); - PatchLoadConstants(); - } - - private void PatchLoadConstants() - { - ClassFile.Method.Instruction[] code = method.Instructions; - for (int i = 0; i < code.Length; i++) - { - if (state[i] != null) - { - switch (code[i].NormalizedOpCode) - { - case NormalizedByteCode.__ldc: - switch (GetConstantPoolConstantType(code[i].Arg1)) - { - case ClassFile.ConstantType.Double: - case ClassFile.ConstantType.Float: - case ClassFile.ConstantType.Integer: - case ClassFile.ConstantType.Long: - case ClassFile.ConstantType.String: - case ClassFile.ConstantType.LiveObject: - code[i].PatchOpCode(NormalizedByteCode.__ldc_nothrow); - break; - } - break; - } - } - } - } - - internal CodeInfo GetCodeInfoAndErrors(UntangledExceptionTable exceptions, out List errors) - { - CodeInfo codeInfo = new CodeInfo(state); - OptimizationPass(codeInfo, classFile, method, exceptions, wrapper, classLoader); - PatchHardErrorsAndDynamicMemberAccess(wrapper, mw); - errors = errorMessages; - if (AnalyzePotentialFaultBlocks(codeInfo, method, exceptions)) - { - AnalyzeTypeFlow(); - } - ConvertFinallyBlocks(codeInfo, method, exceptions); - return codeInfo; - } - - private void AnalyzeTypeFlow() - { - InstructionState s = new InstructionState(method.MaxLocals, method.MaxStack); - bool done = false; - ClassFile.Method.Instruction[] instructions = method.Instructions; - while (!done) - { - done = true; - for (int i = 0; i < instructions.Length; i++) - { - if (state[i] != null && state[i].changed) - { - try - { - //Console.WriteLine(method.Instructions[i].PC + ": " + method.Instructions[i].OpCode.ToString()); - done = false; - state[i].changed = false; - // mark the exception handlers reachable from this instruction - for (int j = 0; j < method.ExceptionTable.Length; j++) - { - if (method.ExceptionTable[j].startIndex <= i && i < method.ExceptionTable[j].endIndex) - { - MergeExceptionHandler(j, state[i]); - } - } - state[i].CopyTo(s); - ClassFile.Method.Instruction instr = instructions[i]; - switch (instr.NormalizedOpCode) - { - case NormalizedByteCode.__aload: - { - TypeWrapper type = s.GetLocalType(instr.NormalizedArg1); - if (type == VerifierTypeWrapper.Invalid || type.IsPrimitive) - { - throw new VerifyError("Object reference expected"); - } - s.PushType(type); - break; - } - case NormalizedByteCode.__astore: - { - if (VerifierTypeWrapper.IsFaultBlockException(s.PeekType())) - { - s.SetLocalType(instr.NormalizedArg1, s.PopFaultBlockException(), i); - break; - } - // NOTE since the reference can be uninitialized, we cannot use PopObjectType - TypeWrapper type = s.PopType(); - if (type.IsPrimitive) - { - throw new VerifyError("Object reference expected"); - } - s.SetLocalType(instr.NormalizedArg1, type, i); - break; - } - case NormalizedByteCode.__aconst_null: - s.PushType(VerifierTypeWrapper.Null); - break; - case NormalizedByteCode.__aaload: - { - s.PopInt(); - TypeWrapper type = s.PopArrayType(); - if (type == VerifierTypeWrapper.Null) - { - // if the array is null, we have use null as the element type, because - // otherwise the rest of the code will not verify correctly - s.PushType(VerifierTypeWrapper.Null); - } - else if (type.IsUnloadable) - { - s.PushType(VerifierTypeWrapper.Unloadable); - } - else - { - type = type.ElementTypeWrapper; - if (type.IsPrimitive) - { - throw new VerifyError("Object array expected"); - } - s.PushType(type); - } - break; - } - case NormalizedByteCode.__aastore: - s.PopObjectType(); - s.PopInt(); - s.PopArrayType(); - // TODO check that elem is assignable to the array - break; - case NormalizedByteCode.__baload: - { - s.PopInt(); - TypeWrapper type = s.PopArrayType(); - if (!VerifierTypeWrapper.IsNullOrUnloadable(type) && - type != ByteArrayType && - type != BooleanArrayType) - { - throw new VerifyError(); - } - s.PushInt(); - break; - } - case NormalizedByteCode.__bastore: - { - s.PopInt(); - s.PopInt(); - TypeWrapper type = s.PopArrayType(); - if (!VerifierTypeWrapper.IsNullOrUnloadable(type) && - type != ByteArrayType && - type != BooleanArrayType) - { - throw new VerifyError(); - } - break; - } - case NormalizedByteCode.__caload: - s.PopInt(); - s.PopObjectType(CharArrayType); - s.PushInt(); - break; - case NormalizedByteCode.__castore: - s.PopInt(); - s.PopInt(); - s.PopObjectType(CharArrayType); - break; - case NormalizedByteCode.__saload: - s.PopInt(); - s.PopObjectType(ShortArrayType); - s.PushInt(); - break; - case NormalizedByteCode.__sastore: - s.PopInt(); - s.PopInt(); - s.PopObjectType(ShortArrayType); - break; - case NormalizedByteCode.__iaload: - s.PopInt(); - s.PopObjectType(IntArrayType); - s.PushInt(); - break; - case NormalizedByteCode.__iastore: - s.PopInt(); - s.PopInt(); - s.PopObjectType(IntArrayType); - break; - case NormalizedByteCode.__laload: - s.PopInt(); - s.PopObjectType(LongArrayType); - s.PushLong(); - break; - case NormalizedByteCode.__lastore: - s.PopLong(); - s.PopInt(); - s.PopObjectType(LongArrayType); - break; - case NormalizedByteCode.__daload: - s.PopInt(); - s.PopObjectType(DoubleArrayType); - s.PushDouble(); - break; - case NormalizedByteCode.__dastore: - s.PopDouble(); - s.PopInt(); - s.PopObjectType(DoubleArrayType); - break; - case NormalizedByteCode.__faload: - s.PopInt(); - s.PopObjectType(FloatArrayType); - s.PushFloat(); - break; - case NormalizedByteCode.__fastore: - s.PopFloat(); - s.PopInt(); - s.PopObjectType(FloatArrayType); - break; - case NormalizedByteCode.__arraylength: - s.PopArrayType(); - s.PushInt(); - break; - case NormalizedByteCode.__iconst: - s.PushInt(); - break; - case NormalizedByteCode.__if_icmpeq: - case NormalizedByteCode.__if_icmpne: - case NormalizedByteCode.__if_icmplt: - case NormalizedByteCode.__if_icmpge: - case NormalizedByteCode.__if_icmpgt: - case NormalizedByteCode.__if_icmple: - s.PopInt(); - s.PopInt(); - break; - case NormalizedByteCode.__ifeq: - case NormalizedByteCode.__ifge: - case NormalizedByteCode.__ifgt: - case NormalizedByteCode.__ifle: - case NormalizedByteCode.__iflt: - case NormalizedByteCode.__ifne: - s.PopInt(); - break; - case NormalizedByteCode.__ifnonnull: - case NormalizedByteCode.__ifnull: - // TODO it might be legal to use an unitialized ref here - s.PopObjectType(); - break; - case NormalizedByteCode.__if_acmpeq: - case NormalizedByteCode.__if_acmpne: - // TODO it might be legal to use an unitialized ref here - s.PopObjectType(); - s.PopObjectType(); - break; - case NormalizedByteCode.__getstatic: - case NormalizedByteCode.__dynamic_getstatic: - // special support for when we're being called from IsSideEffectFreeStaticInitializer - if (mw == null) - { - switch (GetFieldref(instr.Arg1).Signature[0]) - { - case 'B': - case 'Z': - case 'C': - case 'S': - case 'I': - s.PushInt(); - break; - case 'F': - s.PushFloat(); - break; - case 'D': - s.PushDouble(); - break; - case 'J': - s.PushLong(); - break; - case 'L': - case '[': - throw new VerifyError(); - default: - throw new InvalidOperationException(); - } - } - else - { - ClassFile.ConstantPoolItemFieldref cpi = GetFieldref(instr.Arg1); - if (cpi.GetField() != null && cpi.GetField().FieldTypeWrapper.IsUnloadable) - { - s.PushType(cpi.GetField().FieldTypeWrapper); - } - else - { - s.PushType(cpi.GetFieldType()); - } - } - break; - case NormalizedByteCode.__putstatic: - case NormalizedByteCode.__dynamic_putstatic: - // special support for when we're being called from IsSideEffectFreeStaticInitializer - if (mw == null) - { - switch (GetFieldref(instr.Arg1).Signature[0]) - { - case 'B': - case 'Z': - case 'C': - case 'S': - case 'I': - s.PopInt(); - break; - case 'F': - s.PopFloat(); - break; - case 'D': - s.PopDouble(); - break; - case 'J': - s.PopLong(); - break; - case 'L': - case '[': - if (s.PopAnyType() != VerifierTypeWrapper.Null) - { - throw new VerifyError(); - } - break; - default: - throw new InvalidOperationException(); - } - } - else - { - s.PopType(GetFieldref(instr.Arg1).GetFieldType()); - } - break; - case NormalizedByteCode.__getfield: - case NormalizedByteCode.__dynamic_getfield: - { - s.PopObjectType(GetFieldref(instr.Arg1).GetClassType()); - ClassFile.ConstantPoolItemFieldref cpi = GetFieldref(instr.Arg1); - if (cpi.GetField() != null && cpi.GetField().FieldTypeWrapper.IsUnloadable) - { - s.PushType(cpi.GetField().FieldTypeWrapper); - } - else - { - s.PushType(cpi.GetFieldType()); - } - break; - } - case NormalizedByteCode.__putfield: - case NormalizedByteCode.__dynamic_putfield: - s.PopType(GetFieldref(instr.Arg1).GetFieldType()); - // putfield is allowed to access the uninitialized this - if (s.PeekType() == VerifierTypeWrapper.UninitializedThis - && wrapper.IsAssignableTo(GetFieldref(instr.Arg1).GetClassType())) - { - s.PopType(); - } - else - { - s.PopObjectType(GetFieldref(instr.Arg1).GetClassType()); - } - break; - case NormalizedByteCode.__ldc_nothrow: - case NormalizedByteCode.__ldc: - { - switch (GetConstantPoolConstantType(instr.Arg1)) - { - case ClassFile.ConstantType.Double: - s.PushDouble(); - break; - case ClassFile.ConstantType.Float: - s.PushFloat(); - break; - case ClassFile.ConstantType.Integer: - s.PushInt(); - break; - case ClassFile.ConstantType.Long: - s.PushLong(); - break; - case ClassFile.ConstantType.String: - s.PushType(CoreClasses.java.lang.String.Wrapper); - break; - case ClassFile.ConstantType.LiveObject: - s.PushType(CoreClasses.java.lang.Object.Wrapper); - break; - case ClassFile.ConstantType.Class: - if (classFile.MajorVersion < 49) - { - throw new VerifyError("Illegal type in constant pool"); - } - s.PushType(CoreClasses.java.lang.Class.Wrapper); - break; - case ClassFile.ConstantType.MethodHandle: - s.PushType(CoreClasses.java.lang.invoke.MethodHandle.Wrapper); - break; - case ClassFile.ConstantType.MethodType: - s.PushType(CoreClasses.java.lang.invoke.MethodType.Wrapper); - break; - default: - // NOTE this is not a VerifyError, because it cannot happen (unless we have - // a bug in ClassFile.GetConstantPoolConstantType) - throw new InvalidOperationException(); - } - break; - } - case NormalizedByteCode.__clone_array: - case NormalizedByteCode.__invokevirtual: - case NormalizedByteCode.__invokespecial: - case NormalizedByteCode.__invokeinterface: - case NormalizedByteCode.__invokestatic: - case NormalizedByteCode.__dynamic_invokevirtual: - case NormalizedByteCode.__dynamic_invokespecial: - case NormalizedByteCode.__dynamic_invokeinterface: - case NormalizedByteCode.__dynamic_invokestatic: - case NormalizedByteCode.__privileged_invokevirtual: - case NormalizedByteCode.__privileged_invokespecial: - case NormalizedByteCode.__privileged_invokestatic: - case NormalizedByteCode.__methodhandle_invoke: - case NormalizedByteCode.__methodhandle_link: - { - ClassFile.ConstantPoolItemMI cpi = GetMethodref(instr.Arg1); - TypeWrapper retType = cpi.GetRetType(); - // HACK to allow the result of Unsafe.getObjectVolatile() (on an array) - // to be used with Unsafe.putObject() we need to propagate the - // element type here as the return type (instead of object) - if (cpi.GetMethod() != null - && cpi.GetMethod().IsIntrinsic - && cpi.Class == "sun.misc.Unsafe" - && cpi.Name == "getObjectVolatile" - && Intrinsics.IsSupportedArrayTypeForUnsafeOperation(s.GetStackSlot(1))) - { - retType = s.GetStackSlot(1).ElementTypeWrapper; - } - s.MultiPopAnyType(cpi.GetArgTypes().Length); - if (instr.NormalizedOpCode != NormalizedByteCode.__invokestatic - && instr.NormalizedOpCode != NormalizedByteCode.__dynamic_invokestatic) - { - TypeWrapper type = s.PopType(); - if (ReferenceEquals(cpi.Name, StringConstants.INIT)) - { - // after we've invoked the constructor, the uninitialized references - // are now initialized - if (type == VerifierTypeWrapper.UninitializedThis) - { - if (s.GetLocalTypeEx(0) == type) - { - s.SetLocalType(0, thisType, i); - } - s.MarkInitialized(type, wrapper, i); - s.SetUnitializedThis(false); - } - else if (VerifierTypeWrapper.IsNew(type)) - { - s.MarkInitialized(type, ((VerifierTypeWrapper)type).UnderlyingType, i); - } - else - { - // This is a VerifyError, but it will be caught by our second pass - } - } - } - if (retType != PrimitiveTypeWrapper.VOID) - { - if (cpi.GetMethod() != null && cpi.GetMethod().ReturnType.IsUnloadable) - { - s.PushType(cpi.GetMethod().ReturnType); - } - else if (retType == PrimitiveTypeWrapper.DOUBLE) - { - s.PushExtendedDouble(); - } - else if (retType == PrimitiveTypeWrapper.FLOAT) - { - s.PushExtendedFloat(); - } - else - { - s.PushType(retType); - } - } - break; - } - case NormalizedByteCode.__invokedynamic: - { - ClassFile.ConstantPoolItemInvokeDynamic cpi = GetInvokeDynamic(instr.Arg1); - s.MultiPopAnyType(cpi.GetArgTypes().Length); - TypeWrapper retType = cpi.GetRetType(); - if (retType != PrimitiveTypeWrapper.VOID) - { - if (retType == PrimitiveTypeWrapper.DOUBLE) - { - s.PushExtendedDouble(); - } - else if (retType == PrimitiveTypeWrapper.FLOAT) - { - s.PushExtendedFloat(); - } - else - { - s.PushType(retType); - } - } - break; - } - case NormalizedByteCode.__goto: - break; - case NormalizedByteCode.__istore: - s.PopInt(); - s.SetLocalInt(instr.NormalizedArg1, i); - break; - case NormalizedByteCode.__iload: - s.GetLocalInt(instr.NormalizedArg1); - s.PushInt(); - break; - case NormalizedByteCode.__ineg: - s.PopInt(); - s.PushInt(); - break; - case NormalizedByteCode.__iadd: - case NormalizedByteCode.__isub: - case NormalizedByteCode.__imul: - case NormalizedByteCode.__idiv: - case NormalizedByteCode.__irem: - case NormalizedByteCode.__iand: - case NormalizedByteCode.__ior: - case NormalizedByteCode.__ixor: - case NormalizedByteCode.__ishl: - case NormalizedByteCode.__ishr: - case NormalizedByteCode.__iushr: - s.PopInt(); - s.PopInt(); - s.PushInt(); - break; - case NormalizedByteCode.__lneg: - s.PopLong(); - s.PushLong(); - break; - case NormalizedByteCode.__ladd: - case NormalizedByteCode.__lsub: - case NormalizedByteCode.__lmul: - case NormalizedByteCode.__ldiv: - case NormalizedByteCode.__lrem: - case NormalizedByteCode.__land: - case NormalizedByteCode.__lor: - case NormalizedByteCode.__lxor: - s.PopLong(); - s.PopLong(); - s.PushLong(); - break; - case NormalizedByteCode.__lshl: - case NormalizedByteCode.__lshr: - case NormalizedByteCode.__lushr: - s.PopInt(); - s.PopLong(); - s.PushLong(); - break; - case NormalizedByteCode.__fneg: - if (s.PopFloat()) - { - s.PushExtendedFloat(); - } - else - { - s.PushFloat(); - } - break; - case NormalizedByteCode.__fadd: - case NormalizedByteCode.__fsub: - case NormalizedByteCode.__fmul: - case NormalizedByteCode.__fdiv: - case NormalizedByteCode.__frem: - s.PopFloat(); - s.PopFloat(); - s.PushExtendedFloat(); - break; - case NormalizedByteCode.__dneg: - if (s.PopDouble()) - { - s.PushExtendedDouble(); - } - else - { - s.PushDouble(); - } - break; - case NormalizedByteCode.__dadd: - case NormalizedByteCode.__dsub: - case NormalizedByteCode.__dmul: - case NormalizedByteCode.__ddiv: - case NormalizedByteCode.__drem: - s.PopDouble(); - s.PopDouble(); - s.PushExtendedDouble(); - break; - case NormalizedByteCode.__new: - { - // mark the type, so that we can ascertain that it is a "new object" - TypeWrapper type; - if (!newTypes.TryGetValue(i, out type)) - { - type = GetConstantPoolClassType(instr.Arg1); - if (type.IsArray) - { - throw new VerifyError("Illegal use of array type"); - } - type = VerifierTypeWrapper.MakeNew(type, i); - newTypes[i] = type; - } - s.PushType(type); - break; - } - case NormalizedByteCode.__multianewarray: - { - if (instr.Arg2 < 1) - { - throw new VerifyError("Illegal dimension argument"); - } - for (int j = 0; j < instr.Arg2; j++) - { - s.PopInt(); - } - TypeWrapper type = GetConstantPoolClassType(instr.Arg1); - if (type.ArrayRank < instr.Arg2) - { - throw new VerifyError("Illegal dimension argument"); - } - s.PushType(type); - break; - } - case NormalizedByteCode.__anewarray: - { - s.PopInt(); - TypeWrapper type = GetConstantPoolClassType(instr.Arg1); - if (type.IsUnloadable) - { - s.PushType(new UnloadableTypeWrapper("[" + type.SigName)); - } - else - { - s.PushType(type.MakeArrayType(1)); - } - break; - } - case NormalizedByteCode.__newarray: - s.PopInt(); - switch (instr.Arg1) - { - case 4: - s.PushType(BooleanArrayType); - break; - case 5: - s.PushType(CharArrayType); - break; - case 6: - s.PushType(FloatArrayType); - break; - case 7: - s.PushType(DoubleArrayType); - break; - case 8: - s.PushType(ByteArrayType); - break; - case 9: - s.PushType(ShortArrayType); - break; - case 10: - s.PushType(IntArrayType); - break; - case 11: - s.PushType(LongArrayType); - break; - default: - throw new VerifyError("Bad type"); - } - break; - case NormalizedByteCode.__swap: - { - TypeWrapper t1 = s.PopType(); - TypeWrapper t2 = s.PopType(); - s.PushType(t1); - s.PushType(t2); - break; - } - case NormalizedByteCode.__dup: - { - TypeWrapper t = s.PopType(); - s.PushType(t); - s.PushType(t); - break; - } - case NormalizedByteCode.__dup2: - { - TypeWrapper t = s.PopAnyType(); - if (t.IsWidePrimitive || t == VerifierTypeWrapper.ExtendedDouble) - { - s.PushType(t); - s.PushType(t); - } - else - { - TypeWrapper t2 = s.PopType(); - s.PushType(t2); - s.PushType(t); - s.PushType(t2); - s.PushType(t); - } - break; - } - case NormalizedByteCode.__dup_x1: - { - TypeWrapper value1 = s.PopType(); - TypeWrapper value2 = s.PopType(); - s.PushType(value1); - s.PushType(value2); - s.PushType(value1); - break; - } - case NormalizedByteCode.__dup2_x1: - { - TypeWrapper value1 = s.PopAnyType(); - if (value1.IsWidePrimitive || value1 == VerifierTypeWrapper.ExtendedDouble) - { - TypeWrapper value2 = s.PopType(); - s.PushType(value1); - s.PushType(value2); - s.PushType(value1); - } - else - { - TypeWrapper value2 = s.PopType(); - TypeWrapper value3 = s.PopType(); - s.PushType(value2); - s.PushType(value1); - s.PushType(value3); - s.PushType(value2); - s.PushType(value1); - } - break; - } - case NormalizedByteCode.__dup_x2: - { - TypeWrapper value1 = s.PopType(); - TypeWrapper value2 = s.PopAnyType(); - if (value2.IsWidePrimitive || value2 == VerifierTypeWrapper.ExtendedDouble) - { - s.PushType(value1); - s.PushType(value2); - s.PushType(value1); - } - else - { - TypeWrapper value3 = s.PopType(); - s.PushType(value1); - s.PushType(value3); - s.PushType(value2); - s.PushType(value1); - } - break; - } - case NormalizedByteCode.__dup2_x2: - { - TypeWrapper value1 = s.PopAnyType(); - if (value1.IsWidePrimitive || value1 == VerifierTypeWrapper.ExtendedDouble) - { - TypeWrapper value2 = s.PopAnyType(); - if (value2.IsWidePrimitive || value2 == VerifierTypeWrapper.ExtendedDouble) - { - // Form 4 - s.PushType(value1); - s.PushType(value2); - s.PushType(value1); - } - else - { - // Form 2 - TypeWrapper value3 = s.PopType(); - s.PushType(value1); - s.PushType(value3); - s.PushType(value2); - s.PushType(value1); - } - } - else - { - TypeWrapper value2 = s.PopType(); - TypeWrapper value3 = s.PopAnyType(); - if (value3.IsWidePrimitive || value3 == VerifierTypeWrapper.ExtendedDouble) - { - // Form 3 - s.PushType(value2); - s.PushType(value1); - s.PushType(value3); - s.PushType(value2); - s.PushType(value1); - } - else - { - // Form 4 - TypeWrapper value4 = s.PopType(); - s.PushType(value2); - s.PushType(value1); - s.PushType(value4); - s.PushType(value3); - s.PushType(value2); - s.PushType(value1); - } - } - break; - } - case NormalizedByteCode.__pop: - s.PopType(); - break; - case NormalizedByteCode.__pop2: - { - TypeWrapper type = s.PopAnyType(); - if (!type.IsWidePrimitive && type != VerifierTypeWrapper.ExtendedDouble) - { - s.PopType(); - } - break; - } - case NormalizedByteCode.__monitorenter: - case NormalizedByteCode.__monitorexit: - // TODO these bytecodes are allowed on an uninitialized object, but - // we don't support that at the moment... - s.PopObjectType(); - break; - case NormalizedByteCode.__return: - // mw is null if we're called from IsSideEffectFreeStaticInitializer - if (mw != null) - { - if (mw.ReturnType != PrimitiveTypeWrapper.VOID) - { - throw new VerifyError("Wrong return type in function"); - } - // if we're a constructor, make sure we called the base class constructor - s.CheckUninitializedThis(); - } - break; - case NormalizedByteCode.__areturn: - s.PopObjectType(mw.ReturnType); - break; - case NormalizedByteCode.__ireturn: - { - s.PopInt(); - if (!mw.ReturnType.IsIntOnStackPrimitive) - { - throw new VerifyError("Wrong return type in function"); - } - break; - } - case NormalizedByteCode.__lreturn: - s.PopLong(); - if (mw.ReturnType != PrimitiveTypeWrapper.LONG) - { - throw new VerifyError("Wrong return type in function"); - } - break; - case NormalizedByteCode.__freturn: - s.PopFloat(); - if (mw.ReturnType != PrimitiveTypeWrapper.FLOAT) - { - throw new VerifyError("Wrong return type in function"); - } - break; - case NormalizedByteCode.__dreturn: - s.PopDouble(); - if (mw.ReturnType != PrimitiveTypeWrapper.DOUBLE) - { - throw new VerifyError("Wrong return type in function"); - } - break; - case NormalizedByteCode.__fload: - s.GetLocalFloat(instr.NormalizedArg1); - s.PushFloat(); - break; - case NormalizedByteCode.__fstore: - s.PopFloat(); - s.SetLocalFloat(instr.NormalizedArg1, i); - break; - case NormalizedByteCode.__dload: - s.GetLocalDouble(instr.NormalizedArg1); - s.PushDouble(); - break; - case NormalizedByteCode.__dstore: - s.PopDouble(); - s.SetLocalDouble(instr.NormalizedArg1, i); - break; - case NormalizedByteCode.__lload: - s.GetLocalLong(instr.NormalizedArg1); - s.PushLong(); - break; - case NormalizedByteCode.__lstore: - s.PopLong(); - s.SetLocalLong(instr.NormalizedArg1, i); - break; - case NormalizedByteCode.__lconst_0: - case NormalizedByteCode.__lconst_1: - s.PushLong(); - break; - case NormalizedByteCode.__fconst_0: - case NormalizedByteCode.__fconst_1: - case NormalizedByteCode.__fconst_2: - s.PushFloat(); - break; - case NormalizedByteCode.__dconst_0: - case NormalizedByteCode.__dconst_1: - s.PushDouble(); - break; - case NormalizedByteCode.__lcmp: - s.PopLong(); - s.PopLong(); - s.PushInt(); - break; - case NormalizedByteCode.__fcmpl: - case NormalizedByteCode.__fcmpg: - s.PopFloat(); - s.PopFloat(); - s.PushInt(); - break; - case NormalizedByteCode.__dcmpl: - case NormalizedByteCode.__dcmpg: - s.PopDouble(); - s.PopDouble(); - s.PushInt(); - break; - case NormalizedByteCode.__checkcast: - s.PopObjectType(); - s.PushType(GetConstantPoolClassType(instr.Arg1)); - break; - case NormalizedByteCode.__instanceof: - s.PopObjectType(); - s.PushInt(); - break; - case NormalizedByteCode.__iinc: - s.GetLocalInt(instr.Arg1); - break; - case NormalizedByteCode.__athrow: - if (VerifierTypeWrapper.IsFaultBlockException(s.PeekType())) - { - s.PopFaultBlockException(); - } - else - { - s.PopObjectType(CoreClasses.java.lang.Throwable.Wrapper); - } - break; - case NormalizedByteCode.__tableswitch: - case NormalizedByteCode.__lookupswitch: - s.PopInt(); - break; - case NormalizedByteCode.__i2b: - s.PopInt(); - s.PushInt(); - break; - case NormalizedByteCode.__i2c: - s.PopInt(); - s.PushInt(); - break; - case NormalizedByteCode.__i2s: - s.PopInt(); - s.PushInt(); - break; - case NormalizedByteCode.__i2l: - s.PopInt(); - s.PushLong(); - break; - case NormalizedByteCode.__i2f: - s.PopInt(); - s.PushFloat(); - break; - case NormalizedByteCode.__i2d: - s.PopInt(); - s.PushDouble(); - break; - case NormalizedByteCode.__l2i: - s.PopLong(); - s.PushInt(); - break; - case NormalizedByteCode.__l2f: - s.PopLong(); - s.PushFloat(); - break; - case NormalizedByteCode.__l2d: - s.PopLong(); - s.PushDouble(); - break; - case NormalizedByteCode.__f2i: - s.PopFloat(); - s.PushInt(); - break; - case NormalizedByteCode.__f2l: - s.PopFloat(); - s.PushLong(); - break; - case NormalizedByteCode.__f2d: - s.PopFloat(); - s.PushDouble(); - break; - case NormalizedByteCode.__d2i: - s.PopDouble(); - s.PushInt(); - break; - case NormalizedByteCode.__d2f: - s.PopDouble(); - s.PushFloat(); - break; - case NormalizedByteCode.__d2l: - s.PopDouble(); - s.PushLong(); - break; - case NormalizedByteCode.__nop: - if (i + 1 == instructions.Length) - { - throw new VerifyError("Falling off the end of the code"); - } - break; - case NormalizedByteCode.__static_error: - break; - case NormalizedByteCode.__jsr: - case NormalizedByteCode.__ret: - throw new VerifyError("Bad instruction"); - default: - throw new NotImplementedException(instr.NormalizedOpCode.ToString()); - } - if (s.GetStackHeight() > method.MaxStack) - { - throw new VerifyError("Stack size too large"); - } - for (int j = 0; j < method.ExceptionTable.Length; j++) - { - if (method.ExceptionTable[j].endIndex == i + 1) - { - MergeExceptionHandler(j, s); - } - } - try - { - switch (ByteCodeMetaData.GetFlowControl(instr.NormalizedOpCode)) - { - case ByteCodeFlowControl.Switch: - for (int j = 0; j < instr.SwitchEntryCount; j++) - { - state[instr.GetSwitchTargetIndex(j)] += s; - } - state[instr.DefaultTarget] += s; - break; - case ByteCodeFlowControl.CondBranch: - state[i + 1] += s; - state[instr.TargetIndex] += s; - break; - case ByteCodeFlowControl.Branch: - state[instr.TargetIndex] += s; - break; - case ByteCodeFlowControl.Return: - case ByteCodeFlowControl.Throw: - break; - case ByteCodeFlowControl.Next: - state[i + 1] += s; - break; - default: - throw new InvalidOperationException(); - } - } - catch (IndexOutOfRangeException) - { - // we're going to assume that this always means that we have an invalid branch target - // NOTE because PcIndexMap returns -1 for illegal PCs (in the middle of an instruction) and - // we always use that value as an index into the state array, any invalid PC will result - // in an IndexOutOfRangeException - throw new VerifyError("Illegal target of jump or branch"); - } - } - catch (VerifyError x) - { - string opcode = instructions[i].NormalizedOpCode.ToString(); - if (opcode.StartsWith("__")) - { - opcode = opcode.Substring(2); - } - throw new VerifyError(string.Format("{5} (class: {0}, method: {1}, signature: {2}, offset: {3}, instruction: {4})", - classFile.Name, method.Name, method.Signature, instructions[i].PC, opcode, x.Message), x); - } - } - } - } - } - - private void MergeExceptionHandler(int exceptionIndex, InstructionState curr) - { - int idx = method.ExceptionTable[exceptionIndex].handlerIndex; - InstructionState ex = curr.CopyLocals(); - int catch_type = method.ExceptionTable[exceptionIndex].catch_type; - if (catch_type == 0) - { - TypeWrapper tw; - if (!faultTypes.TryGetValue(idx, out tw)) - { - tw = VerifierTypeWrapper.MakeFaultBlockException(this, idx); - faultTypes.Add(idx, tw); - } - ex.PushType(tw); - } - else - { - // TODO if the exception type is unloadable we should consider pushing - // Throwable as the type and recording a loader constraint - ex.PushType(GetConstantPoolClassType(catch_type)); - } - state[idx] += ex; - } - - // this verification pass must run on the unmodified bytecode stream - private void VerifyPassTwo() - { - ClassFile.Method.Instruction[] instructions = method.Instructions; - for (int i = 0; i < instructions.Length; i++) - { - if (state[i] != null) - { - try - { - switch (instructions[i].NormalizedOpCode) - { - case NormalizedByteCode.__invokeinterface: - case NormalizedByteCode.__invokespecial: - case NormalizedByteCode.__invokestatic: - case NormalizedByteCode.__invokevirtual: - VerifyInvokePassTwo(i); - break; - case NormalizedByteCode.__invokedynamic: - VerifyInvokeDynamic(i); - break; - } - } - catch (VerifyError x) - { - string opcode = instructions[i].NormalizedOpCode.ToString(); - if (opcode.StartsWith("__")) - { - opcode = opcode.Substring(2); - } - throw new VerifyError(string.Format("{5} (class: {0}, method: {1}, signature: {2}, offset: {3}, instruction: {4})", - classFile.Name, method.Name, method.Signature, instructions[i].PC, opcode, x.Message), x); - } - } - } - } - - private void VerifyInvokePassTwo(int index) - { - StackState stack = new StackState(state[index]); - NormalizedByteCode invoke = method.Instructions[index].NormalizedOpCode; - ClassFile.ConstantPoolItemMI cpi = GetMethodref(method.Instructions[index].Arg1); - if ((invoke == NormalizedByteCode.__invokestatic || invoke == NormalizedByteCode.__invokespecial) && classFile.MajorVersion >= 52) - { - // invokestatic and invokespecial may be used to invoke interface methods in Java 8 - // but invokespecial can only invoke methods in the current interface or a directly implemented interface - if (invoke == NormalizedByteCode.__invokespecial && cpi is ClassFile.ConstantPoolItemInterfaceMethodref) - { - if (cpi.GetClassType() == host) - { - // ok - } - else if (cpi.GetClassType() != wrapper && Array.IndexOf(wrapper.Interfaces, cpi.GetClassType()) == -1) - { - throw new VerifyError("Bad invokespecial instruction: interface method reference is in an indirect superinterface."); - } - } - } - else if ((cpi is ClassFile.ConstantPoolItemInterfaceMethodref) != (invoke == NormalizedByteCode.__invokeinterface)) - { - throw new VerifyError("Illegal constant pool index"); - } - if (invoke != NormalizedByteCode.__invokespecial && ReferenceEquals(cpi.Name, StringConstants.INIT)) - { - throw new VerifyError("Must call initializers using invokespecial"); - } - if (ReferenceEquals(cpi.Name, StringConstants.CLINIT)) - { - throw new VerifyError("Illegal call to internal method"); - } - TypeWrapper[] args = cpi.GetArgTypes(); - for (int j = args.Length - 1; j >= 0; j--) - { - stack.PopType(args[j]); - } - if (invoke == NormalizedByteCode.__invokeinterface) - { - int argcount = args.Length + 1; - for (int j = 0; j < args.Length; j++) - { - if (args[j].IsWidePrimitive) - { - argcount++; - } - } - if (method.Instructions[index].Arg2 != argcount) - { - throw new VerifyError("Inconsistent args size"); - } - } - bool isnew = false; - TypeWrapper thisType; - if (invoke == NormalizedByteCode.__invokestatic) - { - thisType = null; - } - else - { - thisType = SigTypeToClassName(stack.PeekType(), cpi.GetClassType(), wrapper); - if (ReferenceEquals(cpi.Name, StringConstants.INIT)) - { - TypeWrapper type = stack.PopType(); - isnew = VerifierTypeWrapper.IsNew(type); - if ((isnew && ((VerifierTypeWrapper)type).UnderlyingType != cpi.GetClassType()) || - (type == VerifierTypeWrapper.UninitializedThis && cpi.GetClassType() != wrapper.BaseTypeWrapper && cpi.GetClassType() != wrapper) || - (!isnew && type != VerifierTypeWrapper.UninitializedThis)) - { - // TODO oddly enough, Java fails verification for the class without - // even running the constructor, so maybe constructors are always - // verified... - // NOTE when a constructor isn't verifiable, the static initializer - // doesn't run either - throw new VerifyError("Call to wrong initialization method"); - } - } - else - { - if (invoke != NormalizedByteCode.__invokeinterface) - { - TypeWrapper refType = stack.PopObjectType(); - TypeWrapper targetType = cpi.GetClassType(); - if (!VerifierTypeWrapper.IsNullOrUnloadable(refType) && - !targetType.IsUnloadable && - !refType.IsAssignableTo(targetType)) - { - throw new VerifyError("Incompatible object argument for function call"); - } - // for invokespecial we also need to make sure we're calling ourself or a base class - if (invoke == NormalizedByteCode.__invokespecial) - { - if (VerifierTypeWrapper.IsNullOrUnloadable(refType)) - { - // ok - } - else if (refType.IsSubTypeOf(wrapper)) - { - // ok - } - else if (host != null && refType.IsSubTypeOf(host)) - { - // ok - } - else - { - throw new VerifyError("Incompatible target object for invokespecial"); - } - if (targetType.IsUnloadable) - { - // ok - } - else if (wrapper.IsSubTypeOf(targetType)) - { - // ok - } - else if (host != null && host.IsSubTypeOf(targetType)) - { - // ok - } - else - { - throw new VerifyError("Invokespecial cannot call subclass methods"); - } - } - } - else /* __invokeinterface */ - { - // NOTE unlike in the above case, we also allow *any* interface target type - // regardless of whether it is compatible or not, because if it is not compatible - // we want an IncompatibleClassChangeError at runtime - TypeWrapper refType = stack.PopObjectType(); - TypeWrapper targetType = cpi.GetClassType(); - if (!VerifierTypeWrapper.IsNullOrUnloadable(refType) - && !targetType.IsUnloadable - && !refType.IsAssignableTo(targetType) - && !targetType.IsInterface) - { - throw new VerifyError("Incompatible object argument for function call"); - } - } - } - } - } - - private void VerifyInvokeDynamic(int index) - { - StackState stack = new StackState(state[index]); - ClassFile.ConstantPoolItemInvokeDynamic cpi = GetInvokeDynamic(method.Instructions[index].Arg1); - TypeWrapper[] args = cpi.GetArgTypes(); - for (int j = args.Length - 1; j >= 0; j--) - { - stack.PopType(args[j]); - } - } - - private static void OptimizationPass(CodeInfo codeInfo, ClassFile classFile, ClassFile.Method method, UntangledExceptionTable exceptions, TypeWrapper wrapper, ClassLoaderWrapper classLoader) - { - // Optimization pass - if (classLoader.RemoveAsserts) - { - // 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); - ClassFile.Method.Instruction[] instructions = method.Instructions; - for (int i = 0; i < instructions.Length; i++) - { - if (instructions[i].NormalizedOpCode == NormalizedByteCode.__getstatic - && instructions[i + 1].NormalizedOpCode == NormalizedByteCode.__ifne - && instructions[i + 1].TargetIndex > i - && (flags[i + 1] & InstructionFlags.BranchTarget) == 0) - { - var field = classFile.GetFieldref(instructions[i].Arg1).GetField() as ConstantFieldWrapper; - if (field != null && field.FieldTypeWrapper == PrimitiveTypeWrapper.BOOLEAN && (bool)field.GetConstantValue()) - { - // 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); - } - } - } - } - } - } - - private void PatchHardErrorsAndDynamicMemberAccess(TypeWrapper wrapper, MethodWrapper mw) - { - // Now we do another pass to find "hard error" instructions - if (true) - { - ClassFile.Method.Instruction[] instructions = method.Instructions; - for (int i = 0; i < instructions.Length; i++) - { - if (state[i] != null) - { - StackState stack = new StackState(state[i]); - switch (instructions[i].NormalizedOpCode) - { - case NormalizedByteCode.__invokeinterface: - case NormalizedByteCode.__invokespecial: - case NormalizedByteCode.__invokestatic: - case NormalizedByteCode.__invokevirtual: - PatchInvoke(wrapper, ref instructions[i], stack); - break; - case NormalizedByteCode.__getfield: - case NormalizedByteCode.__putfield: - case NormalizedByteCode.__getstatic: - case NormalizedByteCode.__putstatic: - PatchFieldAccess(wrapper, mw, ref instructions[i], stack); - break; - case NormalizedByteCode.__ldc: - switch (classFile.GetConstantPoolConstantType(instructions[i].Arg1)) - { - case ClassFile.ConstantType.Class: - { - TypeWrapper tw = classFile.GetConstantPoolClassType(instructions[i].Arg1); - if (tw.IsUnloadable) - { - ConditionalPatchNoClassDefFoundError(ref instructions[i], tw); - } - break; - } - case ClassFile.ConstantType.MethodType: - { - ClassFile.ConstantPoolItemMethodType cpi = classFile.GetConstantPoolConstantMethodType(instructions[i].Arg1); - TypeWrapper[] args = cpi.GetArgTypes(); - TypeWrapper tw = cpi.GetRetType(); - for (int j = 0; !tw.IsUnloadable && j < args.Length; j++) - { - tw = args[j]; - } - if (tw.IsUnloadable) - { - ConditionalPatchNoClassDefFoundError(ref instructions[i], tw); - } - break; - } - case ClassFile.ConstantType.MethodHandle: - PatchLdcMethodHandle(ref instructions[i]); - break; - } - break; - case NormalizedByteCode.__new: - { - TypeWrapper tw = classFile.GetConstantPoolClassType(instructions[i].Arg1); - if (tw.IsUnloadable) - { - ConditionalPatchNoClassDefFoundError(ref instructions[i], tw); - } - else if (!tw.IsAccessibleFrom(wrapper)) - { - SetHardError(wrapper.GetClassLoader(), ref instructions[i], HardError.IllegalAccessError, "Try to access class {0} from class {1}", tw.Name, wrapper.Name); - } - else if (tw.IsAbstract) - { - SetHardError(wrapper.GetClassLoader(), ref instructions[i], HardError.InstantiationError, "{0}", tw.Name); - } - break; - } - case NormalizedByteCode.__multianewarray: - case NormalizedByteCode.__anewarray: - { - TypeWrapper tw = classFile.GetConstantPoolClassType(instructions[i].Arg1); - if (tw.IsUnloadable) - { - ConditionalPatchNoClassDefFoundError(ref instructions[i], tw); - } - else if (!tw.IsAccessibleFrom(wrapper)) - { - SetHardError(wrapper.GetClassLoader(), ref instructions[i], HardError.IllegalAccessError, "Try to access class {0} from class {1}", tw.Name, wrapper.Name); - } - break; - } - case NormalizedByteCode.__checkcast: - case NormalizedByteCode.__instanceof: - { - TypeWrapper tw = classFile.GetConstantPoolClassType(instructions[i].Arg1); - if (tw.IsUnloadable) - { - // If the type is unloadable, we always generate the dynamic code - // (regardless of ClassLoaderWrapper.DisableDynamicBinding), because at runtime, - // null references should always pass thru without attempting - // to load the type (for Sun compatibility). - } - else if (!tw.IsAccessibleFrom(wrapper)) - { - SetHardError(wrapper.GetClassLoader(), ref instructions[i], HardError.IllegalAccessError, "Try to access class {0} from class {1}", tw.Name, wrapper.Name); - } - break; - } - case NormalizedByteCode.__aaload: - { - stack.PopInt(); - TypeWrapper tw = stack.PopArrayType(); - if (tw.IsUnloadable) - { - ConditionalPatchNoClassDefFoundError(ref instructions[i], tw); - } - break; - } - case NormalizedByteCode.__aastore: - { - stack.PopObjectType(); - stack.PopInt(); - TypeWrapper tw = stack.PopArrayType(); - if (tw.IsUnloadable) - { - ConditionalPatchNoClassDefFoundError(ref instructions[i], tw); - } - break; - } - default: - break; - } - } - } - } - } - - private void PatchLdcMethodHandle(ref ClassFile.Method.Instruction instr) - { - ClassFile.ConstantPoolItemMethodHandle cpi = classFile.GetConstantPoolConstantMethodHandle(instr.Arg1); - if (cpi.GetClassType().IsUnloadable) - { - ConditionalPatchNoClassDefFoundError(ref instr, cpi.GetClassType()); - } - else if (!cpi.GetClassType().IsAccessibleFrom(wrapper)) - { - SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IllegalAccessError, "tried to access class {0} from class {1}", cpi.Class, wrapper.Name); - } - else if (cpi.Kind == ReferenceKind.InvokeVirtual - && cpi.GetClassType() == CoreClasses.java.lang.invoke.MethodHandle.Wrapper - && (cpi.Name == "invoke" || cpi.Name == "invokeExact")) - { - // it's allowed to use ldc to create a MethodHandle invoker - } - else if (cpi.Member == null || cpi.Member.IsStatic != (cpi.Kind == ReferenceKind.GetStatic || cpi.Kind == ReferenceKind.PutStatic || cpi.Kind == ReferenceKind.InvokeStatic)) - { - HardError err; - string msg; - switch (cpi.Kind) - { - case ReferenceKind.GetField: - case ReferenceKind.GetStatic: - case ReferenceKind.PutField: - case ReferenceKind.PutStatic: - err = HardError.NoSuchFieldError; - msg = cpi.Name; - break; - default: - err = HardError.NoSuchMethodError; - msg = cpi.Class + "." + cpi.Name + cpi.Signature; - break; - } - SetHardError(wrapper.GetClassLoader(), ref instr, err, msg, cpi.Class, cpi.Name, SigToString(cpi.Signature)); - } - else if (!cpi.Member.IsAccessibleFrom(cpi.GetClassType(), wrapper, cpi.GetClassType())) - { - if (cpi.Member.IsProtected && wrapper.IsSubTypeOf(cpi.Member.DeclaringType)) - { - // this is allowed, the receiver will be narrowed to current type - } - else - { - SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IllegalAccessException, "member is private: {0}.{1}/{2}/{3}, from {4}", cpi.Class, cpi.Name, SigToString(cpi.Signature), cpi.Kind, wrapper.Name); - } - } - } - - private static string SigToString(string sig) - { - System.Text.StringBuilder sb = new System.Text.StringBuilder(); - string sep = ""; - int dims = 0; - for (int i = 0; i < sig.Length; i++) - { - if (sig[i] == '(' || sig[i] == ')') - { - sb.Append(sig[i]); - sep = ""; - continue; - } - else if (sig[i] == '[') - { - dims++; - continue; - } - sb.Append(sep); - sep = ","; - switch (sig[i]) - { - case 'V': - sb.Append("void"); - break; - case 'B': - sb.Append("byte"); - break; - case 'Z': - sb.Append("boolean"); - break; - case 'S': - sb.Append("short"); - break; - case 'C': - sb.Append("char"); - break; - case 'I': - sb.Append("int"); - break; - case 'J': - sb.Append("long"); - break; - case 'F': - sb.Append("float"); - break; - case 'D': - sb.Append("double"); - break; - case 'L': - sb.Append(sig, i + 1, sig.IndexOf(';', i + 1) - (i + 1)); - i = sig.IndexOf(';', i + 1); - break; - } - for (; dims != 0; dims--) - { - sb.Append("[]"); - } - } - return sb.ToString(); - } - - internal static InstructionFlags[] ComputePartialReachability(CodeInfo codeInfo, ClassFile.Method.Instruction[] instructions, UntangledExceptionTable exceptions, int initialInstructionIndex, bool skipFaultBlocks) - { - InstructionFlags[] flags = new InstructionFlags[instructions.Length]; - flags[initialInstructionIndex] |= InstructionFlags.Reachable; - UpdatePartialReachability(flags, codeInfo, instructions, exceptions, skipFaultBlocks); - return flags; - } - - private static void UpdatePartialReachability(InstructionFlags[] flags, CodeInfo codeInfo, ClassFile.Method.Instruction[] instructions, UntangledExceptionTable exceptions, bool skipFaultBlocks) - { - bool done = false; - while (!done) - { - done = true; - for (int i = 0; i < instructions.Length; i++) - { - if ((flags[i] & (InstructionFlags.Reachable | InstructionFlags.Processed)) == InstructionFlags.Reachable) - { - done = false; - flags[i] |= InstructionFlags.Processed; - // mark the exception handlers reachable from this instruction - for (int j = 0; j < exceptions.Length; j++) - { - if (exceptions[j].startIndex <= i && i < exceptions[j].endIndex) - { - int idx = exceptions[j].handlerIndex; - if (!skipFaultBlocks || !VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(idx, 0))) - { - flags[idx] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; - } - } - } - MarkSuccessors(instructions, flags, i); - } - } - } - } - - private static void MarkSuccessors(ClassFile.Method.Instruction[] code, InstructionFlags[] flags, int index) - { - switch (ByteCodeMetaData.GetFlowControl(code[index].NormalizedOpCode)) - { - case ByteCodeFlowControl.Switch: - { - for (int i = 0; i < code[index].SwitchEntryCount; i++) - { - flags[code[index].GetSwitchTargetIndex(i)] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; - } - flags[code[index].DefaultTarget] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; - break; - } - case ByteCodeFlowControl.Branch: - flags[code[index].TargetIndex] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; - break; - case ByteCodeFlowControl.CondBranch: - flags[code[index].TargetIndex] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; - flags[index + 1] |= InstructionFlags.Reachable; - break; - case ByteCodeFlowControl.Return: - case ByteCodeFlowControl.Throw: - break; - case ByteCodeFlowControl.Next: - flags[index + 1] |= InstructionFlags.Reachable; - break; - default: - throw new InvalidOperationException(); - } - } - - internal static UntangledExceptionTable UntangleExceptionBlocks(ClassFile classFile, ClassFile.Method method) - { - ClassFile.Method.Instruction[] instructions = method.Instructions; - ExceptionTableEntry[] exceptionTable = method.ExceptionTable; - List ar = new List(exceptionTable); - - // This optimization removes the recursive exception handlers that Java compiler place around - // the exit of a synchronization block to be "safe" in the face of asynchronous exceptions. - // (see http://weblog.ikvm.net/PermaLink.aspx?guid=3af9548e-4905-4557-8809-65a205ce2cd6) - // We can safely remove them since the code we generate for this construct isn't async safe anyway, - // but there is another reason why this optimization may be slightly controversial. In some - // pathological cases it can cause observable differences, where the Sun JVM would spin in an - // infinite loop, but we will throw an exception. However, the perf benefit is large enough to - // warrant this "incompatibility". - // Note that there is also code in the exception handler handling code that detects these bytecode - // sequences to try to compile them into a fault block, instead of an exception handler. - for (int i = 0; i < ar.Count; i++) - { - ExceptionTableEntry ei = ar[i]; - if (ei.startIndex == ei.handlerIndex && ei.catch_type == 0) - { - int index = ei.startIndex; - if (index + 2 < instructions.Length - && ei.endIndex == index + 2 - && instructions[index].NormalizedOpCode == NormalizedByteCode.__aload - && instructions[index + 1].NormalizedOpCode == NormalizedByteCode.__monitorexit - && instructions[index + 2].NormalizedOpCode == NormalizedByteCode.__athrow) - { - // this is the async exception guard that Jikes and the Eclipse Java Compiler produce - ar.RemoveAt(i); - i--; - } - else if (index + 4 < instructions.Length - && ei.endIndex == index + 3 - && instructions[index].NormalizedOpCode == NormalizedByteCode.__astore - && instructions[index + 1].NormalizedOpCode == NormalizedByteCode.__aload - && instructions[index + 2].NormalizedOpCode == NormalizedByteCode.__monitorexit - && instructions[index + 3].NormalizedOpCode == NormalizedByteCode.__aload - && instructions[index + 4].NormalizedOpCode == NormalizedByteCode.__athrow - && instructions[index].NormalizedArg1 == instructions[index + 3].NormalizedArg1) - { - // this is the async exception guard that javac produces - ar.RemoveAt(i); - i--; - } - else if (index + 1 < instructions.Length - && ei.endIndex == index + 1 - && instructions[index].NormalizedOpCode == NormalizedByteCode.__astore) - { - // this is the finally guard that javac produces - ar.RemoveAt(i); - i--; - } - } - } - - // Modern versions of javac split try blocks when the try block contains a return statement. - // Here we merge these exception blocks again, because it allows us to generate more efficient code. - for (int i = 0; i < ar.Count - 1; i++) - { - if (ar[i].endIndex + 1 == ar[i + 1].startIndex - && ar[i].handlerIndex == ar[i + 1].handlerIndex - && ar[i].catch_type == ar[i + 1].catch_type - && IsReturn(instructions[ar[i].endIndex].NormalizedOpCode)) - { - ar[i] = new ExceptionTableEntry(ar[i].startIndex, ar[i + 1].endIndex, ar[i].handlerIndex, ar[i].catch_type, ar[i].ordinal); - ar.RemoveAt(i + 1); - i--; - } - } - - restart: - for (int i = 0; i < ar.Count; i++) - { - ExceptionTableEntry ei = ar[i]; - for (int j = 0; j < ar.Count; j++) - { - ExceptionTableEntry ej = ar[j]; - if (ei.startIndex <= ej.startIndex && ej.startIndex < ei.endIndex) - { - // 0006/test.j - if (ej.endIndex > ei.endIndex) - { - ExceptionTableEntry emi = new ExceptionTableEntry(ej.startIndex, ei.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); - ExceptionTableEntry emj = new ExceptionTableEntry(ej.startIndex, ei.endIndex, ej.handlerIndex, ej.catch_type, ej.ordinal); - ei = new ExceptionTableEntry(ei.startIndex, emi.startIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); - ej = new ExceptionTableEntry(emj.endIndex, ej.endIndex, ej.handlerIndex, ej.catch_type, ej.ordinal); - ar[i] = ei; - ar[j] = ej; - ar.Insert(j, emj); - ar.Insert(i + 1, emi); - goto restart; - } - // 0007/test.j - else if (j > i && ej.endIndex < ei.endIndex) - { - ExceptionTableEntry emi = new ExceptionTableEntry(ej.startIndex, ej.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); - ExceptionTableEntry eei = new ExceptionTableEntry(ej.endIndex, ei.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); - ei = new ExceptionTableEntry(ei.startIndex, emi.startIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); - ar[i] = ei; - ar.Insert(i + 1, eei); - ar.Insert(i + 1, emi); - goto restart; - } - } - } - } - // Split try blocks at branch targets (branches from outside the try block) - restart_split: - for (int i = 0; i < ar.Count; i++) - { - ExceptionTableEntry ei = ar[i]; - int start = ei.startIndex; - int end = ei.endIndex; - for (int j = 0; j < instructions.Length; j++) - { - if (j < start || j >= end) - { - switch (instructions[j].NormalizedOpCode) - { - case NormalizedByteCode.__tableswitch: - case NormalizedByteCode.__lookupswitch: - // start at -1 to have an opportunity to handle the default offset - for (int k = -1; k < instructions[j].SwitchEntryCount; k++) - { - int targetIndex = (k == -1 ? instructions[j].DefaultTarget : instructions[j].GetSwitchTargetIndex(k)); - if (ei.startIndex < targetIndex && targetIndex < ei.endIndex) - { - ExceptionTableEntry en = new ExceptionTableEntry(targetIndex, ei.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); - ei = new ExceptionTableEntry(ei.startIndex, targetIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); - ar[i] = ei; - ar.Insert(i + 1, en); - goto restart_split; - } - } - break; - 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: - { - int targetIndex = instructions[j].Arg1; - if (ei.startIndex < targetIndex && targetIndex < ei.endIndex) - { - ExceptionTableEntry en = new ExceptionTableEntry(targetIndex, ei.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); - ei = new ExceptionTableEntry(ei.startIndex, targetIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); - ar[i] = ei; - ar.Insert(i + 1, en); - goto restart_split; - } - break; - } - } - } - } - } - // exception handlers are also a kind of jump, so we need to split try blocks around handlers as well - for (int i = 0; i < ar.Count; i++) - { - ExceptionTableEntry ei = ar[i]; - for (int j = 0; j < ar.Count; j++) - { - ExceptionTableEntry ej = ar[j]; - if (ei.startIndex < ej.handlerIndex && ej.handlerIndex < ei.endIndex) - { - ExceptionTableEntry en = new ExceptionTableEntry(ej.handlerIndex, ei.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); - ei = new ExceptionTableEntry(ei.startIndex, ej.handlerIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); - ar[i] = ei; - ar.Insert(i + 1, en); - goto restart_split; - } - } - } - // filter out zero length try blocks - for (int i = 0; i < ar.Count; i++) - { - ExceptionTableEntry ei = ar[i]; - if (ei.startIndex == ei.endIndex) - { - ar.RemoveAt(i); - i--; - } - else - { - // exception blocks that only contain harmless instructions (i.e. instructions that will *never* throw an exception) - // are also filtered out (to improve the quality of the generated code) - TypeWrapper exceptionType = ei.catch_type == 0 ? CoreClasses.java.lang.Throwable.Wrapper : classFile.GetConstantPoolClassType(ei.catch_type); - if (exceptionType.IsUnloadable) - { - // we can't remove handlers for unloadable types - } - else if (java_lang_ThreadDeath.IsAssignableTo(exceptionType)) - { - // We only remove exception handlers that could catch ThreadDeath in limited cases, because it can be thrown - // asynchronously (and thus appear on any instruction). This is particularly important to ensure that - // we run finally blocks when a thread is killed. - // Note that even so, we aren't remotely async exception safe. - int start = ei.startIndex; - int end = ei.endIndex; - for (int j = start; j < end; j++) - { - switch (instructions[j].NormalizedOpCode) - { - case NormalizedByteCode.__aload: - case NormalizedByteCode.__iload: - case NormalizedByteCode.__lload: - case NormalizedByteCode.__fload: - case NormalizedByteCode.__dload: - case NormalizedByteCode.__astore: - case NormalizedByteCode.__istore: - case NormalizedByteCode.__lstore: - case NormalizedByteCode.__fstore: - case NormalizedByteCode.__dstore: - break; - case NormalizedByteCode.__dup: - case NormalizedByteCode.__dup_x1: - case NormalizedByteCode.__dup_x2: - case NormalizedByteCode.__dup2: - case NormalizedByteCode.__dup2_x1: - case NormalizedByteCode.__dup2_x2: - case NormalizedByteCode.__pop: - case NormalizedByteCode.__pop2: - break; - case NormalizedByteCode.__return: - case NormalizedByteCode.__areturn: - case NormalizedByteCode.__ireturn: - case NormalizedByteCode.__lreturn: - case NormalizedByteCode.__freturn: - case NormalizedByteCode.__dreturn: - break; - case NormalizedByteCode.__goto: - // if there is a branch that stays inside the block, we should keep the block - if (start <= instructions[j].TargetIndex && instructions[j].TargetIndex < end) - goto next; - break; - default: - goto next; - } - } - ar.RemoveAt(i); - i--; - } - else - { - int start = ei.startIndex; - int end = ei.endIndex; - for (int j = start; j < end; j++) - { - if (ByteCodeMetaData.CanThrowException(instructions[j].NormalizedOpCode)) - { - goto next; - } - } - ar.RemoveAt(i); - i--; - } - } - next:; - } - - ExceptionTableEntry[] exceptions = ar.ToArray(); - Array.Sort(exceptions, new ExceptionSorter()); - - return new UntangledExceptionTable(exceptions); - } - - private static bool IsReturn(NormalizedByteCode bc) - { - return bc == NormalizedByteCode.__return - || bc == NormalizedByteCode.__areturn - || bc == NormalizedByteCode.__dreturn - || bc == NormalizedByteCode.__ireturn - || bc == NormalizedByteCode.__freturn - || bc == NormalizedByteCode.__lreturn; - } - - private static bool AnalyzePotentialFaultBlocks(CodeInfo codeInfo, ClassFile.Method method, UntangledExceptionTable exceptions) - { - ClassFile.Method.Instruction[] code = method.Instructions; - bool changed = false; - bool done = false; - while (!done) - { - done = true; - Stack stack = new Stack(); - ExceptionTableEntry current = new ExceptionTableEntry(0, code.Length, -1, ushort.MaxValue, -1); - stack.Push(current); - for (int i = 0; i < exceptions.Length; i++) - { - while (exceptions[i].startIndex >= current.endIndex) - { - current = stack.Pop(); - } - Debug.Assert(exceptions[i].startIndex >= current.startIndex && exceptions[i].endIndex <= current.endIndex); - if (exceptions[i].catch_type == 0 - && codeInfo.HasState(exceptions[i].handlerIndex) - && VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(exceptions[i].handlerIndex, 0))) - { - InstructionFlags[] flags = MethodAnalyzer.ComputePartialReachability(codeInfo, method.Instructions, exceptions, exceptions[i].handlerIndex, true); - for (int j = 0; j < code.Length; j++) - { - if ((flags[j] & InstructionFlags.Reachable) != 0) - { - switch (code[j].NormalizedOpCode) - { - case NormalizedByteCode.__return: - case NormalizedByteCode.__areturn: - case NormalizedByteCode.__ireturn: - case NormalizedByteCode.__lreturn: - case NormalizedByteCode.__freturn: - case NormalizedByteCode.__dreturn: - goto not_fault_block; - case NormalizedByteCode.__athrow: - for (int k = i + 1; k < exceptions.Length; k++) - { - if (exceptions[k].startIndex <= j && j < exceptions[k].endIndex) - { - goto not_fault_block; - } - } - if (VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(j, 0)) - && codeInfo.GetRawStackTypeWrapper(j, 0) != codeInfo.GetRawStackTypeWrapper(exceptions[i].handlerIndex, 0)) - { - goto not_fault_block; - } - break; - } - if (j < current.startIndex || j >= current.endIndex) - { - goto not_fault_block; - } - else if (exceptions[i].startIndex <= j && j < exceptions[i].endIndex) - { - goto not_fault_block; - } - else - { - continue; - } - not_fault_block: - VerifierTypeWrapper.ClearFaultBlockException(codeInfo.GetRawStackTypeWrapper(exceptions[i].handlerIndex, 0)); - done = false; - changed = true; - break; - } - } - } - stack.Push(current); - current = exceptions[i]; - } - } - return changed; - } - - private static void ConvertFinallyBlocks(CodeInfo codeInfo, ClassFile.Method method, UntangledExceptionTable exceptions) - { - ClassFile.Method.Instruction[] code = method.Instructions; - InstructionFlags[] flags = ComputePartialReachability(codeInfo, code, exceptions, 0, false); - for (int i = 0; i < exceptions.Length; i++) - { - if (exceptions[i].catch_type == 0 - && codeInfo.HasState(exceptions[i].handlerIndex) - && VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(exceptions[i].handlerIndex, 0))) - { - int exit; - if (IsSynchronizedBlockHandler(code, exceptions[i].handlerIndex) - && exceptions[i].endIndex - 2 >= exceptions[i].startIndex - && TryFindSingleTryBlockExit(code, flags, exceptions, new ExceptionTableEntry(exceptions[i].startIndex, exceptions[i].endIndex - 2, exceptions[i].handlerIndex, 0, exceptions[i].ordinal), i, out exit) - && exit == exceptions[i].endIndex - 2 - && (flags[exit + 1] & InstructionFlags.BranchTarget) == 0 - && MatchInstructions(code, exit, exceptions[i].handlerIndex + 1) - && MatchInstructions(code, exit + 1, exceptions[i].handlerIndex + 2) - && MatchExceptionCoverage(exceptions, i, exceptions[i].handlerIndex + 1, exceptions[i].handlerIndex + 3, exit, exit + 2) - && exceptions[i].handlerIndex <= ushort.MaxValue) - { - code[exit].PatchOpCode(NormalizedByteCode.__goto_finally, exceptions[i].endIndex, (short)exceptions[i].handlerIndex); - exceptions.SetFinally(i); - } - else if (TryFindSingleTryBlockExit(code, flags, exceptions, exceptions[i], i, out exit) - // the stack must be empty - && codeInfo.GetStackHeight(exit) == 0 - // the exit code must not be reachable (except from within the try-block), - // because we're going to patch it to jump around the exit code - && !IsReachableFromOutsideTryBlock(codeInfo, code, exceptions, exceptions[i], exit)) - { - int exitHandlerEnd; - int faultHandlerEnd; - if (MatchFinallyBlock(codeInfo, code, exceptions, exceptions[i].handlerIndex, exit, out exitHandlerEnd, out faultHandlerEnd)) - { - if (exit != exitHandlerEnd - && codeInfo.GetStackHeight(exitHandlerEnd) == 0 - && MatchExceptionCoverage(exceptions, -1, exceptions[i].handlerIndex, faultHandlerEnd, exit, exitHandlerEnd)) - { - // We use Arg2 (which is a short) to store the handler in the __goto_finally pseudo-opcode, - // so we can only do that if handlerIndex fits in a short (note that we can use the sign bit too). - if (exceptions[i].handlerIndex <= ushort.MaxValue) - { - code[exit].PatchOpCode(NormalizedByteCode.__goto_finally, exitHandlerEnd, (short)exceptions[i].handlerIndex); - exceptions.SetFinally(i); - } - } - } - } - } - } - } - - private static bool IsSynchronizedBlockHandler(ClassFile.Method.Instruction[] code, int index) - { - return code[index].NormalizedOpCode == NormalizedByteCode.__astore - && code[index + 1].NormalizedOpCode == NormalizedByteCode.__aload - && code[index + 2].NormalizedOpCode == NormalizedByteCode.__monitorexit - && code[index + 3].NormalizedOpCode == NormalizedByteCode.__aload && code[index + 3].Arg1 == code[index].Arg1 - && code[index + 4].NormalizedOpCode == NormalizedByteCode.__athrow; - } - - private static bool MatchExceptionCoverage(UntangledExceptionTable exceptions, int skipException, int startFault, int endFault, int startExit, int endExit) - { - for (int j = 0; j < exceptions.Length; j++) - { - if (j != skipException && ExceptionCovers(exceptions[j], startFault, endFault) != ExceptionCovers(exceptions[j], startExit, endExit)) - { - return false; - } - } - return true; - } - - private static bool ExceptionCovers(ExceptionTableEntry exception, int start, int end) - { - return exception.startIndex < end && exception.endIndex > start; - } - - private static bool MatchFinallyBlock(CodeInfo codeInfo, ClassFile.Method.Instruction[] code, UntangledExceptionTable exceptions, int faultHandler, int exitHandler, out int exitHandlerEnd, out int faultHandlerEnd) - { - exitHandlerEnd = -1; - faultHandlerEnd = -1; - if (code[faultHandler].NormalizedOpCode != NormalizedByteCode.__astore) - { - return false; - } - int startFault = faultHandler; - int faultLocal = code[faultHandler++].NormalizedArg1; - for (; ; ) - { - if (code[faultHandler].NormalizedOpCode == NormalizedByteCode.__aload - && code[faultHandler].NormalizedArg1 == faultLocal - && code[faultHandler + 1].NormalizedOpCode == NormalizedByteCode.__athrow) - { - // make sure that instructions that we haven't covered aren't reachable - InstructionFlags[] flags = ComputePartialReachability(codeInfo, code, exceptions, startFault, false); - for (int i = 0; i < flags.Length; i++) - { - if ((i < startFault || i > faultHandler + 1) && (flags[i] & InstructionFlags.Reachable) != 0) - { - return false; - } - } - exitHandlerEnd = exitHandler; - faultHandlerEnd = faultHandler; - return true; - } - if (!MatchInstructions(code, faultHandler, exitHandler)) - { - return false; - } - faultHandler++; - exitHandler++; - } - } - - private static bool MatchInstructions(ClassFile.Method.Instruction[] code, int i, int j) - { - if (code[i].NormalizedOpCode != code[j].NormalizedOpCode) - { - return false; - } - switch (ByteCodeMetaData.GetFlowControl(code[i].NormalizedOpCode)) - { - case ByteCodeFlowControl.Branch: - case ByteCodeFlowControl.CondBranch: - if (code[i].Arg1 - i != code[j].Arg1 - j) - { - return false; - } - break; - case ByteCodeFlowControl.Switch: - if (code[i].SwitchEntryCount != code[j].SwitchEntryCount) - { - return false; - } - for (int k = 0; k < code[i].SwitchEntryCount; k++) - { - if (code[i].GetSwitchTargetIndex(k) != code[j].GetSwitchTargetIndex(k)) - { - return false; - } - } - if (code[i].DefaultTarget != code[j].DefaultTarget) - { - return false; - } - break; - default: - if (code[i].Arg1 != code[j].Arg1) - { - return false; - } - if (code[i].Arg2 != code[j].Arg2) - { - return false; - } - break; - } - return true; - } - - private static bool IsReachableFromOutsideTryBlock(CodeInfo codeInfo, ClassFile.Method.Instruction[] code, UntangledExceptionTable exceptions, ExceptionTableEntry tryBlock, int instructionIndex) - { - InstructionFlags[] flags = new InstructionFlags[code.Length]; - flags[0] |= InstructionFlags.Reachable; - // We mark the first instruction of the try-block as already processed, so that UpdatePartialReachability will skip the try-block. - // Note that we can do this, because it is not possible to jump into the middle of a try-block (after the exceptions have been untangled). - flags[tryBlock.startIndex] = InstructionFlags.Processed; - // We mark the successor instructions of the instruction we're examinining as reachable, - // to figure out if the code following the handler somehow branches back to it. - MarkSuccessors(code, flags, instructionIndex); - UpdatePartialReachability(flags, codeInfo, code, exceptions, false); - return (flags[instructionIndex] & InstructionFlags.Reachable) != 0; - } - - private static bool TryFindSingleTryBlockExit(ClassFile.Method.Instruction[] code, InstructionFlags[] flags, UntangledExceptionTable exceptions, ExceptionTableEntry exception, int exceptionIndex, out int exit) - { - exit = -1; - bool fail = false; - bool nextIsReachable = false; - for (int i = exception.startIndex; !fail && i < exception.endIndex; i++) - { - if ((flags[i] & InstructionFlags.Reachable) != 0) - { - nextIsReachable = false; - for (int j = 0; j < exceptions.Length; j++) - { - if (j != exceptionIndex && exceptions[j].startIndex >= exception.startIndex && exception.endIndex <= exceptions[j].endIndex) - { - UpdateTryBlockExit(exception, exceptions[j].handlerIndex, ref exit, ref fail); - } - } - switch (ByteCodeMetaData.GetFlowControl(code[i].NormalizedOpCode)) - { - case ByteCodeFlowControl.Switch: - { - for (int j = 0; j < code[i].SwitchEntryCount; j++) - { - UpdateTryBlockExit(exception, code[i].GetSwitchTargetIndex(j), ref exit, ref fail); - } - UpdateTryBlockExit(exception, code[i].DefaultTarget, ref exit, ref fail); - break; - } - case ByteCodeFlowControl.Branch: - UpdateTryBlockExit(exception, code[i].TargetIndex, ref exit, ref fail); - break; - case ByteCodeFlowControl.CondBranch: - UpdateTryBlockExit(exception, code[i].TargetIndex, ref exit, ref fail); - nextIsReachable = true; - break; - case ByteCodeFlowControl.Return: - fail = true; - break; - case ByteCodeFlowControl.Throw: - break; - case ByteCodeFlowControl.Next: - nextIsReachable = true; - break; - default: - throw new InvalidOperationException(); - } - } - } - if (nextIsReachable) - { - UpdateTryBlockExit(exception, exception.endIndex, ref exit, ref fail); - } - return !fail && exit != -1; - } - - private static void UpdateTryBlockExit(ExceptionTableEntry exception, int targetIndex, ref int exitIndex, ref bool fail) - { - if (exception.startIndex <= targetIndex && targetIndex < exception.endIndex) - { - // branch stays inside try block - } - else if (exitIndex == -1) - { - exitIndex = targetIndex; - } - else if (exitIndex != targetIndex) - { - fail = true; - } - } - - private void ConditionalPatchNoClassDefFoundError(ref ClassFile.Method.Instruction instruction, TypeWrapper tw) - { - ClassLoaderWrapper loader = wrapper.GetClassLoader(); - if (loader.DisableDynamicBinding) - { - SetHardError(loader, ref instruction, HardError.NoClassDefFoundError, "{0}", tw.Name); - } - } - - private void SetHardError(ClassLoaderWrapper classLoader, ref ClassFile.Method.Instruction instruction, HardError hardError, string message, params object[] args) - { - string text = string.Format(message, args); -#if IMPORTER - Message msg; - switch (hardError) - { - case HardError.NoClassDefFoundError: - msg = Message.EmittedNoClassDefFoundError; - break; - case HardError.IllegalAccessError: - msg = Message.EmittedIllegalAccessError; - break; - case HardError.InstantiationError: - msg = Message.EmittedIllegalAccessError; - break; - case HardError.IncompatibleClassChangeError: - case HardError.IllegalAccessException: - msg = Message.EmittedIncompatibleClassChangeError; - break; - case HardError.NoSuchFieldError: - msg = Message.EmittedNoSuchFieldError; - break; - case HardError.AbstractMethodError: - msg = Message.EmittedAbstractMethodError; - break; - case HardError.NoSuchMethodError: - msg = Message.EmittedNoSuchMethodError; - break; - case HardError.LinkageError: - msg = Message.EmittedLinkageError; - break; - default: - throw new InvalidOperationException(); - } - classLoader.IssueMessage(msg, classFile.Name + "." + method.Name + method.Signature, text); -#endif - instruction.SetHardError(hardError, AllocErrorMessage(text)); - } - - private void PatchInvoke(TypeWrapper wrapper, ref ClassFile.Method.Instruction instr, StackState stack) - { - ClassFile.ConstantPoolItemMI cpi = GetMethodref(instr.Arg1); - NormalizedByteCode invoke = instr.NormalizedOpCode; - bool isnew = false; - TypeWrapper thisType; - if (invoke == NormalizedByteCode.__invokevirtual - && cpi.Class == "java.lang.invoke.MethodHandle" - && (cpi.Name == "invoke" || cpi.Name == "invokeExact" || cpi.Name == "invokeBasic")) - { - if (cpi.GetArgTypes().Length > 127 && MethodHandleUtil.SlotCount(cpi.GetArgTypes()) > 254) - { - instr.SetHardError(HardError.LinkageError, AllocErrorMessage("bad parameter count")); - return; - } - instr.PatchOpCode(NormalizedByteCode.__methodhandle_invoke); - return; - } - else if (invoke == NormalizedByteCode.__invokestatic - && cpi.Class == "java.lang.invoke.MethodHandle" - && (cpi.Name == "linkToVirtual" || cpi.Name == "linkToStatic" || cpi.Name == "linkToSpecial" || cpi.Name == "linkToInterface") - && CoreClasses.java.lang.invoke.MethodHandle.Wrapper.IsPackageAccessibleFrom(wrapper)) - { - instr.PatchOpCode(NormalizedByteCode.__methodhandle_link); - return; - } - else if (invoke == NormalizedByteCode.__invokestatic) - { - thisType = null; - } - else - { - TypeWrapper[] args = cpi.GetArgTypes(); - for (int j = args.Length - 1; j >= 0; j--) - { - stack.PopType(args[j]); - } - thisType = SigTypeToClassName(stack.PeekType(), cpi.GetClassType(), wrapper); - if (ReferenceEquals(cpi.Name, StringConstants.INIT)) - { - TypeWrapper type = stack.PopType(); - isnew = VerifierTypeWrapper.IsNew(type); - } - } - - if (cpi.GetClassType().IsUnloadable) - { - if (wrapper.GetClassLoader().DisableDynamicBinding) - { - SetHardError(wrapper.GetClassLoader(), ref instr, HardError.NoClassDefFoundError, "{0}", cpi.GetClassType().Name); - } - else - { - switch (invoke) - { - case NormalizedByteCode.__invokeinterface: - instr.PatchOpCode(NormalizedByteCode.__dynamic_invokeinterface); - break; - case NormalizedByteCode.__invokestatic: - instr.PatchOpCode(NormalizedByteCode.__dynamic_invokestatic); - break; - case NormalizedByteCode.__invokevirtual: - instr.PatchOpCode(NormalizedByteCode.__dynamic_invokevirtual); - break; - case NormalizedByteCode.__invokespecial: - if (isnew) - { - instr.PatchOpCode(NormalizedByteCode.__dynamic_invokespecial); - } - else - { - throw new VerifyError("Invokespecial cannot call subclass methods"); - } - break; - default: - throw new InvalidOperationException(); - } - } - } - else if (invoke == NormalizedByteCode.__invokeinterface && !cpi.GetClassType().IsInterface) - { - SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IncompatibleClassChangeError, "invokeinterface on non-interface"); - } - else if (cpi.GetClassType().IsInterface && invoke != NormalizedByteCode.__invokeinterface && ((invoke != NormalizedByteCode.__invokestatic && invoke != NormalizedByteCode.__invokespecial) || classFile.MajorVersion < 52)) - { - SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IncompatibleClassChangeError, - classFile.MajorVersion < 52 - ? "interface method must be invoked using invokeinterface" - : "interface method must be invoked using invokeinterface, invokespecial or invokestatic"); - } - else - { - MethodWrapper targetMethod = invoke == NormalizedByteCode.__invokespecial ? cpi.GetMethodForInvokespecial() : cpi.GetMethod(); - if (targetMethod != null) - { - string errmsg = CheckLoaderConstraints(cpi, targetMethod); - if (errmsg != null) - { - SetHardError(wrapper.GetClassLoader(), ref instr, HardError.LinkageError, "{0}", errmsg); - } - else if (targetMethod.IsStatic == (invoke == NormalizedByteCode.__invokestatic)) - { - if (targetMethod.IsAbstract && invoke == NormalizedByteCode.__invokespecial && (targetMethod.GetMethod() == null || targetMethod.GetMethod().IsAbstract)) - { - SetHardError(wrapper.GetClassLoader(), ref instr, HardError.AbstractMethodError, "{0}.{1}{2}", cpi.Class, cpi.Name, cpi.Signature); - } - else if (invoke == NormalizedByteCode.__invokeinterface && targetMethod.IsPrivate) - { - SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IncompatibleClassChangeError, "private interface method requires invokespecial, not invokeinterface: method {0}.{1}{2}", cpi.Class, cpi.Name, cpi.Signature); - } - else if (targetMethod.IsAccessibleFrom(cpi.GetClassType(), wrapper, thisType)) - { - return; - } - else if (host != null && targetMethod.IsAccessibleFrom(cpi.GetClassType(), host, thisType)) - { - switch (invoke) - { - case NormalizedByteCode.__invokespecial: - instr.PatchOpCode(NormalizedByteCode.__privileged_invokespecial); - break; - case NormalizedByteCode.__invokestatic: - instr.PatchOpCode(NormalizedByteCode.__privileged_invokestatic); - break; - case NormalizedByteCode.__invokevirtual: - instr.PatchOpCode(NormalizedByteCode.__privileged_invokevirtual); - break; - default: - throw new InvalidOperationException(); - } - return; - } - else - { - // NOTE special case for incorrect invocation of Object.clone(), because this could mean - // we're calling clone() on an array - // (bug in javac, see http://developer.java.sun.com/developer/bugParade/bugs/4329886.html) - if (cpi.GetClassType() == CoreClasses.java.lang.Object.Wrapper - && thisType.IsArray - && ReferenceEquals(cpi.Name, StringConstants.CLONE)) - { - // Patch the instruction, so that the compiler doesn't need to do this test again. - instr.PatchOpCode(NormalizedByteCode.__clone_array); - return; - } - SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IllegalAccessError, "tried to access method {0}.{1}{2} from class {3}", ToSlash(targetMethod.DeclaringType.Name), cpi.Name, ToSlash(cpi.Signature), ToSlash(wrapper.Name)); - } - } - else - { - SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IncompatibleClassChangeError, "static call to non-static method (or v.v.)"); - } - } - else - { - SetHardError(wrapper.GetClassLoader(), ref instr, HardError.NoSuchMethodError, "{0}.{1}{2}", cpi.Class, cpi.Name, cpi.Signature); - } - } - } - - private static string ToSlash(string str) - { - return str.Replace('.', '/'); - } - - private void PatchFieldAccess(TypeWrapper wrapper, MethodWrapper mw, ref ClassFile.Method.Instruction instr, StackState stack) - { - ClassFile.ConstantPoolItemFieldref cpi = classFile.GetFieldref(instr.Arg1); - bool isStatic; - bool write; - TypeWrapper thisType; - switch (instr.NormalizedOpCode) - { - case NormalizedByteCode.__getfield: - isStatic = false; - write = false; - thisType = SigTypeToClassName(stack.PopObjectType(GetFieldref(instr.Arg1).GetClassType()), cpi.GetClassType(), wrapper); - break; - case NormalizedByteCode.__putfield: - stack.PopType(GetFieldref(instr.Arg1).GetFieldType()); - isStatic = false; - write = true; - // putfield is allowed to access the unintialized this - if (stack.PeekType() == VerifierTypeWrapper.UninitializedThis - && wrapper.IsAssignableTo(GetFieldref(instr.Arg1).GetClassType())) - { - thisType = wrapper; - } - else - { - thisType = SigTypeToClassName(stack.PopObjectType(GetFieldref(instr.Arg1).GetClassType()), cpi.GetClassType(), wrapper); - } - break; - case NormalizedByteCode.__getstatic: - isStatic = true; - write = false; - thisType = null; - break; - case NormalizedByteCode.__putstatic: - // special support for when we're being called from IsSideEffectFreeStaticInitializer - if (mw == null) - { - switch (GetFieldref(instr.Arg1).Signature[0]) - { - case 'B': - case 'Z': - case 'C': - case 'S': - case 'I': - stack.PopInt(); - break; - case 'F': - stack.PopFloat(); - break; - case 'D': - stack.PopDouble(); - break; - case 'J': - stack.PopLong(); - break; - case 'L': - case '[': - if (stack.PopAnyType() != VerifierTypeWrapper.Null) - { - throw new VerifyError(); - } - break; - default: - throw new InvalidOperationException(); - } - } - else - { - stack.PopType(GetFieldref(instr.Arg1).GetFieldType()); - } - isStatic = true; - write = true; - thisType = null; - break; - default: - throw new InvalidOperationException(); - } - if (mw == null) - { - // We're being called from IsSideEffectFreeStaticInitializer, - // no further checks are possible (nor needed). - } - else if (cpi.GetClassType().IsUnloadable) - { - if (wrapper.GetClassLoader().DisableDynamicBinding) - { - SetHardError(wrapper.GetClassLoader(), ref instr, HardError.NoClassDefFoundError, "{0}", cpi.GetClassType().Name); - } - else - { - switch (instr.NormalizedOpCode) - { - case NormalizedByteCode.__getstatic: - instr.PatchOpCode(NormalizedByteCode.__dynamic_getstatic); - break; - case NormalizedByteCode.__putstatic: - instr.PatchOpCode(NormalizedByteCode.__dynamic_putstatic); - break; - case NormalizedByteCode.__getfield: - instr.PatchOpCode(NormalizedByteCode.__dynamic_getfield); - break; - case NormalizedByteCode.__putfield: - instr.PatchOpCode(NormalizedByteCode.__dynamic_putfield); - break; - default: - throw new InvalidOperationException(); - } - } - return; - } - else - { - FieldWrapper field = cpi.GetField(); - if (field == null) - { - SetHardError(wrapper.GetClassLoader(), ref instr, HardError.NoSuchFieldError, "{0}.{1}", cpi.Class, cpi.Name); - return; - } - if (false && cpi.GetFieldType() != field.FieldTypeWrapper && !cpi.GetFieldType().IsUnloadable & !field.FieldTypeWrapper.IsUnloadable) - { -#if IMPORTER - StaticCompiler.LinkageError("Field \"{2}.{3}\" is of type \"{0}\" instead of type \"{1}\" as expected by \"{4}\"", field.FieldTypeWrapper, cpi.GetFieldType(), cpi.GetClassType().Name, cpi.Name, wrapper.Name); -#endif - SetHardError(wrapper.GetClassLoader(), ref instr, HardError.LinkageError, "Loader constraints violated: {0}.{1}", field.DeclaringType.Name, field.Name); - return; - } - if (field.IsStatic != isStatic) - { - SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IncompatibleClassChangeError, "Static field access to non-static field (or v.v.)"); - return; - } - if (!field.IsAccessibleFrom(cpi.GetClassType(), wrapper, thisType)) - { - SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IllegalAccessError, "Try to access field {0}.{1} from class {2}", field.DeclaringType.Name, field.Name, wrapper.Name); - return; - } - // are we trying to mutate a final field? (they are read-only from outside of the defining class) - if (write && field.IsFinal - && ((isStatic ? wrapper != cpi.GetClassType() : wrapper != thisType) || (wrapper.GetClassLoader().StrictFinalFieldSemantics && (isStatic ? (mw != null && mw.Name != "") : (mw == null || mw.Name != ""))))) - { - SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IllegalAccessError, "Field {0}.{1} is final", field.DeclaringType.Name, field.Name); - return; - } - } - } - - // TODO this method should have a better name - private TypeWrapper SigTypeToClassName(TypeWrapper type, TypeWrapper nullType, TypeWrapper wrapper) - { - if (type == VerifierTypeWrapper.UninitializedThis) - { - return wrapper; - } - else if (VerifierTypeWrapper.IsNew(type)) - { - return ((VerifierTypeWrapper)type).UnderlyingType; - } - else if (type == VerifierTypeWrapper.Null) - { - return nullType; - } - else - { - return type; - } - } - - private int AllocErrorMessage(string message) - { - if (errorMessages == null) - { - errorMessages = new List(); - } - int index = errorMessages.Count; - errorMessages.Add(message); - return index; - } - - private string CheckLoaderConstraints(ClassFile.ConstantPoolItemMI cpi, MethodWrapper mw) - { -#if NETFRAMEWORK - if (cpi.GetRetType() != mw.ReturnType && !cpi.GetRetType().IsUnloadable && !mw.ReturnType.IsUnloadable) -#else - if (cpi.GetRetType() != mw.ReturnType && cpi.GetRetType().Name != mw.ReturnType.Name && !cpi.GetRetType().IsUnloadable && !mw.ReturnType.IsUnloadable) -#endif - { -#if IMPORTER - StaticCompiler.LinkageError("Method \"{2}.{3}{4}\" has a return type \"{0}\" instead of type \"{1}\" as expected by \"{5}\"", mw.ReturnType, cpi.GetRetType(), cpi.GetClassType().Name, cpi.Name, cpi.Signature, classFile.Name); -#endif - return "Loader constraints violated (return type): " + mw.DeclaringType.Name + "." + mw.Name + mw.Signature; - } - TypeWrapper[] here = cpi.GetArgTypes(); - TypeWrapper[] there = mw.GetParameters(); - for (int i = 0; i < here.Length; i++) - { -#if NETFRAMEWORK - if (here[i] != there[i] && !here[i].IsUnloadable && !there[i].IsUnloadable) -#else - if (here[i] != there[i] && here[i].Name != there[i].Name && !here[i].IsUnloadable && !there[i].IsUnloadable) -#endif - { -#if IMPORTER - StaticCompiler.LinkageError("Method \"{2}.{3}{4}\" has a argument type \"{0}\" instead of type \"{1}\" as expected by \"{5}\"", there[i], here[i], cpi.GetClassType().Name, cpi.Name, cpi.Signature, classFile.Name); -#endif - return "Loader constraints violated (arg " + i + "): " + mw.DeclaringType.Name + "." + mw.Name + mw.Signature; - } - } - return null; - } - - private ClassFile.ConstantPoolItemInvokeDynamic GetInvokeDynamic(int index) - { - try - { - ClassFile.ConstantPoolItemInvokeDynamic item = classFile.GetInvokeDynamic(index); - if (item != null) - { - return item; - } - } - catch (InvalidCastException) - { - } - catch (IndexOutOfRangeException) - { - } - throw new VerifyError("Illegal constant pool index"); - } - - private ClassFile.ConstantPoolItemMI GetMethodref(int index) - { - try - { - ClassFile.ConstantPoolItemMI item = classFile.GetMethodref(index); - if (item != null) - { - return item; - } - } - catch (InvalidCastException) - { - } - catch (IndexOutOfRangeException) - { - } - throw new VerifyError("Illegal constant pool index"); - } - - private ClassFile.ConstantPoolItemFieldref GetFieldref(int index) - { - try - { - ClassFile.ConstantPoolItemFieldref item = classFile.GetFieldref(index); - if (item != null) - { - return item; - } - } - catch (InvalidCastException) - { - } - catch (IndexOutOfRangeException) - { - } - throw new VerifyError("Illegal constant pool index"); - } - - private ClassFile.ConstantType GetConstantPoolConstantType(int index) - { - try - { - return classFile.GetConstantPoolConstantType(index); - } - catch (IndexOutOfRangeException) - { - // constant pool index out of range - } - catch (InvalidOperationException) - { - // specified constant pool entry doesn't contain a constant - } - catch (NullReferenceException) - { - // specified constant pool entry is empty (entry 0 or the filler following a wide entry) - } - throw new VerifyError("Illegal constant pool index"); - } - - private TypeWrapper GetConstantPoolClassType(int index) - { - try - { - return classFile.GetConstantPoolClassType(index); - } - catch (InvalidCastException) - { - } - catch (IndexOutOfRangeException) - { - } - catch (NullReferenceException) - { - } - throw new VerifyError("Illegal constant pool index"); - } - - internal void ClearFaultBlockException(int instructionIndex) - { - Debug.Assert(state[instructionIndex].GetStackHeight() == 1); - state[instructionIndex].ClearFaultBlockException(); - } - - private static void DumpMethod(CodeInfo codeInfo, ClassFile.Method method, UntangledExceptionTable exceptions) - { - ClassFile.Method.Instruction[] code = method.Instructions; - InstructionFlags[] flags = ComputePartialReachability(codeInfo, code, exceptions, 0, false); - for (int i = 0; i < code.Length; i++) - { - bool label = (flags[i] & InstructionFlags.BranchTarget) != 0; - if (!label) - { - for (int j = 0; j < exceptions.Length; j++) - { - if (exceptions[j].startIndex == i - || exceptions[j].endIndex == i - || exceptions[j].handlerIndex == i) - { - label = true; - break; - } - } - } - if (label) - { - Console.WriteLine("label{0}:", i); - } - if ((flags[i] & InstructionFlags.Reachable) != 0) - { - Console.Write(" {1}", i, code[i].NormalizedOpCode.ToString().Substring(2)); - switch (ByteCodeMetaData.GetFlowControl(code[i].NormalizedOpCode)) - { - case ByteCodeFlowControl.Branch: - case ByteCodeFlowControl.CondBranch: - Console.Write(" label{0}", code[i].Arg1); - break; - } - switch (code[i].NormalizedOpCode) - { - case NormalizedByteCode.__iload: - case NormalizedByteCode.__lload: - case NormalizedByteCode.__fload: - case NormalizedByteCode.__dload: - case NormalizedByteCode.__aload: - case NormalizedByteCode.__istore: - case NormalizedByteCode.__lstore: - case NormalizedByteCode.__fstore: - case NormalizedByteCode.__dstore: - case NormalizedByteCode.__astore: - case NormalizedByteCode.__iconst: - Console.Write(" {0}", code[i].Arg1); - break; - case NormalizedByteCode.__ldc: - case NormalizedByteCode.__ldc_nothrow: - case NormalizedByteCode.__getfield: - case NormalizedByteCode.__getstatic: - case NormalizedByteCode.__putfield: - case NormalizedByteCode.__putstatic: - case NormalizedByteCode.__invokeinterface: - case NormalizedByteCode.__invokespecial: - case NormalizedByteCode.__invokestatic: - case NormalizedByteCode.__invokevirtual: - case NormalizedByteCode.__new: - Console.Write(" #{0}", code[i].Arg1); - break; - } - Console.WriteLine(); - } - } - for (int i = 0; i < exceptions.Length; i++) - { - Console.WriteLine(".catch #{0} from label{1} to label{2} using label{3}", exceptions[i].catch_type, exceptions[i].startIndex, exceptions[i].endIndex, exceptions[i].handlerIndex); - } - } -} diff --git a/src/IKVM.Tools.Exporter/BootstrapBootstrapClassLoader.cs b/src/IKVM.Tools.Exporter/BootstrapBootstrapClassLoader.cs index c10bf2dbfe..1bcdc5e1db 100644 --- a/src/IKVM.Tools.Exporter/BootstrapBootstrapClassLoader.cs +++ b/src/IKVM.Tools.Exporter/BootstrapBootstrapClassLoader.cs @@ -24,7 +24,6 @@ Jeroen Frijters using System; using IKVM.Attributes; -using IKVM.Internal; using IKVM.Runtime; sealed class BootstrapBootstrapClassLoader : ClassLoaderWrapper diff --git a/src/IKVM.Tools.Exporter/IkvmExporterInternal.cs b/src/IKVM.Tools.Exporter/IkvmExporterInternal.cs index 2f44f95aef..f0a418adfa 100644 --- a/src/IKVM.Tools.Exporter/IkvmExporterInternal.cs +++ b/src/IKVM.Tools.Exporter/IkvmExporterInternal.cs @@ -4,7 +4,6 @@ using System.IO.Compression; using System.Linq; -using IKVM.Internal; using IKVM.Reflection; using IKVM.Runtime; using IKVM.Tools.Importer; @@ -31,8 +30,8 @@ static class IkvmExporterInternal /// public static int Execute(IkvmExporterOptions options) { - IKVM.Internal.Tracer.EnableTraceConsoleListener(); - IKVM.Internal.Tracer.EnableTraceForDebug(); + IKVM.Runtime.Tracer.EnableTraceConsoleListener(); + IKVM.Runtime.Tracer.EnableTraceForDebug(); var references = new List(); if (options.References != null) diff --git a/src/IKVM.Tools.Exporter/Intrinsics.cs b/src/IKVM.Tools.Exporter/Intrinsics.cs index f40f5149e6..101ce73183 100644 --- a/src/IKVM.Tools.Exporter/Intrinsics.cs +++ b/src/IKVM.Tools.Exporter/Intrinsics.cs @@ -21,7 +21,7 @@ Jeroen Frijters jeroen@frijters.net */ -using IKVM.Internal; +using IKVM.Runtime; static class Intrinsics { @@ -32,3 +32,4 @@ internal static bool IsIntrinsic(MethodWrapper methodWrapper) } } + diff --git a/src/IKVM.Tools.Exporter/StubTypeWrapper.cs b/src/IKVM.Tools.Exporter/StubTypeWrapper.cs index 7cb2053921..873a0dbf58 100644 --- a/src/IKVM.Tools.Exporter/StubTypeWrapper.cs +++ b/src/IKVM.Tools.Exporter/StubTypeWrapper.cs @@ -24,39 +24,44 @@ Jeroen Frijters using System; using IKVM.Attributes; -using IKVM.Internal; using Type = IKVM.Reflection.Type; -sealed class StubTypeWrapper : TypeWrapper +namespace IKVM.Runtime { - private readonly bool remapped; - private readonly TypeWrapper baseWrapper; - internal StubTypeWrapper(Modifiers modifiers, string name, TypeWrapper baseWrapper, bool remapped) - : base(TypeFlags.None, modifiers, name) + sealed class StubTypeWrapper : TypeWrapper { - this.remapped = remapped; - this.baseWrapper = baseWrapper; - } - internal override TypeWrapper BaseTypeWrapper - { - get { return baseWrapper; } - } + private readonly bool remapped; + private readonly TypeWrapper baseWrapper; - internal override ClassLoaderWrapper GetClassLoader() - { - return ClassLoaderWrapper.GetBootstrapClassLoader(); - } + internal StubTypeWrapper(Modifiers modifiers, string name, TypeWrapper baseWrapper, bool remapped) + : base(TypeFlags.None, modifiers, name) + { + this.remapped = remapped; + this.baseWrapper = baseWrapper; + } - internal override Type TypeAsTBD - { - get { throw new NotSupportedException(); } - } + internal override TypeWrapper BaseTypeWrapper + { + get { return baseWrapper; } + } - internal override bool IsRemapped - { - get { return remapped; } + internal override ClassLoaderWrapper GetClassLoader() + { + return ClassLoaderWrapper.GetBootstrapClassLoader(); + } + + internal override Type TypeAsTBD + { + get { throw new NotSupportedException(); } + } + + internal override bool IsRemapped + { + get { return remapped; } + } } + } diff --git a/src/IKVM.Tools.Importer/AotTypeWrapper.cs b/src/IKVM.Tools.Importer/AotTypeWrapper.cs index 90f5758c64..0918b62841 100644 --- a/src/IKVM.Tools.Importer/AotTypeWrapper.cs +++ b/src/IKVM.Tools.Importer/AotTypeWrapper.cs @@ -26,7 +26,6 @@ Jeroen Frijters using System.Collections.Generic; using IKVM.Attributes; -using IKVM.Internal; using IKVM.Reflection; using IKVM.Reflection.Emit; using IKVM.Runtime; diff --git a/src/IKVM.Tools.Importer/AssemblyResolver.cs b/src/IKVM.Tools.Importer/AssemblyResolver.cs index 4315773afc..a227eac215 100644 --- a/src/IKVM.Tools.Importer/AssemblyResolver.cs +++ b/src/IKVM.Tools.Importer/AssemblyResolver.cs @@ -25,8 +25,8 @@ Jeroen Frijters using System.Collections.Generic; using System.IO; -using IKVM.Internal; using IKVM.Reflection; +using IKVM.Runtime; namespace IKVM.Tools.Importer { diff --git a/src/IKVM.Tools.Importer/CompilerClassLoader.cs b/src/IKVM.Tools.Importer/CompilerClassLoader.cs index 5ba606b77d..1b447887e2 100644 --- a/src/IKVM.Tools.Importer/CompilerClassLoader.cs +++ b/src/IKVM.Tools.Importer/CompilerClassLoader.cs @@ -35,7 +35,6 @@ Jeroen Frijters using IKVM.Attributes; using IKVM.ByteCode.Reading; -using IKVM.Internal; using IKVM.Reflection; using IKVM.Reflection.Emit; using IKVM.Runtime; diff --git a/src/IKVM.Tools.Importer/FakeTypes.cs b/src/IKVM.Tools.Importer/FakeTypes.cs index a3dec3f1a8..84b57015bc 100644 --- a/src/IKVM.Tools.Importer/FakeTypes.cs +++ b/src/IKVM.Tools.Importer/FakeTypes.cs @@ -21,16 +21,16 @@ Jeroen Frijters jeroen@frijters.net */ -using IKVM.Internal; using IKVM.Reflection; using IKVM.Reflection.Emit; +using IKVM.Runtime; using Type = IKVM.Reflection.Type; namespace IKVM.Tools.Importer { - static class FakeTypes + static class FakeTypes { private static Type genericEnumEnumType; diff --git a/src/IKVM.Tools.Importer/IkvmImporterInternal.cs b/src/IKVM.Tools.Importer/IkvmImporterInternal.cs index af3e12a143..e84cdae0d9 100644 --- a/src/IKVM.Tools.Importer/IkvmImporterInternal.cs +++ b/src/IKVM.Tools.Importer/IkvmImporterInternal.cs @@ -29,7 +29,6 @@ Jeroen Frijters using System.Threading; using IKVM.ByteCode.Reading; -using IKVM.Internal; using IKVM.Reflection; using IKVM.Reflection.Emit; using IKVM.Runtime; diff --git a/src/IKVM.Tools.Importer/MapXml/Beq.cs b/src/IKVM.Tools.Importer/MapXml/Beq.cs index 7816cd31ec..3da5f40b8c 100644 --- a/src/IKVM.Tools.Importer/MapXml/Beq.cs +++ b/src/IKVM.Tools.Importer/MapXml/Beq.cs @@ -24,7 +24,7 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/Bge_Un.cs b/src/IKVM.Tools.Importer/MapXml/Bge_Un.cs index 566e250848..f9025947b7 100644 --- a/src/IKVM.Tools.Importer/MapXml/Bge_Un.cs +++ b/src/IKVM.Tools.Importer/MapXml/Bge_Un.cs @@ -24,7 +24,7 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/Ble_Un.cs b/src/IKVM.Tools.Importer/MapXml/Ble_Un.cs index ed3e51be4b..a6e7305c12 100644 --- a/src/IKVM.Tools.Importer/MapXml/Ble_Un.cs +++ b/src/IKVM.Tools.Importer/MapXml/Ble_Un.cs @@ -24,7 +24,7 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/Blt.cs b/src/IKVM.Tools.Importer/MapXml/Blt.cs index d6001e822c..57dc18ddf8 100644 --- a/src/IKVM.Tools.Importer/MapXml/Blt.cs +++ b/src/IKVM.Tools.Importer/MapXml/Blt.cs @@ -24,7 +24,7 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/Blt_Un.cs b/src/IKVM.Tools.Importer/MapXml/Blt_Un.cs index 352120577a..3021f570e9 100644 --- a/src/IKVM.Tools.Importer/MapXml/Blt_Un.cs +++ b/src/IKVM.Tools.Importer/MapXml/Blt_Un.cs @@ -24,7 +24,7 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/Bne_Un.cs b/src/IKVM.Tools.Importer/MapXml/Bne_Un.cs index 273321f758..757e964901 100644 --- a/src/IKVM.Tools.Importer/MapXml/Bne_Un.cs +++ b/src/IKVM.Tools.Importer/MapXml/Bne_Un.cs @@ -24,7 +24,7 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/Br.cs b/src/IKVM.Tools.Importer/MapXml/Br.cs index fa302e2c21..a72e72ce3a 100644 --- a/src/IKVM.Tools.Importer/MapXml/Br.cs +++ b/src/IKVM.Tools.Importer/MapXml/Br.cs @@ -24,7 +24,7 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/BrFalse.cs b/src/IKVM.Tools.Importer/MapXml/BrFalse.cs index 0f300a8645..51da5410cf 100644 --- a/src/IKVM.Tools.Importer/MapXml/BrFalse.cs +++ b/src/IKVM.Tools.Importer/MapXml/BrFalse.cs @@ -23,9 +23,8 @@ Jeroen Frijters */ using System.Xml.Linq; -using System.Xml.Serialization; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/BrLabel.cs b/src/IKVM.Tools.Importer/MapXml/BrLabel.cs index 55de8432db..2a693c5e3c 100644 --- a/src/IKVM.Tools.Importer/MapXml/BrLabel.cs +++ b/src/IKVM.Tools.Importer/MapXml/BrLabel.cs @@ -25,7 +25,7 @@ Jeroen Frijters using System.Xml.Linq; using System.Xml.Serialization; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/BrTrue.cs b/src/IKVM.Tools.Importer/MapXml/BrTrue.cs index 7cfd344ac9..886d99899d 100644 --- a/src/IKVM.Tools.Importer/MapXml/BrTrue.cs +++ b/src/IKVM.Tools.Importer/MapXml/BrTrue.cs @@ -24,7 +24,7 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/Branch.cs b/src/IKVM.Tools.Importer/MapXml/Branch.cs index ea0e8598e3..58c2e5d950 100644 --- a/src/IKVM.Tools.Importer/MapXml/Branch.cs +++ b/src/IKVM.Tools.Importer/MapXml/Branch.cs @@ -24,7 +24,7 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/Call.cs b/src/IKVM.Tools.Importer/MapXml/Call.cs index ee7da26896..d81d15ba31 100644 --- a/src/IKVM.Tools.Importer/MapXml/Call.cs +++ b/src/IKVM.Tools.Importer/MapXml/Call.cs @@ -27,9 +27,9 @@ Jeroen Frijters using System.Linq; using System.Xml.Linq; -using IKVM.Internal; using IKVM.Reflection; using IKVM.Reflection.Emit; +using IKVM.Runtime; using Type = IKVM.Reflection.Type; diff --git a/src/IKVM.Tools.Importer/MapXml/Castclass.cs b/src/IKVM.Tools.Importer/MapXml/Castclass.cs index 5823d0be44..d7f3ff7fc1 100644 --- a/src/IKVM.Tools.Importer/MapXml/Castclass.cs +++ b/src/IKVM.Tools.Importer/MapXml/Castclass.cs @@ -24,8 +24,8 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; using IKVM.Reflection.Emit; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/Castclass_impl.cs b/src/IKVM.Tools.Importer/MapXml/Castclass_impl.cs index 13ce89d45e..b79758e69e 100644 --- a/src/IKVM.Tools.Importer/MapXml/Castclass_impl.cs +++ b/src/IKVM.Tools.Importer/MapXml/Castclass_impl.cs @@ -24,8 +24,8 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; using IKVM.Reflection.Emit; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/ClassInitializer.cs b/src/IKVM.Tools.Importer/MapXml/ClassInitializer.cs index f2948ead67..b64f8a1531 100644 --- a/src/IKVM.Tools.Importer/MapXml/ClassInitializer.cs +++ b/src/IKVM.Tools.Importer/MapXml/ClassInitializer.cs @@ -22,10 +22,8 @@ Jeroen Frijters */ -using System.Linq; using System.Xml.Linq; -using IKVM.Internal; using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml diff --git a/src/IKVM.Tools.Importer/MapXml/CodeGenContext.cs b/src/IKVM.Tools.Importer/MapXml/CodeGenContext.cs index 6b351fa802..fee9cf4f26 100644 --- a/src/IKVM.Tools.Importer/MapXml/CodeGenContext.cs +++ b/src/IKVM.Tools.Importer/MapXml/CodeGenContext.cs @@ -24,7 +24,7 @@ Jeroen Frijters using System.Collections.Generic; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/ConditionalInstruction.cs b/src/IKVM.Tools.Importer/MapXml/ConditionalInstruction.cs index ee4fb7d284..cb8100f9fa 100644 --- a/src/IKVM.Tools.Importer/MapXml/ConditionalInstruction.cs +++ b/src/IKVM.Tools.Importer/MapXml/ConditionalInstruction.cs @@ -26,7 +26,7 @@ Jeroen Frijters using System.Linq; using System.Xml.Linq; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/Constructor.cs b/src/IKVM.Tools.Importer/MapXml/Constructor.cs index 121217834f..960f09aca6 100644 --- a/src/IKVM.Tools.Importer/MapXml/Constructor.cs +++ b/src/IKVM.Tools.Importer/MapXml/Constructor.cs @@ -24,7 +24,6 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml diff --git a/src/IKVM.Tools.Importer/MapXml/EmitExceptionMapping.cs b/src/IKVM.Tools.Importer/MapXml/EmitExceptionMapping.cs index 4ec630c3e3..e1ea480f7b 100644 --- a/src/IKVM.Tools.Importer/MapXml/EmitExceptionMapping.cs +++ b/src/IKVM.Tools.Importer/MapXml/EmitExceptionMapping.cs @@ -24,7 +24,7 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/ExceptionBlock.cs b/src/IKVM.Tools.Importer/MapXml/ExceptionBlock.cs index c9556fbea4..5250df6c49 100644 --- a/src/IKVM.Tools.Importer/MapXml/ExceptionBlock.cs +++ b/src/IKVM.Tools.Importer/MapXml/ExceptionBlock.cs @@ -24,9 +24,8 @@ Jeroen Frijters using System.Linq; using System.Xml.Linq; -using System.Xml.Serialization; -using IKVM.Internal; +using IKVM.Runtime; using Type = IKVM.Reflection.Type; diff --git a/src/IKVM.Tools.Importer/MapXml/Instruction.cs b/src/IKVM.Tools.Importer/MapXml/Instruction.cs index 1cf46bd2cf..1b3b09c37b 100644 --- a/src/IKVM.Tools.Importer/MapXml/Instruction.cs +++ b/src/IKVM.Tools.Importer/MapXml/Instruction.cs @@ -3,7 +3,7 @@ using System.Reflection; using System.Xml.Linq; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/InstructionList.cs b/src/IKVM.Tools.Importer/MapXml/InstructionList.cs index 6ffd10db88..d7fa4019d5 100644 --- a/src/IKVM.Tools.Importer/MapXml/InstructionList.cs +++ b/src/IKVM.Tools.Importer/MapXml/InstructionList.cs @@ -25,7 +25,7 @@ Jeroen Frijters using System.Linq; using System.Xml.Linq; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/IsInst.cs b/src/IKVM.Tools.Importer/MapXml/IsInst.cs index 3d3f00fdca..feecfa389b 100644 --- a/src/IKVM.Tools.Importer/MapXml/IsInst.cs +++ b/src/IKVM.Tools.Importer/MapXml/IsInst.cs @@ -23,10 +23,9 @@ Jeroen Frijters */ using System.Xml.Linq; -using System.Xml.Serialization; -using IKVM.Internal; using IKVM.Reflection.Emit; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/LdArg_S.cs b/src/IKVM.Tools.Importer/MapXml/LdArg_S.cs index 71a1ed4a3b..e597fc9c76 100644 --- a/src/IKVM.Tools.Importer/MapXml/LdArg_S.cs +++ b/src/IKVM.Tools.Importer/MapXml/LdArg_S.cs @@ -24,7 +24,7 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/LdArga.cs b/src/IKVM.Tools.Importer/MapXml/LdArga.cs index c4fef0720d..c3d93989f9 100644 --- a/src/IKVM.Tools.Importer/MapXml/LdArga.cs +++ b/src/IKVM.Tools.Importer/MapXml/LdArga.cs @@ -24,7 +24,7 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/LdLoc.cs b/src/IKVM.Tools.Importer/MapXml/LdLoc.cs index c0abf8f9c8..566a143103 100644 --- a/src/IKVM.Tools.Importer/MapXml/LdLoc.cs +++ b/src/IKVM.Tools.Importer/MapXml/LdLoc.cs @@ -23,10 +23,9 @@ Jeroen Frijters */ using System.Xml.Linq; -using System.Xml.Serialization; -using IKVM.Internal; using IKVM.Reflection.Emit; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/Ldc_I4.cs b/src/IKVM.Tools.Importer/MapXml/Ldc_I4.cs index 9fdbb23946..0c8930eed7 100644 --- a/src/IKVM.Tools.Importer/MapXml/Ldc_I4.cs +++ b/src/IKVM.Tools.Importer/MapXml/Ldc_I4.cs @@ -24,7 +24,7 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/Ldelema.cs b/src/IKVM.Tools.Importer/MapXml/Ldelema.cs index d1bebcfc66..1b4688cdaa 100644 --- a/src/IKVM.Tools.Importer/MapXml/Ldelema.cs +++ b/src/IKVM.Tools.Importer/MapXml/Ldelema.cs @@ -24,7 +24,7 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Reflection.Emit; namespace IKVM.Tools.Importer.MapXml diff --git a/src/IKVM.Tools.Importer/MapXml/Ldfld.cs b/src/IKVM.Tools.Importer/MapXml/Ldfld.cs index ae9dbb5682..e521facdec 100644 --- a/src/IKVM.Tools.Importer/MapXml/Ldfld.cs +++ b/src/IKVM.Tools.Importer/MapXml/Ldfld.cs @@ -24,7 +24,7 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Reflection.Emit; namespace IKVM.Tools.Importer.MapXml diff --git a/src/IKVM.Tools.Importer/MapXml/Ldflda.cs b/src/IKVM.Tools.Importer/MapXml/Ldflda.cs index 4ddcf2db3c..ec778c47d5 100644 --- a/src/IKVM.Tools.Importer/MapXml/Ldflda.cs +++ b/src/IKVM.Tools.Importer/MapXml/Ldflda.cs @@ -24,8 +24,8 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; using IKVM.Reflection.Emit; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/Ldlen.cs b/src/IKVM.Tools.Importer/MapXml/Ldlen.cs index 2c1b6621a0..e134943bf2 100644 --- a/src/IKVM.Tools.Importer/MapXml/Ldlen.cs +++ b/src/IKVM.Tools.Importer/MapXml/Ldlen.cs @@ -23,7 +23,6 @@ Jeroen Frijters */ using System.Xml.Linq; -using System.Xml.Serialization; using IKVM.Reflection.Emit; diff --git a/src/IKVM.Tools.Importer/MapXml/Ldsfld.cs b/src/IKVM.Tools.Importer/MapXml/Ldsfld.cs index 96ca7e9567..ecfca097fa 100644 --- a/src/IKVM.Tools.Importer/MapXml/Ldsfld.cs +++ b/src/IKVM.Tools.Importer/MapXml/Ldsfld.cs @@ -24,9 +24,9 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; using IKVM.Reflection; using IKVM.Reflection.Emit; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/Ldstr.cs b/src/IKVM.Tools.Importer/MapXml/Ldstr.cs index b895fa4458..3cc6e13ce8 100644 --- a/src/IKVM.Tools.Importer/MapXml/Ldstr.cs +++ b/src/IKVM.Tools.Importer/MapXml/Ldstr.cs @@ -24,8 +24,8 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; using IKVM.Reflection.Emit; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/Ldtoken.cs b/src/IKVM.Tools.Importer/MapXml/Ldtoken.cs index 430586cae7..a01013cca1 100644 --- a/src/IKVM.Tools.Importer/MapXml/Ldtoken.cs +++ b/src/IKVM.Tools.Importer/MapXml/Ldtoken.cs @@ -24,11 +24,10 @@ Jeroen Frijters using System; using System.Xml.Linq; -using System.Xml.Serialization; -using IKVM.Internal; using IKVM.Reflection; using IKVM.Reflection.Emit; +using IKVM.Runtime; using Type = IKVM.Reflection.Type; diff --git a/src/IKVM.Tools.Importer/MapXml/Leave.cs b/src/IKVM.Tools.Importer/MapXml/Leave.cs index cbb87f7a15..c70a2a7bb6 100644 --- a/src/IKVM.Tools.Importer/MapXml/Leave.cs +++ b/src/IKVM.Tools.Importer/MapXml/Leave.cs @@ -23,9 +23,8 @@ Jeroen Frijters */ using System.Xml.Linq; -using System.Xml.Serialization; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/MethodConstructorBase.cs b/src/IKVM.Tools.Importer/MapXml/MethodConstructorBase.cs index dc576f7907..a9e0891eef 100644 --- a/src/IKVM.Tools.Importer/MapXml/MethodConstructorBase.cs +++ b/src/IKVM.Tools.Importer/MapXml/MethodConstructorBase.cs @@ -25,7 +25,7 @@ Jeroen Frijters using System.Linq; using System.Xml.Linq; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/Newarr.cs b/src/IKVM.Tools.Importer/MapXml/Newarr.cs index 44ec264757..5b3223adef 100644 --- a/src/IKVM.Tools.Importer/MapXml/Newarr.cs +++ b/src/IKVM.Tools.Importer/MapXml/Newarr.cs @@ -24,7 +24,7 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; +using IKVM.Runtime; using IKVM.Reflection.Emit; namespace IKVM.Tools.Importer.MapXml diff --git a/src/IKVM.Tools.Importer/MapXml/Pop.cs b/src/IKVM.Tools.Importer/MapXml/Pop.cs index 3768edcfe0..9a6ac80925 100644 --- a/src/IKVM.Tools.Importer/MapXml/Pop.cs +++ b/src/IKVM.Tools.Importer/MapXml/Pop.cs @@ -23,10 +23,9 @@ Jeroen Frijters */ using System.Xml.Linq; -using System.Xml.Serialization; -using IKVM.Internal; using IKVM.Reflection.Emit; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/Redirect.cs b/src/IKVM.Tools.Importer/MapXml/Redirect.cs index b72769bc71..84df4136a1 100644 --- a/src/IKVM.Tools.Importer/MapXml/Redirect.cs +++ b/src/IKVM.Tools.Importer/MapXml/Redirect.cs @@ -25,9 +25,9 @@ Jeroen Frijters using System; using System.Xml.Linq; -using IKVM.Internal; using IKVM.Reflection; using IKVM.Reflection.Emit; +using IKVM.Runtime; using Type = IKVM.Reflection.Type; diff --git a/src/IKVM.Tools.Importer/MapXml/Rem_Un.cs b/src/IKVM.Tools.Importer/MapXml/Rem_Un.cs index 5011c91e95..8b6a21f6c3 100644 --- a/src/IKVM.Tools.Importer/MapXml/Rem_Un.cs +++ b/src/IKVM.Tools.Importer/MapXml/Rem_Un.cs @@ -23,7 +23,6 @@ Jeroen Frijters */ using System.Xml.Linq; -using System.Xml.Serialization; using IKVM.Reflection.Emit; diff --git a/src/IKVM.Tools.Importer/MapXml/RunClassInit.cs b/src/IKVM.Tools.Importer/MapXml/RunClassInit.cs index 2f900dff42..0bea238ca4 100644 --- a/src/IKVM.Tools.Importer/MapXml/RunClassInit.cs +++ b/src/IKVM.Tools.Importer/MapXml/RunClassInit.cs @@ -24,7 +24,7 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/Simple.cs b/src/IKVM.Tools.Importer/MapXml/Simple.cs index 6e9f0ae44a..7d2a9db171 100644 --- a/src/IKVM.Tools.Importer/MapXml/Simple.cs +++ b/src/IKVM.Tools.Importer/MapXml/Simple.cs @@ -24,8 +24,8 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; using IKVM.Reflection.Emit; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/StLoc.cs b/src/IKVM.Tools.Importer/MapXml/StLoc.cs index ec1fe3085c..f5bee5db70 100644 --- a/src/IKVM.Tools.Importer/MapXml/StLoc.cs +++ b/src/IKVM.Tools.Importer/MapXml/StLoc.cs @@ -25,8 +25,8 @@ Jeroen Frijters using System.Diagnostics; using System.Xml.Linq; -using IKVM.Internal; using IKVM.Reflection.Emit; +using IKVM.Runtime; using Type = IKVM.Reflection.Type; diff --git a/src/IKVM.Tools.Importer/MapXml/Stfld.cs b/src/IKVM.Tools.Importer/MapXml/Stfld.cs index 7adbecfd06..2f03472bde 100644 --- a/src/IKVM.Tools.Importer/MapXml/Stfld.cs +++ b/src/IKVM.Tools.Importer/MapXml/Stfld.cs @@ -24,8 +24,8 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; using IKVM.Reflection.Emit; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/Stsfld.cs b/src/IKVM.Tools.Importer/MapXml/Stsfld.cs index ef37b37f96..c8a9791877 100644 --- a/src/IKVM.Tools.Importer/MapXml/Stsfld.cs +++ b/src/IKVM.Tools.Importer/MapXml/Stsfld.cs @@ -24,8 +24,8 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; using IKVM.Reflection.Emit; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/MapXml/TypeInstruction.cs b/src/IKVM.Tools.Importer/MapXml/TypeInstruction.cs index 3a04670656..e5f867038a 100644 --- a/src/IKVM.Tools.Importer/MapXml/TypeInstruction.cs +++ b/src/IKVM.Tools.Importer/MapXml/TypeInstruction.cs @@ -25,8 +25,8 @@ Jeroen Frijters using System.Diagnostics; using System.Xml.Linq; -using IKVM.Internal; using IKVM.Reflection.Emit; +using IKVM.Runtime; using Type = IKVM.Reflection.Type; diff --git a/src/IKVM.Tools.Importer/MapXml/TypeOrTypeWrapperInstruction.cs b/src/IKVM.Tools.Importer/MapXml/TypeOrTypeWrapperInstruction.cs index ec7583e744..defe7c2894 100644 --- a/src/IKVM.Tools.Importer/MapXml/TypeOrTypeWrapperInstruction.cs +++ b/src/IKVM.Tools.Importer/MapXml/TypeOrTypeWrapperInstruction.cs @@ -25,7 +25,7 @@ Jeroen Frijters using System.Diagnostics; using System.Xml.Linq; -using IKVM.Internal; +using IKVM.Runtime; using Type = IKVM.Reflection.Type; diff --git a/src/IKVM.Tools.Importer/MapXml/Unaligned.cs b/src/IKVM.Tools.Importer/MapXml/Unaligned.cs index 1e84c35c1b..961cbc0aaa 100644 --- a/src/IKVM.Tools.Importer/MapXml/Unaligned.cs +++ b/src/IKVM.Tools.Importer/MapXml/Unaligned.cs @@ -24,7 +24,7 @@ Jeroen Frijters using System.Xml.Linq; -using IKVM.Internal; +using IKVM.Runtime; namespace IKVM.Tools.Importer.MapXml { diff --git a/src/IKVM.Tools.Importer/Proxy.cs b/src/IKVM.Tools.Importer/Proxy.cs index aec88fba97..495ace44e4 100644 --- a/src/IKVM.Tools.Importer/Proxy.cs +++ b/src/IKVM.Tools.Importer/Proxy.cs @@ -25,7 +25,6 @@ Jeroen Frijters using System.Collections.Generic; using IKVM.Attributes; -using IKVM.Internal; using IKVM.Reflection; using IKVM.Reflection.Emit; using IKVM.Runtime; @@ -35,7 +34,7 @@ Jeroen Frijters namespace IKVM.Tools.Importer { - static class ProxyGenerator + static class ProxyGenerator { private static readonly TypeWrapper proxyClass;