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

github.com/mono/ikvm-fork.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LICENSE4
-rw-r--r--classpath/gnu/java/nio/channels/FileChannelImpl.java4
-rw-r--r--classpath/ikvm/lang/CIL.java30
-rw-r--r--classpath/java/lang/reflect/Constructor.java4
-rw-r--r--classpath/java/lang/reflect/Field.java41
-rw-r--r--classpath/java/lang/reflect/Method.java4
-rw-r--r--classpath/map.xml160
-rw-r--r--runtime/ClassFile.cs4
-rw-r--r--runtime/JniInterface.cs4
-rw-r--r--runtime/MemberWrapper.cs310
-rw-r--r--runtime/TypeWrapper.cs105
-rw-r--r--runtime/remapper.cs81
-rw-r--r--runtime/vm.cs13
13 files changed, 566 insertions, 198 deletions
diff --git a/LICENSE b/LICENSE
index 26326145..73e41f50 100644
--- a/LICENSE
+++ b/LICENSE
@@ -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);
+ }
}