diff options
-rw-r--r-- | LICENSE | 4 | ||||
-rw-r--r-- | classpath/gnu/java/nio/channels/FileChannelImpl.java | 4 | ||||
-rw-r--r-- | classpath/ikvm/lang/CIL.java | 30 | ||||
-rw-r--r-- | classpath/java/lang/reflect/Constructor.java | 4 | ||||
-rw-r--r-- | classpath/java/lang/reflect/Field.java | 41 | ||||
-rw-r--r-- | classpath/java/lang/reflect/Method.java | 4 | ||||
-rw-r--r-- | classpath/map.xml | 160 | ||||
-rw-r--r-- | runtime/ClassFile.cs | 4 | ||||
-rw-r--r-- | runtime/JniInterface.cs | 4 | ||||
-rw-r--r-- | runtime/MemberWrapper.cs | 310 | ||||
-rw-r--r-- | runtime/TypeWrapper.cs | 105 | ||||
-rw-r--r-- | runtime/remapper.cs | 81 | ||||
-rw-r--r-- | runtime/vm.cs | 13 |
13 files changed, 566 insertions, 198 deletions
@@ -2,7 +2,7 @@ IMPORTANT NOTICE Some files in this distribution are part of GNU Classpath and have a different license. This applies in particular to: - - classpath.dll + - IKVM.GNU.Classpath.dll - some of the *.java files (see each file header for license) See http://www.gnu.org/software/classpath/ for information on the @@ -10,7 +10,7 @@ IMPORTANT NOTICE ----------------------------------------------------------------------------- - Copyright (C) 2002, 2003 Jeroen Frijters + Copyright (C) 2002, 2003, 2004 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 diff --git a/classpath/gnu/java/nio/channels/FileChannelImpl.java b/classpath/gnu/java/nio/channels/FileChannelImpl.java index 93a022b5..960c2795 100644 --- a/classpath/gnu/java/nio/channels/FileChannelImpl.java +++ b/classpath/gnu/java/nio/channels/FileChannelImpl.java @@ -56,6 +56,7 @@ import java.nio.channels.WritableByteChannel; import cli.System.Console; import cli.System.IO.*; import ikvm.lang.ByteArrayHack; +import ikvm.lang.CIL; /** * This file is not user visible ! @@ -478,8 +479,7 @@ public final class FileChannelImpl extends FileChannel public void write (int b) throws IOException { - // HACK we can't call WriteByte because it takes a cli.System.Byte - write(new byte[] { (byte)b }, 0, 1); + stream.WriteByte(CIL.box_ubyte((byte)b)); } public long write(ByteBuffer[] srcs, int offset, int length) diff --git a/classpath/ikvm/lang/CIL.java b/classpath/ikvm/lang/CIL.java index 50081814..6ab8df78 100644 --- a/classpath/ikvm/lang/CIL.java +++ b/classpath/ikvm/lang/CIL.java @@ -1,5 +1,5 @@ /* - Copyright (C) 2003 Jeroen Frijters + Copyright (C) 2003, 2004 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 @@ -25,5 +25,31 @@ package ikvm.lang; public class CIL { - public static native int unbox_int(Object o); + public static native byte unbox_byte(Object o); + public static native boolean unbox_boolean(Object o); + public static native short unbox_short(Object o); + public static native char unbox_char(Object o); + public static native int unbox_int(Object o); + public static native float unbox_float(Object o); + public static native long unbox_long(Object o); + public static native double unbox_double(Object o); + + public static native Object box_byte(byte v); + public static native Object box_boolean(boolean v); + public static native Object box_short(short v); + public static native Object box_char(char v); + public static native Object box_int(int v); + public static native Object box_float(float v); + public static native Object box_long(long v); + public static native Object box_double(double v); + + public static native cli.System.Byte box_ubyte(byte v); + public static native cli.System.UInt16 box_ushort(short v); + public static native cli.System.UInt32 box_uint(int v); + public static native cli.System.UInt64 box_ulong(long v); + + public static native byte unbox_ubyte(cli.System.Byte v); + public static native short unbox_ushort(cli.System.UInt16 v); + public static native int unbox_uint(cli.System.UInt32 v); + public static native long unbox_ulong(cli.System.UInt64 v); } diff --git a/classpath/java/lang/reflect/Constructor.java b/classpath/java/lang/reflect/Constructor.java index abf963e6..7e78d4eb 100644 --- a/classpath/java/lang/reflect/Constructor.java +++ b/classpath/java/lang/reflect/Constructor.java @@ -79,6 +79,7 @@ public final class Constructor private Class declaringClass; private Object methodCookie; private int modifiers; + private boolean classIsPublic; /** * This class is instantiated by java.lang.Class @@ -89,6 +90,7 @@ public final class Constructor this.declaringClass = declaringClass; this.methodCookie = methodCookie; modifiers = Method.GetModifiers(methodCookie); + classIsPublic = (declaringClass.getModifiers() & Modifier.PUBLIC) != 0; } /** @@ -260,7 +262,7 @@ public final class Constructor throws InstantiationException, IllegalAccessException, InvocationTargetException { - if(!isAccessible() && !Modifier.isPublic(modifiers)) + if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) Field.checkAccess(modifiers, declaringClass, new StackFrame(1)); if(Modifier.isAbstract(declaringClass.getModifiers())) { diff --git a/classpath/java/lang/reflect/Field.java b/classpath/java/lang/reflect/Field.java index b9ca9be2..8a672f50 100644 --- a/classpath/java/lang/reflect/Field.java +++ b/classpath/java/lang/reflect/Field.java @@ -78,6 +78,7 @@ public final class Field extends AccessibleObject implements Member private Class declaringClass; private Object fieldCookie; private int modifiers; + private boolean classIsPublic; /** * This class is uninstantiable except natively. @@ -87,6 +88,7 @@ public final class Field extends AccessibleObject implements Member this.declaringClass = declaringClass; this.fieldCookie = fieldCookie; modifiers = GetModifiers(fieldCookie); + classIsPublic = (declaringClass.getModifiers() & Modifier.PUBLIC) != 0; } private static native int GetModifiers(Object fieldCookie); @@ -233,7 +235,7 @@ public final class Field extends AccessibleObject implements Member public Object get(Object o) throws IllegalAccessException { - if(!isAccessible() && !Modifier.isPublic(modifiers)) + if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) checkAccess(modifiers, declaringClass, new StackFrame(1)); return GetValue(fieldCookie, o); } @@ -259,7 +261,7 @@ public final class Field extends AccessibleObject implements Member public boolean getBoolean(Object o) throws IllegalAccessException { - if(!isAccessible() && !Modifier.isPublic(modifiers)) + if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) checkAccess(modifiers, declaringClass, new StackFrame(1)); return ((Boolean)GetValue(fieldCookie, o)).booleanValue(); } @@ -284,7 +286,7 @@ public final class Field extends AccessibleObject implements Member public byte getByte(Object o) throws IllegalAccessException { - if(!isAccessible() && !Modifier.isPublic(modifiers)) + if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) checkAccess(modifiers, declaringClass, new StackFrame(1)); return ((Byte)GetValue(fieldCookie, o)).byteValue(); } @@ -307,7 +309,7 @@ public final class Field extends AccessibleObject implements Member public char getChar(Object o) throws IllegalAccessException { - if(!isAccessible() && !Modifier.isPublic(modifiers)) + if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) checkAccess(modifiers, declaringClass, new StackFrame(1)); return ((Character)GetValue(fieldCookie, o)).charValue(); } @@ -332,7 +334,7 @@ public final class Field extends AccessibleObject implements Member public short getShort(Object o) throws IllegalAccessException { - if(!isAccessible() && !Modifier.isPublic(modifiers)) + if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) checkAccess(modifiers, declaringClass, new StackFrame(1)); return ((Short)GetValue(fieldCookie, o)).shortValue(); } @@ -357,7 +359,7 @@ public final class Field extends AccessibleObject implements Member public int getInt(Object o) throws IllegalAccessException { - if(!isAccessible() && !Modifier.isPublic(modifiers)) + if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) checkAccess(modifiers, declaringClass, new StackFrame(1)); return ((Integer)GetValue(fieldCookie, o)).intValue(); } @@ -382,7 +384,7 @@ public final class Field extends AccessibleObject implements Member public long getLong(Object o) throws IllegalAccessException { - if(!isAccessible() && !Modifier.isPublic(modifiers)) + if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) checkAccess(modifiers, declaringClass, new StackFrame(1)); return ((Long)GetValue(fieldCookie, o)).longValue(); } @@ -407,7 +409,7 @@ public final class Field extends AccessibleObject implements Member public float getFloat(Object o) throws IllegalAccessException { - if(!isAccessible() && !Modifier.isPublic(modifiers)) + if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) checkAccess(modifiers, declaringClass, new StackFrame(1)); return ((Float)GetValue(fieldCookie, o)).floatValue(); } @@ -433,7 +435,7 @@ public final class Field extends AccessibleObject implements Member public double getDouble(Object o) throws IllegalAccessException { - if(!isAccessible() && !Modifier.isPublic(modifiers)) + if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) checkAccess(modifiers, declaringClass, new StackFrame(1)); return ((Double)GetValue(fieldCookie, o)).doubleValue(); } @@ -486,7 +488,7 @@ public final class Field extends AccessibleObject implements Member public void set(Object o, Object value) throws IllegalAccessException { - if(!isAccessible() && !Modifier.isPublic(modifiers)) + if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) checkAccess(modifiers, declaringClass, new StackFrame(1)); SetValue(fieldCookie, o, value); } @@ -494,8 +496,9 @@ public final class Field extends AccessibleObject implements Member static void checkAccess(int modifiers, Class declaringClass, StackFrame frame) throws IllegalAccessException { + boolean declaringClassIsPublic = (declaringClass.getModifiers() & Modifier.PUBLIC) != 0; Class caller = getClassFromFrame(frame); - if(!Modifier.isPublic(modifiers) && declaringClass != caller) + if((!Modifier.isPublic(modifiers) || !declaringClassIsPublic) && declaringClass != caller) { if(Modifier.isProtected(modifiers) && declaringClass.isAssignableFrom(caller)) { @@ -529,7 +532,7 @@ public final class Field extends AccessibleObject implements Member public void setBoolean(Object o, boolean value) throws IllegalAccessException { - if(!isAccessible() && !Modifier.isPublic(modifiers)) + if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) checkAccess(modifiers, declaringClass, new StackFrame(1)); SetValue(fieldCookie, o, new Boolean(value)); } @@ -554,7 +557,7 @@ public final class Field extends AccessibleObject implements Member public void setByte(Object o, byte value) throws IllegalAccessException { - if(!isAccessible() && !Modifier.isPublic(modifiers)) + if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) checkAccess(modifiers, declaringClass, new StackFrame(1)); SetValue(fieldCookie, o, new Byte(value)); } @@ -579,7 +582,7 @@ public final class Field extends AccessibleObject implements Member public void setChar(Object o, char value) throws IllegalAccessException { - if(!isAccessible() && !Modifier.isPublic(modifiers)) + if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) checkAccess(modifiers, declaringClass, new StackFrame(1)); SetValue(fieldCookie, o, new Character(value)); } @@ -604,7 +607,7 @@ public final class Field extends AccessibleObject implements Member public void setShort(Object o, short value) throws IllegalAccessException { - if(!isAccessible() && !Modifier.isPublic(modifiers)) + if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) checkAccess(modifiers, declaringClass, new StackFrame(1)); SetValue(fieldCookie, o, new Short(value)); } @@ -629,7 +632,7 @@ public final class Field extends AccessibleObject implements Member public void setInt(Object o, int value) throws IllegalAccessException { - if(!isAccessible() && !Modifier.isPublic(modifiers)) + if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) checkAccess(modifiers, declaringClass, new StackFrame(1)); SetValue(fieldCookie, o, new Integer(value)); } @@ -654,7 +657,7 @@ public final class Field extends AccessibleObject implements Member public void setLong(Object o, long value) throws IllegalAccessException { - if(!isAccessible() && !Modifier.isPublic(modifiers)) + if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) checkAccess(modifiers, declaringClass, new StackFrame(1)); SetValue(fieldCookie, o, new Long(value)); } @@ -679,7 +682,7 @@ public final class Field extends AccessibleObject implements Member public void setFloat(Object o, float value) throws IllegalAccessException { - if(!isAccessible() && !Modifier.isPublic(modifiers)) + if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) checkAccess(modifiers, declaringClass, new StackFrame(1)); SetValue(fieldCookie, o, new Float(value)); } @@ -704,7 +707,7 @@ public final class Field extends AccessibleObject implements Member public void setDouble(Object o, double value) throws IllegalAccessException { - if(!isAccessible() && !Modifier.isPublic(modifiers)) + if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) checkAccess(modifiers, declaringClass, new StackFrame(1)); SetValue(fieldCookie, o, new Double(value)); } diff --git a/classpath/java/lang/reflect/Method.java b/classpath/java/lang/reflect/Method.java index 59497d38..87c95b49 100644 --- a/classpath/java/lang/reflect/Method.java +++ b/classpath/java/lang/reflect/Method.java @@ -78,6 +78,7 @@ public final class Method extends AccessibleObject implements Member private Class declaringClass; private Object methodCookie; private int modifiers; + private boolean classIsPublic; /** * This class is uninstantiable. @@ -87,6 +88,7 @@ public final class Method extends AccessibleObject implements Member this.declaringClass = declaringClass; this.methodCookie = methodCookie; modifiers = GetModifiers(methodCookie); + classIsPublic = (declaringClass.getModifiers() & Modifier.PUBLIC) != 0; } static native int GetModifiers(Object methodCookie); @@ -321,7 +323,7 @@ public final class Method extends AccessibleObject implements Member throws IllegalAccessException, InvocationTargetException { // TODO check args - if(!isAccessible() && !Modifier.isPublic(modifiers)) + if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) Field.checkAccess(modifiers, declaringClass, new StackFrame(1)); if(!Modifier.isStatic(getModifiers())) { diff --git a/classpath/map.xml b/classpath/map.xml index 1974fe43..3f31b379 100644 --- a/classpath/map.xml +++ b/classpath/map.xml @@ -544,6 +544,38 @@ </class> <!-- This is where the "native" helper methods start --> <class name="ikvm.lang.CIL"> + <method name="unbox_byte" sig="(Ljava.lang.Object;)B"> + <body> + <ldarg_0 /> + <unbox type="System.SByte, mscorlib" /> + <ldind_i1 /> + <ret /> + </body> + </method> + <method name="unbox_boolean" sig="(Ljava.lang.Object;)Z"> + <body> + <ldarg_0 /> + <unbox type="System.Boolean, mscorlib" /> + <ldind_i1 /> + <ret /> + </body> + </method> + <method name="unbox_short" sig="(Ljava.lang.Object;)S"> + <body> + <ldarg_0 /> + <unbox type="System.Int16, mscorlib" /> + <ldind_i2 /> + <ret /> + </body> + </method> + <method name="unbox_char" sig="(Ljava.lang.Object;)C"> + <body> + <ldarg_0 /> + <unbox type="System.Char, mscorlib" /> + <ldind_i2 /> + <ret /> + </body> + </method> <method name="unbox_int" sig="(Ljava.lang.Object;)I"> <body> <ldarg_0 /> @@ -552,6 +584,134 @@ <ret /> </body> </method> + <method name="unbox_float" sig="(Ljava.lang.Object;)F"> + <body> + <ldarg_0 /> + <unbox type="System.Single, mscorlib" /> + <ldind_r4 /> + <ret /> + </body> + </method> + <method name="unbox_long" sig="(Ljava.lang.Object;)J"> + <body> + <ldarg_0 /> + <unbox type="System.Int64, mscorlib" /> + <ldind_i8 /> + <ret /> + </body> + </method> + <method name="unbox_double" sig="(Ljava.lang.Object;)D"> + <body> + <ldarg_0 /> + <unbox type="System.Double, mscorlib" /> + <ldind_r8 /> + <ret /> + </body> + </method> + <method name="box_byte" sig="(B)Ljava.lang.Object;"> + <body> + <ldarg_0 /> + <box type="System.SByte, mscorlib" /> + <ret /> + </body> + </method> + <method name="box_boolean" sig="(Z)Ljava.lang.Object;"> + <body> + <ldarg_0 /> + <box type="System.Boolean, mscorlib" /> + <ret /> + </body> + </method> + <method name="box_short" sig="(S)Ljava.lang.Object;"> + <body> + <ldarg_0 /> + <box type="System.Int16, mscorlib" /> + <ret /> + </body> + </method> + <method name="box_char" sig="(C)Ljava.lang.Object;"> + <body> + <ldarg_0 /> + <box type="System.Char, mscorlib" /> + <ret /> + </body> + </method> + <method name="box_int" sig="(I)Ljava.lang.Object;"> + <body> + <ldarg_0 /> + <box type="System.Int32, mscorlib" /> + <ret /> + </body> + </method> + <method name="box_float" sig="(F)Ljava.lang.Object;"> + <body> + <ldarg_0 /> + <box type="System.Single, mscorlib" /> + <ret /> + </body> + </method> + <method name="box_long" sig="(J)Ljava.lang.Object;"> + <body> + <ldarg_0 /> + <box type="System.Int64, mscorlib" /> + <ret /> + </body> + </method> + <method name="box_double" sig="(D)Ljava.lang.Object;"> + <body> + <ldarg_0 /> + <box type="System.Double, mscorlib" /> + <ret /> + </body> + </method> + <method name="box_ubyte" sig="(B)Lcli.System.Byte;"> + <body> + <ldarg_0 /> + <ret /> + </body> + </method> + <method name="box_ushort" sig="(S)Lcli.System.UInt16;"> + <body> + <ldarg_0 /> + <ret /> + </body> + </method> + <method name="box_uint" sig="(I)Lcli.System.UInt32;"> + <body> + <ldarg_0 /> + <ret /> + </body> + </method> + <method name="box_ulong" sig="(J)Lcli.System.UInt64;"> + <body> + <ldarg_0 /> + <ret /> + </body> + </method> + <method name="unbox_ubyte" sig="(Lcli.System.Byte;)B"> + <body> + <ldarg_0 /> + <ret /> + </body> + </method> + <method name="unbox_ushort" sig="(Lcli.System.UInt16;)S"> + <body> + <ldarg_0 /> + <ret /> + </body> + </method> + <method name="unbox_uint" sig="(Lcli.System.UInt32;)I"> + <body> + <ldarg_0 /> + <ret /> + </body> + </method> + <method name="unbox_ulong" sig="(Lcli.System.UInt64;)J"> + <body> + <ldarg_0 /> + <ret /> + </body> + </method> </class> <class name="ikvm.lang.ByteArrayHack"> <method name="cast" sig="([B)[Lcli.System.Byte;"> diff --git a/runtime/ClassFile.cs b/runtime/ClassFile.cs index 7b941369..ec8c9223 100644 --- a/runtime/ClassFile.cs +++ b/runtime/ClassFile.cs @@ -1501,9 +1501,11 @@ class ClassFile } else { + // LAMESPEC: vmspec 4.6 says that abstract methods can not be strictfp (and this makes sense), but + // javac (pre 1.5) is broken and marks abstract methods as strictfp (if you put the strictfp on the class) if((Name == "<init>" && (IsStatic || IsSynchronized || IsFinal || IsAbstract)) || (IsPrivate && IsPublic) || (IsPrivate && IsProtected) || (IsPublic && IsProtected) - || (IsAbstract && (IsFinal || IsNative || IsPrivate || IsStatic || IsStrictfp || IsSynchronized)) + || (IsAbstract && (IsFinal || IsNative || IsPrivate || IsStatic || IsSynchronized)) || (classFile.IsInterface && (!IsPublic || !IsAbstract))) { throw new ClassFormatError("{0} (Illegal method modifiers: 0x{1:X})", classFile.Name, access_flags); diff --git a/runtime/JniInterface.cs b/runtime/JniInterface.cs index 080014e9..d3a4ddba 100644 --- a/runtime/JniInterface.cs +++ b/runtime/JniInterface.cs @@ -132,8 +132,8 @@ public sealed class JniHelper { TypeWrapper wrapper = NativeCode.java.lang.VMClass.getWrapperFromClass(clazz); wrapper.Finish(); - // TODO if we're instantiating a remapping type, we need to use TypeAsBaseType (except for String) - return System.Runtime.Serialization.FormatterServices.GetUninitializedObject(wrapper.TypeAsTBD); + // TODO add error handling (e.g. when trying to instantiate an interface or abstract class) + return System.Runtime.Serialization.FormatterServices.GetUninitializedObject(wrapper.TypeAsBaseType); } } diff --git a/runtime/MemberWrapper.cs b/runtime/MemberWrapper.cs index fd067037..ffa6035b 100644 --- a/runtime/MemberWrapper.cs +++ b/runtime/MemberWrapper.cs @@ -137,8 +137,7 @@ class MemberWrapper class MethodWrapper : MemberWrapper { private MethodDescriptor md; - private MethodBase originalMethod; - private MethodBase redirMethod; + private MethodBase method; private string[] declaredExceptions; internal CodeEmitter EmitCall; internal CodeEmitter EmitCallvirt; @@ -162,19 +161,59 @@ class MethodWrapper : MemberWrapper } } - // TODO creation of MethodWrappers should be cleaned up (and every instance should support Invoke()) - internal static MethodWrapper Create(TypeWrapper declaringType, MethodDescriptor md, MethodBase originalMethod, MethodBase method, Modifiers modifiers, bool hideFromReflection) + internal static MethodWrapper Create(TypeWrapper declaringType, MethodDescriptor md, MethodBase method, Modifiers modifiers, bool hideFromReflection) { - Debug.Assert(method != null); + Debug.Assert(declaringType != null && md != null && method != null); - MethodWrapper wrapper = new MethodWrapper(declaringType, md, originalMethod, method, modifiers, hideFromReflection); + MethodWrapper wrapper = new MethodWrapper(declaringType, md, method, modifiers, hideFromReflection); if(declaringType.IsGhost) { - wrapper.EmitCallvirt = new GhostCallEmitter(declaringType, md, originalMethod); + wrapper.EmitCall = CodeEmitter.InternalError; + wrapper.EmitCallvirt = new GhostCallEmitter(declaringType, md, method); + wrapper.EmitNewobj = CodeEmitter.InternalError; } else { - CreateEmitters(originalMethod, method, ref wrapper.EmitCall, ref wrapper.EmitCallvirt, ref wrapper.EmitNewobj); + if(method is ConstructorInfo) + { + wrapper.EmitCall = CodeEmitter.Create(OpCodes.Call, (ConstructorInfo)method); + wrapper.EmitCallvirt = CodeEmitter.InternalError; + wrapper.EmitNewobj = CodeEmitter.Create(OpCodes.Newobj, (ConstructorInfo)method); + } + else + { + if(md.Name == "<init>") + { + // we're a redirected constructor (which means that the class is final), + // so EmitCall isn't available. This also means that we won't be able to invoke + // the constructor using reflection (on an existing instance). + wrapper.EmitCall = CodeEmitter.InternalError; + wrapper.EmitCallvirt = CodeEmitter.InternalError; + wrapper.EmitNewobj = CodeEmitter.Create(OpCodes.Call, (MethodInfo)method); + } + else + { + wrapper.EmitCall = CodeEmitter.Create(OpCodes.Call, (MethodInfo)method); + if(method.IsStatic) + { + // because of redirection, it can be legal to call a static method with invokevirtual + if(!wrapper.IsStatic) + { + // we don't do a null pointer check on "this", the callee is responsible for that + wrapper.EmitCallvirt = CodeEmitter.Create(OpCodes.Call, (MethodInfo)method); + } + else + { + wrapper.EmitCallvirt = CodeEmitter.InternalError; + } + } + else + { + wrapper.EmitCallvirt = CodeEmitter.Create(OpCodes.Callvirt, (MethodInfo)method); + } + wrapper.EmitNewobj = CodeEmitter.InternalError; + } + } } TypeWrapper retType = md.RetTypeWrapper; if(!retType.IsUnloadable) @@ -229,48 +268,12 @@ class MethodWrapper : MemberWrapper } } - internal static void CreateEmitters(MethodBase originalMethod, MethodBase method, ref CodeEmitter call, ref CodeEmitter callvirt, ref CodeEmitter newobj) - { - if(method is ConstructorInfo) - { - call = CodeEmitter.Create(OpCodes.Call, (ConstructorInfo)method); - callvirt = null; - newobj = CodeEmitter.Create(OpCodes.Newobj, (ConstructorInfo)method); - } - else - { - call = CodeEmitter.Create(OpCodes.Call, (MethodInfo)method); - if(originalMethod != null && originalMethod != method) - { - // if we're calling a virtual method that is redirected, that overrides an already - // existing method, we have to call it virtually, instead of redirecting - callvirt = CodeEmitter.Create(OpCodes.Callvirt, (MethodInfo)originalMethod); - } - else if(method.IsStatic) - { - // because of redirection, it can be legal to call a static method with invokevirtual - callvirt = CodeEmitter.Create(OpCodes.Call, (MethodInfo)method); - } - else - { - callvirt = CodeEmitter.Create(OpCodes.Callvirt, (MethodInfo)method); - } - newobj = CodeEmitter.Create(OpCodes.Call, (MethodInfo)method); - } - } - - internal MethodWrapper(TypeWrapper declaringType, MethodDescriptor md, MethodBase originalMethod, MethodBase method, Modifiers modifiers, bool hideFromReflection) + internal MethodWrapper(TypeWrapper declaringType, MethodDescriptor md, MethodBase method, Modifiers modifiers, bool hideFromReflection) : base(declaringType, modifiers, hideFromReflection) { Profiler.Count("MethodWrapper"); - if(method != originalMethod) - { - redirMethod = method; - Debug.Assert(!(method is MethodBuilder)); - } this.md = md; - // NOTE originalMethod may be null - this.originalMethod = originalMethod; + this.method = method; } internal void SetDeclaredExceptions(string[] exceptions) @@ -354,10 +357,12 @@ class MethodWrapper : MemberWrapper { return (string[])declaredExceptions.Clone(); } - // NOTE if originalMethod is a MethodBuilder, GetCustomAttributes doesn't work - if(originalMethod != null && !(originalMethod is MethodBuilder)) + // NOTE if method is a MethodBuilder, GetCustomAttributes doesn't work (and if + // the method had any declared exceptions, the declaredExceptions field would have + // been set) + if(!(method is MethodBuilder)) { - object[] attributes = originalMethod.GetCustomAttributes(typeof(ThrowsAttribute), false); + object[] attributes = method.GetCustomAttributes(typeof(ThrowsAttribute), false); if(attributes.Length == 1) { return ((ThrowsAttribute)attributes[0]).Classes; @@ -368,17 +373,17 @@ class MethodWrapper : MemberWrapper // we expose the underlying MethodBase object, // for Java types, this is the method that contains the compiled Java bytecode - // for remapped types, this is the method that underlies the remapped method + // for remapped types, this is the mbCore method (not the helper) internal MethodBase GetMethod() { - return originalMethod; + return method; } internal string RealName { get { - return originalMethod.Name; + return method.Name; } } @@ -432,93 +437,184 @@ class MethodWrapper : MemberWrapper internal virtual object Invoke(object obj, object[] args, bool nonVirtual) { - // TODO if any of the parameters is a ghost, convert the passed in reference to a ghost value type - // TODO instead of looking up the method using reflection, we should use the method object passed into the - // constructor - if(IsStatic) + // if we've still got the builder object, we need to replace it with the real thing before we can call it + if(method is MethodBuilder) { - MethodInfo method = this.originalMethod != null && !(this.originalMethod is MethodBuilder) ? (MethodInfo)this.originalMethod : DeclaringType.TypeAsTBD.GetMethod(md.Name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, md.ArgTypesDontUse, null); - try + bool found = false; + int token = ((MethodBuilder)method).GetToken().Token; + ModuleBuilder module = (ModuleBuilder)((MethodBuilder)method).GetModule(); + foreach(MethodInfo mi in this.DeclaringType.TypeAsTBD.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance)) + { + if(module.GetMethodToken(mi).Token == token) + { + found = true; + method = mi; + break; + } + } + if(!found) { - return method.Invoke(null, args); + throw new InvalidOperationException("Failed to fixate method: " + this.DeclaringType.Name + "." + this.Name + this.Descriptor.Signature); } - catch(ArgumentException x1) + } + if(method is ConstructorBuilder) + { + bool found = false; + int token = ((ConstructorBuilder)method).GetToken().Token; + ModuleBuilder module = (ModuleBuilder)((ConstructorBuilder)method).GetModule(); + foreach(ConstructorInfo ci in this.DeclaringType.TypeAsTBD.GetConstructors(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { - throw JavaException.IllegalArgumentException(x1.Message); + if(module.GetConstructorToken(ci).Token == token) + { + found = true; + method = ci; + break; + } } - catch(TargetInvocationException x) + if(!found) { - throw JavaException.InvocationTargetException(ExceptionHelper.MapExceptionFast(x.InnerException)); + throw new InvalidOperationException("Failed to fixate constructor: " + this.DeclaringType.Name + "." + this.Name + this.Descriptor.Signature); } } + return InvokeImpl(method, obj, args, nonVirtual); + } + + internal object InvokeImpl(MethodBase method, object obj, object[] args, bool nonVirtual) + { + Debug.Assert(!(method is MethodBuilder || method is ConstructorBuilder)); + + if(IsStatic) + { + // Java allows bogus 'obj' to be specified for static methods + obj = null; + } else { - // calling <init> without an instance means that we're constructing a new instance - // NOTE this means that we cannot detect a NullPointerException when calling <init> if(md.Name == "<init>") { - ConstructorInfo constructor = this.originalMethod != null && !(this.originalMethod is ConstructorBuilder) ? (ConstructorInfo)this.originalMethod : DeclaringType.TypeAsTBD.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Standard, md.ArgTypesDontUse, null); - try + if(method is MethodInfo) { + Debug.Assert(method.IsStatic); + // we're dealing with a constructor on a remapped type, if obj is supplied, it means + // that we should call the constructor on an already existing instance, but that isn't + // possible with remapped types if(obj != null) { - return constructor.Invoke(obj, args); - } - else - { - return constructor.Invoke(args); + // the type of this exception is a bit random (note that this can only happen through JNI reflection or + // if there is a bug in serialization [which uses the ObjectInputStream.callConstructor() in classpath.cs) + throw JavaException.IncompatibleClassChangeError("Remapped type {0} doesn't support constructor invocation on an existing instance", DeclaringType.Name); } } - catch(ArgumentException x1) + else if(obj == null) { - throw JavaException.IllegalArgumentException(x1.Message); - } - catch(TargetInvocationException x) - { - throw JavaException.InvocationTargetException(ExceptionHelper.MapExceptionFast(x.InnerException)); + // calling <init> without an instance means that we're constructing a new instance + // NOTE this means that we cannot detect a NullPointerException when calling <init> (does JNI require this?) + try + { + InvokeArgsProcessor proc = new InvokeArgsProcessor(this, method, null, args); + object o = ((ConstructorInfo)method).Invoke(proc.GetArgs()); + // since we just constructed an instance, it can't possibly be a ghost + return o; + } + catch(ArgumentException x1) + { + throw JavaException.IllegalArgumentException(x1.Message); + } + catch(TargetInvocationException x) + { + throw JavaException.InvocationTargetException(ExceptionHelper.MapExceptionFast(x.InnerException)); + } } } - if(nonVirtual) + else if(nonVirtual && !method.IsStatic) { + // TODO figure out how to implement this (one way would be to generate some code on the fly) throw new NotImplementedException("non-virtual reflective method invocation not implemented"); } - MethodInfo method = (MethodInfo)this.originalMethod; - if(redirMethod != null) + } + try + { + InvokeArgsProcessor proc = new InvokeArgsProcessor(this, method, obj, args); + object o = method.Invoke(proc.GetObj(), proc.GetArgs()); + TypeWrapper retType = md.RetTypeWrapper; + if(!retType.IsUnloadable && retType.IsGhost) + { + o = md.RetTypeWrapper.GhostRefField.GetValue(o); + } + return o; + } + catch(ArgumentException x1) + { + throw JavaException.IllegalArgumentException(x1.Message); + } + catch(TargetInvocationException x) + { + throw JavaException.InvocationTargetException(ExceptionHelper.MapExceptionFast(x.InnerException)); + } + } + + private struct InvokeArgsProcessor + { + private object obj; + private object[] args; + + internal InvokeArgsProcessor(MethodWrapper mw, MethodBase method, object original_obj, object[] original_args) + { + TypeWrapper[] argTypes = mw.md.ArgTypeWrappers; + + if(!mw.IsStatic && mw.DeclaringType.IsGhost) + { + object o = Activator.CreateInstance(mw.DeclaringType.TypeAsParameterType); + mw.DeclaringType.GhostRefField.SetValue(o, original_obj); + original_obj = o; + } + + if(!mw.IsStatic && method.IsStatic && mw.md.Name != "<init>") { - method = (MethodInfo)redirMethod; - if(method.IsStatic) + // we've been redirected to a static method, so we have to copy the 'obj' into the args + args = new object[original_args.Length + 1]; + args[0] = original_obj; + original_args.CopyTo(args, 1); + this.obj = null; + this.args = args; + for(int i = 0; i < argTypes.Length; i++) { - // we've been redirected to a static method, so we have to copy the this into the args - object[] oldargs = args; - args = new object[args.Length + 1]; - args[0] = obj; - oldargs.CopyTo(args, 1); - obj = null; + if(!argTypes[i].IsUnloadable && argTypes[i].IsGhost) + { + object v = Activator.CreateInstance(argTypes[i].TypeAsParameterType); + argTypes[i].GhostRefField.SetValue(v, args[i + 1]); + args[i + 1] = v; + } } } else { - if(method is MethodBuilder || method == null) - { - method = DeclaringType.TypeAsTBD.GetMethod(md.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, md.ArgTypesDontUse, null); - } - if(method == null) + this.obj = original_obj; + this.args = original_args; + for(int i = 0; i < argTypes.Length; i++) { - throw new NotImplementedException("method not found: " + this.DeclaringType.Name + "." + md.Name + md.Signature); + if(!argTypes[i].IsUnloadable && argTypes[i].IsGhost) + { + if(this.args == original_args) + { + this.args = (object[])args.Clone(); + } + object v = Activator.CreateInstance(argTypes[i].TypeAsParameterType); + argTypes[i].GhostRefField.SetValue(v, args[i]); + this.args[i] = v; + } } } - try - { - return method.Invoke(obj, args); - } - catch(ArgumentException x1) - { - throw JavaException.IllegalArgumentException(x1.Message); - } - catch(TargetInvocationException x) - { - throw JavaException.InvocationTargetException(ExceptionHelper.MapExceptionFast(x.InnerException)); - } + } + + internal object GetObj() + { + return obj; + } + + internal object[] GetArgs() + { + return args; } } } diff --git a/runtime/TypeWrapper.cs b/runtime/TypeWrapper.cs index ef735405..ac83c58a 100644 --- a/runtime/TypeWrapper.cs +++ b/runtime/TypeWrapper.cs @@ -1423,7 +1423,7 @@ abstract class TypeWrapper // NOTE because we are introducing a Miranda method, we must also update the corresponding wrapper. // If we don't do this, subclasses might think they are introducing a new method, instead of overriding // this one. - wrapper.AddMethod(MethodWrapper.Create(wrapper, md, mb, mb, Modifiers.Public | Modifiers.Abstract, true)); + wrapper.AddMethod(MethodWrapper.Create(wrapper, md, mb, Modifiers.Public | Modifiers.Abstract, true)); // NOTE if the interface method name is remapped, we need to add an explicit methodoverride. Note that when this // is required we always need to emit this stub, even if the above mentioned bug is fixed in the CLR if(md.Name != ifmethod.Name) @@ -3691,7 +3691,7 @@ class DynamicTypeWrapper : TypeWrapper } string[] exceptions = m.ExceptionsAttribute; AttributeHelper.SetThrowsAttribute(method, exceptions); - methods[index] = MethodWrapper.Create(wrapper, new MethodDescriptor(wrapper.GetClassLoader(), m), method, method, m.Modifiers, false); + methods[index] = MethodWrapper.Create(wrapper, new MethodDescriptor(wrapper.GetClassLoader(), m), method, m.Modifiers, false); methods[index].SetDeclaredExceptions(exceptions); if(JVM.IsStaticCompiler && m.DeprecatedAttribute) { @@ -4195,7 +4195,7 @@ class CompiledTypeWrapper : LazyTypeWrapper MethodBase method = m as MethodBase; if(method != null) { - AddMethod(CreateMethodWrapper(method)); + AddMethod(MethodWrapper.Create(this, MethodDescriptor.FromMethodBase(method), method, AttributeHelper.GetModifiers(method, false), false)); } else { @@ -4240,7 +4240,7 @@ class CompiledTypeWrapper : LazyTypeWrapper Modifiers modifiers = AttributeHelper.GetModifiers(method, false); MethodDescriptor md = MethodDescriptor.FromMethodBase(method); md = MethodDescriptor.FromNameSig(GetClassLoader(), m.Name, md.Signature); - MethodWrapper mw = new MethodWrapper(this, md, method, null, modifiers, false); + MethodWrapper mw = new MethodWrapper(this, md, method, modifiers, false); mw.EmitCall = CodeEmitter.InternalError; mw.EmitCallvirt = CodeEmitter.Create(OpCodes.Callvirt, method); mw.EmitNewobj = CodeEmitter.InternalError; @@ -4250,11 +4250,28 @@ class CompiledTypeWrapper : LazyTypeWrapper } } + private class CompiledRemappedMethodWrapper : MethodWrapper + { + private MethodBase mbHelper; + + internal CompiledRemappedMethodWrapper(TypeWrapper declaringType, MethodDescriptor md, MethodBase method, Modifiers modifiers, bool hideFromReflection, MethodBase mbHelper) + : base(declaringType, md, method, modifiers, hideFromReflection) + { + this.mbHelper = mbHelper; + } + + internal override object Invoke(object obj, object[] args, bool nonVirtual) + { + return InvokeImpl(mbHelper, obj, args, nonVirtual); + } + } + private MethodWrapper CreateRemappedMethodWrapper(MethodBase mb) { bool instancehelper = false; Modifiers modifiers = AttributeHelper.GetModifiers(mb, false); MethodDescriptor md = MethodDescriptor.FromMethodBase(mb); + MethodBase mbHelper = mb; if(md.Name.StartsWith("instancehelper_")) { instancehelper = true; @@ -4268,7 +4285,22 @@ class CompiledTypeWrapper : LazyTypeWrapper md = MethodDescriptor.FromNameSig(GetClassLoader(), "<init>", sig.Substring(0, sig.LastIndexOf(')')) + ")V"); modifiers &= ~Modifiers.Static; } - MethodWrapper method = new MethodWrapper(this, md, mb, null, modifiers, false); + else if(!mb.IsStatic && !mb.IsConstructor) + { + ParameterInfo[] parameters = mb.GetParameters(); + Type[] argTypes = new Type[parameters.Length + 1]; + argTypes[0] = remappedType; + for(int i = 0; i < parameters.Length; i++) + { + argTypes[i + 1] = parameters[i].ParameterType; + } + mbHelper = type.GetMethod("instancehelper_" + mb.Name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, null, argTypes, null); + if(mbHelper == null) + { + mbHelper = mb; + } + } + MethodWrapper method = new CompiledRemappedMethodWrapper(this, md, mb, modifiers, false, mbHelper); if(mb is ConstructorInfo) { method.EmitCallvirt = CodeEmitter.InternalError; @@ -4304,17 +4336,9 @@ class CompiledTypeWrapper : LazyTypeWrapper else { method.EmitCall = CodeEmitter.Create(OpCodes.Call, (MethodInfo)mb); - ParameterInfo[] parameters = mb.GetParameters(); - Type[] argTypes = new Type[parameters.Length + 1]; - argTypes[0] = remappedType; - for(int i = 0; i < parameters.Length; i++) + if(mbHelper != mb) { - argTypes[i + 1] = parameters[i].ParameterType; - } - MethodInfo helper = type.GetMethod("instancehelper_" + mb.Name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, null, argTypes, null); - if(helper != null) - { - method.EmitCallvirt = CodeEmitter.Create(OpCodes.Call, helper); + method.EmitCallvirt = CodeEmitter.Create(OpCodes.Call, (MethodInfo)mbHelper); } else { @@ -4326,41 +4350,6 @@ class CompiledTypeWrapper : LazyTypeWrapper return method; } - private MethodWrapper CreateMethodWrapper(MethodBase mb) - { - MethodDescriptor md = MethodDescriptor.FromMethodBase(mb); - MethodWrapper method = new MethodWrapper(this, md, mb, null, AttributeHelper.GetModifiers(mb, false), false); - if(IsGhost) - { - method.EmitCall = CodeEmitter.InternalError; - method.EmitCallvirt = new MethodWrapper.GhostCallEmitter(this, md, mb); - method.EmitNewobj = CodeEmitter.InternalError; - } - else - { - if(mb is ConstructorInfo) - { - method.EmitCall = CodeEmitter.Create(OpCodes.Call, (ConstructorInfo)mb); - method.EmitCallvirt = CodeEmitter.InternalError; - method.EmitNewobj = CodeEmitter.Create(OpCodes.Newobj, (ConstructorInfo)mb); - } - else - { - method.EmitCall = CodeEmitter.Create(OpCodes.Call, (MethodInfo)mb); - if(!mb.IsStatic) - { - method.EmitCallvirt = CodeEmitter.Create(OpCodes.Callvirt, (MethodInfo)mb); - } - else - { - method.EmitCallvirt = CodeEmitter.InternalError; - } - method.EmitNewobj = CodeEmitter.InternalError; - } - } - return method; - } - private FieldWrapper CreateFieldWrapper(FieldInfo field) { MethodInfo getter = null; @@ -4661,7 +4650,7 @@ class DotNetTypeWrapper : LazyTypeWrapper private class DelegateMethodWrapper : MethodWrapper { internal DelegateMethodWrapper(TypeWrapper declaringType, MethodDescriptor md) - : base(declaringType, md, null, null, Modifiers.Public, false) + : base(declaringType, md, null, Modifiers.Public, false) { } @@ -4676,8 +4665,8 @@ class DotNetTypeWrapper : LazyTypeWrapper { private bool[] byrefs; - internal ByRefMethodWrapper(bool[] byrefs, TypeWrapper declaringType, MethodDescriptor md, MethodBase originalMethod, MethodBase method, Modifiers modifiers, bool hideFromReflection) - : base(declaringType, md, originalMethod, method, modifiers, hideFromReflection) + internal ByRefMethodWrapper(bool[] byrefs, TypeWrapper declaringType, MethodDescriptor md, MethodBase method, Modifiers modifiers, bool hideFromReflection) + : base(declaringType, md, method, modifiers, hideFromReflection) { this.byrefs = byrefs; } @@ -4735,7 +4724,7 @@ class DotNetTypeWrapper : LazyTypeWrapper CodeEmitter setter = CodeEmitter.Pop + CodeEmitter.Pop; FieldWrapper fw = FieldWrapper.Create(this, fieldType, "Value", fieldType.SigName, Modifiers.Public | Modifiers.Final, null, getter, setter); AddField(fw); - MethodWrapper mw = new MethodWrapper(this, MethodDescriptor.FromNameSig(GetClassLoader(), "wrap", "(" + fieldType.SigName + ")" + this.SigName), null, null, Modifiers.Static | Modifiers.Public, false); + MethodWrapper mw = new MethodWrapper(this, MethodDescriptor.FromNameSig(GetClassLoader(), "wrap", "(" + fieldType.SigName + ")" + this.SigName), null, Modifiers.Static | Modifiers.Public, false); // NOTE we don't support custom boxing rules for enums mw.EmitCall = CodeEmitter.Create(OpCodes.Box, type); AddMethod(mw); @@ -4850,7 +4839,7 @@ class DotNetTypeWrapper : LazyTypeWrapper if(!h.ContainsKey(m.Descriptor.Name + m.Descriptor.Signature)) { h.Add(m.Descriptor.Name + m.Descriptor.Signature, ""); - MethodWrapper newmw = new MethodWrapper(this, m.Descriptor, m.GetMethod(), m.GetMethod(), m.Modifiers | Modifiers.Final, false); + MethodWrapper newmw = new MethodWrapper(this, m.Descriptor, m.GetMethod(), m.Modifiers | Modifiers.Final, false); newmw.EmitNewobj = CodeEmitter.InternalError; // we bind EmitCall to EmitCallvirt, because we always want to end up at the instancehelper method // (EmitCall would go to our alter ego .NET type and that wouldn't be legal) @@ -5066,7 +5055,7 @@ class DotNetTypeWrapper : LazyTypeWrapper TypeAsBaseType.IsSubclassOf(CoreClasses.java.lang.Object.Wrapper.TypeAsBaseType)) { // TODO if the .NET also has a "finalize" method, we need to hide that one (or rename it, or whatever) - MethodWrapper mw = new MethodWrapper(this, MethodDescriptor.FromNameSig(GetClassLoader(), "finalize", "()V"), mb, null, mods, false); + MethodWrapper mw = new MethodWrapper(this, MethodDescriptor.FromNameSig(GetClassLoader(), "finalize", "()V"), mb, mods, false); mw.SetDeclaredExceptions(new string[] { "java.lang.Throwable" }); mw.EmitCall = CodeEmitter.Create(OpCodes.Call, mb); mw.EmitCallvirt = CodeEmitter.Create(OpCodes.Callvirt, mb); @@ -5100,7 +5089,7 @@ class DotNetTypeWrapper : LazyTypeWrapper mods |= Modifiers.Final; } MethodWrapper method = hasByRefArgs ? - new ByRefMethodWrapper(byrefs, this, md, mb, null, mods, false) : new MethodWrapper(this, md, mb, null, mods, false); + new ByRefMethodWrapper(byrefs, this, md, mb, mods, false) : new MethodWrapper(this, md, mb, mods, false); if(mb is ConstructorInfo) { method.EmitCall = CodeEmitter.Create(OpCodes.Call, (ConstructorInfo)mb); @@ -5228,7 +5217,7 @@ class ArrayTypeWrapper : TypeWrapper { clone = typeof(Array).GetMethod("Clone"); } - MethodWrapper mw = new MethodWrapper(this, mdClone, clone, null, Modifiers.Public, true); + MethodWrapper mw = new MethodWrapper(this, mdClone, clone, Modifiers.Public, true); if(callclone == null) { callclone = CodeEmitter.Create(OpCodes.Callvirt, clone); diff --git a/runtime/remapper.cs b/runtime/remapper.cs index afce499c..6f79d12c 100644 --- a/runtime/remapper.cs +++ b/runtime/remapper.cs @@ -498,6 +498,22 @@ namespace MapXml } } + [XmlType("ldind_i1")] + public sealed class Ldind_i1 : Simple + { + public Ldind_i1() : base(OpCodes.Ldind_I1) + { + } + } + + [XmlType("ldind_i2")] + public sealed class Ldind_i2 : Simple + { + public Ldind_i2() : base(OpCodes.Ldind_I2) + { + } + } + [XmlType("ldind_i4")] public sealed class Ldind_i4 : Simple { @@ -506,6 +522,30 @@ namespace MapXml } } + [XmlType("ldind_i8")] + public sealed class Ldind_i8 : Simple + { + public Ldind_i8() : base(OpCodes.Ldind_I8) + { + } + } + + [XmlType("ldind_r4")] + public sealed class Ldind_r4 : Simple + { + public Ldind_r4() : base(OpCodes.Ldind_R4) + { + } + } + + [XmlType("ldind_r8")] + public sealed class Ldind_r8 : Simple + { + public Ldind_r8() : base(OpCodes.Ldind_R8) + { + } + } + [XmlType("ret")] public sealed class Ret : Simple { @@ -546,6 +586,38 @@ namespace MapXml } } + [XmlType("conv_u1")] + public sealed class Conv_U1 : Simple + { + public Conv_U1() : base(OpCodes.Conv_U1) + { + } + } + + [XmlType("conv_u2")] + public sealed class Conv_U2 : Simple + { + public Conv_U2() : base(OpCodes.Conv_U2) + { + } + } + + [XmlType("conv_u4")] + public sealed class Conv_U4 : Simple + { + public Conv_U4() : base(OpCodes.Conv_U4) + { + } + } + + [XmlType("conv_u8")] + public sealed class Conv_U8 : Simple + { + public Conv_U8() : base(OpCodes.Conv_U8) + { + } + } + public class InstructionList : CodeEmitter { [XmlElement(typeof(Ldstr))] @@ -568,12 +640,21 @@ namespace MapXml [XmlElement(typeof(LdArg_1))] [XmlElement(typeof(LdArg_2))] [XmlElement(typeof(LdArg_3))] + [XmlElement(typeof(Ldind_i1))] + [XmlElement(typeof(Ldind_i2))] [XmlElement(typeof(Ldind_i4))] + [XmlElement(typeof(Ldind_i8))] + [XmlElement(typeof(Ldind_r4))] + [XmlElement(typeof(Ldind_r8))] [XmlElement(typeof(Ret))] [XmlElement(typeof(Throw))] [XmlElement(typeof(Ldnull))] [XmlElement(typeof(Stsfld))] [XmlElement(typeof(Ldc_I4_0))] + [XmlElement(typeof(Conv_U1))] + [XmlElement(typeof(Conv_U2))] + [XmlElement(typeof(Conv_U4))] + [XmlElement(typeof(Conv_U8))] public Instruction[] invoke; internal sealed override void Emit(ILGenerator ilgen) diff --git a/runtime/vm.cs b/runtime/vm.cs index c1f35ae2..19f0f4d0 100644 --- a/runtime/vm.cs +++ b/runtime/vm.cs @@ -463,7 +463,7 @@ public class JVM private ArrayList overriders = new ArrayList(); private RemappedMethodWrapper(TypeWrapper typeWrapper, MethodDescriptor md, MethodBuilder mbCore, MethodBuilder mbHelper, Modifiers modifiers, MapXml.Method m) - : base(typeWrapper, md, /*TODO*/mbCore, mbCore, modifiers, false) + : base(typeWrapper, md, mbCore, modifiers, false) { this.xmlMethod = m; this.mbCore = mbCore; @@ -489,7 +489,7 @@ public class JVM } private RemappedMethodWrapper(RemapperTypeWrapper typeWrapper, MethodDescriptor md, ConstructorBuilder cbCore, MethodBuilder cbHelper, Modifiers modifiers, MapXml.Constructor m) - : base(typeWrapper, md, /*TODO*/cbCore, cbCore, modifiers, false) + : base(typeWrapper, md, cbCore, modifiers, false) { this.xmlConstructor = m; this.cbCore = cbCore; @@ -509,7 +509,7 @@ public class JVM } private RemappedMethodWrapper(RemapperTypeWrapper typeWrapper, MethodDescriptor md, MethodInfo interfaceMethod, Modifiers modifiers) - : base(typeWrapper, md, interfaceMethod, null, modifiers, false) + : base(typeWrapper, md, interfaceMethod, modifiers, false) { this.interfaceMethod = interfaceMethod; this.EmitCallvirt = CodeEmitter.Create(OpCodes.Callvirt, interfaceMethod); @@ -1362,6 +1362,7 @@ public class JVM { Tracer.Info(Tracer.Compiler, "Loading remapped types (1) from {0}", remapfile); System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(MapXml.Root)); + ser.UnknownElement += new System.Xml.Serialization.XmlElementEventHandler(ser_UnknownElement); using(FileStream fs = File.Open(remapfile, FileMode.Open)) { map = (MapXml.Root)ser.Deserialize(fs); @@ -1495,4 +1496,10 @@ public class JVM } Environment.Exit(1); } + + private static void ser_UnknownElement(object sender, System.Xml.Serialization.XmlElementEventArgs e) + { + Console.Error.WriteLine("Unknown element {0} in XML mapping file, line {1}, column {2}", e.Element.Name, e.LineNumber, e.LinePosition); + Environment.Exit(1); + } } |